@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 +21 -0
- package/README.md +209 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.es.js +480 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +87 -10
- package/index.js +0 -1
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
|
package/dist/index.d.ts
ADDED
|
@@ -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 { }
|
package/dist/index.es.js
ADDED
|
@@ -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":";;;;;;;;;;;AAcA,SAAwB,SAAS;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,kBAAkB,OAAA;AACxB,QAAM,kBAAkB,OAAe,EAAE;AACzC,QAAM,kBAAkB,OAAA;AAExB,YAAU,MAAM;AAEd,aAAS,CAAC,UAAU;AAAA,MAClB,GAAG;AAAA,MACH,YAAY,WAAW;AAAA,MACvB,aAAa,WAAW;AAAA,IAAA,EACxB;AAAA,EACJ,GAAG,CAAC,UAAU,CAAC;AAEf,YAAU,MAAM;AACd,QAAI,gBAAgB,SAAS;AAC3B,mBAAa,gBAAgB,OAAO;AAAA,IACtC;AAEA,QAAI,gBAAgB,SAAS;AAC3B,sBAAgB,QAAQ,MAAA;AAAA,IAC1B;AAEA,mBAAe,cAAc;AAC3B,UAAI,CAAC,MAAM,eAAe,OAAO,MAAM,WAAW,MAAM,GAAG;AACzD,iBAAS,CAAC,UAAU,EAAE,GAAG,MAAM,cAAc,KAAK;AAClD;AAAA,MACF;AAEA,UAAI,CAAC,QAAQ;AACX,iBAAS,CAAC,UAAU;AAAA,UAClB,GAAG;AAAA,UACH,cAAc;AAAA,UACd,OAAO;AAAA,QAAA,EACP;AACF;AAAA,MACF;AAEA,YAAM,WAAW,GAAG,WAAW,QAAQ,OAAO,IAAI,WAAW,SAAS,OAAO,IAAI,MAAM,WAAW;AAClG,UAAI,gBAAgB,YAAY,UAAU;AACxC;AAAA,MACF;AACA,sBAAgB,UAAU;AAE1B,YAAM,aAAa,IAAI,gBAAA;AACvB,sBAAgB,UAAU;AAE1B,UAAI;AACF,iBAAS,CAAC,UAAU,EAAE,GAAG,MAAM,SAAS,MAAM,OAAO,KAAA,EAAO;AAE5D,cAAM,EAAE,cAAc,UAAA,IAAc,MAAM,SAAS;AAAA,UACjD;AAAA,UACA,YAAY,WAAW;AAAA,UACvB,aAAa,WAAW;AAAA,UACxB,aAAa,MAAM;AAAA,UACnB;AAAA,UACA,QAAQ,WAAW;AAAA,QAAA,CACpB;AAED,YAAI,WAAW,OAAO,SAAS;AAC7B;AAAA,QACF;AAEA,iBAAS,CAAC,UAAU,EAAE,GAAG,MAAM,cAAc,YAAY;AAAA,MAC3D,SAAS,KAAK;AACZ,YAAI,WAAW,OAAO,SAAS;AAC7B;AAAA,QACF;AAEA,cAAM,eACJ,eAAe,QAAQ,IAAI,UAAU;AAEvC,iBAAS,CAAC,UAAU;AAAA,UAClB,GAAG;AAAA,UACH,cAAc;AAAA,UACd,OAAO;AAAA,QAAA,EACP;AAAA,MACJ,UAAA;AACE,YAAI,CAAC,WAAW,OAAO,SAAS;AAC9B,mBAAS,CAAC,UAAU,EAAE,GAAG,MAAM,SAAS,QAAQ;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAEA,oBAAgB,UAAU;AAAA,MACxB;AAAA,MACA,kBAAkB;AAAA,IAAA;AAGpB,WAAO,MAAM;AACX,UAAI,gBAAgB,SAAS;AAC3B,qBAAa,gBAAgB,OAAO;AAAA,MACtC;AACA,UAAI,gBAAgB,SAAS;AAC3B,wBAAgB,QAAQ,MAAA;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,aAAa,YAAY,MAAM,CAAC;AAE1C;AACF;ACrHA,SAAwB,QAAQ;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,iBAAe,OAAO;AACpB,QAAI,CAAC,QAAQ;AACX,eAAS,CAAC,UAAU,EAAE,GAAG,MAAM,OAAO,+BAA+B;AACrE;AAAA,IACF;AAEA,QAAI,CAAC,MAAM,cAAc,CAAC,MAAM,aAAa;AAC3C,eAAS,CAAC,UAAU,EAAE,GAAG,MAAM,OAAO,2BAA2B;AACjE;AAAA,IACF;AAEA,aAAS,CAAC,UAAU,EAAE,GAAG,MAAM,WAAW,OAAO;AAEjD,QAAI;AACF,YAAM,YAAY;AAAA,QAChB;AAAA,QACA,YAAY,MAAM;AAAA,QAClB,aAAa,MAAM;AAAA,QACnB,aAAa,MAAM;AAAA,QACnB,cAAc,MAAM;AAAA,QACpB;AAAA,MAAA,CACD;AAAA,IACH,SAAS,OAAO;AACd,eAAS,CAAC,UAAU;AAAA,QAClB,GAAG;AAAA,QACH,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAAA,EAChD;AAAA,IACJ,UAAA;AACE,eAAS,CAAC,UAAU,EAAE,GAAG,MAAM,WAAW,QAAQ;AAAA,IACpD;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,EAAA;AAEJ;ACvCA,MAAM,KAAK,IAAI,YACb,QAAQ,OAAO,OAAO,EAAE,KAAK,GAAG;AAElC,MAAM,YAAY,CAAC,UACjB,oBAAC,OAAA,EAAK,GAAG,OAAO,SAAQ,eAAc,WAAU,oBAAmB,MAAK,gBACtE,8BAAC,QAAA,EAAK,GAAE,gCAA8B,GACxC;AAGF,MAAM,aAAkC,CAAC;AAAA,EACvC,aAAa;AAAA,EACb,OAAO,cAAc,CAAA;AAAA,EACrB;AACF,MAAM;AACJ,QAAM,EAAE,KAAA,IAAS,UAAA;AACjB,QAAM,EAAE,YAAA,IAAgB,WAAA;AACxB,QAAM,EAAE,MAAM,aAAA,IAAiB,gBAAA;AAC/B,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,QAAM,SAAS,QAAQ,MAAM;;AAC3B,QAAI,CAAC,aAAc,QAAO;AAC1B,UAAM,EAAE,SAAS,OAAO,UAAA,IAAc;AACtC,UAAM,UAAU;AAAA,MACd,SAAS,MAAM;AAAA,MACf,MAAM,MAAM;AAAA,MACZ,aAAY,iBAAM,cAAN,mBAAiB,gBAAjB,mBAA8B;AAAA,IAAA;AAE5C,UAAM,WAAW,IAAI,OAAO,UAAU,aAAa,WAAW,OAAO;AACrE,WAAO,SAAS,UAAU,QAAQ,OAAO;AAAA,EAC3C,GAAG,CAAC,YAAY,CAAC;AAGjB,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAa;AAAA,QACX,GAAG,WAAW;AAAA,QACd,GAAG,YAAY;AAAA,MAAA;AAAA,MAEjB,YAAY;AAAA,QACV,GAAG,WAAW;AAAA,QACd,GAAG,YAAY;AAAA,MAAA;AAAA,MAEjB,eAAe;AAAA,QACb,GAAG,WAAW;AAAA,QACd,GAAG,YAAY;AAAA,MAAA;AAAA,MAEjB,YAAY;AAAA,QACV,GAAG,WAAW;AAAA,QACd,GAAG,YAAY;AAAA,MAAA;AAAA,MAEjB,YAAY;AAAA,QACV,GAAG,WAAW;AAAA,QACd,GAAG,YAAY;AAAA,MAAA;AAAA,IACjB;AAAA,IAEF,CAAC,WAAW;AAAA,EAAA;AAGd,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB;AAAA,IAC5C,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,SAAS;AAAA,IACT,OAAO;AAAA,IACP,eAAe;AAAA,EAAA,CAChB;AAED,YAAU,MAAM;AACd,aAAS,CAAC,UAAU;AAAA,MAClB,GAAG;AAAA,MACH,eAAe,CAAC;AAAA,MAChB,OAAO,CAAC,cAAc,+BAA+B;AAAA,IAAA,EACrD;AAAA,EACJ,GAAG,CAAC,WAAW,CAAC;AAGhB,WAAS,EAAE,OAAO,UAAU,YAAY,QAAQ,UAAU,QAAW;AACrE,QAAM,EAAE,KAAA,IAAS,QAAQ,EAAE,OAAO,UAAU,QAAQ,QAAQ,UAAU,QAAW;AAEjF,QAAM,aAAa,YAAY;AAC7B,QAAI,CAAC,QAAQ;AACX,eAAS,WAAS,EAAE,GAAG,MAAM,OAAO,+BAA+B;AACnE;AAAA,IACF;AACA,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,KAAA;AAAA,IACR,UAAA;AACE,oBAAc,KAAK;AACnB,eAAS,CAAC,UAAU,EAAE,GAAG,MAAM,aAAa,IAAI,cAAc,GAAA,EAAK;AAAA,IACrE;AAAA,EACF;AAEA,QAAM,0BAA0B,CAAC,MAA2C;AAC1E,UAAM,QAAQ,EAAE,OAAO;AACvB,QAAI,UAAU,MAAM,cAAc,KAAK,KAAK,GAAG;AAC7C,eAAS,CAAC,UAAU,EAAE,GAAG,MAAM,aAAa,QAAQ;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,kBAAkB,YAAY;AAClC,SAAK;AAAA,MACH,MAAM;AAAA,IAAA,CACP;AAAA,EACH;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,iBAAiB,MAAM,WAAA;AAAA,MAGhC,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,iBAAiB,MAAM;AAAA,cACvB,QAAQ,aAAa,MAAM,MAAM;AAAA,cACjC,SAAS,CAAC,cAAc,MAAM;AAAA,YAAA;AAAA,YAGhC,UAAA;AAAA,cAAA,oBAAC,SAAA,EAAM,WAAU,cAAa,OAAO,EAAE,OAAO,MAAM,cAAA,GAAiB,UAAA,OAAA,CAErE;AAAA,cACA,qBAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,UAAU,CAAC;AAAA,oBACX,OAAO,MAAM;AAAA,oBACb,UAAU;AAAA,oBACV,WAAW;AAAA,sBACT;AAAA,sBACA,CAAC,eAAe;AAAA,oBAAA;AAAA,oBAElB,aAAY;AAAA,oBACZ,WAAU;AAAA,oBACV,OAAO;AAAA,sBACL,iBAAiB,CAAC,cACd,MAAM,WAAW,qBACjB,MAAM,WAAW;AAAA,sBACrB,OAAO,CAAC,cACJ,MAAM,WAAW,eACjB,MAAM,WAAW;AAAA,oBAAA;AAAA,kBACvB;AAAA,gBAAA;AAAA,gBAEF,oBAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW;AAAA,sBACT;AAAA,sBACA,CAAC,eAAe;AAAA,oBAAA;AAAA,oBAElB,OAAO;AAAA,sBACL,iBAAiB,MAAM,YAAY;AAAA,sBACnC,QAAQ,aAAa,MAAM,YAAY,MAAM;AAAA,oBAAA;AAAA,oBAG9C,UAAA;AAAA,sBAAA,WAAW,QAAQ,WAClB;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,KAAK,WAAW,QAAQ;AAAA,0BACxB,KAAK,WAAW,QAAQ;AAAA,0BACxB,WAAU;AAAA,0BACV,SAAS,CAAC,MAAM;AACb,8BAAE,OAA4B,MAAM,UAAU;AAAA,0BACjD;AAAA,wBAAA;AAAA,sBAAA;AAAA,sBAGJ;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,OAAO,EAAE,OAAO,MAAM,YAAY,KAAA;AAAA,0BAClC,WAAU;AAAA,0BAET,qBAAW,QAAQ;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACtB;AAAA,kBAAA;AAAA,gBAAA,EACF,CACF;AAAA,cAAA,EAAA,CACF;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAIF,oBAAC,OAAA,EAAI,WAAU,0DACb,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,iBAAiB,MAAM;AAAA,cACvB,SAAS,CAAC,cAAc,MAAM;AAAA,YAAA;AAAA,YAGhC,UAAA,oBAAC,aAAU,WAAU,YAAW,OAAO,EAAE,OAAO,MAAM,OAAK,CAAG;AAAA,UAAA;AAAA,QAAA,GAElE;AAAA,QAGA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,iBAAiB,MAAM,WAAW;AAAA,cAClC,QAAQ,aAAa,MAAM,WAAW,MAAM;AAAA,cAC5C,SAAS,CAAC,cAAc,MAAM;AAAA,YAAA;AAAA,YAGhC,UAAA;AAAA,cAAA,oBAAC,SAAA,EAAM,WAAU,cAAa,OAAO,EAAE,OAAO,MAAM,cAAA,GAAiB,UAAA,MAAA,CAErE;AAAA,cACA,qBAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,OACE,MAAM,UAAU,oBAAoB,MAAM,gBAAgB;AAAA,oBAE5D,UAAQ;AAAA,oBACR,UAAU;AAAA,oBACV,WAAW;AAAA,sBACT;AAAA,sBACA,CAAC,eAAe;AAAA,oBAAA;AAAA,oBAElB,OAAO;AAAA,sBACL,iBAAiB,CAAC,cACd,MAAM,WAAW,qBACjB,MAAM,WAAW;AAAA,sBACrB,OAAO,CAAC,cACJ,MAAM,WAAW,eACjB,MAAM,WAAW;AAAA,sBACrB,SAAS,MAAM,UAAU,MAAM,CAAC,cAAc,MAAM;AAAA,oBAAA;AAAA,oBAEtD,aAAY;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEd,oBAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW;AAAA,sBACT;AAAA,sBACA,CAAC,eAAe;AAAA,oBAAA;AAAA,oBAElB,OAAO;AAAA,sBACL,iBAAiB,MAAM,YAAY;AAAA,sBACnC,QAAQ,aAAa,MAAM,YAAY,MAAM;AAAA,sBAC7C,SAAS,GAAG,MAAM,YAAY,QAAQ,MAAM,MAAM,YAAY,QAAQ;AAAA,oBAAA;AAAA,oBAGvE,UAAA;AAAA,sBAAA,WAAW,SAAS,WACnB;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,KAAK,WAAW,SAAS;AAAA,0BACzB,KAAK,WAAW,SAAS;AAAA,0BACzB,WAAU;AAAA,0BACV,SAAS,CAAC,MAAM;AACb,8BAAE,OAA4B,MAAM,UAAU;AAAA,0BACjD;AAAA,wBAAA;AAAA,sBAAA;AAAA,sBAGJ;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,OAAO,EAAE,OAAO,MAAM,YAAY,KAAA;AAAA,0BAClC,WAAU;AAAA,0BAET,qBAAW,SAAS;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACvB;AAAA,kBAAA;AAAA,gBAAA,EACF,CACF;AAAA,cAAA,EAAA,CACF;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAID,MAAM,SACL,oBAAC,SAAI,WAAU,iEACZ,gBAAM,OACT;AAAA,QAID,cACC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,UACE,MAAM,WACN,cACA,CAAC,MAAM,eACP,OAAO,MAAM,WAAW,KAAK;AAAA,YAE/B,SAAS;AAAA,YACT,WAAU;AAAA,YACV,OAAO;AAAA,cACL,iBACE,MAAM,WACN,cACA,CAAC,MAAM,eACP,OAAO,MAAM,WAAW,KAAK,IACzB,MAAM,WAAW,qBACjB,MAAM,WAAW;AAAA,cACvB,OACE,MAAM,WACN,cACA,CAAC,MAAM,eACP,OAAO,MAAM,WAAW,KAAK,IACzB,MAAM,WAAW,eACjB,MAAM,WAAW;AAAA,YAAA;AAAA,YAGxB,UAAA,aAAa,gBAAgB,MAAM,UAAU,qBAAqB;AAAA,UAAA;AAAA,QAAA,IAGrE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS;AAAA,YACT,WAAU;AAAA,YACV,OAAO;AAAA,cACL,iBAAiB,MAAM,cAAc;AAAA,cACrC,OAAO,MAAM,cAAc;AAAA,YAAA;AAAA,YAE9B,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAMF,MAAM,eAAe,MAAM,gBAC1B,qBAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,EAAE,OAAO,MAAM,cAAA;AAAA,cACvB,UAAA;AAAA,gBAAA;AAAA,gBACI,WAAW,QAAQ;AAAA,gBAAO;AAAA,gBAAG;AAAA,iBAC9B,OAAO,MAAM,YAAY,IAAI,OAAO,MAAM,WAAW,GAAG;AAAA,kBACxD;AAAA,gBAAA;AAAA,gBACC;AAAA,gBACF,WAAW,SAAS;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGtB,MAAM,aACL;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,EAAE,OAAO,MAAM,cAAA;AAAA,cAErB,gBAAM,UAAU,gBACf,qBAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,gBAAA,oBAAC,UAAK,UAAA,cAAA,CAAW;AAAA,gBACjB,oBAAC,QAAA,EAAM,UAAA,MAAM,UAAU,YAAA,CAAY;AAAA,cAAA,EAAA,CACrC,IAEA,oBAAC,OAAA,EAAI,WAAU,wBACb,+BAAC,QAAA,EAAK,UAAA;AAAA,gBAAA;AAAA,gBAAQ,MAAM,UAAU;AAAA,cAAA,EAAA,CAAY,EAAA,CAC5C;AAAA,YAAA;AAAA,UAAA;AAAA,QAEJ,GAEJ;AAAA,QAID,eACC,oBAAC,OAAA,EAAI,WAAU,yCACb,UAAA,oBAAC,2BAAsB,EAAA,CACzB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;AClWO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA,cAAc,IAAI,YAAA;AACpB,GAAkB;AAChB,SACE,oBAAC,eAAA,EAAc,QAAQ,aAAa,aAClC,8BAAC,qBAAA,EAAoB,QAAQ,aAAc,SAAA,CAAS,EAAA,CACtD;AAEJ;"}
|
|
@@ -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": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
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
|
-
"
|
|
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
|