@hongming-wang/usdc-bridge-widget 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +272 -0
- package/dist/chunk-6JW37N76.mjs +211 -0
- package/dist/chunk-GJBJYQCU.mjs +218 -0
- package/dist/chunk-JHG7XCWW.mjs +218 -0
- package/dist/index.d.mts +765 -0
- package/dist/index.d.ts +765 -0
- package/dist/index.js +2356 -0
- package/dist/index.mjs +2295 -0
- package/dist/useBridge-LDEXWLEC.mjs +10 -0
- package/dist/useBridge-VGN5DMO6.mjs +10 -0
- package/dist/useBridge-WJA4XLLR.mjs +10 -0
- package/package.json +63 -0
- package/src/BridgeWidget.tsx +1133 -0
- package/src/__tests__/BridgeWidget.test.tsx +310 -0
- package/src/__tests__/chains.test.ts +131 -0
- package/src/__tests__/constants.test.ts +77 -0
- package/src/__tests__/hooks.test.ts +127 -0
- package/src/__tests__/icons.test.tsx +159 -0
- package/src/__tests__/setup.ts +8 -0
- package/src/__tests__/theme.test.ts +148 -0
- package/src/__tests__/useBridge.test.ts +133 -0
- package/src/__tests__/utils.test.ts +255 -0
- package/src/chains.ts +209 -0
- package/src/constants.ts +97 -0
- package/src/hooks.ts +349 -0
- package/src/icons.tsx +228 -0
- package/src/index.tsx +111 -0
- package/src/theme.ts +131 -0
- package/src/types.ts +160 -0
- package/src/useBridge.ts +424 -0
- package/src/utils.ts +239 -0
package/src/icons.tsx
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface IconProps {
|
|
4
|
+
/** Icon size in pixels */
|
|
5
|
+
size?: number;
|
|
6
|
+
/** Stroke/fill color */
|
|
7
|
+
color?: string;
|
|
8
|
+
/** Additional CSS class */
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Additional inline styles */
|
|
11
|
+
style?: React.CSSProperties;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Chevron down icon for dropdowns
|
|
16
|
+
*/
|
|
17
|
+
export function ChevronDownIcon({
|
|
18
|
+
size = 16,
|
|
19
|
+
color = "currentColor",
|
|
20
|
+
className,
|
|
21
|
+
style,
|
|
22
|
+
}: IconProps) {
|
|
23
|
+
return (
|
|
24
|
+
<svg
|
|
25
|
+
width={size}
|
|
26
|
+
height={size}
|
|
27
|
+
viewBox="0 0 24 24"
|
|
28
|
+
fill="none"
|
|
29
|
+
stroke={color}
|
|
30
|
+
className={className}
|
|
31
|
+
style={style}
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
>
|
|
34
|
+
<path
|
|
35
|
+
strokeLinecap="round"
|
|
36
|
+
strokeLinejoin="round"
|
|
37
|
+
strokeWidth={2}
|
|
38
|
+
d="M19 9l-7 7-7-7"
|
|
39
|
+
/>
|
|
40
|
+
</svg>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Swap/exchange icon for chain swap button
|
|
46
|
+
*/
|
|
47
|
+
export function SwapIcon({
|
|
48
|
+
size = 20,
|
|
49
|
+
color = "currentColor",
|
|
50
|
+
className,
|
|
51
|
+
style,
|
|
52
|
+
}: IconProps) {
|
|
53
|
+
return (
|
|
54
|
+
<svg
|
|
55
|
+
width={size}
|
|
56
|
+
height={size}
|
|
57
|
+
viewBox="0 0 24 24"
|
|
58
|
+
fill="none"
|
|
59
|
+
stroke={color}
|
|
60
|
+
className={className}
|
|
61
|
+
style={style}
|
|
62
|
+
aria-hidden="true"
|
|
63
|
+
>
|
|
64
|
+
<path
|
|
65
|
+
strokeLinecap="round"
|
|
66
|
+
strokeLinejoin="round"
|
|
67
|
+
strokeWidth={2}
|
|
68
|
+
d="M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"
|
|
69
|
+
/>
|
|
70
|
+
</svg>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Loading spinner icon
|
|
76
|
+
*/
|
|
77
|
+
export function SpinnerIcon({
|
|
78
|
+
size = 20,
|
|
79
|
+
color = "currentColor",
|
|
80
|
+
className,
|
|
81
|
+
style,
|
|
82
|
+
}: IconProps) {
|
|
83
|
+
return (
|
|
84
|
+
<svg
|
|
85
|
+
width={size}
|
|
86
|
+
height={size}
|
|
87
|
+
viewBox="0 0 24 24"
|
|
88
|
+
fill="none"
|
|
89
|
+
stroke={color}
|
|
90
|
+
className={className}
|
|
91
|
+
style={{
|
|
92
|
+
animation: "cc-spin 1s linear infinite",
|
|
93
|
+
...style,
|
|
94
|
+
}}
|
|
95
|
+
aria-hidden="true"
|
|
96
|
+
>
|
|
97
|
+
<style>{`@keyframes cc-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`}</style>
|
|
98
|
+
<circle
|
|
99
|
+
cx="12"
|
|
100
|
+
cy="12"
|
|
101
|
+
r="10"
|
|
102
|
+
strokeWidth={2}
|
|
103
|
+
strokeDasharray="32"
|
|
104
|
+
strokeLinecap="round"
|
|
105
|
+
/>
|
|
106
|
+
</svg>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Check/success icon
|
|
112
|
+
*/
|
|
113
|
+
export function CheckIcon({
|
|
114
|
+
size = 20,
|
|
115
|
+
color = "currentColor",
|
|
116
|
+
className,
|
|
117
|
+
style,
|
|
118
|
+
}: IconProps) {
|
|
119
|
+
return (
|
|
120
|
+
<svg
|
|
121
|
+
width={size}
|
|
122
|
+
height={size}
|
|
123
|
+
viewBox="0 0 24 24"
|
|
124
|
+
fill="none"
|
|
125
|
+
stroke={color}
|
|
126
|
+
className={className}
|
|
127
|
+
style={style}
|
|
128
|
+
aria-hidden="true"
|
|
129
|
+
>
|
|
130
|
+
<path
|
|
131
|
+
strokeLinecap="round"
|
|
132
|
+
strokeLinejoin="round"
|
|
133
|
+
strokeWidth={2}
|
|
134
|
+
d="M5 13l4 4L19 7"
|
|
135
|
+
/>
|
|
136
|
+
</svg>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Error/X icon
|
|
142
|
+
*/
|
|
143
|
+
export function ErrorIcon({
|
|
144
|
+
size = 20,
|
|
145
|
+
color = "currentColor",
|
|
146
|
+
className,
|
|
147
|
+
style,
|
|
148
|
+
}: IconProps) {
|
|
149
|
+
return (
|
|
150
|
+
<svg
|
|
151
|
+
width={size}
|
|
152
|
+
height={size}
|
|
153
|
+
viewBox="0 0 24 24"
|
|
154
|
+
fill="none"
|
|
155
|
+
stroke={color}
|
|
156
|
+
className={className}
|
|
157
|
+
style={style}
|
|
158
|
+
aria-hidden="true"
|
|
159
|
+
>
|
|
160
|
+
<path
|
|
161
|
+
strokeLinecap="round"
|
|
162
|
+
strokeLinejoin="round"
|
|
163
|
+
strokeWidth={2}
|
|
164
|
+
d="M6 18L18 6M6 6l12 12"
|
|
165
|
+
/>
|
|
166
|
+
</svg>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* External link icon
|
|
172
|
+
*/
|
|
173
|
+
export function ExternalLinkIcon({
|
|
174
|
+
size = 16,
|
|
175
|
+
color = "currentColor",
|
|
176
|
+
className,
|
|
177
|
+
style,
|
|
178
|
+
}: IconProps) {
|
|
179
|
+
return (
|
|
180
|
+
<svg
|
|
181
|
+
width={size}
|
|
182
|
+
height={size}
|
|
183
|
+
viewBox="0 0 24 24"
|
|
184
|
+
fill="none"
|
|
185
|
+
stroke={color}
|
|
186
|
+
className={className}
|
|
187
|
+
style={style}
|
|
188
|
+
aria-hidden="true"
|
|
189
|
+
>
|
|
190
|
+
<path
|
|
191
|
+
strokeLinecap="round"
|
|
192
|
+
strokeLinejoin="round"
|
|
193
|
+
strokeWidth={2}
|
|
194
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
195
|
+
/>
|
|
196
|
+
</svg>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Wallet icon
|
|
202
|
+
*/
|
|
203
|
+
export function WalletIcon({
|
|
204
|
+
size = 20,
|
|
205
|
+
color = "currentColor",
|
|
206
|
+
className,
|
|
207
|
+
style,
|
|
208
|
+
}: IconProps) {
|
|
209
|
+
return (
|
|
210
|
+
<svg
|
|
211
|
+
width={size}
|
|
212
|
+
height={size}
|
|
213
|
+
viewBox="0 0 24 24"
|
|
214
|
+
fill="none"
|
|
215
|
+
stroke={color}
|
|
216
|
+
className={className}
|
|
217
|
+
style={style}
|
|
218
|
+
aria-hidden="true"
|
|
219
|
+
>
|
|
220
|
+
<path
|
|
221
|
+
strokeLinecap="round"
|
|
222
|
+
strokeLinejoin="round"
|
|
223
|
+
strokeWidth={2}
|
|
224
|
+
d="M3 10h18M3 6h18a2 2 0 012 2v10a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2zm14 6h.01"
|
|
225
|
+
/>
|
|
226
|
+
</svg>
|
|
227
|
+
);
|
|
228
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Main widget export
|
|
2
|
+
export { BridgeWidget } from "./BridgeWidget";
|
|
3
|
+
|
|
4
|
+
// Types
|
|
5
|
+
export type {
|
|
6
|
+
BridgeWidgetProps,
|
|
7
|
+
BridgeWidgetTheme,
|
|
8
|
+
BridgeChainConfig,
|
|
9
|
+
BridgeEstimate,
|
|
10
|
+
BridgeResult,
|
|
11
|
+
} from "./types";
|
|
12
|
+
|
|
13
|
+
// Hooks (for advanced usage)
|
|
14
|
+
export {
|
|
15
|
+
useUSDCBalance,
|
|
16
|
+
useAllUSDCBalances,
|
|
17
|
+
useUSDCAllowance,
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated Use `useBridgeQuote` instead
|
|
20
|
+
*/
|
|
21
|
+
useBridgeEstimate,
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Use `formatNumber` from utils instead
|
|
24
|
+
*/
|
|
25
|
+
useFormatNumber,
|
|
26
|
+
} from "./hooks";
|
|
27
|
+
|
|
28
|
+
// Bridge hook
|
|
29
|
+
export { useBridge, useBridgeQuote, getChainName } from "./useBridge";
|
|
30
|
+
export type { BridgeParams, BridgeState, BridgeEvent, UseBridgeResult, BridgeQuote } from "./useBridge";
|
|
31
|
+
|
|
32
|
+
// Utilities
|
|
33
|
+
export {
|
|
34
|
+
formatNumber,
|
|
35
|
+
getErrorMessage,
|
|
36
|
+
parseUSDCAmount,
|
|
37
|
+
isValidPositiveAmount,
|
|
38
|
+
validateAmountInput,
|
|
39
|
+
validateChainConfig,
|
|
40
|
+
validateChainConfigs,
|
|
41
|
+
MAX_USDC_AMOUNT,
|
|
42
|
+
MIN_USDC_AMOUNT,
|
|
43
|
+
} from "./utils";
|
|
44
|
+
export type { ChainConfigValidationResult } from "./utils";
|
|
45
|
+
|
|
46
|
+
// Constants
|
|
47
|
+
export {
|
|
48
|
+
USDC_DECIMALS,
|
|
49
|
+
USDC_BRAND_COLOR,
|
|
50
|
+
USDC_ADDRESSES,
|
|
51
|
+
TOKEN_MESSENGER_V1_ADDRESSES,
|
|
52
|
+
TOKEN_MESSENGER_V2_ADDRESS,
|
|
53
|
+
TOKEN_MESSENGER_ADDRESSES,
|
|
54
|
+
CHAIN_ICONS,
|
|
55
|
+
DEFAULT_LOCALE,
|
|
56
|
+
} from "./constants";
|
|
57
|
+
|
|
58
|
+
// Chain configs and helpers
|
|
59
|
+
export {
|
|
60
|
+
createChainConfig,
|
|
61
|
+
DEFAULT_CHAIN_CONFIGS,
|
|
62
|
+
// Custom chains
|
|
63
|
+
unichain,
|
|
64
|
+
hyperEvm,
|
|
65
|
+
plume,
|
|
66
|
+
monad,
|
|
67
|
+
codex,
|
|
68
|
+
// Re-exported viem chains
|
|
69
|
+
mainnet,
|
|
70
|
+
arbitrum,
|
|
71
|
+
avalanche,
|
|
72
|
+
base,
|
|
73
|
+
optimism,
|
|
74
|
+
polygon,
|
|
75
|
+
linea,
|
|
76
|
+
sei,
|
|
77
|
+
worldchain,
|
|
78
|
+
ink,
|
|
79
|
+
sonic,
|
|
80
|
+
xdc,
|
|
81
|
+
// Testnet support
|
|
82
|
+
createTestnetChainConfig,
|
|
83
|
+
TESTNET_CHAIN_CONFIGS,
|
|
84
|
+
sepolia,
|
|
85
|
+
arbitrumSepolia,
|
|
86
|
+
avalancheFuji,
|
|
87
|
+
baseSepolia,
|
|
88
|
+
optimismSepolia,
|
|
89
|
+
polygonAmoy,
|
|
90
|
+
} from "./chains";
|
|
91
|
+
|
|
92
|
+
// Theme utilities
|
|
93
|
+
export {
|
|
94
|
+
defaultTheme,
|
|
95
|
+
mergeTheme,
|
|
96
|
+
themePresets,
|
|
97
|
+
THEME_COLORS,
|
|
98
|
+
THEME_SIZING,
|
|
99
|
+
THEME_FONTS,
|
|
100
|
+
} from "./theme";
|
|
101
|
+
|
|
102
|
+
// Icons (for custom implementations)
|
|
103
|
+
export {
|
|
104
|
+
ChevronDownIcon,
|
|
105
|
+
SwapIcon,
|
|
106
|
+
SpinnerIcon,
|
|
107
|
+
CheckIcon,
|
|
108
|
+
ErrorIcon,
|
|
109
|
+
ExternalLinkIcon,
|
|
110
|
+
WalletIcon,
|
|
111
|
+
} from "./icons";
|
package/src/theme.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { BridgeWidgetTheme } from "./types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default theme color palette
|
|
5
|
+
*/
|
|
6
|
+
export const THEME_COLORS = {
|
|
7
|
+
/** Primary accent - Indigo */
|
|
8
|
+
primary: "#6366f1",
|
|
9
|
+
/** Secondary accent - Purple */
|
|
10
|
+
secondary: "#a855f7",
|
|
11
|
+
/** Success state - Green */
|
|
12
|
+
success: "#22c55e",
|
|
13
|
+
/** Error state - Red */
|
|
14
|
+
error: "#ef4444",
|
|
15
|
+
/** Text color - White */
|
|
16
|
+
text: "#ffffff",
|
|
17
|
+
/** Muted text - Semi-transparent white */
|
|
18
|
+
mutedText: "rgba(255, 255, 255, 0.54)",
|
|
19
|
+
/** Border color - Semi-transparent white */
|
|
20
|
+
border: "rgba(255, 255, 255, 0.06)",
|
|
21
|
+
/** Background - Dark with transparency */
|
|
22
|
+
background: "rgba(15, 15, 25, 0.8)",
|
|
23
|
+
/** Card background - Darker with transparency */
|
|
24
|
+
cardBackground: "rgba(15, 15, 25, 0.6)",
|
|
25
|
+
/** Dropdown background - Near opaque dark */
|
|
26
|
+
dropdownBackground: "rgba(20, 20, 35, 0.98)",
|
|
27
|
+
/** Input background - Transparent black */
|
|
28
|
+
inputBackground: "rgba(0, 0, 0, 0.3)",
|
|
29
|
+
/** Hover state - Semi-transparent white */
|
|
30
|
+
hover: "rgba(255, 255, 255, 0.05)",
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Default theme spacing and sizing
|
|
35
|
+
*/
|
|
36
|
+
export const THEME_SIZING = {
|
|
37
|
+
/** Default border radius in pixels */
|
|
38
|
+
borderRadius: 12,
|
|
39
|
+
/** Widget max width */
|
|
40
|
+
maxWidth: "480px",
|
|
41
|
+
/** Standard padding */
|
|
42
|
+
padding: "16px",
|
|
43
|
+
/** Gap between elements */
|
|
44
|
+
gap: "12px",
|
|
45
|
+
/** Small gap */
|
|
46
|
+
smallGap: "8px",
|
|
47
|
+
/** Dropdown max height */
|
|
48
|
+
dropdownMaxHeight: "300px",
|
|
49
|
+
} as const;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Default font settings
|
|
53
|
+
*/
|
|
54
|
+
export const THEME_FONTS = {
|
|
55
|
+
/** Primary font family */
|
|
56
|
+
family: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
57
|
+
/** Font sizes */
|
|
58
|
+
sizes: {
|
|
59
|
+
xs: "10px",
|
|
60
|
+
sm: "12px",
|
|
61
|
+
base: "14px",
|
|
62
|
+
lg: "18px",
|
|
63
|
+
},
|
|
64
|
+
/** Font weights */
|
|
65
|
+
weights: {
|
|
66
|
+
normal: 400,
|
|
67
|
+
medium: 500,
|
|
68
|
+
semibold: 600,
|
|
69
|
+
bold: 700,
|
|
70
|
+
},
|
|
71
|
+
} as const;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Default complete theme configuration
|
|
75
|
+
*/
|
|
76
|
+
export const defaultTheme: Required<BridgeWidgetTheme> = {
|
|
77
|
+
primaryColor: THEME_COLORS.primary,
|
|
78
|
+
secondaryColor: THEME_COLORS.secondary,
|
|
79
|
+
backgroundColor: THEME_COLORS.background,
|
|
80
|
+
cardBackgroundColor: THEME_COLORS.cardBackground,
|
|
81
|
+
textColor: THEME_COLORS.text,
|
|
82
|
+
mutedTextColor: THEME_COLORS.mutedText,
|
|
83
|
+
borderColor: THEME_COLORS.border,
|
|
84
|
+
successColor: THEME_COLORS.success,
|
|
85
|
+
errorColor: THEME_COLORS.error,
|
|
86
|
+
hoverColor: THEME_COLORS.hover,
|
|
87
|
+
borderRadius: THEME_SIZING.borderRadius,
|
|
88
|
+
fontFamily: THEME_FONTS.family,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Merge user theme overrides with defaults
|
|
93
|
+
*/
|
|
94
|
+
export function mergeTheme(
|
|
95
|
+
theme?: BridgeWidgetTheme
|
|
96
|
+
): Required<BridgeWidgetTheme> {
|
|
97
|
+
return { ...defaultTheme, ...theme };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Pre-built theme presets
|
|
102
|
+
*/
|
|
103
|
+
export const themePresets = {
|
|
104
|
+
/** Default dark theme */
|
|
105
|
+
dark: defaultTheme,
|
|
106
|
+
|
|
107
|
+
/** Light theme variant */
|
|
108
|
+
light: {
|
|
109
|
+
...defaultTheme,
|
|
110
|
+
backgroundColor: "rgba(255, 255, 255, 0.95)",
|
|
111
|
+
cardBackgroundColor: "rgba(245, 245, 245, 0.9)",
|
|
112
|
+
textColor: "#1a1a2e",
|
|
113
|
+
mutedTextColor: "rgba(0, 0, 0, 0.54)",
|
|
114
|
+
borderColor: "rgba(0, 0, 0, 0.1)",
|
|
115
|
+
hoverColor: "rgba(0, 0, 0, 0.05)",
|
|
116
|
+
} as Required<BridgeWidgetTheme>,
|
|
117
|
+
|
|
118
|
+
/** Blue accent theme */
|
|
119
|
+
blue: {
|
|
120
|
+
...defaultTheme,
|
|
121
|
+
primaryColor: "#3b82f6",
|
|
122
|
+
secondaryColor: "#06b6d4",
|
|
123
|
+
} as Required<BridgeWidgetTheme>,
|
|
124
|
+
|
|
125
|
+
/** Green accent theme */
|
|
126
|
+
green: {
|
|
127
|
+
...defaultTheme,
|
|
128
|
+
primaryColor: "#10b981",
|
|
129
|
+
secondaryColor: "#34d399",
|
|
130
|
+
} as Required<BridgeWidgetTheme>,
|
|
131
|
+
} as const;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { Chain } from "viem";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Theme configuration for the Bridge Widget.
|
|
5
|
+
* All color values should be valid CSS color strings (hex, rgb, rgba, etc.).
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const customTheme: BridgeWidgetTheme = {
|
|
9
|
+
* primaryColor: "#3b82f6",
|
|
10
|
+
* backgroundColor: "rgba(0, 0, 0, 0.9)",
|
|
11
|
+
* borderRadius: 16,
|
|
12
|
+
* };
|
|
13
|
+
*/
|
|
14
|
+
export interface BridgeWidgetTheme {
|
|
15
|
+
/** Primary accent color used for buttons and highlights (hex) */
|
|
16
|
+
primaryColor?: string;
|
|
17
|
+
/** Secondary accent color used for gradients (hex) */
|
|
18
|
+
secondaryColor?: string;
|
|
19
|
+
/** Main background color of the widget (hex or rgba) */
|
|
20
|
+
backgroundColor?: string;
|
|
21
|
+
/** Background color for cards and nested elements (hex or rgba) */
|
|
22
|
+
cardBackgroundColor?: string;
|
|
23
|
+
/** Primary text color (hex) */
|
|
24
|
+
textColor?: string;
|
|
25
|
+
/** Secondary/muted text color for labels (hex or rgba) */
|
|
26
|
+
mutedTextColor?: string;
|
|
27
|
+
/** Border color for inputs and containers (hex or rgba) */
|
|
28
|
+
borderColor?: string;
|
|
29
|
+
/** Color for success states and messages (hex) */
|
|
30
|
+
successColor?: string;
|
|
31
|
+
/** Color for error states and messages (hex) */
|
|
32
|
+
errorColor?: string;
|
|
33
|
+
/** Color for hover states (hex or rgba) */
|
|
34
|
+
hoverColor?: string;
|
|
35
|
+
/** Border radius in pixels for rounded corners */
|
|
36
|
+
borderRadius?: number;
|
|
37
|
+
/** Font family for all text in the widget */
|
|
38
|
+
fontFamily?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Configuration for a supported blockchain in the bridge.
|
|
43
|
+
* Contains chain metadata, USDC contract address, and CCTP TokenMessenger address.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* const ethereumConfig: BridgeChainConfig = {
|
|
47
|
+
* chain: mainnet,
|
|
48
|
+
* usdcAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
49
|
+
* tokenMessengerAddress: "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
|
|
50
|
+
* iconUrl: "https://icons.llamao.fi/icons/chains/rsz_ethereum.jpg",
|
|
51
|
+
* };
|
|
52
|
+
*/
|
|
53
|
+
export interface BridgeChainConfig {
|
|
54
|
+
/** Chain definition from viem containing id, name, and network details */
|
|
55
|
+
chain: Chain;
|
|
56
|
+
/** USDC token contract address on this chain (checksummed) */
|
|
57
|
+
usdcAddress: `0x${string}`;
|
|
58
|
+
/** Circle TokenMessenger contract address for CCTP transfers */
|
|
59
|
+
tokenMessengerAddress?: `0x${string}`;
|
|
60
|
+
/** URL for the chain's icon/logo image (optional, falls back to initial) */
|
|
61
|
+
iconUrl?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Props for the BridgeWidget component.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* <BridgeWidget
|
|
69
|
+
* defaultSourceChainId={1}
|
|
70
|
+
* defaultDestinationChainId={8453}
|
|
71
|
+
* onBridgeSuccess={({ txHash }) => console.log('Success:', txHash)}
|
|
72
|
+
* onBridgeError={(error) => console.error('Error:', error)}
|
|
73
|
+
* theme={{ primaryColor: "#3b82f6" }}
|
|
74
|
+
* />
|
|
75
|
+
*/
|
|
76
|
+
export interface BridgeWidgetProps {
|
|
77
|
+
/**
|
|
78
|
+
* Array of supported chains with their USDC addresses.
|
|
79
|
+
* Defaults to all CCTP-supported chains from DEFAULT_CHAIN_CONFIGS.
|
|
80
|
+
*/
|
|
81
|
+
chains?: BridgeChainConfig[];
|
|
82
|
+
/** Chain ID to pre-select as the source chain */
|
|
83
|
+
defaultSourceChainId?: number;
|
|
84
|
+
/** Chain ID to pre-select as the destination chain */
|
|
85
|
+
defaultDestinationChainId?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Callback fired when a bridge transaction is initiated.
|
|
88
|
+
* Called before approval (if needed) or bridge execution begins.
|
|
89
|
+
*/
|
|
90
|
+
onBridgeStart?: (params: {
|
|
91
|
+
/** Source chain ID */
|
|
92
|
+
sourceChainId: number;
|
|
93
|
+
/** Destination chain ID */
|
|
94
|
+
destChainId: number;
|
|
95
|
+
/** Amount being bridged (as string) */
|
|
96
|
+
amount: string;
|
|
97
|
+
/** Transaction hash (only present if tx already submitted) */
|
|
98
|
+
txHash?: `0x${string}`;
|
|
99
|
+
}) => void;
|
|
100
|
+
/**
|
|
101
|
+
* Callback fired when a bridge transaction completes successfully.
|
|
102
|
+
* The txHash can be used to link to a block explorer.
|
|
103
|
+
*/
|
|
104
|
+
onBridgeSuccess?: (params: {
|
|
105
|
+
/** Source chain ID */
|
|
106
|
+
sourceChainId: number;
|
|
107
|
+
/** Destination chain ID */
|
|
108
|
+
destChainId: number;
|
|
109
|
+
/** Amount bridged (as string) */
|
|
110
|
+
amount: string;
|
|
111
|
+
/** Transaction hash of the successful bridge */
|
|
112
|
+
txHash: `0x${string}`;
|
|
113
|
+
}) => void;
|
|
114
|
+
/**
|
|
115
|
+
* Callback fired when a bridge transaction fails.
|
|
116
|
+
* The error object contains details about what went wrong.
|
|
117
|
+
*/
|
|
118
|
+
onBridgeError?: (error: Error) => void;
|
|
119
|
+
/**
|
|
120
|
+
* Callback fired when the user clicks "Connect Wallet".
|
|
121
|
+
* If not provided, the widget will attempt to use wagmi's connectors.
|
|
122
|
+
*/
|
|
123
|
+
onConnectWallet?: () => void;
|
|
124
|
+
/** Custom theme overrides to customize the widget appearance */
|
|
125
|
+
theme?: BridgeWidgetTheme;
|
|
126
|
+
/** Custom CSS class name to apply to the widget container */
|
|
127
|
+
className?: string;
|
|
128
|
+
/** Custom inline styles to apply to the widget container */
|
|
129
|
+
style?: React.CSSProperties;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Estimated costs and timing for a bridge transfer.
|
|
134
|
+
* Used by the deprecated useBridgeEstimate hook.
|
|
135
|
+
*
|
|
136
|
+
* @deprecated Use BridgeQuote from useBridge.ts instead
|
|
137
|
+
*/
|
|
138
|
+
export interface BridgeEstimate {
|
|
139
|
+
/** Estimated gas fee (as formatted string) */
|
|
140
|
+
gasFee: string;
|
|
141
|
+
/** Protocol bridge fee (as formatted string) */
|
|
142
|
+
bridgeFee: string;
|
|
143
|
+
/** Total estimated fee including gas and protocol (as formatted string) */
|
|
144
|
+
totalFee: string;
|
|
145
|
+
/** Estimated time for the bridge to complete (e.g., "~15-20 minutes") */
|
|
146
|
+
estimatedTime: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Result state for a bridge operation.
|
|
151
|
+
* Tracks the current state and any associated transaction hash or error.
|
|
152
|
+
*/
|
|
153
|
+
export interface BridgeResult {
|
|
154
|
+
/** Current state of the bridge operation */
|
|
155
|
+
state: "idle" | "pending" | "success" | "error";
|
|
156
|
+
/** Transaction hash if a transaction has been submitted */
|
|
157
|
+
txHash?: `0x${string}`;
|
|
158
|
+
/** Error message if the operation failed */
|
|
159
|
+
error?: string;
|
|
160
|
+
}
|