@uniswap-widget/react 0.0.0 → 2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Houtan Rocky
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,209 @@
1
+ # @uniswap-widget/react
2
+
3
+ <img width="581" height="546" alt="image" src="https://github.com/user-attachments/assets/b98e27cd-3a08-4a1e-a018-f12ef1cd9bba" />
4
+
5
+ A React component package for easily integrating Uniswap swap functionality into your dApp with maximum dev flexibility no token limitations, no warnings, and no added fee.
6
+
7
+ > Looking for a runnable end-to-end setup? See [`examples/basic`](https://github.com/houtan/uniswap-widget/tree/main/examples/basic) in the monorepo.
8
+
9
+ ## Installation
10
+
11
+ The widget keeps its heavy dependencies as **peer dependencies**, so you install them alongside it (and stay in control of their versions):
12
+
13
+ ```bash
14
+ pnpm add @uniswap-widget/react \
15
+ @reown/appkit @reown/appkit-adapter-wagmi wagmi viem \
16
+ @tanstack/react-query ethers \
17
+ @uniswap/sdk-core @uniswap/v3-sdk @uniswap/v3-core
18
+ # or: npm install … / yarn add …
19
+ ```
20
+
21
+ ## Host-app requirements
22
+
23
+ The widget makes three assumptions about the app embedding it. Satisfy all three or it won't render/behave correctly. (These are tracked for removal see the [decoupling spec](https://github.com/houtan/uniswap-widget/blob/main/docs/0004-core-deps-decoupling.md).)
24
+
25
+ ### 1. Tailwind CSS
26
+
27
+ The widget is styled with **Tailwind utility classes** and ships **no CSS of its own**. Your app must run Tailwind and include the package in its `content` globs so those classes are generated:
28
+
29
+ ```js
30
+ // tailwind.config.js
31
+ export default {
32
+ content: [
33
+ './src/**/*.{js,ts,jsx,tsx}',
34
+ './node_modules/@uniswap-widget/react/dist/*.js', // generate the widget's classes
35
+ ],
36
+ }
37
+ ```
38
+
39
+ ### 2. API proxy
40
+
41
+ The widget calls these **relative** paths, which your app must proxy:
42
+
43
+ | Path | Method | Purpose | Required when |
44
+ |------|--------|---------|---------------|
45
+ | `/api/base-rpc` | POST | Base-chain JSON-RPC reads (balances, pool reserves, quotes) | Always |
46
+ | `/api/uniswap/v2/Search.v1.SearchService/SearchTokens` | POST | Token search | `searchConfig.enabled` is `true` |
47
+
48
+ See [`examples/basic/vite.config.ts`](https://github.com/houtan/uniswap-widget/blob/main/examples/basic/vite.config.ts) (dev proxy) and [`examples/basic/api`](https://github.com/houtan/uniswap-widget/tree/main/examples/basic/api) (Vercel functions) for a working reference.
49
+
50
+ ### 3. Vite-style env
51
+
52
+ Configuration is read from `import.meta.env.VITE_*` (with sensible fallbacks), so the widget currently expects a **Vite** host. See [Environment Variables](#environment-variables).
53
+
54
+ ## Configuration
55
+
56
+ ### 1. WalletConnect Project ID
57
+
58
+ Get your WalletConnect v2 Project ID at https://cloud.walletconnect.com/
59
+
60
+ ### 2. Provider setup
61
+
62
+ Wrap your app with the `Provider`, passing a configured `WagmiAdapter`:
63
+
64
+ ```tsx
65
+ import { Provider, createAppKit, WagmiAdapter, base } from '@uniswap-widget/react';
66
+ import { QueryClient } from '@tanstack/react-query';
67
+
68
+ const projectId = 'your_project_id';
69
+ const queryClient = new QueryClient();
70
+
71
+ const wagmiAdapter = new WagmiAdapter({
72
+ projectId,
73
+ networks: [base],
74
+ ssr: true,
75
+ });
76
+
77
+ createAppKit({
78
+ adapters: [wagmiAdapter],
79
+ networks: [base],
80
+ projectId,
81
+ metadata: {
82
+ name: 'Your App Name',
83
+ description: 'Your app description',
84
+ url: 'https://your-domain.com',
85
+ icons: ['https://your-icon-url.com'],
86
+ },
87
+ features: {
88
+ analytics: true,
89
+ email: false,
90
+ socials: [],
91
+ allWallets: true,
92
+ emailShowWallets: true,
93
+ swaps: false,
94
+ },
95
+ });
96
+
97
+ export default function App({ children }: { children: React.ReactNode }) {
98
+ return (
99
+ <Provider wagmiAdapter={wagmiAdapter} queryClient={queryClient}>
100
+ {children}
101
+ </Provider>
102
+ );
103
+ }
104
+ ```
105
+
106
+ ### Provider props
107
+
108
+ | Prop | Type | Required | Description |
109
+ |------|------|----------|-------------|
110
+ | `wagmiAdapter` | `WagmiAdapter` | Yes | Configured `WagmiAdapter` instance |
111
+ | `queryClient` | `QueryClient` | No | React Query client (defaults to a new `QueryClient`) |
112
+ | `children` | `ReactNode` | Yes | Child components |
113
+
114
+ ## Usage
115
+
116
+ ```tsx
117
+ import { SwapWidget } from '@uniswap-widget/react';
118
+
119
+ export default function SwapPage() {
120
+ const handleSwap = async (inputAmount: string, outputAmount: string) => {
121
+ console.log('Swap:', { inputAmount, outputAmount });
122
+ // Add your post-swap logic here
123
+ };
124
+
125
+ return (
126
+ <SwapWidget
127
+ poolConfig={{
128
+ tokenIn: {
129
+ chainId: 8453,
130
+ address: '0x0b3e328455c4059eeb9e3f84b5543f74e24e7e1b',
131
+ decimals: 18,
132
+ symbol: 'VIRTUAL',
133
+ name: 'Virtual Protocol',
134
+ logoURI: 'https://assets.coingecko.com/coins/images/33154/standard/256x256_mark.png',
135
+ },
136
+ tokenOut: {
137
+ chainId: 8453,
138
+ address: '0x7d6fcB3327D7E17095fA8B0E3513AC7A3564f5E1',
139
+ decimals: 18,
140
+ symbol: 'SOLACE',
141
+ name: 'Solace by Virtuals',
142
+ logoURI: 'https://assets.coingecko.com/coins/images/32849/standard/solace_logo_256.png',
143
+ },
144
+ poolAddress: '0x912567c105A172777e56411DD0AA4Acc10e628a9',
145
+ version: 'V2',
146
+ }}
147
+ allowTokenChange
148
+ onSwap={handleSwap}
149
+ searchConfig={{ enabled: true, chainIds: [8453] }}
150
+ />
151
+ );
152
+ }
153
+ ```
154
+
155
+ ### SwapWidget props (`SwapProps`)
156
+
157
+ | Prop | Type | Required | Description |
158
+ |------|------|----------|-------------|
159
+ | `poolConfig` | `PoolConfig` | No | The pool to trade against (see below) |
160
+ | `theme` | `Partial<ThemeConfig>` | No | Override colors/spacing. `lightTheme` / `darkTheme` are exported |
161
+ | `allowTokenChange` | `boolean` | No | Allow the user to switch tokens |
162
+ | `onTokenSelect` | `(type: 'input' \| 'output', token: TokenInfo) => void` | No | Fired on token selection |
163
+ | `onAmountChange` | `(amount: string, type: 'input' \| 'output') => void` | No | Fired on amount change |
164
+ | `onSwap` | `(inputAmount: string, outputAmount: string) => Promise<void>` | No | Called after a successful swap |
165
+ | `customTokenList` | `TokenInfo[]` | No | Restrict selectable tokens to this list |
166
+ | `searchConfig` | `{ enabled: boolean; chainIds?: number[] }` | No | Enable token search (requires the search proxy) |
167
+
168
+ ### `PoolConfig`
169
+
170
+ | Field | Type | Description |
171
+ |-------|------|-------------|
172
+ | `tokenIn` / `tokenOut` | `TokenInfo` | The traded tokens (`chainId`, `address`, `decimals`, `symbol`, `name`, `logoURI`) |
173
+ | `poolAddress` | `string` | The pool/pair address |
174
+ | `version` | `'V2' \| 'V3'` | Pool type |
175
+ | `fee` | `number` | V3 fee tier (e.g. `500`, `3000`, `10000`) |
176
+
177
+ ## Exports
178
+
179
+ - **Components:** `SwapWidget`, `Provider` (+ `ProviderProps`)
180
+ - **AppKit/wagmi re-exports:** `createAppKit`, `useAppKit`, `WagmiAdapter`, `CreateConnectorFn`
181
+ - **Networks:** `base`, `mainnet`, `polygon`, `optimism`, `arbitrum`, `avalanche`, `fantom`, `moonbeam`, `solana`
182
+ - **Themes:** `lightTheme`, `darkTheme`
183
+ - **Constants:** `VIRTUAL_PROTOCOL_TOKEN`, `DEFAULT_SLIPPAGE`, `DEFAULT_DEADLINE_MINUTES`, `VritualProtocolTokenInfo`, `SolaceTokenInfo`
184
+ - **Types:** `SwapProps`, `ThemeConfig`, `TokenInfo`, `PoolConfig`, `SwapState`, `AppKitNetwork`, `AppKitFeatures`, `AppKitMetadata`
185
+
186
+ ## Requirements
187
+
188
+ - React 18 or higher
189
+ - A Vite-based host app (for `import.meta.env`)
190
+ - A valid WalletConnect v2 Project ID
191
+ - The API proxy described above
192
+
193
+ ## Environment Variables
194
+
195
+ ```env
196
+ VITE_REOWN_PROJECT_ID=your_project_id
197
+ VITE_APP_NAME=Your App Name
198
+ VITE_APP_DESCRIPTION=Your app description
199
+ VITE_APP_URL=https://your-domain.com
200
+ VITE_APP_ICON=https://your-icon-url.com
201
+
202
+ # Optional token-change controls (default: true)
203
+ VITE_ALLOW_SELL_TOKEN_CHANGE=true
204
+ VITE_ALLOW_BUY_TOKEN_CHANGE=true
205
+ ```
206
+
207
+ ## License
208
+
209
+ MIT
@@ -0,0 +1,102 @@
1
+ import { arbitrum } from '@reown/appkit/networks';
2
+ import { avalanche } from '@reown/appkit/networks';
3
+ import { base } from '@reown/appkit/networks';
4
+ import { createAppKit } from '@reown/appkit/react';
5
+ import { CreateConnectorFn } from 'wagmi';
6
+ import { darkTheme } from '@uniswap-widget/core';
7
+ import { default as default_2 } from 'react';
8
+ import { DEFAULT_DEADLINE_MINUTES } from '@uniswap-widget/core';
9
+ import { DEFAULT_SLIPPAGE } from '@uniswap-widget/core';
10
+ import { fantom } from '@reown/appkit/networks';
11
+ import { Features } from '@reown/appkit/react';
12
+ import { JSX as JSX_2 } from 'react';
13
+ import { lightTheme } from '@uniswap-widget/core';
14
+ import { mainnet } from '@reown/appkit/networks';
15
+ import { moonbeam } from '@reown/appkit/networks';
16
+ import { optimism } from '@reown/appkit/networks';
17
+ import { polygon } from '@reown/appkit/networks';
18
+ import { PoolConfig } from '@uniswap-widget/core';
19
+ import { QueryClient } from '@tanstack/react-query';
20
+ import { SolaceTokenInfo } from '@uniswap-widget/core';
21
+ import { solana } from '@reown/appkit/networks';
22
+ import { SwapProps } from '@uniswap-widget/core';
23
+ import { SwapState } from '@uniswap-widget/core';
24
+ import { ThemeConfig } from '@uniswap-widget/core';
25
+ import { TokenInfo } from '@uniswap-widget/core';
26
+ import { useAppKit } from '@reown/appkit/react';
27
+ import { VIRTUAL_PROTOCOL_TOKEN } from '@uniswap-widget/core';
28
+ import { VritualProtocolTokenInfo } from '@uniswap-widget/core';
29
+ import { WagmiAdapter } from '@reown/appkit-adapter-wagmi';
30
+
31
+ export declare type AppKitFeatures = Features;
32
+
33
+ export declare interface AppKitMetadata {
34
+ name: string;
35
+ description: string;
36
+ url: string;
37
+ icons: string[];
38
+ }
39
+
40
+ export declare type AppKitNetwork = typeof base;
41
+
42
+ export { arbitrum }
43
+
44
+ export { avalanche }
45
+
46
+ export { base }
47
+
48
+ export { createAppKit }
49
+
50
+ export { CreateConnectorFn }
51
+
52
+ export { darkTheme }
53
+
54
+ export { DEFAULT_DEADLINE_MINUTES }
55
+
56
+ export { DEFAULT_SLIPPAGE }
57
+
58
+ export { fantom }
59
+
60
+ export { lightTheme }
61
+
62
+ export { mainnet }
63
+
64
+ export { moonbeam }
65
+
66
+ export { optimism }
67
+
68
+ export { polygon }
69
+
70
+ export { PoolConfig }
71
+
72
+ export declare function Provider({ children, wagmiAdapter, queryClient, }: ProviderProps): JSX_2.Element;
73
+
74
+ export declare interface ProviderProps {
75
+ children: React.ReactNode;
76
+ wagmiAdapter: WagmiAdapter;
77
+ queryClient?: QueryClient;
78
+ }
79
+
80
+ export { SolaceTokenInfo }
81
+
82
+ export { solana }
83
+
84
+ export { SwapProps }
85
+
86
+ export { SwapState }
87
+
88
+ export declare const SwapWidget: default_2.FC<SwapProps>;
89
+
90
+ export { ThemeConfig }
91
+
92
+ export { TokenInfo }
93
+
94
+ export { useAppKit }
95
+
96
+ export { VIRTUAL_PROTOCOL_TOKEN }
97
+
98
+ export { VritualProtocolTokenInfo }
99
+
100
+ export { WagmiAdapter }
101
+
102
+ export { }
@@ -0,0 +1,480 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useRef, useEffect, useState, useMemo } from "react";
3
+ import { useAccount, useWalletClient, WagmiProvider } from "wagmi";
4
+ import { ethers } from "ethers";
5
+ import { RATE_LIMIT_CONFIG, getQuote, executeSwap, lightTheme, DEFAULT_POOL_CONFIG } from "@uniswap-widget/core";
6
+ import { DEFAULT_DEADLINE_MINUTES, DEFAULT_SLIPPAGE, SolaceTokenInfo, VIRTUAL_PROTOCOL_TOKEN, VritualProtocolTokenInfo, darkTheme, lightTheme as lightTheme2 } from "@uniswap-widget/core";
7
+ import { useAppKit } from "@reown/appkit/react";
8
+ import { createAppKit, useAppKit as useAppKit2 } from "@reown/appkit/react";
9
+ import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
10
+ import { WagmiAdapter } from "@reown/appkit-adapter-wagmi";
11
+ import { arbitrum, avalanche, base, fantom, mainnet, moonbeam, optimism, polygon, solana } from "@reown/appkit/networks";
12
+ function useQuote({
13
+ signer,
14
+ state,
15
+ setState,
16
+ poolConfig
17
+ }) {
18
+ const debounceTimeout = useRef();
19
+ const lastQuoteParams = useRef("");
20
+ const abortController = useRef();
21
+ useEffect(() => {
22
+ setState((prev) => ({
23
+ ...prev,
24
+ inputToken: poolConfig.tokenIn,
25
+ outputToken: poolConfig.tokenOut
26
+ }));
27
+ }, [poolConfig]);
28
+ useEffect(() => {
29
+ if (debounceTimeout.current) {
30
+ clearTimeout(debounceTimeout.current);
31
+ }
32
+ if (abortController.current) {
33
+ abortController.current.abort();
34
+ }
35
+ async function updateQuote() {
36
+ if (!state.inputAmount || Number(state.inputAmount) === 0) {
37
+ setState((prev) => ({ ...prev, outputAmount: "" }));
38
+ return;
39
+ }
40
+ if (!signer) {
41
+ setState((prev) => ({
42
+ ...prev,
43
+ outputAmount: "",
44
+ error: "Please connect your wallet to get quotes"
45
+ }));
46
+ return;
47
+ }
48
+ const quoteKey = `${poolConfig.tokenIn.address}-${poolConfig.tokenOut.address}-${state.inputAmount}`;
49
+ if (lastQuoteParams.current === quoteKey) {
50
+ return;
51
+ }
52
+ lastQuoteParams.current = quoteKey;
53
+ const controller = new AbortController();
54
+ abortController.current = controller;
55
+ try {
56
+ setState((prev) => ({ ...prev, loading: true, error: null }));
57
+ const { outputAmount, routeInfo } = await getQuote({
58
+ signer,
59
+ inputToken: poolConfig.tokenIn,
60
+ outputToken: poolConfig.tokenOut,
61
+ inputAmount: state.inputAmount,
62
+ poolConfig,
63
+ signal: controller.signal
64
+ });
65
+ if (controller.signal.aborted) {
66
+ return;
67
+ }
68
+ setState((prev) => ({ ...prev, outputAmount, routeInfo }));
69
+ } catch (err) {
70
+ if (controller.signal.aborted) {
71
+ return;
72
+ }
73
+ const errorMessage = err instanceof Error ? err.message : "Failed to get quote";
74
+ setState((prev) => ({
75
+ ...prev,
76
+ outputAmount: "",
77
+ error: errorMessage
78
+ }));
79
+ } finally {
80
+ if (!controller.signal.aborted) {
81
+ setState((prev) => ({ ...prev, loading: false }));
82
+ }
83
+ }
84
+ }
85
+ debounceTimeout.current = setTimeout(
86
+ updateQuote,
87
+ RATE_LIMIT_CONFIG.QUOTE_DEBOUNCE
88
+ );
89
+ return () => {
90
+ if (debounceTimeout.current) {
91
+ clearTimeout(debounceTimeout.current);
92
+ }
93
+ if (abortController.current) {
94
+ abortController.current.abort();
95
+ }
96
+ };
97
+ }, [state.inputAmount, poolConfig, signer]);
98
+ return;
99
+ }
100
+ function useSwap({
101
+ state,
102
+ setState,
103
+ onSwap,
104
+ signer
105
+ }) {
106
+ async function swap() {
107
+ if (!signer) {
108
+ setState((prev) => ({ ...prev, error: "Please connect your wallet" }));
109
+ return;
110
+ }
111
+ if (!state.inputToken || !state.outputToken) {
112
+ setState((prev) => ({ ...prev, error: "Tokens not initialized" }));
113
+ return;
114
+ }
115
+ setState((prev) => ({ ...prev, txLoading: true }));
116
+ try {
117
+ await executeSwap({
118
+ signer,
119
+ inputToken: state.inputToken,
120
+ outputToken: state.outputToken,
121
+ inputAmount: state.inputAmount,
122
+ outputAmount: state.outputAmount,
123
+ onSwap
124
+ });
125
+ } catch (error) {
126
+ setState((prev) => ({
127
+ ...prev,
128
+ error: error instanceof Error ? error.message : "Swap failed"
129
+ }));
130
+ } finally {
131
+ setState((prev) => ({ ...prev, txLoading: false }));
132
+ }
133
+ }
134
+ return {
135
+ swap
136
+ };
137
+ }
138
+ const cx = (...classes) => classes.filter(Boolean).join(" ");
139
+ const ArrowDown = (props) => /* @__PURE__ */ jsx("svg", { ...props, viewBox: "0 0 512 512", className: "text-2xl w-6 h-6", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M256 400L56 200h400L256 400z" }) });
140
+ const SwapWidget = ({
141
+ poolConfig = DEFAULT_POOL_CONFIG,
142
+ theme: customTheme = {},
143
+ onSwap
144
+ }) => {
145
+ const { open } = useAppKit();
146
+ const { isConnected } = useAccount();
147
+ const { data: walletClient } = useWalletClient();
148
+ const [isSwapping, setIsSwapping] = useState(false);
149
+ const signer = useMemo(() => {
150
+ var _a, _b;
151
+ if (!walletClient) return void 0;
152
+ const { account, chain, transport } = walletClient;
153
+ const network = {
154
+ chainId: chain.id,
155
+ name: chain.name,
156
+ ensAddress: (_b = (_a = chain.contracts) == null ? void 0 : _a.ensRegistry) == null ? void 0 : _b.address
157
+ };
158
+ const provider = new ethers.providers.Web3Provider(transport, network);
159
+ return provider.getSigner(account.address);
160
+ }, [walletClient]);
161
+ const theme = useMemo(
162
+ () => ({
163
+ ...lightTheme,
164
+ ...customTheme,
165
+ tokenButton: {
166
+ ...lightTheme.tokenButton,
167
+ ...customTheme.tokenButton
168
+ },
169
+ swapButton: {
170
+ ...lightTheme.swapButton,
171
+ ...customTheme.swapButton
172
+ },
173
+ connectButton: {
174
+ ...lightTheme.connectButton,
175
+ ...customTheme.connectButton
176
+ },
177
+ inputField: {
178
+ ...lightTheme.inputField,
179
+ ...customTheme.inputField
180
+ },
181
+ buySection: {
182
+ ...lightTheme.buySection,
183
+ ...customTheme.buySection
184
+ }
185
+ }),
186
+ [customTheme]
187
+ );
188
+ const [state, setState] = useState({
189
+ inputAmount: "",
190
+ outputAmount: "",
191
+ inputToken: null,
192
+ outputToken: null,
193
+ loading: false,
194
+ error: null,
195
+ inputDisabled: true
196
+ });
197
+ useEffect(() => {
198
+ setState((prev) => ({
199
+ ...prev,
200
+ inputDisabled: !isConnected,
201
+ error: !isConnected ? "Please connect your wallet" : null
202
+ }));
203
+ }, [isConnected]);
204
+ useQuote({ state, setState, poolConfig, signer: signer || void 0 });
205
+ const { swap } = useSwap({ state, setState, onSwap, signer: signer || void 0 });
206
+ const handleSwap = async () => {
207
+ if (!signer) {
208
+ setState((prev) => ({ ...prev, error: "Please connect your wallet" }));
209
+ return;
210
+ }
211
+ setIsSwapping(true);
212
+ try {
213
+ await swap();
214
+ } finally {
215
+ setIsSwapping(false);
216
+ setState((prev) => ({ ...prev, inputAmount: "", outputAmount: "" }));
217
+ }
218
+ };
219
+ const handleInputAmountChange = (e) => {
220
+ const value = e.target.value;
221
+ if (value === "" || /^\d*\.?\d*$/.test(value)) {
222
+ setState((prev) => ({ ...prev, inputAmount: value }));
223
+ }
224
+ };
225
+ const onConnectWallet = async () => {
226
+ open({
227
+ view: "Connect"
228
+ });
229
+ };
230
+ return /* @__PURE__ */ jsxs(
231
+ "div",
232
+ {
233
+ className: "relative w-full max-w-md rounded-xl p-2",
234
+ style: { backgroundColor: theme.background },
235
+ children: [
236
+ /* @__PURE__ */ jsxs(
237
+ "div",
238
+ {
239
+ className: "p-4 rounded-2xl relative",
240
+ style: {
241
+ backgroundColor: theme.foreground,
242
+ border: `1px solid ${theme.border}`,
243
+ opacity: !isConnected ? 0.5 : 1
244
+ },
245
+ children: [
246
+ /* @__PURE__ */ jsx("label", { className: "block mb-2", style: { color: theme.textSecondary }, children: "Sell" }),
247
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
248
+ /* @__PURE__ */ jsx(
249
+ "input",
250
+ {
251
+ type: "text",
252
+ disabled: !isConnected,
253
+ value: state.inputAmount,
254
+ onChange: handleInputAmountChange,
255
+ className: cx(
256
+ "w-full text-2xl outline-none",
257
+ !isConnected && "cursor-not-allowed"
258
+ ),
259
+ placeholder: "0",
260
+ inputMode: "decimal",
261
+ style: {
262
+ backgroundColor: !isConnected ? theme.inputField.disabledBackground : theme.inputField.background,
263
+ color: !isConnected ? theme.inputField.disabledText : theme.inputField.text
264
+ }
265
+ }
266
+ ),
267
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsxs(
268
+ "div",
269
+ {
270
+ className: cx(
271
+ "ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]",
272
+ !isConnected && "opacity-50"
273
+ ),
274
+ style: {
275
+ backgroundColor: theme.tokenButton.background,
276
+ border: `1px solid ${theme.tokenButton.border}`
277
+ },
278
+ children: [
279
+ poolConfig.tokenIn.logoURI && /* @__PURE__ */ jsx(
280
+ "img",
281
+ {
282
+ src: poolConfig.tokenIn.logoURI,
283
+ alt: poolConfig.tokenIn.symbol,
284
+ className: "h-[20px] w-[20px] flex-shrink-0 rounded-full",
285
+ onError: (e) => {
286
+ e.target.style.display = "none";
287
+ }
288
+ }
289
+ ),
290
+ /* @__PURE__ */ jsx(
291
+ "span",
292
+ {
293
+ style: { color: theme.tokenButton.text },
294
+ className: "font-bold text-sm",
295
+ children: poolConfig.tokenIn.symbol
296
+ }
297
+ )
298
+ ]
299
+ }
300
+ ) })
301
+ ] })
302
+ ]
303
+ }
304
+ ),
305
+ /* @__PURE__ */ jsx("div", { className: "relative z-10 flex justify-center items-center h-[5px]", children: /* @__PURE__ */ jsx(
306
+ "div",
307
+ {
308
+ className: "rounded-2xl w-[40px] h-[40px] flex justify-center items-center",
309
+ style: {
310
+ backgroundColor: theme.border,
311
+ opacity: !isConnected ? 0.5 : 1
312
+ },
313
+ children: /* @__PURE__ */ jsx(ArrowDown, { className: "text-2xl", style: { color: theme.text } })
314
+ }
315
+ ) }),
316
+ /* @__PURE__ */ jsxs(
317
+ "div",
318
+ {
319
+ className: "mb-2 p-4 rounded-2xl relative",
320
+ style: {
321
+ backgroundColor: theme.buySection.background,
322
+ border: `1px solid ${theme.buySection.border}`,
323
+ opacity: !isConnected ? 0.5 : 1
324
+ },
325
+ children: [
326
+ /* @__PURE__ */ jsx("label", { className: "block mb-2", style: { color: theme.textSecondary }, children: "Buy" }),
327
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
328
+ /* @__PURE__ */ jsx(
329
+ "input",
330
+ {
331
+ type: "text",
332
+ value: state.loading ? "Fetching Quotes" : state.outputAmount || "0",
333
+ readOnly: true,
334
+ disabled: true,
335
+ className: cx(
336
+ "w-full text-2xl outline-none disabled:text-lg",
337
+ !isConnected && "cursor-not-allowed"
338
+ ),
339
+ style: {
340
+ backgroundColor: !isConnected ? theme.inputField.disabledBackground : theme.inputField.background,
341
+ color: !isConnected ? theme.inputField.disabledText : theme.inputField.text,
342
+ opacity: state.loading ? 0.3 : !isConnected ? 0.5 : 0.8
343
+ },
344
+ placeholder: "0"
345
+ }
346
+ ),
347
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsxs(
348
+ "div",
349
+ {
350
+ className: cx(
351
+ "ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]",
352
+ !isConnected && "opacity-50"
353
+ ),
354
+ style: {
355
+ backgroundColor: theme.tokenButton.background,
356
+ border: `1px solid ${theme.tokenButton.border}`,
357
+ padding: `${theme.tokenButton.paddingY}px ${theme.tokenButton.paddingX}px`
358
+ },
359
+ children: [
360
+ poolConfig.tokenOut.logoURI && /* @__PURE__ */ jsx(
361
+ "img",
362
+ {
363
+ src: poolConfig.tokenOut.logoURI,
364
+ alt: poolConfig.tokenOut.symbol,
365
+ className: "h-[20px] w-[20px] flex-shrink-0 rounded-full",
366
+ onError: (e) => {
367
+ e.target.style.display = "none";
368
+ }
369
+ }
370
+ ),
371
+ /* @__PURE__ */ jsx(
372
+ "span",
373
+ {
374
+ style: { color: theme.tokenButton.text },
375
+ className: "font-bold text-sm",
376
+ children: poolConfig.tokenOut.symbol
377
+ }
378
+ )
379
+ ]
380
+ }
381
+ ) })
382
+ ] })
383
+ ]
384
+ }
385
+ ),
386
+ state.error && /* @__PURE__ */ jsx("div", { className: "mb-2 p-4 bg-red-50 text-red-500 rounded-2xl overflow-x-hidden", children: state.error }),
387
+ isConnected ? /* @__PURE__ */ jsx(
388
+ "button",
389
+ {
390
+ disabled: state.loading || isSwapping || !state.inputAmount || Number(state.inputAmount) <= 0,
391
+ onClick: handleSwap,
392
+ className: "w-full py-4 rounded-2xl transition-colors cursor-pointer",
393
+ style: {
394
+ backgroundColor: state.loading || isSwapping || !state.inputAmount || Number(state.inputAmount) <= 0 ? theme.swapButton.disabledBackground : theme.swapButton.background,
395
+ color: state.loading || isSwapping || !state.inputAmount || Number(state.inputAmount) <= 0 ? theme.swapButton.disabledText : theme.swapButton.text
396
+ },
397
+ children: isSwapping ? "Swapping..." : state.loading ? "Getting Quote..." : "Swap"
398
+ }
399
+ ) : /* @__PURE__ */ jsx(
400
+ "button",
401
+ {
402
+ onClick: onConnectWallet,
403
+ className: "w-full py-4 rounded-2xl transition-colors",
404
+ style: {
405
+ backgroundColor: theme.connectButton.background,
406
+ color: theme.connectButton.text
407
+ },
408
+ children: "Connect Wallet"
409
+ }
410
+ ),
411
+ state.inputAmount && state.outputAmount && /* @__PURE__ */ jsxs("div", { className: "p-4 rounded-2xl", children: [
412
+ /* @__PURE__ */ jsxs(
413
+ "div",
414
+ {
415
+ className: "flex justify-between items-center text-sm mb-2",
416
+ style: { color: theme.textSecondary },
417
+ children: [
418
+ "1 ",
419
+ poolConfig.tokenIn.symbol,
420
+ " =",
421
+ " ",
422
+ (Number(state.outputAmount) / Number(state.inputAmount)).toFixed(
423
+ 6
424
+ ),
425
+ " ",
426
+ poolConfig.tokenOut.symbol
427
+ ]
428
+ }
429
+ ),
430
+ state.routeInfo && /* @__PURE__ */ jsx(
431
+ "div",
432
+ {
433
+ className: "mt-2 text-xs",
434
+ style: { color: theme.textSecondary },
435
+ children: state.routeInfo.isDirectRoute ? /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
436
+ /* @__PURE__ */ jsx("span", { children: "Direct swap" }),
437
+ /* @__PURE__ */ jsx("span", { children: state.routeInfo.routeString })
438
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex justify-between", children: /* @__PURE__ */ jsxs("span", { children: [
439
+ "Route: ",
440
+ state.routeInfo.routeString
441
+ ] }) })
442
+ }
443
+ )
444
+ ] }),
445
+ isConnected && /* @__PURE__ */ jsx("div", { className: "flex justify-center items-center mt-2", children: /* @__PURE__ */ jsx("appkit-account-button", {}) })
446
+ ]
447
+ }
448
+ );
449
+ };
450
+ function Provider({
451
+ children,
452
+ wagmiAdapter,
453
+ queryClient = new QueryClient()
454
+ }) {
455
+ return /* @__PURE__ */ jsx(WagmiProvider, { config: wagmiAdapter.wagmiConfig, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children }) });
456
+ }
457
+ export {
458
+ DEFAULT_DEADLINE_MINUTES,
459
+ DEFAULT_SLIPPAGE,
460
+ Provider,
461
+ SolaceTokenInfo,
462
+ SwapWidget,
463
+ VIRTUAL_PROTOCOL_TOKEN,
464
+ VritualProtocolTokenInfo,
465
+ WagmiAdapter,
466
+ arbitrum,
467
+ avalanche,
468
+ base,
469
+ createAppKit,
470
+ darkTheme,
471
+ fantom,
472
+ lightTheme2 as lightTheme,
473
+ mainnet,
474
+ moonbeam,
475
+ optimism,
476
+ polygon,
477
+ solana,
478
+ useAppKit2 as useAppKit
479
+ };
480
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.es.js","sources":["../src/hooks/useQuote.ts","../src/hooks/useSwap.ts","../src/components/SwapWidget.tsx","../src/components/Provider.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { ethers } from \"ethers\";\nimport {\n getQuote,\n RATE_LIMIT_CONFIG,\n type SwapState,\n type PoolConfig,\n} from \"@uniswap-widget/core\";\n\n/**\n * React binding for the core `getQuote`. Owns the reactive concerns debounce,\n * de-duplication, abort, and state writes while the actual quote logic lives\n * in `@uniswap-widget/core`.\n */\nexport default function useQuote({\n signer,\n state,\n setState,\n poolConfig,\n}: {\n signer?: ethers.Signer;\n state: SwapState;\n setState: React.Dispatch<React.SetStateAction<SwapState>>;\n poolConfig: PoolConfig;\n}) {\n const debounceTimeout = useRef<NodeJS.Timeout>();\n const lastQuoteParams = useRef<string>(\"\");\n const abortController = useRef<AbortController>();\n\n useEffect(() => {\n // Initialize tokens from pool config\n setState((prev) => ({\n ...prev,\n inputToken: poolConfig.tokenIn,\n outputToken: poolConfig.tokenOut,\n }));\n }, [poolConfig]);\n\n useEffect(() => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n\n if (abortController.current) {\n abortController.current.abort();\n }\n\n async function updateQuote() {\n if (!state.inputAmount || Number(state.inputAmount) === 0) {\n setState((prev) => ({ ...prev, outputAmount: \"\" }));\n return;\n }\n\n if (!signer) {\n setState((prev) => ({\n ...prev,\n outputAmount: \"\",\n error: \"Please connect your wallet to get quotes\",\n }));\n return;\n }\n\n const quoteKey = `${poolConfig.tokenIn.address}-${poolConfig.tokenOut.address}-${state.inputAmount}`;\n if (lastQuoteParams.current === quoteKey) {\n return;\n }\n lastQuoteParams.current = quoteKey;\n\n const controller = new AbortController();\n abortController.current = controller;\n\n try {\n setState((prev) => ({ ...prev, loading: true, error: null }));\n\n const { outputAmount, routeInfo } = await getQuote({\n signer,\n inputToken: poolConfig.tokenIn,\n outputToken: poolConfig.tokenOut,\n inputAmount: state.inputAmount,\n poolConfig,\n signal: controller.signal,\n });\n\n if (controller.signal.aborted) {\n return;\n }\n\n setState((prev) => ({ ...prev, outputAmount, routeInfo }));\n } catch (err) {\n if (controller.signal.aborted) {\n return;\n }\n\n const errorMessage =\n err instanceof Error ? err.message : \"Failed to get quote\";\n\n setState((prev) => ({\n ...prev,\n outputAmount: \"\",\n error: errorMessage,\n }));\n } finally {\n if (!controller.signal.aborted) {\n setState((prev) => ({ ...prev, loading: false }));\n }\n }\n }\n\n debounceTimeout.current = setTimeout(\n updateQuote,\n RATE_LIMIT_CONFIG.QUOTE_DEBOUNCE\n );\n\n return () => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n if (abortController.current) {\n abortController.current.abort();\n }\n };\n }, [state.inputAmount, poolConfig, signer]);\n\n return;\n}\n","import { ethers } from \"ethers\";\nimport { executeSwap, type SwapState } from \"@uniswap-widget/core\";\n\n/**\n * React binding for the core `executeSwap`. Manages loading/error state; the\n * swap itself (approve, send, wait, callback) lives in `@uniswap-widget/core`.\n */\nexport default function useSwap({\n state,\n setState,\n onSwap,\n signer,\n}: {\n state: SwapState;\n setState: React.Dispatch<React.SetStateAction<SwapState>>;\n onSwap?: (inputAmount: string, outputAmount: string) => Promise<void>;\n signer?: ethers.Signer;\n}) {\n async function swap() {\n if (!signer) {\n setState((prev) => ({ ...prev, error: \"Please connect your wallet\" }));\n return;\n }\n\n if (!state.inputToken || !state.outputToken) {\n setState((prev) => ({ ...prev, error: \"Tokens not initialized\" }));\n return;\n }\n\n setState((prev) => ({ ...prev, txLoading: true }));\n\n try {\n await executeSwap({\n signer,\n inputToken: state.inputToken,\n outputToken: state.outputToken,\n inputAmount: state.inputAmount,\n outputAmount: state.outputAmount,\n onSwap,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n error: error instanceof Error ? error.message : \"Swap failed\",\n }));\n } finally {\n setState((prev) => ({ ...prev, txLoading: false }));\n }\n }\n\n return {\n swap,\n };\n}\n","import React, { useState, useMemo, useEffect } from \"react\";\nimport { useAccount, useWalletClient } from \"wagmi\";\nimport { ethers } from \"ethers\";\nimport {\n DEFAULT_POOL_CONFIG,\n lightTheme,\n type SwapState,\n type SwapProps,\n type ThemeConfig,\n} from \"@uniswap-widget/core\";\nimport useQuote from \"../hooks/useQuote\";\nimport useSwap from \"../hooks/useSwap\";\nimport { useAppKit } from \"@reown/appkit/react\";\n\nconst cx = (...classes: (string | false | null | undefined)[]) =>\n classes.filter(Boolean).join(\" \");\n\nconst ArrowDown = (props: React.SVGProps<SVGSVGElement>) => (\n <svg {...props} viewBox=\"0 0 512 512\" className=\"text-2xl w-6 h-6\" fill=\"currentColor\">\n <path d=\"M256 400L56 200h400L256 400z\"/>\n </svg>\n)\n\nconst SwapWidget: React.FC<SwapProps> = ({\n poolConfig = DEFAULT_POOL_CONFIG,\n theme: customTheme = {},\n onSwap,\n}) => {\n const { open } = useAppKit();\n const { isConnected } = useAccount();\n const { data: walletClient } = useWalletClient();\n const [isSwapping, setIsSwapping] = useState(false);\n\n const signer = useMemo(() => {\n if (!walletClient) return undefined;\n const { account, chain, transport } = walletClient;\n const network = {\n chainId: chain.id,\n name: chain.name,\n ensAddress: chain.contracts?.ensRegistry?.address,\n };\n const provider = new ethers.providers.Web3Provider(transport, network);\n return provider.getSigner(account.address);\n }, [walletClient]);\n\n // Merge custom theme with default light theme\n const theme = useMemo<ThemeConfig>(\n () => ({\n ...lightTheme,\n ...customTheme,\n tokenButton: {\n ...lightTheme.tokenButton,\n ...customTheme.tokenButton,\n },\n swapButton: {\n ...lightTheme.swapButton,\n ...customTheme.swapButton,\n },\n connectButton: {\n ...lightTheme.connectButton,\n ...customTheme.connectButton,\n },\n inputField: {\n ...lightTheme.inputField,\n ...customTheme.inputField,\n },\n buySection: {\n ...lightTheme.buySection,\n ...customTheme.buySection,\n },\n }),\n [customTheme]\n );\n\n const [state, setState] = useState<SwapState>({\n inputAmount: \"\",\n outputAmount: \"\",\n inputToken: null,\n outputToken: null,\n loading: false,\n error: null,\n inputDisabled: true,\n });\n\n useEffect(() => {\n setState((prev) => ({\n ...prev,\n inputDisabled: !isConnected,\n error: !isConnected ? \"Please connect your wallet\" : null,\n }));\n }, [isConnected]);\n\n // Always call hooks, but pass undefined if no signer\n useQuote({ state, setState, poolConfig, signer: signer || undefined });\n const { swap } = useSwap({ state, setState, onSwap, signer: signer || undefined });\n\n const handleSwap = async () => {\n if (!signer) {\n setState(prev => ({ ...prev, error: \"Please connect your wallet\" }));\n return;\n }\n setIsSwapping(true);\n try {\n await swap();\n } finally {\n setIsSwapping(false);\n setState((prev) => ({ ...prev, inputAmount: \"\", outputAmount: \"\" }));\n }\n };\n\n const handleInputAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n if (value === \"\" || /^\\d*\\.?\\d*$/.test(value)) {\n setState((prev) => ({ ...prev, inputAmount: value }));\n }\n };\n\n const onConnectWallet = async () => {\n open({\n view: \"Connect\",\n });\n };\n\n return (\n <div\n className=\"relative w-full max-w-md rounded-xl p-2\"\n style={{ backgroundColor: theme.background }}\n >\n {/* Sell Section */}\n <div\n className=\"p-4 rounded-2xl relative\"\n style={{\n backgroundColor: theme.foreground,\n border: `1px solid ${theme.border}`,\n opacity: !isConnected ? 0.5 : 1,\n }}\n >\n <label className=\"block mb-2\" style={{ color: theme.textSecondary }}>\n Sell\n </label>\n <div className=\"flex items-center\">\n <input\n type=\"text\"\n disabled={!isConnected}\n value={state.inputAmount}\n onChange={handleInputAmountChange}\n className={cx(\n \"w-full text-2xl outline-none\",\n !isConnected && \"cursor-not-allowed\"\n )}\n placeholder=\"0\"\n inputMode=\"decimal\"\n style={{\n backgroundColor: !isConnected\n ? theme.inputField.disabledBackground\n : theme.inputField.background,\n color: !isConnected\n ? theme.inputField.disabledText\n : theme.inputField.text,\n }}\n />\n <div className=\"flex flex-col gap-2\">\n <div\n className={cx(\n \"ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]\",\n !isConnected && \"opacity-50\"\n )}\n style={{\n backgroundColor: theme.tokenButton.background,\n border: `1px solid ${theme.tokenButton.border}`,\n }}\n >\n {poolConfig.tokenIn.logoURI && (\n <img\n src={poolConfig.tokenIn.logoURI}\n alt={poolConfig.tokenIn.symbol}\n className=\"h-[20px] w-[20px] flex-shrink-0 rounded-full\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n )}\n <span\n style={{ color: theme.tokenButton.text }}\n className=\"font-bold text-sm\"\n >\n {poolConfig.tokenIn.symbol}\n </span>\n </div>\n </div>\n </div>\n </div>\n\n {/* Swap Arrow */}\n <div className=\"relative z-10 flex justify-center items-center h-[5px]\">\n <div\n className=\"rounded-2xl w-[40px] h-[40px] flex justify-center items-center\"\n style={{ \n backgroundColor: theme.border,\n opacity: !isConnected ? 0.5 : 1\n }}\n >\n <ArrowDown className=\"text-2xl\" style={{ color: theme.text }} />\n </div>\n </div>\n\n {/* Buy Section */}\n <div\n className=\"mb-2 p-4 rounded-2xl relative\"\n style={{\n backgroundColor: theme.buySection.background,\n border: `1px solid ${theme.buySection.border}`,\n opacity: !isConnected ? 0.5 : 1,\n }}\n >\n <label className=\"block mb-2\" style={{ color: theme.textSecondary }}>\n Buy\n </label>\n <div className=\"flex items-center\">\n <input\n type=\"text\"\n value={\n state.loading ? \"Fetching Quotes\" : state.outputAmount || \"0\"\n }\n readOnly\n disabled={true}\n className={cx(\n \"w-full text-2xl outline-none disabled:text-lg\",\n !isConnected && \"cursor-not-allowed\"\n )}\n style={{\n backgroundColor: !isConnected\n ? theme.inputField.disabledBackground\n : theme.inputField.background,\n color: !isConnected\n ? theme.inputField.disabledText\n : theme.inputField.text,\n opacity: state.loading ? 0.3 : !isConnected ? 0.5 : 0.8,\n }}\n placeholder=\"0\"\n />\n <div className=\"flex flex-col gap-2\">\n <div\n className={cx(\n \"ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]\",\n !isConnected && \"opacity-50\"\n )}\n style={{\n backgroundColor: theme.tokenButton.background,\n border: `1px solid ${theme.tokenButton.border}`,\n padding: `${theme.tokenButton.paddingY}px ${theme.tokenButton.paddingX}px`,\n }}\n >\n {poolConfig.tokenOut.logoURI && (\n <img\n src={poolConfig.tokenOut.logoURI}\n alt={poolConfig.tokenOut.symbol}\n className=\"h-[20px] w-[20px] flex-shrink-0 rounded-full\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n )}\n <span\n style={{ color: theme.tokenButton.text }}\n className=\"font-bold text-sm\"\n >\n {poolConfig.tokenOut.symbol}\n </span>\n </div>\n </div>\n </div>\n </div>\n\n {/* Error Message */}\n {state.error && (\n <div className=\"mb-2 p-4 bg-red-50 text-red-500 rounded-2xl overflow-x-hidden\">\n {state.error}\n </div>\n )}\n\n {/* Action Button */}\n {isConnected ? (\n <button\n disabled={\n state.loading ||\n isSwapping ||\n !state.inputAmount ||\n Number(state.inputAmount) <= 0\n }\n onClick={handleSwap}\n className=\"w-full py-4 rounded-2xl transition-colors cursor-pointer\"\n style={{\n backgroundColor:\n state.loading ||\n isSwapping ||\n !state.inputAmount ||\n Number(state.inputAmount) <= 0\n ? theme.swapButton.disabledBackground\n : theme.swapButton.background,\n color:\n state.loading ||\n isSwapping ||\n !state.inputAmount ||\n Number(state.inputAmount) <= 0\n ? theme.swapButton.disabledText\n : theme.swapButton.text,\n }}\n >\n {isSwapping ? \"Swapping...\" : state.loading ? \"Getting Quote...\" : \"Swap\"}\n </button>\n ) : (\n <button\n onClick={onConnectWallet}\n className=\"w-full py-4 rounded-2xl transition-colors\"\n style={{\n backgroundColor: theme.connectButton.background,\n color: theme.connectButton.text,\n }}\n >\n Connect Wallet\n </button>\n )}\n\n {/* Price Info */}\n {state.inputAmount && state.outputAmount && (\n <div className=\"p-4 rounded-2xl\">\n <div\n className=\"flex justify-between items-center text-sm mb-2\"\n style={{ color: theme.textSecondary }}\n >\n 1 {poolConfig.tokenIn.symbol} ={\" \"}\n {(Number(state.outputAmount) / Number(state.inputAmount)).toFixed(\n 6\n )}{\" \"}\n {poolConfig.tokenOut.symbol}\n </div>\n\n {state.routeInfo && (\n <div\n className=\"mt-2 text-xs\"\n style={{ color: theme.textSecondary }}\n >\n {state.routeInfo.isDirectRoute ? (\n <div className=\"flex justify-between\">\n <span>Direct swap</span>\n <span>{state.routeInfo.routeString}</span>\n </div>\n ) : (\n <div className=\"flex justify-between\">\n <span>Route: {state.routeInfo.routeString}</span>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {/* Account Button */}\n {isConnected && (\n <div className=\"flex justify-center items-center mt-2\">\n <appkit-account-button />\n </div>\n )}\n </div>\n );\n};\n\nexport default SwapWidget;\n","\"use client\";\n\nimport { WagmiAdapter } from \"@reown/appkit-adapter-wagmi\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { WagmiProvider } from \"wagmi\";\n\nexport interface ProviderProps {\n children: React.ReactNode;\n wagmiAdapter: WagmiAdapter;\n queryClient?: QueryClient;\n}\n\nexport function Provider({\n children,\n wagmiAdapter,\n queryClient = new QueryClient(),\n}: ProviderProps) {\n return (\n <WagmiProvider config={wagmiAdapter.wagmiConfig}>\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n </WagmiProvider>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react/jsx-runtime"),require("react"),require("wagmi"),require("ethers"),require("@uniswap-widget/core"),require("@reown/appkit/react"),require("@tanstack/react-query"),require("@reown/appkit-adapter-wagmi"),require("@reown/appkit/networks")):"function"==typeof define&&define.amd?define(["exports","react/jsx-runtime","react","wagmi","ethers","@uniswap-widget/core","@reown/appkit/react","@tanstack/react-query","@reown/appkit-adapter-wagmi","@reown/appkit/networks"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).UniswapWidgetReact={},e.jsx,e.React,e.wagmi,e.ethers,e.UniswapWidgetCore,e.reownAppkitReact,e.reactQuery,e.reownAppkitAdapterWagmi,e.reownAppkitNetworks)}(this,function(e,t,n,o,r,i,l,u,a,s){"use strict";const c=(...e)=>e.filter(Boolean).join(" "),d=e=>t.jsx("svg",{...e,viewBox:"0 0 512 512",className:"text-2xl w-6 h-6",fill:"currentColor",children:t.jsx("path",{d:"M256 400L56 200h400L256 400z"})});Object.defineProperty(e,"DEFAULT_DEADLINE_MINUTES",{enumerable:!0,get:()=>i.DEFAULT_DEADLINE_MINUTES}),Object.defineProperty(e,"DEFAULT_SLIPPAGE",{enumerable:!0,get:()=>i.DEFAULT_SLIPPAGE}),Object.defineProperty(e,"SolaceTokenInfo",{enumerable:!0,get:()=>i.SolaceTokenInfo}),Object.defineProperty(e,"VIRTUAL_PROTOCOL_TOKEN",{enumerable:!0,get:()=>i.VIRTUAL_PROTOCOL_TOKEN}),Object.defineProperty(e,"VritualProtocolTokenInfo",{enumerable:!0,get:()=>i.VritualProtocolTokenInfo}),Object.defineProperty(e,"darkTheme",{enumerable:!0,get:()=>i.darkTheme}),Object.defineProperty(e,"lightTheme",{enumerable:!0,get:()=>i.lightTheme}),Object.defineProperty(e,"createAppKit",{enumerable:!0,get:()=>l.createAppKit}),Object.defineProperty(e,"useAppKit",{enumerable:!0,get:()=>l.useAppKit}),Object.defineProperty(e,"WagmiAdapter",{enumerable:!0,get:()=>a.WagmiAdapter}),Object.defineProperty(e,"arbitrum",{enumerable:!0,get:()=>s.arbitrum}),Object.defineProperty(e,"avalanche",{enumerable:!0,get:()=>s.avalanche}),Object.defineProperty(e,"base",{enumerable:!0,get:()=>s.base}),Object.defineProperty(e,"fantom",{enumerable:!0,get:()=>s.fantom}),Object.defineProperty(e,"mainnet",{enumerable:!0,get:()=>s.mainnet}),Object.defineProperty(e,"moonbeam",{enumerable:!0,get:()=>s.moonbeam}),Object.defineProperty(e,"optimism",{enumerable:!0,get:()=>s.optimism}),Object.defineProperty(e,"polygon",{enumerable:!0,get:()=>s.polygon}),Object.defineProperty(e,"solana",{enumerable:!0,get:()=>s.solana}),e.Provider=function({children:e,wagmiAdapter:n,queryClient:r=new u.QueryClient}){return t.jsx(o.WagmiProvider,{config:n.wagmiConfig,children:t.jsx(u.QueryClientProvider,{client:r,children:e})})},e.SwapWidget=({poolConfig:e=i.DEFAULT_POOL_CONFIG,theme:u={},onSwap:a})=>{const{open:s}=l.useAppKit(),{isConnected:p}=o.useAccount(),{data:m}=o.useWalletClient(),[g,b]=n.useState(!1),x=n.useMemo(()=>{var e,t;if(!m)return;const{account:n,chain:o,transport:i}=m,l={chainId:o.id,name:o.name,ensAddress:null==(t=null==(e=o.contracts)?void 0:e.ensRegistry)?void 0:t.address};return new r.ethers.providers.Web3Provider(i,l).getSigner(n.address)},[m]),f=n.useMemo(()=>({...i.lightTheme,...u,tokenButton:{...i.lightTheme.tokenButton,...u.tokenButton},swapButton:{...i.lightTheme.swapButton,...u.swapButton},connectButton:{...i.lightTheme.connectButton,...u.connectButton},inputField:{...i.lightTheme.inputField,...u.inputField},buySection:{...i.lightTheme.buySection,...u.buySection}}),[u]),[y,k]=n.useState({inputAmount:"",outputAmount:"",inputToken:null,outputToken:null,loading:!1,error:null,inputDisabled:!0});n.useEffect(()=>{k(e=>({...e,inputDisabled:!p,error:p?null:"Please connect your wallet"}))},[p]),function({signer:e,state:t,setState:o,poolConfig:r}){const l=n.useRef(),u=n.useRef(""),a=n.useRef();n.useEffect(()=>{o(e=>({...e,inputToken:r.tokenIn,outputToken:r.tokenOut}))},[r]),n.useEffect(()=>(l.current&&clearTimeout(l.current),a.current&&a.current.abort(),l.current=setTimeout(async function(){if(!t.inputAmount||0===Number(t.inputAmount))return void o(e=>({...e,outputAmount:""}));if(!e)return void o(e=>({...e,outputAmount:"",error:"Please connect your wallet to get quotes"}));const n=`${r.tokenIn.address}-${r.tokenOut.address}-${t.inputAmount}`;if(u.current===n)return;u.current=n;const l=new AbortController;a.current=l;try{o(e=>({...e,loading:!0,error:null}));const{outputAmount:n,routeInfo:u}=await i.getQuote({signer:e,inputToken:r.tokenIn,outputToken:r.tokenOut,inputAmount:t.inputAmount,poolConfig:r,signal:l.signal});if(l.signal.aborted)return;o(e=>({...e,outputAmount:n,routeInfo:u}))}catch(s){if(l.signal.aborted)return;const e=s instanceof Error?s.message:"Failed to get quote";o(t=>({...t,outputAmount:"",error:e}))}finally{l.signal.aborted||o(e=>({...e,loading:!1}))}},i.RATE_LIMIT_CONFIG.QUOTE_DEBOUNCE),()=>{l.current&&clearTimeout(l.current),a.current&&a.current.abort()}),[t.inputAmount,r,e])}({state:y,setState:k,poolConfig:e,signer:x||void 0});const{swap:h}=function({state:e,setState:t,onSwap:n,signer:o}){return{swap:async function(){if(o)if(e.inputToken&&e.outputToken){t(e=>({...e,txLoading:!0}));try{await i.executeSwap({signer:o,inputToken:e.inputToken,outputToken:e.outputToken,inputAmount:e.inputAmount,outputAmount:e.outputAmount,onSwap:n})}catch(r){t(e=>({...e,error:r instanceof Error?r.message:"Swap failed"}))}finally{t(e=>({...e,txLoading:!1}))}}else t(e=>({...e,error:"Tokens not initialized"}));else t(e=>({...e,error:"Please connect your wallet"}))}}}({state:y,setState:k,onSwap:a,signer:x||void 0});return t.jsxs("div",{className:"relative w-full max-w-md rounded-xl p-2",style:{backgroundColor:f.background},children:[t.jsxs("div",{className:"p-4 rounded-2xl relative",style:{backgroundColor:f.foreground,border:`1px solid ${f.border}`,opacity:p?1:.5},children:[t.jsx("label",{className:"block mb-2",style:{color:f.textSecondary},children:"Sell"}),t.jsxs("div",{className:"flex items-center",children:[t.jsx("input",{type:"text",disabled:!p,value:y.inputAmount,onChange:e=>{const t=e.target.value;(""===t||/^\d*\.?\d*$/.test(t))&&k(e=>({...e,inputAmount:t}))},className:c("w-full text-2xl outline-none",!p&&"cursor-not-allowed"),placeholder:"0",inputMode:"decimal",style:{backgroundColor:p?f.inputField.background:f.inputField.disabledBackground,color:p?f.inputField.text:f.inputField.disabledText}}),t.jsx("div",{className:"flex flex-col gap-2",children:t.jsxs("div",{className:c("ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]",!p&&"opacity-50"),style:{backgroundColor:f.tokenButton.background,border:`1px solid ${f.tokenButton.border}`},children:[e.tokenIn.logoURI&&t.jsx("img",{src:e.tokenIn.logoURI,alt:e.tokenIn.symbol,className:"h-[20px] w-[20px] flex-shrink-0 rounded-full",onError:e=>{e.target.style.display="none"}}),t.jsx("span",{style:{color:f.tokenButton.text},className:"font-bold text-sm",children:e.tokenIn.symbol})]})})]})]}),t.jsx("div",{className:"relative z-10 flex justify-center items-center h-[5px]",children:t.jsx("div",{className:"rounded-2xl w-[40px] h-[40px] flex justify-center items-center",style:{backgroundColor:f.border,opacity:p?1:.5},children:t.jsx(d,{className:"text-2xl",style:{color:f.text}})})}),t.jsxs("div",{className:"mb-2 p-4 rounded-2xl relative",style:{backgroundColor:f.buySection.background,border:`1px solid ${f.buySection.border}`,opacity:p?1:.5},children:[t.jsx("label",{className:"block mb-2",style:{color:f.textSecondary},children:"Buy"}),t.jsxs("div",{className:"flex items-center",children:[t.jsx("input",{type:"text",value:y.loading?"Fetching Quotes":y.outputAmount||"0",readOnly:!0,disabled:!0,className:c("w-full text-2xl outline-none disabled:text-lg",!p&&"cursor-not-allowed"),style:{backgroundColor:p?f.inputField.background:f.inputField.disabledBackground,color:p?f.inputField.text:f.inputField.disabledText,opacity:y.loading?.3:p?.8:.5},placeholder:"0"}),t.jsx("div",{className:"flex flex-col gap-2",children:t.jsxs("div",{className:c("ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]",!p&&"opacity-50"),style:{backgroundColor:f.tokenButton.background,border:`1px solid ${f.tokenButton.border}`,padding:`${f.tokenButton.paddingY}px ${f.tokenButton.paddingX}px`},children:[e.tokenOut.logoURI&&t.jsx("img",{src:e.tokenOut.logoURI,alt:e.tokenOut.symbol,className:"h-[20px] w-[20px] flex-shrink-0 rounded-full",onError:e=>{e.target.style.display="none"}}),t.jsx("span",{style:{color:f.tokenButton.text},className:"font-bold text-sm",children:e.tokenOut.symbol})]})})]})]}),y.error&&t.jsx("div",{className:"mb-2 p-4 bg-red-50 text-red-500 rounded-2xl overflow-x-hidden",children:y.error}),p?t.jsx("button",{disabled:y.loading||g||!y.inputAmount||Number(y.inputAmount)<=0,onClick:async()=>{if(x){b(!0);try{await h()}finally{b(!1),k(e=>({...e,inputAmount:"",outputAmount:""}))}}else k(e=>({...e,error:"Please connect your wallet"}))},className:"w-full py-4 rounded-2xl transition-colors cursor-pointer",style:{backgroundColor:y.loading||g||!y.inputAmount||Number(y.inputAmount)<=0?f.swapButton.disabledBackground:f.swapButton.background,color:y.loading||g||!y.inputAmount||Number(y.inputAmount)<=0?f.swapButton.disabledText:f.swapButton.text},children:g?"Swapping...":y.loading?"Getting Quote...":"Swap"}):t.jsx("button",{onClick:async()=>{s({view:"Connect"})},className:"w-full py-4 rounded-2xl transition-colors",style:{backgroundColor:f.connectButton.background,color:f.connectButton.text},children:"Connect Wallet"}),y.inputAmount&&y.outputAmount&&t.jsxs("div",{className:"p-4 rounded-2xl",children:[t.jsxs("div",{className:"flex justify-between items-center text-sm mb-2",style:{color:f.textSecondary},children:["1 ",e.tokenIn.symbol," ="," ",(Number(y.outputAmount)/Number(y.inputAmount)).toFixed(6)," ",e.tokenOut.symbol]}),y.routeInfo&&t.jsx("div",{className:"mt-2 text-xs",style:{color:f.textSecondary},children:y.routeInfo.isDirectRoute?t.jsxs("div",{className:"flex justify-between",children:[t.jsx("span",{children:"Direct swap"}),t.jsx("span",{children:y.routeInfo.routeString})]}):t.jsx("div",{className:"flex justify-between",children:t.jsxs("span",{children:["Route: ",y.routeInfo.routeString]})})})]}),p&&t.jsx("div",{className:"flex justify-center items-center mt-2",children:t.jsx("appkit-account-button",{})})]})},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
2
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/components/SwapWidget.tsx","../src/components/Provider.tsx","../src/hooks/useQuote.ts","../src/hooks/useSwap.ts"],"sourcesContent":["import React, { useState, useMemo, useEffect } from \"react\";\nimport { useAccount, useWalletClient } from \"wagmi\";\nimport { ethers } from \"ethers\";\nimport {\n DEFAULT_POOL_CONFIG,\n lightTheme,\n type SwapState,\n type SwapProps,\n type ThemeConfig,\n} from \"@uniswap-widget/core\";\nimport useQuote from \"../hooks/useQuote\";\nimport useSwap from \"../hooks/useSwap\";\nimport { useAppKit } from \"@reown/appkit/react\";\n\nconst cx = (...classes: (string | false | null | undefined)[]) =>\n classes.filter(Boolean).join(\" \");\n\nconst ArrowDown = (props: React.SVGProps<SVGSVGElement>) => (\n <svg {...props} viewBox=\"0 0 512 512\" className=\"text-2xl w-6 h-6\" fill=\"currentColor\">\n <path d=\"M256 400L56 200h400L256 400z\"/>\n </svg>\n)\n\nconst SwapWidget: React.FC<SwapProps> = ({\n poolConfig = DEFAULT_POOL_CONFIG,\n theme: customTheme = {},\n onSwap,\n}) => {\n const { open } = useAppKit();\n const { isConnected } = useAccount();\n const { data: walletClient } = useWalletClient();\n const [isSwapping, setIsSwapping] = useState(false);\n\n const signer = useMemo(() => {\n if (!walletClient) return undefined;\n const { account, chain, transport } = walletClient;\n const network = {\n chainId: chain.id,\n name: chain.name,\n ensAddress: chain.contracts?.ensRegistry?.address,\n };\n const provider = new ethers.providers.Web3Provider(transport, network);\n return provider.getSigner(account.address);\n }, [walletClient]);\n\n // Merge custom theme with default light theme\n const theme = useMemo<ThemeConfig>(\n () => ({\n ...lightTheme,\n ...customTheme,\n tokenButton: {\n ...lightTheme.tokenButton,\n ...customTheme.tokenButton,\n },\n swapButton: {\n ...lightTheme.swapButton,\n ...customTheme.swapButton,\n },\n connectButton: {\n ...lightTheme.connectButton,\n ...customTheme.connectButton,\n },\n inputField: {\n ...lightTheme.inputField,\n ...customTheme.inputField,\n },\n buySection: {\n ...lightTheme.buySection,\n ...customTheme.buySection,\n },\n }),\n [customTheme]\n );\n\n const [state, setState] = useState<SwapState>({\n inputAmount: \"\",\n outputAmount: \"\",\n inputToken: null,\n outputToken: null,\n loading: false,\n error: null,\n inputDisabled: true,\n });\n\n useEffect(() => {\n setState((prev) => ({\n ...prev,\n inputDisabled: !isConnected,\n error: !isConnected ? \"Please connect your wallet\" : null,\n }));\n }, [isConnected]);\n\n // Always call hooks, but pass undefined if no signer\n useQuote({ state, setState, poolConfig, signer: signer || undefined });\n const { swap } = useSwap({ state, setState, onSwap, signer: signer || undefined });\n\n const handleSwap = async () => {\n if (!signer) {\n setState(prev => ({ ...prev, error: \"Please connect your wallet\" }));\n return;\n }\n setIsSwapping(true);\n try {\n await swap();\n } finally {\n setIsSwapping(false);\n setState((prev) => ({ ...prev, inputAmount: \"\", outputAmount: \"\" }));\n }\n };\n\n const handleInputAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n if (value === \"\" || /^\\d*\\.?\\d*$/.test(value)) {\n setState((prev) => ({ ...prev, inputAmount: value }));\n }\n };\n\n const onConnectWallet = async () => {\n open({\n view: \"Connect\",\n });\n };\n\n return (\n <div\n className=\"relative w-full max-w-md rounded-xl p-2\"\n style={{ backgroundColor: theme.background }}\n >\n {/* Sell Section */}\n <div\n className=\"p-4 rounded-2xl relative\"\n style={{\n backgroundColor: theme.foreground,\n border: `1px solid ${theme.border}`,\n opacity: !isConnected ? 0.5 : 1,\n }}\n >\n <label className=\"block mb-2\" style={{ color: theme.textSecondary }}>\n Sell\n </label>\n <div className=\"flex items-center\">\n <input\n type=\"text\"\n disabled={!isConnected}\n value={state.inputAmount}\n onChange={handleInputAmountChange}\n className={cx(\n \"w-full text-2xl outline-none\",\n !isConnected && \"cursor-not-allowed\"\n )}\n placeholder=\"0\"\n inputMode=\"decimal\"\n style={{\n backgroundColor: !isConnected\n ? theme.inputField.disabledBackground\n : theme.inputField.background,\n color: !isConnected\n ? theme.inputField.disabledText\n : theme.inputField.text,\n }}\n />\n <div className=\"flex flex-col gap-2\">\n <div\n className={cx(\n \"ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]\",\n !isConnected && \"opacity-50\"\n )}\n style={{\n backgroundColor: theme.tokenButton.background,\n border: `1px solid ${theme.tokenButton.border}`,\n }}\n >\n {poolConfig.tokenIn.logoURI && (\n <img\n src={poolConfig.tokenIn.logoURI}\n alt={poolConfig.tokenIn.symbol}\n className=\"h-[20px] w-[20px] flex-shrink-0 rounded-full\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n )}\n <span\n style={{ color: theme.tokenButton.text }}\n className=\"font-bold text-sm\"\n >\n {poolConfig.tokenIn.symbol}\n </span>\n </div>\n </div>\n </div>\n </div>\n\n {/* Swap Arrow */}\n <div className=\"relative z-10 flex justify-center items-center h-[5px]\">\n <div\n className=\"rounded-2xl w-[40px] h-[40px] flex justify-center items-center\"\n style={{ \n backgroundColor: theme.border,\n opacity: !isConnected ? 0.5 : 1\n }}\n >\n <ArrowDown className=\"text-2xl\" style={{ color: theme.text }} />\n </div>\n </div>\n\n {/* Buy Section */}\n <div\n className=\"mb-2 p-4 rounded-2xl relative\"\n style={{\n backgroundColor: theme.buySection.background,\n border: `1px solid ${theme.buySection.border}`,\n opacity: !isConnected ? 0.5 : 1,\n }}\n >\n <label className=\"block mb-2\" style={{ color: theme.textSecondary }}>\n Buy\n </label>\n <div className=\"flex items-center\">\n <input\n type=\"text\"\n value={\n state.loading ? \"Fetching Quotes\" : state.outputAmount || \"0\"\n }\n readOnly\n disabled={true}\n className={cx(\n \"w-full text-2xl outline-none disabled:text-lg\",\n !isConnected && \"cursor-not-allowed\"\n )}\n style={{\n backgroundColor: !isConnected\n ? theme.inputField.disabledBackground\n : theme.inputField.background,\n color: !isConnected\n ? theme.inputField.disabledText\n : theme.inputField.text,\n opacity: state.loading ? 0.3 : !isConnected ? 0.5 : 0.8,\n }}\n placeholder=\"0\"\n />\n <div className=\"flex flex-col gap-2\">\n <div\n className={cx(\n \"ml-2 p-3 py-2 rounded-full flex items-center justify-center gap-2 min-w-[140px]\",\n !isConnected && \"opacity-50\"\n )}\n style={{\n backgroundColor: theme.tokenButton.background,\n border: `1px solid ${theme.tokenButton.border}`,\n padding: `${theme.tokenButton.paddingY}px ${theme.tokenButton.paddingX}px`,\n }}\n >\n {poolConfig.tokenOut.logoURI && (\n <img\n src={poolConfig.tokenOut.logoURI}\n alt={poolConfig.tokenOut.symbol}\n className=\"h-[20px] w-[20px] flex-shrink-0 rounded-full\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n )}\n <span\n style={{ color: theme.tokenButton.text }}\n className=\"font-bold text-sm\"\n >\n {poolConfig.tokenOut.symbol}\n </span>\n </div>\n </div>\n </div>\n </div>\n\n {/* Error Message */}\n {state.error && (\n <div className=\"mb-2 p-4 bg-red-50 text-red-500 rounded-2xl overflow-x-hidden\">\n {state.error}\n </div>\n )}\n\n {/* Action Button */}\n {isConnected ? (\n <button\n disabled={\n state.loading ||\n isSwapping ||\n !state.inputAmount ||\n Number(state.inputAmount) <= 0\n }\n onClick={handleSwap}\n className=\"w-full py-4 rounded-2xl transition-colors cursor-pointer\"\n style={{\n backgroundColor:\n state.loading ||\n isSwapping ||\n !state.inputAmount ||\n Number(state.inputAmount) <= 0\n ? theme.swapButton.disabledBackground\n : theme.swapButton.background,\n color:\n state.loading ||\n isSwapping ||\n !state.inputAmount ||\n Number(state.inputAmount) <= 0\n ? theme.swapButton.disabledText\n : theme.swapButton.text,\n }}\n >\n {isSwapping ? \"Swapping...\" : state.loading ? \"Getting Quote...\" : \"Swap\"}\n </button>\n ) : (\n <button\n onClick={onConnectWallet}\n className=\"w-full py-4 rounded-2xl transition-colors\"\n style={{\n backgroundColor: theme.connectButton.background,\n color: theme.connectButton.text,\n }}\n >\n Connect Wallet\n </button>\n )}\n\n {/* Price Info */}\n {state.inputAmount && state.outputAmount && (\n <div className=\"p-4 rounded-2xl\">\n <div\n className=\"flex justify-between items-center text-sm mb-2\"\n style={{ color: theme.textSecondary }}\n >\n 1 {poolConfig.tokenIn.symbol} ={\" \"}\n {(Number(state.outputAmount) / Number(state.inputAmount)).toFixed(\n 6\n )}{\" \"}\n {poolConfig.tokenOut.symbol}\n </div>\n\n {state.routeInfo && (\n <div\n className=\"mt-2 text-xs\"\n style={{ color: theme.textSecondary }}\n >\n {state.routeInfo.isDirectRoute ? (\n <div className=\"flex justify-between\">\n <span>Direct swap</span>\n <span>{state.routeInfo.routeString}</span>\n </div>\n ) : (\n <div className=\"flex justify-between\">\n <span>Route: {state.routeInfo.routeString}</span>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {/* Account Button */}\n {isConnected && (\n <div className=\"flex justify-center items-center mt-2\">\n <appkit-account-button />\n </div>\n )}\n </div>\n );\n};\n\nexport default SwapWidget;\n","\"use client\";\n\nimport { WagmiAdapter } from \"@reown/appkit-adapter-wagmi\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { WagmiProvider } from \"wagmi\";\n\nexport interface ProviderProps {\n children: React.ReactNode;\n wagmiAdapter: WagmiAdapter;\n queryClient?: QueryClient;\n}\n\nexport function Provider({\n children,\n wagmiAdapter,\n queryClient = new QueryClient(),\n}: ProviderProps) {\n return (\n <WagmiProvider config={wagmiAdapter.wagmiConfig}>\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n </WagmiProvider>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport { ethers } from \"ethers\";\nimport {\n getQuote,\n RATE_LIMIT_CONFIG,\n type SwapState,\n type PoolConfig,\n} from \"@uniswap-widget/core\";\n\n/**\n * React binding for the core `getQuote`. Owns the reactive concerns debounce,\n * de-duplication, abort, and state writes while the actual quote logic lives\n * in `@uniswap-widget/core`.\n */\nexport default function useQuote({\n signer,\n state,\n setState,\n poolConfig,\n}: {\n signer?: ethers.Signer;\n state: SwapState;\n setState: React.Dispatch<React.SetStateAction<SwapState>>;\n poolConfig: PoolConfig;\n}) {\n const debounceTimeout = useRef<NodeJS.Timeout>();\n const lastQuoteParams = useRef<string>(\"\");\n const abortController = useRef<AbortController>();\n\n useEffect(() => {\n // Initialize tokens from pool config\n setState((prev) => ({\n ...prev,\n inputToken: poolConfig.tokenIn,\n outputToken: poolConfig.tokenOut,\n }));\n }, [poolConfig]);\n\n useEffect(() => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n\n if (abortController.current) {\n abortController.current.abort();\n }\n\n async function updateQuote() {\n if (!state.inputAmount || Number(state.inputAmount) === 0) {\n setState((prev) => ({ ...prev, outputAmount: \"\" }));\n return;\n }\n\n if (!signer) {\n setState((prev) => ({\n ...prev,\n outputAmount: \"\",\n error: \"Please connect your wallet to get quotes\",\n }));\n return;\n }\n\n const quoteKey = `${poolConfig.tokenIn.address}-${poolConfig.tokenOut.address}-${state.inputAmount}`;\n if (lastQuoteParams.current === quoteKey) {\n return;\n }\n lastQuoteParams.current = quoteKey;\n\n const controller = new AbortController();\n abortController.current = controller;\n\n try {\n setState((prev) => ({ ...prev, loading: true, error: null }));\n\n const { outputAmount, routeInfo } = await getQuote({\n signer,\n inputToken: poolConfig.tokenIn,\n outputToken: poolConfig.tokenOut,\n inputAmount: state.inputAmount,\n poolConfig,\n signal: controller.signal,\n });\n\n if (controller.signal.aborted) {\n return;\n }\n\n setState((prev) => ({ ...prev, outputAmount, routeInfo }));\n } catch (err) {\n if (controller.signal.aborted) {\n return;\n }\n\n const errorMessage =\n err instanceof Error ? err.message : \"Failed to get quote\";\n\n setState((prev) => ({\n ...prev,\n outputAmount: \"\",\n error: errorMessage,\n }));\n } finally {\n if (!controller.signal.aborted) {\n setState((prev) => ({ ...prev, loading: false }));\n }\n }\n }\n\n debounceTimeout.current = setTimeout(\n updateQuote,\n RATE_LIMIT_CONFIG.QUOTE_DEBOUNCE\n );\n\n return () => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n if (abortController.current) {\n abortController.current.abort();\n }\n };\n }, [state.inputAmount, poolConfig, signer]);\n\n return;\n}\n","import { ethers } from \"ethers\";\nimport { executeSwap, type SwapState } from \"@uniswap-widget/core\";\n\n/**\n * React binding for the core `executeSwap`. Manages loading/error state; the\n * swap itself (approve, send, wait, callback) lives in `@uniswap-widget/core`.\n */\nexport default function useSwap({\n state,\n setState,\n onSwap,\n signer,\n}: {\n state: SwapState;\n setState: React.Dispatch<React.SetStateAction<SwapState>>;\n onSwap?: (inputAmount: string, outputAmount: string) => Promise<void>;\n signer?: ethers.Signer;\n}) {\n async function swap() {\n if (!signer) {\n setState((prev) => ({ ...prev, error: \"Please connect your wallet\" }));\n return;\n }\n\n if (!state.inputToken || !state.outputToken) {\n setState((prev) => ({ ...prev, error: \"Tokens not initialized\" }));\n return;\n }\n\n setState((prev) => ({ ...prev, txLoading: true }));\n\n try {\n await executeSwap({\n signer,\n inputToken: state.inputToken,\n outputToken: state.outputToken,\n inputAmount: state.inputAmount,\n outputAmount: state.outputAmount,\n onSwap,\n });\n } catch (error) {\n setState((prev) => ({\n ...prev,\n error: error instanceof Error ? error.message : \"Swap failed\",\n }));\n } finally {\n setState((prev) => ({ ...prev, txLoading: false }));\n }\n }\n\n return {\n swap,\n };\n}\n"],"names":["cx","classes","filter","Boolean","join","ArrowDown","props","jsx","viewBox","className","fill","children","d","wagmiAdapter","queryClient","QueryClient","WagmiProvider","config","wagmiConfig","QueryClientProvider","client","poolConfig","DEFAULT_POOL_CONFIG","theme","customTheme","onSwap","open","useAppKit","isConnected","useAccount","data","walletClient","useWalletClient","isSwapping","setIsSwapping","useState","signer","useMemo","account","chain","transport","network","chainId","id","name","ensAddress","_b","_a","contracts","ensRegistry","address","ethers","providers","Web3Provider","getSigner","lightTheme","tokenButton","swapButton","connectButton","inputField","buySection","state","setState","inputAmount","outputAmount","inputToken","outputToken","loading","error","inputDisabled","useEffect","prev","debounceTimeout","useRef","lastQuoteParams","abortController","tokenIn","tokenOut","current","clearTimeout","abort","setTimeout","async","Number","quoteKey","controller","AbortController","routeInfo","getQuote","signal","aborted","err","errorMessage","Error","message","RATE_LIMIT_CONFIG","QUOTE_DEBOUNCE","useQuote","swap","txLoading","executeSwap","useSwap","jsxs","style","backgroundColor","background","foreground","border","opacity","color","textSecondary","type","disabled","value","onChange","e","target","test","placeholder","inputMode","disabledBackground","text","disabledText","logoURI","src","alt","symbol","onError","display","readOnly","padding","paddingY","paddingX","onClick","view","toFixed","isDirectRoute","routeString"],"mappings":"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"}
package/package.json CHANGED
@@ -1,14 +1,91 @@
1
1
  {
2
2
  "name": "@uniswap-widget/react",
3
- "version": "0.0.0",
4
- "description": "Placeholder for @uniswap-widget/react",
5
- "main": "index.js",
6
- "scripts": {},
7
- "keywords": [],
8
- "author": "houtan-rocky (https://www.npmjs.com/~houtan-rocky)",
9
- "license": "UNLICENSED",
10
- "private": false,
3
+ "version": "2.1.1",
4
+ "type": "module",
5
+ "description": "A clean Uniswap swap widget package for easy integration",
6
+ "license": "MIT",
7
+ "main": "./src/index.ts",
8
+ "module": "./src/index.ts",
9
+ "types": "./src/index.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./src/index.ts",
13
+ "import": "./src/index.ts"
14
+ }
15
+ },
11
16
  "publishConfig": {
12
- "access": "public"
17
+ "main": "./dist/index.umd.js",
18
+ "module": "./dist/index.es.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.es.js",
24
+ "require": "./dist/index.umd.js"
25
+ }
26
+ }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "scripts": {
34
+ "build": "tsc --noEmit && vite build",
35
+ "build:watch": "vite build --watch",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest",
39
+ "test:coverage": "vitest run --coverage",
40
+ "prepublishOnly": "pnpm run build"
41
+ },
42
+ "keywords": [
43
+ "uniswap",
44
+ "swap",
45
+ "widget",
46
+ "defi",
47
+ "react",
48
+ "ethereum"
49
+ ],
50
+ "dependencies": {
51
+ "@uniswap-widget/core": "workspace:*"
52
+ },
53
+ "peerDependencies": {
54
+ "@reown/appkit": ">=1.4.0",
55
+ "@reown/appkit-adapter-wagmi": ">=1.4.0",
56
+ "@tanstack/react-query": ">=5.0.0",
57
+ "@uniswap/sdk-core": ">=5.0.0",
58
+ "@uniswap/v3-sdk": ">=3.0.0",
59
+ "@uniswap/v3-core": ">=1.0.0",
60
+ "ethers": ">=5.7.0 <7.0.0",
61
+ "react": ">=18.0.0",
62
+ "react-dom": ">=18.0.0",
63
+ "wagmi": ">=2.0.0"
64
+ },
65
+ "devDependencies": {
66
+ "@reown/appkit": "catalog:web3",
67
+ "@reown/appkit-adapter-wagmi": "catalog:web3",
68
+ "@tanstack/react-query": "catalog:web3",
69
+ "@testing-library/dom": "catalog:",
70
+ "@testing-library/jest-dom": "catalog:",
71
+ "@testing-library/react": "catalog:",
72
+ "@types/react": "catalog:react18",
73
+ "@types/react-dom": "catalog:react18",
74
+ "@uniswap/sdk-core": "catalog:uniswap",
75
+ "@uniswap/v3-core": "catalog:uniswap",
76
+ "@uniswap/v3-sdk": "catalog:uniswap",
77
+ "@vitejs/plugin-react": "catalog:",
78
+ "@vitest/coverage-v8": "catalog:",
79
+ "ethers": "catalog:web3",
80
+ "jsdom": "catalog:",
81
+ "react": "catalog:react18",
82
+ "react-dom": "catalog:react18",
83
+ "terser": "catalog:",
84
+ "typescript": "catalog:",
85
+ "viem": "catalog:web3",
86
+ "vite": "catalog:",
87
+ "vite-plugin-dts": "catalog:",
88
+ "vitest": "catalog:",
89
+ "wagmi": "catalog:web3"
13
90
  }
14
- }
91
+ }
package/index.js DELETED
@@ -1 +0,0 @@
1
- // Placeholder