@compass-labs/widgets 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/dist/index.js ADDED
@@ -0,0 +1,3330 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var reactQuery = require('@tanstack/react-query');
5
+ var apiSdk = require('@compass-labs/api-sdk');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var chains = require('viem/chains');
8
+ var lucideReact = require('lucide-react');
9
+
10
+ // src/provider/CompassProvider.tsx
11
+ var ApiContext = react.createContext(null);
12
+ function ApiProvider({ children, apiKey, serverURL }) {
13
+ const client = react.useMemo(() => {
14
+ return new apiSdk.CompassApiSDK({
15
+ apiKeyAuth: apiKey,
16
+ serverURL: serverURL || "https://api.compasslabs.ai"
17
+ });
18
+ }, [apiKey, serverURL]);
19
+ const value = react.useMemo(
20
+ () => ({
21
+ apiKey,
22
+ client
23
+ }),
24
+ [apiKey, client]
25
+ );
26
+ return /* @__PURE__ */ jsxRuntime.jsx(ApiContext.Provider, { value, children });
27
+ }
28
+ function useCompassApi() {
29
+ const context = react.useContext(ApiContext);
30
+ if (!context) {
31
+ throw new Error("useCompassApi must be used within a CompassProvider");
32
+ }
33
+ return context;
34
+ }
35
+ var useEmbeddableApi = useCompassApi;
36
+ var ChainContext = react.createContext(null);
37
+ var CHAIN_CONFIG = {
38
+ ethereum: {
39
+ viemChain: chains.mainnet,
40
+ name: "Ethereum",
41
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
42
+ },
43
+ base: {
44
+ viemChain: chains.base,
45
+ name: "Base",
46
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/info/logo.png"
47
+ },
48
+ arbitrum: {
49
+ viemChain: chains.arbitrum,
50
+ name: "Arbitrum",
51
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/arbitrum/info/logo.png"
52
+ }
53
+ };
54
+ function ChainProvider({ children, defaultChain }) {
55
+ const [chainId, setChainIdState] = react.useState(defaultChain);
56
+ react.useEffect(() => {
57
+ if (typeof window === "undefined") return;
58
+ const stored = localStorage.getItem("compass-chain");
59
+ if (stored && stored in CHAIN_CONFIG) {
60
+ setChainIdState(stored);
61
+ }
62
+ }, []);
63
+ const setChainId = (newChainId) => {
64
+ setChainIdState(newChainId);
65
+ if (typeof window !== "undefined") {
66
+ localStorage.setItem("compass-chain", newChainId);
67
+ }
68
+ };
69
+ const chain = react.useMemo(() => CHAIN_CONFIG[chainId], [chainId]);
70
+ return /* @__PURE__ */ jsxRuntime.jsx(ChainContext.Provider, { value: { chainId, setChainId, setChain: setChainId, chain }, children });
71
+ }
72
+ function useCompassChain() {
73
+ const context = react.useContext(ChainContext);
74
+ if (!context) {
75
+ throw new Error("useCompassChain must be used within a CompassProvider");
76
+ }
77
+ return context;
78
+ }
79
+ var useChain = useCompassChain;
80
+ var WalletContext = react.createContext(null);
81
+ var disconnectedWallet = {
82
+ address: null,
83
+ isConnected: false,
84
+ signTypedData: async () => {
85
+ throw new Error("No wallet connected. Please connect a wallet first.");
86
+ },
87
+ switchChain: null,
88
+ login: null,
89
+ logout: null
90
+ };
91
+ function WalletProvider({ children, wallet }) {
92
+ const value = wallet ? {
93
+ address: wallet.address,
94
+ isConnected: wallet.address !== null,
95
+ signTypedData: wallet.signTypedData,
96
+ switchChain: wallet.switchChain ?? null,
97
+ login: wallet.login ?? null,
98
+ logout: wallet.logout ?? null
99
+ } : disconnectedWallet;
100
+ return /* @__PURE__ */ jsxRuntime.jsx(WalletContext.Provider, { value, children });
101
+ }
102
+ function useCompassWallet() {
103
+ const context = react.useContext(WalletContext);
104
+ if (!context) {
105
+ return disconnectedWallet;
106
+ }
107
+ return context;
108
+ }
109
+ var useEmbeddableWallet = useCompassWallet;
110
+ var EarnAccountContext = react.createContext(null);
111
+ function EarnAccountProvider({ children }) {
112
+ const { address } = useEmbeddableWallet();
113
+ const { chainId } = useChain();
114
+ const queryClient = reactQuery.useQueryClient();
115
+ const [isCreating, setIsCreating] = react.useState(false);
116
+ const [createError, setCreateError] = react.useState(null);
117
+ const {
118
+ data: accountData,
119
+ isLoading: isChecking,
120
+ error: checkError,
121
+ refetch
122
+ } = reactQuery.useQuery({
123
+ queryKey: ["earnAccount", address, chainId],
124
+ queryFn: async () => {
125
+ if (!address) return null;
126
+ const response = await fetch(
127
+ `/api/compass/earn-account/check?owner=${address}&chain=${chainId}`
128
+ );
129
+ if (!response.ok) {
130
+ const error = await response.json();
131
+ throw new Error(error.error || "Failed to check earn account");
132
+ }
133
+ return response.json();
134
+ },
135
+ enabled: !!address,
136
+ staleTime: 60 * 1e3,
137
+ // 1 minute
138
+ refetchOnMount: true
139
+ });
140
+ const createAccount = react.useCallback(async () => {
141
+ if (!address) {
142
+ throw new Error("No wallet connected");
143
+ }
144
+ if (accountData?.isDeployed) {
145
+ return accountData.earnAccountAddress;
146
+ }
147
+ setIsCreating(true);
148
+ setCreateError(null);
149
+ try {
150
+ const response = await fetch("/api/compass/create-account", {
151
+ method: "POST",
152
+ headers: { "Content-Type": "application/json" },
153
+ body: JSON.stringify({
154
+ owner: address,
155
+ chain: chainId
156
+ })
157
+ });
158
+ if (!response.ok) {
159
+ const error = await response.json();
160
+ throw new Error(error.error || "Failed to create earn account");
161
+ }
162
+ const result = await response.json();
163
+ await queryClient.invalidateQueries({
164
+ queryKey: ["earnAccount", address, chainId]
165
+ });
166
+ return result.earnAccountAddress;
167
+ } catch (error) {
168
+ const err = error instanceof Error ? error : new Error("Unknown error");
169
+ setCreateError(err);
170
+ throw err;
171
+ } finally {
172
+ setIsCreating(false);
173
+ }
174
+ }, [address, chainId, accountData, queryClient]);
175
+ const value = {
176
+ earnAccountAddress: accountData?.earnAccountAddress || null,
177
+ isDeployed: accountData?.isDeployed ?? false,
178
+ isChecking,
179
+ isCreating,
180
+ error: checkError instanceof Error ? checkError : createError,
181
+ createAccount,
182
+ refetch
183
+ };
184
+ return /* @__PURE__ */ jsxRuntime.jsx(EarnAccountContext.Provider, { value, children });
185
+ }
186
+ function useEarnAccount() {
187
+ const context = react.useContext(EarnAccountContext);
188
+ if (!context) {
189
+ throw new Error("useEarnAccount must be used within a CompassProvider");
190
+ }
191
+ return context;
192
+ }
193
+
194
+ // src/theme/presets.ts
195
+ var baseTypography = {
196
+ fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
197
+ fontFamilyMono: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',
198
+ heading: {
199
+ fontSize: "1.5rem",
200
+ lineHeight: 1.2,
201
+ fontWeight: 600,
202
+ letterSpacing: "-0.02em"
203
+ },
204
+ subheading: {
205
+ fontSize: "1.125rem",
206
+ lineHeight: 1.3,
207
+ fontWeight: 500,
208
+ letterSpacing: "-0.01em"
209
+ },
210
+ body: {
211
+ fontSize: "0.875rem",
212
+ lineHeight: 1.5,
213
+ fontWeight: 400
214
+ },
215
+ caption: {
216
+ fontSize: "0.75rem",
217
+ lineHeight: 1.4,
218
+ fontWeight: 400
219
+ },
220
+ label: {
221
+ fontSize: "0.75rem",
222
+ lineHeight: 1.2,
223
+ fontWeight: 500,
224
+ letterSpacing: "0.02em"
225
+ }
226
+ };
227
+ var highContrastTypography = {
228
+ ...baseTypography,
229
+ heading: {
230
+ fontSize: "1.75rem",
231
+ lineHeight: 1.2,
232
+ fontWeight: 700,
233
+ letterSpacing: "-0.02em"
234
+ },
235
+ subheading: {
236
+ fontSize: "1.25rem",
237
+ lineHeight: 1.3,
238
+ fontWeight: 600,
239
+ letterSpacing: "-0.01em"
240
+ },
241
+ body: {
242
+ fontSize: "1rem",
243
+ lineHeight: 1.6,
244
+ fontWeight: 400
245
+ },
246
+ caption: {
247
+ fontSize: "0.875rem",
248
+ lineHeight: 1.5,
249
+ fontWeight: 400
250
+ },
251
+ label: {
252
+ fontSize: "0.875rem",
253
+ lineHeight: 1.2,
254
+ fontWeight: 600,
255
+ letterSpacing: "0.02em"
256
+ }
257
+ };
258
+ var baseSpacing = {
259
+ unit: "4px",
260
+ containerPadding: "1.5rem",
261
+ cardPadding: "1.25rem",
262
+ inputPadding: "0.75rem 1rem"
263
+ };
264
+ var baseTransitions = {
265
+ fast: "150ms ease-out",
266
+ normal: "200ms ease-out",
267
+ slow: "300ms ease-out"
268
+ };
269
+ var compassDark = {
270
+ name: "compass-dark",
271
+ mode: "dark",
272
+ colors: {
273
+ backgrounds: {
274
+ // wallet-earn: --background: #050507
275
+ background: "#050507",
276
+ // wallet-earn: --surface-1: #0c0c10, --surface-2: #12121a
277
+ surface: "#0c0c10",
278
+ surfaceHover: "#12121a",
279
+ overlay: "rgba(0, 0, 0, 0.7)"
280
+ },
281
+ brand: {
282
+ // wallet-earn: --accent-primary: #6366f1, --accent-secondary: #8b5cf6
283
+ primary: "#6366f1",
284
+ primaryHover: "#818cf8",
285
+ primaryText: "#ffffff",
286
+ secondary: "#8b5cf6",
287
+ secondaryHover: "#a78bfa"
288
+ },
289
+ text: {
290
+ // wallet-earn: --foreground: #f4f4f5, text-zinc-400: #a1a1aa, text-zinc-500: #71717a
291
+ text: "#f4f4f5",
292
+ textSecondary: "#a1a1aa",
293
+ textTertiary: "#71717a"
294
+ },
295
+ borders: {
296
+ // wallet-earn: --border-subtle: rgba(255,255,255,0.06), --border-default: rgba(255,255,255,0.1)
297
+ border: "rgba(255, 255, 255, 0.08)",
298
+ borderHover: "rgba(255, 255, 255, 0.12)",
299
+ borderFocus: "#6366f1"
300
+ },
301
+ semantic: {
302
+ success: {
303
+ // wallet-earn: --success: #10b981
304
+ DEFAULT: "#10b981",
305
+ muted: "rgba(16, 185, 129, 0.15)"
306
+ },
307
+ warning: {
308
+ DEFAULT: "#f59e0b",
309
+ muted: "rgba(245, 158, 11, 0.15)"
310
+ },
311
+ error: {
312
+ // wallet-earn: --error: #ef4444
313
+ DEFAULT: "#ef4444",
314
+ muted: "rgba(239, 68, 68, 0.15)"
315
+ },
316
+ info: {
317
+ DEFAULT: "#6366f1",
318
+ muted: "rgba(99, 102, 241, 0.15)"
319
+ }
320
+ }
321
+ },
322
+ typography: baseTypography,
323
+ spacing: baseSpacing,
324
+ shape: {
325
+ borderRadius: {
326
+ none: "0",
327
+ sm: "0.375rem",
328
+ md: "0.5rem",
329
+ lg: "0.75rem",
330
+ xl: "1rem",
331
+ full: "9999px"
332
+ },
333
+ borderWidth: "1px"
334
+ },
335
+ effects: {
336
+ shadow: {
337
+ sm: "0 1px 2px rgba(0, 0, 0, 0.3)",
338
+ md: "0 4px 12px rgba(0, 0, 0, 0.4)",
339
+ lg: "0 8px 24px rgba(0, 0, 0, 0.5)"
340
+ },
341
+ blur: {
342
+ sm: "4px",
343
+ md: "8px",
344
+ lg: "16px"
345
+ },
346
+ transition: baseTransitions
347
+ }
348
+ };
349
+ var compassLight = {
350
+ name: "compass-light",
351
+ mode: "light",
352
+ colors: {
353
+ backgrounds: {
354
+ background: "#ffffff",
355
+ surface: "#f8fafc",
356
+ surfaceHover: "#f1f5f9",
357
+ overlay: "rgba(0, 0, 0, 0.5)"
358
+ },
359
+ brand: {
360
+ primary: "#6366f1",
361
+ primaryHover: "#4f46e5",
362
+ primaryText: "#ffffff",
363
+ secondary: "#4f46e5",
364
+ secondaryHover: "#4338ca"
365
+ },
366
+ text: {
367
+ text: "#0f172a",
368
+ textSecondary: "#475569",
369
+ textTertiary: "#94a3b8"
370
+ },
371
+ borders: {
372
+ border: "#e2e8f0",
373
+ borderHover: "#cbd5e1",
374
+ borderFocus: "#6366f1"
375
+ },
376
+ semantic: {
377
+ success: {
378
+ DEFAULT: "#16a34a",
379
+ muted: "#dcfce7"
380
+ },
381
+ warning: {
382
+ DEFAULT: "#d97706",
383
+ muted: "#fef3c7"
384
+ },
385
+ error: {
386
+ DEFAULT: "#dc2626",
387
+ muted: "#fee2e2"
388
+ },
389
+ info: {
390
+ DEFAULT: "#2563eb",
391
+ muted: "#dbeafe"
392
+ }
393
+ }
394
+ },
395
+ typography: baseTypography,
396
+ spacing: baseSpacing,
397
+ shape: {
398
+ borderRadius: {
399
+ none: "0",
400
+ sm: "0.375rem",
401
+ md: "0.5rem",
402
+ lg: "0.75rem",
403
+ xl: "1rem",
404
+ full: "9999px"
405
+ },
406
+ borderWidth: "1px"
407
+ },
408
+ effects: {
409
+ shadow: {
410
+ sm: "0 1px 2px rgba(0, 0, 0, 0.05)",
411
+ md: "0 4px 12px rgba(0, 0, 0, 0.08)",
412
+ lg: "0 8px 24px rgba(0, 0, 0, 0.12)"
413
+ },
414
+ blur: {
415
+ sm: "4px",
416
+ md: "8px",
417
+ lg: "16px"
418
+ },
419
+ transition: baseTransitions
420
+ }
421
+ };
422
+ var minimalDark = {
423
+ name: "minimal-dark",
424
+ mode: "dark",
425
+ colors: {
426
+ backgrounds: {
427
+ background: "#0a0a0a",
428
+ surface: "#171717",
429
+ surfaceHover: "#262626",
430
+ overlay: "rgba(0, 0, 0, 0.8)"
431
+ },
432
+ brand: {
433
+ primary: "#ffffff",
434
+ primaryHover: "#e5e5e5",
435
+ primaryText: "#0a0a0a",
436
+ secondary: "#a3a3a3",
437
+ secondaryHover: "#d4d4d4"
438
+ },
439
+ text: {
440
+ text: "#fafafa",
441
+ textSecondary: "#a3a3a3",
442
+ textTertiary: "#525252"
443
+ },
444
+ borders: {
445
+ border: "#262626",
446
+ borderHover: "#404040",
447
+ borderFocus: "#ffffff"
448
+ },
449
+ semantic: {
450
+ success: {
451
+ DEFAULT: "#4ade80",
452
+ muted: "rgba(74, 222, 128, 0.1)"
453
+ },
454
+ warning: {
455
+ DEFAULT: "#fbbf24",
456
+ muted: "rgba(251, 191, 36, 0.1)"
457
+ },
458
+ error: {
459
+ DEFAULT: "#f87171",
460
+ muted: "rgba(248, 113, 113, 0.1)"
461
+ },
462
+ info: {
463
+ DEFAULT: "#60a5fa",
464
+ muted: "rgba(96, 165, 250, 0.1)"
465
+ }
466
+ }
467
+ },
468
+ typography: baseTypography,
469
+ spacing: baseSpacing,
470
+ shape: {
471
+ borderRadius: {
472
+ none: "0",
473
+ sm: "0.125rem",
474
+ md: "0.25rem",
475
+ lg: "0.375rem",
476
+ xl: "0.5rem",
477
+ full: "9999px"
478
+ },
479
+ borderWidth: "1px"
480
+ },
481
+ effects: {
482
+ shadow: {
483
+ sm: "none",
484
+ md: "none",
485
+ lg: "none"
486
+ },
487
+ blur: {
488
+ sm: "0",
489
+ md: "0",
490
+ lg: "0"
491
+ },
492
+ transition: baseTransitions
493
+ }
494
+ };
495
+ var minimalLight = {
496
+ name: "minimal-light",
497
+ mode: "light",
498
+ colors: {
499
+ backgrounds: {
500
+ background: "#ffffff",
501
+ surface: "#fafafa",
502
+ surfaceHover: "#f5f5f5",
503
+ overlay: "rgba(0, 0, 0, 0.6)"
504
+ },
505
+ brand: {
506
+ primary: "#0a0a0a",
507
+ primaryHover: "#262626",
508
+ primaryText: "#ffffff",
509
+ secondary: "#525252",
510
+ secondaryHover: "#404040"
511
+ },
512
+ text: {
513
+ text: "#0a0a0a",
514
+ textSecondary: "#525252",
515
+ textTertiary: "#a3a3a3"
516
+ },
517
+ borders: {
518
+ border: "#e5e5e5",
519
+ borderHover: "#d4d4d4",
520
+ borderFocus: "#0a0a0a"
521
+ },
522
+ semantic: {
523
+ success: {
524
+ DEFAULT: "#16a34a",
525
+ muted: "#f0fdf4"
526
+ },
527
+ warning: {
528
+ DEFAULT: "#ca8a04",
529
+ muted: "#fefce8"
530
+ },
531
+ error: {
532
+ DEFAULT: "#dc2626",
533
+ muted: "#fef2f2"
534
+ },
535
+ info: {
536
+ DEFAULT: "#2563eb",
537
+ muted: "#eff6ff"
538
+ }
539
+ }
540
+ },
541
+ typography: baseTypography,
542
+ spacing: baseSpacing,
543
+ shape: {
544
+ borderRadius: {
545
+ none: "0",
546
+ sm: "0.125rem",
547
+ md: "0.25rem",
548
+ lg: "0.375rem",
549
+ xl: "0.5rem",
550
+ full: "9999px"
551
+ },
552
+ borderWidth: "1px"
553
+ },
554
+ effects: {
555
+ shadow: {
556
+ sm: "none",
557
+ md: "none",
558
+ lg: "none"
559
+ },
560
+ blur: {
561
+ sm: "0",
562
+ md: "0",
563
+ lg: "0"
564
+ },
565
+ transition: baseTransitions
566
+ }
567
+ };
568
+ var highContrastDark = {
569
+ name: "high-contrast-dark",
570
+ mode: "dark",
571
+ colors: {
572
+ backgrounds: {
573
+ background: "#000000",
574
+ surface: "#0a0a0a",
575
+ surfaceHover: "#1a1a1a",
576
+ overlay: "rgba(0, 0, 0, 0.9)"
577
+ },
578
+ brand: {
579
+ primary: "#3b82f6",
580
+ primaryHover: "#60a5fa",
581
+ primaryText: "#ffffff",
582
+ secondary: "#60a5fa",
583
+ secondaryHover: "#93c5fd"
584
+ },
585
+ text: {
586
+ text: "#ffffff",
587
+ textSecondary: "#e5e5e5",
588
+ textTertiary: "#a3a3a3"
589
+ },
590
+ borders: {
591
+ border: "#404040",
592
+ borderHover: "#525252",
593
+ borderFocus: "#3b82f6"
594
+ },
595
+ semantic: {
596
+ success: {
597
+ DEFAULT: "#22c55e",
598
+ muted: "rgba(34, 197, 94, 0.2)"
599
+ },
600
+ warning: {
601
+ DEFAULT: "#fbbf24",
602
+ muted: "rgba(251, 191, 36, 0.2)"
603
+ },
604
+ error: {
605
+ DEFAULT: "#ef4444",
606
+ muted: "rgba(239, 68, 68, 0.2)"
607
+ },
608
+ info: {
609
+ DEFAULT: "#3b82f6",
610
+ muted: "rgba(59, 130, 246, 0.2)"
611
+ }
612
+ }
613
+ },
614
+ typography: highContrastTypography,
615
+ spacing: baseSpacing,
616
+ shape: {
617
+ borderRadius: {
618
+ none: "0",
619
+ sm: "0.25rem",
620
+ md: "0.375rem",
621
+ lg: "0.5rem",
622
+ xl: "0.75rem",
623
+ full: "9999px"
624
+ },
625
+ borderWidth: "2px"
626
+ },
627
+ effects: {
628
+ shadow: {
629
+ sm: "0 1px 3px rgba(0, 0, 0, 0.5)",
630
+ md: "0 4px 12px rgba(0, 0, 0, 0.6)",
631
+ lg: "0 8px 24px rgba(0, 0, 0, 0.7)"
632
+ },
633
+ blur: {
634
+ sm: "4px",
635
+ md: "8px",
636
+ lg: "16px"
637
+ },
638
+ transition: baseTransitions
639
+ }
640
+ };
641
+ var highContrastLight = {
642
+ name: "high-contrast-light",
643
+ mode: "light",
644
+ colors: {
645
+ backgrounds: {
646
+ background: "#ffffff",
647
+ surface: "#f5f5f5",
648
+ surfaceHover: "#e5e5e5",
649
+ overlay: "rgba(0, 0, 0, 0.7)"
650
+ },
651
+ brand: {
652
+ primary: "#1d4ed8",
653
+ primaryHover: "#1e40af",
654
+ primaryText: "#ffffff",
655
+ secondary: "#1e40af",
656
+ secondaryHover: "#1e3a8a"
657
+ },
658
+ text: {
659
+ text: "#000000",
660
+ textSecondary: "#1a1a1a",
661
+ textTertiary: "#525252"
662
+ },
663
+ borders: {
664
+ border: "#525252",
665
+ borderHover: "#404040",
666
+ borderFocus: "#1d4ed8"
667
+ },
668
+ semantic: {
669
+ success: {
670
+ DEFAULT: "#15803d",
671
+ muted: "#dcfce7"
672
+ },
673
+ warning: {
674
+ DEFAULT: "#a16207",
675
+ muted: "#fef9c3"
676
+ },
677
+ error: {
678
+ DEFAULT: "#b91c1c",
679
+ muted: "#fee2e2"
680
+ },
681
+ info: {
682
+ DEFAULT: "#1d4ed8",
683
+ muted: "#dbeafe"
684
+ }
685
+ }
686
+ },
687
+ typography: highContrastTypography,
688
+ spacing: baseSpacing,
689
+ shape: {
690
+ borderRadius: {
691
+ none: "0",
692
+ sm: "0.25rem",
693
+ md: "0.375rem",
694
+ lg: "0.5rem",
695
+ xl: "0.75rem",
696
+ full: "9999px"
697
+ },
698
+ borderWidth: "2px"
699
+ },
700
+ effects: {
701
+ shadow: {
702
+ sm: "0 1px 2px rgba(0, 0, 0, 0.1)",
703
+ md: "0 4px 8px rgba(0, 0, 0, 0.15)",
704
+ lg: "0 8px 16px rgba(0, 0, 0, 0.2)"
705
+ },
706
+ blur: {
707
+ sm: "4px",
708
+ md: "8px",
709
+ lg: "16px"
710
+ },
711
+ transition: baseTransitions
712
+ }
713
+ };
714
+ var themePresets = {
715
+ "compass-dark": compassDark,
716
+ "compass-light": compassLight,
717
+ "minimal-dark": minimalDark,
718
+ "minimal-light": minimalLight,
719
+ "high-contrast-dark": highContrastDark,
720
+ "high-contrast-light": highContrastLight
721
+ };
722
+ var defaultTheme = compassDark;
723
+
724
+ // src/theme/css-variables.ts
725
+ function camelToKebab(str) {
726
+ return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
727
+ }
728
+ function cssVarPath(category, ...parts) {
729
+ const kebabParts = parts.map(camelToKebab).join("-");
730
+ return `--compass-${category}-${kebabParts}`;
731
+ }
732
+ function colorsToCssVariables(colors) {
733
+ const vars = {};
734
+ for (const [key, value] of Object.entries(colors.backgrounds)) {
735
+ vars[cssVarPath("color", key)] = value;
736
+ }
737
+ for (const [key, value] of Object.entries(colors.brand)) {
738
+ vars[cssVarPath("color", key)] = value;
739
+ }
740
+ for (const [key, value] of Object.entries(colors.text)) {
741
+ vars[cssVarPath("color", key)] = value;
742
+ }
743
+ for (const [key, value] of Object.entries(colors.borders)) {
744
+ vars[cssVarPath("color", key)] = value;
745
+ }
746
+ for (const [semantic, colorObj] of Object.entries(colors.semantic)) {
747
+ const semanticColor = colorObj;
748
+ vars[cssVarPath("color", semantic)] = semanticColor.DEFAULT;
749
+ vars[cssVarPath("color", semantic, "muted")] = semanticColor.muted;
750
+ }
751
+ return vars;
752
+ }
753
+ function typographyScaleToCssVariables(name, scale) {
754
+ const vars = {};
755
+ vars[cssVarPath("font", name, "size")] = scale.fontSize;
756
+ vars[cssVarPath("font", name, "line-height")] = String(scale.lineHeight);
757
+ vars[cssVarPath("font", name, "weight")] = String(scale.fontWeight);
758
+ if (scale.letterSpacing) {
759
+ vars[cssVarPath("font", name, "letter-spacing")] = scale.letterSpacing;
760
+ }
761
+ return vars;
762
+ }
763
+ function typographyToCssVariables(typography) {
764
+ const vars = {};
765
+ vars["--compass-font-family"] = typography.fontFamily;
766
+ vars["--compass-font-family-mono"] = typography.fontFamilyMono;
767
+ const scales = [
768
+ "heading",
769
+ "subheading",
770
+ "body",
771
+ "caption",
772
+ "label"
773
+ ];
774
+ for (const scaleName of scales) {
775
+ const scale = typography[scaleName];
776
+ if (typeof scale === "object" && "fontSize" in scale) {
777
+ Object.assign(
778
+ vars,
779
+ typographyScaleToCssVariables(scaleName, scale)
780
+ );
781
+ }
782
+ }
783
+ return vars;
784
+ }
785
+ function spacingToCssVariables(spacing) {
786
+ const vars = {};
787
+ vars["--compass-spacing-unit"] = spacing.unit;
788
+ vars["--compass-spacing-container"] = spacing.containerPadding;
789
+ vars["--compass-spacing-card"] = spacing.cardPadding;
790
+ vars["--compass-spacing-input"] = spacing.inputPadding;
791
+ return vars;
792
+ }
793
+ function shapeToCssVariables(shape) {
794
+ const vars = {};
795
+ for (const [key, value] of Object.entries(shape.borderRadius)) {
796
+ vars[cssVarPath("radius", key)] = value;
797
+ }
798
+ vars["--compass-border-width"] = shape.borderWidth;
799
+ return vars;
800
+ }
801
+ function effectsToCssVariables(effects) {
802
+ const vars = {};
803
+ for (const [key, value] of Object.entries(effects.shadow)) {
804
+ vars[cssVarPath("shadow", key)] = value;
805
+ }
806
+ for (const [key, value] of Object.entries(effects.blur)) {
807
+ vars[cssVarPath("blur", key)] = value;
808
+ }
809
+ for (const [key, value] of Object.entries(effects.transition)) {
810
+ vars[cssVarPath("transition", key)] = value;
811
+ }
812
+ return vars;
813
+ }
814
+ function themeToCssVariables(theme) {
815
+ return {
816
+ // Theme metadata
817
+ "--compass-theme-name": theme.name,
818
+ "--compass-theme-mode": theme.mode,
819
+ // Color variables
820
+ ...colorsToCssVariables(theme.colors),
821
+ // Typography variables
822
+ ...typographyToCssVariables(theme.typography),
823
+ // Spacing variables
824
+ ...spacingToCssVariables(theme.spacing),
825
+ // Shape variables (border radius)
826
+ ...shapeToCssVariables(theme.shape),
827
+ // Effects variables (shadows, blur, transitions)
828
+ ...effectsToCssVariables(theme.effects)
829
+ };
830
+ }
831
+ function injectCssVariables(theme, selector = ".compass-widget") {
832
+ const variables = themeToCssVariables(theme);
833
+ const variableLines = Object.entries(variables).map(([name, value]) => ` ${name}: ${value};`).join("\n");
834
+ return `${selector} {
835
+ ${variableLines}
836
+ }`;
837
+ }
838
+ var ThemeContext = react.createContext(void 0);
839
+ function deepMerge(target, source) {
840
+ const result = { ...target };
841
+ for (const key in source) {
842
+ const sourceValue = source[key];
843
+ const targetValue = target[key];
844
+ if (sourceValue !== void 0 && typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null) {
845
+ result[key] = deepMerge(
846
+ targetValue,
847
+ sourceValue
848
+ );
849
+ } else if (sourceValue !== void 0) {
850
+ result[key] = sourceValue;
851
+ }
852
+ }
853
+ return result;
854
+ }
855
+ function resolveTheme(input) {
856
+ if (!input) return defaultTheme;
857
+ if (typeof input === "string") {
858
+ return themePresets[input] ?? defaultTheme;
859
+ }
860
+ if ("preset" in input) {
861
+ const base3 = themePresets[input.preset] ?? defaultTheme;
862
+ return input.overrides ? deepMerge(base3, input.overrides) : base3;
863
+ }
864
+ return input;
865
+ }
866
+ function ThemeProvider({ children, theme: initialTheme }) {
867
+ const [themeInput, setThemeInput] = react.useState(initialTheme);
868
+ const theme = react.useMemo(() => resolveTheme(themeInput), [themeInput]);
869
+ const cssVariables = react.useMemo(() => injectCssVariables(theme, ".compass-widget"), [theme]);
870
+ react.useEffect(() => {
871
+ const styleId = "compass-theme-variables";
872
+ let styleEl = document.getElementById(styleId);
873
+ if (!styleEl) {
874
+ styleEl = document.createElement("style");
875
+ styleEl.id = styleId;
876
+ document.head.appendChild(styleEl);
877
+ }
878
+ styleEl.textContent = cssVariables;
879
+ return () => {
880
+ };
881
+ }, [cssVariables]);
882
+ const value = react.useMemo(
883
+ () => ({
884
+ theme,
885
+ setTheme: setThemeInput,
886
+ cssVariables
887
+ }),
888
+ [theme, cssVariables]
889
+ );
890
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value, children });
891
+ }
892
+ function useTheme() {
893
+ const context = react.useContext(ThemeContext);
894
+ if (!context) {
895
+ throw new Error("useTheme must be used within a ThemeProvider");
896
+ }
897
+ return context;
898
+ }
899
+ function CompassProvider({
900
+ children,
901
+ apiKey,
902
+ defaultChain = "base",
903
+ theme,
904
+ wallet
905
+ }) {
906
+ const queryClient = react.useMemo(
907
+ () => new reactQuery.QueryClient({
908
+ defaultOptions: {
909
+ queries: {
910
+ staleTime: 30 * 1e3,
911
+ // 30 seconds
912
+ gcTime: 2 * 60 * 1e3,
913
+ // 2 minutes
914
+ refetchOnWindowFocus: false
915
+ }
916
+ }
917
+ }),
918
+ []
919
+ );
920
+ return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(ApiProvider, { apiKey, children: /* @__PURE__ */ jsxRuntime.jsx(ChainProvider, { defaultChain, children: /* @__PURE__ */ jsxRuntime.jsx(WalletProvider, { wallet, children: /* @__PURE__ */ jsxRuntime.jsx(EarnAccountProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "compass-widget", children }) }) }) }) }) }) });
921
+ }
922
+ var SUPPORTED_CHAINS = ["ethereum", "base", "arbitrum"];
923
+ function ChainSwitcher() {
924
+ const { chainId, setChain, chain } = useChain();
925
+ const chainConfigs = {
926
+ ethereum: {
927
+ viemChain: chain.viemChain,
928
+ name: "Ethereum",
929
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
930
+ },
931
+ base: {
932
+ viemChain: chain.viemChain,
933
+ name: "Base",
934
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/info/logo.png"
935
+ },
936
+ arbitrum: {
937
+ viemChain: chain.viemChain,
938
+ name: "Arbitrum",
939
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/arbitrum/info/logo.png"
940
+ }
941
+ };
942
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1 p-1 rounded-lg", style: { backgroundColor: "var(--compass-color-surface)" }, children: SUPPORTED_CHAINS.map((id) => {
943
+ const config = chainConfigs[id];
944
+ const isActive = chainId === id;
945
+ return /* @__PURE__ */ jsxRuntime.jsxs(
946
+ "button",
947
+ {
948
+ onClick: () => setChain(id),
949
+ className: "flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-all",
950
+ style: {
951
+ backgroundColor: isActive ? "var(--compass-color-primary)" : "transparent",
952
+ color: isActive ? "var(--compass-color-primary-text)" : "var(--compass-color-text-secondary)"
953
+ },
954
+ children: [
955
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src: config.icon, alt: config.name, className: "w-4 h-4" }),
956
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: config.name })
957
+ ]
958
+ },
959
+ id
960
+ );
961
+ }) });
962
+ }
963
+ function truncateAddress(address) {
964
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
965
+ }
966
+ function WalletStatus({
967
+ showFullAddress = false,
968
+ showLogout = true,
969
+ compact = false,
970
+ onConnect,
971
+ onDisconnect
972
+ }) {
973
+ const { address, isConnected, login, logout } = useCompassWallet();
974
+ const connectFn = onConnect ?? login;
975
+ const disconnectFn = onDisconnect ?? logout;
976
+ if (!isConnected || !address) {
977
+ if (connectFn !== null) {
978
+ return /* @__PURE__ */ jsxRuntime.jsxs(
979
+ "button",
980
+ {
981
+ onClick: () => connectFn(),
982
+ className: `flex items-center gap-2 rounded-lg font-medium transition-colors hover:opacity-90 ${compact ? "px-2 py-1.5" : "px-4 py-2"}`,
983
+ style: {
984
+ backgroundColor: "var(--compass-color-primary)",
985
+ color: "var(--compass-color-primary-text)"
986
+ },
987
+ children: [
988
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { size: compact ? 14 : 16 }),
989
+ !compact && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Connect Wallet" })
990
+ ]
991
+ }
992
+ );
993
+ }
994
+ return /* @__PURE__ */ jsxRuntime.jsxs(
995
+ "div",
996
+ {
997
+ className: `flex items-center gap-2 rounded-lg ${compact ? "px-2 py-1.5" : "px-3 py-2"}`,
998
+ style: {
999
+ backgroundColor: "var(--compass-color-surface)",
1000
+ color: "var(--compass-color-text-secondary)"
1001
+ },
1002
+ children: [
1003
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { size: compact ? 14 : 16 }),
1004
+ !compact && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Not connected" })
1005
+ ]
1006
+ }
1007
+ );
1008
+ }
1009
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1010
+ "div",
1011
+ {
1012
+ className: `flex items-center gap-2 rounded-lg ${compact ? "px-2 py-1.5" : "px-3 py-2"}`,
1013
+ style: {
1014
+ backgroundColor: "var(--compass-color-surface)",
1015
+ border: "1px solid var(--compass-color-border)"
1016
+ },
1017
+ children: [
1018
+ /* @__PURE__ */ jsxRuntime.jsx(
1019
+ "div",
1020
+ {
1021
+ className: "w-2 h-2 rounded-full flex-shrink-0",
1022
+ style: { backgroundColor: "var(--compass-color-success)" }
1023
+ }
1024
+ ),
1025
+ /* @__PURE__ */ jsxRuntime.jsx(
1026
+ "span",
1027
+ {
1028
+ className: `font-mono whitespace-nowrap ${compact ? "text-xs" : "text-sm"}`,
1029
+ style: { color: "var(--compass-color-text)" },
1030
+ children: showFullAddress ? address : truncateAddress(address)
1031
+ }
1032
+ ),
1033
+ showLogout && disconnectFn !== null && /* @__PURE__ */ jsxRuntime.jsx(
1034
+ "button",
1035
+ {
1036
+ onClick: () => disconnectFn(),
1037
+ className: `rounded hover:bg-white/10 transition-all flex-shrink-0 ${compact ? "p-1" : "p-1.5"}`,
1038
+ title: "Disconnect wallet",
1039
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { size: 14, style: { color: "var(--compass-color-text-secondary)" } })
1040
+ }
1041
+ )
1042
+ ]
1043
+ }
1044
+ );
1045
+ }
1046
+ function ActionModal({ isOpen, onClose, title, children }) {
1047
+ react.useEffect(() => {
1048
+ const handleEscape = (e) => {
1049
+ if (e.key === "Escape") onClose();
1050
+ };
1051
+ if (isOpen) {
1052
+ document.addEventListener("keydown", handleEscape);
1053
+ document.body.style.overflow = "hidden";
1054
+ }
1055
+ return () => {
1056
+ document.removeEventListener("keydown", handleEscape);
1057
+ document.body.style.overflow = "";
1058
+ };
1059
+ }, [isOpen, onClose]);
1060
+ if (!isOpen) return null;
1061
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
1062
+ /* @__PURE__ */ jsxRuntime.jsx(
1063
+ "div",
1064
+ {
1065
+ className: "absolute inset-0",
1066
+ style: { backgroundColor: "var(--compass-color-overlay)" },
1067
+ onClick: onClose
1068
+ }
1069
+ ),
1070
+ /* @__PURE__ */ jsxRuntime.jsxs(
1071
+ "div",
1072
+ {
1073
+ className: "relative w-full max-w-md mx-4 rounded-xl overflow-hidden",
1074
+ style: {
1075
+ backgroundColor: "var(--compass-color-surface)",
1076
+ boxShadow: "var(--compass-shadow-lg)"
1077
+ },
1078
+ children: [
1079
+ /* @__PURE__ */ jsxRuntime.jsxs(
1080
+ "div",
1081
+ {
1082
+ className: "flex items-center justify-between px-4 py-3 border-b",
1083
+ style: { borderColor: "var(--compass-color-border)" },
1084
+ children: [
1085
+ /* @__PURE__ */ jsxRuntime.jsx(
1086
+ "h2",
1087
+ {
1088
+ className: "font-semibold",
1089
+ style: {
1090
+ fontSize: "var(--compass-font-size-subheading)",
1091
+ color: "var(--compass-color-text)"
1092
+ },
1093
+ children: title
1094
+ }
1095
+ ),
1096
+ /* @__PURE__ */ jsxRuntime.jsx(
1097
+ "button",
1098
+ {
1099
+ onClick: onClose,
1100
+ className: "p-1 rounded-md transition-colors hover:opacity-70",
1101
+ style: { color: "var(--compass-color-text-secondary)" },
1102
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20 })
1103
+ }
1104
+ )
1105
+ ]
1106
+ }
1107
+ ),
1108
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children })
1109
+ ]
1110
+ }
1111
+ )
1112
+ ] });
1113
+ }
1114
+ function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
1115
+ const [isExpanded, setIsExpanded] = react.useState(false);
1116
+ if (!pnl) return null;
1117
+ const unrealizedPnl = parseFloat(pnl.unrealizedPnl || "0");
1118
+ const realizedPnl = parseFloat(pnl.realizedPnl || "0");
1119
+ const totalPnl = parseFloat(pnl.totalPnl || "0");
1120
+ const totalDeposited = parseFloat(pnl.totalDeposited || "0");
1121
+ if (totalDeposited === 0) return null;
1122
+ const formatPnL = (value) => {
1123
+ const prefix = value >= 0 ? "+" : "";
1124
+ return `${prefix}${value.toFixed(4)}`;
1125
+ };
1126
+ const formatUSD = (value) => {
1127
+ const usdValue = value * tokenPrice;
1128
+ const prefix = usdValue >= 0 ? "+$" : "-$";
1129
+ return `${prefix}${Math.abs(usdValue).toFixed(2)}`;
1130
+ };
1131
+ const pnlColor = (value) => value >= 0 ? "var(--compass-color-success)" : "var(--compass-color-error)";
1132
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col w-full mt-2", children: [
1133
+ /* @__PURE__ */ jsxRuntime.jsxs(
1134
+ "button",
1135
+ {
1136
+ onClick: () => setIsExpanded(!isExpanded),
1137
+ className: "flex items-center justify-between w-full px-3 py-2 rounded-lg border transition-colors",
1138
+ style: {
1139
+ backgroundColor: "var(--compass-color-surface)",
1140
+ borderColor: "var(--compass-color-border)"
1141
+ },
1142
+ children: [
1143
+ /* @__PURE__ */ jsxRuntime.jsx(
1144
+ "span",
1145
+ {
1146
+ className: "text-sm font-medium",
1147
+ style: { color: "var(--compass-color-text-secondary)" },
1148
+ children: "Performance"
1149
+ }
1150
+ ),
1151
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1152
+ /* @__PURE__ */ jsxRuntime.jsxs(
1153
+ "span",
1154
+ {
1155
+ className: "text-xs font-mono font-medium",
1156
+ style: { color: pnlColor(totalPnl) },
1157
+ children: [
1158
+ formatPnL(totalPnl),
1159
+ " ",
1160
+ tokenSymbol
1161
+ ]
1162
+ }
1163
+ ),
1164
+ /* @__PURE__ */ jsxRuntime.jsx(
1165
+ lucideReact.ChevronDown,
1166
+ {
1167
+ size: 16,
1168
+ className: `transition-transform duration-200 ${isExpanded ? "rotate-180" : ""}`,
1169
+ style: { color: "var(--compass-color-text-tertiary)" }
1170
+ }
1171
+ )
1172
+ ] })
1173
+ ]
1174
+ }
1175
+ ),
1176
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsxs(
1177
+ "div",
1178
+ {
1179
+ className: "mt-2 p-3 rounded-lg border",
1180
+ style: {
1181
+ backgroundColor: "var(--compass-color-surface)",
1182
+ borderColor: "var(--compass-color-border)"
1183
+ },
1184
+ children: [
1185
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
1186
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1187
+ /* @__PURE__ */ jsxRuntime.jsx(
1188
+ "span",
1189
+ {
1190
+ className: "text-[10px] font-medium uppercase tracking-wide",
1191
+ style: { color: "var(--compass-color-text-tertiary)" },
1192
+ children: "Unrealized P&L"
1193
+ }
1194
+ ),
1195
+ /* @__PURE__ */ jsxRuntime.jsx(
1196
+ "span",
1197
+ {
1198
+ className: "text-sm font-bold font-mono",
1199
+ style: { color: pnlColor(unrealizedPnl) },
1200
+ children: formatPnL(unrealizedPnl)
1201
+ }
1202
+ ),
1203
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(unrealizedPnl) }, children: formatUSD(unrealizedPnl) })
1204
+ ] }),
1205
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1206
+ /* @__PURE__ */ jsxRuntime.jsx(
1207
+ "span",
1208
+ {
1209
+ className: "text-[10px] font-medium uppercase tracking-wide",
1210
+ style: { color: "var(--compass-color-text-tertiary)" },
1211
+ children: "Realized P&L"
1212
+ }
1213
+ ),
1214
+ /* @__PURE__ */ jsxRuntime.jsx(
1215
+ "span",
1216
+ {
1217
+ className: "text-sm font-bold font-mono",
1218
+ style: { color: pnlColor(realizedPnl) },
1219
+ children: formatPnL(realizedPnl)
1220
+ }
1221
+ ),
1222
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-mono", style: { color: pnlColor(realizedPnl) }, children: formatUSD(realizedPnl) })
1223
+ ] })
1224
+ ] }),
1225
+ /* @__PURE__ */ jsxRuntime.jsxs(
1226
+ "div",
1227
+ {
1228
+ className: "flex items-center justify-between mt-3 pt-3 border-t",
1229
+ style: { borderColor: "var(--compass-color-border)" },
1230
+ children: [
1231
+ /* @__PURE__ */ jsxRuntime.jsx(
1232
+ "span",
1233
+ {
1234
+ className: "text-xs font-medium",
1235
+ style: { color: "var(--compass-color-text-tertiary)" },
1236
+ children: "Total P&L"
1237
+ }
1238
+ ),
1239
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1240
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-bold font-mono", style: { color: pnlColor(totalPnl) }, children: [
1241
+ formatPnL(totalPnl),
1242
+ " ",
1243
+ tokenSymbol
1244
+ ] }),
1245
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-mono", style: { color: pnlColor(totalPnl) }, children: [
1246
+ "(",
1247
+ formatUSD(totalPnl),
1248
+ ")"
1249
+ ] })
1250
+ ] })
1251
+ ]
1252
+ }
1253
+ )
1254
+ ]
1255
+ }
1256
+ )
1257
+ ] });
1258
+ }
1259
+ var CHAINS = {
1260
+ ethereum: {
1261
+ id: "ethereum",
1262
+ name: "Ethereum",
1263
+ viemChain: chains.mainnet,
1264
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"
1265
+ },
1266
+ base: {
1267
+ id: "base",
1268
+ name: "Base",
1269
+ viemChain: chains.base,
1270
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/info/logo.png"
1271
+ },
1272
+ arbitrum: {
1273
+ id: "arbitrum",
1274
+ name: "Arbitrum",
1275
+ viemChain: chains.arbitrum,
1276
+ icon: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/arbitrum/info/logo.png"
1277
+ }
1278
+ };
1279
+ var TOKEN_DECIMALS = {
1280
+ USDC: 6,
1281
+ USDT: 6,
1282
+ DAI: 18,
1283
+ ETH: 18,
1284
+ WETH: 18,
1285
+ WBTC: 8,
1286
+ cbBTC: 8
1287
+ };
1288
+ function DepositWithdrawForm({
1289
+ venueType,
1290
+ venueAddress,
1291
+ tokenSymbol,
1292
+ tokenDecimals,
1293
+ positionBalance = "0",
1294
+ onSuccess,
1295
+ onError
1296
+ }) {
1297
+ const [activeTab, setActiveTab] = react.useState("deposit");
1298
+ const [amount, setAmount] = react.useState("");
1299
+ const [isSubmitting, setIsSubmitting] = react.useState(false);
1300
+ const [statusMessage, setStatusMessage] = react.useState("");
1301
+ const [error, setError] = react.useState(null);
1302
+ const { address, isConnected, signTypedData, switchChain } = useCompassWallet();
1303
+ const { client } = useEmbeddableApi();
1304
+ const { chainId } = useChain();
1305
+ const { earnAccountAddress } = useEarnAccount();
1306
+ const queryClient = reactQuery.useQueryClient();
1307
+ const chainConfig = CHAINS[chainId];
1308
+ const targetChainId = chainConfig?.viemChain?.id;
1309
+ const { data: tokenBalance } = reactQuery.useQuery({
1310
+ queryKey: ["earnAccountTokenBalance", chainId, earnAccountAddress, tokenSymbol],
1311
+ queryFn: async () => {
1312
+ if (!earnAccountAddress) return "0";
1313
+ try {
1314
+ const response = await client.token.tokenBalance({
1315
+ chain: chainId,
1316
+ user: earnAccountAddress,
1317
+ token: tokenSymbol
1318
+ });
1319
+ return response.amount || "0";
1320
+ } catch (error2) {
1321
+ console.error("Error fetching earn account token balance:", error2);
1322
+ return "0";
1323
+ }
1324
+ },
1325
+ enabled: !!earnAccountAddress,
1326
+ staleTime: 10 * 1e3
1327
+ });
1328
+ const availableBalance = tokenBalance || "0";
1329
+ const maxBalance = activeTab === "deposit" ? availableBalance : positionBalance;
1330
+ const handleQuickAmount = react.useCallback((percentage) => {
1331
+ const max = parseFloat(maxBalance);
1332
+ if (isNaN(max)) return;
1333
+ setAmount((max * percentage).toFixed(tokenDecimals > 6 ? 6 : tokenDecimals));
1334
+ }, [maxBalance, tokenDecimals]);
1335
+ const handleSubmit = react.useCallback(async () => {
1336
+ if (!address || !amount) return;
1337
+ setIsSubmitting(true);
1338
+ setStatusMessage("Preparing transaction...");
1339
+ setError(null);
1340
+ try {
1341
+ if (switchChain && targetChainId) {
1342
+ setStatusMessage("Checking network...");
1343
+ try {
1344
+ await switchChain(targetChainId);
1345
+ } catch {
1346
+ }
1347
+ }
1348
+ const isDeposit = activeTab === "deposit";
1349
+ const prepareEndpoint = isDeposit ? "/api/compass/deposit/prepare" : "/api/compass/withdraw/prepare";
1350
+ const executeEndpoint = isDeposit ? "/api/compass/deposit/execute" : "/api/compass/withdraw/execute";
1351
+ const prepareBody = {
1352
+ amount,
1353
+ token: tokenSymbol,
1354
+ owner: address,
1355
+ chain: chainId,
1356
+ venueType
1357
+ };
1358
+ if (venueType === "VAULT") {
1359
+ prepareBody.vaultAddress = venueAddress;
1360
+ } else if (venueType === "PENDLE_PT") {
1361
+ prepareBody.marketAddress = venueAddress;
1362
+ prepareBody.maxSlippagePercent = 1;
1363
+ }
1364
+ setStatusMessage("Getting transaction data...");
1365
+ const prepareResponse = await fetch(prepareEndpoint, {
1366
+ method: "POST",
1367
+ headers: { "Content-Type": "application/json" },
1368
+ body: JSON.stringify(prepareBody)
1369
+ });
1370
+ if (!prepareResponse.ok) {
1371
+ const errorData = await prepareResponse.json();
1372
+ throw new Error(errorData.error || "Failed to prepare transaction");
1373
+ }
1374
+ const { eip712, normalizedTypes, domain, message } = await prepareResponse.json();
1375
+ setStatusMessage("Please sign the transaction...");
1376
+ const signature = await signTypedData({
1377
+ domain,
1378
+ types: normalizedTypes,
1379
+ primaryType: "SafeTx",
1380
+ message
1381
+ });
1382
+ setStatusMessage("Executing transaction...");
1383
+ const executeResponse = await fetch(executeEndpoint, {
1384
+ method: "POST",
1385
+ headers: { "Content-Type": "application/json" },
1386
+ body: JSON.stringify({
1387
+ owner: address,
1388
+ eip712,
1389
+ signature,
1390
+ chain: chainId
1391
+ })
1392
+ });
1393
+ if (!executeResponse.ok) {
1394
+ const errorData = await executeResponse.json();
1395
+ throw new Error(errorData.error || "Failed to execute transaction");
1396
+ }
1397
+ const { txHash } = await executeResponse.json();
1398
+ setStatusMessage("Transaction successful!");
1399
+ onSuccess?.(activeTab, amount, txHash);
1400
+ setAmount("");
1401
+ queryClient.invalidateQueries({ queryKey: ["earnAccountTokenBalance"] });
1402
+ queryClient.invalidateQueries({ queryKey: ["vaults"] });
1403
+ queryClient.invalidateQueries({ queryKey: ["vaultPositions"] });
1404
+ queryClient.invalidateQueries({ queryKey: ["aaveMarkets"] });
1405
+ queryClient.invalidateQueries({ queryKey: ["aavePositions"] });
1406
+ queryClient.invalidateQueries({ queryKey: ["pendleMarkets"] });
1407
+ queryClient.invalidateQueries({ queryKey: ["pendlePositions"] });
1408
+ setTimeout(() => setStatusMessage(""), 3e3);
1409
+ setTimeout(() => {
1410
+ queryClient.invalidateQueries({ queryKey: ["earnAccountTokenBalance"] });
1411
+ queryClient.invalidateQueries({ queryKey: ["vaults"] });
1412
+ queryClient.invalidateQueries({ queryKey: ["vaultPositions"] });
1413
+ }, 5e3);
1414
+ } catch (err) {
1415
+ console.error("Transaction failed:", err);
1416
+ const errorMessage = err instanceof Error ? err.message : "Transaction failed";
1417
+ setError(errorMessage);
1418
+ onError?.(err);
1419
+ } finally {
1420
+ setIsSubmitting(false);
1421
+ }
1422
+ }, [
1423
+ address,
1424
+ amount,
1425
+ chainId,
1426
+ targetChainId,
1427
+ activeTab,
1428
+ venueType,
1429
+ venueAddress,
1430
+ tokenSymbol,
1431
+ signTypedData,
1432
+ switchChain,
1433
+ queryClient,
1434
+ onSuccess,
1435
+ onError
1436
+ ]);
1437
+ if (!isConnected) {
1438
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1439
+ "div",
1440
+ {
1441
+ className: "flex flex-col items-center gap-3 py-6 px-4 rounded-lg",
1442
+ style: {
1443
+ backgroundColor: "var(--compass-color-surface)",
1444
+ border: "1px solid var(--compass-color-border)"
1445
+ },
1446
+ children: [
1447
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 24, style: { color: "var(--compass-color-text-tertiary)" } }),
1448
+ /* @__PURE__ */ jsxRuntime.jsx(
1449
+ "p",
1450
+ {
1451
+ className: "text-sm text-center",
1452
+ style: { color: "var(--compass-color-text-secondary)" },
1453
+ children: "Connect your wallet to deposit or withdraw"
1454
+ }
1455
+ )
1456
+ ]
1457
+ }
1458
+ );
1459
+ }
1460
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
1461
+ /* @__PURE__ */ jsxRuntime.jsx(
1462
+ "div",
1463
+ {
1464
+ className: "flex gap-1 p-1 rounded-lg",
1465
+ style: { backgroundColor: "var(--compass-color-background)" },
1466
+ children: ["deposit", "withdraw"].map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
1467
+ "button",
1468
+ {
1469
+ onClick: () => {
1470
+ setActiveTab(tab);
1471
+ setError(null);
1472
+ setStatusMessage("");
1473
+ },
1474
+ className: "flex-1 py-2 rounded-md text-sm font-medium capitalize transition-all",
1475
+ style: {
1476
+ backgroundColor: activeTab === tab ? "var(--compass-color-surface)" : "transparent",
1477
+ color: activeTab === tab ? "var(--compass-color-text)" : "var(--compass-color-text-secondary)"
1478
+ },
1479
+ children: tab
1480
+ },
1481
+ tab
1482
+ ))
1483
+ }
1484
+ ),
1485
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1486
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1", children: [
1487
+ /* @__PURE__ */ jsxRuntime.jsx(
1488
+ "label",
1489
+ {
1490
+ className: "text-sm font-medium",
1491
+ style: { color: "var(--compass-color-text-secondary)" },
1492
+ children: "Amount"
1493
+ }
1494
+ ),
1495
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
1496
+ "Available: ",
1497
+ parseFloat(maxBalance).toFixed(4),
1498
+ " ",
1499
+ tokenSymbol
1500
+ ] })
1501
+ ] }),
1502
+ /* @__PURE__ */ jsxRuntime.jsxs(
1503
+ "div",
1504
+ {
1505
+ className: "flex items-center gap-2 p-3 rounded-lg border",
1506
+ style: {
1507
+ backgroundColor: "var(--compass-color-background)",
1508
+ borderColor: "var(--compass-color-border)"
1509
+ },
1510
+ children: [
1511
+ /* @__PURE__ */ jsxRuntime.jsx(
1512
+ "input",
1513
+ {
1514
+ type: "number",
1515
+ value: amount,
1516
+ onChange: (e) => {
1517
+ setAmount(e.target.value);
1518
+ setError(null);
1519
+ },
1520
+ placeholder: "0.00",
1521
+ className: "flex-1 bg-transparent outline-none text-lg font-mono",
1522
+ style: { color: "var(--compass-color-text)" }
1523
+ }
1524
+ ),
1525
+ /* @__PURE__ */ jsxRuntime.jsx(
1526
+ "span",
1527
+ {
1528
+ className: "text-sm font-medium",
1529
+ style: { color: "var(--compass-color-text-secondary)" },
1530
+ children: tokenSymbol
1531
+ }
1532
+ )
1533
+ ]
1534
+ }
1535
+ )
1536
+ ] }),
1537
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", children: [0.25, 0.5, 1].map((pct) => /* @__PURE__ */ jsxRuntime.jsx(
1538
+ "button",
1539
+ {
1540
+ onClick: () => handleQuickAmount(pct),
1541
+ className: "flex-1 py-1.5 rounded-md text-xs font-medium transition-colors",
1542
+ style: {
1543
+ backgroundColor: "var(--compass-color-secondary)",
1544
+ color: "var(--compass-color-text-secondary)"
1545
+ },
1546
+ children: pct === 1 ? "Max" : `${pct * 100}%`
1547
+ },
1548
+ pct
1549
+ )) }),
1550
+ error && /* @__PURE__ */ jsxRuntime.jsx(
1551
+ "div",
1552
+ {
1553
+ className: "p-3 rounded-lg text-sm",
1554
+ style: {
1555
+ backgroundColor: "var(--compass-color-error-muted, rgba(239, 68, 68, 0.1))",
1556
+ color: "var(--compass-color-error, #ef4444)"
1557
+ },
1558
+ children: error
1559
+ }
1560
+ ),
1561
+ statusMessage && !error && /* @__PURE__ */ jsxRuntime.jsx(
1562
+ "div",
1563
+ {
1564
+ className: "p-3 rounded-lg text-sm text-center",
1565
+ style: {
1566
+ backgroundColor: "var(--compass-color-success-muted, rgba(34, 197, 94, 0.1))",
1567
+ color: "var(--compass-color-success, #22c55e)"
1568
+ },
1569
+ children: statusMessage
1570
+ }
1571
+ ),
1572
+ /* @__PURE__ */ jsxRuntime.jsxs(
1573
+ "button",
1574
+ {
1575
+ onClick: handleSubmit,
1576
+ disabled: isSubmitting || !amount || parseFloat(amount) <= 0,
1577
+ className: "w-full py-3 rounded-lg font-medium transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
1578
+ style: {
1579
+ backgroundColor: "var(--compass-color-primary)",
1580
+ color: "var(--compass-color-primary-text)"
1581
+ },
1582
+ children: [
1583
+ isSubmitting && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 18, className: "animate-spin" }),
1584
+ isSubmitting ? "Processing..." : activeTab === "deposit" ? "Deposit" : "Withdraw"
1585
+ ]
1586
+ }
1587
+ )
1588
+ ] });
1589
+ }
1590
+ function getExplorerUrl(txHash, chainId) {
1591
+ const explorers = {
1592
+ ethereum: "https://etherscan.io/tx/",
1593
+ arbitrum: "https://arbiscan.io/tx/",
1594
+ base: "https://basescan.org/tx/"
1595
+ };
1596
+ return `${explorers[chainId] || explorers.ethereum}${txHash}`;
1597
+ }
1598
+ function TransactionHistory({
1599
+ deposits = [],
1600
+ withdrawals = [],
1601
+ tokenSymbol
1602
+ }) {
1603
+ const [isExpanded, setIsExpanded] = react.useState(false);
1604
+ const { chainId } = useChain();
1605
+ const allEvents = [
1606
+ ...deposits.map((d) => ({ type: "deposit", event: d })),
1607
+ ...withdrawals.map((w) => ({ type: "withdrawal", event: w }))
1608
+ ].sort((a, b) => b.event.blockNumber - a.event.blockNumber);
1609
+ if (allEvents.length === 0) return null;
1610
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col w-full", children: [
1611
+ /* @__PURE__ */ jsxRuntime.jsxs(
1612
+ "button",
1613
+ {
1614
+ onClick: () => setIsExpanded(!isExpanded),
1615
+ className: "flex items-center justify-between w-full px-3 py-2 rounded-lg border transition-colors",
1616
+ style: {
1617
+ backgroundColor: "var(--compass-color-surface)",
1618
+ borderColor: "var(--compass-color-border)"
1619
+ },
1620
+ children: [
1621
+ /* @__PURE__ */ jsxRuntime.jsxs(
1622
+ "span",
1623
+ {
1624
+ className: "text-sm font-medium",
1625
+ style: { color: "var(--compass-color-text-secondary)" },
1626
+ children: [
1627
+ "Transaction History (",
1628
+ allEvents.length,
1629
+ ")"
1630
+ ]
1631
+ }
1632
+ ),
1633
+ /* @__PURE__ */ jsxRuntime.jsx(
1634
+ lucideReact.ChevronDown,
1635
+ {
1636
+ size: 16,
1637
+ className: `transition-transform duration-200 ${isExpanded ? "rotate-180" : ""}`,
1638
+ style: { color: "var(--compass-color-text-tertiary)" }
1639
+ }
1640
+ )
1641
+ ]
1642
+ }
1643
+ ),
1644
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsx(
1645
+ "div",
1646
+ {
1647
+ className: "mt-2 max-h-48 overflow-y-auto rounded-lg border",
1648
+ style: { borderColor: "var(--compass-color-border)" },
1649
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: allEvents.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
1650
+ "div",
1651
+ {
1652
+ className: "flex items-center justify-between px-3 py-2",
1653
+ style: {
1654
+ backgroundColor: "var(--compass-color-surface)",
1655
+ borderTop: index > 0 ? "1px solid var(--compass-color-border)" : "none"
1656
+ },
1657
+ children: [
1658
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1659
+ item.type === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(
1660
+ "div",
1661
+ {
1662
+ className: "p-1 rounded-full",
1663
+ style: { backgroundColor: "var(--compass-color-success-muted)" },
1664
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 12, style: { color: "var(--compass-color-success)" } })
1665
+ }
1666
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1667
+ "div",
1668
+ {
1669
+ className: "p-1 rounded-full",
1670
+ style: { backgroundColor: "var(--compass-color-warning-muted)" },
1671
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { size: 12, style: { color: "var(--compass-color-warning)" } })
1672
+ }
1673
+ ),
1674
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1675
+ /* @__PURE__ */ jsxRuntime.jsx(
1676
+ "span",
1677
+ {
1678
+ className: "text-xs font-medium",
1679
+ style: { color: "var(--compass-color-text)" },
1680
+ children: item.type === "deposit" ? "Deposit" : "Withdrawal"
1681
+ }
1682
+ ),
1683
+ /* @__PURE__ */ jsxRuntime.jsxs(
1684
+ "span",
1685
+ {
1686
+ className: "text-[10px]",
1687
+ style: { color: "var(--compass-color-text-tertiary)" },
1688
+ children: [
1689
+ "Block #",
1690
+ item.event.blockNumber.toLocaleString()
1691
+ ]
1692
+ }
1693
+ )
1694
+ ] })
1695
+ ] }),
1696
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1697
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs(
1698
+ "span",
1699
+ {
1700
+ className: "text-xs font-mono font-medium",
1701
+ style: {
1702
+ color: item.type === "deposit" ? "var(--compass-color-success)" : "var(--compass-color-warning)"
1703
+ },
1704
+ children: [
1705
+ item.type === "deposit" ? "+" : "-",
1706
+ parseFloat(item.event.amount).toFixed(4),
1707
+ " ",
1708
+ tokenSymbol
1709
+ ]
1710
+ }
1711
+ ) }),
1712
+ /* @__PURE__ */ jsxRuntime.jsx(
1713
+ "a",
1714
+ {
1715
+ href: getExplorerUrl(item.event.txHash, chainId),
1716
+ target: "_blank",
1717
+ rel: "noopener noreferrer",
1718
+ className: "p-1 rounded hover:opacity-70 transition-opacity",
1719
+ title: "View on explorer",
1720
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1721
+ lucideReact.ExternalLink,
1722
+ {
1723
+ size: 12,
1724
+ style: { color: "var(--compass-color-text-tertiary)" }
1725
+ }
1726
+ )
1727
+ }
1728
+ )
1729
+ ] })
1730
+ ]
1731
+ },
1732
+ `${item.type}-${item.event.txHash}-${index}`
1733
+ )) })
1734
+ }
1735
+ )
1736
+ ] });
1737
+ }
1738
+ function EarnAccountGuard({
1739
+ children,
1740
+ loadingComponent,
1741
+ createAccountComponent
1742
+ }) {
1743
+ const { isConnected, login } = useEmbeddableWallet();
1744
+ const { isDeployed, isChecking, isCreating, createAccount, error } = useEarnAccount();
1745
+ const [createError, setCreateError] = react.useState(null);
1746
+ if (!isConnected) {
1747
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1748
+ "div",
1749
+ {
1750
+ className: "compass-earn-guard p-6 text-center rounded-xl",
1751
+ style: {
1752
+ backgroundColor: "var(--compass-color-surface)"
1753
+ },
1754
+ children: [
1755
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mb-4", style: { color: "var(--compass-color-text-secondary)" }, children: "Connect your wallet to continue" }),
1756
+ login && /* @__PURE__ */ jsxRuntime.jsx(
1757
+ "button",
1758
+ {
1759
+ onClick: login,
1760
+ className: "px-4 py-2 rounded-lg font-medium transition-colors",
1761
+ style: {
1762
+ backgroundColor: "var(--compass-color-primary)",
1763
+ color: "var(--compass-color-primary-text)"
1764
+ },
1765
+ children: "Connect Wallet"
1766
+ }
1767
+ )
1768
+ ]
1769
+ }
1770
+ );
1771
+ }
1772
+ if (isChecking) {
1773
+ if (loadingComponent) {
1774
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loadingComponent });
1775
+ }
1776
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1777
+ "div",
1778
+ {
1779
+ className: "compass-earn-guard p-6 text-center rounded-xl",
1780
+ style: { backgroundColor: "var(--compass-color-surface)" },
1781
+ children: [
1782
+ /* @__PURE__ */ jsxRuntime.jsx(
1783
+ lucideReact.Loader2,
1784
+ {
1785
+ size: 24,
1786
+ className: "animate-spin mx-auto mb-3",
1787
+ style: { color: "var(--compass-color-primary)" }
1788
+ }
1789
+ ),
1790
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: "Checking account status..." })
1791
+ ]
1792
+ }
1793
+ );
1794
+ }
1795
+ if (isDeployed) {
1796
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
1797
+ }
1798
+ if (createAccountComponent) {
1799
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: createAccountComponent });
1800
+ }
1801
+ const handleCreate = async () => {
1802
+ setCreateError(null);
1803
+ try {
1804
+ await createAccount();
1805
+ } catch (err) {
1806
+ setCreateError(err instanceof Error ? err.message : "Failed to create account");
1807
+ }
1808
+ };
1809
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1810
+ "div",
1811
+ {
1812
+ className: "compass-earn-guard p-6 text-center rounded-xl border",
1813
+ style: {
1814
+ backgroundColor: "var(--compass-color-surface)",
1815
+ borderColor: "var(--compass-color-border)"
1816
+ },
1817
+ children: [
1818
+ /* @__PURE__ */ jsxRuntime.jsx(
1819
+ "div",
1820
+ {
1821
+ className: "w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-4",
1822
+ style: { backgroundColor: "var(--compass-color-primary)", opacity: 0.15 },
1823
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1824
+ "svg",
1825
+ {
1826
+ width: "24",
1827
+ height: "24",
1828
+ viewBox: "0 0 24 24",
1829
+ fill: "none",
1830
+ stroke: "var(--compass-color-primary)",
1831
+ strokeWidth: "2",
1832
+ strokeLinecap: "round",
1833
+ strokeLinejoin: "round",
1834
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83" })
1835
+ }
1836
+ )
1837
+ }
1838
+ ),
1839
+ /* @__PURE__ */ jsxRuntime.jsx(
1840
+ "h3",
1841
+ {
1842
+ className: "text-lg font-semibold mb-2",
1843
+ style: { color: "var(--compass-color-text)" },
1844
+ children: "Create Your Earn Account"
1845
+ }
1846
+ ),
1847
+ /* @__PURE__ */ jsxRuntime.jsx(
1848
+ "p",
1849
+ {
1850
+ className: "text-sm mb-6 max-w-xs mx-auto",
1851
+ style: { color: "var(--compass-color-text-secondary)" },
1852
+ children: "To start earning, we need to create a secure smart wallet for you. This is a one-time setup with no gas fees."
1853
+ }
1854
+ ),
1855
+ (error || createError) && /* @__PURE__ */ jsxRuntime.jsx(
1856
+ "p",
1857
+ {
1858
+ className: "text-sm mb-4",
1859
+ style: { color: "var(--compass-color-error)" },
1860
+ children: createError || (error instanceof Error ? error.message : "An error occurred")
1861
+ }
1862
+ ),
1863
+ /* @__PURE__ */ jsxRuntime.jsxs(
1864
+ "button",
1865
+ {
1866
+ onClick: handleCreate,
1867
+ disabled: isCreating,
1868
+ className: "px-6 py-3 rounded-lg font-medium transition-all inline-flex items-center gap-2",
1869
+ style: {
1870
+ backgroundColor: isCreating ? "var(--compass-color-surface-hover)" : "var(--compass-color-primary)",
1871
+ color: isCreating ? "var(--compass-color-text-secondary)" : "var(--compass-color-primary-text)",
1872
+ cursor: isCreating ? "not-allowed" : "pointer"
1873
+ },
1874
+ children: [
1875
+ isCreating && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
1876
+ isCreating ? "Creating..." : "Create Account"
1877
+ ]
1878
+ }
1879
+ ),
1880
+ /* @__PURE__ */ jsxRuntime.jsx(
1881
+ "p",
1882
+ {
1883
+ className: "text-xs mt-4",
1884
+ style: { color: "var(--compass-color-text-tertiary)" },
1885
+ children: "Gas fees are sponsored by Compass"
1886
+ }
1887
+ )
1888
+ ]
1889
+ }
1890
+ );
1891
+ }
1892
+ function formatTVL(tvl) {
1893
+ if (!tvl) return "$0";
1894
+ const num = parseFloat(tvl);
1895
+ if (isNaN(num)) return "$0";
1896
+ if (num >= 1e9) return `$${(num / 1e9).toFixed(2)}B`;
1897
+ if (num >= 1e6) return `$${(num / 1e6).toFixed(2)}M`;
1898
+ if (num >= 1e3) return `$${(num / 1e3).toFixed(2)}K`;
1899
+ return `$${num.toFixed(2)}`;
1900
+ }
1901
+ function formatAPY(apy) {
1902
+ if (!apy) return "0.00%";
1903
+ const num = parseFloat(apy);
1904
+ if (isNaN(num)) return "0.00%";
1905
+ return `${num.toFixed(2)}%`;
1906
+ }
1907
+ function VaultCard({
1908
+ vault,
1909
+ showApy,
1910
+ apyPeriods,
1911
+ showTvl,
1912
+ showUserPosition,
1913
+ onClick
1914
+ }) {
1915
+ const getApyValue = (period) => {
1916
+ switch (period) {
1917
+ case "7d":
1918
+ return vault.apy7d;
1919
+ case "30d":
1920
+ return vault.apy30d;
1921
+ case "90d":
1922
+ return vault.apy90d;
1923
+ }
1924
+ };
1925
+ const primaryApy = getApyValue(apyPeriods[0] || "7d");
1926
+ const hasPosition = vault.userPosition && parseFloat(vault.userPosition.balance) > 0;
1927
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1928
+ "button",
1929
+ {
1930
+ onClick,
1931
+ className: "w-full p-4 rounded-xl border transition-all text-left hover:scale-[1.01]",
1932
+ style: {
1933
+ backgroundColor: "var(--compass-color-surface)",
1934
+ borderColor: hasPosition ? "var(--compass-color-primary)" : "var(--compass-color-border)"
1935
+ },
1936
+ children: [
1937
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
1938
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
1939
+ /* @__PURE__ */ jsxRuntime.jsx(
1940
+ "h3",
1941
+ {
1942
+ className: "font-semibold",
1943
+ style: {
1944
+ fontSize: "var(--compass-font-size-body)",
1945
+ color: "var(--compass-color-text)"
1946
+ },
1947
+ children: vault.name
1948
+ }
1949
+ ),
1950
+ /* @__PURE__ */ jsxRuntime.jsx(
1951
+ "span",
1952
+ {
1953
+ className: "text-sm",
1954
+ style: { color: "var(--compass-color-text-secondary)" },
1955
+ children: vault.assetSymbol
1956
+ }
1957
+ )
1958
+ ] }),
1959
+ showApy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
1960
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { size: 14, style: { color: "var(--compass-color-success)" } }),
1961
+ /* @__PURE__ */ jsxRuntime.jsx(
1962
+ "span",
1963
+ {
1964
+ className: "font-mono font-semibold",
1965
+ style: { color: "var(--compass-color-success)" },
1966
+ children: formatAPY(primaryApy)
1967
+ }
1968
+ )
1969
+ ] })
1970
+ ] }),
1971
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mt-3 pt-3 border-t", style: { borderColor: "var(--compass-color-border)" }, children: [
1972
+ showTvl && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1973
+ /* @__PURE__ */ jsxRuntime.jsx(
1974
+ "span",
1975
+ {
1976
+ className: "text-xs",
1977
+ style: { color: "var(--compass-color-text-tertiary)" },
1978
+ children: "TVL"
1979
+ }
1980
+ ),
1981
+ /* @__PURE__ */ jsxRuntime.jsx(
1982
+ "span",
1983
+ {
1984
+ className: "font-mono text-sm",
1985
+ style: { color: "var(--compass-color-text-secondary)" },
1986
+ children: formatTVL(vault.tvlUsd)
1987
+ }
1988
+ )
1989
+ ] }),
1990
+ showUserPosition && hasPosition && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
1991
+ /* @__PURE__ */ jsxRuntime.jsx(
1992
+ "span",
1993
+ {
1994
+ className: "text-xs",
1995
+ style: { color: "var(--compass-color-text-tertiary)" },
1996
+ children: "Your Position"
1997
+ }
1998
+ ),
1999
+ /* @__PURE__ */ jsxRuntime.jsxs(
2000
+ "span",
2001
+ {
2002
+ className: "font-mono text-sm font-medium",
2003
+ style: { color: "var(--compass-color-primary)" },
2004
+ children: [
2005
+ parseFloat(vault.userPosition.balance).toFixed(4),
2006
+ " ",
2007
+ vault.assetSymbol
2008
+ ]
2009
+ }
2010
+ )
2011
+ ] })
2012
+ ] })
2013
+ ]
2014
+ }
2015
+ );
2016
+ }
2017
+ function useVaultsData(options = {}) {
2018
+ const { client } = useEmbeddableApi();
2019
+ const { address } = useEmbeddableWallet();
2020
+ const { chainId } = useChain();
2021
+ const { sortBy = "apy_7d", assetFilter, minApy } = options;
2022
+ const vaultsQuery = reactQuery.useQuery({
2023
+ queryKey: ["vaults", chainId, sortBy, assetFilter, minApy],
2024
+ queryFn: async () => {
2025
+ const assetSymbol = assetFilter && assetFilter.length === 1 ? assetFilter[0] : void 0;
2026
+ const response = await client.earn.earnVaults({
2027
+ chain: chainId,
2028
+ orderBy: sortBy === "tvl" ? "tvl_usd" : sortBy,
2029
+ direction: "desc",
2030
+ limit: 100,
2031
+ ...assetSymbol && { assetSymbol }
2032
+ });
2033
+ let vaults = (response.vaults || []).map((v) => ({
2034
+ vaultAddress: v.vaultAddress,
2035
+ name: v.name || "Unknown Vault",
2036
+ assetSymbol: v.assetSymbol || "UNKNOWN",
2037
+ apy7d: v.apy7d ?? null,
2038
+ apy30d: v.apy30d ?? null,
2039
+ apy90d: v.apy90d ?? null,
2040
+ tvlUsd: v.tvlUsd ?? null
2041
+ }));
2042
+ if (assetFilter && assetFilter.length > 1) {
2043
+ vaults = vaults.filter(
2044
+ (v) => assetFilter.includes(v.assetSymbol.toUpperCase())
2045
+ );
2046
+ }
2047
+ if (minApy !== void 0 && minApy > 0) {
2048
+ vaults = vaults.filter((v) => {
2049
+ const apy = parseFloat(v.apy7d || "0");
2050
+ return apy >= minApy;
2051
+ });
2052
+ }
2053
+ return vaults;
2054
+ },
2055
+ staleTime: 30 * 1e3
2056
+ });
2057
+ const positionsQuery = reactQuery.useQuery({
2058
+ queryKey: ["vaultPositions", chainId, address],
2059
+ queryFn: async () => {
2060
+ if (!address) return [];
2061
+ const response = await client.earn.earnPositions({
2062
+ chain: chainId,
2063
+ owner: address
2064
+ });
2065
+ return (response.vaults || []).map((p) => ({
2066
+ vaultAddress: p.vaultAddress,
2067
+ balance: p.balance || "0",
2068
+ pnl: p.pnl ? {
2069
+ unrealizedPnl: p.pnl.unrealizedPnl || "0",
2070
+ realizedPnl: p.pnl.realizedPnl || "0",
2071
+ totalPnl: p.pnl.totalPnl || "0",
2072
+ totalDeposited: p.pnl.totalDeposited || "0"
2073
+ } : void 0,
2074
+ deposits: (p.deposits || []).map((d) => ({
2075
+ amount: d.inputAmount || d.amount || "0",
2076
+ blockNumber: d.blockNumber || 0,
2077
+ txHash: d.transactionHash || d.txHash || ""
2078
+ })),
2079
+ withdrawals: (p.withdrawals || []).map((w) => ({
2080
+ amount: w.outputAmount || w.amount || "0",
2081
+ blockNumber: w.blockNumber || 0,
2082
+ txHash: w.transactionHash || w.txHash || ""
2083
+ }))
2084
+ }));
2085
+ },
2086
+ enabled: !!address,
2087
+ staleTime: 30 * 1e3
2088
+ });
2089
+ const vaultsWithPositions = (vaultsQuery.data || []).map((vault) => {
2090
+ const position = positionsQuery.data?.find(
2091
+ (p) => p.vaultAddress.toLowerCase() === vault.vaultAddress.toLowerCase()
2092
+ );
2093
+ return { ...vault, userPosition: position };
2094
+ });
2095
+ return {
2096
+ vaults: vaultsWithPositions,
2097
+ isLoading: vaultsQuery.isLoading,
2098
+ isError: vaultsQuery.isError,
2099
+ error: vaultsQuery.error,
2100
+ refetch: () => {
2101
+ vaultsQuery.refetch();
2102
+ positionsQuery.refetch();
2103
+ }
2104
+ };
2105
+ }
2106
+ var TOKEN_DECIMALS2 = {
2107
+ USDC: 6,
2108
+ USDT: 6,
2109
+ DAI: 18,
2110
+ ETH: 18,
2111
+ WETH: 18,
2112
+ WBTC: 8,
2113
+ cbBTC: 8
2114
+ };
2115
+ function VaultsList({
2116
+ showApy = true,
2117
+ apyPeriods = ["7d", "30d", "90d"],
2118
+ showTvl = true,
2119
+ showUserPosition = true,
2120
+ showPnL = true,
2121
+ showHistory = true,
2122
+ showSearch = true,
2123
+ showSort = true,
2124
+ actionMode = "modal",
2125
+ defaultSort = "apy_7d",
2126
+ assetFilter,
2127
+ minApy,
2128
+ onVaultSelect,
2129
+ onDeposit,
2130
+ onWithdraw
2131
+ }) {
2132
+ const [searchQuery, setSearchQuery] = react.useState("");
2133
+ const [sortBy, setSortBy] = react.useState(defaultSort);
2134
+ const [selectedVault, setSelectedVault] = react.useState(null);
2135
+ const { vaults, isLoading, isError, refetch } = useVaultsData({
2136
+ sortBy,
2137
+ assetFilter,
2138
+ minApy
2139
+ });
2140
+ const filteredVaults = react.useMemo(() => {
2141
+ if (!searchQuery) return vaults;
2142
+ const query = searchQuery.toLowerCase();
2143
+ return vaults.filter(
2144
+ (v) => v.name.toLowerCase().includes(query) || v.assetSymbol.toLowerCase().includes(query)
2145
+ );
2146
+ }, [vaults, searchQuery]);
2147
+ const handleVaultClick = (vault) => {
2148
+ setSelectedVault(vault);
2149
+ onVaultSelect?.(vault);
2150
+ };
2151
+ const handleActionSuccess = (action, amount, txHash) => {
2152
+ if (action === "deposit") {
2153
+ onDeposit?.(selectedVault, amount, txHash);
2154
+ } else {
2155
+ onWithdraw?.(selectedVault, amount, txHash);
2156
+ }
2157
+ refetch();
2158
+ };
2159
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
2160
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
2161
+ /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
2162
+ /* @__PURE__ */ jsxRuntime.jsx(WalletStatus, { compact: true })
2163
+ ] }),
2164
+ (showSearch || showSort) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
2165
+ showSearch && /* @__PURE__ */ jsxRuntime.jsxs(
2166
+ "div",
2167
+ {
2168
+ className: "flex-1 flex items-center gap-2 px-3 py-2 rounded-lg border",
2169
+ style: {
2170
+ backgroundColor: "var(--compass-color-background)",
2171
+ borderColor: "var(--compass-color-border)"
2172
+ },
2173
+ children: [
2174
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { size: 16, style: { color: "var(--compass-color-text-tertiary)" } }),
2175
+ /* @__PURE__ */ jsxRuntime.jsx(
2176
+ "input",
2177
+ {
2178
+ type: "text",
2179
+ placeholder: "Search vaults...",
2180
+ value: searchQuery,
2181
+ onChange: (e) => setSearchQuery(e.target.value),
2182
+ className: "flex-1 bg-transparent outline-none text-sm",
2183
+ style: { color: "var(--compass-color-text)" }
2184
+ }
2185
+ )
2186
+ ]
2187
+ }
2188
+ ),
2189
+ showSort && /* @__PURE__ */ jsxRuntime.jsxs(
2190
+ "select",
2191
+ {
2192
+ value: sortBy,
2193
+ onChange: (e) => setSortBy(e.target.value),
2194
+ className: "px-3 py-2 rounded-lg border text-sm cursor-pointer",
2195
+ style: {
2196
+ backgroundColor: "var(--compass-color-background)",
2197
+ borderColor: "var(--compass-color-border)",
2198
+ color: "var(--compass-color-text)"
2199
+ },
2200
+ children: [
2201
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "apy_7d", children: "APY (7D)" }),
2202
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "apy_30d", children: "APY (30D)" }),
2203
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "apy_90d", children: "APY (90D)" }),
2204
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "tvl", children: "TVL" })
2205
+ ]
2206
+ }
2207
+ )
2208
+ ] }),
2209
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 24, className: "animate-spin", style: { color: "var(--compass-color-primary)" } }) }) : isError ? /* @__PURE__ */ jsxRuntime.jsx(
2210
+ "div",
2211
+ {
2212
+ className: "p-4 rounded-lg text-center",
2213
+ style: {
2214
+ backgroundColor: "var(--compass-color-error-muted)",
2215
+ color: "var(--compass-color-error)"
2216
+ },
2217
+ children: "Failed to load vaults. Please try again."
2218
+ }
2219
+ ) : filteredVaults.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2220
+ "div",
2221
+ {
2222
+ className: "p-8 text-center",
2223
+ style: { color: "var(--compass-color-text-secondary)" },
2224
+ children: "No vaults found"
2225
+ }
2226
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: filteredVaults.map((vault) => /* @__PURE__ */ jsxRuntime.jsx(
2227
+ VaultCard,
2228
+ {
2229
+ vault,
2230
+ showApy,
2231
+ apyPeriods,
2232
+ showTvl,
2233
+ showUserPosition,
2234
+ onClick: () => handleVaultClick(vault)
2235
+ },
2236
+ vault.vaultAddress
2237
+ )) }),
2238
+ actionMode === "modal" && selectedVault && /* @__PURE__ */ jsxRuntime.jsx(
2239
+ ActionModal,
2240
+ {
2241
+ isOpen: !!selectedVault,
2242
+ onClose: () => setSelectedVault(null),
2243
+ title: selectedVault.name,
2244
+ children: /* @__PURE__ */ jsxRuntime.jsx(EarnAccountGuard, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
2245
+ showPnL && selectedVault.userPosition?.pnl && /* @__PURE__ */ jsxRuntime.jsx(
2246
+ PnLSummary,
2247
+ {
2248
+ pnl: selectedVault.userPosition.pnl,
2249
+ tokenSymbol: selectedVault.assetSymbol,
2250
+ tokenPrice: 1
2251
+ }
2252
+ ),
2253
+ showHistory && (selectedVault.userPosition?.deposits?.length || selectedVault.userPosition?.withdrawals?.length) && /* @__PURE__ */ jsxRuntime.jsx(
2254
+ TransactionHistory,
2255
+ {
2256
+ deposits: selectedVault.userPosition?.deposits,
2257
+ withdrawals: selectedVault.userPosition?.withdrawals,
2258
+ tokenSymbol: selectedVault.assetSymbol
2259
+ }
2260
+ ),
2261
+ /* @__PURE__ */ jsxRuntime.jsx(
2262
+ DepositWithdrawForm,
2263
+ {
2264
+ venueType: "VAULT",
2265
+ venueAddress: selectedVault.vaultAddress,
2266
+ tokenSymbol: selectedVault.assetSymbol,
2267
+ tokenDecimals: TOKEN_DECIMALS2[selectedVault.assetSymbol] || 18,
2268
+ positionBalance: selectedVault.userPosition?.balance,
2269
+ onSuccess: handleActionSuccess
2270
+ }
2271
+ )
2272
+ ] }) })
2273
+ }
2274
+ )
2275
+ ] });
2276
+ }
2277
+ function useAaveData(options = {}) {
2278
+ const { client } = useEmbeddableApi();
2279
+ const { address } = useEmbeddableWallet();
2280
+ const { chainId } = useChain();
2281
+ const { sortBy = "supply_apy", assetFilter } = options;
2282
+ const marketsQuery = reactQuery.useQuery({
2283
+ queryKey: ["aaveMarkets", chainId, sortBy, assetFilter],
2284
+ queryFn: async () => {
2285
+ const response = await client.earn.earnAaveMarkets({
2286
+ chain: chainId
2287
+ });
2288
+ const marketsDict = response.markets || {};
2289
+ let markets = [];
2290
+ for (const [symbol, tokenData] of Object.entries(marketsDict)) {
2291
+ if (assetFilter && assetFilter.length > 0) {
2292
+ if (!assetFilter.includes(symbol.toUpperCase())) {
2293
+ continue;
2294
+ }
2295
+ }
2296
+ const token = tokenData;
2297
+ const chainData = token.chains?.[chainId];
2298
+ if (chainData) {
2299
+ markets.push({
2300
+ marketAddress: chainData.address || "",
2301
+ reserveSymbol: symbol,
2302
+ underlyingSymbol: symbol,
2303
+ supplyApy: chainData.supplyApy?.toString() ?? null,
2304
+ borrowApy: chainData.borrowApy?.toString() ?? null,
2305
+ // Aave API doesn't provide TVL
2306
+ tvlUsd: null
2307
+ });
2308
+ }
2309
+ }
2310
+ markets.sort((a, b) => {
2311
+ return parseFloat(b.supplyApy || "0") - parseFloat(a.supplyApy || "0");
2312
+ });
2313
+ return markets;
2314
+ },
2315
+ staleTime: 30 * 1e3
2316
+ });
2317
+ const positionsQuery = reactQuery.useQuery({
2318
+ queryKey: ["aavePositions", chainId, address],
2319
+ queryFn: async () => {
2320
+ if (!address) return [];
2321
+ const response = await client.earn.earnPositions({
2322
+ chain: chainId,
2323
+ owner: address
2324
+ });
2325
+ return (response.aave || []).map((p) => ({
2326
+ marketAddress: p.marketAddress || "",
2327
+ reserveSymbol: p.reserveSymbol || "",
2328
+ balance: p.balance || "0",
2329
+ pnl: p.pnl ? {
2330
+ unrealizedPnl: p.pnl.unrealizedPnl || "0",
2331
+ realizedPnl: p.pnl.realizedPnl || "0",
2332
+ totalPnl: p.pnl.totalPnl || "0",
2333
+ totalDeposited: p.pnl.totalDeposited || "0"
2334
+ } : void 0,
2335
+ deposits: (p.deposits || []).map((d) => ({
2336
+ amount: d.inputAmount || d.amount || "0",
2337
+ blockNumber: d.blockNumber || 0,
2338
+ txHash: d.transactionHash || d.txHash || ""
2339
+ })),
2340
+ withdrawals: (p.withdrawals || []).map((w) => ({
2341
+ amount: w.outputAmount || w.amount || "0",
2342
+ blockNumber: w.blockNumber || 0,
2343
+ txHash: w.transactionHash || w.txHash || ""
2344
+ }))
2345
+ }));
2346
+ },
2347
+ enabled: !!address,
2348
+ staleTime: 30 * 1e3
2349
+ });
2350
+ const marketsWithPositions = (marketsQuery.data || []).map((market) => {
2351
+ const position = positionsQuery.data?.find(
2352
+ (p) => p.reserveSymbol.toLowerCase() === market.reserveSymbol.toLowerCase()
2353
+ );
2354
+ return { ...market, userPosition: position };
2355
+ });
2356
+ return {
2357
+ markets: marketsWithPositions,
2358
+ isLoading: marketsQuery.isLoading,
2359
+ isError: marketsQuery.isError,
2360
+ error: marketsQuery.error,
2361
+ refetch: () => {
2362
+ marketsQuery.refetch();
2363
+ positionsQuery.refetch();
2364
+ }
2365
+ };
2366
+ }
2367
+ var TOKEN_DECIMALS3 = {
2368
+ USDC: 6,
2369
+ USDT: 6,
2370
+ DAI: 18,
2371
+ ETH: 18,
2372
+ WETH: 18,
2373
+ WBTC: 8,
2374
+ cbBTC: 8
2375
+ };
2376
+ function formatAPY2(apy) {
2377
+ if (!apy) return "0.00%";
2378
+ const num = parseFloat(apy);
2379
+ return `${num.toFixed(2)}%`;
2380
+ }
2381
+ function formatTVL2(tvl) {
2382
+ if (!tvl) return "$0";
2383
+ const num = parseFloat(tvl);
2384
+ if (num >= 1e9) return `$${(num / 1e9).toFixed(2)}B`;
2385
+ if (num >= 1e6) return `$${(num / 1e6).toFixed(2)}M`;
2386
+ if (num >= 1e3) return `$${(num / 1e3).toFixed(2)}K`;
2387
+ return `$${num.toFixed(2)}`;
2388
+ }
2389
+ function AaveMarketsList({
2390
+ showApy = true,
2391
+ showTvl = false,
2392
+ // Aave API doesn't provide TVL data
2393
+ showUserPosition = true,
2394
+ showPnL = true,
2395
+ showHistory = true,
2396
+ showSearch = true,
2397
+ showSort = false,
2398
+ // Only one sort option (APY), so hide by default
2399
+ actionMode = "modal",
2400
+ defaultSort = "supply_apy",
2401
+ assetFilter,
2402
+ onMarketSelect,
2403
+ onSupply,
2404
+ onWithdraw
2405
+ }) {
2406
+ const [searchQuery, setSearchQuery] = react.useState("");
2407
+ const [sortBy, setSortBy] = react.useState(defaultSort);
2408
+ const [selectedMarket, setSelectedMarket] = react.useState(null);
2409
+ const { markets, isLoading, isError, refetch } = useAaveData({ sortBy, assetFilter });
2410
+ const filteredMarkets = react.useMemo(() => {
2411
+ if (!searchQuery) return markets;
2412
+ const query = searchQuery.toLowerCase();
2413
+ return markets.filter(
2414
+ (m) => m.reserveSymbol.toLowerCase().includes(query) || m.underlyingSymbol.toLowerCase().includes(query)
2415
+ );
2416
+ }, [markets, searchQuery]);
2417
+ const handleMarketClick = (market) => {
2418
+ setSelectedMarket(market);
2419
+ onMarketSelect?.(market);
2420
+ };
2421
+ const handleActionSuccess = (action, amount, txHash) => {
2422
+ if (action === "deposit") {
2423
+ onSupply?.(selectedMarket, amount, txHash);
2424
+ } else {
2425
+ onWithdraw?.(selectedMarket, amount, txHash);
2426
+ }
2427
+ refetch();
2428
+ };
2429
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
2430
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
2431
+ /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
2432
+ /* @__PURE__ */ jsxRuntime.jsx(WalletStatus, { compact: true })
2433
+ ] }),
2434
+ (showSearch || showSort) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
2435
+ showSearch && /* @__PURE__ */ jsxRuntime.jsxs(
2436
+ "div",
2437
+ {
2438
+ className: "flex-1 flex items-center gap-2 px-3 py-2 rounded-lg border",
2439
+ style: {
2440
+ backgroundColor: "var(--compass-color-background)",
2441
+ borderColor: "var(--compass-color-border)"
2442
+ },
2443
+ children: [
2444
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { size: 16, style: { color: "var(--compass-color-text-tertiary)" } }),
2445
+ /* @__PURE__ */ jsxRuntime.jsx(
2446
+ "input",
2447
+ {
2448
+ type: "text",
2449
+ placeholder: "Search markets...",
2450
+ value: searchQuery,
2451
+ onChange: (e) => setSearchQuery(e.target.value),
2452
+ className: "flex-1 bg-transparent outline-none text-sm",
2453
+ style: { color: "var(--compass-color-text)" }
2454
+ }
2455
+ )
2456
+ ]
2457
+ }
2458
+ ),
2459
+ showSort && /* @__PURE__ */ jsxRuntime.jsx(
2460
+ "select",
2461
+ {
2462
+ value: sortBy,
2463
+ onChange: (e) => setSortBy(e.target.value),
2464
+ className: "px-3 py-2 rounded-lg border text-sm cursor-pointer",
2465
+ style: {
2466
+ backgroundColor: "var(--compass-color-background)",
2467
+ borderColor: "var(--compass-color-border)",
2468
+ color: "var(--compass-color-text)"
2469
+ },
2470
+ children: /* @__PURE__ */ jsxRuntime.jsx("option", { value: "supply_apy", children: "Supply APY" })
2471
+ }
2472
+ )
2473
+ ] }),
2474
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 24, className: "animate-spin", style: { color: "var(--compass-color-primary)" } }) }) : isError ? /* @__PURE__ */ jsxRuntime.jsx(
2475
+ "div",
2476
+ {
2477
+ className: "p-4 rounded-lg text-center",
2478
+ style: {
2479
+ backgroundColor: "var(--compass-color-error-muted)",
2480
+ color: "var(--compass-color-error)"
2481
+ },
2482
+ children: "Failed to load Aave markets. Please try again."
2483
+ }
2484
+ ) : filteredMarkets.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2485
+ "div",
2486
+ {
2487
+ className: "p-8 text-center",
2488
+ style: { color: "var(--compass-color-text-secondary)" },
2489
+ children: "No markets found"
2490
+ }
2491
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: filteredMarkets.map((market) => {
2492
+ const hasPosition = market.userPosition && parseFloat(market.userPosition.balance) > 0;
2493
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2494
+ "button",
2495
+ {
2496
+ onClick: () => handleMarketClick(market),
2497
+ className: "w-full p-4 rounded-xl border transition-all text-left hover:scale-[1.01]",
2498
+ style: {
2499
+ backgroundColor: "var(--compass-color-surface)",
2500
+ borderColor: hasPosition ? "var(--compass-color-primary)" : "var(--compass-color-border)"
2501
+ },
2502
+ children: [
2503
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
2504
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
2505
+ /* @__PURE__ */ jsxRuntime.jsx(
2506
+ "h3",
2507
+ {
2508
+ className: "font-semibold",
2509
+ style: {
2510
+ fontSize: "var(--compass-font-size-body)",
2511
+ color: "var(--compass-color-text)"
2512
+ },
2513
+ children: market.underlyingSymbol
2514
+ }
2515
+ ),
2516
+ /* @__PURE__ */ jsxRuntime.jsx(
2517
+ "span",
2518
+ {
2519
+ className: "text-sm",
2520
+ style: { color: "var(--compass-color-text-secondary)" },
2521
+ children: "Aave V3"
2522
+ }
2523
+ )
2524
+ ] }),
2525
+ showApy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2526
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { size: 14, style: { color: "var(--compass-color-success)" } }),
2527
+ /* @__PURE__ */ jsxRuntime.jsx(
2528
+ "span",
2529
+ {
2530
+ className: "font-mono font-semibold",
2531
+ style: { color: "var(--compass-color-success)" },
2532
+ children: formatAPY2(market.supplyApy)
2533
+ }
2534
+ )
2535
+ ] })
2536
+ ] }),
2537
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mt-3 pt-3 border-t", style: { borderColor: "var(--compass-color-border)" }, children: [
2538
+ showTvl && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
2539
+ /* @__PURE__ */ jsxRuntime.jsx(
2540
+ "span",
2541
+ {
2542
+ className: "text-xs",
2543
+ style: { color: "var(--compass-color-text-tertiary)" },
2544
+ children: "TVL"
2545
+ }
2546
+ ),
2547
+ /* @__PURE__ */ jsxRuntime.jsx(
2548
+ "span",
2549
+ {
2550
+ className: "font-mono text-sm",
2551
+ style: { color: "var(--compass-color-text-secondary)" },
2552
+ children: formatTVL2(market.tvlUsd)
2553
+ }
2554
+ )
2555
+ ] }),
2556
+ showUserPosition && hasPosition && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
2557
+ /* @__PURE__ */ jsxRuntime.jsx(
2558
+ "span",
2559
+ {
2560
+ className: "text-xs",
2561
+ style: { color: "var(--compass-color-text-tertiary)" },
2562
+ children: "Your Position"
2563
+ }
2564
+ ),
2565
+ /* @__PURE__ */ jsxRuntime.jsxs(
2566
+ "span",
2567
+ {
2568
+ className: "font-mono text-sm font-medium",
2569
+ style: { color: "var(--compass-color-primary)" },
2570
+ children: [
2571
+ parseFloat(market.userPosition.balance).toFixed(4),
2572
+ " ",
2573
+ market.underlyingSymbol
2574
+ ]
2575
+ }
2576
+ )
2577
+ ] })
2578
+ ] })
2579
+ ]
2580
+ },
2581
+ market.marketAddress
2582
+ );
2583
+ }) }),
2584
+ actionMode === "modal" && selectedMarket && /* @__PURE__ */ jsxRuntime.jsx(
2585
+ ActionModal,
2586
+ {
2587
+ isOpen: !!selectedMarket,
2588
+ onClose: () => setSelectedMarket(null),
2589
+ title: `${selectedMarket.underlyingSymbol} - Aave`,
2590
+ children: /* @__PURE__ */ jsxRuntime.jsx(EarnAccountGuard, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
2591
+ showPnL && selectedMarket.userPosition?.pnl && /* @__PURE__ */ jsxRuntime.jsx(
2592
+ PnLSummary,
2593
+ {
2594
+ pnl: selectedMarket.userPosition.pnl,
2595
+ tokenSymbol: selectedMarket.underlyingSymbol,
2596
+ tokenPrice: 1
2597
+ }
2598
+ ),
2599
+ showHistory && (selectedMarket.userPosition?.deposits?.length || selectedMarket.userPosition?.withdrawals?.length) && /* @__PURE__ */ jsxRuntime.jsx(
2600
+ TransactionHistory,
2601
+ {
2602
+ deposits: selectedMarket.userPosition?.deposits,
2603
+ withdrawals: selectedMarket.userPosition?.withdrawals,
2604
+ tokenSymbol: selectedMarket.underlyingSymbol
2605
+ }
2606
+ ),
2607
+ /* @__PURE__ */ jsxRuntime.jsx(
2608
+ DepositWithdrawForm,
2609
+ {
2610
+ venueType: "AAVE",
2611
+ venueAddress: selectedMarket.marketAddress,
2612
+ tokenSymbol: selectedMarket.underlyingSymbol,
2613
+ tokenDecimals: TOKEN_DECIMALS3[selectedMarket.underlyingSymbol] || 18,
2614
+ positionBalance: selectedMarket.userPosition?.balance,
2615
+ onSuccess: handleActionSuccess
2616
+ }
2617
+ )
2618
+ ] }) })
2619
+ }
2620
+ )
2621
+ ] });
2622
+ }
2623
+ function usePendleData(options = {}) {
2624
+ const { client } = useEmbeddableApi();
2625
+ const { address } = useEmbeddableWallet();
2626
+ const { chainId } = useChain();
2627
+ const { sortBy = "fixed_apy", assetFilter } = options;
2628
+ const marketsQuery = reactQuery.useQuery({
2629
+ queryKey: ["pendleMarkets", chainId, sortBy, assetFilter],
2630
+ queryFn: async () => {
2631
+ const underlyingSymbol = assetFilter && assetFilter.length === 1 ? assetFilter[0] : void 0;
2632
+ const orderBy = sortBy === "tvl" ? "tvl_usd" : "implied_apy";
2633
+ const response = await client.earn.earnPendleMarkets({
2634
+ chain: chainId,
2635
+ orderBy,
2636
+ direction: "desc",
2637
+ limit: 100,
2638
+ ...underlyingSymbol && { underlyingSymbol }
2639
+ });
2640
+ const now = Date.now() / 1e3;
2641
+ let markets = (response.markets || []).filter((m) => m.expiry && m.expiry > now).map((m) => ({
2642
+ marketAddress: m.marketAddress || "",
2643
+ ptAddress: m.ptAddress || "",
2644
+ name: m.ptName || `PT-${m.underlyingSymbol || "UNKNOWN"}`,
2645
+ underlyingSymbol: m.underlyingSymbol || "UNKNOWN",
2646
+ // Use impliedApy as the main APY (this is what wallet-earn displays)
2647
+ fixedApy: m.impliedApy?.toString() ?? null,
2648
+ impliedApy: m.impliedApy?.toString() ?? null,
2649
+ tvlUsd: m.tvlUsd?.toString() ?? null,
2650
+ // Convert Unix timestamp to ISO string for display
2651
+ expiry: new Date(m.expiry * 1e3).toISOString()
2652
+ }));
2653
+ if (assetFilter && assetFilter.length > 1) {
2654
+ markets = markets.filter(
2655
+ (m) => assetFilter.includes(m.underlyingSymbol.toUpperCase())
2656
+ );
2657
+ }
2658
+ if (sortBy === "expiry") {
2659
+ markets.sort((a, b) => {
2660
+ return new Date(a.expiry).getTime() - new Date(b.expiry).getTime();
2661
+ });
2662
+ }
2663
+ return markets;
2664
+ },
2665
+ staleTime: 30 * 1e3
2666
+ });
2667
+ const positionsQuery = reactQuery.useQuery({
2668
+ queryKey: ["pendlePositions", chainId, address],
2669
+ queryFn: async () => {
2670
+ if (!address) return [];
2671
+ const response = await client.earn.earnPositions({
2672
+ chain: chainId,
2673
+ owner: address
2674
+ });
2675
+ return (response.pendlePt || []).map((p) => ({
2676
+ marketAddress: p.marketAddress || "",
2677
+ balance: p.balance || "0",
2678
+ pnl: p.pnl ? {
2679
+ unrealizedPnl: p.pnl.unrealizedPnl || "0",
2680
+ realizedPnl: p.pnl.realizedPnl || "0",
2681
+ totalPnl: p.pnl.totalPnl || "0",
2682
+ totalDeposited: p.pnl.totalDeposited || "0"
2683
+ } : void 0,
2684
+ deposits: (p.deposits || []).map((d) => ({
2685
+ amount: d.inputAmount || d.amount || "0",
2686
+ blockNumber: d.blockNumber || 0,
2687
+ txHash: d.transactionHash || d.txHash || ""
2688
+ })),
2689
+ withdrawals: (p.withdrawals || []).map((w) => ({
2690
+ amount: w.outputAmount || w.amount || "0",
2691
+ blockNumber: w.blockNumber || 0,
2692
+ txHash: w.transactionHash || w.txHash || ""
2693
+ }))
2694
+ }));
2695
+ },
2696
+ enabled: !!address,
2697
+ staleTime: 30 * 1e3
2698
+ });
2699
+ const marketsWithPositions = (marketsQuery.data || []).map((market) => {
2700
+ const position = positionsQuery.data?.find(
2701
+ (p) => p.marketAddress.toLowerCase() === market.marketAddress.toLowerCase()
2702
+ );
2703
+ return { ...market, userPosition: position };
2704
+ });
2705
+ return {
2706
+ markets: marketsWithPositions,
2707
+ isLoading: marketsQuery.isLoading,
2708
+ isError: marketsQuery.isError,
2709
+ error: marketsQuery.error,
2710
+ refetch: () => {
2711
+ marketsQuery.refetch();
2712
+ positionsQuery.refetch();
2713
+ }
2714
+ };
2715
+ }
2716
+ var TOKEN_DECIMALS4 = {
2717
+ USDC: 6,
2718
+ USDT: 6,
2719
+ DAI: 18,
2720
+ ETH: 18,
2721
+ WETH: 18,
2722
+ WBTC: 8,
2723
+ cbBTC: 8
2724
+ };
2725
+ function formatAPY3(apy) {
2726
+ if (!apy) return "0.00%";
2727
+ return `${parseFloat(apy).toFixed(2)}%`;
2728
+ }
2729
+ function formatExpiry(expiry) {
2730
+ const date = new Date(expiry);
2731
+ return date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
2732
+ }
2733
+ function formatTVL3(tvl) {
2734
+ if (!tvl) return "$0";
2735
+ const num = parseFloat(tvl);
2736
+ if (num >= 1e9) return `$${(num / 1e9).toFixed(2)}B`;
2737
+ if (num >= 1e6) return `$${(num / 1e6).toFixed(2)}M`;
2738
+ if (num >= 1e3) return `$${(num / 1e3).toFixed(2)}K`;
2739
+ return `$${num.toFixed(2)}`;
2740
+ }
2741
+ function PendleMarketsList({
2742
+ showApy = true,
2743
+ showTvl = true,
2744
+ showExpiry = true,
2745
+ showUserPosition = true,
2746
+ showPnL = true,
2747
+ showHistory = true,
2748
+ showSearch = true,
2749
+ showSort = true,
2750
+ actionMode = "modal",
2751
+ defaultSort = "fixed_apy",
2752
+ assetFilter,
2753
+ onMarketSelect,
2754
+ onDeposit,
2755
+ onWithdraw
2756
+ }) {
2757
+ const [searchQuery, setSearchQuery] = react.useState("");
2758
+ const [sortBy, setSortBy] = react.useState(defaultSort);
2759
+ const [selectedMarket, setSelectedMarket] = react.useState(null);
2760
+ const { markets, isLoading, isError, refetch } = usePendleData({ sortBy, assetFilter });
2761
+ const filteredMarkets = react.useMemo(() => {
2762
+ if (!searchQuery) return markets;
2763
+ const query = searchQuery.toLowerCase();
2764
+ return markets.filter(
2765
+ (m) => m.name.toLowerCase().includes(query) || m.underlyingSymbol.toLowerCase().includes(query)
2766
+ );
2767
+ }, [markets, searchQuery]);
2768
+ const handleMarketClick = (market) => {
2769
+ setSelectedMarket(market);
2770
+ onMarketSelect?.(market);
2771
+ };
2772
+ const handleActionSuccess = (action, amount, txHash) => {
2773
+ if (action === "deposit") {
2774
+ onDeposit?.(selectedMarket, amount, txHash);
2775
+ } else {
2776
+ onWithdraw?.(selectedMarket, amount, txHash);
2777
+ }
2778
+ refetch();
2779
+ };
2780
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
2781
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
2782
+ /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
2783
+ /* @__PURE__ */ jsxRuntime.jsx(WalletStatus, { compact: true })
2784
+ ] }),
2785
+ (showSearch || showSort) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
2786
+ showSearch && /* @__PURE__ */ jsxRuntime.jsxs(
2787
+ "div",
2788
+ {
2789
+ className: "flex-1 flex items-center gap-2 px-3 py-2 rounded-lg border",
2790
+ style: {
2791
+ backgroundColor: "var(--compass-color-background)",
2792
+ borderColor: "var(--compass-color-border)"
2793
+ },
2794
+ children: [
2795
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { size: 16, style: { color: "var(--compass-color-text-tertiary)" } }),
2796
+ /* @__PURE__ */ jsxRuntime.jsx(
2797
+ "input",
2798
+ {
2799
+ type: "text",
2800
+ placeholder: "Search markets...",
2801
+ value: searchQuery,
2802
+ onChange: (e) => setSearchQuery(e.target.value),
2803
+ className: "flex-1 bg-transparent outline-none text-sm",
2804
+ style: { color: "var(--compass-color-text)" }
2805
+ }
2806
+ )
2807
+ ]
2808
+ }
2809
+ ),
2810
+ showSort && /* @__PURE__ */ jsxRuntime.jsxs(
2811
+ "select",
2812
+ {
2813
+ value: sortBy,
2814
+ onChange: (e) => setSortBy(e.target.value),
2815
+ className: "px-3 py-2 rounded-lg border text-sm cursor-pointer",
2816
+ style: {
2817
+ backgroundColor: "var(--compass-color-background)",
2818
+ borderColor: "var(--compass-color-border)",
2819
+ color: "var(--compass-color-text)"
2820
+ },
2821
+ children: [
2822
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "fixed_apy", children: "Fixed APY" }),
2823
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "tvl", children: "TVL" }),
2824
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "expiry", children: "Expiry" })
2825
+ ]
2826
+ }
2827
+ )
2828
+ ] }),
2829
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 24, className: "animate-spin", style: { color: "var(--compass-color-primary)" } }) }) : isError ? /* @__PURE__ */ jsxRuntime.jsx(
2830
+ "div",
2831
+ {
2832
+ className: "p-4 rounded-lg text-center",
2833
+ style: {
2834
+ backgroundColor: "var(--compass-color-error-muted)",
2835
+ color: "var(--compass-color-error)"
2836
+ },
2837
+ children: "Failed to load Pendle markets. Please try again."
2838
+ }
2839
+ ) : filteredMarkets.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2840
+ "div",
2841
+ {
2842
+ className: "p-8 text-center",
2843
+ style: { color: "var(--compass-color-text-secondary)" },
2844
+ children: "No active markets found"
2845
+ }
2846
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: filteredMarkets.map((market) => {
2847
+ const hasPosition = market.userPosition && parseFloat(market.userPosition.balance) > 0;
2848
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2849
+ "button",
2850
+ {
2851
+ onClick: () => handleMarketClick(market),
2852
+ className: "w-full p-4 rounded-xl border transition-all text-left hover:scale-[1.01]",
2853
+ style: {
2854
+ backgroundColor: "var(--compass-color-surface)",
2855
+ borderColor: hasPosition ? "var(--compass-color-primary)" : "var(--compass-color-border)"
2856
+ },
2857
+ children: [
2858
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
2859
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
2860
+ /* @__PURE__ */ jsxRuntime.jsx(
2861
+ "h3",
2862
+ {
2863
+ className: "font-semibold",
2864
+ style: {
2865
+ fontSize: "var(--compass-font-size-body)",
2866
+ color: "var(--compass-color-text)"
2867
+ },
2868
+ children: market.name
2869
+ }
2870
+ ),
2871
+ /* @__PURE__ */ jsxRuntime.jsx(
2872
+ "span",
2873
+ {
2874
+ className: "text-sm",
2875
+ style: { color: "var(--compass-color-text-secondary)" },
2876
+ children: market.underlyingSymbol
2877
+ }
2878
+ )
2879
+ ] }),
2880
+ showApy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2881
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { size: 14, style: { color: "var(--compass-color-success)" } }),
2882
+ /* @__PURE__ */ jsxRuntime.jsx(
2883
+ "span",
2884
+ {
2885
+ className: "font-mono font-semibold",
2886
+ style: { color: "var(--compass-color-success)" },
2887
+ children: formatAPY3(market.fixedApy)
2888
+ }
2889
+ )
2890
+ ] })
2891
+ ] }),
2892
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mt-3 pt-3 border-t", style: { borderColor: "var(--compass-color-border)" }, children: [
2893
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
2894
+ showTvl && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
2895
+ /* @__PURE__ */ jsxRuntime.jsx(
2896
+ "span",
2897
+ {
2898
+ className: "text-xs",
2899
+ style: { color: "var(--compass-color-text-tertiary)" },
2900
+ children: "TVL"
2901
+ }
2902
+ ),
2903
+ /* @__PURE__ */ jsxRuntime.jsx(
2904
+ "span",
2905
+ {
2906
+ className: "font-mono text-sm",
2907
+ style: { color: "var(--compass-color-text-secondary)" },
2908
+ children: formatTVL3(market.tvlUsd)
2909
+ }
2910
+ )
2911
+ ] }),
2912
+ showExpiry && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
2913
+ /* @__PURE__ */ jsxRuntime.jsx(
2914
+ "span",
2915
+ {
2916
+ className: "text-xs",
2917
+ style: { color: "var(--compass-color-text-tertiary)" },
2918
+ children: "Expiry"
2919
+ }
2920
+ ),
2921
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2922
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 12, style: { color: "var(--compass-color-text-secondary)" } }),
2923
+ /* @__PURE__ */ jsxRuntime.jsx(
2924
+ "span",
2925
+ {
2926
+ className: "font-mono text-sm",
2927
+ style: { color: "var(--compass-color-text-secondary)" },
2928
+ children: formatExpiry(market.expiry)
2929
+ }
2930
+ )
2931
+ ] })
2932
+ ] })
2933
+ ] }),
2934
+ showUserPosition && hasPosition && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
2935
+ /* @__PURE__ */ jsxRuntime.jsx(
2936
+ "span",
2937
+ {
2938
+ className: "text-xs",
2939
+ style: { color: "var(--compass-color-text-tertiary)" },
2940
+ children: "Your Position"
2941
+ }
2942
+ ),
2943
+ /* @__PURE__ */ jsxRuntime.jsxs(
2944
+ "span",
2945
+ {
2946
+ className: "font-mono text-sm font-medium",
2947
+ style: { color: "var(--compass-color-primary)" },
2948
+ children: [
2949
+ parseFloat(market.userPosition.balance).toFixed(4),
2950
+ " PT"
2951
+ ]
2952
+ }
2953
+ )
2954
+ ] })
2955
+ ] })
2956
+ ]
2957
+ },
2958
+ market.marketAddress
2959
+ );
2960
+ }) }),
2961
+ actionMode === "modal" && selectedMarket && /* @__PURE__ */ jsxRuntime.jsx(
2962
+ ActionModal,
2963
+ {
2964
+ isOpen: !!selectedMarket,
2965
+ onClose: () => setSelectedMarket(null),
2966
+ title: selectedMarket.name,
2967
+ children: /* @__PURE__ */ jsxRuntime.jsx(EarnAccountGuard, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
2968
+ showPnL && selectedMarket.userPosition?.pnl && /* @__PURE__ */ jsxRuntime.jsx(
2969
+ PnLSummary,
2970
+ {
2971
+ pnl: selectedMarket.userPosition.pnl,
2972
+ tokenSymbol: selectedMarket.underlyingSymbol,
2973
+ tokenPrice: 1
2974
+ }
2975
+ ),
2976
+ showHistory && (selectedMarket.userPosition?.deposits?.length || selectedMarket.userPosition?.withdrawals?.length) && /* @__PURE__ */ jsxRuntime.jsx(
2977
+ TransactionHistory,
2978
+ {
2979
+ deposits: selectedMarket.userPosition?.deposits,
2980
+ withdrawals: selectedMarket.userPosition?.withdrawals,
2981
+ tokenSymbol: selectedMarket.underlyingSymbol
2982
+ }
2983
+ ),
2984
+ /* @__PURE__ */ jsxRuntime.jsx(
2985
+ DepositWithdrawForm,
2986
+ {
2987
+ venueType: "PENDLE_PT",
2988
+ venueAddress: selectedMarket.marketAddress,
2989
+ tokenSymbol: selectedMarket.underlyingSymbol,
2990
+ tokenDecimals: TOKEN_DECIMALS4[selectedMarket.underlyingSymbol] || 18,
2991
+ positionBalance: selectedMarket.userPosition?.balance,
2992
+ onSuccess: handleActionSuccess
2993
+ }
2994
+ )
2995
+ ] }) })
2996
+ }
2997
+ )
2998
+ ] });
2999
+ }
3000
+ function useSwapQuote({ fromToken, toToken, amount, enabled = true }) {
3001
+ const { client } = useEmbeddableApi();
3002
+ const { chainId } = useChain();
3003
+ const query = reactQuery.useQuery({
3004
+ queryKey: ["swapQuote", chainId, fromToken, toToken, amount],
3005
+ queryFn: async () => {
3006
+ if (!fromToken || !toToken || !amount || parseFloat(amount) <= 0) {
3007
+ return null;
3008
+ }
3009
+ try {
3010
+ const estimatedRate = 1;
3011
+ const outputAmount = (parseFloat(amount) * estimatedRate).toString();
3012
+ return {
3013
+ inputAmount: amount,
3014
+ outputAmount,
3015
+ rate: estimatedRate.toString(),
3016
+ priceImpact: "0",
3017
+ fee: "0"
3018
+ };
3019
+ } catch (error) {
3020
+ console.error("Failed to get swap quote:", error);
3021
+ return null;
3022
+ }
3023
+ },
3024
+ enabled: enabled && !!fromToken && !!toToken && !!amount && parseFloat(amount) > 0,
3025
+ staleTime: 10 * 1e3,
3026
+ // 10 seconds - quotes change frequently
3027
+ refetchInterval: 15 * 1e3
3028
+ // Refresh every 15 seconds
3029
+ });
3030
+ return {
3031
+ quote: query.data,
3032
+ isLoading: query.isLoading,
3033
+ isError: query.isError,
3034
+ refetch: query.refetch
3035
+ };
3036
+ }
3037
+ var DEFAULT_TOKENS = ["USDC", "ETH", "WETH", "WBTC", "DAI", "USDT"];
3038
+ function SwapWidget({
3039
+ layout = "full",
3040
+ defaultFromToken = "ETH",
3041
+ defaultToToken = "USDC",
3042
+ allowedTokens = DEFAULT_TOKENS,
3043
+ showReverseButton = true,
3044
+ showSettings = false,
3045
+ showPriceImpact = true,
3046
+ onSwapSuccess,
3047
+ onSwapError
3048
+ }) {
3049
+ const [fromToken, setFromToken] = react.useState(defaultFromToken);
3050
+ const [toToken, setToToken] = react.useState(defaultToToken);
3051
+ const [fromAmount, setFromAmount] = react.useState("");
3052
+ const [isSwapping, setIsSwapping] = react.useState(false);
3053
+ const { address, isConnected } = useCompassWallet();
3054
+ const { client } = useEmbeddableApi();
3055
+ const { chainId } = useChain();
3056
+ const { quote, isLoading: isQuoteLoading } = useSwapQuote({
3057
+ fromToken,
3058
+ toToken,
3059
+ amount: fromAmount,
3060
+ enabled: !!fromAmount && parseFloat(fromAmount) > 0
3061
+ });
3062
+ const handleReverse = react.useCallback(() => {
3063
+ setFromToken(toToken);
3064
+ setToToken(fromToken);
3065
+ setFromAmount("");
3066
+ }, [fromToken, toToken]);
3067
+ const handleSwap = react.useCallback(async () => {
3068
+ if (!address || !fromAmount || !quote) return;
3069
+ setIsSwapping(true);
3070
+ try {
3071
+ const response = await client.earn.earnSwap({
3072
+ chain: chainId,
3073
+ sender: address,
3074
+ tokenIn: fromToken,
3075
+ tokenOut: toToken,
3076
+ humanReadableAmountIn: fromAmount
3077
+ });
3078
+ console.log("Swap prepared:", response);
3079
+ onSwapSuccess?.(fromToken, toToken, fromAmount, quote.outputAmount, "pending");
3080
+ setFromAmount("");
3081
+ } catch (error) {
3082
+ console.error("Swap failed:", error);
3083
+ onSwapError?.(error);
3084
+ } finally {
3085
+ setIsSwapping(false);
3086
+ }
3087
+ }, [address, fromAmount, quote, client, chainId, fromToken, toToken, onSwapSuccess, onSwapError]);
3088
+ const isCompact = layout === "compact";
3089
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
3090
+ !isCompact && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
3091
+ /* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
3092
+ /* @__PURE__ */ jsxRuntime.jsx(WalletStatus, { compact: true })
3093
+ ] }),
3094
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
3095
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 rounded-xl border", style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)" }, children: [
3096
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "From" }) }),
3097
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
3098
+ /* @__PURE__ */ jsxRuntime.jsx(
3099
+ "input",
3100
+ {
3101
+ type: "number",
3102
+ value: fromAmount,
3103
+ onChange: (e) => setFromAmount(e.target.value),
3104
+ placeholder: "0.00",
3105
+ className: "flex-1 bg-transparent outline-none text-2xl font-mono",
3106
+ style: { color: "var(--compass-color-text)" }
3107
+ }
3108
+ ),
3109
+ /* @__PURE__ */ jsxRuntime.jsx(
3110
+ "select",
3111
+ {
3112
+ value: fromToken,
3113
+ onChange: (e) => setFromToken(e.target.value),
3114
+ className: "px-3 py-2 rounded-lg border text-sm font-medium cursor-pointer",
3115
+ style: { backgroundColor: "var(--compass-color-background)", borderColor: "var(--compass-color-border)", color: "var(--compass-color-text)" },
3116
+ children: allowedTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: token, children: token }, token))
3117
+ }
3118
+ )
3119
+ ] })
3120
+ ] }),
3121
+ showReverseButton && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center -my-1 relative z-10", children: /* @__PURE__ */ jsxRuntime.jsx(
3122
+ "button",
3123
+ {
3124
+ onClick: handleReverse,
3125
+ className: "p-2 rounded-full border transition-colors hover:opacity-80",
3126
+ style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)" },
3127
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownUp, { size: 16, style: { color: "var(--compass-color-text-secondary)" } })
3128
+ }
3129
+ ) }),
3130
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 rounded-xl border", style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)" }, children: [
3131
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "To" }) }),
3132
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
3133
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 text-2xl font-mono", style: { color: isQuoteLoading ? "var(--compass-color-text-tertiary)" : "var(--compass-color-text)" }, children: isQuoteLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
3134
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
3135
+ "Loading..."
3136
+ ] }) : quote?.outputAmount ? parseFloat(quote.outputAmount).toFixed(6) : "0.00" }),
3137
+ /* @__PURE__ */ jsxRuntime.jsx(
3138
+ "select",
3139
+ {
3140
+ value: toToken,
3141
+ onChange: (e) => setToToken(e.target.value),
3142
+ className: "px-3 py-2 rounded-lg border text-sm font-medium cursor-pointer",
3143
+ style: { backgroundColor: "var(--compass-color-background)", borderColor: "var(--compass-color-border)", color: "var(--compass-color-text)" },
3144
+ children: allowedTokens.filter((t) => t !== fromToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: token, children: token }, token))
3145
+ }
3146
+ )
3147
+ ] })
3148
+ ] })
3149
+ ] }),
3150
+ showPriceImpact && quote && parseFloat(quote.priceImpact) > 0.01 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 p-3 rounded-lg", style: { backgroundColor: "var(--compass-color-warning-muted)" }, children: [
3151
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 16, style: { color: "var(--compass-color-warning)" } }),
3152
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm", style: { color: "var(--compass-color-warning)" }, children: [
3153
+ "Price impact: ",
3154
+ (parseFloat(quote.priceImpact) * 100).toFixed(2),
3155
+ "%"
3156
+ ] })
3157
+ ] }),
3158
+ quote && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: [
3159
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rate" }),
3160
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
3161
+ "1 ",
3162
+ fromToken,
3163
+ " = ",
3164
+ parseFloat(quote.rate).toFixed(6),
3165
+ " ",
3166
+ toToken
3167
+ ] })
3168
+ ] }),
3169
+ !isConnected ? /* @__PURE__ */ jsxRuntime.jsxs(
3170
+ "div",
3171
+ {
3172
+ className: "flex flex-col items-center gap-3 py-6 px-4 rounded-lg",
3173
+ style: {
3174
+ backgroundColor: "var(--compass-color-surface)",
3175
+ border: "1px solid var(--compass-color-border)"
3176
+ },
3177
+ children: [
3178
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 24, style: { color: "var(--compass-color-text-tertiary)" } }),
3179
+ /* @__PURE__ */ jsxRuntime.jsx(
3180
+ "p",
3181
+ {
3182
+ className: "text-sm text-center",
3183
+ style: { color: "var(--compass-color-text-secondary)" },
3184
+ children: "Connect your wallet to swap"
3185
+ }
3186
+ )
3187
+ ]
3188
+ }
3189
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
3190
+ "button",
3191
+ {
3192
+ onClick: handleSwap,
3193
+ disabled: isSwapping || !quote || !fromAmount || parseFloat(fromAmount) <= 0,
3194
+ className: "w-full py-3 rounded-lg font-medium transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
3195
+ style: { backgroundColor: "var(--compass-color-primary)", color: "var(--compass-color-primary-text)" },
3196
+ children: [
3197
+ isSwapping && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 18, className: "animate-spin" }),
3198
+ isSwapping ? "Swapping..." : "Swap"
3199
+ ]
3200
+ }
3201
+ )
3202
+ ] });
3203
+ }
3204
+
3205
+ // src/components/CompassEarnWidget/presets.ts
3206
+ var allTabs = [
3207
+ { id: "vaults", label: "Vaults", enabled: true },
3208
+ { id: "aave", label: "Aave", enabled: true },
3209
+ { id: "pendle", label: "Pendle", enabled: true },
3210
+ { id: "swap", label: "Swap", enabled: true }
3211
+ ];
3212
+ function getTabsForPreset(preset) {
3213
+ switch (preset) {
3214
+ case "full":
3215
+ return allTabs;
3216
+ case "earn-only":
3217
+ return allTabs.map((tab) => ({
3218
+ ...tab,
3219
+ enabled: tab.id !== "swap"
3220
+ }));
3221
+ case "swap-only":
3222
+ return allTabs.map((tab) => ({
3223
+ ...tab,
3224
+ enabled: tab.id === "swap"
3225
+ }));
3226
+ case "vaults-only":
3227
+ return allTabs.map((tab) => ({
3228
+ ...tab,
3229
+ enabled: tab.id === "vaults"
3230
+ }));
3231
+ default:
3232
+ return allTabs;
3233
+ }
3234
+ }
3235
+ function getDefaultTab(tabs) {
3236
+ const enabledTab = tabs.find((t) => t.enabled);
3237
+ return enabledTab?.id || "vaults";
3238
+ }
3239
+ function CompassEarnWidget({
3240
+ preset = "full",
3241
+ enableVaults,
3242
+ enableAave,
3243
+ enablePendle,
3244
+ enableSwap,
3245
+ defaultTab,
3246
+ showHeader = true,
3247
+ onTabChange
3248
+ }) {
3249
+ const tabs = react.useMemo(() => {
3250
+ const baseTabs = getTabsForPreset(preset);
3251
+ return baseTabs.map((tab) => {
3252
+ let enabled = tab.enabled;
3253
+ if (tab.id === "vaults" && enableVaults !== void 0) enabled = enableVaults;
3254
+ if (tab.id === "aave" && enableAave !== void 0) enabled = enableAave;
3255
+ if (tab.id === "pendle" && enablePendle !== void 0) enabled = enablePendle;
3256
+ if (tab.id === "swap" && enableSwap !== void 0) enabled = enableSwap;
3257
+ return { ...tab, enabled };
3258
+ });
3259
+ }, [preset, enableVaults, enableAave, enablePendle, enableSwap]);
3260
+ const enabledTabs = tabs.filter((t) => t.enabled);
3261
+ const initialTab = defaultTab && tabs.find((t) => t.id === defaultTab)?.enabled ? defaultTab : getDefaultTab(tabs);
3262
+ const [activeTab, setActiveTab] = react.useState(initialTab);
3263
+ const handleTabChange = (tab) => {
3264
+ setActiveTab(tab);
3265
+ onTabChange?.(tab);
3266
+ };
3267
+ const showTabs = enabledTabs.length > 1;
3268
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
3269
+ showHeader && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "font-bold text-xl", style: { color: "var(--compass-color-text)" }, children: "Compass Earn" }),
3270
+ showTabs && /* @__PURE__ */ jsxRuntime.jsx(
3271
+ "div",
3272
+ {
3273
+ className: "flex gap-1 p-1 rounded-lg",
3274
+ style: { backgroundColor: "var(--compass-color-surface)" },
3275
+ children: enabledTabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
3276
+ "button",
3277
+ {
3278
+ onClick: () => handleTabChange(tab.id),
3279
+ className: "flex-1 py-2 px-3 rounded-md text-sm font-medium transition-all",
3280
+ style: {
3281
+ backgroundColor: activeTab === tab.id ? "var(--compass-color-primary)" : "transparent",
3282
+ color: activeTab === tab.id ? "var(--compass-color-primary-text)" : "var(--compass-color-text-secondary)"
3283
+ },
3284
+ children: tab.label
3285
+ },
3286
+ tab.id
3287
+ ))
3288
+ }
3289
+ ),
3290
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3291
+ activeTab === "vaults" && tabs.find((t) => t.id === "vaults")?.enabled && /* @__PURE__ */ jsxRuntime.jsx(VaultsList, { showSearch: true, showSort: true }),
3292
+ activeTab === "aave" && tabs.find((t) => t.id === "aave")?.enabled && /* @__PURE__ */ jsxRuntime.jsx(AaveMarketsList, { showSearch: true, showSort: true }),
3293
+ activeTab === "pendle" && tabs.find((t) => t.id === "pendle")?.enabled && /* @__PURE__ */ jsxRuntime.jsx(PendleMarketsList, { showSearch: true, showSort: true }),
3294
+ activeTab === "swap" && tabs.find((t) => t.id === "swap")?.enabled && /* @__PURE__ */ jsxRuntime.jsx(SwapWidget, { layout: "full" })
3295
+ ] })
3296
+ ] });
3297
+ }
3298
+
3299
+ exports.AaveMarketsList = AaveMarketsList;
3300
+ exports.ActionModal = ActionModal;
3301
+ exports.ApiProvider = ApiProvider;
3302
+ exports.CHAINS = CHAINS;
3303
+ exports.ChainSwitcher = ChainSwitcher;
3304
+ exports.CompassEarnWidget = CompassEarnWidget;
3305
+ exports.CompassProvider = CompassProvider;
3306
+ exports.DepositWithdrawForm = DepositWithdrawForm;
3307
+ exports.EarnAccountGuard = EarnAccountGuard;
3308
+ exports.PendleMarketsList = PendleMarketsList;
3309
+ exports.PnLSummary = PnLSummary;
3310
+ exports.SwapWidget = SwapWidget;
3311
+ exports.TOKEN_DECIMALS = TOKEN_DECIMALS;
3312
+ exports.ThemeProvider = ThemeProvider;
3313
+ exports.TransactionHistory = TransactionHistory;
3314
+ exports.VaultsList = VaultsList;
3315
+ exports.WalletStatus = WalletStatus;
3316
+ exports.themePresets = themePresets;
3317
+ exports.useAaveData = useAaveData;
3318
+ exports.useChain = useChain;
3319
+ exports.useCompassApi = useCompassApi;
3320
+ exports.useCompassChain = useCompassChain;
3321
+ exports.useCompassWallet = useCompassWallet;
3322
+ exports.useEarnAccount = useEarnAccount;
3323
+ exports.useEmbeddableApi = useEmbeddableApi;
3324
+ exports.useEmbeddableWallet = useEmbeddableWallet;
3325
+ exports.usePendleData = usePendleData;
3326
+ exports.useSwapQuote = useSwapQuote;
3327
+ exports.useTheme = useTheme;
3328
+ exports.useVaultsData = useVaultsData;
3329
+ //# sourceMappingURL=index.js.map
3330
+ //# sourceMappingURL=index.js.map