@hfunlabs/hypurr-connect 0.1.11 → 0.1.13

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 CHANGED
@@ -4,7 +4,6 @@ import {
4
4
  HttpTransport
5
5
  } from "@hfunlabs/hyperliquid";
6
6
  import {
7
- PrivateKeySigner,
8
7
  signUserSignedAction
9
8
  } from "@hfunlabs/hyperliquid/signing";
10
9
  import {
@@ -17,6 +16,25 @@ import {
17
16
  useState
18
17
  } from "react";
19
18
 
19
+ // src/privateKeySigner.ts
20
+ import { privateKeyToAccount } from "viem/accounts";
21
+ var PrivateKeySigner = class {
22
+ #account;
23
+ address;
24
+ constructor(privateKey) {
25
+ this.#account = privateKeyToAccount(normalizePrivateKey(privateKey));
26
+ this.address = this.#account.address;
27
+ }
28
+ signTypedData(params) {
29
+ return this.#account.signTypedData(
30
+ params
31
+ );
32
+ }
33
+ };
34
+ function normalizePrivateKey(privateKey) {
35
+ return privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
36
+ }
37
+
20
38
  // src/agent.ts
21
39
  var AGENT_NAME = "hypurr-connect";
22
40
  var AGENT_STORAGE_PREFIX = "hypurr-connect-agent";
@@ -41,8 +59,7 @@ async function generateAgentKey() {
41
59
  const bytes = crypto.getRandomValues(new Uint8Array(32));
42
60
  const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
43
61
  const privateKey = `0x${hex}`;
44
- const { PrivateKeySigner: PrivateKeySigner2 } = await import("@hfunlabs/hyperliquid/signing");
45
- const signer = new PrivateKeySigner2(privateKey);
62
+ const signer = new PrivateKeySigner(privateKey);
46
63
  return { privateKey, address: signer.address };
47
64
  }
