@hfunlabs/hypurr-connect 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/index.d.ts +86 -3
- package/dist/index.js +1827 -333
- package/dist/index.js.map +1 -1
- package/package.json +21 -6
- package/src/AddWalletModal.tsx +744 -0
- package/src/AgentExpiryWarning.tsx +129 -0
- package/src/DeleteWalletModal.tsx +2 -1
- package/src/HypurrConnectProvider.tsx +190 -0
- package/src/LoginModal.tsx +11 -11
- package/src/RenameWalletModal.tsx +2 -1
- package/src/RenewAgentModal.tsx +380 -0
- package/src/UserProfileModal.tsx +151 -23
- package/src/WalletSelectorDropdown.tsx +138 -4
- package/src/agent.ts +38 -12
- package/src/agentWallet.ts +86 -0
- package/src/css.d.ts +1 -0
- package/src/icons/lucide.tsx +61 -0
- package/src/index.ts +17 -1
- package/src/profileStyles.ts +58 -0
- package/src/styles.css +1 -0
- package/src/tailwind.css +77 -0
- package/src/types.ts +13 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useCallback,
|
|
3
|
+
useRef,
|
|
4
|
+
useState,
|
|
5
|
+
type CSSProperties,
|
|
6
|
+
type RefCallback,
|
|
7
|
+
} from "react";
|
|
8
|
+
import { AlertTriangle } from "./icons/lucide";
|
|
9
|
+
|
|
10
|
+
const EXPIRED_AGENT_COLOR = "#f59e0b";
|
|
11
|
+
|
|
12
|
+
interface TooltipPosition {
|
|
13
|
+
left: number;
|
|
14
|
+
top: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function AgentExpiryWarningIcon({
|
|
18
|
+
message,
|
|
19
|
+
onClick,
|
|
20
|
+
size = 13,
|
|
21
|
+
}: {
|
|
22
|
+
message: string;
|
|
23
|
+
onClick?: () => void;
|
|
24
|
+
size?: number;
|
|
25
|
+
}) {
|
|
26
|
+
const triggerRef = useRef<HTMLElement | null>(null);
|
|
27
|
+
const [tooltipPosition, setTooltipPosition] =
|
|
28
|
+
useState<TooltipPosition | null>(null);
|
|
29
|
+
|
|
30
|
+
const setTriggerRef: RefCallback<HTMLElement> = useCallback((node) => {
|
|
31
|
+
triggerRef.current = node;
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
const showTooltip = useCallback(() => {
|
|
35
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
36
|
+
if (!rect) return;
|
|
37
|
+
|
|
38
|
+
const tooltipWidth = 260;
|
|
39
|
+
const left = Math.min(
|
|
40
|
+
Math.max(rect.left + rect.width / 2, tooltipWidth / 2 + 8),
|
|
41
|
+
window.innerWidth - tooltipWidth / 2 - 8,
|
|
42
|
+
);
|
|
43
|
+
const top =
|
|
44
|
+
rect.bottom + 8 < window.innerHeight - 48
|
|
45
|
+
? rect.bottom + 8
|
|
46
|
+
: Math.max(8, rect.top - 44);
|
|
47
|
+
|
|
48
|
+
setTooltipPosition({ left, top });
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
const hideTooltip = useCallback(() => {
|
|
52
|
+
setTooltipPosition(null);
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
55
|
+
const triggerStyle: CSSProperties = {
|
|
56
|
+
width: size + 5,
|
|
57
|
+
height: size + 5,
|
|
58
|
+
padding: 0,
|
|
59
|
+
border: "none",
|
|
60
|
+
borderRadius: 4,
|
|
61
|
+
background: "transparent",
|
|
62
|
+
color: EXPIRED_AGENT_COLOR,
|
|
63
|
+
display: "inline-flex",
|
|
64
|
+
alignItems: "center",
|
|
65
|
+
justifyContent: "center",
|
|
66
|
+
flexShrink: 0,
|
|
67
|
+
cursor: onClick ? "pointer" : "help",
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const sharedProps = {
|
|
71
|
+
ref: setTriggerRef,
|
|
72
|
+
"aria-label": "Agent approval expired",
|
|
73
|
+
onMouseEnter: showTooltip,
|
|
74
|
+
onMouseLeave: hideTooltip,
|
|
75
|
+
onFocus: showTooltip,
|
|
76
|
+
onBlur: hideTooltip,
|
|
77
|
+
style: triggerStyle,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<>
|
|
82
|
+
{onClick ? (
|
|
83
|
+
<button
|
|
84
|
+
type="button"
|
|
85
|
+
{...sharedProps}
|
|
86
|
+
onClick={(event) => {
|
|
87
|
+
event.stopPropagation();
|
|
88
|
+
onClick();
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<AlertTriangle size={size} color={EXPIRED_AGENT_COLOR} />
|
|
92
|
+
</button>
|
|
93
|
+
) : (
|
|
94
|
+
<span {...sharedProps}>
|
|
95
|
+
<AlertTriangle size={size} color={EXPIRED_AGENT_COLOR} />
|
|
96
|
+
</span>
|
|
97
|
+
)}
|
|
98
|
+
{tooltipPosition && (
|
|
99
|
+
<div
|
|
100
|
+
role="tooltip"
|
|
101
|
+
style={{
|
|
102
|
+
position: "fixed",
|
|
103
|
+
left: tooltipPosition.left,
|
|
104
|
+
top: tooltipPosition.top,
|
|
105
|
+
transform: "translateX(-50%)",
|
|
106
|
+
zIndex: 10_000,
|
|
107
|
+
width: 260,
|
|
108
|
+
maxWidth: "calc(100vw - 16px)",
|
|
109
|
+
padding: "7px 9px",
|
|
110
|
+
borderRadius: 6,
|
|
111
|
+
border: "1px solid rgba(255,255,255,0.12)",
|
|
112
|
+
background: "#111827",
|
|
113
|
+
boxShadow: "0 10px 28px rgba(0,0,0,0.45)",
|
|
114
|
+
color: "#e5e7eb",
|
|
115
|
+
fontSize: 12,
|
|
116
|
+
lineHeight: "1rem",
|
|
117
|
+
fontWeight: 500,
|
|
118
|
+
pointerEvents: "none",
|
|
119
|
+
whiteSpace: "normal",
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
{message}
|
|
123
|
+
</div>
|
|
124
|
+
)}
|
|
125
|
+
</>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { EXPIRED_AGENT_COLOR };
|
|
@@ -132,6 +132,7 @@ export function DeleteWalletModal({
|
|
|
132
132
|
const [deleteHovered, setDeleteHovered] = useState(false);
|
|
133
133
|
|
|
134
134
|
const walletName = wallet?.name || "Unnamed Wallet";
|
|
135
|
+
const displayAddress = wallet?.ethereumAddress;
|
|
135
136
|
const isNameMatch = confirmName === walletName;
|
|
136
137
|
const canDelete = isNameMatch && !isDeleting;
|
|
137
138
|
|
|
@@ -258,7 +259,7 @@ export function DeleteWalletModal({
|
|
|
258
259
|
wordBreak: "break-all",
|
|
259
260
|
}}
|
|
260
261
|
>
|
|
261
|
-
{
|
|
262
|
+
{displayAddress}
|
|
262
263
|
</p>
|
|
263
264
|
</div>
|
|
264
265
|
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
import {
|
|
28
28
|
AGENT_NAME,
|
|
29
29
|
clearAgent as clearStoredAgent,
|
|
30
|
+
fetchAgentByAddress,
|
|
30
31
|
fetchActiveAgent,
|
|
31
32
|
generateAgentKey,
|
|
32
33
|
isAgentValid,
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
import { createStaticClient, createTelegramClient } from "./grpc";
|
|
38
39
|
import { GrpcExchangeTransport } from "./GrpcExchangeTransport";
|
|
39
40
|
import { PrivateKeySigner } from "./privateKeySigner";
|
|
41
|
+
import { createTelegramAgentApprovalName } from "./agentWallet";
|
|
40
42
|
import type {
|
|
41
43
|
AuthMethod,
|
|
42
44
|
EoaSigner,
|
|
@@ -45,6 +47,7 @@ import type {
|
|
|
45
47
|
HypurrConnectConfig,
|
|
46
48
|
HypurrConnectState,
|
|
47
49
|
HypurrUser,
|
|
50
|
+
RenewAgentWalletParams,
|
|
48
51
|
SignTypedDataFn,
|
|
49
52
|
StoredAgent,
|
|
50
53
|
} from "./types";
|
|
@@ -60,6 +63,23 @@ const TELEGRAM_AUTH_STATE_KEY = "hypurr-connect-auth-state";
|
|
|
60
63
|
const TELEGRAM_AUTH_MESSAGE = "hypurr-connect:telegram-auth";
|
|
61
64
|
const DEFAULT_AUTH_HUB_URL = "https://auth.hypurr.fun/login";
|
|
62
65
|
const DEFAULT_MEDIA_URL = "https://media.hypurr.fun";
|
|
66
|
+
const USER_SIGNED_DOMAIN_NAME = "HyperliquidSignTransaction";
|
|
67
|
+
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" as const;
|
|
68
|
+
const APPROVE_AGENT_PRIMARY_TYPE = "HyperliquidTransaction:ApproveAgent";
|
|
69
|
+
const APPROVE_AGENT_TYPES = {
|
|
70
|
+
[APPROVE_AGENT_PRIMARY_TYPE]: [
|
|
71
|
+
{ name: "hyperliquidChain", type: "string" },
|
|
72
|
+
{ name: "agentAddress", type: "address" },
|
|
73
|
+
{ name: "agentName", type: "string" },
|
|
74
|
+
{ name: "nonce", type: "uint64" },
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
const EIP712_DOMAIN_TYPES = [
|
|
78
|
+
{ name: "name", type: "string" },
|
|
79
|
+
{ name: "version", type: "string" },
|
|
80
|
+
{ name: "chainId", type: "uint256" },
|
|
81
|
+
{ name: "verifyingContract", type: "address" },
|
|
82
|
+
];
|
|
63
83
|
const IGNORED_EXTERNAL_SIGNATURE =
|
|
64
84
|
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b" as const;
|
|
65
85
|
const DEFAULT_TELEGRAM_SCOPES = [
|
|
@@ -105,6 +125,67 @@ function isAddress(value?: string | null): value is Hex {
|
|
|
105
125
|
return !!value && /^0x[a-fA-F0-9]{40}$/.test(value);
|
|
106
126
|
}
|
|
107
127
|
|
|
128
|
+
function createApproveAgentAction(params: {
|
|
129
|
+
agentAddress: Hex;
|
|
130
|
+
agentName: string;
|
|
131
|
+
chainId: number;
|
|
132
|
+
isTestnet: boolean;
|
|
133
|
+
}) {
|
|
134
|
+
const nonce = Date.now();
|
|
135
|
+
return {
|
|
136
|
+
action: {
|
|
137
|
+
type: "approveAgent" as const,
|
|
138
|
+
signatureChainId: `0x${params.chainId.toString(16)}` as Hex,
|
|
139
|
+
hyperliquidChain: (params.isTestnet ? "Testnet" : "Mainnet") as
|
|
140
|
+
| "Testnet"
|
|
141
|
+
| "Mainnet",
|
|
142
|
+
agentAddress: params.agentAddress.toLowerCase() as Hex,
|
|
143
|
+
agentName: params.agentName,
|
|
144
|
+
nonce,
|
|
145
|
+
},
|
|
146
|
+
nonce,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
type ApproveAgentAction = ReturnType<typeof createApproveAgentAction>["action"];
|
|
151
|
+
|
|
152
|
+
async function signApproveAgentAction(params: {
|
|
153
|
+
signTypedDataAsync: SignTypedDataFn;
|
|
154
|
+
agentAddress: Hex;
|
|
155
|
+
agentName: string;
|
|
156
|
+
chainId: number;
|
|
157
|
+
isTestnet: boolean;
|
|
158
|
+
}): Promise<{
|
|
159
|
+
action: ApproveAgentAction;
|
|
160
|
+
signatureHex: Hex;
|
|
161
|
+
}> {
|
|
162
|
+
const { action } = createApproveAgentAction(params);
|
|
163
|
+
const signatureHex = await params.signTypedDataAsync({
|
|
164
|
+
domain: {
|
|
165
|
+
name: USER_SIGNED_DOMAIN_NAME,
|
|
166
|
+
version: "1",
|
|
167
|
+
chainId: params.chainId,
|
|
168
|
+
verifyingContract: ZERO_ADDRESS,
|
|
169
|
+
},
|
|
170
|
+
types: {
|
|
171
|
+
EIP712Domain: EIP712_DOMAIN_TYPES,
|
|
172
|
+
...APPROVE_AGENT_TYPES,
|
|
173
|
+
},
|
|
174
|
+
primaryType: APPROVE_AGENT_PRIMARY_TYPE,
|
|
175
|
+
message: {
|
|
176
|
+
hyperliquidChain: action.hyperliquidChain,
|
|
177
|
+
agentAddress: action.agentAddress,
|
|
178
|
+
agentName: action.agentName,
|
|
179
|
+
nonce: action.nonce,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
action,
|
|
185
|
+
signatureHex,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
108
189
|
function getRawSignedTransaction(result: unknown): Hex | null {
|
|
109
190
|
if (typeof result === "string" && result.startsWith("0x")) {
|
|
110
191
|
return result as Hex;
|
|
@@ -928,6 +1009,113 @@ export function HypurrConnectProvider({
|
|
|
928
1009
|
[tgClient, telegramRpcOptions, refreshWallets],
|
|
929
1010
|
);
|
|
930
1011
|
|
|
1012
|
+
const renewAgentWallet = useCallback(
|
|
1013
|
+
async ({
|
|
1014
|
+
walletId,
|
|
1015
|
+
ownerAddress,
|
|
1016
|
+
signTypedDataAsync,
|
|
1017
|
+
chainId,
|
|
1018
|
+
approvalDurationMs,
|
|
1019
|
+
agentName,
|
|
1020
|
+
}: RenewAgentWalletParams): Promise<void> => {
|
|
1021
|
+
if (authMethod !== "telegram") {
|
|
1022
|
+
throw new Error(
|
|
1023
|
+
"[HypurrConnect] Agent wallet renewal is only available for Telegram wallets.",
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
if (!isAddress(ownerAddress)) {
|
|
1027
|
+
throw new Error(
|
|
1028
|
+
"[HypurrConnect] Connect the owner EOA wallet before renewing this agent.",
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
if (!telegramRpcOptions) {
|
|
1032
|
+
throw new Error("[HypurrConnect] No Telegram RPC session available.");
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
const wallet = wallets.find((w) => w.id === walletId);
|
|
1036
|
+
if (!wallet) {
|
|
1037
|
+
throw new Error("[HypurrConnect] Agent wallet not found.");
|
|
1038
|
+
}
|
|
1039
|
+
if (!wallet.isAgent) {
|
|
1040
|
+
throw new Error(
|
|
1041
|
+
"[HypurrConnect] Selected wallet is not an agent wallet.",
|
|
1042
|
+
);
|
|
1043
|
+
}
|
|
1044
|
+
if (!isAddress(wallet.ethereumAddress)) {
|
|
1045
|
+
throw new Error(
|
|
1046
|
+
"[HypurrConnect] Agent wallet does not have a valid owner EVM address.",
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
if (ownerAddress.toLowerCase() !== wallet.ethereumAddress.toLowerCase()) {
|
|
1050
|
+
throw new Error(
|
|
1051
|
+
"[HypurrConnect] Connect the owner EOA for this agent wallet before renewing.",
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
const agentAddress = wallet.agentEthereumAddress?.value;
|
|
1056
|
+
if (!isAddress(agentAddress)) {
|
|
1057
|
+
throw new Error(
|
|
1058
|
+
"[HypurrConnect] Agent wallet does not have a valid agent EVM address.",
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
const isTestnet = config.isTestnet ?? false;
|
|
1063
|
+
const approvalAgentName =
|
|
1064
|
+
agentName ?? createTelegramAgentApprovalName(approvalDurationMs);
|
|
1065
|
+
setTgError(null);
|
|
1066
|
+
|
|
1067
|
+
try {
|
|
1068
|
+
const { action, signatureHex } = await signApproveAgentAction({
|
|
1069
|
+
signTypedDataAsync,
|
|
1070
|
+
agentAddress,
|
|
1071
|
+
agentName: approvalAgentName,
|
|
1072
|
+
chainId,
|
|
1073
|
+
isTestnet,
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
await tgClient.hyperliquidAgentWalletRenew(
|
|
1077
|
+
{
|
|
1078
|
+
authData: {},
|
|
1079
|
+
address: { value: wallet.ethereumAddress },
|
|
1080
|
+
signature: {
|
|
1081
|
+
agentAddress: action.agentAddress,
|
|
1082
|
+
agentName: action.agentName,
|
|
1083
|
+
nonce: action.nonce,
|
|
1084
|
+
chainId,
|
|
1085
|
+
signature: signatureHex,
|
|
1086
|
+
},
|
|
1087
|
+
},
|
|
1088
|
+
telegramRpcOptions,
|
|
1089
|
+
);
|
|
1090
|
+
|
|
1091
|
+
const remote = await fetchAgentByAddress(
|
|
1092
|
+
ownerAddress,
|
|
1093
|
+
agentAddress,
|
|
1094
|
+
isTestnet,
|
|
1095
|
+
);
|
|
1096
|
+
if (remote && remote.validUntil <= Date.now()) {
|
|
1097
|
+
throw new Error(
|
|
1098
|
+
"[HypurrConnect] Agent renewal was submitted, but the agent is still expired.",
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
refreshWallets();
|
|
1103
|
+
} catch (err) {
|
|
1104
|
+
console.error("[HypurrConnect] Agent wallet renewal failed:", err);
|
|
1105
|
+
setTgError(err instanceof Error ? err.message : String(err));
|
|
1106
|
+
throw err;
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1109
|
+
[
|
|
1110
|
+
authMethod,
|
|
1111
|
+
config.isTestnet,
|
|
1112
|
+
refreshWallets,
|
|
1113
|
+
telegramRpcOptions,
|
|
1114
|
+
tgClient,
|
|
1115
|
+
wallets,
|
|
1116
|
+
],
|
|
1117
|
+
);
|
|
1118
|
+
|
|
931
1119
|
const createWalletPack = useCallback(
|
|
932
1120
|
async (name: string): Promise<number> => {
|
|
933
1121
|
const { response } = await tgClient.telegramChatWalletPackCreate(
|
|
@@ -1352,6 +1540,7 @@ export function HypurrConnectProvider({
|
|
|
1352
1540
|
createWallet,
|
|
1353
1541
|
deleteWallet,
|
|
1354
1542
|
renameWallet,
|
|
1543
|
+
renewAgentWallet,
|
|
1355
1544
|
refreshWallets,
|
|
1356
1545
|
|
|
1357
1546
|
packs,
|
|
@@ -1401,6 +1590,7 @@ export function HypurrConnectProvider({
|
|
|
1401
1590
|
createWallet,
|
|
1402
1591
|
deleteWallet,
|
|
1403
1592
|
renameWallet,
|
|
1593
|
+
renewAgentWallet,
|
|
1404
1594
|
refreshWallets,
|
|
1405
1595
|
packs,
|
|
1406
1596
|
createWalletPack,
|
package/src/LoginModal.tsx
CHANGED
|
@@ -32,19 +32,19 @@ const btnStyle: CSSProperties = {
|
|
|
32
32
|
alignItems: "center",
|
|
33
33
|
gap: 12,
|
|
34
34
|
overflow: "hidden",
|
|
35
|
-
borderRadius:
|
|
36
|
-
background: "rgba(255,255,255,0.
|
|
37
|
-
padding: "
|
|
35
|
+
borderRadius: 4,
|
|
36
|
+
background: "rgba(255,255,255,0.1)",
|
|
37
|
+
padding: "4px 24px",
|
|
38
38
|
fontSize: 14,
|
|
39
|
-
fontWeight:
|
|
40
|
-
letterSpacing: "-0.
|
|
39
|
+
fontWeight: 500,
|
|
40
|
+
letterSpacing: "-0.03em",
|
|
41
41
|
color: "#fff",
|
|
42
42
|
cursor: "pointer",
|
|
43
43
|
border: "none",
|
|
44
44
|
transition: "background 150ms",
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
const btnHoverBg = { background: "rgba(255,255,255,0.
|
|
47
|
+
const btnHoverBg = { background: "rgba(255,255,255,0.15)" };
|
|
48
48
|
|
|
49
49
|
const backdropStyle: CSSProperties = {
|
|
50
50
|
position: "fixed",
|
|
@@ -78,9 +78,9 @@ const modalBoxStyle: CSSProperties = {
|
|
|
78
78
|
};
|
|
79
79
|
|
|
80
80
|
const headingStyle: CSSProperties = {
|
|
81
|
-
fontSize:
|
|
82
|
-
fontWeight:
|
|
83
|
-
letterSpacing: "-0.
|
|
81
|
+
fontSize: 20,
|
|
82
|
+
fontWeight: 500,
|
|
83
|
+
letterSpacing: "-0.03em",
|
|
84
84
|
color: "#fff",
|
|
85
85
|
margin: 0,
|
|
86
86
|
};
|
|
@@ -91,7 +91,7 @@ const dividerStyle: CSSProperties = {
|
|
|
91
91
|
background: "rgba(255,255,255,0.05)",
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
const iconSize: CSSProperties = { width:
|
|
94
|
+
const iconSize: CSSProperties = { width: 26, height: 26 };
|
|
95
95
|
|
|
96
96
|
const mobileQuery =
|
|
97
97
|
typeof window !== "undefined"
|
|
@@ -265,7 +265,7 @@ const grabHandleStyle: CSSProperties = {
|
|
|
265
265
|
margin: "0 auto",
|
|
266
266
|
height: 4,
|
|
267
267
|
width: 100,
|
|
268
|
-
borderRadius:
|
|
268
|
+
borderRadius: 4,
|
|
269
269
|
background: "rgba(255,255,255,0.05)",
|
|
270
270
|
};
|
|
271
271
|
|
|
@@ -125,6 +125,7 @@ export function RenameWalletModal({
|
|
|
125
125
|
const [saveHovered, setSaveHovered] = useState(false);
|
|
126
126
|
|
|
127
127
|
const currentName = wallet?.name || "Unnamed";
|
|
128
|
+
const displayAddress = wallet?.ethereumAddress;
|
|
128
129
|
const trimmedName = name.trim();
|
|
129
130
|
const isNameChanged = trimmedName !== currentName;
|
|
130
131
|
const isNameValid = WALLET_NAME_REGEX.test(trimmedName);
|
|
@@ -233,7 +234,7 @@ export function RenameWalletModal({
|
|
|
233
234
|
wordBreak: "break-all",
|
|
234
235
|
}}
|
|
235
236
|
>
|
|
236
|
-
{
|
|
237
|
+
{displayAddress}
|
|
237
238
|
</p>
|
|
238
239
|
</div>
|
|
239
240
|
|