@compass-labs/widgets 0.1.31 → 0.1.33
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.d.mts +42 -58
- package/dist/index.d.ts +42 -58
- package/dist/index.js +861 -725
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +862 -725
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +19 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +19 -3
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1111,68 +1111,75 @@ function ActionModal({ isOpen, onClose, title, children }) {
|
|
|
1111
1111
|
};
|
|
1112
1112
|
}, [isOpen, onClose]);
|
|
1113
1113
|
if (!isOpen) return null;
|
|
1114
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1114
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1115
|
+
"div",
|
|
1116
|
+
{
|
|
1117
|
+
className: "fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
1118
|
+
style: { overflowY: "auto", scrollbarWidth: "none" },
|
|
1119
|
+
children: [
|
|
1120
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1121
|
+
"div",
|
|
1122
|
+
{
|
|
1123
|
+
className: "absolute inset-0",
|
|
1124
|
+
style: { backgroundColor: "var(--compass-color-overlay)" },
|
|
1125
|
+
onClick: onClose
|
|
1126
|
+
}
|
|
1127
|
+
),
|
|
1128
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1129
|
+
"div",
|
|
1130
|
+
{
|
|
1131
|
+
className: "relative w-full max-w-md",
|
|
1132
|
+
style: {
|
|
1133
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
1134
|
+
boxShadow: "var(--compass-shadow-lg)",
|
|
1135
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
1136
|
+
fontFamily: "var(--compass-font-family)"
|
|
1137
|
+
},
|
|
1138
|
+
children: [
|
|
1139
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1140
|
+
"div",
|
|
1141
|
+
{
|
|
1142
|
+
className: "flex items-center justify-between border-b",
|
|
1143
|
+
style: {
|
|
1144
|
+
borderColor: "var(--compass-color-border)",
|
|
1145
|
+
padding: "calc(var(--compass-spacing-card) * 0.75) var(--compass-spacing-card)"
|
|
1146
|
+
},
|
|
1147
|
+
children: [
|
|
1148
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1149
|
+
"h2",
|
|
1150
|
+
{
|
|
1151
|
+
className: "font-semibold",
|
|
1152
|
+
style: {
|
|
1153
|
+
fontSize: "var(--compass-font-size-subheading)",
|
|
1154
|
+
color: "var(--compass-color-text)"
|
|
1155
|
+
},
|
|
1156
|
+
children: title
|
|
1157
|
+
}
|
|
1158
|
+
),
|
|
1159
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1160
|
+
"button",
|
|
1161
|
+
{
|
|
1162
|
+
onClick: onClose,
|
|
1163
|
+
className: "hover:opacity-70",
|
|
1164
|
+
style: {
|
|
1165
|
+
color: "var(--compass-color-text-secondary)",
|
|
1166
|
+
borderRadius: "var(--compass-border-radius-md)",
|
|
1167
|
+
padding: "calc(var(--compass-spacing-unit) * 0.25)",
|
|
1168
|
+
transition: "var(--compass-transition-normal)"
|
|
1169
|
+
},
|
|
1170
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20 })
|
|
1171
|
+
}
|
|
1172
|
+
)
|
|
1173
|
+
]
|
|
1174
|
+
}
|
|
1175
|
+
),
|
|
1176
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "var(--compass-spacing-card)" }, children })
|
|
1177
|
+
]
|
|
1178
|
+
}
|
|
1179
|
+
)
|
|
1180
|
+
]
|
|
1181
|
+
}
|
|
1182
|
+
);
|
|
1176
1183
|
}
|
|
1177
1184
|
function PnLSummary({ pnl, tokenSymbol, tokenPrice }) {
|
|
1178
1185
|
const [isExpanded, setIsExpanded] = react.useState(false);
|
|
@@ -2232,227 +2239,84 @@ function AccountBalancesModal({
|
|
|
2232
2239
|
onClose,
|
|
2233
2240
|
balances,
|
|
2234
2241
|
totalUsdValue,
|
|
2235
|
-
isLoading = false
|
|
2236
|
-
earnAccountAddress
|
|
2242
|
+
isLoading = false
|
|
2237
2243
|
}) {
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
document.body.style.overflow = "hidden";
|
|
2244
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ActionModal, { isOpen, onClose, title: "Balance Breakdown", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2245
|
+
lucideReact.Loader2,
|
|
2246
|
+
{
|
|
2247
|
+
size: 24,
|
|
2248
|
+
className: "animate-spin",
|
|
2249
|
+
style: { color: "var(--compass-color-primary)" }
|
|
2245
2250
|
}
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2251
|
+
) }) : balances.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2252
|
+
"div",
|
|
2253
|
+
{
|
|
2254
|
+
className: "text-center py-4",
|
|
2255
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2256
|
+
children: "No tokens in account"
|
|
2257
|
+
}
|
|
2258
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2259
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2260
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2261
|
+
"span",
|
|
2262
|
+
{
|
|
2263
|
+
className: "text-xs font-medium uppercase tracking-wide",
|
|
2264
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2265
|
+
children: "Available in Account"
|
|
2266
|
+
}
|
|
2267
|
+
),
|
|
2268
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2269
|
+
"div",
|
|
2270
|
+
{
|
|
2271
|
+
className: "flex flex-col gap-2",
|
|
2272
|
+
style: {
|
|
2273
|
+
maxHeight: "50vh",
|
|
2274
|
+
overflowY: "auto",
|
|
2275
|
+
scrollbarWidth: "none"
|
|
2276
|
+
},
|
|
2277
|
+
children: balances.map((token) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2273
2278
|
"div",
|
|
2274
2279
|
{
|
|
2275
|
-
className: "flex items-center justify-between
|
|
2280
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
2276
2281
|
style: {
|
|
2277
|
-
|
|
2278
|
-
|
|
2282
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2283
|
+
border: "1px solid var(--compass-color-border)",
|
|
2284
|
+
flexShrink: 0
|
|
2279
2285
|
},
|
|
2280
2286
|
children: [
|
|
2281
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2282
|
-
|
|
2283
|
-
{
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
fontSize: "var(--compass-font-size-subheading)",
|
|
2287
|
-
color: "var(--compass-color-text)"
|
|
2288
|
-
},
|
|
2289
|
-
children: [
|
|
2290
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Coins, { size: 20 }),
|
|
2291
|
-
"Account Balances"
|
|
2292
|
-
]
|
|
2293
|
-
}
|
|
2294
|
-
),
|
|
2295
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2296
|
-
"button",
|
|
2297
|
-
{
|
|
2298
|
-
onClick: onClose,
|
|
2299
|
-
className: "hover:opacity-70",
|
|
2300
|
-
style: {
|
|
2301
|
-
color: "var(--compass-color-text-secondary)",
|
|
2302
|
-
borderRadius: "var(--compass-border-radius-md)",
|
|
2303
|
-
padding: "calc(var(--compass-spacing-unit) * 0.25)",
|
|
2304
|
-
transition: "var(--compass-transition-normal)"
|
|
2305
|
-
},
|
|
2306
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20 })
|
|
2307
|
-
}
|
|
2308
|
-
)
|
|
2287
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: token.symbol }),
|
|
2288
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
|
|
2289
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount(token.balance) }),
|
|
2290
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatUSD(token.usdValue) })
|
|
2291
|
+
] })
|
|
2309
2292
|
]
|
|
2293
|
+
},
|
|
2294
|
+
token.symbol
|
|
2295
|
+
))
|
|
2296
|
+
}
|
|
2297
|
+
)
|
|
2298
|
+
] }),
|
|
2299
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2300
|
+
"div",
|
|
2301
|
+
{
|
|
2302
|
+
className: "flex items-center justify-between pt-3 mt-2",
|
|
2303
|
+
style: { borderTop: "2px solid var(--compass-color-border)" },
|
|
2304
|
+
children: [
|
|
2305
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
|
|
2306
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2307
|
+
"span",
|
|
2308
|
+
{
|
|
2309
|
+
className: "font-bold text-xl",
|
|
2310
|
+
style: { color: "var(--compass-color-text)" },
|
|
2311
|
+
children: formatUSD(totalUsdValue)
|
|
2310
2312
|
}
|
|
2311
|
-
)
|
|
2312
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "var(--compass-spacing-card)" }, children: [
|
|
2313
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", style: { padding: "calc(var(--compass-spacing-unit) * 2) 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2314
|
-
lucideReact.Loader2,
|
|
2315
|
-
{
|
|
2316
|
-
size: 24,
|
|
2317
|
-
className: "animate-spin",
|
|
2318
|
-
style: { color: "var(--compass-color-primary)" }
|
|
2319
|
-
}
|
|
2320
|
-
) }) : balances.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2321
|
-
"div",
|
|
2322
|
-
{
|
|
2323
|
-
className: "text-center",
|
|
2324
|
-
style: { color: "var(--compass-color-text-secondary)", padding: "calc(var(--compass-spacing-unit) * 2) 0" },
|
|
2325
|
-
children: "No token balances found"
|
|
2326
|
-
}
|
|
2327
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
2328
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2329
|
-
"div",
|
|
2330
|
-
{
|
|
2331
|
-
className: "flex items-center justify-between border",
|
|
2332
|
-
style: {
|
|
2333
|
-
borderColor: "var(--compass-color-border)",
|
|
2334
|
-
backgroundColor: "var(--compass-color-surface)",
|
|
2335
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
2336
|
-
padding: "calc(var(--compass-spacing-unit) * 1)",
|
|
2337
|
-
marginBottom: "calc(var(--compass-spacing-unit) * 0.5)"
|
|
2338
|
-
},
|
|
2339
|
-
children: [
|
|
2340
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2341
|
-
"span",
|
|
2342
|
-
{
|
|
2343
|
-
className: "font-medium",
|
|
2344
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
2345
|
-
children: "Total Balance"
|
|
2346
|
-
}
|
|
2347
|
-
),
|
|
2348
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2349
|
-
"span",
|
|
2350
|
-
{
|
|
2351
|
-
className: "font-bold text-xl",
|
|
2352
|
-
style: { color: "var(--compass-color-text)" },
|
|
2353
|
-
children: formatUSD(totalUsdValue)
|
|
2354
|
-
}
|
|
2355
|
-
)
|
|
2356
|
-
]
|
|
2357
|
-
}
|
|
2358
|
-
),
|
|
2359
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2360
|
-
"div",
|
|
2361
|
-
{
|
|
2362
|
-
className: "text-xs font-medium uppercase tracking-wide",
|
|
2363
|
-
style: {
|
|
2364
|
-
color: "var(--compass-color-text-tertiary)",
|
|
2365
|
-
padding: "calc(var(--compass-spacing-unit) * 0.5) 0"
|
|
2366
|
-
},
|
|
2367
|
-
children: "Token Breakdown"
|
|
2368
|
-
}
|
|
2369
|
-
),
|
|
2370
|
-
balances.map((token) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2371
|
-
"div",
|
|
2372
|
-
{
|
|
2373
|
-
className: "flex items-center justify-between",
|
|
2374
|
-
style: {
|
|
2375
|
-
backgroundColor: "var(--compass-color-background)",
|
|
2376
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
2377
|
-
padding: "calc(var(--compass-spacing-unit) * 0.75)"
|
|
2378
|
-
},
|
|
2379
|
-
children: [
|
|
2380
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
|
|
2381
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2382
|
-
"div",
|
|
2383
|
-
{
|
|
2384
|
-
className: "w-8 h-8 flex items-center justify-center text-xs font-bold",
|
|
2385
|
-
style: {
|
|
2386
|
-
backgroundColor: "var(--compass-color-primary-muted)",
|
|
2387
|
-
color: "var(--compass-color-primary)",
|
|
2388
|
-
borderRadius: "var(--compass-border-radius-full)"
|
|
2389
|
-
},
|
|
2390
|
-
children: token.symbol.slice(0, 2)
|
|
2391
|
-
}
|
|
2392
|
-
),
|
|
2393
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2394
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2395
|
-
"div",
|
|
2396
|
-
{
|
|
2397
|
-
className: "font-medium",
|
|
2398
|
-
style: { color: "var(--compass-color-text)" },
|
|
2399
|
-
children: token.symbol
|
|
2400
|
-
}
|
|
2401
|
-
),
|
|
2402
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2403
|
-
"div",
|
|
2404
|
-
{
|
|
2405
|
-
className: "text-sm font-mono",
|
|
2406
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
2407
|
-
children: formatAmount(token.balance)
|
|
2408
|
-
}
|
|
2409
|
-
)
|
|
2410
|
-
] })
|
|
2411
|
-
] }),
|
|
2412
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2413
|
-
"div",
|
|
2414
|
-
{
|
|
2415
|
-
className: "font-medium",
|
|
2416
|
-
style: { color: "var(--compass-color-text)" },
|
|
2417
|
-
children: formatUSD(token.usdValue)
|
|
2418
|
-
}
|
|
2419
|
-
)
|
|
2420
|
-
]
|
|
2421
|
-
},
|
|
2422
|
-
token.symbol
|
|
2423
|
-
))
|
|
2424
|
-
] }),
|
|
2425
|
-
earnAccountAddress && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2426
|
-
"div",
|
|
2427
|
-
{
|
|
2428
|
-
className: "border-t text-center",
|
|
2429
|
-
style: {
|
|
2430
|
-
borderColor: "var(--compass-color-border)",
|
|
2431
|
-
marginTop: "var(--compass-spacing-card)",
|
|
2432
|
-
paddingTop: "var(--compass-spacing-card)"
|
|
2433
|
-
},
|
|
2434
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2435
|
-
"span",
|
|
2436
|
-
{
|
|
2437
|
-
className: "text-xs",
|
|
2438
|
-
style: { color: "var(--compass-color-text-tertiary)" },
|
|
2439
|
-
children: [
|
|
2440
|
-
"Earn Account: ",
|
|
2441
|
-
earnAccountAddress.slice(0, 6),
|
|
2442
|
-
"...",
|
|
2443
|
-
earnAccountAddress.slice(-4)
|
|
2444
|
-
]
|
|
2445
|
-
}
|
|
2446
|
-
)
|
|
2447
|
-
}
|
|
2448
|
-
)
|
|
2449
|
-
] })
|
|
2313
|
+
)
|
|
2450
2314
|
]
|
|
2451
2315
|
}
|
|
2452
2316
|
)
|
|
2453
|
-
] });
|
|
2317
|
+
] }) }) });
|
|
2454
2318
|
}
|
|
2455
|
-
var TRANSFER_TOKENS = ["USDC"];
|
|
2319
|
+
var TRANSFER_TOKENS = ["USDC", "SBC"];
|
|
2456
2320
|
var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
2457
2321
|
compact = false,
|
|
2458
2322
|
hideVisual = false,
|
|
@@ -2952,7 +2816,459 @@ var EarnAccountBalance = react.forwardRef(function EarnAccountBalance2({
|
|
|
2952
2816
|
}
|
|
2953
2817
|
)
|
|
2954
2818
|
] });
|
|
2955
|
-
});
|
|
2819
|
+
});
|
|
2820
|
+
function useSwapQuote({ fromToken, toToken, amount, enabled = true }) {
|
|
2821
|
+
const { chainId } = useChain();
|
|
2822
|
+
const { address } = useEmbeddableWallet();
|
|
2823
|
+
const query = reactQuery.useQuery({
|
|
2824
|
+
queryKey: ["swapQuote", chainId, fromToken, toToken, amount, address],
|
|
2825
|
+
queryFn: async () => {
|
|
2826
|
+
if (!fromToken || !toToken || !amount || parseFloat(amount) <= 0 || !address) {
|
|
2827
|
+
return null;
|
|
2828
|
+
}
|
|
2829
|
+
const params = new URLSearchParams({
|
|
2830
|
+
owner: address,
|
|
2831
|
+
chain: chainId,
|
|
2832
|
+
tokenIn: fromToken,
|
|
2833
|
+
tokenOut: toToken,
|
|
2834
|
+
amountIn: amount
|
|
2835
|
+
});
|
|
2836
|
+
const response = await fetch(`/api/compass/swap/quote?${params}`);
|
|
2837
|
+
if (!response.ok) {
|
|
2838
|
+
const errorData = await response.json();
|
|
2839
|
+
const errorMessage = errorData.message || errorData.error || "Failed to get swap quote";
|
|
2840
|
+
throw new Error(errorMessage);
|
|
2841
|
+
}
|
|
2842
|
+
const data = await response.json();
|
|
2843
|
+
const outputAmount = data.estimatedAmountOut || "0";
|
|
2844
|
+
const inputAmountNum = parseFloat(amount);
|
|
2845
|
+
const outputAmountNum = parseFloat(outputAmount);
|
|
2846
|
+
return {
|
|
2847
|
+
inputAmount: amount,
|
|
2848
|
+
outputAmount,
|
|
2849
|
+
rate: inputAmountNum > 0 ? (outputAmountNum / inputAmountNum).toString() : "0"
|
|
2850
|
+
};
|
|
2851
|
+
},
|
|
2852
|
+
enabled: enabled && !!address && !!fromToken && !!toToken && !!amount && parseFloat(amount) > 0,
|
|
2853
|
+
staleTime: 10 * 1e3,
|
|
2854
|
+
refetchInterval: 15 * 1e3,
|
|
2855
|
+
retry: 1
|
|
2856
|
+
});
|
|
2857
|
+
return {
|
|
2858
|
+
quote: query.data,
|
|
2859
|
+
isLoading: query.isLoading,
|
|
2860
|
+
isError: query.isError,
|
|
2861
|
+
error: query.error,
|
|
2862
|
+
refetch: query.refetch
|
|
2863
|
+
};
|
|
2864
|
+
}
|
|
2865
|
+
var COMMON_TOKENS = [
|
|
2866
|
+
"USDC",
|
|
2867
|
+
"USDT",
|
|
2868
|
+
"DAI",
|
|
2869
|
+
"USDS",
|
|
2870
|
+
"USDE",
|
|
2871
|
+
"sUSDE",
|
|
2872
|
+
"sDAI",
|
|
2873
|
+
"FRAX",
|
|
2874
|
+
"LUSD",
|
|
2875
|
+
"GUSD",
|
|
2876
|
+
"PYUSD",
|
|
2877
|
+
"crvUSD",
|
|
2878
|
+
"GHO",
|
|
2879
|
+
"EURC",
|
|
2880
|
+
"EURS",
|
|
2881
|
+
"EURA",
|
|
2882
|
+
"WETH",
|
|
2883
|
+
"WBTC",
|
|
2884
|
+
"wstETH",
|
|
2885
|
+
"cbETH",
|
|
2886
|
+
"rETH"
|
|
2887
|
+
];
|
|
2888
|
+
function SwapForm({
|
|
2889
|
+
availableFromTokens,
|
|
2890
|
+
availableToTokens,
|
|
2891
|
+
balances,
|
|
2892
|
+
defaultFromToken,
|
|
2893
|
+
defaultToToken,
|
|
2894
|
+
onSwapSuccess,
|
|
2895
|
+
onSwapError
|
|
2896
|
+
}) {
|
|
2897
|
+
const toTokens = Array.from(/* @__PURE__ */ new Set([
|
|
2898
|
+
...availableFromTokens,
|
|
2899
|
+
...COMMON_TOKENS,
|
|
2900
|
+
...availableToTokens || []
|
|
2901
|
+
]));
|
|
2902
|
+
const [fromToken, setFromToken] = react.useState(defaultFromToken || availableFromTokens[0] || "USDC");
|
|
2903
|
+
const [toToken, setToToken] = react.useState(defaultToToken || toTokens.find((t) => t !== (defaultFromToken || availableFromTokens[0])) || "USDC");
|
|
2904
|
+
const [fromAmount, setFromAmount] = react.useState("");
|
|
2905
|
+
const [isSwapping, setIsSwapping] = react.useState(false);
|
|
2906
|
+
const [swapStatus, setSwapStatus] = react.useState("");
|
|
2907
|
+
const [isFromOpen, setIsFromOpen] = react.useState(false);
|
|
2908
|
+
const [isToOpen, setIsToOpen] = react.useState(false);
|
|
2909
|
+
const { address, isConnected, signTypedData } = useEmbeddableWallet();
|
|
2910
|
+
const { chainId } = useChain();
|
|
2911
|
+
const { quote, isLoading: isQuoteLoading, error: quoteError } = useSwapQuote({
|
|
2912
|
+
fromToken,
|
|
2913
|
+
toToken,
|
|
2914
|
+
amount: fromAmount,
|
|
2915
|
+
enabled: !!fromAmount && parseFloat(fromAmount) > 0
|
|
2916
|
+
});
|
|
2917
|
+
const handleReverse = react.useCallback(() => {
|
|
2918
|
+
const oldFrom = fromToken;
|
|
2919
|
+
const oldTo = toToken;
|
|
2920
|
+
if (availableFromTokens.includes(oldTo)) {
|
|
2921
|
+
setFromToken(oldTo);
|
|
2922
|
+
setToToken(oldFrom);
|
|
2923
|
+
setFromAmount("");
|
|
2924
|
+
}
|
|
2925
|
+
}, [fromToken, toToken, availableFromTokens]);
|
|
2926
|
+
const handleSwap = react.useCallback(async () => {
|
|
2927
|
+
if (!address || !fromAmount || !quote || !signTypedData) return;
|
|
2928
|
+
setIsSwapping(true);
|
|
2929
|
+
setSwapStatus("Preparing swap...");
|
|
2930
|
+
try {
|
|
2931
|
+
const prepareResponse = await fetch("/api/compass/swap/prepare", {
|
|
2932
|
+
method: "POST",
|
|
2933
|
+
headers: { "Content-Type": "application/json" },
|
|
2934
|
+
body: JSON.stringify({
|
|
2935
|
+
owner: address,
|
|
2936
|
+
chain: chainId,
|
|
2937
|
+
tokenIn: fromToken,
|
|
2938
|
+
tokenOut: toToken,
|
|
2939
|
+
amountIn: fromAmount
|
|
2940
|
+
})
|
|
2941
|
+
});
|
|
2942
|
+
if (!prepareResponse.ok) {
|
|
2943
|
+
const error = await prepareResponse.json();
|
|
2944
|
+
throw new Error(error.error || "Failed to prepare swap");
|
|
2945
|
+
}
|
|
2946
|
+
const prepareData = await prepareResponse.json();
|
|
2947
|
+
const { eip712, normalizedTypes } = prepareData;
|
|
2948
|
+
if (!eip712) {
|
|
2949
|
+
throw new Error("No EIP-712 data returned from prepare");
|
|
2950
|
+
}
|
|
2951
|
+
setSwapStatus("Please sign the transaction...");
|
|
2952
|
+
const signature = await signTypedData({
|
|
2953
|
+
domain: eip712.domain,
|
|
2954
|
+
types: normalizedTypes || eip712.types,
|
|
2955
|
+
primaryType: "SafeTx",
|
|
2956
|
+
message: eip712.message
|
|
2957
|
+
});
|
|
2958
|
+
setSwapStatus("Executing swap...");
|
|
2959
|
+
const executeResponse = await fetch("/api/compass/swap/execute", {
|
|
2960
|
+
method: "POST",
|
|
2961
|
+
headers: { "Content-Type": "application/json" },
|
|
2962
|
+
body: JSON.stringify({
|
|
2963
|
+
owner: address,
|
|
2964
|
+
chain: chainId,
|
|
2965
|
+
eip712,
|
|
2966
|
+
signature
|
|
2967
|
+
})
|
|
2968
|
+
});
|
|
2969
|
+
if (!executeResponse.ok) {
|
|
2970
|
+
const error = await executeResponse.json();
|
|
2971
|
+
throw new Error(error.error || "Failed to execute swap");
|
|
2972
|
+
}
|
|
2973
|
+
const executeData = await executeResponse.json();
|
|
2974
|
+
const txHash = executeData.txHash;
|
|
2975
|
+
setSwapStatus("Swap successful!");
|
|
2976
|
+
onSwapSuccess?.(fromToken, toToken, fromAmount, quote.outputAmount, txHash);
|
|
2977
|
+
setFromAmount("");
|
|
2978
|
+
setTimeout(() => setSwapStatus(""), 3e3);
|
|
2979
|
+
} catch (error) {
|
|
2980
|
+
setSwapStatus("");
|
|
2981
|
+
onSwapError?.(error);
|
|
2982
|
+
} finally {
|
|
2983
|
+
setIsSwapping(false);
|
|
2984
|
+
}
|
|
2985
|
+
}, [address, fromAmount, quote, chainId, fromToken, toToken, signTypedData, onSwapSuccess, onSwapError]);
|
|
2986
|
+
const canReverse = availableFromTokens.includes(toToken);
|
|
2987
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
|
|
2988
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2989
|
+
"div",
|
|
2990
|
+
{
|
|
2991
|
+
style: {
|
|
2992
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
2993
|
+
border: "1px solid var(--compass-color-border)",
|
|
2994
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
2995
|
+
padding: "calc(var(--compass-spacing-unit) * 0.75)"
|
|
2996
|
+
},
|
|
2997
|
+
children: [
|
|
2998
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", style: { marginBottom: "calc(var(--compass-spacing-unit) * 0.25)" }, children: [
|
|
2999
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "From" }),
|
|
3000
|
+
balances?.[fromToken] && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: [
|
|
3001
|
+
"Balance: ",
|
|
3002
|
+
parseFloat(balances[fromToken]).toLocaleString(void 0, { maximumFractionDigits: 6 })
|
|
3003
|
+
] })
|
|
3004
|
+
] }),
|
|
3005
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
3006
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3007
|
+
"input",
|
|
3008
|
+
{
|
|
3009
|
+
type: "number",
|
|
3010
|
+
value: fromAmount,
|
|
3011
|
+
onChange: (e) => setFromAmount(e.target.value),
|
|
3012
|
+
placeholder: "0.00",
|
|
3013
|
+
disabled: isSwapping,
|
|
3014
|
+
className: "flex-1 bg-transparent outline-none font-medium min-w-0",
|
|
3015
|
+
style: { color: "var(--compass-color-text)", fontSize: "1.25rem" }
|
|
3016
|
+
}
|
|
3017
|
+
),
|
|
3018
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", style: { flexShrink: 0 }, children: [
|
|
3019
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3020
|
+
"button",
|
|
3021
|
+
{
|
|
3022
|
+
onClick: () => {
|
|
3023
|
+
setIsFromOpen(!isFromOpen);
|
|
3024
|
+
setIsToOpen(false);
|
|
3025
|
+
},
|
|
3026
|
+
disabled: isSwapping,
|
|
3027
|
+
className: "flex items-center font-medium",
|
|
3028
|
+
style: {
|
|
3029
|
+
backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-background))",
|
|
3030
|
+
border: "1px solid var(--compass-color-border)",
|
|
3031
|
+
color: "var(--compass-color-text)",
|
|
3032
|
+
borderRadius: "var(--compass-border-radius-md)",
|
|
3033
|
+
padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
|
|
3034
|
+
gap: "calc(var(--compass-spacing-unit) * 0.25)",
|
|
3035
|
+
fontSize: "0.875rem"
|
|
3036
|
+
},
|
|
3037
|
+
children: [
|
|
3038
|
+
fromToken,
|
|
3039
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
3040
|
+
]
|
|
3041
|
+
}
|
|
3042
|
+
),
|
|
3043
|
+
isFromOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3044
|
+
"div",
|
|
3045
|
+
{
|
|
3046
|
+
className: "absolute right-0 mt-1 z-10",
|
|
3047
|
+
style: {
|
|
3048
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3049
|
+
border: "1px solid var(--compass-color-border)",
|
|
3050
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3051
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
3052
|
+
minWidth: "120px",
|
|
3053
|
+
maxHeight: "200px",
|
|
3054
|
+
overflowY: "auto",
|
|
3055
|
+
scrollbarWidth: "none"
|
|
3056
|
+
},
|
|
3057
|
+
children: availableFromTokens.filter((t) => t !== toToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3058
|
+
"button",
|
|
3059
|
+
{
|
|
3060
|
+
onClick: () => {
|
|
3061
|
+
setFromToken(token);
|
|
3062
|
+
setIsFromOpen(false);
|
|
3063
|
+
},
|
|
3064
|
+
className: "w-full text-left font-medium transition-colors",
|
|
3065
|
+
style: {
|
|
3066
|
+
padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
|
|
3067
|
+
color: token === fromToken ? "var(--compass-color-primary)" : "var(--compass-color-text)",
|
|
3068
|
+
backgroundColor: token === fromToken ? "var(--compass-color-primary-muted, rgba(99, 102, 241, 0.1))" : "transparent",
|
|
3069
|
+
fontSize: "0.875rem"
|
|
3070
|
+
},
|
|
3071
|
+
children: token
|
|
3072
|
+
},
|
|
3073
|
+
token
|
|
3074
|
+
))
|
|
3075
|
+
}
|
|
3076
|
+
)
|
|
3077
|
+
] })
|
|
3078
|
+
] })
|
|
3079
|
+
]
|
|
3080
|
+
}
|
|
3081
|
+
),
|
|
3082
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center relative z-10", style: { margin: "calc(var(--compass-spacing-unit) * -0.25) 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3083
|
+
"button",
|
|
3084
|
+
{
|
|
3085
|
+
onClick: handleReverse,
|
|
3086
|
+
disabled: !canReverse || isSwapping,
|
|
3087
|
+
className: "border disabled:opacity-30",
|
|
3088
|
+
style: {
|
|
3089
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3090
|
+
borderColor: "var(--compass-color-border)",
|
|
3091
|
+
borderRadius: "var(--compass-border-radius-full)",
|
|
3092
|
+
padding: "calc(var(--compass-spacing-unit) * 0.5)",
|
|
3093
|
+
transition: "var(--compass-transition-normal)"
|
|
3094
|
+
},
|
|
3095
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownUp, { size: 16, style: { color: "var(--compass-color-text-secondary)" } })
|
|
3096
|
+
}
|
|
3097
|
+
) }),
|
|
3098
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3099
|
+
"div",
|
|
3100
|
+
{
|
|
3101
|
+
style: {
|
|
3102
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3103
|
+
border: "1px solid var(--compass-color-border)",
|
|
3104
|
+
borderRadius: "var(--compass-border-radius-xl)",
|
|
3105
|
+
padding: "calc(var(--compass-spacing-unit) * 0.75)"
|
|
3106
|
+
},
|
|
3107
|
+
children: [
|
|
3108
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", style: { marginBottom: "calc(var(--compass-spacing-unit) * 0.25)" }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "To" }) }),
|
|
3109
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
3110
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3111
|
+
"div",
|
|
3112
|
+
{
|
|
3113
|
+
className: "flex-1 font-medium min-w-0",
|
|
3114
|
+
style: {
|
|
3115
|
+
color: isQuoteLoading ? "var(--compass-color-text-tertiary)" : "var(--compass-color-text)",
|
|
3116
|
+
fontSize: "1.25rem"
|
|
3117
|
+
},
|
|
3118
|
+
children: isQuoteLoading ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
|
|
3119
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
|
|
3120
|
+
"Loading..."
|
|
3121
|
+
] }) : quote?.outputAmount ? parseFloat(quote.outputAmount).toFixed(8) : "0.00"
|
|
3122
|
+
}
|
|
3123
|
+
),
|
|
3124
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", style: { flexShrink: 0 }, children: [
|
|
3125
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3126
|
+
"button",
|
|
3127
|
+
{
|
|
3128
|
+
onClick: () => {
|
|
3129
|
+
setIsToOpen(!isToOpen);
|
|
3130
|
+
setIsFromOpen(false);
|
|
3131
|
+
},
|
|
3132
|
+
disabled: isSwapping,
|
|
3133
|
+
className: "flex items-center font-medium",
|
|
3134
|
+
style: {
|
|
3135
|
+
backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-background))",
|
|
3136
|
+
border: "1px solid var(--compass-color-border)",
|
|
3137
|
+
color: "var(--compass-color-text)",
|
|
3138
|
+
borderRadius: "var(--compass-border-radius-md)",
|
|
3139
|
+
padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
|
|
3140
|
+
gap: "calc(var(--compass-spacing-unit) * 0.25)",
|
|
3141
|
+
fontSize: "0.875rem"
|
|
3142
|
+
},
|
|
3143
|
+
children: [
|
|
3144
|
+
toToken,
|
|
3145
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14, style: { color: "var(--compass-color-text-tertiary)" } })
|
|
3146
|
+
]
|
|
3147
|
+
}
|
|
3148
|
+
),
|
|
3149
|
+
isToOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3150
|
+
"div",
|
|
3151
|
+
{
|
|
3152
|
+
className: "absolute right-0 mt-1 z-10",
|
|
3153
|
+
style: {
|
|
3154
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3155
|
+
border: "1px solid var(--compass-color-border)",
|
|
3156
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3157
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
3158
|
+
minWidth: "140px",
|
|
3159
|
+
maxHeight: "280px",
|
|
3160
|
+
overflowY: "auto",
|
|
3161
|
+
scrollbarWidth: "none"
|
|
3162
|
+
},
|
|
3163
|
+
children: toTokens.filter((t) => t !== fromToken).map((token) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3164
|
+
"button",
|
|
3165
|
+
{
|
|
3166
|
+
onClick: () => {
|
|
3167
|
+
setToToken(token);
|
|
3168
|
+
setIsToOpen(false);
|
|
3169
|
+
},
|
|
3170
|
+
className: "w-full text-left font-medium transition-colors",
|
|
3171
|
+
style: {
|
|
3172
|
+
padding: "calc(var(--compass-spacing-unit) * 0.5) calc(var(--compass-spacing-unit) * 0.75)",
|
|
3173
|
+
color: token === toToken ? "var(--compass-color-primary)" : "var(--compass-color-text)",
|
|
3174
|
+
backgroundColor: token === toToken ? "var(--compass-color-primary-muted, rgba(99, 102, 241, 0.1))" : "transparent",
|
|
3175
|
+
fontSize: "0.875rem"
|
|
3176
|
+
},
|
|
3177
|
+
children: token
|
|
3178
|
+
},
|
|
3179
|
+
token
|
|
3180
|
+
))
|
|
3181
|
+
}
|
|
3182
|
+
)
|
|
3183
|
+
] })
|
|
3184
|
+
] })
|
|
3185
|
+
]
|
|
3186
|
+
}
|
|
3187
|
+
),
|
|
3188
|
+
quote && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: [
|
|
3189
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rate" }),
|
|
3190
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
|
|
3191
|
+
"1 ",
|
|
3192
|
+
fromToken,
|
|
3193
|
+
" = ",
|
|
3194
|
+
parseFloat(quote.rate).toFixed(6),
|
|
3195
|
+
" ",
|
|
3196
|
+
toToken
|
|
3197
|
+
] })
|
|
3198
|
+
] }),
|
|
3199
|
+
quoteError && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3200
|
+
"div",
|
|
3201
|
+
{
|
|
3202
|
+
className: "flex items-center text-sm",
|
|
3203
|
+
style: {
|
|
3204
|
+
backgroundColor: "var(--compass-color-error-muted)",
|
|
3205
|
+
color: "var(--compass-color-error)",
|
|
3206
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3207
|
+
padding: "calc(var(--compass-spacing-unit) * 0.75)",
|
|
3208
|
+
gap: "calc(var(--compass-spacing-unit) * 0.5)"
|
|
3209
|
+
},
|
|
3210
|
+
children: [
|
|
3211
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 16 }),
|
|
3212
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: quoteError.message })
|
|
3213
|
+
]
|
|
3214
|
+
}
|
|
3215
|
+
),
|
|
3216
|
+
swapStatus && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3217
|
+
"div",
|
|
3218
|
+
{
|
|
3219
|
+
className: "flex items-center text-sm",
|
|
3220
|
+
style: {
|
|
3221
|
+
backgroundColor: swapStatus.includes("successful") ? "var(--compass-color-success-muted)" : "var(--compass-color-surface)",
|
|
3222
|
+
color: swapStatus.includes("successful") ? "var(--compass-color-success)" : "var(--compass-color-text-secondary)",
|
|
3223
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3224
|
+
padding: "calc(var(--compass-spacing-unit) * 0.75)",
|
|
3225
|
+
gap: "calc(var(--compass-spacing-unit) * 0.5)"
|
|
3226
|
+
},
|
|
3227
|
+
children: [
|
|
3228
|
+
!swapStatus.includes("successful") && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 14, className: "animate-spin" }),
|
|
3229
|
+
swapStatus
|
|
3230
|
+
]
|
|
3231
|
+
}
|
|
3232
|
+
),
|
|
3233
|
+
!isConnected ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3234
|
+
"div",
|
|
3235
|
+
{
|
|
3236
|
+
className: "flex flex-col items-center",
|
|
3237
|
+
style: {
|
|
3238
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
3239
|
+
border: "1px solid var(--compass-color-border)",
|
|
3240
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3241
|
+
padding: "calc(var(--compass-spacing-unit) * 1) var(--compass-spacing-card)",
|
|
3242
|
+
gap: "calc(var(--compass-spacing-unit) * 0.5)"
|
|
3243
|
+
},
|
|
3244
|
+
children: [
|
|
3245
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 20, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
3246
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-center", style: { color: "var(--compass-color-text-secondary)" }, children: "Connect your wallet to swap" })
|
|
3247
|
+
]
|
|
3248
|
+
}
|
|
3249
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3250
|
+
"button",
|
|
3251
|
+
{
|
|
3252
|
+
onClick: handleSwap,
|
|
3253
|
+
disabled: isSwapping || !quote || !fromAmount || parseFloat(fromAmount) <= 0,
|
|
3254
|
+
className: "w-full font-semibold flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3255
|
+
style: {
|
|
3256
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
3257
|
+
color: "var(--compass-color-primary-text, white)",
|
|
3258
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
3259
|
+
padding: "calc(var(--compass-spacing-unit) * 0.75)",
|
|
3260
|
+
gap: "calc(var(--compass-spacing-unit) * 0.5)",
|
|
3261
|
+
fontSize: "0.875rem",
|
|
3262
|
+
transition: "var(--compass-transition-normal)"
|
|
3263
|
+
},
|
|
3264
|
+
children: [
|
|
3265
|
+
isSwapping && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "animate-spin" }),
|
|
3266
|
+
isSwapping ? "Swapping..." : "Swap"
|
|
3267
|
+
]
|
|
3268
|
+
}
|
|
3269
|
+
)
|
|
3270
|
+
] });
|
|
3271
|
+
}
|
|
2956
3272
|
var MARKET_TABS = [
|
|
2957
3273
|
{ value: "variable", label: "VARIABLE" },
|
|
2958
3274
|
{ value: "fixed", label: "FIXED" }
|
|
@@ -3785,7 +4101,6 @@ var EVM_CHAIN_IDS = {
|
|
|
3785
4101
|
base: 8453,
|
|
3786
4102
|
arbitrum: 42161
|
|
3787
4103
|
};
|
|
3788
|
-
var SUPPORTED_TOKENS = ["USDC", "USDT", "DAI", "WETH", "SBC", "AUSD"];
|
|
3789
4104
|
function formatCurrency(amount) {
|
|
3790
4105
|
if (!amount) return "$0.00";
|
|
3791
4106
|
const num = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
@@ -3837,6 +4152,7 @@ function EarnAccount({
|
|
|
3837
4152
|
const [isBalancesModalOpen, setIsBalancesModalOpen] = react.useState(false);
|
|
3838
4153
|
const [marketTab, setMarketTab] = react.useState(defaultMarketTab);
|
|
3839
4154
|
const [selectedMarket, setSelectedMarket] = react.useState(null);
|
|
4155
|
+
const [isSwapModalOpen, setIsSwapModalOpen] = react.useState(false);
|
|
3840
4156
|
const [isEarningsModalOpen, setIsEarningsModalOpen] = react.useState(false);
|
|
3841
4157
|
react.useEffect(() => {
|
|
3842
4158
|
setSelectedMarket(null);
|
|
@@ -3886,6 +4202,7 @@ function EarnAccount({
|
|
|
3886
4202
|
enabled: !!address && isDeployed,
|
|
3887
4203
|
staleTime: 30 * 1e3
|
|
3888
4204
|
});
|
|
4205
|
+
const balanceTokens = Object.keys(balancesQuery.data?.balances || {});
|
|
3889
4206
|
const selectedTokenBalance = balancesQuery.data?.balances?.[selectedToken]?.balance || "0";
|
|
3890
4207
|
const earnAccountTotalUsd = Object.values(balancesQuery.data?.balances || {}).reduce((sum, b) => sum + parseFloat(b.usdValue || "0"), 0).toString();
|
|
3891
4208
|
const positionQuery = reactQuery.useQuery({
|
|
@@ -4555,39 +4872,59 @@ function EarnAccount({
|
|
|
4555
4872
|
]
|
|
4556
4873
|
}
|
|
4557
4874
|
),
|
|
4558
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4559
|
-
|
|
4875
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4876
|
+
"button",
|
|
4877
|
+
{
|
|
4878
|
+
onClick: () => setIsBalancesModalOpen(true),
|
|
4879
|
+
className: "transition-opacity hover:opacity-80",
|
|
4880
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4881
|
+
"span",
|
|
4882
|
+
{
|
|
4883
|
+
className: "font-bold",
|
|
4884
|
+
style: {
|
|
4885
|
+
color: "var(--compass-color-text)",
|
|
4886
|
+
fontSize: compact ? "2rem" : "2.5rem",
|
|
4887
|
+
lineHeight: "1"
|
|
4888
|
+
},
|
|
4889
|
+
children: formatCurrency(earnAccountTotal)
|
|
4890
|
+
}
|
|
4891
|
+
)
|
|
4892
|
+
}
|
|
4893
|
+
),
|
|
4894
|
+
(balanceTokens.length > 0 || showTopUpButton) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "6px", marginTop: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
4895
|
+
balanceTokens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4560
4896
|
"button",
|
|
4561
4897
|
{
|
|
4562
|
-
onClick: () =>
|
|
4563
|
-
className: "transition-
|
|
4564
|
-
|
|
4565
|
-
"
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
}
|
|
4575
|
-
|
|
4898
|
+
onClick: () => setIsSwapModalOpen(true),
|
|
4899
|
+
className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
|
|
4900
|
+
style: {
|
|
4901
|
+
backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
|
|
4902
|
+
border: "1px solid var(--compass-color-border)",
|
|
4903
|
+
color: "var(--compass-color-text-secondary)",
|
|
4904
|
+
borderRadius: "var(--compass-border-radius-md)",
|
|
4905
|
+
padding: "8px 10px",
|
|
4906
|
+
gap: "6px",
|
|
4907
|
+
fontSize: "13px"
|
|
4908
|
+
},
|
|
4909
|
+
children: [
|
|
4910
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftRight, { size: 14 }),
|
|
4911
|
+
"Swap"
|
|
4912
|
+
]
|
|
4576
4913
|
}
|
|
4577
4914
|
),
|
|
4578
4915
|
showTopUpButton && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4579
4916
|
"button",
|
|
4580
4917
|
{
|
|
4581
4918
|
onClick: () => setIsFundModalOpen(true),
|
|
4582
|
-
className: "flex items-center font-medium transition-all hover:opacity-80",
|
|
4919
|
+
className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
|
|
4583
4920
|
style: {
|
|
4584
4921
|
backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
|
|
4585
4922
|
border: "1px solid var(--compass-color-border)",
|
|
4586
4923
|
color: "var(--compass-color-text-secondary)",
|
|
4587
4924
|
borderRadius: "var(--compass-border-radius-md)",
|
|
4588
|
-
padding: "
|
|
4589
|
-
gap: "
|
|
4590
|
-
fontSize: "
|
|
4925
|
+
padding: "8px 10px",
|
|
4926
|
+
gap: "6px",
|
|
4927
|
+
fontSize: "13px"
|
|
4591
4928
|
},
|
|
4592
4929
|
children: [
|
|
4593
4930
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14 }),
|
|
@@ -4791,7 +5128,7 @@ function EarnAccount({
|
|
|
4791
5128
|
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
4792
5129
|
minWidth: "100px"
|
|
4793
5130
|
},
|
|
4794
|
-
children:
|
|
5131
|
+
children: balanceTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4795
5132
|
"button",
|
|
4796
5133
|
{
|
|
4797
5134
|
onClick: () => {
|
|
@@ -5092,402 +5429,134 @@ function EarnAccount({
|
|
|
5092
5429
|
{
|
|
5093
5430
|
onClick: handleFund,
|
|
5094
5431
|
disabled: isFunding || !fundAmount || parseFloat(fundAmount) <= 0,
|
|
5095
|
-
className: "w-full py-4 rounded-xl font-semibold text-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed",
|
|
5096
|
-
style: {
|
|
5097
|
-
backgroundColor: "var(--compass-color-primary)",
|
|
5098
|
-
color: "white"
|
|
5099
|
-
},
|
|
5100
|
-
children: isFunding ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center gap-2", children: [
|
|
5101
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 20, className: "animate-spin" }),
|
|
5102
|
-
"Processing..."
|
|
5103
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center gap-2", children: [
|
|
5104
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 20 }),
|
|
5105
|
-
needsFundSwap ? `Swap ${fundToken} & Transfer` : "Transfer to Savings"
|
|
5106
|
-
] })
|
|
5107
|
-
}
|
|
5108
|
-
),
|
|
5109
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5110
|
-
"p",
|
|
5111
|
-
{
|
|
5112
|
-
className: "text-xs text-center",
|
|
5113
|
-
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5114
|
-
children: "Gas fees are sponsored"
|
|
5115
|
-
}
|
|
5116
|
-
)
|
|
5117
|
-
] })
|
|
5118
|
-
}
|
|
5119
|
-
),
|
|
5120
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5121
|
-
ActionModal,
|
|
5122
|
-
{
|
|
5123
|
-
isOpen: isBalancesModalOpen,
|
|
5124
|
-
onClose: () => setIsBalancesModalOpen(false),
|
|
5125
|
-
title: "Balance Breakdown",
|
|
5126
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: balancesQuery.data?.balances && Object.keys(balancesQuery.data.balances).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5127
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
5128
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5129
|
-
"span",
|
|
5130
|
-
{
|
|
5131
|
-
className: "text-xs font-medium uppercase tracking-wide",
|
|
5132
|
-
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5133
|
-
children: "Available in Account"
|
|
5134
|
-
}
|
|
5135
|
-
),
|
|
5136
|
-
Object.entries(balancesQuery.data.balances).map(([symbol, data]) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5137
|
-
"div",
|
|
5138
|
-
{
|
|
5139
|
-
className: "flex items-center justify-between p-3 rounded-lg",
|
|
5140
|
-
style: {
|
|
5141
|
-
backgroundColor: "var(--compass-color-surface)",
|
|
5142
|
-
border: "1px solid var(--compass-color-border)"
|
|
5143
|
-
},
|
|
5144
|
-
children: [
|
|
5145
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: symbol }),
|
|
5146
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
|
|
5147
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount2(data.balance) }),
|
|
5148
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatCurrency(data.usdValue) })
|
|
5149
|
-
] })
|
|
5150
|
-
]
|
|
5151
|
-
},
|
|
5152
|
-
symbol
|
|
5153
|
-
))
|
|
5154
|
-
] }),
|
|
5155
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5156
|
-
"div",
|
|
5157
|
-
{
|
|
5158
|
-
className: "flex items-center justify-between pt-3 mt-2",
|
|
5159
|
-
style: { borderTop: "2px solid var(--compass-color-border)" },
|
|
5160
|
-
children: [
|
|
5161
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
|
|
5162
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5163
|
-
"span",
|
|
5164
|
-
{
|
|
5165
|
-
className: "font-bold text-xl",
|
|
5166
|
-
style: { color: "var(--compass-color-text)" },
|
|
5167
|
-
children: formatCurrency(earnAccountTotalUsd)
|
|
5168
|
-
}
|
|
5169
|
-
)
|
|
5170
|
-
]
|
|
5171
|
-
}
|
|
5172
|
-
)
|
|
5173
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5174
|
-
"div",
|
|
5175
|
-
{
|
|
5176
|
-
className: "text-center py-4",
|
|
5177
|
-
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5178
|
-
children: "No tokens in account"
|
|
5179
|
-
}
|
|
5180
|
-
) })
|
|
5181
|
-
}
|
|
5182
|
-
),
|
|
5183
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5184
|
-
EarningsModal,
|
|
5185
|
-
{
|
|
5186
|
-
isOpen: isEarningsModalOpen,
|
|
5187
|
-
onClose: () => setIsEarningsModalOpen(false),
|
|
5188
|
-
positions,
|
|
5189
|
-
totalEarned,
|
|
5190
|
-
isLoading: positionQuery.isLoading
|
|
5191
|
-
}
|
|
5192
|
-
)
|
|
5193
|
-
] });
|
|
5194
|
-
}
|
|
5195
|
-
function useSwapQuote({ fromToken, toToken, amount, enabled = true }) {
|
|
5196
|
-
const { chainId } = useChain();
|
|
5197
|
-
const { address } = useCompassWallet();
|
|
5198
|
-
const query = reactQuery.useQuery({
|
|
5199
|
-
queryKey: ["swapQuote", chainId, fromToken, toToken, amount, address],
|
|
5200
|
-
queryFn: async () => {
|
|
5201
|
-
if (!fromToken || !toToken || !amount || parseFloat(amount) <= 0 || !address) {
|
|
5202
|
-
return null;
|
|
5203
|
-
}
|
|
5204
|
-
try {
|
|
5205
|
-
const params = new URLSearchParams({
|
|
5206
|
-
owner: address,
|
|
5207
|
-
chain: chainId,
|
|
5208
|
-
tokenIn: fromToken,
|
|
5209
|
-
tokenOut: toToken,
|
|
5210
|
-
amountIn: amount
|
|
5211
|
-
});
|
|
5212
|
-
const response = await fetch(`/api/compass/swap/quote?${params}`);
|
|
5213
|
-
if (!response.ok) {
|
|
5214
|
-
const errorData = await response.json();
|
|
5215
|
-
const errorMessage = errorData.message || errorData.error || "Failed to get swap quote";
|
|
5216
|
-
throw new Error(errorMessage);
|
|
5217
|
-
}
|
|
5218
|
-
const data = await response.json();
|
|
5219
|
-
const outputAmount = data.estimatedAmountOut || "0";
|
|
5220
|
-
const inputAmountNum = parseFloat(amount);
|
|
5221
|
-
const outputAmountNum = parseFloat(outputAmount);
|
|
5222
|
-
return {
|
|
5223
|
-
inputAmount: amount,
|
|
5224
|
-
outputAmount,
|
|
5225
|
-
rate: inputAmountNum > 0 ? (outputAmountNum / inputAmountNum).toString() : "0"
|
|
5226
|
-
};
|
|
5227
|
-
} catch (error) {
|
|
5228
|
-
throw error;
|
|
5229
|
-
}
|
|
5230
|
-
},
|
|
5231
|
-
enabled: enabled && !!address && !!fromToken && !!toToken && !!amount && parseFloat(amount) > 0,
|
|
5232
|
-
staleTime: 10 * 1e3,
|
|
5233
|
-
refetchInterval: 15 * 1e3,
|
|
5234
|
-
retry: 1
|
|
5235
|
-
});
|
|
5236
|
-
return {
|
|
5237
|
-
quote: query.data,
|
|
5238
|
-
isLoading: query.isLoading,
|
|
5239
|
-
isError: query.isError,
|
|
5240
|
-
error: query.error,
|
|
5241
|
-
refetch: query.refetch
|
|
5242
|
-
};
|
|
5243
|
-
}
|
|
5244
|
-
|
|
5245
|
-
// src/components/SwapWidget/types.ts
|
|
5246
|
-
var DEFAULT_SWAP_TOKENS = ["USDC", "ETH", "WETH", "WBTC", "DAI", "USDT", "AUSD", "SBC"];
|
|
5247
|
-
function SwapWidget({
|
|
5248
|
-
layout = "full",
|
|
5249
|
-
defaultFromToken = "ETH",
|
|
5250
|
-
defaultToToken = "USDC",
|
|
5251
|
-
allowedTokens = [...DEFAULT_SWAP_TOKENS],
|
|
5252
|
-
showReverseButton = true,
|
|
5253
|
-
showSettings = false,
|
|
5254
|
-
onSwapSuccess,
|
|
5255
|
-
onSwapError
|
|
5256
|
-
}) {
|
|
5257
|
-
const [fromToken, setFromToken] = react.useState(defaultFromToken);
|
|
5258
|
-
const [toToken, setToToken] = react.useState(defaultToToken);
|
|
5259
|
-
const [fromAmount, setFromAmount] = react.useState("");
|
|
5260
|
-
const [isSwapping, setIsSwapping] = react.useState(false);
|
|
5261
|
-
const [swapStatus, setSwapStatus] = react.useState("");
|
|
5262
|
-
const { address, isConnected, signTypedData } = useCompassWallet();
|
|
5263
|
-
const { chainId } = useChain();
|
|
5264
|
-
const { quote, isLoading: isQuoteLoading, error: quoteError } = useSwapQuote({
|
|
5265
|
-
fromToken,
|
|
5266
|
-
toToken,
|
|
5267
|
-
amount: fromAmount,
|
|
5268
|
-
enabled: !!fromAmount && parseFloat(fromAmount) > 0
|
|
5269
|
-
});
|
|
5270
|
-
const handleReverse = react.useCallback(() => {
|
|
5271
|
-
setFromToken(toToken);
|
|
5272
|
-
setToToken(fromToken);
|
|
5273
|
-
setFromAmount("");
|
|
5274
|
-
}, [fromToken, toToken]);
|
|
5275
|
-
const handleSwap = react.useCallback(async () => {
|
|
5276
|
-
if (!address || !fromAmount || !quote) return;
|
|
5277
|
-
setIsSwapping(true);
|
|
5278
|
-
setSwapStatus("Preparing swap...");
|
|
5279
|
-
try {
|
|
5280
|
-
const prepareResponse = await fetch("/api/compass/swap/prepare", {
|
|
5281
|
-
method: "POST",
|
|
5282
|
-
headers: { "Content-Type": "application/json" },
|
|
5283
|
-
body: JSON.stringify({
|
|
5284
|
-
owner: address,
|
|
5285
|
-
chain: chainId,
|
|
5286
|
-
tokenIn: fromToken,
|
|
5287
|
-
tokenOut: toToken,
|
|
5288
|
-
amountIn: fromAmount
|
|
5289
|
-
})
|
|
5290
|
-
});
|
|
5291
|
-
if (!prepareResponse.ok) {
|
|
5292
|
-
const error = await prepareResponse.json();
|
|
5293
|
-
throw new Error(error.error || "Failed to prepare swap");
|
|
5294
|
-
}
|
|
5295
|
-
const prepareData = await prepareResponse.json();
|
|
5296
|
-
const { eip712, normalizedTypes } = prepareData;
|
|
5297
|
-
if (!eip712) {
|
|
5298
|
-
throw new Error("No EIP-712 data returned from prepare");
|
|
5299
|
-
}
|
|
5300
|
-
setSwapStatus("Please sign the transaction...");
|
|
5301
|
-
const signature = await signTypedData({
|
|
5302
|
-
domain: eip712.domain,
|
|
5303
|
-
types: normalizedTypes || eip712.types,
|
|
5304
|
-
primaryType: "SafeTx",
|
|
5305
|
-
message: eip712.message
|
|
5306
|
-
});
|
|
5307
|
-
setSwapStatus("Executing swap...");
|
|
5308
|
-
const executeResponse = await fetch("/api/compass/swap/execute", {
|
|
5309
|
-
method: "POST",
|
|
5310
|
-
headers: { "Content-Type": "application/json" },
|
|
5311
|
-
body: JSON.stringify({
|
|
5312
|
-
owner: address,
|
|
5313
|
-
chain: chainId,
|
|
5314
|
-
eip712,
|
|
5315
|
-
signature
|
|
5316
|
-
})
|
|
5317
|
-
});
|
|
5318
|
-
if (!executeResponse.ok) {
|
|
5319
|
-
const error = await executeResponse.json();
|
|
5320
|
-
throw new Error(error.error || "Failed to execute swap");
|
|
5432
|
+
className: "w-full py-4 rounded-xl font-semibold text-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed",
|
|
5433
|
+
style: {
|
|
5434
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
5435
|
+
color: "white"
|
|
5436
|
+
},
|
|
5437
|
+
children: isFunding ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center gap-2", children: [
|
|
5438
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 20, className: "animate-spin" }),
|
|
5439
|
+
"Processing..."
|
|
5440
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center gap-2", children: [
|
|
5441
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { size: 20 }),
|
|
5442
|
+
needsFundSwap ? `Swap ${fundToken} & Transfer` : "Transfer to Savings"
|
|
5443
|
+
] })
|
|
5444
|
+
}
|
|
5445
|
+
),
|
|
5446
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5447
|
+
"p",
|
|
5448
|
+
{
|
|
5449
|
+
className: "text-xs text-center",
|
|
5450
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5451
|
+
children: "Gas fees are sponsored"
|
|
5452
|
+
}
|
|
5453
|
+
)
|
|
5454
|
+
] })
|
|
5321
5455
|
}
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
} finally {
|
|
5332
|
-
setIsSwapping(false);
|
|
5333
|
-
}
|
|
5334
|
-
}, [address, fromAmount, quote, chainId, fromToken, toToken, signTypedData, onSwapSuccess, onSwapError]);
|
|
5335
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "var(--compass-spacing-card)" }, children: [
|
|
5336
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between flex-wrap", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
5337
|
-
/* @__PURE__ */ jsxRuntime.jsx(ChainSwitcher, {}),
|
|
5338
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
5339
|
-
/* @__PURE__ */ jsxRuntime.jsx(EarnAccountBalance, { compact: true }),
|
|
5340
|
-
/* @__PURE__ */ jsxRuntime.jsx(WalletStatus, { compact: true })
|
|
5341
|
-
] })
|
|
5342
|
-
] }),
|
|
5343
|
-
/* @__PURE__ */ jsxRuntime.jsxs(EarnAccountGuard, { children: [
|
|
5344
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
5345
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border relative", style: { backgroundColor: "var(--compass-color-surface)", borderColor: "var(--compass-color-border)", borderRadius: "var(--compass-border-radius-xl)", fontFamily: "var(--compass-font-family)", padding: "var(--compass-spacing-card)" }, children: [
|
|
5346
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", style: { marginBottom: "calc(var(--compass-spacing-unit) * 0.5)" }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: "From" }) }),
|
|
5347
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
|
|
5456
|
+
),
|
|
5457
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5458
|
+
ActionModal,
|
|
5459
|
+
{
|
|
5460
|
+
isOpen: isBalancesModalOpen,
|
|
5461
|
+
onClose: () => setIsBalancesModalOpen(false),
|
|
5462
|
+
title: "Balance Breakdown",
|
|
5463
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: balancesQuery.data?.balances && Object.keys(balancesQuery.data.balances).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5464
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
5348
5465
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5349
|
-
"
|
|
5466
|
+
"span",
|
|
5350
5467
|
{
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
placeholder: "0.00",
|
|
5355
|
-
className: "flex-1 bg-transparent outline-none text-2xl font-mono min-w-0",
|
|
5356
|
-
style: { color: "var(--compass-color-text)" }
|
|
5468
|
+
className: "text-xs font-medium uppercase tracking-wide",
|
|
5469
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5470
|
+
children: "Available in Account"
|
|
5357
5471
|
}
|
|
5358
5472
|
),
|
|
5359
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5360
|
-
"
|
|
5473
|
+
Object.entries(balancesQuery.data.balances).map(([symbol, data]) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5474
|
+
"div",
|
|
5361
5475
|
{
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5476
|
+
className: "flex items-center justify-between p-3 rounded-lg",
|
|
5477
|
+
style: {
|
|
5478
|
+
backgroundColor: "var(--compass-color-surface)",
|
|
5479
|
+
border: "1px solid var(--compass-color-border)"
|
|
5480
|
+
},
|
|
5481
|
+
children: [
|
|
5482
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--compass-color-text)" }, children: symbol }),
|
|
5483
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
|
|
5484
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", style: { color: "var(--compass-color-text)" }, children: formatAmount2(data.balance) }),
|
|
5485
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: "var(--compass-color-text-tertiary)" }, children: formatCurrency(data.usdValue) })
|
|
5486
|
+
] })
|
|
5487
|
+
]
|
|
5488
|
+
},
|
|
5489
|
+
symbol
|
|
5490
|
+
))
|
|
5491
|
+
] }),
|
|
5492
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5493
|
+
"div",
|
|
5494
|
+
{
|
|
5495
|
+
className: "flex items-center justify-between pt-3 mt-2",
|
|
5496
|
+
style: { borderTop: "2px solid var(--compass-color-border)" },
|
|
5497
|
+
children: [
|
|
5498
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", style: { color: "var(--compass-color-text)" }, children: "Total" }),
|
|
5499
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5500
|
+
"span",
|
|
5501
|
+
{
|
|
5502
|
+
className: "font-bold text-xl",
|
|
5503
|
+
style: { color: "var(--compass-color-text)" },
|
|
5504
|
+
children: formatCurrency(earnAccountTotalUsd)
|
|
5505
|
+
}
|
|
5506
|
+
)
|
|
5507
|
+
]
|
|
5508
|
+
}
|
|
5509
|
+
)
|
|
5510
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5511
|
+
"div",
|
|
5373
5512
|
{
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownUp, { size: 16, style: { color: "var(--compass-color-text-secondary)" } })
|
|
5513
|
+
className: "text-center py-4",
|
|
5514
|
+
style: { color: "var(--compass-color-text-tertiary)" },
|
|
5515
|
+
children: "No tokens in account"
|
|
5378
5516
|
}
|
|
5379
|
-
) })
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
children: [
|
|
5423
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 16 }),
|
|
5424
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: quoteError.message })
|
|
5425
|
-
]
|
|
5426
|
-
}
|
|
5427
|
-
),
|
|
5428
|
-
swapStatus && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5429
|
-
"div",
|
|
5430
|
-
{
|
|
5431
|
-
className: "flex items-center text-sm",
|
|
5432
|
-
style: {
|
|
5433
|
-
backgroundColor: swapStatus.includes("successful") ? "var(--compass-color-success-muted)" : "var(--compass-color-surface)",
|
|
5434
|
-
color: swapStatus.includes("successful") ? "var(--compass-color-success)" : "var(--compass-color-text-secondary)",
|
|
5435
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
5436
|
-
padding: "calc(var(--compass-spacing-unit) * 0.75)",
|
|
5437
|
-
gap: "calc(var(--compass-spacing-unit) * 0.5)"
|
|
5438
|
-
},
|
|
5439
|
-
children: [
|
|
5440
|
-
!swapStatus.includes("successful") && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 14, className: "animate-spin" }),
|
|
5441
|
-
swapStatus
|
|
5442
|
-
]
|
|
5443
|
-
}
|
|
5444
|
-
),
|
|
5445
|
-
!isConnected ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5446
|
-
"div",
|
|
5447
|
-
{
|
|
5448
|
-
className: "flex flex-col items-center",
|
|
5449
|
-
style: {
|
|
5450
|
-
backgroundColor: "var(--compass-color-surface)",
|
|
5451
|
-
border: "1px solid var(--compass-color-border)",
|
|
5452
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
5453
|
-
fontFamily: "var(--compass-font-family)",
|
|
5454
|
-
padding: "calc(var(--compass-spacing-unit) * 1.5) var(--compass-spacing-card)",
|
|
5455
|
-
gap: "calc(var(--compass-spacing-unit) * 0.75)"
|
|
5456
|
-
},
|
|
5457
|
-
children: [
|
|
5458
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 24, style: { color: "var(--compass-color-text-tertiary)" } }),
|
|
5459
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5460
|
-
"p",
|
|
5461
|
-
{
|
|
5462
|
-
className: "text-sm text-center",
|
|
5463
|
-
style: { color: "var(--compass-color-text-secondary)" },
|
|
5464
|
-
children: "Connect your wallet to swap"
|
|
5465
|
-
}
|
|
5466
|
-
)
|
|
5467
|
-
]
|
|
5468
|
-
}
|
|
5469
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5470
|
-
"button",
|
|
5471
|
-
{
|
|
5472
|
-
onClick: handleSwap,
|
|
5473
|
-
disabled: isSwapping || !quote || !fromAmount || parseFloat(fromAmount) <= 0,
|
|
5474
|
-
className: "w-full font-medium flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed",
|
|
5475
|
-
style: {
|
|
5476
|
-
backgroundColor: "var(--compass-color-primary)",
|
|
5477
|
-
color: "var(--compass-color-primary-text)",
|
|
5478
|
-
borderRadius: "var(--compass-border-radius-lg)",
|
|
5479
|
-
fontFamily: "var(--compass-font-family)",
|
|
5480
|
-
padding: "calc(var(--compass-spacing-unit) * 0.75)",
|
|
5481
|
-
gap: "calc(var(--compass-spacing-unit) * 0.5)",
|
|
5482
|
-
transition: "var(--compass-transition-normal)"
|
|
5483
|
-
},
|
|
5484
|
-
children: [
|
|
5485
|
-
isSwapping && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 18, className: "animate-spin" }),
|
|
5486
|
-
isSwapping ? "Swapping..." : "Swap"
|
|
5487
|
-
]
|
|
5488
|
-
}
|
|
5489
|
-
)
|
|
5490
|
-
] })
|
|
5517
|
+
) })
|
|
5518
|
+
}
|
|
5519
|
+
),
|
|
5520
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5521
|
+
ActionModal,
|
|
5522
|
+
{
|
|
5523
|
+
isOpen: isSwapModalOpen,
|
|
5524
|
+
onClose: () => setIsSwapModalOpen(false),
|
|
5525
|
+
title: "Swap Tokens",
|
|
5526
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5527
|
+
SwapForm,
|
|
5528
|
+
{
|
|
5529
|
+
availableFromTokens: balanceTokens,
|
|
5530
|
+
balances: Object.fromEntries(
|
|
5531
|
+
Object.entries(balancesQuery.data?.balances || {}).map(([token, data]) => [token, data.balance])
|
|
5532
|
+
),
|
|
5533
|
+
onSwapSuccess: () => {
|
|
5534
|
+
setIsSwapModalOpen(false);
|
|
5535
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
5536
|
+
balancesQuery.refetch();
|
|
5537
|
+
setTimeout(() => {
|
|
5538
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
5539
|
+
balancesQuery.refetch();
|
|
5540
|
+
}, 5e3);
|
|
5541
|
+
setTimeout(() => {
|
|
5542
|
+
queryClient.invalidateQueries({ queryKey: ["earnAccountBalances"] });
|
|
5543
|
+
balancesQuery.refetch();
|
|
5544
|
+
}, 15e3);
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5547
|
+
)
|
|
5548
|
+
}
|
|
5549
|
+
),
|
|
5550
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5551
|
+
EarningsModal,
|
|
5552
|
+
{
|
|
5553
|
+
isOpen: isEarningsModalOpen,
|
|
5554
|
+
onClose: () => setIsEarningsModalOpen(false),
|
|
5555
|
+
positions,
|
|
5556
|
+
totalEarned,
|
|
5557
|
+
isLoading: positionQuery.isLoading
|
|
5558
|
+
}
|
|
5559
|
+
)
|
|
5491
5560
|
] });
|
|
5492
5561
|
}
|
|
5493
5562
|
function getEarliestDepositTimestamp(deposits) {
|
|
@@ -5974,7 +6043,8 @@ function PositionDetailModal({ position, onClose }) {
|
|
|
5974
6043
|
className: "relative w-full max-w-md rounded-xl border overflow-hidden max-h-[90vh] overflow-y-auto",
|
|
5975
6044
|
style: {
|
|
5976
6045
|
backgroundColor: "var(--compass-color-background)",
|
|
5977
|
-
borderColor: "var(--compass-color-border)"
|
|
6046
|
+
borderColor: "var(--compass-color-border)",
|
|
6047
|
+
scrollbarWidth: "none"
|
|
5978
6048
|
},
|
|
5979
6049
|
onClick: (e) => e.stopPropagation(),
|
|
5980
6050
|
children: [
|
|
@@ -6477,7 +6547,7 @@ function useRebalancingData(chainOverride) {
|
|
|
6477
6547
|
if (usdValue <= 0) continue;
|
|
6478
6548
|
balances.push({
|
|
6479
6549
|
token: symbol,
|
|
6480
|
-
balance: parseFloat(td.
|
|
6550
|
+
balance: parseFloat(td.balance || "0"),
|
|
6481
6551
|
usdValue
|
|
6482
6552
|
});
|
|
6483
6553
|
}
|
|
@@ -6763,7 +6833,8 @@ function PortfolioBalanceCard({
|
|
|
6763
6833
|
positionCount,
|
|
6764
6834
|
totalEarned = 0,
|
|
6765
6835
|
showTopUp = true,
|
|
6766
|
-
onTopUp
|
|
6836
|
+
onTopUp,
|
|
6837
|
+
onSwap
|
|
6767
6838
|
}) {
|
|
6768
6839
|
const [showBalancesModal, setShowBalancesModal] = react.useState(false);
|
|
6769
6840
|
const tokenBalances = idleBalances.map((b) => ({
|
|
@@ -6804,39 +6875,59 @@ function PortfolioBalanceCard({
|
|
|
6804
6875
|
]
|
|
6805
6876
|
}
|
|
6806
6877
|
),
|
|
6807
|
-
/* @__PURE__ */ jsxRuntime.
|
|
6808
|
-
|
|
6878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6879
|
+
"button",
|
|
6880
|
+
{
|
|
6881
|
+
onClick: () => setShowBalancesModal(true),
|
|
6882
|
+
className: "transition-opacity hover:opacity-80",
|
|
6883
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6884
|
+
"span",
|
|
6885
|
+
{
|
|
6886
|
+
className: "font-bold",
|
|
6887
|
+
style: {
|
|
6888
|
+
color: "var(--compass-color-text)",
|
|
6889
|
+
fontSize: "2rem",
|
|
6890
|
+
lineHeight: "1"
|
|
6891
|
+
},
|
|
6892
|
+
children: formatUSD(totalUsd)
|
|
6893
|
+
}
|
|
6894
|
+
)
|
|
6895
|
+
}
|
|
6896
|
+
),
|
|
6897
|
+
(onSwap || showTopUp && onTopUp) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "6px", marginTop: "calc(var(--compass-spacing-unit) * 0.5)" }, children: [
|
|
6898
|
+
onSwap && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6809
6899
|
"button",
|
|
6810
6900
|
{
|
|
6811
|
-
onClick:
|
|
6812
|
-
className: "transition-
|
|
6813
|
-
|
|
6814
|
-
"
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
}
|
|
6824
|
-
|
|
6901
|
+
onClick: onSwap,
|
|
6902
|
+
className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
|
|
6903
|
+
style: {
|
|
6904
|
+
backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
|
|
6905
|
+
border: "1px solid var(--compass-color-border)",
|
|
6906
|
+
color: "var(--compass-color-text-secondary)",
|
|
6907
|
+
borderRadius: "var(--compass-border-radius-md)",
|
|
6908
|
+
padding: "8px 10px",
|
|
6909
|
+
gap: "6px",
|
|
6910
|
+
fontSize: "13px"
|
|
6911
|
+
},
|
|
6912
|
+
children: [
|
|
6913
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftRight, { size: 14 }),
|
|
6914
|
+
"Swap"
|
|
6915
|
+
]
|
|
6825
6916
|
}
|
|
6826
6917
|
),
|
|
6827
6918
|
showTopUp && onTopUp && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6828
6919
|
"button",
|
|
6829
6920
|
{
|
|
6830
6921
|
onClick: onTopUp,
|
|
6831
|
-
className: "flex items-center font-medium transition-all hover:opacity-80",
|
|
6922
|
+
className: "flex items-center justify-center font-medium transition-all hover:opacity-80 w-full",
|
|
6832
6923
|
style: {
|
|
6833
6924
|
backgroundColor: "var(--compass-color-surface-elevated, var(--compass-color-surface))",
|
|
6834
6925
|
border: "1px solid var(--compass-color-border)",
|
|
6835
6926
|
color: "var(--compass-color-text-secondary)",
|
|
6836
6927
|
borderRadius: "var(--compass-border-radius-md)",
|
|
6837
|
-
padding: "
|
|
6838
|
-
gap: "
|
|
6839
|
-
fontSize: "
|
|
6928
|
+
padding: "8px 10px",
|
|
6929
|
+
gap: "6px",
|
|
6930
|
+
fontSize: "13px"
|
|
6840
6931
|
},
|
|
6841
6932
|
children: [
|
|
6842
6933
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14 }),
|
|
@@ -7177,7 +7268,6 @@ function AllocationEditor({
|
|
|
7177
7268
|
) })
|
|
7178
7269
|
] });
|
|
7179
7270
|
}
|
|
7180
|
-
var SUPPORTED_TOKENS2 = ["USDC", "USDT", "DAI", "WETH", "SBC", "AUSD"];
|
|
7181
7271
|
var EVM_CHAIN_IDS2 = {
|
|
7182
7272
|
ethereum: 1,
|
|
7183
7273
|
base: 8453,
|
|
@@ -7238,7 +7328,12 @@ function RebalancingWidget({
|
|
|
7238
7328
|
const [txHash, setTxHash] = react.useState(null);
|
|
7239
7329
|
const [hasInitializedTargets, setHasInitializedTargets] = react.useState(false);
|
|
7240
7330
|
const [isEarningsModalOpen, setIsEarningsModalOpen] = react.useState(false);
|
|
7331
|
+
const [isSwapModalOpen, setIsSwapModalOpen] = react.useState(false);
|
|
7241
7332
|
const [isAddMarketExpanded, setIsAddMarketExpanded] = react.useState(false);
|
|
7333
|
+
const balanceTokens = react.useMemo(() => {
|
|
7334
|
+
if (!portfolio?.idleBalances) return [];
|
|
7335
|
+
return portfolio.idleBalances.map((b) => b.token);
|
|
7336
|
+
}, [portfolio?.idleBalances]);
|
|
7242
7337
|
const [marketTab, setMarketTab] = react.useState("variable");
|
|
7243
7338
|
const [selectedMarket, setSelectedMarket] = react.useState(null);
|
|
7244
7339
|
const [selectedToken, setSelectedToken] = react.useState("USDC");
|
|
@@ -7257,13 +7352,14 @@ function RebalancingWidget({
|
|
|
7257
7352
|
setTxHash(null);
|
|
7258
7353
|
setHasInitializedTargets(false);
|
|
7259
7354
|
setIsAddMarketExpanded(false);
|
|
7355
|
+
setIsSwapModalOpen(false);
|
|
7260
7356
|
setSelectedMarket(null);
|
|
7261
7357
|
setDepositAmount("");
|
|
7262
7358
|
setDepositError(null);
|
|
7263
7359
|
setDepositStatus("");
|
|
7264
7360
|
}, [CHAIN_ID]);
|
|
7265
7361
|
react.useEffect(() => {
|
|
7266
|
-
if (portfolio && portfolio.positions.length > 0 && !hasInitializedTargets) {
|
|
7362
|
+
if (portfolio && portfolio.positions.length > 0 && !hasInitializedTargets && !isLoading) {
|
|
7267
7363
|
setTargets(
|
|
7268
7364
|
portfolio.positions.map((p) => ({
|
|
7269
7365
|
venueType: p.venueType,
|
|
@@ -7275,7 +7371,7 @@ function RebalancingWidget({
|
|
|
7275
7371
|
);
|
|
7276
7372
|
setHasInitializedTargets(true);
|
|
7277
7373
|
}
|
|
7278
|
-
}, [portfolio, hasInitializedTargets]);
|
|
7374
|
+
}, [portfolio, hasInitializedTargets, isLoading]);
|
|
7279
7375
|
const state = react.useMemo(() => {
|
|
7280
7376
|
if (isLoading) return "loading";
|
|
7281
7377
|
if (!portfolio || portfolio.positions.length === 0) return "empty";
|
|
@@ -7698,7 +7794,7 @@ function RebalancingWidget({
|
|
|
7698
7794
|
]
|
|
7699
7795
|
}
|
|
7700
7796
|
),
|
|
7701
|
-
state === "empty" && /* @__PURE__ */ jsxRuntime.
|
|
7797
|
+
state === "empty" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7702
7798
|
"div",
|
|
7703
7799
|
{
|
|
7704
7800
|
className: "p-8 text-center",
|
|
@@ -7706,7 +7802,32 @@ function RebalancingWidget({
|
|
|
7706
7802
|
backgroundColor: "var(--compass-color-surface)",
|
|
7707
7803
|
borderRadius: "var(--compass-border-radius-xl)"
|
|
7708
7804
|
},
|
|
7709
|
-
children: [
|
|
7805
|
+
children: !isConnected ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7806
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7807
|
+
"p",
|
|
7808
|
+
{
|
|
7809
|
+
className: "text-lg font-semibold mb-2",
|
|
7810
|
+
style: { color: "var(--compass-color-text)" },
|
|
7811
|
+
children: "Connect your wallet"
|
|
7812
|
+
}
|
|
7813
|
+
),
|
|
7814
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mb-4", style: { color: "var(--compass-color-text-secondary)" }, children: "Connect your wallet to view and manage your DeFi portfolio." }),
|
|
7815
|
+
login && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7816
|
+
"button",
|
|
7817
|
+
{
|
|
7818
|
+
onClick: login,
|
|
7819
|
+
className: "font-semibold transition-all",
|
|
7820
|
+
style: {
|
|
7821
|
+
backgroundColor: "var(--compass-color-primary)",
|
|
7822
|
+
color: "var(--compass-color-primary-text, white)",
|
|
7823
|
+
borderRadius: "var(--compass-border-radius-lg)",
|
|
7824
|
+
padding: "calc(var(--compass-spacing-unit) * 0.75) calc(var(--compass-spacing-unit) * 1.5)",
|
|
7825
|
+
fontSize: "0.875rem"
|
|
7826
|
+
},
|
|
7827
|
+
children: "Connect Wallet"
|
|
7828
|
+
}
|
|
7829
|
+
)
|
|
7830
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7710
7831
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7711
7832
|
"p",
|
|
7712
7833
|
{
|
|
@@ -7716,7 +7837,7 @@ function RebalancingWidget({
|
|
|
7716
7837
|
}
|
|
7717
7838
|
),
|
|
7718
7839
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", style: { color: "var(--compass-color-text-secondary)" }, children: "Deposit into a vault, Aave market, or Pendle market to start rebalancing." })
|
|
7719
|
-
]
|
|
7840
|
+
] })
|
|
7720
7841
|
}
|
|
7721
7842
|
),
|
|
7722
7843
|
state !== "loading" && state !== "empty" && portfolio && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { gap: "calc(var(--compass-spacing-unit) * 0.75)" }, children: [
|
|
@@ -7730,7 +7851,8 @@ function RebalancingWidget({
|
|
|
7730
7851
|
positionCount: portfolio.positions.length,
|
|
7731
7852
|
totalEarned,
|
|
7732
7853
|
showTopUp,
|
|
7733
|
-
onTopUp: () => earnBalanceRef.current?.openTransferModal()
|
|
7854
|
+
onTopUp: () => earnBalanceRef.current?.openTransferModal(),
|
|
7855
|
+
onSwap: balanceTokens.length > 0 ? () => setIsSwapModalOpen(true) : void 0
|
|
7734
7856
|
}
|
|
7735
7857
|
),
|
|
7736
7858
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -7850,7 +7972,7 @@ function RebalancingWidget({
|
|
|
7850
7972
|
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
7851
7973
|
minWidth: "100px"
|
|
7852
7974
|
},
|
|
7853
|
-
children:
|
|
7975
|
+
children: balanceTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7854
7976
|
"button",
|
|
7855
7977
|
{
|
|
7856
7978
|
onClick: () => {
|
|
@@ -8190,6 +8312,30 @@ function RebalancingWidget({
|
|
|
8190
8312
|
}
|
|
8191
8313
|
) }),
|
|
8192
8314
|
/* @__PURE__ */ jsxRuntime.jsx(EarnAccountBalance, { ref: earnBalanceRef, compact: true, hideVisual: true, onTransferComplete: () => refetch() }),
|
|
8315
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8316
|
+
ActionModal,
|
|
8317
|
+
{
|
|
8318
|
+
isOpen: isSwapModalOpen,
|
|
8319
|
+
onClose: () => setIsSwapModalOpen(false),
|
|
8320
|
+
title: "Swap Tokens",
|
|
8321
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8322
|
+
SwapForm,
|
|
8323
|
+
{
|
|
8324
|
+
availableFromTokens: balanceTokens,
|
|
8325
|
+
balances: Object.fromEntries(
|
|
8326
|
+
(portfolio?.idleBalances || []).map((b) => [b.token, b.balance.toString()])
|
|
8327
|
+
),
|
|
8328
|
+
onSwapSuccess: () => {
|
|
8329
|
+
setIsSwapModalOpen(false);
|
|
8330
|
+
refetch();
|
|
8331
|
+
setTimeout(() => refetch(), 5e3);
|
|
8332
|
+
setTimeout(() => refetch(), 15e3);
|
|
8333
|
+
},
|
|
8334
|
+
onSwapError: onError
|
|
8335
|
+
}
|
|
8336
|
+
)
|
|
8337
|
+
}
|
|
8338
|
+
),
|
|
8193
8339
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8194
8340
|
EarningsModal,
|
|
8195
8341
|
{
|
|
@@ -8247,7 +8393,6 @@ function ActionList({ actions }) {
|
|
|
8247
8393
|
|
|
8248
8394
|
// src/components/CompassEarnWidget/presets.ts
|
|
8249
8395
|
var allTabs = [
|
|
8250
|
-
{ id: "swap", label: "Swap", enabled: true },
|
|
8251
8396
|
{ id: "rebalance", label: "Rebalance", enabled: true },
|
|
8252
8397
|
// TODO: Positions tab temporarily disabled - needs more work on API response handling
|
|
8253
8398
|
{ id: "positions", label: "Positions", enabled: false }
|
|
@@ -8256,22 +8401,16 @@ function getTabsForPreset(preset) {
|
|
|
8256
8401
|
switch (preset) {
|
|
8257
8402
|
case "full":
|
|
8258
8403
|
return allTabs;
|
|
8259
|
-
case "swap-only":
|
|
8260
|
-
return allTabs.map((tab) => ({
|
|
8261
|
-
...tab,
|
|
8262
|
-
enabled: tab.id === "swap"
|
|
8263
|
-
}));
|
|
8264
8404
|
default:
|
|
8265
8405
|
return allTabs;
|
|
8266
8406
|
}
|
|
8267
8407
|
}
|
|
8268
8408
|
function getDefaultTab(tabs) {
|
|
8269
8409
|
const enabledTab = tabs.find((t) => t.enabled);
|
|
8270
|
-
return enabledTab?.id || "
|
|
8410
|
+
return enabledTab?.id || "rebalance";
|
|
8271
8411
|
}
|
|
8272
8412
|
function CompassEarnWidget({
|
|
8273
8413
|
preset = "full",
|
|
8274
|
-
enableSwap,
|
|
8275
8414
|
enablePositions,
|
|
8276
8415
|
enableRebalance,
|
|
8277
8416
|
defaultTab,
|
|
@@ -8283,12 +8422,11 @@ function CompassEarnWidget({
|
|
|
8283
8422
|
const baseTabs = getTabsForPreset(preset);
|
|
8284
8423
|
return baseTabs.map((tab) => {
|
|
8285
8424
|
let enabled = tab.enabled;
|
|
8286
|
-
if (tab.id === "swap" && enableSwap !== void 0) enabled = enableSwap;
|
|
8287
8425
|
if (tab.id === "positions" && enablePositions !== void 0) enabled = enablePositions;
|
|
8288
8426
|
if (tab.id === "rebalance" && enableRebalance !== void 0) enabled = enableRebalance;
|
|
8289
8427
|
return { ...tab, enabled };
|
|
8290
8428
|
});
|
|
8291
|
-
}, [preset,
|
|
8429
|
+
}, [preset, enablePositions, enableRebalance]);
|
|
8292
8430
|
const enabledTabs = tabs.filter((t) => t.enabled);
|
|
8293
8431
|
const initialTab = defaultTab && tabs.find((t) => t.id === defaultTab)?.enabled ? defaultTab : getDefaultTab(tabs);
|
|
8294
8432
|
const [activeTab, setActiveTab] = react.useState(initialTab);
|
|
@@ -8329,7 +8467,6 @@ function CompassEarnWidget({
|
|
|
8329
8467
|
}
|
|
8330
8468
|
),
|
|
8331
8469
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
8332
|
-
activeTab === "swap" && /* @__PURE__ */ jsxRuntime.jsx(SwapWidget, {}),
|
|
8333
8470
|
activeTab === "rebalance" && /* @__PURE__ */ jsxRuntime.jsx(RebalancingWidget, {}),
|
|
8334
8471
|
activeTab === "positions" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8335
8472
|
EarnPositionsList,
|
|
@@ -8368,14 +8505,13 @@ exports.CHAINS = CHAINS;
|
|
|
8368
8505
|
exports.ChainSwitcher = ChainSwitcher;
|
|
8369
8506
|
exports.CompassEarnWidget = CompassEarnWidget;
|
|
8370
8507
|
exports.CompassProvider = CompassProvider;
|
|
8371
|
-
exports.DEFAULT_SWAP_TOKENS = DEFAULT_SWAP_TOKENS;
|
|
8372
8508
|
exports.DepositWithdrawForm = DepositWithdrawForm;
|
|
8373
8509
|
exports.EarnAccount = EarnAccount;
|
|
8374
8510
|
exports.EarnAccountBalance = EarnAccountBalance;
|
|
8375
8511
|
exports.EarnAccountGuard = EarnAccountGuard;
|
|
8376
8512
|
exports.PnLSummary = PnLSummary;
|
|
8377
8513
|
exports.RebalancingWidget = RebalancingWidget;
|
|
8378
|
-
exports.
|
|
8514
|
+
exports.SwapForm = SwapForm;
|
|
8379
8515
|
exports.ThemeProvider = ThemeProvider;
|
|
8380
8516
|
exports.TransactionHistory = TransactionHistory;
|
|
8381
8517
|
exports.WalletStatus = WalletStatus;
|