48
65
  async function fetchActiveAgent(userAddress, isTestnet) {
@@ -188,6 +205,7 @@ var TELEGRAM_AUTH_STATE_KEY = "hypurr-connect-auth-state";
188
205
  var TELEGRAM_AUTH_MESSAGE = "hypurr-connect:telegram-auth";
189
206
  var DEFAULT_AUTH_HUB_URL = "https://auth.hypurr.fun/login";
190
207
  var DEFAULT_MEDIA_URL = "https://media.hypurr.fun";
208
+ var IGNORED_EXTERNAL_SIGNATURE = "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b";
191
209
  var DEFAULT_TELEGRAM_SCOPES = [
192
210
  "telegram:user:read",
193
211
  "telegram:wallet:read",
@@ -196,8 +214,19 @@ var DEFAULT_TELEGRAM_SCOPES = [
196
214
  "telegram:trade:write",
197
215
  "telegram:cabal:read",
198
216
  "telegram:cabal:write",
199
- "telegram:agent:write"
217
+ "telegram:agent:write",
218
+ "telegram:support:read",
219
+ "telegram:support:write"
200
220
  ];
221
+ function createExternalSigningWallet(address) {
222
+ return {
223
+ address,
224
+ signTypedData(params) {
225
+ void params;
226
+ return Promise.resolve(IGNORED_EXTERNAL_SIGNATURE);
227
+ }
228
+ };
229
+ }
201
230
  function isInvalidTelegramAuthError(err) {
202
231
  const msg = err instanceof Error ? err.message : typeof err === "object" && err !== null && "message" in err ? String(err.message) : String(err);
203
232
  return /invalid telegram auth data|invalid auth token|missing authorization token/i.test(
@@ -207,6 +236,47 @@ function isInvalidTelegramAuthError(err) {
207
236
  function normalizeMediaUrl(mediaUrl) {
208
237
  return (mediaUrl?.trim() || DEFAULT_MEDIA_URL).replace(/\/+$/, "");
209
238
  }
239
+ function isAddress(value) {
240
+ return !!value && /^0x[a-fA-F0-9]{40}$/.test(value);
241
+ }
242
+ function getRawSignedTransaction(result) {
243
+ if (typeof result === "string" && result.startsWith("0x")) {
244
+ return result;
245
+ }
246
+ if (!result || typeof result !== "object") return null;
247
+ const record = result;
248
+ const candidates = [
249
+ record.raw,
250
+ record.rawTransaction,
251
+ record.signedTransaction,
252
+ record.serializedTransaction,
253
+ record.result
254
+ ];
255
+ const raw = candidates.find(
256
+ (value) => typeof value === "string" && value.startsWith("0x")
257
+ );
258
+ return raw ? raw : null;
259
+ }
260
+ function decodeJsonBytes(bytes) {
261
+ const text = new TextDecoder().decode(bytes);
262
+ if (!text) return null;
263
+ try {
264
+ return JSON.parse(text);
265
+ } catch {
266
+ return text;
267
+ }
268
+ }
269
+ function encodeJsonBytes(value) {
270
+ return new TextEncoder().encode(JSON.stringify(value));
271
+ }
272
+ function withExpectedFrom(transaction, address) {
273
+ if (transaction.from && transaction.from.toLowerCase() !== address.toLowerCase()) {
274
+ throw new Error(
275
+ "[HypurrConnect] EVM transaction `from` does not match the connected wallet."
276
+ );
277
+ }
278
+ return transaction.from ? transaction : { ...transaction, from: address };
279
+ }
210
280
  function currentReturnTo() {
211
281
  const url = new URL(window.location.href);
212
282
  for (const param of [
@@ -474,7 +544,10 @@ function HypurrConnectProvider({
474
544
  address: selectedWallet.ethereumAddress,
475
545
  walletId: selectedWallet.id,
476
546
  displayName: tgUser.telegramUsername ? `@${tgUser.telegramUsername}` : `Telegram ${tgUser.telegramId}`,
477
- photoUrl: tgUser.pictureFileId ? `${mediaUrl}/${tgUser.pictureFileId}` : void 0,
547
+ photoUrl: (() => {
548
+ const fileId = tgUser.pictureFileId;
549
+ return fileId ? `${mediaUrl}/${fileId}` : void 0;
550
+ })(),
478
551
  authMethod: "telegram",
479
552
  telegramId: String(tgUser.telegramId),
480
553
  hfunScore: tgUser?.reputation?.hfunScore,
@@ -525,8 +598,7 @@ function HypurrConnectProvider({
525
598
  });
526
599
  return new ExchangeClient({
527
600
  transport,
528
- externalSigning: true,
529
- userAddress: user.address
601
+ wallet: createExternalSigningWallet(user.address)
530
602
  });
531
603
  }
532
604
  if (authMethod === "eoa" && eoaAddress) {
@@ -542,8 +614,7 @@ function HypurrConnectProvider({
542
614
  };
543
615
  return new ExchangeClient({
544
616
  transport: noAgentTransport,
545
- externalSigning: true,
546
- userAddress: eoaAddress
617
+ wallet: createExternalSigningWallet(eoaAddress)
547
618
  });
548
619
  }
549
620
  const isTestnet = config.isTestnet ?? false;
@@ -684,6 +755,81 @@ function HypurrConnectProvider({
684
755
  setAgent(null);
685
756
  }
686
757
  }, [eoaAddress]);
758
+ const signEvmTransaction = useCallback(
759
+ async (transaction) => {
760
+ if (authMethod === "eoa") {
761
+ if (!eoaAddress) {
762
+ throw new Error("[HypurrConnect] No EOA wallet connected.");
763
+ }
764
+ const signer = eoaSignerRef.current;
765
+ if (!signer) {
766
+ throw new Error(
767
+ "[HypurrConnect] No EOA signer available. Pass a signer to connectEoa(address, signer)."
768
+ );
769
+ }
770
+ const tx = withExpectedFrom(transaction, eoaAddress);
771
+ const result = signer.signTransaction ? await signer.signTransaction(tx) : signer.request ? await signer.request({
772
+ method: "eth_signTransaction",
773
+ params: [tx]
774
+ }) : null;
775
+ const rawTransaction = getRawSignedTransaction(result);
776
+ if (!rawTransaction) {
777
+ throw new Error(
778
+ "[HypurrConnect] EOA signer did not return a raw transaction."
779
+ );
780
+ }
781
+ return rawTransaction;
782
+ }
783
+ if (authMethod === "telegram") {
784
+ if (!telegramRpcOptions) {
785
+ throw new Error("[HypurrConnect] No Telegram RPC session available.");
786
+ }
787
+ if (!selectedWallet) {
788
+ throw new Error("[HypurrConnect] No Telegram wallet selected.");
789
+ }
790
+ if (selectedWallet.id <= 0 || selectedWallet.isReadOnly || selectedWallet.isAgent) {
791
+ throw new Error(
792
+ "[HypurrConnect] Select a Telegram private-key wallet to sign EVM transactions."
793
+ );
794
+ }
795
+ if (!isAddress(selectedWallet.ethereumAddress)) {
796
+ throw new Error(
797
+ "[HypurrConnect] Selected Telegram wallet does not have a valid EVM address."
798
+ );
799
+ }
800
+ const tx = withExpectedFrom(
801
+ transaction,
802
+ selectedWallet.ethereumAddress
803
+ );
804
+ try {
805
+ const signResponse = await tgClient.eVMSignTransaction(
806
+ {
807
+ authData: {},
808
+ walletId: selectedWallet.id,
809
+ params: encodeJsonBytes(tx)
810
+ },
811
+ telegramRpcOptions
812
+ );
813
+ const rawTransaction = getRawSignedTransaction(
814
+ decodeJsonBytes(signResponse.response.result)
815
+ );
816
+ if (!rawTransaction) {
817
+ throw new Error(
818
+ "[HypurrConnect] Telegram signer did not return a raw transaction."
819
+ );
820
+ }
821
+ return rawTransaction;
822
+ } catch (err) {
823
+ if (isInvalidTelegramAuthError(err)) {
824
+ onInvalidAuthRef.current?.();
825
+ }
826
+ throw err;
827
+ }
828
+ }
829
+ throw new Error("[HypurrConnect] No wallet connected.");
830
+ },
831
+ [authMethod, eoaAddress, selectedWallet, telegramRpcOptions, tgClient]
832
+ );
687
833
  const createWallet = useCallback(
688
834
  async (name) => {
689
835
  const { response } = await tgClient.hyperliquidWalletCreate(
@@ -717,6 +863,20 @@ function HypurrConnectProvider({
717
863
  },
718
864
  [tgClient, telegramRpcOptions, selectedWalletId, wallets, refreshWallets]
719
865
  );
866
+ const renameWallet = useCallback(
867
+ async (walletId, name) => {
868
+ await tgClient.hyperliquidWalletUpdate(
869
+ {
870
+ authData: {},
871
+ walletId,
872
+ name
873
+ },
874
+ telegramRpcOptions
875
+ );
876
+ refreshWallets();
877
+ },
878
+ [tgClient, telegramRpcOptions, refreshWallets]
879
+ );
720
880
  const createWalletPack = useCallback(
721
881
  async (name) => {
722
882
  const { response } = await tgClient.telegramChatWalletPackCreate(
@@ -890,12 +1050,12 @@ function HypurrConnectProvider({
890
1050
  const loginTelegram = useCallback(() => {
891
1051
  const state = randomState();
892
1052
  sessionStorage.setItem(TELEGRAM_AUTH_STATE_KEY, state);
893
- const configuredReturnTo = config.telegram.returnTo;
1053
+ const configuredReturnTo = config.telegram?.returnTo;
894
1054
  const returnTo = typeof configuredReturnTo === "function" ? configuredReturnTo() : configuredReturnTo || currentReturnTo();
895
- const authUrl = new URL(config.telegram.authHubUrl || DEFAULT_AUTH_HUB_URL);
1055
+ const authUrl = new URL(config.telegram?.authHubUrl || DEFAULT_AUTH_HUB_URL);
896
1056
  authUrl.searchParams.set("return_to", returnTo);
897
1057
  authUrl.searchParams.set("state", state);
898
- authUrl.searchParams.set("scope", normalizeScopes(config.telegram.scope));
1058
+ authUrl.searchParams.set("scope", normalizeScopes(config.telegram?.scope));
899
1059
  const width = 520;
900
1060
  const height = 720;
901
1061
  const left = window.screenX + Math.max(0, (window.outerWidth - width) / 2);
@@ -918,9 +1078,9 @@ function HypurrConnectProvider({
918
1078
  }
919
1079
  window.location.assign(authUrl.toString());
920
1080
  }, [
921
- config.telegram.authHubUrl,
922
- config.telegram.returnTo,
923
- config.telegram.scope
1081
+ config.telegram?.authHubUrl,
1082
+ config.telegram?.returnTo,
1083
+ config.telegram?.scope
924
1084
  ]);
925
1085
  const connectEoa = useCallback(
926
1086
  (address, signer) => {
@@ -949,7 +1109,13 @@ function HypurrConnectProvider({
949
1109
  "[HypurrConnect] Cannot approve agent: no EOA wallet connected. Call connectEoa(address) first."
950
1110
  );
951
1111
  }
952
- eoaSignerRef.current = { signTypedData: signTypedDataAsync, chainId };
1112
+ const currentSigner = eoaSignerRef.current;
1113
+ eoaSignerRef.current = {
1114
+ signTypedData: signTypedDataAsync,
1115
+ signTransaction: currentSigner?.signTransaction,
1116
+ request: currentSigner?.request,
1117
+ chainId
1118
+ };
953
1119
  setEoaLoading(true);
954
1120
  setEoaError(null);
955
1121
  try {
@@ -1052,6 +1218,7 @@ function HypurrConnectProvider({
1052
1218
  selectWallet,
1053
1219
  createWallet,
1054
1220
  deleteWallet,
1221
+ renameWallet,
1055
1222
  refreshWallets,
1056
1223
  packs,
1057
1224
  createWalletPack,
@@ -1068,14 +1235,12 @@ function HypurrConnectProvider({
1068
1235
  closeLoginModal,
1069
1236
  loginTelegram,
1070
1237
  connectEoa,
1238
+ signEvmTransaction,
1071
1239
  approveAgent: approveAgentFn,
1072
1240
  logout,
1073
1241
  agent,
1074
1242
  agentReady,
1075
1243
  clearAgent: handleClearAgent,
1076
- botId: config.telegram?.botId ?? "",
1077
- botUsername: config.telegram?.botUsername ?? "",
1078
- useWidget: config.telegram?.useWidget ?? false,
1079
1244
  authDataMap,
1080
1245
  authToken: tgAuthToken,
1081
1246
  telegramRpcOptions,
@@ -1095,6 +1260,7 @@ function HypurrConnectProvider({
1095
1260
  selectWallet,
1096
1261
  createWallet,
1097
1262
  deleteWallet,
1263
+ renameWallet,
1098
1264
  refreshWallets,
1099
1265
  packs,
1100
1266
  createWalletPack,
@@ -1111,14 +1277,12 @@ function HypurrConnectProvider({
1111
1277
  closeLoginModal,
1112
1278
  loginTelegram,
1113
1279
  connectEoa,
1280
+ signEvmTransaction,
1114
1281
  approveAgentFn,
1115
1282
  logout,
1116
1283
  agent,
1117
1284
  agentReady,
1118
1285
  handleClearAgent,
1119
- config.telegram?.botId,
1120
- config.telegram?.botUsername,
1121
- config.telegram?.useWidget,
1122
1286
  authDataMap,
1123
1287
  tgAuthToken,
1124
1288
  telegramRpcOptions,
@@ -1532,18 +1696,2563 @@ function MobileDrawer({
1532
1696
  ] });
1533
1697
  }
1534
1698
 
1699
+ // src/WalletSelectorDropdown.tsx
1700
+ import { AnimatePresence as AnimatePresence5, motion as motion5 } from "framer-motion";
1701
+ import {
1702
+ Fragment as Fragment5,
1703
+ useCallback as useCallback6,
1704
+ useMemo as useMemo2,
1705
+ useState as useState5
1706
+ } from "react";
1707
+
1708
+ // src/UserProfileModal.tsx
1709
+ import { AnimatePresence as AnimatePresence4, motion as motion4 } from "framer-motion";
1710
+ import {
1711
+ useCallback as useCallback5,
1712
+ useState as useState4
1713
+ } from "react";
1714
+
1715
+ // src/DeleteWalletModal.tsx
1716
+ import { AnimatePresence as AnimatePresence2, motion as motion2 } from "framer-motion";
1717
+ import {
1718
+ useCallback as useCallback3,
1719
+ useState as useState2
1720
+ } from "react";
1721
+
1722
+ // src/icons/lucide.tsx
1723
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1724
+ function svgBase({
1725
+ size = 16,
1726
+ color = "currentColor",
1727
+ fill = "none",
1728
+ ...rest
1729
+ }) {
1730
+ return {
1731
+ width: size,
1732
+ height: size,
1733
+ viewBox: "0 0 24 24",
1734
+ fill,
1735
+ stroke: color,
1736
+ strokeWidth: 2,
1737
+ strokeLinecap: "round",
1738
+ strokeLinejoin: "round",
1739
+ ...rest
1740
+ };
1741
+ }
1742
+ function Copy(props) {
1743
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1744
+ /* @__PURE__ */ jsx5("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
1745
+ /* @__PURE__ */ jsx5("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
1746
+ ] });
1747
+ }
1748
+ function Star(props) {
1749
+ return /* @__PURE__ */ jsx5("svg", { ...svgBase(props), children: /* @__PURE__ */ jsx5("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" }) });
1750
+ }
1751
+ function User(props) {
1752
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1753
+ /* @__PURE__ */ jsx5("path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" }),
1754
+ /* @__PURE__ */ jsx5("circle", { cx: "12", cy: "7", r: "4" })
1755
+ ] });
1756
+ }
1757
+ function Zap(props) {
1758
+ return /* @__PURE__ */ jsx5("svg", { ...svgBase(props), children: /* @__PURE__ */ jsx5("polygon", { points: "13 2 3 14 12 14 11 22 21 10 12 10 13 2" }) });
1759
+ }
1760
+ function Wallet(props) {
1761
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1762
+ /* @__PURE__ */ jsx5("path", { d: "M20 12V8H6a2 2 0 0 1-2-2c0-1.1.9-2 2-2h12v4" }),
1763
+ /* @__PURE__ */ jsx5("path", { d: "M4 6v12c0 1.1.9 2 2 2h14v-4" }),
1764
+ /* @__PURE__ */ jsx5("path", { d: "M18 12a2 2 0 0 0-2 2c0 1.1.9 2 2 2h4v-4z" })
1765
+ ] });
1766
+ }
1767
+ function TrendingUp(props) {
1768
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1769
+ /* @__PURE__ */ jsx5("polyline", { points: "22 7 13.5 15.5 8.5 10.5 2 17" }),
1770
+ /* @__PURE__ */ jsx5("polyline", { points: "16 7 22 7 22 13" })
1771
+ ] });
1772
+ }
1773
+ function Trash2(props) {
1774
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1775
+ /* @__PURE__ */ jsx5("path", { d: "M3 6h18" }),
1776
+ /* @__PURE__ */ jsx5("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
1777
+ /* @__PURE__ */ jsx5("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }),
1778
+ /* @__PURE__ */ jsx5("line", { x1: "10", x2: "10", y1: "11", y2: "17" }),
1779
+ /* @__PURE__ */ jsx5("line", { x1: "14", x2: "14", y1: "11", y2: "17" })
1780
+ ] });
1781
+ }
1782
+ function Pencil(props) {
1783
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1784
+ /* @__PURE__ */ jsx5("path", { d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" }),
1785
+ /* @__PURE__ */ jsx5("path", { d: "m15 5 4 4" })
1786
+ ] });
1787
+ }
1788
+ function LayoutDashboard(props) {
1789
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1790
+ /* @__PURE__ */ jsx5("rect", { width: "7", height: "9", x: "3", y: "3", rx: "1" }),
1791
+ /* @__PURE__ */ jsx5("rect", { width: "7", height: "5", x: "14", y: "3", rx: "1" }),
1792
+ /* @__PURE__ */ jsx5("rect", { width: "7", height: "9", x: "14", y: "12", rx: "1" }),
1793
+ /* @__PURE__ */ jsx5("rect", { width: "7", height: "5", x: "3", y: "16", rx: "1" })
1794
+ ] });
1795
+ }
1796
+ function AlertTriangle(props) {
1797
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1798
+ /* @__PURE__ */ jsx5("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
1799
+ /* @__PURE__ */ jsx5("line", { x1: "12", x2: "12", y1: "9", y2: "13" }),
1800
+ /* @__PURE__ */ jsx5("line", { x1: "12", x2: "12.01", y1: "17", y2: "17" })
1801
+ ] });
1802
+ }
1803
+ function Loader2(props) {
1804
+ const { size = 16, color = "currentColor", style, ...rest } = props;
1805
+ return /* @__PURE__ */ jsx5(
1806
+ "svg",
1807
+ {
1808
+ width: size,
1809
+ height: size,
1810
+ viewBox: "0 0 24 24",
1811
+ fill: "none",
1812
+ stroke: color,
1813
+ strokeWidth: 2,
1814
+ strokeLinecap: "round",
1815
+ strokeLinejoin: "round",
1816
+ style: {
1817
+ animation: "hypurr-spin 1s linear infinite",
1818
+ ...style
1819
+ },
1820
+ ...rest,
1821
+ children: /* @__PURE__ */ jsx5("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
1822
+ }
1823
+ );
1824
+ }
1825
+ function Crown(props) {
1826
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1827
+ /* @__PURE__ */ jsx5("path", { d: "M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z" }),
1828
+ /* @__PURE__ */ jsx5("path", { d: "M5 21h14" })
1829
+ ] });
1830
+ }
1831
+ function Folder(props) {
1832
+ return /* @__PURE__ */ jsx5("svg", { ...svgBase(props), children: /* @__PURE__ */ jsx5("path", { d: "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" }) });
1833
+ }
1834
+ function LogOut(props) {
1835
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1836
+ /* @__PURE__ */ jsx5("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
1837
+ /* @__PURE__ */ jsx5("polyline", { points: "16 17 21 12 16 7" }),
1838
+ /* @__PURE__ */ jsx5("line", { x1: "21", x2: "9", y1: "12", y2: "12" })
1839
+ ] });
1840
+ }
1841
+ function Plus(props) {
1842
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1843
+ /* @__PURE__ */ jsx5("path", { d: "M5 12h14" }),
1844
+ /* @__PURE__ */ jsx5("path", { d: "M12 5v14" })
1845
+ ] });
1846
+ }
1847
+ function X(props) {
1848
+ return /* @__PURE__ */ jsxs4("svg", { ...svgBase(props), children: [
1849
+ /* @__PURE__ */ jsx5("path", { d: "M18 6 6 18" }),
1850
+ /* @__PURE__ */ jsx5("path", { d: "m6 6 12 12" })
1851
+ ] });
1852
+ }
1853
+ function SpinKeyframes() {
1854
+ return /* @__PURE__ */ jsx5("style", { children: `@keyframes hypurr-spin { to { transform: rotate(360deg); } }` });
1855
+ }
1856
+
1857
+ // src/profileStyles.ts
1858
+ var profileColors = {
1859
+ accent: "#a855f7",
1860
+ panel: "rgba(14,18,24,0.8)",
1861
+ panelSolid: "#0e1218",
1862
+ backdrop: "rgba(0,0,0,0.7)",
1863
+ border: "#1f2937",
1864
+ surfaceBtn: "#0D1219",
1865
+ surfaceBtnHover: "#15171A",
1866
+ surfaceBtnActive: "#1E2124",
1867
+ surfaceBd: "#262A30",
1868
+ surfaceBdHover: "#444548",
1869
+ surfaceBdActive: "#4B4D50",
1870
+ text: "#ffffff",
1871
+ muted: "#aab1c1",
1872
+ subdued: "#7d8597",
1873
+ disabled: "#4b5563",
1874
+ danger: "#f87171",
1875
+ dangerStrong: "#ef4444",
1876
+ purple: "#d8b4fe",
1877
+ yellow: "#eab308"
1878
+ };
1879
+ var fontFamily = {
1880
+ sans: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif",
1881
+ mono: "Google Sans Code, Roboto Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"
1882
+ };
1883
+ var colorWithAlpha = (color, alpha) => {
1884
+ const hex = color.trim();
1885
+ const shortHex = /^#([0-9a-f]{3})$/i.exec(hex);
1886
+ const longHex = /^#([0-9a-f]{6})$/i.exec(hex);
1887
+ if (shortHex) {
1888
+ const [r, g, b] = shortHex[1].split("").map((value) => value + value);
1889
+ return `rgba(${parseInt(r, 16)},${parseInt(g, 16)},${parseInt(b, 16)},${alpha})`;
1890
+ }
1891
+ if (longHex) {
1892
+ const value = longHex[1];
1893
+ return `rgba(${parseInt(value.slice(0, 2), 16)},${parseInt(
1894
+ value.slice(2, 4),
1895
+ 16
1896
+ )},${parseInt(value.slice(4, 6), 16)},${alpha})`;
1897
+ }
1898
+ return `color-mix(in srgb, ${color} ${Math.round(alpha * 100)}%, transparent)`;
1899
+ };
1900
+ var resolvePrincipalColors = (accentColor, overrides = {}) => {
1901
+ const hasCustomAccent = !!accentColor || !!overrides.accent;
1902
+ const accent = overrides.accent ?? accentColor ?? profileColors.accent;
1903
+ const accentText = overrides.accentText ?? (hasCustomAccent ? accent : profileColors.purple);
1904
+ return {
1905
+ accent,
1906
+ accentText,
1907
+ accentBackground: overrides.accentBackground ?? colorWithAlpha(accent, 0.1),
1908
+ accentBorder: overrides.accentBorder ?? colorWithAlpha(accent, 0.25),
1909
+ accentHoverBackground: overrides.accentHoverBackground ?? colorWithAlpha(accent, 0.1)
1910
+ };
1911
+ };
1912
+ var modalBackdropStyle = (zIndex) => ({
1913
+ position: "fixed",
1914
+ inset: 0,
1915
+ zIndex,
1916
+ background: profileColors.backdrop,
1917
+ backdropFilter: "blur(4px)",
1918
+ WebkitBackdropFilter: "blur(4px)"
1919
+ });
1920
+ var modalWrapperStyle2 = (zIndex, padding = 0) => ({
1921
+ position: "fixed",
1922
+ inset: 0,
1923
+ zIndex,
1924
+ display: "flex",
1925
+ alignItems: "center",
1926
+ justifyContent: "center",
1927
+ padding
1928
+ });
1929
+ var modalPanelStyle = (solid = false) => ({
1930
+ position: "relative",
1931
+ width: "100%",
1932
+ maxWidth: 448,
1933
+ background: solid ? profileColors.panelSolid : profileColors.panel,
1934
+ backdropFilter: solid ? void 0 : "blur(10px)",
1935
+ WebkitBackdropFilter: solid ? void 0 : "blur(10px)",
1936
+ border: `1px solid ${profileColors.border}`,
1937
+ borderRadius: 8,
1938
+ boxShadow: "0 25px 50px -12px rgba(0,0,0,0.6)",
1939
+ overflow: "hidden",
1940
+ fontFamily: fontFamily.sans
1941
+ });
1942
+ var modalHeaderStyle = {
1943
+ position: "relative",
1944
+ display: "flex",
1945
+ alignItems: "center",
1946
+ justifyContent: "center",
1947
+ padding: "24px 24px 20px",
1948
+ borderBottom: `1px solid ${profileColors.border}`
1949
+ };
1950
+ var titleStyle = {
1951
+ margin: 0,
1952
+ fontSize: 14,
1953
+ lineHeight: "1.25rem",
1954
+ fontWeight: 600,
1955
+ color: profileColors.text
1956
+ };
1957
+ var closeBtnStyle = (disabled = false) => ({
1958
+ position: "absolute",
1959
+ right: 24,
1960
+ background: "transparent",
1961
+ border: "none",
1962
+ color: profileColors.muted,
1963
+ cursor: disabled ? "not-allowed" : "pointer",
1964
+ padding: 0,
1965
+ display: "flex",
1966
+ opacity: disabled ? 0.4 : 1,
1967
+ transition: "color 150ms"
1968
+ });
1969
+ var upperLabelStyle = {
1970
+ fontSize: 11,
1971
+ lineHeight: "1rem",
1972
+ fontWeight: 500,
1973
+ textTransform: "uppercase",
1974
+ letterSpacing: "0.1em"
1975
+ };
1976
+ var raisedButtonStyle = (state = "default") => {
1977
+ if (state === "active") {
1978
+ return {
1979
+ backgroundColor: profileColors.surfaceBtnActive,
1980
+ backgroundImage: "linear-gradient(to bottom, rgba(255,255,255,0.05), transparent)",
1981
+ boxShadow: "inset 0 1px 0 rgba(255,255,255,0.18), inset 0 -1px 0 rgba(0,0,0,0.45), inset 0 0 0 1px #4B4D50, 0 1px 2px rgba(0,0,0,0.5)",
1982
+ color: profileColors.text,
1983
+ border: "none"
1984
+ };
1985
+ }
1986
+ if (state === "disabled") {
1987
+ return {
1988
+ backgroundColor: profileColors.surfaceBtn,
1989
+ backgroundImage: "linear-gradient(to bottom, rgba(255,255,255,0.02), transparent)",
1990
+ boxShadow: "inset 0 1px 0 rgba(255,255,255,0.05), inset 0 -1px 0 rgba(0,0,0,0.25), inset 0 0 0 1px #1c2026",
1991
+ color: profileColors.subdued,
1992
+ border: "none",
1993
+ cursor: "not-allowed"
1994
+ };
1995
+ }
1996
+ if (state === "hover") {
1997
+ return {
1998
+ backgroundColor: profileColors.surfaceBtnHover,
1999
+ backgroundImage: "linear-gradient(to bottom, rgba(255,255,255,0.04), transparent)",
2000
+ boxShadow: "inset 0 1px 0 rgba(255,255,255,0.14), inset 0 -1px 0 rgba(0,0,0,0.40), inset 0 0 0 1px #444548",
2001
+ color: "#d1d5db",
2002
+ border: "none"
2003
+ };
2004
+ }
2005
+ return {
2006
+ backgroundColor: profileColors.surfaceBtn,
2007
+ backgroundImage: "linear-gradient(to bottom, rgba(255,255,255,0.03), transparent)",
2008
+ boxShadow: "inset 0 1px 0 rgba(255,255,255,0.10), inset 0 -1px 0 rgba(0,0,0,0.35), inset 0 0 0 1px #262A30",
2009
+ color: profileColors.muted,
2010
+ border: "none"
2011
+ };
2012
+ };
2013
+ var dangerOutlineButtonStyle = (enabled, hovered = false) => ({
2014
+ background: enabled && hovered ? "rgba(248,113,113,0.1)" : "transparent",
2015
+ border: `1px solid ${enabled ? profileColors.danger : "#374151"}`,
2016
+ color: enabled ? profileColors.danger : profileColors.disabled,
2017
+ cursor: enabled ? "pointer" : "not-allowed"
2018
+ });
2019
+
2020
+ // src/DeleteWalletModal.tsx
2021
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2022
+ var DANGER_BG = "rgba(248,113,113,0.07)";
2023
+ var DANGER_BORDER = "rgba(248,113,113,0.2)";
2024
+ var backdropStyle2 = modalBackdropStyle(110);
2025
+ var wrapperStyle = modalWrapperStyle2(111, 16);
2026
+ var panelStyle = {
2027
+ ...modalPanelStyle(true),
2028
+ border: `1px solid ${profileColors.surfaceBd}`
2029
+ };
2030
+ var headerStyle = {
2031
+ ...modalHeaderStyle,
2032
+ borderBottom: "1px solid rgba(255,255,255,0.06)"
2033
+ };
2034
+ var bodyStyle = {
2035
+ padding: "20px 24px",
2036
+ display: "flex",
2037
+ flexDirection: "column",
2038
+ gap: 16
2039
+ };
2040
+ var warningBoxStyle = {
2041
+ display: "flex",
2042
+ alignItems: "flex-start",
2043
+ gap: 12,
2044
+ padding: 14,
2045
+ background: DANGER_BG,
2046
+ border: `1px solid ${DANGER_BORDER}`,
2047
+ borderRadius: 8
2048
+ };
2049
+ var infoBoxStyle = {
2050
+ padding: "10px 12px",
2051
+ background: "rgba(255,255,255,0.03)",
2052
+ border: "1px solid rgba(255,255,255,0.06)",
2053
+ borderRadius: 8
2054
+ };
2055
+ var labelStyle = {
2056
+ display: "block",
2057
+ fontSize: 12.5,
2058
+ lineHeight: "1rem",
2059
+ color: profileColors.muted,
2060
+ marginBottom: 8
2061
+ };
2062
+ var inputStyle = (disabled) => ({
2063
+ width: "100%",
2064
+ background: "rgba(13,18,25,0.9)",
2065
+ border: `1px solid ${profileColors.surfaceBd}`,
2066
+ borderRadius: 8,
2067
+ padding: "10px 12px",
2068
+ color: profileColors.text,
2069
+ fontFamily: fontFamily.mono,
2070
+ fontSize: 12.5,
2071
+ lineHeight: "1rem",
2072
+ outline: "none",
2073
+ opacity: disabled ? 0.5 : 1,
2074
+ boxSizing: "border-box",
2075
+ transition: "border-color 150ms, background-color 150ms"
2076
+ });
2077
+ var footerStyle = {
2078
+ padding: "0 24px 24px"
2079
+ };
2080
+ var deleteButtonStyle = (enabled, hovered) => ({
2081
+ ...dangerOutlineButtonStyle(enabled, hovered),
2082
+ width: "100%",
2083
+ padding: "8px 0",
2084
+ borderRadius: 8,
2085
+ fontSize: 12.5,
2086
+ lineHeight: "1rem",
2087
+ fontWeight: 500,
2088
+ display: "flex",
2089
+ alignItems: "center",
2090
+ justifyContent: "center",
2091
+ gap: 8,
2092
+ transition: "background-color 150ms, color 150ms, border-color 150ms"
2093
+ });
2094
+ function DeleteWalletModal({
2095
+ isOpen,
2096
+ onClose,
2097
+ wallet,
2098
+ onConfirm,
2099
+ onNotify
2100
+ }) {
2101
+ const [confirmName, setConfirmName] = useState2("");
2102
+ const [isDeleting, setIsDeleting] = useState2(false);
2103
+ const [error, setError] = useState2(null);
2104
+ const [deleteHovered, setDeleteHovered] = useState2(false);
2105
+ const walletName = wallet?.name || "Unnamed Wallet";
2106
+ const isNameMatch = confirmName === walletName;
2107
+ const canDelete = isNameMatch && !isDeleting;
2108
+ const handleClose = useCallback3(() => {
2109
+ if (isDeleting) return;
2110
+ setConfirmName("");
2111
+ setError(null);
2112
+ onClose();
2113
+ }, [isDeleting, onClose]);
2114
+ const handleDelete = useCallback3(async () => {
2115
+ if (!wallet || !isNameMatch) return;
2116
+ setError(null);
2117
+ setIsDeleting(true);
2118
+ try {
2119
+ await onConfirm(wallet.id);
2120
+ setConfirmName("");
2121
+ onNotify?.({ type: "success", message: "Wallet deleted successfully" });
2122
+ onClose();
2123
+ } catch (e) {
2124
+ setError(e instanceof Error ? e.message : "Failed to delete wallet");
2125
+ } finally {
2126
+ setIsDeleting(false);
2127
+ }
2128
+ }, [wallet, isNameMatch, onConfirm, onClose, onNotify]);
2129
+ return /* @__PURE__ */ jsx6(AnimatePresence2, { children: isOpen && wallet && /* @__PURE__ */ jsxs5(Fragment2, { children: [
2130
+ /* @__PURE__ */ jsx6(SpinKeyframes, {}),
2131
+ /* @__PURE__ */ jsx6(
2132
+ motion2.div,
2133
+ {
2134
+ style: backdropStyle2,
2135
+ initial: { opacity: 0 },
2136
+ animate: { opacity: 1 },
2137
+ exit: { opacity: 0 },
2138
+ transition: { duration: 0.15 },
2139
+ onClick: handleClose
2140
+ },
2141
+ "backdrop"
2142
+ ),
2143
+ /* @__PURE__ */ jsx6("div", { style: wrapperStyle, children: /* @__PURE__ */ jsxs5(
2144
+ motion2.div,
2145
+ {
2146
+ style: panelStyle,
2147
+ initial: { opacity: 0, y: 8 },
2148
+ animate: { opacity: 1, y: 0 },
2149
+ exit: { opacity: 0, y: 8 },
2150
+ transition: { duration: 0.18, ease: "easeOut" },
2151
+ onClick: (e) => e.stopPropagation(),
2152
+ children: [
2153
+ /* @__PURE__ */ jsxs5("div", { style: headerStyle, children: [
2154
+ /* @__PURE__ */ jsx6("h3", { style: titleStyle, children: "Delete Wallet" }),
2155
+ /* @__PURE__ */ jsx6(
2156
+ "button",
2157
+ {
2158
+ onClick: handleClose,
2159
+ disabled: isDeleting,
2160
+ style: closeBtnStyle(isDeleting),
2161
+ "aria-label": "Close",
2162
+ children: /* @__PURE__ */ jsx6(X, { size: 16 })
2163
+ }
2164
+ )
2165
+ ] }),
2166
+ /* @__PURE__ */ jsxs5("div", { style: bodyStyle, children: [
2167
+ /* @__PURE__ */ jsxs5("div", { style: warningBoxStyle, children: [
2168
+ /* @__PURE__ */ jsx6(
2169
+ AlertTriangle,
2170
+ {
2171
+ size: 15,
2172
+ color: profileColors.danger,
2173
+ style: { flexShrink: 0, marginTop: 2 }
2174
+ }
2175
+ ),
2176
+ /* @__PURE__ */ jsxs5("div", { children: [
2177
+ /* @__PURE__ */ jsx6(
2178
+ "p",
2179
+ {
2180
+ style: {
2181
+ margin: 0,
2182
+ fontSize: 12.5,
2183
+ lineHeight: "1rem",
2184
+ color: profileColors.danger,
2185
+ fontWeight: 500
2186
+ },
2187
+ children: "This action cannot be undone"
2188
+ }
2189
+ ),
2190
+ /* @__PURE__ */ jsx6(
2191
+ "p",
2192
+ {
2193
+ style: {
2194
+ margin: "2px 0 0",
2195
+ fontSize: 12.5,
2196
+ lineHeight: "1rem",
2197
+ color: "rgba(248,113,113,0.7)"
2198
+ },
2199
+ children: "The private key will be permanently deleted. Any remaining funds will be inaccessible."
2200
+ }
2201
+ )
2202
+ ] })
2203
+ ] }),
2204
+ /* @__PURE__ */ jsxs5("div", { style: infoBoxStyle, children: [
2205
+ /* @__PURE__ */ jsx6(
2206
+ "p",
2207
+ {
2208
+ style: {
2209
+ margin: "0 0 4px",
2210
+ color: profileColors.muted,
2211
+ ...upperLabelStyle
2212
+ },
2213
+ children: "Wallet to delete"
2214
+ }
2215
+ ),
2216
+ /* @__PURE__ */ jsx6(
2217
+ "p",
2218
+ {
2219
+ style: {
2220
+ margin: 0,
2221
+ fontSize: 12.5,
2222
+ lineHeight: "1rem",
2223
+ fontWeight: 500,
2224
+ color: profileColors.text
2225
+ },
2226
+ children: walletName
2227
+ }
2228
+ ),
2229
+ /* @__PURE__ */ jsx6(
2230
+ "p",
2231
+ {
2232
+ style: {
2233
+ margin: "2px 0 0",
2234
+ fontSize: 12.5,
2235
+ lineHeight: "1rem",
2236
+ color: profileColors.muted,
2237
+ fontFamily: fontFamily.mono,
2238
+ wordBreak: "break-all"
2239
+ },
2240
+ children: wallet.ethereumAddress
2241
+ }
2242
+ )
2243
+ ] }),
2244
+ /* @__PURE__ */ jsxs5("div", { children: [
2245
+ /* @__PURE__ */ jsxs5("label", { style: labelStyle, children: [
2246
+ "Type",
2247
+ " ",
2248
+ /* @__PURE__ */ jsxs5(
2249
+ "span",
2250
+ {
2251
+ style: {
2252
+ color: profileColors.text,
2253
+ fontWeight: 500
2254
+ },
2255
+ children: [
2256
+ '"',
2257
+ walletName,
2258
+ '"'
2259
+ ]
2260
+ }
2261
+ ),
2262
+ " ",
2263
+ "to confirm"
2264
+ ] }),
2265
+ /* @__PURE__ */ jsx6(
2266
+ "input",
2267
+ {
2268
+ type: "text",
2269
+ value: confirmName,
2270
+ onChange: (e) => setConfirmName(e.target.value),
2271
+ placeholder: walletName,
2272
+ disabled: isDeleting,
2273
+ style: inputStyle(isDeleting)
2274
+ }
2275
+ )
2276
+ ] }),
2277
+ error && /* @__PURE__ */ jsxs5(
2278
+ "div",
2279
+ {
2280
+ style: {
2281
+ display: "flex",
2282
+ alignItems: "flex-start",
2283
+ gap: 8,
2284
+ padding: 12,
2285
+ background: "rgba(248,113,113,0.08)",
2286
+ border: `1px solid ${DANGER_BORDER}`,
2287
+ borderRadius: 8
2288
+ },
2289
+ children: [
2290
+ /* @__PURE__ */ jsx6(
2291
+ AlertTriangle,
2292
+ {
2293
+ size: 14,
2294
+ color: profileColors.danger,
2295
+ style: { flexShrink: 0, marginTop: 2 }
2296
+ }
2297
+ ),
2298
+ /* @__PURE__ */ jsx6(
2299
+ "p",
2300
+ {
2301
+ style: {
2302
+ margin: 0,
2303
+ fontSize: 12.5,
2304
+ lineHeight: "1rem",
2305
+ color: profileColors.danger
2306
+ },
2307
+ children: error
2308
+ }
2309
+ )
2310
+ ]
2311
+ }
2312
+ )
2313
+ ] }),
2314
+ /* @__PURE__ */ jsx6("div", { style: footerStyle, children: /* @__PURE__ */ jsx6(
2315
+ "button",
2316
+ {
2317
+ onClick: handleDelete,
2318
+ disabled: !canDelete,
2319
+ onMouseEnter: () => setDeleteHovered(true),
2320
+ onMouseLeave: () => setDeleteHovered(false),
2321
+ style: deleteButtonStyle(canDelete, deleteHovered),
2322
+ children: isDeleting ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
2323
+ /* @__PURE__ */ jsx6(Loader2, { size: 14 }),
2324
+ " Deleting..."
2325
+ ] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
2326
+ /* @__PURE__ */ jsx6(Trash2, { size: 14 }),
2327
+ " Delete Wallet"
2328
+ ] })
2329
+ }
2330
+ ) })
2331
+ ]
2332
+ },
2333
+ "panel"
2334
+ ) })
2335
+ ] }) });
2336
+ }
2337
+
2338
+ // src/RenameWalletModal.tsx
2339
+ import { AnimatePresence as AnimatePresence3, motion as motion3 } from "framer-motion";
2340
+ import {
2341
+ useCallback as useCallback4,
2342
+ useEffect as useEffect2,
2343
+ useState as useState3
2344
+ } from "react";
2345
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2346
+ var DANGER_BORDER2 = "rgba(248,113,113,0.2)";
2347
+ var WALLET_NAME_REGEX = /^[a-zA-Z0-9/]+$/;
2348
+ var backdropStyle3 = modalBackdropStyle(110);
2349
+ var wrapperStyle2 = modalWrapperStyle2(111, 16);
2350
+ var panelStyle2 = {
2351
+ ...modalPanelStyle(true),
2352
+ border: `1px solid ${profileColors.surfaceBd}`
2353
+ };
2354
+ var headerStyle2 = {
2355
+ ...modalHeaderStyle,
2356
+ borderBottom: "1px solid rgba(255,255,255,0.06)"
2357
+ };
2358
+ var bodyStyle2 = {
2359
+ padding: "20px 24px",
2360
+ display: "flex",
2361
+ flexDirection: "column",
2362
+ gap: 16
2363
+ };
2364
+ var infoBoxStyle2 = {
2365
+ padding: "10px 12px",
2366
+ background: "rgba(255,255,255,0.03)",
2367
+ border: "1px solid rgba(255,255,255,0.06)",
2368
+ borderRadius: 8
2369
+ };
2370
+ var labelStyle2 = {
2371
+ display: "block",
2372
+ fontSize: 12.5,
2373
+ lineHeight: "1rem",
2374
+ color: profileColors.muted,
2375
+ marginBottom: 8
2376
+ };
2377
+ var inputStyle2 = (hasError, disabled) => ({
2378
+ width: "100%",
2379
+ background: "rgba(13,18,25,0.9)",
2380
+ border: `1px solid ${hasError ? "rgba(248,113,113,0.5)" : profileColors.surfaceBd}`,
2381
+ borderRadius: 8,
2382
+ padding: "10px 12px",
2383
+ color: profileColors.text,
2384
+ fontFamily: fontFamily.mono,
2385
+ fontSize: 12.5,
2386
+ lineHeight: "1rem",
2387
+ outline: "none",
2388
+ opacity: disabled ? 0.5 : 1,
2389
+ boxSizing: "border-box",
2390
+ transition: "border-color 150ms, background-color 150ms"
2391
+ });
2392
+ var footerStyle2 = {
2393
+ padding: "0 24px 24px"
2394
+ };
2395
+ var saveButtonStyle = (enabled, hovered) => ({
2396
+ ...raisedButtonStyle(enabled ? hovered ? "hover" : "default" : "disabled"),
2397
+ width: "100%",
2398
+ padding: "8px 0",
2399
+ borderRadius: 8,
2400
+ fontSize: 12.5,
2401
+ lineHeight: "1rem",
2402
+ fontWeight: 500,
2403
+ display: "flex",
2404
+ alignItems: "center",
2405
+ justifyContent: "center",
2406
+ gap: 8
2407
+ });
2408
+ function RenameWalletModal({
2409
+ isOpen,
2410
+ onClose,
2411
+ wallet,
2412
+ onConfirm,
2413
+ onNotify
2414
+ }) {
2415
+ const [name, setName] = useState3("");
2416
+ const [isRenaming, setIsRenaming] = useState3(false);
2417
+ const [error, setError] = useState3(null);
2418
+ const [saveHovered, setSaveHovered] = useState3(false);
2419
+ const currentName = wallet?.name || "Unnamed";
2420
+ const trimmedName = name.trim();
2421
+ const isNameChanged = trimmedName !== currentName;
2422
+ const isNameValid = WALLET_NAME_REGEX.test(trimmedName);
2423
+ const canSubmit = isNameValid && isNameChanged && !isRenaming;
2424
+ useEffect2(() => {
2425
+ if (!wallet) return;
2426
+ setName(wallet.name || "");
2427
+ setError(null);
2428
+ }, [wallet]);
2429
+ const handleClose = useCallback4(() => {
2430
+ if (isRenaming) return;
2431
+ setError(null);
2432
+ onClose();
2433
+ }, [isRenaming, onClose]);
2434
+ const handleRename = useCallback4(async () => {
2435
+ if (!wallet || !isNameValid || !isNameChanged) return;
2436
+ setError(null);
2437
+ setIsRenaming(true);
2438
+ try {
2439
+ await onConfirm(wallet.id, trimmedName);
2440
+ onNotify?.({ type: "success", message: "Wallet renamed successfully" });
2441
+ onClose();
2442
+ } catch (e) {
2443
+ setError(e instanceof Error ? e.message : "Failed to rename wallet");
2444
+ } finally {
2445
+ setIsRenaming(false);
2446
+ }
2447
+ }, [
2448
+ wallet,
2449
+ isNameValid,
2450
+ isNameChanged,
2451
+ onConfirm,
2452
+ trimmedName,
2453
+ onClose,
2454
+ onNotify
2455
+ ]);
2456
+ return /* @__PURE__ */ jsx7(AnimatePresence3, { children: isOpen && wallet && /* @__PURE__ */ jsxs6(Fragment3, { children: [
2457
+ /* @__PURE__ */ jsx7(SpinKeyframes, {}),
2458
+ /* @__PURE__ */ jsx7(
2459
+ motion3.div,
2460
+ {
2461
+ style: backdropStyle3,
2462
+ initial: { opacity: 0 },
2463
+ animate: { opacity: 1 },
2464
+ exit: { opacity: 0 },
2465
+ transition: { duration: 0.15 },
2466
+ onClick: handleClose
2467
+ },
2468
+ "backdrop"
2469
+ ),
2470
+ /* @__PURE__ */ jsx7("div", { style: wrapperStyle2, children: /* @__PURE__ */ jsxs6(
2471
+ motion3.div,
2472
+ {
2473
+ style: panelStyle2,
2474
+ initial: { opacity: 0, y: 8 },
2475
+ animate: { opacity: 1, y: 0 },
2476
+ exit: { opacity: 0, y: 8 },
2477
+ transition: { duration: 0.18, ease: "easeOut" },
2478
+ onClick: (e) => e.stopPropagation(),
2479
+ children: [
2480
+ /* @__PURE__ */ jsxs6("div", { style: headerStyle2, children: [
2481
+ /* @__PURE__ */ jsx7("h3", { style: titleStyle, children: "Rename Wallet" }),
2482
+ /* @__PURE__ */ jsx7(
2483
+ "button",
2484
+ {
2485
+ onClick: handleClose,
2486
+ disabled: isRenaming,
2487
+ style: closeBtnStyle(isRenaming),
2488
+ "aria-label": "Close",
2489
+ children: /* @__PURE__ */ jsx7(X, { size: 16 })
2490
+ }
2491
+ )
2492
+ ] }),
2493
+ /* @__PURE__ */ jsxs6("div", { style: bodyStyle2, children: [
2494
+ /* @__PURE__ */ jsxs6("div", { style: infoBoxStyle2, children: [
2495
+ /* @__PURE__ */ jsx7(
2496
+ "p",
2497
+ {
2498
+ style: {
2499
+ margin: "0 0 4px",
2500
+ color: profileColors.muted,
2501
+ ...upperLabelStyle
2502
+ },
2503
+ children: "Wallet"
2504
+ }
2505
+ ),
2506
+ /* @__PURE__ */ jsx7(
2507
+ "p",
2508
+ {
2509
+ style: {
2510
+ margin: 0,
2511
+ fontSize: 12.5,
2512
+ lineHeight: "1rem",
2513
+ fontWeight: 500,
2514
+ color: profileColors.text
2515
+ },
2516
+ children: currentName
2517
+ }
2518
+ ),
2519
+ /* @__PURE__ */ jsx7(
2520
+ "p",
2521
+ {
2522
+ style: {
2523
+ margin: "2px 0 0",
2524
+ fontSize: 12.5,
2525
+ lineHeight: "1rem",
2526
+ color: profileColors.muted,
2527
+ fontFamily: fontFamily.mono,
2528
+ wordBreak: "break-all"
2529
+ },
2530
+ children: wallet.ethereumAddress
2531
+ }
2532
+ )
2533
+ ] }),
2534
+ /* @__PURE__ */ jsxs6("div", { children: [
2535
+ /* @__PURE__ */ jsx7("label", { style: labelStyle2, children: "Wallet name" }),
2536
+ /* @__PURE__ */ jsx7(
2537
+ "input",
2538
+ {
2539
+ type: "text",
2540
+ value: name,
2541
+ onChange: (e) => {
2542
+ setName(e.target.value);
2543
+ setError(null);
2544
+ },
2545
+ onKeyDown: (e) => {
2546
+ if (e.key === "Enter") handleRename();
2547
+ if (e.key === "Escape") handleClose();
2548
+ },
2549
+ disabled: isRenaming,
2550
+ autoFocus: true,
2551
+ style: inputStyle2(!!error, isRenaming)
2552
+ }
2553
+ ),
2554
+ /* @__PURE__ */ jsx7(
2555
+ "p",
2556
+ {
2557
+ style: {
2558
+ margin: "8px 0 0",
2559
+ fontSize: 12.5,
2560
+ lineHeight: "1rem",
2561
+ color: profileColors.subdued
2562
+ },
2563
+ children: "Use letters, numbers, and / only."
2564
+ }
2565
+ )
2566
+ ] }),
2567
+ error && /* @__PURE__ */ jsxs6(
2568
+ "div",
2569
+ {
2570
+ style: {
2571
+ display: "flex",
2572
+ alignItems: "flex-start",
2573
+ gap: 8,
2574
+ padding: 12,
2575
+ background: "rgba(248,113,113,0.08)",
2576
+ border: `1px solid ${DANGER_BORDER2}`,
2577
+ borderRadius: 8
2578
+ },
2579
+ children: [
2580
+ /* @__PURE__ */ jsx7(
2581
+ AlertTriangle,
2582
+ {
2583
+ size: 14,
2584
+ color: profileColors.danger,
2585
+ style: { flexShrink: 0, marginTop: 2 }
2586
+ }
2587
+ ),
2588
+ /* @__PURE__ */ jsx7(
2589
+ "p",
2590
+ {
2591
+ style: {
2592
+ margin: 0,
2593
+ fontSize: 12.5,
2594
+ lineHeight: "1rem",
2595
+ color: profileColors.danger
2596
+ },
2597
+ children: error
2598
+ }
2599
+ )
2600
+ ]
2601
+ }
2602
+ )
2603
+ ] }),
2604
+ /* @__PURE__ */ jsx7("div", { style: footerStyle2, children: /* @__PURE__ */ jsx7(
2605
+ "button",
2606
+ {
2607
+ onClick: handleRename,
2608
+ disabled: !canSubmit,
2609
+ onMouseEnter: () => setSaveHovered(true),
2610
+ onMouseLeave: () => setSaveHovered(false),
2611
+ style: saveButtonStyle(canSubmit, saveHovered),
2612
+ children: isRenaming ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
2613
+ /* @__PURE__ */ jsx7(Loader2, { size: 14 }),
2614
+ " Saving..."
2615
+ ] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
2616
+ /* @__PURE__ */ jsx7(Pencil, { size: 14 }),
2617
+ " Save Name"
2618
+ ] })
2619
+ }
2620
+ ) })
2621
+ ]
2622
+ },
2623
+ "panel"
2624
+ ) })
2625
+ ] }) });
2626
+ }
2627
+
2628
+ // src/UserProfileModal.tsx
2629
+ import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2630
+ var DEFAULT_SLIPPAGE_OPTIONS = [
2631
+ { label: "0.5%", value: 5e-3 },
2632
+ { label: "1%", value: 0.01 },
2633
+ { label: "2%", value: 0.02 },
2634
+ { label: "5%", value: 0.05 },
2635
+ { label: "10%", value: 0.1 }
2636
+ ];
2637
+ var backdropStyle4 = modalBackdropStyle(100);
2638
+ var wrapperStyle3 = modalWrapperStyle2(101);
2639
+ var panelStyle3 = modalPanelStyle(false);
2640
+ var headerStyle3 = modalHeaderStyle;
2641
+ var profileSectionStyle = {
2642
+ padding: "20px 24px",
2643
+ borderBottom: `1px solid ${profileColors.border}`
2644
+ };
2645
+ var settingsSectionStyle = {
2646
+ padding: "20px 24px"
2647
+ };
2648
+ var tabRowStyle = {
2649
+ display: "flex",
2650
+ gap: 6,
2651
+ marginBottom: 20
2652
+ };
2653
+ var tabButtonLayoutStyle = {
2654
+ flex: 1,
2655
+ padding: "6px 0",
2656
+ borderRadius: 4,
2657
+ fontSize: 12.5,
2658
+ lineHeight: "1rem",
2659
+ fontWeight: 500,
2660
+ display: "flex",
2661
+ alignItems: "center",
2662
+ justifyContent: "center",
2663
+ gap: 6,
2664
+ cursor: "pointer",
2665
+ transition: "background-color 150ms, color 150ms, box-shadow 150ms"
2666
+ };
2667
+ var statBoxStyle = {
2668
+ background: "rgba(255,255,255,0.03)",
2669
+ borderRadius: 8,
2670
+ padding: 12,
2671
+ border: `1px solid ${profileColors.border}`
2672
+ };
2673
+ var slippageBtnBaseStyle = {
2674
+ flex: 1,
2675
+ padding: "4px 0",
2676
+ borderRadius: 4,
2677
+ fontSize: 12.5,
2678
+ lineHeight: "1rem",
2679
+ fontFamily: fontFamily.mono,
2680
+ fontWeight: 500,
2681
+ cursor: "pointer",
2682
+ transition: "background-color 150ms, color 150ms, border-color 150ms"
2683
+ };
2684
+ var walletRowStyle = {
2685
+ display: "flex",
2686
+ alignItems: "center",
2687
+ gap: 12,
2688
+ padding: "10px 12px",
2689
+ borderRadius: 8,
2690
+ background: profileColors.surfaceBtn,
2691
+ border: `1px solid ${profileColors.surfaceBd}`,
2692
+ transition: "background-color 150ms, border-color 150ms"
2693
+ };
2694
+ function ToggleSwitch({
2695
+ checked,
2696
+ onChange,
2697
+ accentColor
2698
+ }) {
2699
+ return /* @__PURE__ */ jsx8(
2700
+ "button",
2701
+ {
2702
+ onClick: onChange,
2703
+ role: "switch",
2704
+ "aria-checked": checked,
2705
+ style: {
2706
+ position: "relative",
2707
+ display: "inline-flex",
2708
+ height: 20,
2709
+ width: 36,
2710
+ alignItems: "center",
2711
+ borderRadius: 9999,
2712
+ border: "none",
2713
+ background: checked ? accentColor : "rgba(255,255,255,0.08)",
2714
+ cursor: "pointer",
2715
+ padding: 0,
2716
+ transition: "background 150ms"
2717
+ },
2718
+ children: /* @__PURE__ */ jsx8(
2719
+ "span",
2720
+ {
2721
+ style: {
2722
+ display: "inline-block",
2723
+ height: 12,
2724
+ width: 12,
2725
+ borderRadius: "50%",
2726
+ background: profileColors.text,
2727
+ transform: checked ? "translateX(20px)" : "translateX(4px)",
2728
+ transition: "transform 150ms"
2729
+ }
2730
+ }
2731
+ )
2732
+ }
2733
+ );
2734
+ }
2735
+ function RaisedButton({
2736
+ selected = false,
2737
+ onClick,
2738
+ children,
2739
+ style
2740
+ }) {
2741
+ const [hovered, setHovered] = useState4(false);
2742
+ return /* @__PURE__ */ jsx8(
2743
+ "button",
2744
+ {
2745
+ type: "button",
2746
+ onClick,
2747
+ onMouseEnter: () => setHovered(true),
2748
+ onMouseLeave: () => setHovered(false),
2749
+ style: {
2750
+ ...tabButtonLayoutStyle,
2751
+ ...raisedButtonStyle(
2752
+ selected ? "active" : hovered ? "hover" : "default"
2753
+ ),
2754
+ ...style
2755
+ },
2756
+ children
2757
+ }
2758
+ );
2759
+ }
2760
+ function SlippageButton({
2761
+ selected,
2762
+ onClick,
2763
+ children
2764
+ }) {
2765
+ const [hovered, setHovered] = useState4(false);
2766
+ return /* @__PURE__ */ jsx8(
2767
+ "button",
2768
+ {
2769
+ type: "button",
2770
+ onClick,
2771
+ onMouseEnter: () => setHovered(true),
2772
+ onMouseLeave: () => setHovered(false),
2773
+ style: {
2774
+ ...slippageBtnBaseStyle,
2775
+ background: selected ? profileColors.surfaceBtnActive : hovered ? profileColors.surfaceBtnHover : profileColors.surfaceBtn,
2776
+ border: `1px solid ${selected ? profileColors.surfaceBdActive : hovered ? profileColors.surfaceBdHover : profileColors.surfaceBd}`,
2777
+ color: selected ? profileColors.text : hovered ? "#d1d5db" : profileColors.muted
2778
+ },
2779
+ children
2780
+ }
2781
+ );
2782
+ }
2783
+ function UserProfileModal({
2784
+ isOpen,
2785
+ onClose,
2786
+ animationsEnabled,
2787
+ onToggleAnimations,
2788
+ defaultSlippage,
2789
+ onSlippageChange,
2790
+ slippageOptions = DEFAULT_SLIPPAGE_OPTIONS,
2791
+ onWalletDeleted,
2792
+ onWalletRenamed,
2793
+ onShowPortfolio,
2794
+ onNotify,
2795
+ accentColor,
2796
+ principalColors
2797
+ }) {
2798
+ const {
2799
+ user,
2800
+ wallets: userWallets,
2801
+ deleteWallet,
2802
+ renameWallet,
2803
+ authMethod
2804
+ } = useHypurrConnectInternal();
2805
+ const [settingsTab, setSettingsTab] = useState4("ui");
2806
+ const [walletToDelete, setWalletToDelete] = useState4(null);
2807
+ const [walletToRename, setWalletToRename] = useState4(null);
2808
+ const profilePic = user?.photoUrl || "";
2809
+ const displayName = user?.displayName || "";
2810
+ const hfunScore = user?.hfunScore ?? null;
2811
+ const reputationScore = user?.reputationScore ?? null;
2812
+ const telegramId = user?.telegramId;
2813
+ const wallets = userWallets ?? [];
2814
+ const colors = resolvePrincipalColors(accentColor, principalColors);
2815
+ const handleDeleteWallet = useCallback5(
2816
+ async (walletId) => {
2817
+ await deleteWallet(walletId);
2818
+ onWalletDeleted?.(walletId);
2819
+ },
2820
+ [deleteWallet, onWalletDeleted]
2821
+ );
2822
+ const handleRenameWallet = useCallback5(
2823
+ async (walletId, name) => {
2824
+ await renameWallet(walletId, name);
2825
+ onWalletRenamed?.(walletId, name);
2826
+ },
2827
+ [renameWallet, onWalletRenamed]
2828
+ );
2829
+ const handleCopyAddress = useCallback5(() => {
2830
+ if (!displayName) return;
2831
+ navigator.clipboard.writeText(displayName);
2832
+ onNotify?.({ type: "success", message: "Address copied" });
2833
+ }, [displayName, onNotify]);
2834
+ return /* @__PURE__ */ jsxs7(Fragment4, { children: [
2835
+ /* @__PURE__ */ jsx8(AnimatePresence4, { children: isOpen && /* @__PURE__ */ jsxs7(Fragment4, { children: [
2836
+ /* @__PURE__ */ jsx8(SpinKeyframes, {}),
2837
+ /* @__PURE__ */ jsx8(
2838
+ motion4.div,
2839
+ {
2840
+ style: backdropStyle4,
2841
+ initial: { opacity: 0 },
2842
+ animate: { opacity: 1 },
2843
+ exit: { opacity: 0 },
2844
+ transition: { duration: 0.15 },
2845
+ onClick: onClose
2846
+ },
2847
+ "backdrop"
2848
+ ),
2849
+ /* @__PURE__ */ jsx8("div", { style: wrapperStyle3, onClick: onClose, children: /* @__PURE__ */ jsxs7(
2850
+ motion4.div,
2851
+ {
2852
+ style: panelStyle3,
2853
+ initial: { opacity: 0, y: 8 },
2854
+ animate: { opacity: 1, y: 0 },
2855
+ exit: { opacity: 0, y: 8 },
2856
+ transition: { duration: 0.18, ease: "easeOut" },
2857
+ onClick: (e) => e.stopPropagation(),
2858
+ children: [
2859
+ /* @__PURE__ */ jsxs7("div", { style: headerStyle3, children: [
2860
+ /* @__PURE__ */ jsx8("h3", { style: titleStyle, children: "Profile & Settings" }),
2861
+ /* @__PURE__ */ jsx8(
2862
+ "button",
2863
+ {
2864
+ onClick: onClose,
2865
+ style: closeBtnStyle(),
2866
+ "aria-label": "Close",
2867
+ children: /* @__PURE__ */ jsx8(X, { size: 16 })
2868
+ }
2869
+ )
2870
+ ] }),
2871
+ /* @__PURE__ */ jsxs7("div", { style: profileSectionStyle, children: [
2872
+ authMethod === "eoa" && !profilePic ? /* @__PURE__ */ jsxs7(
2873
+ "div",
2874
+ {
2875
+ style: {
2876
+ padding: "10px 12px",
2877
+ background: "rgba(255,255,255,0.03)",
2878
+ border: `1px solid ${profileColors.border}`,
2879
+ borderRadius: 8
2880
+ },
2881
+ children: [
2882
+ /* @__PURE__ */ jsx8(
2883
+ "p",
2884
+ {
2885
+ style: {
2886
+ margin: "0 0 6px",
2887
+ color: profileColors.muted,
2888
+ ...upperLabelStyle
2889
+ },
2890
+ children: "Wallet"
2891
+ }
2892
+ ),
2893
+ /* @__PURE__ */ jsxs7(
2894
+ "div",
2895
+ {
2896
+ style: {
2897
+ display: "flex",
2898
+ alignItems: "center",
2899
+ justifyContent: "space-between",
2900
+ gap: 8
2901
+ },
2902
+ children: [
2903
+ /* @__PURE__ */ jsx8(
2904
+ "p",
2905
+ {
2906
+ style: {
2907
+ margin: 0,
2908
+ fontSize: 12.5,
2909
+ lineHeight: "1rem",
2910
+ color: profileColors.text,
2911
+ fontFamily: fontFamily.mono,
2912
+ wordBreak: "break-all"
2913
+ },
2914
+ children: displayName
2915
+ }
2916
+ ),
2917
+ /* @__PURE__ */ jsx8(
2918
+ "button",
2919
+ {
2920
+ onClick: handleCopyAddress,
2921
+ style: {
2922
+ background: "transparent",
2923
+ border: "none",
2924
+ color: profileColors.muted,
2925
+ cursor: "pointer",
2926
+ flexShrink: 0,
2927
+ display: "flex"
2928
+ },
2929
+ "aria-label": "Copy address",
2930
+ children: /* @__PURE__ */ jsx8(Copy, { size: 13 })
2931
+ }
2932
+ )
2933
+ ]
2934
+ }
2935
+ )
2936
+ ]
2937
+ }
2938
+ ) : /* @__PURE__ */ jsxs7(
2939
+ "div",
2940
+ {
2941
+ style: {
2942
+ display: "flex",
2943
+ alignItems: "center",
2944
+ gap: 16
2945
+ },
2946
+ children: [
2947
+ profilePic ? /* @__PURE__ */ jsx8(
2948
+ "img",
2949
+ {
2950
+ src: profilePic,
2951
+ alt: "Profile",
2952
+ style: {
2953
+ height: 56,
2954
+ width: 56,
2955
+ borderRadius: "50%",
2956
+ border: `1px solid ${profileColors.surfaceBd}`
2957
+ }
2958
+ }
2959
+ ) : /* @__PURE__ */ jsx8(
2960
+ "div",
2961
+ {
2962
+ style: {
2963
+ height: 56,
2964
+ width: 56,
2965
+ borderRadius: "50%",
2966
+ border: `1px solid ${profileColors.surfaceBd}`,
2967
+ background: profileColors.surfaceBd,
2968
+ display: "flex",
2969
+ alignItems: "center",
2970
+ justifyContent: "center",
2971
+ fontSize: 18,
2972
+ lineHeight: "1.75rem",
2973
+ fontWeight: 700,
2974
+ color: profileColors.text
2975
+ },
2976
+ children: displayName?.charAt(0)
2977
+ }
2978
+ ),
2979
+ /* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
2980
+ /* @__PURE__ */ jsx8(
2981
+ "h4",
2982
+ {
2983
+ style: {
2984
+ margin: 0,
2985
+ fontSize: 14,
2986
+ lineHeight: "1.25rem",
2987
+ fontWeight: 600,
2988
+ color: profileColors.text,
2989
+ overflow: "hidden",
2990
+ textOverflow: "ellipsis",
2991
+ whiteSpace: "nowrap"
2992
+ },
2993
+ children: displayName
2994
+ }
2995
+ ),
2996
+ telegramId && /* @__PURE__ */ jsxs7(
2997
+ "p",
2998
+ {
2999
+ style: {
3000
+ margin: "2px 0 0",
3001
+ fontSize: 12.5,
3002
+ lineHeight: "1rem",
3003
+ color: profileColors.muted
3004
+ },
3005
+ children: [
3006
+ "ID: ",
3007
+ telegramId
3008
+ ]
3009
+ }
3010
+ )
3011
+ ] })
3012
+ ]
3013
+ }
3014
+ ),
3015
+ user && /* @__PURE__ */ jsxs7(
3016
+ "div",
3017
+ {
3018
+ style: {
3019
+ marginTop: 16,
3020
+ display: "grid",
3021
+ gridTemplateColumns: "1fr 1fr",
3022
+ gap: 10
3023
+ },
3024
+ children: [
3025
+ /* @__PURE__ */ jsxs7("div", { style: statBoxStyle, children: [
3026
+ /* @__PURE__ */ jsxs7(
3027
+ "div",
3028
+ {
3029
+ style: {
3030
+ display: "flex",
3031
+ alignItems: "center",
3032
+ gap: 6,
3033
+ color: "#eab308",
3034
+ marginBottom: 6
3035
+ },
3036
+ children: [
3037
+ /* @__PURE__ */ jsx8(Star, { size: 13, color: "#eab308", fill: "#eab308" }),
3038
+ /* @__PURE__ */ jsx8("span", { style: upperLabelStyle, children: "Hfun Score" })
3039
+ ]
3040
+ }
3041
+ ),
3042
+ /* @__PURE__ */ jsx8(
3043
+ "p",
3044
+ {
3045
+ style: {
3046
+ margin: 0,
3047
+ fontSize: 18,
3048
+ lineHeight: "1.75rem",
3049
+ fontWeight: 700,
3050
+ color: profileColors.text,
3051
+ fontFamily: fontFamily.mono
3052
+ },
3053
+ children: hfunScore !== null ? hfunScore.toFixed(0) : "--"
3054
+ }
3055
+ )
3056
+ ] }),
3057
+ /* @__PURE__ */ jsxs7("div", { style: statBoxStyle, children: [
3058
+ /* @__PURE__ */ jsxs7(
3059
+ "div",
3060
+ {
3061
+ style: {
3062
+ display: "flex",
3063
+ alignItems: "center",
3064
+ gap: 6,
3065
+ color: profileColors.muted,
3066
+ marginBottom: 6
3067
+ },
3068
+ children: [
3069
+ /* @__PURE__ */ jsx8(User, { size: 13 }),
3070
+ /* @__PURE__ */ jsx8("span", { style: upperLabelStyle, children: "Reputation" })
3071
+ ]
3072
+ }
3073
+ ),
3074
+ /* @__PURE__ */ jsx8(
3075
+ "p",
3076
+ {
3077
+ style: {
3078
+ margin: 0,
3079
+ fontSize: 18,
3080
+ lineHeight: "1.75rem",
3081
+ fontWeight: 700,
3082
+ color: profileColors.text,
3083
+ fontFamily: fontFamily.mono
3084
+ },
3085
+ children: reputationScore !== null ? reputationScore.toFixed(0) : "--"
3086
+ }
3087
+ )
3088
+ ] })
3089
+ ]
3090
+ }
3091
+ )
3092
+ ] }),
3093
+ /* @__PURE__ */ jsxs7("div", { style: settingsSectionStyle, children: [
3094
+ /* @__PURE__ */ jsxs7("div", { style: tabRowStyle, children: [
3095
+ /* @__PURE__ */ jsxs7(
3096
+ RaisedButton,
3097
+ {
3098
+ selected: settingsTab === "ui",
3099
+ onClick: () => setSettingsTab("ui"),
3100
+ children: [
3101
+ /* @__PURE__ */ jsx8(Zap, { size: 13 }),
3102
+ " UI"
3103
+ ]
3104
+ }
3105
+ ),
3106
+ /* @__PURE__ */ jsxs7(
3107
+ RaisedButton,
3108
+ {
3109
+ selected: settingsTab === "trading",
3110
+ onClick: () => setSettingsTab("trading"),
3111
+ children: [
3112
+ /* @__PURE__ */ jsx8(TrendingUp, { size: 13 }),
3113
+ " Trading"
3114
+ ]
3115
+ }
3116
+ ),
3117
+ /* @__PURE__ */ jsxs7(
3118
+ RaisedButton,
3119
+ {
3120
+ selected: settingsTab === "wallets",
3121
+ onClick: () => setSettingsTab("wallets"),
3122
+ children: [
3123
+ /* @__PURE__ */ jsx8(Wallet, { size: 13 }),
3124
+ " Wallets"
3125
+ ]
3126
+ }
3127
+ )
3128
+ ] }),
3129
+ settingsTab === "ui" && /* @__PURE__ */ jsx8(
3130
+ "div",
3131
+ {
3132
+ style: {
3133
+ display: "flex",
3134
+ flexDirection: "column",
3135
+ gap: 12
3136
+ },
3137
+ children: /* @__PURE__ */ jsxs7(
3138
+ "div",
3139
+ {
3140
+ style: {
3141
+ display: "flex",
3142
+ alignItems: "center",
3143
+ justifyContent: "space-between",
3144
+ padding: "8px 0"
3145
+ },
3146
+ children: [
3147
+ /* @__PURE__ */ jsxs7(
3148
+ "div",
3149
+ {
3150
+ style: {
3151
+ display: "flex",
3152
+ alignItems: "center",
3153
+ gap: 12
3154
+ },
3155
+ children: [
3156
+ /* @__PURE__ */ jsx8(Zap, { size: 16, color: profileColors.muted }),
3157
+ /* @__PURE__ */ jsxs7("div", { children: [
3158
+ /* @__PURE__ */ jsx8(
3159
+ "p",
3160
+ {
3161
+ style: {
3162
+ margin: 0,
3163
+ fontSize: 12.5,
3164
+ lineHeight: "1rem",
3165
+ fontWeight: 500,
3166
+ color: profileColors.text
3167
+ },
3168
+ children: "Animations"
3169
+ }
3170
+ ),
3171
+ /* @__PURE__ */ jsx8(
3172
+ "p",
3173
+ {
3174
+ style: {
3175
+ margin: 0,
3176
+ fontSize: 12.5,
3177
+ lineHeight: "1rem",
3178
+ color: profileColors.muted
3179
+ },
3180
+ children: "Enable chart and UI animations"
3181
+ }
3182
+ )
3183
+ ] })
3184
+ ]
3185
+ }
3186
+ ),
3187
+ /* @__PURE__ */ jsx8(
3188
+ ToggleSwitch,
3189
+ {
3190
+ checked: animationsEnabled,
3191
+ onChange: onToggleAnimations,
3192
+ accentColor: colors.accent
3193
+ }
3194
+ )
3195
+ ]
3196
+ }
3197
+ )
3198
+ }
3199
+ ),
3200
+ settingsTab === "trading" && /* @__PURE__ */ jsxs7("div", { style: { padding: "8px 0" }, children: [
3201
+ /* @__PURE__ */ jsxs7(
3202
+ "div",
3203
+ {
3204
+ style: {
3205
+ display: "flex",
3206
+ alignItems: "center",
3207
+ gap: 12,
3208
+ marginBottom: 12
3209
+ },
3210
+ children: [
3211
+ /* @__PURE__ */ jsx8(TrendingUp, { size: 16, color: profileColors.muted }),
3212
+ /* @__PURE__ */ jsxs7("div", { children: [
3213
+ /* @__PURE__ */ jsx8(
3214
+ "p",
3215
+ {
3216
+ style: {
3217
+ margin: 0,
3218
+ fontSize: 12.5,
3219
+ lineHeight: "1rem",
3220
+ fontWeight: 500,
3221
+ color: profileColors.text
3222
+ },
3223
+ children: "Default Slippage"
3224
+ }
3225
+ ),
3226
+ /* @__PURE__ */ jsx8(
3227
+ "p",
3228
+ {
3229
+ style: {
3230
+ margin: 0,
3231
+ fontSize: 12.5,
3232
+ lineHeight: "1rem",
3233
+ color: profileColors.muted
3234
+ },
3235
+ children: "Max price deviation for market orders"
3236
+ }
3237
+ )
3238
+ ] })
3239
+ ]
3240
+ }
3241
+ ),
3242
+ /* @__PURE__ */ jsx8("div", { style: { display: "flex", gap: 6 }, children: slippageOptions.map((option) => /* @__PURE__ */ jsx8(
3243
+ SlippageButton,
3244
+ {
3245
+ onClick: () => onSlippageChange(option.value),
3246
+ selected: defaultSlippage === option.value,
3247
+ children: option.label
3248
+ },
3249
+ option.value
3250
+ )) })
3251
+ ] }),
3252
+ settingsTab === "wallets" && /* @__PURE__ */ jsxs7(
3253
+ "div",
3254
+ {
3255
+ style: {
3256
+ display: "flex",
3257
+ flexDirection: "column",
3258
+ gap: 8
3259
+ },
3260
+ children: [
3261
+ wallets.length === 0 ? /* @__PURE__ */ jsxs7(
3262
+ "div",
3263
+ {
3264
+ style: {
3265
+ textAlign: "center",
3266
+ padding: "32px 0"
3267
+ },
3268
+ children: [
3269
+ /* @__PURE__ */ jsx8(
3270
+ "div",
3271
+ {
3272
+ style: {
3273
+ width: 40,
3274
+ height: 40,
3275
+ borderRadius: "50%",
3276
+ background: "rgba(255,255,255,0.04)",
3277
+ display: "flex",
3278
+ alignItems: "center",
3279
+ justifyContent: "center",
3280
+ margin: "0 auto 12px"
3281
+ },
3282
+ children: /* @__PURE__ */ jsx8(Wallet, { size: 18, color: profileColors.muted })
3283
+ }
3284
+ ),
3285
+ /* @__PURE__ */ jsx8(
3286
+ "p",
3287
+ {
3288
+ style: {
3289
+ margin: 0,
3290
+ fontSize: 12.5,
3291
+ lineHeight: "1rem",
3292
+ color: profileColors.muted
3293
+ },
3294
+ children: "No wallets yet"
3295
+ }
3296
+ )
3297
+ ]
3298
+ }
3299
+ ) : /* @__PURE__ */ jsx8(
3300
+ "div",
3301
+ {
3302
+ style: {
3303
+ maxHeight: 208,
3304
+ overflowY: "auto",
3305
+ display: "flex",
3306
+ flexDirection: "column",
3307
+ gap: 6
3308
+ },
3309
+ children: wallets.map((wallet) => /* @__PURE__ */ jsx8(
3310
+ WalletRow,
3311
+ {
3312
+ wallet,
3313
+ colors,
3314
+ onRename: () => setWalletToRename(wallet),
3315
+ onDelete: () => setWalletToDelete(wallet),
3316
+ onShowPortfolio: onShowPortfolio ? () => onShowPortfolio(wallet) : void 0
3317
+ },
3318
+ wallet.id
3319
+ ))
3320
+ }
3321
+ ),
3322
+ /* @__PURE__ */ jsxs7(
3323
+ "p",
3324
+ {
3325
+ style: {
3326
+ margin: "4px 0 0",
3327
+ fontSize: 12.5,
3328
+ lineHeight: "1rem",
3329
+ color: profileColors.subdued,
3330
+ textAlign: "center"
3331
+ },
3332
+ children: [
3333
+ wallets.length,
3334
+ " wallet",
3335
+ wallets.length !== 1 ? "s" : "",
3336
+ " linked"
3337
+ ]
3338
+ }
3339
+ )
3340
+ ]
3341
+ }
3342
+ )
3343
+ ] }),
3344
+ /* @__PURE__ */ jsx8("div", { style: { padding: "0 24px 24px" }, children: /* @__PURE__ */ jsx8(
3345
+ "button",
3346
+ {
3347
+ onClick: onClose,
3348
+ style: {
3349
+ ...raisedButtonStyle("default"),
3350
+ width: "100%",
3351
+ padding: "6px 0",
3352
+ fontSize: 12.5,
3353
+ lineHeight: "1rem",
3354
+ fontWeight: 500,
3355
+ borderRadius: 8,
3356
+ cursor: "pointer"
3357
+ },
3358
+ children: "Close"
3359
+ }
3360
+ ) })
3361
+ ]
3362
+ },
3363
+ "panel"
3364
+ ) })
3365
+ ] }) }),
3366
+ /* @__PURE__ */ jsx8(
3367
+ DeleteWalletModal,
3368
+ {
3369
+ isOpen: !!walletToDelete,
3370
+ onClose: () => setWalletToDelete(null),
3371
+ wallet: walletToDelete,
3372
+ onConfirm: handleDeleteWallet,
3373
+ onNotify
3374
+ }
3375
+ ),
3376
+ /* @__PURE__ */ jsx8(
3377
+ RenameWalletModal,
3378
+ {
3379
+ isOpen: !!walletToRename,
3380
+ onClose: () => setWalletToRename(null),
3381
+ wallet: walletToRename,
3382
+ onConfirm: handleRenameWallet,
3383
+ onNotify,
3384
+ accentColor: colors.accent
3385
+ }
3386
+ )
3387
+ ] });
3388
+ }
3389
+ function WalletRow({
3390
+ wallet,
3391
+ colors,
3392
+ onRename,
3393
+ onDelete,
3394
+ onShowPortfolio
3395
+ }) {
3396
+ const [hovered, setHovered] = useState4(false);
3397
+ return /* @__PURE__ */ jsxs7(
3398
+ "div",
3399
+ {
3400
+ style: {
3401
+ ...walletRowStyle,
3402
+ background: hovered ? profileColors.surfaceBtnHover : profileColors.surfaceBtn,
3403
+ borderColor: hovered ? profileColors.surfaceBdHover : profileColors.surfaceBd
3404
+ },
3405
+ onMouseEnter: () => setHovered(true),
3406
+ onMouseLeave: () => setHovered(false),
3407
+ children: [
3408
+ /* @__PURE__ */ jsx8(
3409
+ "div",
3410
+ {
3411
+ style: {
3412
+ width: 32,
3413
+ height: 32,
3414
+ borderRadius: 6,
3415
+ background: colors.accentBackground,
3416
+ border: `1px solid ${colors.accentBorder}`,
3417
+ display: "flex",
3418
+ alignItems: "center",
3419
+ justifyContent: "center",
3420
+ flexShrink: 0
3421
+ },
3422
+ children: /* @__PURE__ */ jsx8(
3423
+ "span",
3424
+ {
3425
+ style: {
3426
+ fontSize: 12.5,
3427
+ lineHeight: "1rem",
3428
+ fontWeight: 600,
3429
+ color: colors.accentText
3430
+ },
3431
+ children: (wallet.name || "W")[0].toUpperCase()
3432
+ }
3433
+ )
3434
+ }
3435
+ ),
3436
+ /* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
3437
+ /* @__PURE__ */ jsx8(
3438
+ "p",
3439
+ {
3440
+ style: {
3441
+ margin: 0,
3442
+ fontSize: 12.5,
3443
+ lineHeight: "1rem",
3444
+ fontWeight: 500,
3445
+ color: profileColors.text,
3446
+ overflow: "hidden",
3447
+ textOverflow: "ellipsis",
3448
+ whiteSpace: "nowrap"
3449
+ },
3450
+ children: wallet.name || "Unnamed"
3451
+ }
3452
+ ),
3453
+ /* @__PURE__ */ jsxs7(
3454
+ "p",
3455
+ {
3456
+ style: {
3457
+ margin: 0,
3458
+ fontSize: 12.5,
3459
+ lineHeight: "1rem",
3460
+ color: profileColors.muted,
3461
+ fontFamily: fontFamily.mono
3462
+ },
3463
+ children: [
3464
+ wallet.ethereumAddress?.slice(0, 6),
3465
+ "...",
3466
+ wallet.ethereumAddress?.slice(-4)
3467
+ ]
3468
+ }
3469
+ )
3470
+ ] }),
3471
+ /* @__PURE__ */ jsxs7(
3472
+ "div",
3473
+ {
3474
+ style: {
3475
+ display: "flex",
3476
+ alignItems: "center",
3477
+ gap: 4,
3478
+ flexShrink: 0,
3479
+ opacity: hovered ? 1 : 0,
3480
+ transition: "opacity 120ms"
3481
+ },
3482
+ children: [
3483
+ onShowPortfolio && /* @__PURE__ */ jsx8(
3484
+ IconBtn,
3485
+ {
3486
+ color: colors.accent,
3487
+ hoverBackgroundColor: colors.accentHoverBackground,
3488
+ title: "View portfolio",
3489
+ ariaLabel: `View portfolio for ${wallet.name || "wallet"}`,
3490
+ onClick: onShowPortfolio,
3491
+ children: /* @__PURE__ */ jsx8(LayoutDashboard, { size: 13 })
3492
+ }
3493
+ ),
3494
+ /* @__PURE__ */ jsx8(
3495
+ IconBtn,
3496
+ {
3497
+ color: colors.accent,
3498
+ hoverBackgroundColor: colors.accentHoverBackground,
3499
+ title: "Rename wallet",
3500
+ ariaLabel: `Rename ${wallet.name || "wallet"}`,
3501
+ onClick: onRename,
3502
+ children: /* @__PURE__ */ jsx8(Pencil, { size: 13 })
3503
+ }
3504
+ ),
3505
+ /* @__PURE__ */ jsx8(
3506
+ IconBtn,
3507
+ {
3508
+ color: "#ef4444",
3509
+ hoverBackgroundColor: "rgba(239,68,68,0.1)",
3510
+ title: "Delete wallet",
3511
+ ariaLabel: `Delete ${wallet.name || "wallet"}`,
3512
+ onClick: onDelete,
3513
+ children: /* @__PURE__ */ jsx8(Trash2, { size: 13 })
3514
+ }
3515
+ )
3516
+ ]
3517
+ }
3518
+ )
3519
+ ]
3520
+ }
3521
+ );
3522
+ }
3523
+ function IconBtn({
3524
+ children,
3525
+ color,
3526
+ hoverBackgroundColor,
3527
+ title,
3528
+ ariaLabel,
3529
+ onClick
3530
+ }) {
3531
+ const [hovered, setHovered] = useState4(false);
3532
+ return /* @__PURE__ */ jsx8(
3533
+ "button",
3534
+ {
3535
+ onMouseEnter: () => setHovered(true),
3536
+ onMouseLeave: () => setHovered(false),
3537
+ onClick,
3538
+ title,
3539
+ "aria-label": ariaLabel,
3540
+ style: {
3541
+ padding: 6,
3542
+ borderRadius: 4,
3543
+ background: hovered ? hoverBackgroundColor ?? "transparent" : "transparent",
3544
+ border: "none",
3545
+ color: hovered ? color : profileColors.disabled,
3546
+ cursor: "pointer",
3547
+ display: "flex",
3548
+ alignItems: "center",
3549
+ justifyContent: "center",
3550
+ transition: "color 120ms, background 120ms"
3551
+ },
3552
+ children
3553
+ }
3554
+ );
3555
+ }
3556
+
3557
+ // src/WalletSelectorDropdown.tsx
3558
+ import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
3559
+ var DEFAULT_BACKGROUND_COLOR = "rgba(20,20,20,0.95)";
3560
+ var getWalletNameParts = (name) => (name ?? "").split("/").map((part) => part.trim()).filter(Boolean);
3561
+ var buildWalletListEntries = (wallets) => {
3562
+ const standalone = [];
3563
+ const grouped = /* @__PURE__ */ new Map();
3564
+ const walletParts = (wallets ?? []).map((wallet) => ({
3565
+ wallet,
3566
+ parts: getWalletNameParts(wallet.name)
3567
+ }));
3568
+ const prefixCounts = /* @__PURE__ */ new Map();
3569
+ walletParts.forEach(({ parts }) => {
3570
+ for (let index = 1; index < parts.length; index += 1) {
3571
+ const prefix = parts.slice(0, index).join("/");
3572
+ prefixCounts.set(prefix, (prefixCounts.get(prefix) ?? 0) + 1);
3573
+ }
3574
+ });
3575
+ walletParts.forEach(({ wallet, parts }) => {
3576
+ const groupPath = (() => {
3577
+ for (let index = parts.length - 1; index > 0; index -= 1) {
3578
+ const prefix = parts.slice(0, index).join("/");
3579
+ if ((prefixCounts.get(prefix) ?? 0) > 1) {
3580
+ return prefix;
3581
+ }
3582
+ }
3583
+ return null;
3584
+ })();
3585
+ const groupDepth = groupPath ? groupPath.split("/").length : 0;
3586
+ const item = {
3587
+ wallet,
3588
+ label: parts.length > 0 ? parts.slice(groupDepth).join("/") : null
3589
+ };
3590
+ if (!groupPath) {
3591
+ standalone.push(item);
3592
+ return;
3593
+ }
3594
+ const groupItems = grouped.get(groupPath) ?? [];
3595
+ groupItems.push(item);
3596
+ grouped.set(groupPath, groupItems);
3597
+ });
3598
+ const entries = standalone.map((item) => ({
3599
+ type: "wallet",
3600
+ item
3601
+ }));
3602
+ grouped.forEach((items, path) => {
3603
+ if (items.length === 1) {
3604
+ entries.push({
3605
+ type: "wallet",
3606
+ item: { ...items[0], label: `${path}/${items[0].label ?? ""}` }
3607
+ });
3608
+ return;
3609
+ }
3610
+ entries.push({
3611
+ type: "group",
3612
+ path,
3613
+ items: [...items].sort(
3614
+ (a, b) => (a.label ?? "").localeCompare(b.label ?? "")
3615
+ )
3616
+ });
3617
+ });
3618
+ return entries.sort((a, b) => {
3619
+ const aLabel = a.type === "group" ? a.path : a.item.label ?? "";
3620
+ const bLabel = b.type === "group" ? b.path : b.item.label ?? "";
3621
+ return aLabel.localeCompare(bLabel);
3622
+ });
3623
+ };
3624
+ var formatCompactAddress = (addr) => {
3625
+ if (!addr) return "";
3626
+ return `${addr.slice(0, 4)}...${addr.slice(-2)}`;
3627
+ };
3628
+ var rootStyle = {
3629
+ position: "absolute",
3630
+ right: 0,
3631
+ top: "calc(100% + 4px)",
3632
+ width: 240,
3633
+ backdropFilter: "blur(10px)",
3634
+ WebkitBackdropFilter: "blur(10px)",
3635
+ borderRadius: 9,
3636
+ boxShadow: "0 8px 40px rgba(0,0,0,0.85)",
3637
+ border: "1px solid rgba(255,255,255,0.08)",
3638
+ zIndex: 50,
3639
+ transformOrigin: "top right",
3640
+ overflow: "hidden"
3641
+ };
3642
+ var sectionBorder = "1px solid rgba(255,255,255,0.06)";
3643
+ var sectionHeaderStyle = {
3644
+ padding: "8px 16px",
3645
+ fontSize: 12,
3646
+ fontWeight: 600,
3647
+ color: "#9ca3af",
3648
+ textTransform: "uppercase",
3649
+ letterSpacing: "0.05em"
3650
+ };
3651
+ var footerBtnStyle = {
3652
+ width: "100%",
3653
+ textAlign: "left",
3654
+ padding: "10px 16px",
3655
+ fontSize: 14,
3656
+ background: "transparent",
3657
+ border: "none",
3658
+ cursor: "pointer",
3659
+ display: "flex",
3660
+ alignItems: "center",
3661
+ gap: 8,
3662
+ color: "#9ca3af",
3663
+ transition: "background 120ms, color 120ms"
3664
+ };
3665
+ function WalletSelectorDropdown({
3666
+ isOpen,
3667
+ onClose,
3668
+ onAddWallet,
3669
+ onShowPortfolio,
3670
+ onLogout,
3671
+ onNotify,
3672
+ vipThreshold = 10,
3673
+ animationsEnabled,
3674
+ onToggleAnimations,
3675
+ defaultSlippage,
3676
+ onSlippageChange,
3677
+ slippageOptions,
3678
+ onWalletDeleted,
3679
+ onWalletRenamed,
3680
+ accentColor,
3681
+ principalColors,
3682
+ backgroundColor = DEFAULT_BACKGROUND_COLOR
3683
+ }) {
3684
+ const { user, wallets, selectedWalletId, selectWallet, logout, authMethod } = useHypurrConnectInternal();
3685
+ const [profileOpen, setProfileOpen] = useState5(false);
3686
+ const openProfile = useCallback6(() => {
3687
+ setProfileOpen(true);
3688
+ onClose();
3689
+ }, [onClose]);
3690
+ const walletListEntries = useMemo2(
3691
+ () => buildWalletListEntries(Array.isArray(wallets) ? wallets : void 0),
3692
+ [wallets]
3693
+ );
3694
+ const handleCopyAddress = useCallback6(
3695
+ (address) => {
3696
+ if (!address) return;
3697
+ navigator.clipboard.writeText(address);
3698
+ onNotify?.({ type: "success", message: "Address copied" });
3699
+ },
3700
+ [onNotify]
3701
+ );
3702
+ const handleLogout = useCallback6(() => {
3703
+ onLogout?.();
3704
+ logout();
3705
+ onClose();
3706
+ }, [logout, onClose, onLogout]);
3707
+ const profilePic = user?.photoUrl;
3708
+ const displayName = user?.displayName ?? "";
3709
+ const hfunScore = user?.hfunScore ?? 0;
3710
+ const isVip = hfunScore > vipThreshold;
3711
+ const colors = resolvePrincipalColors(accentColor, principalColors);
3712
+ const renderWalletRow = (item, depth) => {
3713
+ const { wallet, label } = item;
3714
+ const isSelected = wallet.id === selectedWalletId;
3715
+ const compactAddress = formatCompactAddress(wallet.ethereumAddress);
3716
+ return /* @__PURE__ */ jsx9(
3717
+ WalletRow2,
3718
+ {
3719
+ depth,
3720
+ isSelected,
3721
+ label,
3722
+ compactAddress,
3723
+ onSelect: () => {
3724
+ selectWallet(wallet.id);
3725
+ onClose();
3726
+ },
3727
+ onShowPortfolio: onShowPortfolio ? () => {
3728
+ onShowPortfolio(wallet);
3729
+ onClose();
3730
+ } : void 0,
3731
+ onCopy: () => handleCopyAddress(wallet.ethereumAddress),
3732
+ colors
3733
+ },
3734
+ wallet.id
3735
+ );
3736
+ };
3737
+ return /* @__PURE__ */ jsxs8(Fragment6, { children: [
3738
+ /* @__PURE__ */ jsx9(AnimatePresence5, { children: isOpen && /* @__PURE__ */ jsxs8(
3739
+ motion5.div,
3740
+ {
3741
+ style: { ...rootStyle, background: backgroundColor },
3742
+ initial: { opacity: 0, scale: 0.95 },
3743
+ animate: { opacity: 1, scale: 1 },
3744
+ exit: { opacity: 0, scale: 0.95 },
3745
+ transition: { duration: 0.15, ease: "easeOut" },
3746
+ children: [
3747
+ /* @__PURE__ */ jsxs8(
3748
+ "button",
3749
+ {
3750
+ onClick: openProfile,
3751
+ style: {
3752
+ width: "100%",
3753
+ padding: "12px 16px",
3754
+ borderBottom: sectionBorder,
3755
+ display: "flex",
3756
+ alignItems: "center",
3757
+ gap: 12,
3758
+ background: "transparent",
3759
+ border: "none",
3760
+ borderBottomColor: "rgba(255,255,255,0.06)",
3761
+ borderBottomStyle: "solid",
3762
+ borderBottomWidth: 1,
3763
+ cursor: "pointer",
3764
+ textAlign: "left",
3765
+ transition: "background 120ms"
3766
+ },
3767
+ onMouseEnter: (e) => e.currentTarget.style.background = "rgba(255,255,255,0.06)",
3768
+ onMouseLeave: (e) => e.currentTarget.style.background = "transparent",
3769
+ children: [
3770
+ profilePic ? /* @__PURE__ */ jsxs8(
3771
+ "div",
3772
+ {
3773
+ style: {
3774
+ position: "relative",
3775
+ padding: isVip ? 2 : 0,
3776
+ borderRadius: "50%",
3777
+ background: isVip ? "linear-gradient(to right, #fde047, #eab308, #ca8a04)" : "transparent"
3778
+ },
3779
+ children: [
3780
+ /* @__PURE__ */ jsx9(
3781
+ "img",
3782
+ {
3783
+ src: profilePic,
3784
+ alt: "Profile",
3785
+ style: {
3786
+ height: 32,
3787
+ width: 32,
3788
+ borderRadius: "50%",
3789
+ display: "block"
3790
+ }
3791
+ }
3792
+ ),
3793
+ isVip && /* @__PURE__ */ jsx9(
3794
+ Crown,
3795
+ {
3796
+ size: 12,
3797
+ color: "#fde047",
3798
+ fill: "#eab308",
3799
+ style: {
3800
+ position: "absolute",
3801
+ top: -4,
3802
+ right: -2,
3803
+ filter: "drop-shadow(0 1px 2px rgba(0,0,0,0.5))"
3804
+ }
3805
+ }
3806
+ )
3807
+ ]
3808
+ }
3809
+ ) : authMethod === "eoa" ? /* @__PURE__ */ jsx9(
3810
+ "div",
3811
+ {
3812
+ style: {
3813
+ height: 32,
3814
+ width: 32,
3815
+ borderRadius: 7,
3816
+ background: colors.accentBackground,
3817
+ border: `1px solid ${colors.accentBorder}`,
3818
+ display: "flex",
3819
+ alignItems: "center",
3820
+ justifyContent: "center",
3821
+ flexShrink: 0
3822
+ },
3823
+ children: /* @__PURE__ */ jsx9(Wallet, { size: 14, color: colors.accentText })
3824
+ }
3825
+ ) : /* @__PURE__ */ jsxs8(
3826
+ "div",
3827
+ {
3828
+ style: {
3829
+ position: "relative",
3830
+ height: 32,
3831
+ width: 32,
3832
+ borderRadius: "50%",
3833
+ background: isVip ? "linear-gradient(135deg, #ca8a04, #fde047)" : colors.accentBackground,
3834
+ border: `1px solid ${isVip ? "rgba(255,255,255,0.08)" : colors.accentBorder}`,
3835
+ display: "flex",
3836
+ alignItems: "center",
3837
+ justifyContent: "center",
3838
+ color: isVip ? profileColors.text : colors.accentText,
3839
+ fontSize: 14,
3840
+ fontWeight: 700
3841
+ },
3842
+ children: [
3843
+ displayName.charAt(0),
3844
+ isVip && /* @__PURE__ */ jsx9(
3845
+ Crown,
3846
+ {
3847
+ size: 12,
3848
+ color: "#fde047",
3849
+ fill: "#eab308",
3850
+ style: {
3851
+ position: "absolute",
3852
+ top: -4,
3853
+ right: -2,
3854
+ filter: "drop-shadow(0 1px 2px rgba(0,0,0,0.5))"
3855
+ }
3856
+ }
3857
+ )
3858
+ ]
3859
+ }
3860
+ ),
3861
+ /* @__PURE__ */ jsx9("div", { style: { overflow: "hidden", flex: 1 }, children: /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
3862
+ /* @__PURE__ */ jsx9(
3863
+ "p",
3864
+ {
3865
+ style: {
3866
+ margin: 0,
3867
+ fontSize: 14,
3868
+ fontWeight: 500,
3869
+ color: "#fff",
3870
+ overflow: "hidden",
3871
+ textOverflow: "ellipsis",
3872
+ whiteSpace: "nowrap"
3873
+ },
3874
+ children: displayName
3875
+ }
3876
+ ),
3877
+ hfunScore > 0 && /* @__PURE__ */ jsxs8(
3878
+ "span",
3879
+ {
3880
+ style: {
3881
+ display: "inline-flex",
3882
+ alignItems: "center",
3883
+ gap: 2,
3884
+ fontSize: 12,
3885
+ color: "#eab308",
3886
+ fontWeight: 500,
3887
+ background: "rgba(234,179,8,0.1)",
3888
+ padding: "2px 6px",
3889
+ borderRadius: 4
3890
+ },
3891
+ children: [
3892
+ /* @__PURE__ */ jsx9(Star, { size: 10, color: "#eab308", fill: "#eab308" }),
3893
+ hfunScore.toFixed(0)
3894
+ ]
3895
+ }
3896
+ )
3897
+ ] }) })
3898
+ ]
3899
+ }
3900
+ ),
3901
+ /* @__PURE__ */ jsxs8("div", { style: { borderBottom: sectionBorder }, children: [
3902
+ /* @__PURE__ */ jsx9("div", { style: sectionHeaderStyle, children: "Wallets" }),
3903
+ /* @__PURE__ */ jsx9(
3904
+ "div",
3905
+ {
3906
+ style: {
3907
+ maxHeight: 256,
3908
+ overflowY: "auto",
3909
+ paddingBottom: 4
3910
+ },
3911
+ children: walletListEntries.map((entry) => {
3912
+ if (entry.type === "wallet") {
3913
+ return renderWalletRow(entry.item, 0);
3914
+ }
3915
+ const isSelectedGroup = entry.items.some(
3916
+ (item) => item.wallet.id === selectedWalletId
3917
+ );
3918
+ return /* @__PURE__ */ jsxs8(Fragment5, { children: [
3919
+ /* @__PURE__ */ jsxs8(
3920
+ "div",
3921
+ {
3922
+ style: {
3923
+ display: "flex",
3924
+ alignItems: "center",
3925
+ gap: 6,
3926
+ padding: "8px 16px 4px",
3927
+ fontSize: 11,
3928
+ fontWeight: 600,
3929
+ textTransform: "uppercase",
3930
+ letterSpacing: "0.05em",
3931
+ color: isSelectedGroup ? "#e5e7eb" : "#6b7280"
3932
+ },
3933
+ children: [
3934
+ /* @__PURE__ */ jsx9(Folder, { size: 12, style: { flexShrink: 0 } }),
3935
+ /* @__PURE__ */ jsx9(
3936
+ "span",
3937
+ {
3938
+ style: {
3939
+ minWidth: 0,
3940
+ flex: 1,
3941
+ overflow: "hidden",
3942
+ textOverflow: "ellipsis",
3943
+ whiteSpace: "nowrap"
3944
+ },
3945
+ children: entry.path
3946
+ }
3947
+ ),
3948
+ /* @__PURE__ */ jsx9(
3949
+ "span",
3950
+ {
3951
+ style: {
3952
+ flexShrink: 0,
3953
+ fontVariantNumeric: "tabular-nums",
3954
+ color: "#4b5563"
3955
+ },
3956
+ children: entry.items.length
3957
+ }
3958
+ )
3959
+ ]
3960
+ }
3961
+ ),
3962
+ entry.items.map((item) => renderWalletRow(item, 1))
3963
+ ] }, entry.path);
3964
+ })
3965
+ }
3966
+ ),
3967
+ authMethod !== "eoa" && onAddWallet && /* @__PURE__ */ jsxs8(
3968
+ "button",
3969
+ {
3970
+ onClick: () => {
3971
+ onAddWallet();
3972
+ onClose();
3973
+ },
3974
+ style: {
3975
+ width: "100%",
3976
+ textAlign: "left",
3977
+ padding: "8px 16px",
3978
+ fontSize: 14,
3979
+ background: "transparent",
3980
+ border: "none",
3981
+ cursor: "pointer",
3982
+ display: "flex",
3983
+ alignItems: "center",
3984
+ gap: 8,
3985
+ color: colors.accentText,
3986
+ transition: "background 120ms"
3987
+ },
3988
+ onMouseEnter: (e) => e.currentTarget.style.background = "rgba(255,255,255,0.06)",
3989
+ onMouseLeave: (e) => e.currentTarget.style.background = "transparent",
3990
+ children: [
3991
+ /* @__PURE__ */ jsx9(Plus, { size: 14 }),
3992
+ "Add Wallet"
3993
+ ]
3994
+ }
3995
+ )
3996
+ ] }),
3997
+ /* @__PURE__ */ jsxs8("div", { children: [
3998
+ /* @__PURE__ */ jsx9(
3999
+ FooterBtn,
4000
+ {
4001
+ onClick: openProfile,
4002
+ icon: /* @__PURE__ */ jsx9(User, { size: 14 }),
4003
+ label: "Profile & Settings"
4004
+ }
4005
+ ),
4006
+ /* @__PURE__ */ jsx9(
4007
+ FooterBtn,
4008
+ {
4009
+ onClick: handleLogout,
4010
+ icon: /* @__PURE__ */ jsx9(LogOut, { size: 14 }),
4011
+ label: "Logout",
4012
+ hoverColor: "#ef4444"
4013
+ }
4014
+ )
4015
+ ] })
4016
+ ]
4017
+ }
4018
+ ) }),
4019
+ /* @__PURE__ */ jsx9(
4020
+ UserProfileModal,
4021
+ {
4022
+ isOpen: profileOpen,
4023
+ onClose: () => setProfileOpen(false),
4024
+ animationsEnabled,
4025
+ onToggleAnimations,
4026
+ defaultSlippage,
4027
+ onSlippageChange,
4028
+ slippageOptions,
4029
+ accentColor,
4030
+ principalColors,
4031
+ onWalletDeleted,
4032
+ onWalletRenamed,
4033
+ onShowPortfolio: onShowPortfolio ? (wallet) => {
4034
+ onShowPortfolio(wallet);
4035
+ setProfileOpen(false);
4036
+ } : void 0,
4037
+ onNotify
4038
+ }
4039
+ )
4040
+ ] });
4041
+ }
4042
+ function FooterBtn({
4043
+ onClick,
4044
+ icon,
4045
+ label,
4046
+ hoverColor = "#fff"
4047
+ }) {
4048
+ return /* @__PURE__ */ jsxs8(
4049
+ "button",
4050
+ {
4051
+ onClick,
4052
+ style: footerBtnStyle,
4053
+ onMouseEnter: (e) => {
4054
+ e.currentTarget.style.background = "rgba(255,255,255,0.06)";
4055
+ e.currentTarget.style.color = hoverColor;
4056
+ },
4057
+ onMouseLeave: (e) => {
4058
+ e.currentTarget.style.background = "transparent";
4059
+ e.currentTarget.style.color = "#9ca3af";
4060
+ },
4061
+ children: [
4062
+ icon,
4063
+ label
4064
+ ]
4065
+ }
4066
+ );
4067
+ }
4068
+ function WalletRow2({
4069
+ depth,
4070
+ isSelected,
4071
+ label,
4072
+ compactAddress,
4073
+ onSelect,
4074
+ onShowPortfolio,
4075
+ onCopy,
4076
+ colors
4077
+ }) {
4078
+ return /* @__PURE__ */ jsxs8(
4079
+ "div",
4080
+ {
4081
+ style: {
4082
+ width: "100%",
4083
+ paddingLeft: 16 + depth * 14,
4084
+ paddingRight: 16,
4085
+ paddingTop: 6,
4086
+ paddingBottom: 6,
4087
+ fontSize: 14,
4088
+ color: "#d1d5db",
4089
+ display: "flex",
4090
+ alignItems: "center",
4091
+ background: isSelected ? "rgba(255,255,255,0.06)" : "transparent",
4092
+ transition: "background 120ms"
4093
+ },
4094
+ onMouseEnter: (e) => {
4095
+ e.currentTarget.style.background = "rgba(255,255,255,0.06)";
4096
+ const actions = e.currentTarget.querySelector("[data-row-actions]");
4097
+ if (actions) actions.style.opacity = "1";
4098
+ },
4099
+ onMouseLeave: (e) => {
4100
+ e.currentTarget.style.background = isSelected ? "rgba(255,255,255,0.06)" : "transparent";
4101
+ const actions = e.currentTarget.querySelector("[data-row-actions]");
4102
+ if (actions) actions.style.opacity = "0";
4103
+ },
4104
+ children: [
4105
+ /* @__PURE__ */ jsx9(
4106
+ "button",
4107
+ {
4108
+ onClick: onSelect,
4109
+ style: {
4110
+ flex: 1,
4111
+ textAlign: "left",
4112
+ minWidth: 0,
4113
+ display: "flex",
4114
+ alignItems: "center",
4115
+ gap: 4,
4116
+ background: "transparent",
4117
+ border: "none",
4118
+ color: "inherit",
4119
+ cursor: "pointer",
4120
+ padding: 0
4121
+ },
4122
+ children: label ? /* @__PURE__ */ jsxs8(Fragment6, { children: [
4123
+ /* @__PURE__ */ jsx9(
4124
+ "span",
4125
+ {
4126
+ style: {
4127
+ overflow: "hidden",
4128
+ textOverflow: "ellipsis",
4129
+ whiteSpace: "nowrap",
4130
+ color: isSelected ? "#fff" : void 0,
4131
+ fontWeight: isSelected ? 500 : void 0
4132
+ },
4133
+ children: label
4134
+ }
4135
+ ),
4136
+ /* @__PURE__ */ jsxs8(
4137
+ "span",
4138
+ {
4139
+ style: {
4140
+ fontSize: 12,
4141
+ fontWeight: 400,
4142
+ flexShrink: 0,
4143
+ color: "#6b7280"
4144
+ },
4145
+ children: [
4146
+ "(",
4147
+ compactAddress,
4148
+ ")"
4149
+ ]
4150
+ }
4151
+ )
4152
+ ] }) : /* @__PURE__ */ jsx9(
4153
+ "span",
4154
+ {
4155
+ style: {
4156
+ fontSize: 12,
4157
+ color: isSelected ? "#fff" : "#9ca3af",
4158
+ fontWeight: isSelected ? 500 : void 0
4159
+ },
4160
+ children: compactAddress
4161
+ }
4162
+ )
4163
+ }
4164
+ ),
4165
+ /* @__PURE__ */ jsxs8(
4166
+ "div",
4167
+ {
4168
+ "data-row-actions": true,
4169
+ style: {
4170
+ display: "flex",
4171
+ alignItems: "center",
4172
+ opacity: 0,
4173
+ transition: "opacity 120ms"
4174
+ },
4175
+ children: [
4176
+ onShowPortfolio && /* @__PURE__ */ jsx9(
4177
+ RowIconBtn,
4178
+ {
4179
+ title: "View portfolio",
4180
+ hoverColor: colors.accent,
4181
+ onClick: (e) => {
4182
+ e.stopPropagation();
4183
+ onShowPortfolio();
4184
+ },
4185
+ children: /* @__PURE__ */ jsx9(LayoutDashboard, { size: 12 })
4186
+ }
4187
+ ),
4188
+ /* @__PURE__ */ jsx9(
4189
+ RowIconBtn,
4190
+ {
4191
+ title: "Copy address",
4192
+ hoverColor: colors.accent,
4193
+ onClick: (e) => {
4194
+ e.stopPropagation();
4195
+ onCopy();
4196
+ },
4197
+ children: /* @__PURE__ */ jsx9(Copy, { size: 12 })
4198
+ }
4199
+ )
4200
+ ]
4201
+ }
4202
+ )
4203
+ ]
4204
+ }
4205
+ );
4206
+ }
4207
+ function RowIconBtn({
4208
+ children,
4209
+ title,
4210
+ onClick,
4211
+ hoverColor = profileColors.text
4212
+ }) {
4213
+ return /* @__PURE__ */ jsx9(
4214
+ "button",
4215
+ {
4216
+ onClick,
4217
+ title,
4218
+ style: {
4219
+ padding: 4,
4220
+ marginLeft: 4,
4221
+ background: "transparent",
4222
+ border: "none",
4223
+ color: "#4b5563",
4224
+ cursor: "pointer",
4225
+ display: "flex",
4226
+ alignItems: "center",
4227
+ justifyContent: "center",
4228
+ transition: "color 120ms"
4229
+ },
4230
+ onMouseEnter: (e) => e.currentTarget.style.color = hoverColor,
4231
+ onMouseLeave: (e) => e.currentTarget.style.color = "#4b5563",
4232
+ children
4233
+ }
4234
+ );
4235
+ }
4236
+
1535
4237
  // src/types.ts
1536
- function createEoaSigner(signTypedDataAsync, chainId) {
4238
+ function createEoaSigner(signTypedDataAsync, chainId, options = {}) {
1537
4239
  const resolve = typeof signTypedDataAsync === "function" ? signTypedDataAsync : (args) => signTypedDataAsync.current(args);
1538
4240
  return {
1539
4241
  signTypedData: (params) => resolve(params),
4242
+ signTransaction: options.signTransaction,
4243
+ request: options.request,
1540
4244
  chainId
1541
4245
  };
1542
4246
  }
1543
4247
  export {
4248
+ DeleteWalletModal,
1544
4249
  GrpcExchangeTransport,
1545
4250
  HypurrConnectProvider,
1546
4251
  LoginModal,
4252
+ PrivateKeySigner,
4253
+ RenameWalletModal,
4254
+ UserProfileModal,
4255
+ WalletSelectorDropdown,
1547
4256
  createEoaSigner,
1548
4257
  createStaticClient,
1549
4258
  createTelegramClient,