ethagent 1.0.9 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -2
- package/src/chat/ChatScreen.tsx +5 -4
- package/src/chat/ContinuityEditReviewView.tsx +3 -3
- package/src/chat/commands.ts +5 -5
- package/src/cli/ResetConfirmView.tsx +12 -13
- package/src/cli/main.tsx +27 -30
- package/src/cli/reset.ts +7 -8
- package/src/cli/updateNotice.ts +52 -0
- package/src/identity/continuity/envelope.ts +11 -5
- package/src/identity/continuity/storage.ts +1 -1
- package/src/identity/hub/IdentityHub.tsx +6 -7
- package/src/identity/hub/identityHubModel.ts +12 -12
- package/src/identity/hub/screens/ContinuityDashboardScreen.tsx +39 -34
- package/src/identity/hub/screens/CreateFlow.tsx +4 -4
- package/src/identity/hub/screens/DetailsScreen.tsx +2 -2
- package/src/identity/hub/screens/EditProfileFlow.tsx +5 -5
- package/src/identity/hub/screens/ErrorScreen.tsx +2 -2
- package/src/identity/hub/screens/IdentitySummary.tsx +32 -12
- package/src/identity/hub/screens/MenuScreen.tsx +17 -17
- package/src/identity/hub/screens/NetworkScreen.tsx +7 -3
- package/src/identity/hub/screens/RecoveryConfirmScreen.tsx +9 -7
- package/src/identity/hub/screens/RestoreFlow.tsx +2 -2
- package/src/identity/hub/screens/StorageCredentialScreen.tsx +5 -5
- package/src/identity/wallet/wallet-page/wallet.html +1095 -966
- package/src/models/ModelPicker.tsx +71 -71
- package/src/models/llamacppPreflight.ts +1 -1
- package/src/models/modelPickerOptions.ts +22 -22
- package/src/storage/factoryReset.ts +17 -20
- package/src/tools/privateContinuityEditTool.ts +1 -1
- package/src/ui/BrandSplash.tsx +7 -4
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html>
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="utf-8">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
-
<title>wallet request</title>
|
|
8
|
-
<style>
|
|
9
|
-
*,
|
|
10
|
-
*::before,
|
|
11
|
-
*::after {
|
|
12
|
-
box-sizing: border-box;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
:root {
|
|
16
|
-
interpolate-size: allow-keywords;
|
|
17
|
-
--font-ui: Inter, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
|
|
18
|
-
--font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "DejaVu Sans Mono", "Liberation Mono", monospace;
|
|
19
|
-
--font-display: Inter, "SF Pro Display", "Segoe UI", system-ui, sans-serif;
|
|
20
|
-
--c-gray-900: #1f2330;
|
|
21
|
-
--c-gray-800: #2f364a;
|
|
22
|
-
--c-gray-700: #49526a;
|
|
23
|
-
--c-gray-500: #6f7890;
|
|
24
|
-
--c-gray-400: #949bb0;
|
|
25
|
-
--c-blue-400: #5f8fff;
|
|
26
|
-
--c-blue-500: #3f76ff;
|
|
27
|
-
--c-blue-700: #2954c6;
|
|
28
|
-
--c-danger: #e5484d;
|
|
29
|
-
--c-success: #1aa86b;
|
|
30
|
-
--ease-standard: cubic-bezier(0.2, 0.0, 0, 1);
|
|
31
|
-
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
32
|
-
--fg-1: #1f2330;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
html,
|
|
36
|
-
body {
|
|
37
|
-
height: 100%;
|
|
38
|
-
margin: 0;
|
|
39
|
-
overflow: hidden;
|
|
40
|
-
}
|
|
41
|
-
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
<title>wallet request</title>
|
|
8
|
+
<style>
|
|
9
|
+
*,
|
|
10
|
+
*::before,
|
|
11
|
+
*::after {
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
:root {
|
|
16
|
+
interpolate-size: allow-keywords;
|
|
17
|
+
--font-ui: Inter, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
|
|
18
|
+
--font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "DejaVu Sans Mono", "Liberation Mono", monospace;
|
|
19
|
+
--font-display: Inter, "SF Pro Display", "Segoe UI", system-ui, sans-serif;
|
|
20
|
+
--c-gray-900: #1f2330;
|
|
21
|
+
--c-gray-800: #2f364a;
|
|
22
|
+
--c-gray-700: #49526a;
|
|
23
|
+
--c-gray-500: #6f7890;
|
|
24
|
+
--c-gray-400: #949bb0;
|
|
25
|
+
--c-blue-400: #5f8fff;
|
|
26
|
+
--c-blue-500: #3f76ff;
|
|
27
|
+
--c-blue-700: #2954c6;
|
|
28
|
+
--c-danger: #e5484d;
|
|
29
|
+
--c-success: #1aa86b;
|
|
30
|
+
--ease-standard: cubic-bezier(0.2, 0.0, 0, 1);
|
|
31
|
+
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
32
|
+
--fg-1: #1f2330;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
html,
|
|
36
|
+
body {
|
|
37
|
+
height: 100%;
|
|
38
|
+
margin: 0;
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
42
|
body {
|
|
43
43
|
position: relative;
|
|
44
44
|
font-family: var(--font-ui);
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
background: #fbfaf6;
|
|
47
47
|
display: grid;
|
|
48
48
|
place-items: center;
|
|
49
|
-
padding:
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
body::before {
|
|
53
|
-
content: "";
|
|
54
|
-
position: fixed;
|
|
49
|
+
padding: clamp(18px, 3vw, 28px);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
body::before {
|
|
53
|
+
content: "";
|
|
54
|
+
position: fixed;
|
|
55
55
|
inset: 0;
|
|
56
56
|
z-index: 0;
|
|
57
57
|
background:
|
|
@@ -62,11 +62,11 @@
|
|
|
62
62
|
radial-gradient(60% 55% at 85% 85%, rgba(212, 230, 245, 0.85), transparent 65%),
|
|
63
63
|
linear-gradient(180deg, #fef3ee 0%, #fef7e8 40%, #f1f9ee 75%, #ecf3fb 100%);
|
|
64
64
|
filter: saturate(1.05);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
body::after {
|
|
68
|
-
content: "";
|
|
69
|
-
position: fixed;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
body::after {
|
|
68
|
+
content: "";
|
|
69
|
+
position: fixed;
|
|
70
70
|
inset: 0;
|
|
71
71
|
z-index: 0;
|
|
72
72
|
pointer-events: none;
|
|
@@ -74,1009 +74,1138 @@
|
|
|
74
74
|
background-size: 3px 3px;
|
|
75
75
|
mix-blend-mode: multiply;
|
|
76
76
|
opacity: 0.6;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
main {
|
|
80
|
-
position: relative;
|
|
81
|
-
z-index: 1;
|
|
82
|
-
width: min(
|
|
83
|
-
max-height: calc(
|
|
84
|
-
display: flex;
|
|
85
|
-
flex-direction: column;
|
|
86
|
-
background: rgba(255, 255, 255, 0.95);
|
|
87
|
-
backdrop-filter: blur(40px) saturate(1.4);
|
|
88
|
-
-webkit-backdrop-filter: blur(40px) saturate(1.4);
|
|
89
|
-
border: 1px solid rgba(255, 255, 255, 0.7);
|
|
90
|
-
border-radius:
|
|
91
|
-
box-shadow:
|
|
92
|
-
0 1px 0 rgba(255, 255, 255, 0.9) inset,
|
|
93
|
-
0 -1px 0 rgba(255, 255, 255, 0.4) inset,
|
|
94
|
-
0 30px 60px -20px rgba(31, 35, 48, 0.25),
|
|
95
|
-
0 12px 24px -8px rgba(31, 35, 48, 0.12);
|
|
96
|
-
overflow: hidden;
|
|
97
|
-
height: fit-content;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
main::before {
|
|
101
|
-
content: "";
|
|
102
|
-
position: absolute;
|
|
103
|
-
top: 0;
|
|
104
|
-
left: 12%;
|
|
105
|
-
right: 12%;
|
|
106
|
-
height: 1px;
|
|
107
|
-
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.95), transparent);
|
|
108
|
-
pointer-events: none;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.chrome {
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
main {
|
|
80
|
+
position: relative;
|
|
81
|
+
z-index: 1;
|
|
82
|
+
width: min(700px, 100%);
|
|
83
|
+
max-height: calc(100dvh - 36px);
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
background: rgba(255, 255, 255, 0.95);
|
|
87
|
+
backdrop-filter: blur(40px) saturate(1.4);
|
|
88
|
+
-webkit-backdrop-filter: blur(40px) saturate(1.4);
|
|
89
|
+
border: 1px solid rgba(255, 255, 255, 0.7);
|
|
90
|
+
border-radius: 26px;
|
|
91
|
+
box-shadow:
|
|
92
|
+
0 1px 0 rgba(255, 255, 255, 0.9) inset,
|
|
93
|
+
0 -1px 0 rgba(255, 255, 255, 0.4) inset,
|
|
94
|
+
0 30px 60px -20px rgba(31, 35, 48, 0.25),
|
|
95
|
+
0 12px 24px -8px rgba(31, 35, 48, 0.12);
|
|
96
|
+
overflow: hidden;
|
|
97
|
+
height: fit-content;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
main::before {
|
|
101
|
+
content: "";
|
|
102
|
+
position: absolute;
|
|
103
|
+
top: 0;
|
|
104
|
+
left: 12%;
|
|
105
|
+
right: 12%;
|
|
106
|
+
height: 1px;
|
|
107
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.95), transparent);
|
|
108
|
+
pointer-events: none;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.chrome {
|
|
112
112
|
display: flex;
|
|
113
113
|
align-items: center;
|
|
114
114
|
gap: 8px;
|
|
115
|
-
padding: 14px
|
|
116
|
-
border-bottom: 1px solid rgba(255, 255, 255, 0.5);
|
|
117
|
-
background: linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2));
|
|
118
|
-
flex: none;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.light {
|
|
122
|
-
width:
|
|
123
|
-
height:
|
|
124
|
-
border-radius: 999px;
|
|
125
|
-
box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.08), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.light.r {
|
|
129
|
-
background: #ff5f57;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.light.y {
|
|
133
|
-
background: #febc2e;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.light.g {
|
|
137
|
-
background: #28c840;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.chrome-title {
|
|
115
|
+
padding: 14px 20px;
|
|
116
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.5);
|
|
117
|
+
background: linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2));
|
|
118
|
+
flex: none;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.light {
|
|
122
|
+
width: 10px;
|
|
123
|
+
height: 10px;
|
|
124
|
+
border-radius: 999px;
|
|
125
|
+
box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.08), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.light.r {
|
|
129
|
+
background: #ff5f57;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.light.y {
|
|
133
|
+
background: #febc2e;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.light.g {
|
|
137
|
+
background: #28c840;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.chrome-title {
|
|
141
141
|
flex: 1;
|
|
142
142
|
text-align: center;
|
|
143
|
-
font-size:
|
|
144
|
-
color: rgba(31, 35, 48, 0.55);
|
|
145
|
-
font-weight: 500;
|
|
146
|
-
letter-spacing: 0.01em;
|
|
147
|
-
margin-right: 56px;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.body {
|
|
143
|
+
font-size: 11.5px;
|
|
144
|
+
color: rgba(31, 35, 48, 0.55);
|
|
145
|
+
font-weight: 500;
|
|
146
|
+
letter-spacing: 0.01em;
|
|
147
|
+
margin-right: 56px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.body {
|
|
151
151
|
flex: 1;
|
|
152
152
|
min-height: 0;
|
|
153
|
-
padding:
|
|
153
|
+
padding: clamp(20px, 3vw, 28px) clamp(22px, 4vw, 32px) clamp(22px, 3vw, 30px);
|
|
154
154
|
display: flex;
|
|
155
155
|
flex-direction: column;
|
|
156
|
-
gap:
|
|
157
|
-
overflow: hidden;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.splash-wrap {
|
|
156
|
+
gap: 15px;
|
|
157
|
+
overflow: hidden;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.splash-wrap {
|
|
161
161
|
flex: none;
|
|
162
162
|
display: flex;
|
|
163
163
|
justify-content: center;
|
|
164
164
|
margin: 6px 0 2px;
|
|
165
165
|
padding: 4px 0;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.splash {
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.splash {
|
|
169
169
|
font-family: var(--font-mono);
|
|
170
|
-
font-size: 11px;
|
|
171
|
-
font-weight: 800;
|
|
172
|
-
line-height: 1.05;
|
|
173
|
-
letter-spacing: 0;
|
|
174
|
-
white-space: pre;
|
|
175
|
-
margin: 0;
|
|
176
|
-
color: var(--c-gray-700);
|
|
177
|
-
text-align: center;
|
|
178
|
-
transform: scaleX(0.75);
|
|
179
|
-
transform-origin: 50% 50%;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.spinner {
|
|
183
|
-
display: inline-block;
|
|
184
|
-
width: 14px;
|
|
185
|
-
height: 14px;
|
|
186
|
-
border-radius: 999px;
|
|
187
|
-
border: 1.6px solid color-mix(in srgb, var(--accent) 30%, transparent);
|
|
188
|
-
border-top-color: var(--accent);
|
|
189
|
-
animation: spin 0.9s linear infinite;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
@keyframes spin {
|
|
193
|
-
to {
|
|
194
|
-
transform: rotate(360deg);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
[data-flow] {
|
|
199
|
-
--accent: #6366f1;
|
|
200
|
-
--accent-soft: rgba(99, 102, 241, 0.12);
|
|
201
|
-
--glow: rgba(99, 102, 241, 0.35);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
main,
|
|
205
|
-
.head .label,
|
|
170
|
+
font-size: clamp(9.5px, 1.35vw, 11px);
|
|
171
|
+
font-weight: 800;
|
|
172
|
+
line-height: 1.05;
|
|
173
|
+
letter-spacing: 0;
|
|
174
|
+
white-space: pre;
|
|
175
|
+
margin: 0;
|
|
176
|
+
color: var(--c-gray-700);
|
|
177
|
+
text-align: center;
|
|
178
|
+
transform: scaleX(0.75);
|
|
179
|
+
transform-origin: 50% 50%;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.spinner {
|
|
183
|
+
display: inline-block;
|
|
184
|
+
width: 14px;
|
|
185
|
+
height: 14px;
|
|
186
|
+
border-radius: 999px;
|
|
187
|
+
border: 1.6px solid color-mix(in srgb, var(--accent) 30%, transparent);
|
|
188
|
+
border-top-color: var(--accent);
|
|
189
|
+
animation: spin 0.9s linear infinite;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@keyframes spin {
|
|
193
|
+
to {
|
|
194
|
+
transform: rotate(360deg);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
[data-flow] {
|
|
199
|
+
--accent: #6366f1;
|
|
200
|
+
--accent-soft: rgba(99, 102, 241, 0.12);
|
|
201
|
+
--glow: rgba(99, 102, 241, 0.35);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
main,
|
|
205
|
+
.head .label,
|
|
206
206
|
.status,
|
|
207
207
|
.status-line,
|
|
208
208
|
.status-hint,
|
|
209
209
|
.flow-detail,
|
|
210
|
-
.tx-summary,
|
|
211
210
|
#error-block-slot,
|
|
212
211
|
.net-pill {
|
|
213
212
|
transition: height 480ms var(--ease-standard), background-color 320ms var(--ease-standard), border-color 320ms var(--ease-standard), color 320ms var(--ease-standard), box-shadow 320ms var(--ease-standard);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
.status-line,
|
|
217
|
-
.status-hint {
|
|
218
|
-
transition: opacity 280ms var(--ease-standard), transform 280ms var(--ease-standard), color 320ms var(--ease-standard);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
.status-line.is-changing,
|
|
222
|
-
.status-hint.is-changing {
|
|
223
|
-
opacity: 0;
|
|
224
|
-
transform: translateY(-3px);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
.head {
|
|
228
|
-
display: flex;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.status-line,
|
|
216
|
+
.status-hint {
|
|
217
|
+
transition: opacity 280ms var(--ease-standard), transform 280ms var(--ease-standard), color 320ms var(--ease-standard);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.status-line.is-changing,
|
|
221
|
+
.status-hint.is-changing {
|
|
222
|
+
opacity: 0;
|
|
223
|
+
transform: translateY(-3px);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.head {
|
|
227
|
+
display: flex;
|
|
229
228
|
align-items: center;
|
|
230
229
|
justify-content: space-between;
|
|
231
230
|
gap: 12px;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.head .label {
|
|
235
|
-
font-family: var(--font-ui);
|
|
236
|
-
color: var(--c-gray-800);
|
|
237
|
-
font-size:
|
|
238
|
-
font-weight: 500;
|
|
239
|
-
letter-spacing: 0;
|
|
240
|
-
text-transform: capitalize;
|
|
241
|
-
display: inline-flex;
|
|
242
|
-
align-items: center;
|
|
243
|
-
gap:
|
|
244
|
-
padding: 5px
|
|
245
|
-
background: rgba(255, 255, 255, 0.6);
|
|
246
|
-
border-radius: 999px;
|
|
247
|
-
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
248
|
-
box-shadow: 0 1px 2px rgba(31, 35, 48, 0.05), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.head .label::before {
|
|
252
|
-
content: "";
|
|
253
|
-
width: 6px;
|
|
254
|
-
height: 6px;
|
|
255
|
-
border-radius: 999px;
|
|
256
|
-
background: var(--accent);
|
|
257
|
-
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.flow-title {
|
|
261
|
-
font-family: var(--font-display);
|
|
262
|
-
font-size: 18px;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.head .label {
|
|
234
|
+
font-family: var(--font-ui);
|
|
235
|
+
color: var(--c-gray-800);
|
|
236
|
+
font-size: 11.5px;
|
|
237
|
+
font-weight: 500;
|
|
238
|
+
letter-spacing: 0;
|
|
239
|
+
text-transform: capitalize;
|
|
240
|
+
display: inline-flex;
|
|
241
|
+
align-items: center;
|
|
242
|
+
gap: 6px;
|
|
243
|
+
padding: 5px 13px 5px 10px;
|
|
244
|
+
background: rgba(255, 255, 255, 0.6);
|
|
245
|
+
border-radius: 999px;
|
|
246
|
+
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
247
|
+
box-shadow: 0 1px 2px rgba(31, 35, 48, 0.05), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.head .label::before {
|
|
251
|
+
content: "";
|
|
252
|
+
width: 6px;
|
|
253
|
+
height: 6px;
|
|
254
|
+
border-radius: 999px;
|
|
255
|
+
background: var(--accent);
|
|
256
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.flow-title {
|
|
260
|
+
font-family: var(--font-display);
|
|
261
|
+
font-size: clamp(18px, 2.6vw, 20px);
|
|
263
262
|
font-weight: 600;
|
|
264
|
-
line-height: 1.
|
|
265
|
-
letter-spacing: 0;
|
|
266
|
-
margin: 0;
|
|
267
|
-
color: var(--c-gray-900);
|
|
268
|
-
text-wrap: balance;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
.details {
|
|
263
|
+
line-height: 1.22;
|
|
264
|
+
letter-spacing: 0;
|
|
265
|
+
margin: 0;
|
|
266
|
+
color: var(--c-gray-900);
|
|
267
|
+
text-wrap: balance;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.details {
|
|
272
271
|
display: flex;
|
|
273
272
|
flex-direction: column;
|
|
274
|
-
gap:
|
|
275
|
-
padding:
|
|
276
|
-
background: rgba(255, 255, 255, 0.45);
|
|
277
|
-
backdrop-filter: blur(16px);
|
|
278
|
-
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
273
|
+
gap: 9px;
|
|
274
|
+
padding: 14px 16px;
|
|
275
|
+
background: rgba(255, 255, 255, 0.45);
|
|
276
|
+
backdrop-filter: blur(16px);
|
|
277
|
+
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
279
278
|
border-radius: 14px;
|
|
280
|
-
box-shadow: 0 4px 16px -4px rgba(31, 35, 48, 0.08), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
281
|
-
max-height:
|
|
282
|
-
opacity: 1;
|
|
283
|
-
margin-top: 0;
|
|
284
|
-
overflow: hidden;
|
|
285
|
-
transition: max-height 480ms var(--ease-standard), padding 480ms var(--ease-standard), margin 480ms var(--ease-standard), opacity 480ms var(--ease-standard), border-color 480ms var(--ease-standard), box-shadow 480ms var(--ease-standard);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.details[hidden] {
|
|
289
|
-
display: flex;
|
|
290
|
-
max-height: 0;
|
|
291
|
-
opacity: 0;
|
|
292
|
-
padding-top: 0;
|
|
293
|
-
padding-bottom: 0;
|
|
294
|
-
margin-top: -14px;
|
|
295
|
-
border-color: transparent;
|
|
296
|
-
box-shadow: none;
|
|
297
|
-
pointer-events: none;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
.flow-detail {
|
|
301
|
-
display: grid;
|
|
302
|
-
grid-template-columns:
|
|
279
|
+
box-shadow: 0 4px 16px -4px rgba(31, 35, 48, 0.08), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
280
|
+
max-height: 210px;
|
|
281
|
+
opacity: 1;
|
|
282
|
+
margin-top: 0;
|
|
283
|
+
overflow: hidden;
|
|
284
|
+
transition: max-height 480ms var(--ease-standard), padding 480ms var(--ease-standard), margin 480ms var(--ease-standard), opacity 480ms var(--ease-standard), border-color 480ms var(--ease-standard), box-shadow 480ms var(--ease-standard);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.details[hidden] {
|
|
288
|
+
display: flex;
|
|
289
|
+
max-height: 0;
|
|
290
|
+
opacity: 0;
|
|
291
|
+
padding-top: 0;
|
|
292
|
+
padding-bottom: 0;
|
|
293
|
+
margin-top: -14px;
|
|
294
|
+
border-color: transparent;
|
|
295
|
+
box-shadow: none;
|
|
296
|
+
pointer-events: none;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.flow-detail {
|
|
300
|
+
display: grid;
|
|
301
|
+
grid-template-columns: 96px 1fr;
|
|
303
302
|
align-items: center;
|
|
304
303
|
gap: 12px;
|
|
305
|
-
font-size:
|
|
306
|
-
color: var(--c-gray-700);
|
|
307
|
-
margin: 0;
|
|
308
|
-
line-height: 1.
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
.flow-detail[hidden] {
|
|
312
|
-
display: none;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
.flow-detail .key {
|
|
316
|
-
font-family: var(--font-mono);
|
|
317
|
-
font-size:
|
|
318
|
-
font-weight: 500;
|
|
319
|
-
color: var(--c-gray-500);
|
|
320
|
-
text-transform: lowercase;
|
|
321
|
-
letter-spacing: 0.05em;
|
|
304
|
+
font-size: 13.5px;
|
|
305
|
+
color: var(--c-gray-700);
|
|
306
|
+
margin: 0;
|
|
307
|
+
line-height: 1.35;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.flow-detail[hidden] {
|
|
311
|
+
display: none;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.flow-detail .key {
|
|
315
|
+
font-family: var(--font-mono);
|
|
316
|
+
font-size: 10px;
|
|
317
|
+
font-weight: 500;
|
|
318
|
+
color: var(--c-gray-500);
|
|
319
|
+
text-transform: lowercase;
|
|
320
|
+
letter-spacing: 0.05em;
|
|
322
321
|
padding: 3px 8px;
|
|
323
|
-
background: rgba(15, 17, 23, 0.04);
|
|
324
|
-
border: 1px solid rgba(15, 17, 23, 0.06);
|
|
325
|
-
border-radius: 6px;
|
|
326
|
-
justify-self: start;
|
|
327
|
-
min-width: 0;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
.flow-detail span:last-child {
|
|
331
|
-
overflow: hidden;
|
|
332
|
-
text-overflow: ellipsis;
|
|
333
|
-
white-space: nowrap;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.status {
|
|
322
|
+
background: rgba(15, 17, 23, 0.04);
|
|
323
|
+
border: 1px solid rgba(15, 17, 23, 0.06);
|
|
324
|
+
border-radius: 6px;
|
|
325
|
+
justify-self: start;
|
|
326
|
+
min-width: 0;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.flow-detail span:last-child {
|
|
330
|
+
overflow: hidden;
|
|
331
|
+
text-overflow: ellipsis;
|
|
332
|
+
white-space: nowrap;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.status {
|
|
337
336
|
display: flex;
|
|
338
337
|
flex-direction: column;
|
|
339
|
-
gap:
|
|
340
|
-
padding:
|
|
341
|
-
background: rgba(255, 255, 255, 0.45);
|
|
342
|
-
backdrop-filter: blur(16px);
|
|
343
|
-
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
338
|
+
gap: 7px;
|
|
339
|
+
padding: 15px 17px;
|
|
340
|
+
background: rgba(255, 255, 255, 0.45);
|
|
341
|
+
backdrop-filter: blur(16px);
|
|
342
|
+
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
344
343
|
border-radius: 14px;
|
|
345
|
-
box-shadow: 0 8px 24px -6px rgba(31, 35, 48, 0.08), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
.status-line {
|
|
344
|
+
box-shadow: 0 8px 24px -6px rgba(31, 35, 48, 0.08), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.status-line {
|
|
349
348
|
display: flex;
|
|
350
349
|
align-items: center;
|
|
351
350
|
gap: 12px;
|
|
351
|
+
font-size: 13.5px;
|
|
352
|
+
font-weight: 500;
|
|
353
|
+
color: var(--c-gray-900);
|
|
354
|
+
margin: 0;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.status-line .marker {
|
|
358
|
+
font-family: var(--font-mono);
|
|
352
359
|
font-size: 13px;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
flex: none;
|
|
370
|
-
font-variant-numeric: tabular-nums;
|
|
371
|
-
font-weight: 600;
|
|
372
|
-
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 15%, transparent) inset;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
.status-hint {
|
|
376
|
-
font-size: 12px;
|
|
360
|
+
width: 29px;
|
|
361
|
+
height: 29px;
|
|
362
|
+
display: inline-flex;
|
|
363
|
+
align-items: center;
|
|
364
|
+
justify-content: center;
|
|
365
|
+
border-radius: 999px;
|
|
366
|
+
background: var(--accent-soft);
|
|
367
|
+
color: var(--accent);
|
|
368
|
+
flex: none;
|
|
369
|
+
font-variant-numeric: tabular-nums;
|
|
370
|
+
font-weight: 600;
|
|
371
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 15%, transparent) inset;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.status-hint {
|
|
375
|
+
font-size: 12.5px;
|
|
377
376
|
color: var(--c-gray-500);
|
|
378
|
-
margin: 0 0 0
|
|
379
|
-
line-height: 1.
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
display:
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
377
|
+
margin: 0 0 0 41px;
|
|
378
|
+
line-height: 1.4;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
#error-block-slot:empty {
|
|
382
|
+
display: block;
|
|
383
|
+
max-height: 0;
|
|
384
|
+
opacity: 0;
|
|
385
|
+
padding-top: 0;
|
|
386
|
+
padding-bottom: 0;
|
|
387
|
+
margin-top: -14px;
|
|
388
|
+
border-color: transparent;
|
|
389
|
+
box-shadow: none;
|
|
390
|
+
pointer-events: none;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
#error-block-slot {
|
|
394
|
+
padding: 12px 14px;
|
|
395
|
+
background: rgba(255, 255, 255, 0.45);
|
|
396
|
+
backdrop-filter: blur(16px);
|
|
397
|
+
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
392
398
|
border-radius: 14px;
|
|
393
|
-
box-shadow: 0
|
|
394
|
-
max-height:
|
|
395
|
-
opacity: 1;
|
|
396
|
-
margin-top: 0;
|
|
397
|
-
overflow: hidden;
|
|
398
|
-
transition: max-height 480ms var(--ease-standard), padding 480ms var(--ease-standard), margin 480ms var(--ease-standard), opacity 480ms var(--ease-standard),
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
.
|
|
402
|
-
|
|
403
|
-
max-height: 0;
|
|
404
|
-
opacity: 0;
|
|
405
|
-
padding-top: 0;
|
|
406
|
-
padding-bottom: 0;
|
|
407
|
-
margin-top: -14px;
|
|
408
|
-
border-color: transparent;
|
|
409
|
-
background-color: transparent;
|
|
410
|
-
pointer-events: none;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
.tx-key {
|
|
414
|
-
font-family: var(--font-mono);
|
|
415
|
-
font-size: 11px;
|
|
416
|
-
color: var(--c-gray-500);
|
|
417
|
-
text-transform: lowercase;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
.tx-value {
|
|
399
|
+
box-shadow: 0 8px 24px -6px rgba(31, 35, 48, 0.08), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
400
|
+
max-height: 400px;
|
|
401
|
+
opacity: 1;
|
|
402
|
+
margin-top: 0;
|
|
403
|
+
overflow: hidden;
|
|
404
|
+
transition: max-height 480ms var(--ease-standard), padding 480ms var(--ease-standard), margin 480ms var(--ease-standard), opacity 480ms var(--ease-standard), border-color 320ms var(--ease-standard), box-shadow 320ms var(--ease-standard);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.error-title {
|
|
408
|
+
color: var(--c-gray-900);
|
|
421
409
|
font-size: 12px;
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
text-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
.
|
|
429
|
-
color: var(--c-gray-
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
#error-block-slot:empty {
|
|
433
|
-
display: block;
|
|
434
|
-
max-height: 0;
|
|
435
|
-
opacity: 0;
|
|
436
|
-
padding-top: 0;
|
|
437
|
-
padding-bottom: 0;
|
|
438
|
-
margin-top: -14px;
|
|
439
|
-
border-color: transparent;
|
|
440
|
-
box-shadow: none;
|
|
441
|
-
pointer-events: none;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
#error-block-slot {
|
|
445
|
-
padding: 16px 20px;
|
|
446
|
-
background: rgba(255, 255, 255, 0.45);
|
|
447
|
-
backdrop-filter: blur(16px);
|
|
448
|
-
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
449
|
-
border-radius: 16px;
|
|
450
|
-
box-shadow: 0 8px 24px -6px rgba(31, 35, 48, 0.08), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
|
|
451
|
-
max-height: 400px;
|
|
452
|
-
opacity: 1;
|
|
453
|
-
margin-top: 0;
|
|
454
|
-
overflow: hidden;
|
|
455
|
-
transition: max-height 480ms var(--ease-standard), padding 480ms var(--ease-standard), margin 480ms var(--ease-standard), opacity 480ms var(--ease-standard), border-color 320ms var(--ease-standard), box-shadow 320ms var(--ease-standard);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
.error-title {
|
|
459
|
-
color: var(--c-gray-900);
|
|
410
|
+
font-weight: 600;
|
|
411
|
+
letter-spacing: 0;
|
|
412
|
+
text-transform: capitalize;
|
|
413
|
+
margin: 0 0 4px;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.error-msg {
|
|
417
|
+
color: var(--c-gray-900);
|
|
460
418
|
font-size: 13px;
|
|
461
|
-
font-weight: 600;
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
.error-hint a {
|
|
483
|
-
color: var(--accent);
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
.
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
background: rgba(
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
.footer {
|
|
506
|
-
flex: none;
|
|
507
|
-
padding: 14px 22px 16px;
|
|
508
|
-
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
|
509
|
-
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.5));
|
|
510
|
-
display: flex;
|
|
511
|
-
align-items: center;
|
|
512
|
-
justify-content: space-between;
|
|
419
|
+
font-weight: 600;
|
|
420
|
+
margin: 0 0 6px;
|
|
421
|
+
line-height: 1.45;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.error-hint {
|
|
425
|
+
color: var(--c-gray-500);
|
|
426
|
+
font-size: 11.5px;
|
|
427
|
+
margin: 0;
|
|
428
|
+
line-height: 1.5;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.error-hint a {
|
|
432
|
+
color: var(--accent);
|
|
433
|
+
text-decoration: none;
|
|
434
|
+
font-weight: 600;
|
|
435
|
+
border-bottom: 1px dashed color-mix(in srgb, var(--accent) 50%, transparent);
|
|
436
|
+
padding-bottom: 1px;
|
|
437
|
+
transition: all 0.2s ease;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.error-hint a:hover {
|
|
441
|
+
color: var(--accent);
|
|
442
|
+
border-bottom-style: solid;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.error-hint code {
|
|
446
|
+
font-family: var(--font-mono);
|
|
447
|
+
font-size: 11px;
|
|
448
|
+
padding: 2px 6px;
|
|
449
|
+
background: rgba(15, 17, 23, 0.06);
|
|
450
|
+
border-radius: 4px;
|
|
451
|
+
color: var(--c-gray-700);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.footer {
|
|
455
|
+
flex: none;
|
|
456
|
+
padding: 15px 22px 17px;
|
|
457
|
+
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
|
458
|
+
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.5));
|
|
459
|
+
display: flex;
|
|
460
|
+
align-items: center;
|
|
461
|
+
justify-content: space-between;
|
|
513
462
|
gap: 12px;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
.net-pill {
|
|
517
|
-
display: inline-flex;
|
|
518
|
-
align-items: center;
|
|
519
|
-
gap: 6px;
|
|
520
|
-
font-family: var(--font-mono);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.net-pill {
|
|
466
|
+
display: inline-flex;
|
|
467
|
+
align-items: center;
|
|
468
|
+
gap: 6px;
|
|
469
|
+
font-family: var(--font-mono);
|
|
521
470
|
font-size: 11px;
|
|
522
|
-
color: var(--c-gray-500);
|
|
471
|
+
color: var(--c-gray-500);
|
|
523
472
|
padding: 5px 10px;
|
|
524
|
-
background: rgba(255, 255, 255, 0.6);
|
|
525
|
-
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
526
|
-
border-radius: 999px;
|
|
527
|
-
box-shadow: 0 1px 2px rgba(31, 35, 48, 0.04);
|
|
473
|
+
background: rgba(255, 255, 255, 0.6);
|
|
474
|
+
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
475
|
+
border-radius: 999px;
|
|
476
|
+
box-shadow: 0 1px 2px rgba(31, 35, 48, 0.04);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.net-pill .dot {
|
|
480
|
+
width: 6px;
|
|
481
|
+
height: 6px;
|
|
482
|
+
border-radius: 999px;
|
|
483
|
+
background: var(--c-success);
|
|
484
|
+
box-shadow: 0 0 0 2px rgba(26, 168, 107, 0.18);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.net-pill[hidden] {
|
|
488
|
+
display: none;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.actions {
|
|
492
|
+
display: inline-flex;
|
|
493
|
+
align-items: center;
|
|
494
|
+
gap: 10px;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.shortcut {
|
|
498
|
+
font: inherit;
|
|
499
|
+
font-family: var(--font-ui);
|
|
500
|
+
|
|
501
|
+
font-weight: 500;
|
|
502
|
+
background: rgba(255, 255, 255, 0.7);
|
|
503
|
+
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
504
|
+
padding: 8px 14px;
|
|
505
|
+
cursor: pointer;
|
|
506
|
+
color: var(--c-gray-700);
|
|
507
|
+
display: inline-flex;
|
|
508
|
+
align-items: center;
|
|
509
|
+
gap: 6px;
|
|
510
|
+
border-radius: 999px;
|
|
511
|
+
transition: all 0.15s var(--ease-standard);
|
|
512
|
+
box-shadow: 0 1px 2px rgba(31, 35, 48, 0.03), 0 1px 0 rgba(255, 255, 255, 0.5) inset;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.shortcut:focus {
|
|
516
|
+
outline: none;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.shortcut:focus-visible {
|
|
520
|
+
outline: 2px solid var(--c-blue-400);
|
|
521
|
+
outline-offset: 2px;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.shortcut:hover:not(:disabled) {
|
|
525
|
+
background: rgba(255, 255, 255, 0.95);
|
|
526
|
+
color: var(--c-gray-900);
|
|
527
|
+
transform: translateY(-0.5px);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.shortcut:active:not(:disabled) {
|
|
531
|
+
transform: translateY(0);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.shortcut:disabled {
|
|
535
|
+
opacity: 0.4;
|
|
536
|
+
cursor: not-allowed;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.shortcut[hidden] {
|
|
540
|
+
display: none;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.shortcut.primary {
|
|
544
|
+
background: var(--c-gray-900);
|
|
545
|
+
border-color: var(--c-gray-900);
|
|
546
|
+
color: #fff;
|
|
547
|
+
box-shadow: 0 2px 8px -2px rgba(15, 17, 23, 0.2), 0 1px 0 rgba(255, 255, 255, 0.1) inset;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.shortcut.primary:hover:not(:disabled) {
|
|
551
|
+
background: #1a1d27;
|
|
552
|
+
color: #fff;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.shortcut.primary .key {
|
|
556
|
+
background: rgba(255, 255, 255, 0.14);
|
|
557
|
+
border-color: rgba(255, 255, 255, 0.18);
|
|
558
|
+
color: rgba(255, 255, 255, 0.9);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.key {
|
|
562
|
+
display: inline-flex;
|
|
563
|
+
align-items: center;
|
|
564
|
+
justify-content: center;
|
|
565
|
+
gap: 4px;
|
|
566
|
+
padding: 2px 6px;
|
|
567
|
+
font-family: var(--font-mono);
|
|
568
|
+
font-size: 10.5px;
|
|
569
|
+
font-weight: 500;
|
|
570
|
+
color: var(--c-gray-500);
|
|
571
|
+
background: rgba(15, 17, 23, 0.04);
|
|
572
|
+
border: 1px solid rgba(15, 17, 23, 0.07);
|
|
573
|
+
border-radius: 5px;
|
|
574
|
+
letter-spacing: 0.02em;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.shortcut .pix {
|
|
578
|
+
color: currentColor;
|
|
579
|
+
opacity: 0.85;
|
|
580
|
+
display: inline-flex;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.head .net {
|
|
584
|
+
display: none;
|
|
528
585
|
}
|
|
529
586
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
background: var(--c-success);
|
|
535
|
-
box-shadow: 0 0 0 2px rgba(26, 168, 107, 0.18);
|
|
536
|
-
}
|
|
587
|
+
@media (max-width: 560px), (max-height: 680px) {
|
|
588
|
+
body {
|
|
589
|
+
padding: 10px;
|
|
590
|
+
}
|
|
537
591
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
592
|
+
main {
|
|
593
|
+
max-height: calc(100dvh - 20px);
|
|
594
|
+
border-radius: 18px;
|
|
595
|
+
}
|
|
541
596
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
gap: 10px;
|
|
546
|
-
}
|
|
597
|
+
.chrome {
|
|
598
|
+
padding: 9px 12px;
|
|
599
|
+
}
|
|
547
600
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
font-weight: 500;
|
|
553
|
-
background: rgba(255, 255, 255, 0.7);
|
|
554
|
-
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
555
|
-
padding: 7px 14px;
|
|
556
|
-
cursor: pointer;
|
|
557
|
-
color: var(--c-gray-700);
|
|
558
|
-
display: inline-flex;
|
|
559
|
-
align-items: center;
|
|
560
|
-
gap: 8px;
|
|
561
|
-
border-radius: 999px;
|
|
562
|
-
transition: all 0.15s var(--ease-standard);
|
|
563
|
-
box-shadow: 0 1px 2px rgba(31, 35, 48, 0.03), 0 1px 0 rgba(255, 255, 255, 0.5) inset;
|
|
564
|
-
}
|
|
601
|
+
.body {
|
|
602
|
+
padding: 12px 13px 14px;
|
|
603
|
+
gap: 9px;
|
|
604
|
+
}
|
|
565
605
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
606
|
+
.splash-wrap {
|
|
607
|
+
margin: 2px 0 0;
|
|
608
|
+
padding: 2px 0;
|
|
609
|
+
}
|
|
569
610
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
611
|
+
.splash {
|
|
612
|
+
font-size: 8px;
|
|
613
|
+
}
|
|
574
614
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
transform: translateY(-0.5px);
|
|
579
|
-
}
|
|
615
|
+
.flow-title {
|
|
616
|
+
font-size: 16px;
|
|
617
|
+
}
|
|
580
618
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
619
|
+
.details,
|
|
620
|
+
.status {
|
|
621
|
+
padding: 10px 11px;
|
|
622
|
+
border-radius: 12px;
|
|
623
|
+
}
|
|
584
624
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
625
|
+
.flow-detail {
|
|
626
|
+
grid-template-columns: 74px 1fr;
|
|
627
|
+
gap: 8px;
|
|
628
|
+
font-size: 12px;
|
|
629
|
+
}
|
|
589
630
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
631
|
+
.status-line {
|
|
632
|
+
gap: 8px;
|
|
633
|
+
font-size: 12px;
|
|
634
|
+
}
|
|
593
635
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
box-shadow: 0 2px 8px -2px rgba(15, 17, 23, 0.2), 0 1px 0 rgba(255, 255, 255, 0.1) inset;
|
|
599
|
-
}
|
|
636
|
+
.status-line .marker {
|
|
637
|
+
width: 24px;
|
|
638
|
+
height: 24px;
|
|
639
|
+
}
|
|
600
640
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
641
|
+
.status-hint {
|
|
642
|
+
margin-left: 32px;
|
|
643
|
+
font-size: 11.5px;
|
|
644
|
+
}
|
|
605
645
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
}
|
|
646
|
+
.footer {
|
|
647
|
+
padding: 10px 12px 12px;
|
|
648
|
+
gap: 8px;
|
|
649
|
+
}
|
|
611
650
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
justify-content: center;
|
|
616
|
-
gap: 4px;
|
|
617
|
-
padding: 2px 7px;
|
|
618
|
-
font-family: var(--font-mono);
|
|
619
|
-
font-size: 10.5px;
|
|
620
|
-
font-weight: 500;
|
|
621
|
-
color: var(--c-gray-500);
|
|
622
|
-
background: rgba(15, 17, 23, 0.04);
|
|
623
|
-
border: 1px solid rgba(15, 17, 23, 0.07);
|
|
624
|
-
border-radius: 5px;
|
|
625
|
-
letter-spacing: 0.02em;
|
|
626
|
-
}
|
|
651
|
+
.actions {
|
|
652
|
+
gap: 7px;
|
|
653
|
+
}
|
|
627
654
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
}
|
|
655
|
+
.shortcut {
|
|
656
|
+
font-size: 12px;
|
|
657
|
+
padding: 6px 10px;
|
|
658
|
+
}
|
|
633
659
|
|
|
634
|
-
|
|
635
|
-
|
|
660
|
+
.net-pill {
|
|
661
|
+
font-size: 10px;
|
|
662
|
+
padding: 4px 8px;
|
|
663
|
+
}
|
|
636
664
|
}
|
|
637
|
-
</style>
|
|
638
|
-
</head>
|
|
639
665
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
<p class="flow-detail" id="flow-detail"><span class="key" id="detail-key">message</span><span
|
|
656
|
-
id="detail-val">—</span></p>
|
|
657
|
-
</div>
|
|
658
|
-
<div class="status" id="status-block">
|
|
659
|
-
<p class="status-line"><span class="marker" id="status-marker">·</span><span id="status-text">connecting to your
|
|
660
|
-
wallet…</span></p>
|
|
661
|
-
<p class="status-hint" id="status-hint">open your wallet extension if it doesn't pop up automatically.</p>
|
|
662
|
-
</div>
|
|
663
|
-
<div class="tx-summary" id="tx-summary" hidden></div>
|
|
664
|
-
<div id="error-block-slot"></div>
|
|
665
|
-
</div>
|
|
666
|
-
<div class="footer">
|
|
667
|
-
<span class="net-pill" id="network-row"><span class="dot"></span><span id="net-val">Sepolia</span></span>
|
|
668
|
-
<div class="actions">
|
|
669
|
-
<button id="cancel" class="shortcut"><span class="key">esc</span><span>cancel</span></button>
|
|
670
|
-
<button id="approve" class="shortcut primary" hidden><span class="key"><svg width="10" height="10"
|
|
671
|
-
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"
|
|
672
|
-
stroke-linejoin="round">
|
|
673
|
-
<polyline points="9 10 4 15 9 20"></polyline>
|
|
674
|
-
<path d="M20 4v7a4 4 0 0 1-4 4H4"></path>
|
|
675
|
-
</svg></span><span>retry</span></button>
|
|
676
|
-
</div>
|
|
677
|
-
</div>
|
|
678
|
-
</main>
|
|
679
|
-
<script>
|
|
680
|
-
const glyphs = {
|
|
681
|
-
eyes: [
|
|
682
|
-
" .-+: ",
|
|
683
|
-
" :=- -%@@@%. ",
|
|
684
|
-
" *@@@@@#- *@@- ",
|
|
685
|
-
" +@@. +@ ",
|
|
686
|
-
" @@= -#=-+++=+: ",
|
|
687
|
-
" #% .:===-: -@* +@@@@% ",
|
|
688
|
-
" *@-+@@@@@: %@@+ @@@=#@ ",
|
|
689
|
-
" *@= @@@@@@@- .@.@@@@@@@ : ",
|
|
690
|
-
" @@+=@@@@@@@@@@@@: .% *@@@@@*-= ",
|
|
691
|
-
" #:-@ -@@@@@@@@@-+% @ -@@@- # ",
|
|
692
|
-
" : #+ @@@@@@@- -% =# = ",
|
|
693
|
-
" -@: *@ .+%% ",
|
|
694
|
-
" :%#: -- ",
|
|
695
|
-
" .-: "
|
|
696
|
-
].join("\n"),
|
|
697
|
-
ellipsis: "…",
|
|
698
|
-
emDash: "—"
|
|
699
|
-
};
|
|
700
|
-
function escapeHtml(value) {
|
|
701
|
-
return String(value == null ? "" : value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """);
|
|
666
|
+
/* dark mode: terminal-style window. */
|
|
667
|
+
main {
|
|
668
|
+
background: #0b0f14;
|
|
669
|
+
color: #f1f1f1;
|
|
670
|
+
border-color: rgba(255, 255, 255, 0.08);
|
|
671
|
+
box-shadow:
|
|
672
|
+
0 1px 0 rgba(255, 255, 255, 0.05) inset,
|
|
673
|
+
0 -1px 0 rgba(0, 0, 0, 0.4) inset,
|
|
674
|
+
0 30px 60px -20px rgba(0, 0, 0, 0.55),
|
|
675
|
+
0 12px 24px -8px rgba(0, 0, 0, 0.35);
|
|
676
|
+
--c-gray-900: #f1f1f1;
|
|
677
|
+
--c-gray-800: #d8d8d8;
|
|
678
|
+
--c-gray-700: #b0b0b0;
|
|
679
|
+
--c-gray-500: #8a8a8a;
|
|
680
|
+
--c-gray-400: #6f6f6f;
|
|
702
681
|
}
|
|
703
|
-
function renderEyes() { return escapeHtml(glyphs.eyes); }
|
|
704
|
-
document.getElementById("splash").innerHTML = renderEyes();
|
|
705
682
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
683
|
+
.splash {
|
|
684
|
+
color: #b0b0b0;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
main::before {
|
|
688
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.18), transparent);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
.chrome {
|
|
692
|
+
border-bottom-color: rgba(255, 255, 255, 0.06);
|
|
693
|
+
background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
.chrome-title {
|
|
697
|
+
color: rgba(241, 241, 241, 0.55);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
.head .label {
|
|
701
|
+
background: rgba(255, 255, 255, 0.06);
|
|
702
|
+
border-color: rgba(255, 255, 255, 0.1);
|
|
703
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.05) inset;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
.details,
|
|
707
|
+
.status,
|
|
708
|
+
#error-block-slot {
|
|
709
|
+
background: rgba(255, 255, 255, 0.04);
|
|
710
|
+
border-color: rgba(255, 255, 255, 0.08);
|
|
711
|
+
box-shadow: 0 4px 16px -4px rgba(0, 0, 0, 0.35), 0 1px 0 rgba(255, 255, 255, 0.04) inset;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
.flow-detail .key {
|
|
715
|
+
background: rgba(255, 255, 255, 0.05);
|
|
716
|
+
border-color: rgba(255, 255, 255, 0.08);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.error-hint code {
|
|
720
|
+
background: rgba(255, 255, 255, 0.06);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
.footer {
|
|
724
|
+
border-top-color: rgba(255, 255, 255, 0.06);
|
|
725
|
+
background: linear-gradient(180deg, rgba(255, 255, 255, 0.01), rgba(255, 255, 255, 0.04));
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.net-pill {
|
|
729
|
+
background: rgba(255, 255, 255, 0.04);
|
|
730
|
+
border-color: rgba(255, 255, 255, 0.08);
|
|
731
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/* esc key: secondary black */
|
|
735
|
+
#cancel.shortcut {
|
|
736
|
+
background: #1f2330;
|
|
737
|
+
border-color: rgba(255, 255, 255, 0.08);
|
|
738
|
+
color: #b0b0b0;
|
|
739
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.04) inset;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
#cancel.shortcut:hover:not(:disabled) {
|
|
743
|
+
background: #2a2e3c;
|
|
744
|
+
color: #f1f1f1;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/* primary action: pin literal so the var override does not bleed through */
|
|
748
|
+
.shortcut.primary {
|
|
749
|
+
background: #1f2330;
|
|
750
|
+
border-color: #1f2330;
|
|
751
|
+
color: #fff;
|
|
752
|
+
box-shadow: 0 2px 8px -2px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.1) inset;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.shortcut.primary:hover:not(:disabled) {
|
|
756
|
+
background: #2a2e3c;
|
|
757
|
+
color: #fff;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
.shortcut.primary .key {
|
|
761
|
+
background: rgba(255, 255, 255, 0.12);
|
|
762
|
+
border-color: rgba(255, 255, 255, 0.2);
|
|
763
|
+
color: rgba(255, 255, 255, 0.9);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.key {
|
|
767
|
+
background: rgba(255, 255, 255, 0.06);
|
|
768
|
+
border-color: rgba(255, 255, 255, 0.1);
|
|
769
|
+
}
|
|
770
|
+
</style>
|
|
771
|
+
</head>
|
|
772
|
+
|
|
773
|
+
<body>
|
|
774
|
+
<main data-flow="sign" id="card">
|
|
775
|
+
<div class="chrome">
|
|
776
|
+
<span class="light r"></span>
|
|
777
|
+
<span class="light y"></span>
|
|
778
|
+
<span class="light g"></span>
|
|
779
|
+
<span class="chrome-title" id="chrome-title">ethagent</span>
|
|
780
|
+
</div>
|
|
781
|
+
<div class="body">
|
|
782
|
+
<div class="splash-wrap">
|
|
783
|
+
<pre class="splash" id="splash"></pre>
|
|
784
|
+
</div>
|
|
785
|
+
<div class="head"><span class="label" id="prompt-text">signature request</span></div>
|
|
786
|
+
<h2 class="flow-title" id="flow-title">Sign a message to prove ownership</h2>
|
|
787
|
+
<div class="details" id="details-block">
|
|
788
|
+
<p class="flow-detail" id="flow-detail"><span class="key" id="detail-key">message</span><span
|
|
789
|
+
id="detail-val">—</span></p>
|
|
790
|
+
</div>
|
|
791
|
+
<div class="status" id="status-block">
|
|
792
|
+
<p class="status-line"><span class="marker" id="status-marker">·</span><span id="status-text">connecting to your
|
|
793
|
+
wallet…</span></p>
|
|
794
|
+
<p class="status-hint" id="status-hint">open your wallet extension if it doesn't pop up automatically.</p>
|
|
795
|
+
</div>
|
|
796
|
+
<div id="error-block-slot"></div>
|
|
797
|
+
</div>
|
|
798
|
+
<div class="footer">
|
|
799
|
+
<span class="net-pill" id="network-row"><span class="dot"></span><span id="net-val">Sepolia</span></span>
|
|
800
|
+
<div class="actions">
|
|
801
|
+
<button id="cancel" class="shortcut"><span class="key">esc</span><span>cancel</span></button>
|
|
802
|
+
<button id="approve" class="shortcut primary" hidden><span class="key"><svg width="10" height="10"
|
|
803
|
+
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"
|
|
804
|
+
stroke-linejoin="round">
|
|
805
|
+
<polyline points="9 10 4 15 9 20"></polyline>
|
|
806
|
+
<path d="M20 4v7a4 4 0 0 1-4 4H4"></path>
|
|
807
|
+
</svg></span><span>retry</span></button>
|
|
808
|
+
</div>
|
|
809
|
+
</div>
|
|
810
|
+
</main>
|
|
811
|
+
<script>
|
|
812
|
+
const glyphs = {
|
|
813
|
+
eyes: [
|
|
814
|
+
" .-+: ",
|
|
815
|
+
" :=- -%@@@%. ",
|
|
816
|
+
" *@@@@@#- *@@- ",
|
|
817
|
+
" +@@. +@ ",
|
|
818
|
+
" @@= -#=-+++=+: ",
|
|
819
|
+
" #% .:===-: -@* +@@@@% ",
|
|
820
|
+
" *@-+@@@@@: %@@+ @@@=#@ ",
|
|
821
|
+
" *@= @@@@@@@- .@.@@@@@@@ : ",
|
|
822
|
+
" @@+=@@@@@@@@@@@@: .% *@@@@@*-= ",
|
|
823
|
+
" #:-@ -@@@@@@@@@-+% @ -@@@- # ",
|
|
824
|
+
" : #+ @@@@@@@- -% =# = ",
|
|
825
|
+
" -@: *@ .+%% ",
|
|
826
|
+
" :%#: -- ",
|
|
827
|
+
" .-: "
|
|
828
|
+
].join("\n"),
|
|
829
|
+
ellipsis: "…",
|
|
830
|
+
emDash: "—"
|
|
831
|
+
};
|
|
832
|
+
function escapeHtml(value) {
|
|
833
|
+
return String(value == null ? "" : value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """);
|
|
834
|
+
}
|
|
835
|
+
function renderEyes() { return escapeHtml(glyphs.eyes); }
|
|
836
|
+
document.getElementById("splash").innerHTML = renderEyes();
|
|
837
|
+
|
|
838
|
+
const config = window.__WALLET_CONFIG__ || { sessionToken: "preview", kind: "sign", chainIdHex: "0xaa36a7", message: "identity proof for 0x9F2a…BC4e" };
|
|
839
|
+
const CLOSE_DELAY_MS = 10000;
|
|
840
|
+
const TX_CLOSE_DELAY_MS = 10000;
|
|
841
|
+
const CANCEL_CLOSE_DELAY_MS = 3200;
|
|
842
|
+
const WALLET_PROVIDER_WAIT_MS = 3000;
|
|
843
|
+
const WALLET_PROVIDER_POLL_MS = 100;
|
|
844
|
+
const CHAINS = { "0x1": { name: "Ethereum Mainnet" }, "0xaa36a7": { name: "Sepolia" }, "0x2105": { name: "Base" }, "0x14a34": { name: "Base Sepolia" }, "0xa": { name: "OP Mainnet" }, "0xa4b1": { name: "Arbitrum One" } };
|
|
845
|
+
const FLOW_COPY = {
|
|
846
|
+
account: { accent: "sign", tabTitle: "connect wallet", label: "wallet request", title: "Connect wallet to find your agent", detail: null },
|
|
847
|
+
sign: { accent: "sign", tabTitle: "sign message", label: "signature request", title: "Sign a message to prove ownership", detail: "message" },
|
|
848
|
+
"sign-transaction": { accent: "transaction", tabTitle: "approve identity update", label: "identity approval", title: "Sign, then save identity files", detail: "message" },
|
|
849
|
+
transaction: { accent: "transaction", tabTitle: "submit transaction", label: "transaction request", title: "Submit transaction to mint your ERC-8004 agent", detail: "registry" }
|
|
850
|
+
};
|
|
851
|
+
const STATE_TITLES = { connecting: "connecting wallet", approveSign: "approve signature", preparingTransaction: "preparing transaction", approveTransaction: "approve transaction", error: "wallet error", default: "wallet request" };
|
|
720
852
|
function chainLabel(hex) { const k = String(hex || "").toLowerCase(); return (CHAINS[k] && CHAINS[k].name) || ("chain " + k); }
|
|
721
853
|
function shortAddr(addr) { if (!addr || typeof addr !== "string") return glyphs.emDash; if (addr.length <= 14) return addr; return addr.slice(0, 6) + glyphs.ellipsis + addr.slice(-4); }
|
|
722
854
|
function isTransactionFlow() { return config.kind === "transaction" || config.kind === "sign-transaction"; }
|
|
723
|
-
function transactionActionLabel() { if (config.kind === "sign-transaction") return "publish identity snapshot"; if (config.kind === "transaction") return "submit transaction"; return "wallet request"; }
|
|
724
855
|
|
|
725
856
|
const card = document.getElementById("card");
|
|
726
|
-
const promptText = document.getElementById("prompt-text");
|
|
727
|
-
const flowTitle = document.getElementById("flow-title");
|
|
728
|
-
const networkRow = document.getElementById("network-row");
|
|
729
|
-
const flowDetail = document.getElementById("flow-detail");
|
|
730
|
-
const detailsBlock = document.getElementById("details-block");
|
|
731
|
-
const detailKey = document.getElementById("detail-key");
|
|
732
|
-
const detailVal = document.getElementById("detail-val");
|
|
733
|
-
const netVal = document.getElementById("net-val");
|
|
734
|
-
const statusBlock = document.getElementById("status-block");
|
|
735
|
-
const statusMarker = document.getElementById("status-marker");
|
|
857
|
+
const promptText = document.getElementById("prompt-text");
|
|
858
|
+
const flowTitle = document.getElementById("flow-title");
|
|
859
|
+
const networkRow = document.getElementById("network-row");
|
|
860
|
+
const flowDetail = document.getElementById("flow-detail");
|
|
861
|
+
const detailsBlock = document.getElementById("details-block");
|
|
862
|
+
const detailKey = document.getElementById("detail-key");
|
|
863
|
+
const detailVal = document.getElementById("detail-val");
|
|
864
|
+
const netVal = document.getElementById("net-val");
|
|
865
|
+
const statusBlock = document.getElementById("status-block");
|
|
866
|
+
const statusMarker = document.getElementById("status-marker");
|
|
736
867
|
const statusText = document.getElementById("status-text");
|
|
737
868
|
const statusHint = document.getElementById("status-hint");
|
|
738
869
|
const errorSlot = document.getElementById("error-block-slot");
|
|
739
|
-
const txSummary = document.getElementById("tx-summary");
|
|
740
870
|
const approve = document.getElementById("approve");
|
|
741
|
-
const cancel = document.getElementById("cancel");
|
|
871
|
+
const cancel = document.getElementById("cancel");
|
|
742
872
|
let announcedEthereum = null;
|
|
743
873
|
let activeEthereum = null;
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
function
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
return
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
window.removeEventListener("
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
settled
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
const
|
|
770
|
-
const
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
window.addEventListener("
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
statusMarker.
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
spinning
|
|
793
|
-
|
|
794
|
-
statusMarker.
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
function
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
if (state === "
|
|
802
|
-
if (state === "
|
|
803
|
-
if (state === "
|
|
804
|
-
if (state === "
|
|
805
|
-
if (state === "
|
|
806
|
-
|
|
807
|
-
if (config.kind === "
|
|
808
|
-
return STATE_TITLES.
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
if (config.kind === "
|
|
813
|
-
return "
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
if (config.kind === "
|
|
818
|
-
return "
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
function
|
|
830
|
-
|
|
831
|
-
if (copy.detail === "
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
const
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
874
|
+
let closeCountdown = null;
|
|
875
|
+
|
|
876
|
+
function rememberAnnouncedProvider(event) { const provider = event && event.detail && event.detail.provider; if (provider && !announcedEthereum) announcedEthereum = provider; }
|
|
877
|
+
window.addEventListener("eip6963:announceProvider", rememberAnnouncedProvider);
|
|
878
|
+
try { window.dispatchEvent(new Event("eip6963:requestProvider")); } catch (_) { }
|
|
879
|
+
function ethereumProvider() { return activeEthereum || window.ethereum || announcedEthereum; }
|
|
880
|
+
function noWalletError() { return new Error("No browser wallet detected. Install MetaMask, Rabby, or use Brave."); }
|
|
881
|
+
|
|
882
|
+
function waitForEthereumProvider(timeoutMs) {
|
|
883
|
+
const existing = ethereumProvider();
|
|
884
|
+
if (existing) return Promise.resolve(existing);
|
|
885
|
+
return new Promise((resolve, reject) => {
|
|
886
|
+
let settled = false;
|
|
887
|
+
const cleanup = () => {
|
|
888
|
+
clearTimeout(timer);
|
|
889
|
+
clearInterval(interval);
|
|
890
|
+
window.removeEventListener("ethereum#initialized", check);
|
|
891
|
+
window.removeEventListener("eip6963:announceProvider", onAnnounce);
|
|
892
|
+
};
|
|
893
|
+
const finish = (fn) => {
|
|
894
|
+
if (settled) return;
|
|
895
|
+
settled = true;
|
|
896
|
+
cleanup();
|
|
897
|
+
fn();
|
|
898
|
+
};
|
|
899
|
+
const check = () => { const provider = ethereumProvider(); if (provider) finish(() => resolve(provider)); };
|
|
900
|
+
const onAnnounce = (event) => { rememberAnnouncedProvider(event); check(); };
|
|
901
|
+
const timer = setTimeout(() => finish(() => reject(noWalletError())), timeoutMs || WALLET_PROVIDER_WAIT_MS);
|
|
902
|
+
const interval = setInterval(check, WALLET_PROVIDER_POLL_MS);
|
|
903
|
+
window.addEventListener("ethereum#initialized", check);
|
|
904
|
+
window.addEventListener("eip6963:announceProvider", onAnnounce);
|
|
905
|
+
try { window.dispatchEvent(new Event("eip6963:requestProvider")); } catch (_) { }
|
|
906
|
+
check();
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
async function walletRequest(method, params) {
|
|
910
|
+
const provider = ethereumProvider();
|
|
911
|
+
if (!provider) throw noWalletError();
|
|
912
|
+
return await provider.request(params === undefined ? { method } : { method, params });
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
let spinning = false;
|
|
916
|
+
function startSpinner() {
|
|
917
|
+
spinning = true;
|
|
918
|
+
statusMarker.innerHTML = '<span class="spinner" aria-hidden="true"></span>';
|
|
919
|
+
statusMarker.style.background = "transparent";
|
|
920
|
+
}
|
|
921
|
+
function stopSpinner() {
|
|
922
|
+
if (!spinning) return;
|
|
923
|
+
spinning = false;
|
|
924
|
+
statusMarker.innerHTML = "";
|
|
925
|
+
statusMarker.style.background = "";
|
|
926
|
+
}
|
|
927
|
+
function setMarker(text) { stopSpinner(); statusMarker.textContent = text; }
|
|
928
|
+
function flowCopy() { return FLOW_COPY[config.kind] || FLOW_COPY.sign; }
|
|
929
|
+
|
|
930
|
+
function tabTitleForState(state) {
|
|
931
|
+
if (state === "connecting") return STATE_TITLES.connecting;
|
|
932
|
+
if (state === "approve-sign") return STATE_TITLES.approveSign;
|
|
933
|
+
if (state === "preparing-transaction") return STATE_TITLES.preparingTransaction;
|
|
934
|
+
if (state === "approve-transaction") return STATE_TITLES.approveTransaction;
|
|
935
|
+
if (state === "error") return STATE_TITLES.error;
|
|
936
|
+
if (state === "approve") {
|
|
937
|
+
if (config.kind === "account") return "approve connection";
|
|
938
|
+
if (config.kind === "sign") return STATE_TITLES.approveSign;
|
|
939
|
+
return STATE_TITLES.approveTransaction;
|
|
940
|
+
}
|
|
941
|
+
if (state === "submitting") {
|
|
942
|
+
if (config.kind === "account") return STATE_TITLES.connecting;
|
|
943
|
+
if (config.kind === "sign") return "verifying signature";
|
|
944
|
+
return "confirming transaction";
|
|
945
|
+
}
|
|
946
|
+
if (state === "done") {
|
|
947
|
+
if (config.kind === "account") return "wallet connected";
|
|
948
|
+
if (config.kind === "sign") return "message signed";
|
|
949
|
+
return "transaction submitted";
|
|
950
|
+
}
|
|
951
|
+
return flowCopy().tabTitle || STATE_TITLES.default;
|
|
952
|
+
}
|
|
953
|
+
function setTabTitle(title) {
|
|
954
|
+
const t = title || flowCopy().tabTitle || STATE_TITLES.default;
|
|
955
|
+
document.title = t;
|
|
956
|
+
const chromeTitle = document.getElementById("chrome-title");
|
|
957
|
+
if (chromeTitle) chromeTitle.textContent = "ethagent · " + t;
|
|
958
|
+
}
|
|
959
|
+
function messagePreview(message) { const preview = String(message || "").split("\n")[0]; return preview.length > 64 ? preview.slice(0, 64) + glyphs.ellipsis : preview; }
|
|
960
|
+
function detailPreview(copy) {
|
|
961
|
+
if (copy.detail === "message") return messagePreview(config.message);
|
|
962
|
+
if (copy.detail === "registry" && config.tx) return shortAddr(config.tx.to);
|
|
963
|
+
return "";
|
|
964
|
+
}
|
|
965
|
+
function showPreparedMessage(message) {
|
|
966
|
+
const copy = flowCopy();
|
|
967
|
+
if (copy.detail !== "message") return;
|
|
968
|
+
const preview = messagePreview(message);
|
|
969
|
+
detailKey.textContent = copy.detail;
|
|
970
|
+
detailVal.textContent = preview;
|
|
971
|
+
flowDetail.hidden = preview.length === 0;
|
|
972
|
+
detailsBlock.hidden = flowDetail.hidden;
|
|
973
|
+
}
|
|
974
|
+
function applyFlowChrome() {
|
|
975
|
+
const copy = flowCopy();
|
|
976
|
+
card.dataset.flow = copy.accent;
|
|
977
|
+
promptText.textContent = copy.label;
|
|
978
|
+
flowTitle.textContent = copy.title;
|
|
979
|
+
setTabTitle(copy.tabTitle);
|
|
980
|
+
if (!copy.detail) {
|
|
981
|
+
networkRow.hidden = true;
|
|
982
|
+
flowDetail.hidden = true;
|
|
983
|
+
detailsBlock.hidden = true;
|
|
984
|
+
} else {
|
|
985
|
+
networkRow.hidden = false;
|
|
986
|
+
flowDetail.hidden = false;
|
|
987
|
+
detailsBlock.hidden = false;
|
|
988
|
+
netVal.textContent = chainLabel(config.chainIdHex);
|
|
989
|
+
detailKey.textContent = copy.detail;
|
|
990
|
+
detailVal.textContent = detailPreview(copy);
|
|
991
|
+
flowDetail.hidden = detailVal.textContent.length === 0;
|
|
992
|
+
if (flowDetail.hidden) detailsBlock.hidden = true;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
function setStatus(marker, text, hint, spin) {
|
|
997
|
+
const lineEl = statusText.parentElement;
|
|
998
|
+
const hintEl = statusHint;
|
|
999
|
+
const apply = () => {
|
|
1000
|
+
if (spin) startSpinner();
|
|
1001
|
+
else setMarker(marker);
|
|
1002
|
+
statusText.textContent = text;
|
|
1003
|
+
hintEl.textContent = hint;
|
|
1004
|
+
requestAnimationFrame(() => {
|
|
1005
|
+
lineEl.classList.remove("is-changing");
|
|
1006
|
+
hintEl.classList.remove("is-changing");
|
|
1007
|
+
});
|
|
1008
|
+
};
|
|
1009
|
+
if (statusText.textContent === text && hintEl.textContent === hint) {
|
|
1010
|
+
if (spin) startSpinner();
|
|
1011
|
+
else setMarker(marker);
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
lineEl.classList.add("is-changing");
|
|
1015
|
+
hintEl.classList.add("is-changing");
|
|
1016
|
+
setTimeout(apply, 220);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
function setState(state, payload) {
|
|
1020
|
+
payload = payload || {};
|
|
890
1021
|
errorSlot.innerHTML = "";
|
|
891
1022
|
statusBlock.style.display = "flex";
|
|
892
1023
|
setTabTitle(tabTitleForState(state));
|
|
893
|
-
renderTransactionSummary(payload);
|
|
894
1024
|
switch (state) {
|
|
895
|
-
case "connecting":
|
|
896
|
-
setStatus("·", "connecting to your wallet…", "open your wallet extension if it doesn't pop up automatically.", true);
|
|
897
|
-
break;
|
|
898
|
-
case "approve":
|
|
899
|
-
if (config.kind === "account") setStatus("·", "approve wallet connection", "the selected address will be used to search for owned agents.", true);
|
|
900
|
-
else if (config.kind === "sign") setStatus("·", "approve the signature in your wallet", "a prompt should be open. waiting for your signature.", true);
|
|
901
|
-
else setStatus("·", "review and submit the transaction in your wallet", "check the network and contract address before approving.", true);
|
|
902
|
-
break;
|
|
1025
|
+
case "connecting":
|
|
1026
|
+
setStatus("·", "connecting to your wallet…", "open your wallet extension if it doesn't pop up automatically.", true);
|
|
1027
|
+
break;
|
|
1028
|
+
case "approve":
|
|
1029
|
+
if (config.kind === "account") setStatus("·", "approve wallet connection", "the selected address will be used to search for owned agents.", true);
|
|
1030
|
+
else if (config.kind === "sign") setStatus("·", "approve the signature in your wallet", "a prompt should be open. waiting for your signature.", true);
|
|
1031
|
+
else setStatus("·", "review and submit the transaction in your wallet", "check the network and contract address before approving.", true);
|
|
1032
|
+
break;
|
|
903
1033
|
case "approve-sign":
|
|
904
|
-
setStatus("·", "approve the signature in your wallet", "
|
|
1034
|
+
setStatus("·", "approve the signature in your wallet", "this encrypts or decrypts SOUL.md and MEMORY.md.", true);
|
|
905
1035
|
break;
|
|
906
1036
|
case "preparing-transaction":
|
|
907
|
-
setStatus("·", "
|
|
908
|
-
break;
|
|
909
|
-
case "approve-transaction":
|
|
910
|
-
setStatus("·", "review and submit the transaction in your wallet", "check the network and contract address before approving.", true);
|
|
911
|
-
break;
|
|
912
|
-
case "submitting":
|
|
913
|
-
if (config.kind === "account") setStatus("·", "connecting wallet…", "sending the selected address back.", true);
|
|
914
|
-
else if (config.kind === "sign") setStatus("·", "verifying signature…", "recovering the signing address.", true);
|
|
915
|
-
else setStatus("·", "submitted · waiting for confirmation…", "your wallet has accepted the transaction.", true);
|
|
916
|
-
break;
|
|
917
|
-
case "done":
|
|
918
|
-
setMarker("✓");
|
|
919
|
-
statusText.textContent = config.kind === "account" ? "connected · returning" : config.kind === "sign" ? "signed · returning" : "submitted · returning";
|
|
920
|
-
statusHint.textContent = payload.txHash ? (isTransactionFlow() ? "transaction submitted. returning." : "this tab will close shortly.") : "this tab will close shortly.";
|
|
921
|
-
break;
|
|
922
|
-
case "error":
|
|
923
|
-
stopSpinner();
|
|
924
|
-
statusBlock.style.display = "none";
|
|
925
|
-
renderError(payload);
|
|
926
|
-
break;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
function
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
const r = await fetch(path, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ ...(body || {}), sessionToken: config.sessionToken }) });
|
|
969
|
-
const d = await r.json();
|
|
970
|
-
if (!r.ok || !d.ok) throw new Error(d.error || "wallet request failed");
|
|
971
|
-
return d;
|
|
1037
|
+
setStatus("·", "encrypting SOUL.md and MEMORY.md, then preparing the update...", "keep this page open. the transaction prompt will appear here.", true);
|
|
1038
|
+
break;
|
|
1039
|
+
case "approve-transaction":
|
|
1040
|
+
setStatus("·", "review and submit the transaction in your wallet", "check the network and contract address before approving.", true);
|
|
1041
|
+
break;
|
|
1042
|
+
case "submitting":
|
|
1043
|
+
if (config.kind === "account") setStatus("·", "connecting wallet…", "sending the selected address back.", true);
|
|
1044
|
+
else if (config.kind === "sign") setStatus("·", "verifying signature…", "recovering the signing address.", true);
|
|
1045
|
+
else setStatus("·", "submitted · waiting for confirmation…", "your wallet has accepted the transaction.", true);
|
|
1046
|
+
break;
|
|
1047
|
+
case "done":
|
|
1048
|
+
setMarker("✓");
|
|
1049
|
+
statusText.textContent = config.kind === "account" ? "connected · returning" : config.kind === "sign" ? "signed · returning" : "submitted · returning";
|
|
1050
|
+
statusHint.textContent = payload.txHash ? (isTransactionFlow() ? "transaction submitted. returning." : "this tab will close shortly.") : "this tab will close shortly.";
|
|
1051
|
+
break;
|
|
1052
|
+
case "error":
|
|
1053
|
+
stopSpinner();
|
|
1054
|
+
statusBlock.style.display = "none";
|
|
1055
|
+
renderError(payload);
|
|
1056
|
+
break;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
function renderError(payload) {
|
|
1061
|
+
const msg = payload.message || "Something went wrong.";
|
|
1062
|
+
const isNoWallet = /no wallet|window\.ethereum|metamask|rabby|brave|extension/i.test(msg);
|
|
1063
|
+
const isUserReject = /user rejected|user denied|cancelled|canceled/i.test(msg);
|
|
1064
|
+
const isWrongChain = /chain|network/i.test(msg) && !isNoWallet;
|
|
1065
|
+
let title = "wallet error";
|
|
1066
|
+
let body = msg;
|
|
1067
|
+
let hint = "press enter to retry, or esc to abort.";
|
|
1068
|
+
if (isNoWallet) {
|
|
1069
|
+
title = "no wallet";
|
|
1070
|
+
body = "install a browser wallet.";
|
|
1071
|
+
hint = 'Get <a href="https://phantom.com/download" target="_blank" rel="noopener">Phantom</a>, then press <code>enter</code>.';
|
|
1072
|
+
} else if (isUserReject) {
|
|
1073
|
+
title = "rejected";
|
|
1074
|
+
body = "request declined in wallet.";
|
|
1075
|
+
hint = "press <code>enter</code> to retry, or <code>esc</code> to abort.";
|
|
1076
|
+
} else if (isWrongChain) {
|
|
1077
|
+
title = "wrong network";
|
|
1078
|
+
hint = "expected <code>" + escapeHtml(chainLabel(config.chainIdHex)) + "</code>. switch networks, then retry.";
|
|
1079
|
+
}
|
|
1080
|
+
errorSlot.innerHTML = '<p class="error-title">' + escapeHtml(title) + "</p>" + '<p class="error-msg">' + escapeHtml(body) + "</p>" + '<p class="error-hint">' + hint + "</p>";
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
async function post(path, body) {
|
|
1084
|
+
const r = await fetch(path, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ ...(body || {}), sessionToken: config.sessionToken }) });
|
|
1085
|
+
const d = await r.json();
|
|
1086
|
+
if (!r.ok || !d.ok) throw new Error(d.error || "wallet request failed");
|
|
1087
|
+
return d;
|
|
1088
|
+
}
|
|
1089
|
+
function showCloseCountdown(delayMs) {
|
|
1090
|
+
if (closeCountdown) clearInterval(closeCountdown);
|
|
1091
|
+
const deadline = Date.now() + delayMs;
|
|
1092
|
+
const update = () => {
|
|
1093
|
+
const seconds = Math.max(1, Math.ceil((deadline - Date.now()) / 1000));
|
|
1094
|
+
statusHint.textContent = "return to your terminal. closing in " + seconds + "s.";
|
|
1095
|
+
};
|
|
1096
|
+
update();
|
|
1097
|
+
closeCountdown = setInterval(update, 250);
|
|
972
1098
|
}
|
|
973
1099
|
function closeSoon(delayMs) {
|
|
1100
|
+
const ms = delayMs == null ? CLOSE_DELAY_MS : delayMs;
|
|
1101
|
+
showCloseCountdown(ms);
|
|
974
1102
|
setTimeout(() => {
|
|
1103
|
+
if (closeCountdown) clearInterval(closeCountdown);
|
|
975
1104
|
try { if (window.opener && !window.opener.closed) window.opener.focus(); } catch (_) { }
|
|
976
1105
|
window.close();
|
|
977
1106
|
window.open("", "_self");
|
|
978
1107
|
window.close();
|
|
979
|
-
},
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
async function ensureWallet() {
|
|
983
|
-
setState("connecting");
|
|
984
|
-
const provider = await waitForEthereumProvider();
|
|
985
|
-
activeEthereum = provider;
|
|
986
|
-
const accounts = await provider.request({ method: "eth_requestAccounts" });
|
|
987
|
-
const account = accounts && accounts[0];
|
|
988
|
-
if (!account) throw new Error("No wallet account was selected.");
|
|
989
|
-
if (!config.chainIdHex) return account;
|
|
990
|
-
try { await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId: config.chainIdHex }] }); }
|
|
991
|
-
catch (err) {
|
|
992
|
-
const cur = await provider.request({ method: "eth_chainId" });
|
|
993
|
-
if (String(cur).toLowerCase() !== String(config.chainIdHex).toLowerCase()) throw err;
|
|
994
|
-
}
|
|
995
|
-
return account;
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
async function runWalletFlow() {
|
|
999
|
-
approve.disabled = true;
|
|
1000
|
-
approve.hidden = true;
|
|
1001
|
-
cancel.disabled = false;
|
|
1002
|
-
errorSlot.innerHTML = "";
|
|
1003
|
-
try {
|
|
1004
|
-
const account = await ensureWallet();
|
|
1005
|
-
if (config.kind === "account") {
|
|
1006
|
-
setState("submitting");
|
|
1007
|
-
await post("/complete", { account });
|
|
1008
|
-
setState("done");
|
|
1009
|
-
closeSoon();
|
|
1010
|
-
return;
|
|
1011
|
-
}
|
|
1012
|
-
if (config.kind === "sign") {
|
|
1013
|
-
const prepared = config.message ? { message: config.message } : await post("/prepare", { account });
|
|
1014
|
-
showPreparedMessage(prepared.message);
|
|
1015
|
-
setState("approve");
|
|
1016
|
-
const signature = await walletRequest("personal_sign", [prepared.message, account]);
|
|
1017
|
-
setState("submitting");
|
|
1018
|
-
await post("/complete", { account, message: prepared.message, signature });
|
|
1019
|
-
setState("done");
|
|
1020
|
-
closeSoon();
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
if (config.kind === "sign-transaction") {
|
|
1024
|
-
const prepared = config.message ? { message: config.message } : await post("/prepare", { account });
|
|
1025
|
-
showPreparedMessage(prepared.message);
|
|
1026
|
-
setState("approve-sign", { account });
|
|
1027
|
-
const signature = await walletRequest("personal_sign", [prepared.message, account]);
|
|
1028
|
-
setState("preparing-transaction", { account });
|
|
1029
|
-
const txPayload = await post("/prepare-transaction", { account, message: prepared.message, signature });
|
|
1030
|
-
setState("approve-transaction", { account, tx: txPayload.tx });
|
|
1031
|
-
const tx = txPayload.tx || {};
|
|
1032
|
-
const txHash = await walletRequest("eth_sendTransaction", [{ from: account, to: tx.to, data: tx.data, value: tx.value }]);
|
|
1033
|
-
setState("submitting", { account, tx, txHash });
|
|
1034
|
-
await post("/complete", { account, txHash });
|
|
1035
|
-
setState("done", { account, tx, txHash });
|
|
1036
|
-
closeSoon(TX_CLOSE_DELAY_MS);
|
|
1037
|
-
return;
|
|
1038
|
-
}
|
|
1039
|
-
if (config.kind === "transaction") {
|
|
1040
|
-
setState("approve", { account, tx: config.tx });
|
|
1041
|
-
const txHash = await walletRequest("eth_sendTransaction", [{ from: account, to: config.tx.to, data: config.tx.data, value: config.tx.value }]);
|
|
1042
|
-
setState("submitting", { account, tx: config.tx, txHash });
|
|
1043
|
-
await post("/complete", { account, txHash });
|
|
1044
|
-
setState("done", { account, tx: config.tx, txHash });
|
|
1045
|
-
closeSoon(TX_CLOSE_DELAY_MS);
|
|
1046
|
-
return;
|
|
1047
|
-
}
|
|
1048
|
-
throw new Error("Unknown wallet request type.");
|
|
1049
|
-
} catch (err) {
|
|
1050
|
-
approve.disabled = false;
|
|
1051
|
-
approve.hidden = false;
|
|
1052
|
-
cancel.disabled = false;
|
|
1053
|
-
setState("error", { message: (err && err.message) || String(err) });
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
async function cancelFlow() {
|
|
1058
|
-
approve.disabled = true;
|
|
1059
|
-
cancel.disabled = true;
|
|
1060
|
-
await post("/cancel", {}).catch(() => { });
|
|
1061
|
-
setState("done");
|
|
1062
|
-
statusText.textContent = "cancelled · returning";
|
|
1063
|
-
closeSoon(CANCEL_CLOSE_DELAY_MS);
|
|
1064
|
-
}
|
|
1065
|
-
approve.onclick = runWalletFlow;
|
|
1066
|
-
cancel.onclick = cancelFlow;
|
|
1067
|
-
window.addEventListener("keydown", (e) => {
|
|
1068
|
-
if (e.key === "Escape") { e.preventDefault(); cancelFlow(); }
|
|
1069
|
-
else if (e.key === "Enter" && !approve.hidden && !approve.disabled) { e.preventDefault(); runWalletFlow(); }
|
|
1070
|
-
});
|
|
1071
|
-
|
|
1072
|
-
applyFlowChrome();
|
|
1073
|
-
if (!window.__WALLET_PREVIEW__) {
|
|
1074
|
-
window.addEventListener("load", () => setTimeout(runWalletFlow, 150));
|
|
1075
|
-
} else {
|
|
1076
|
-
window.__walletPreview = { setState, setConfig: (c) => { Object.assign(config, c); applyFlowChrome(); } };
|
|
1077
|
-
setState("connecting");
|
|
1078
|
-
}
|
|
1079
|
-
</script>
|
|
1080
|
-
</body>
|
|
1081
|
-
|
|
1082
|
-
</html>
|
|
1108
|
+
}, ms);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
async function ensureWallet() {
|
|
1112
|
+
setState("connecting");
|
|
1113
|
+
const provider = await waitForEthereumProvider();
|
|
1114
|
+
activeEthereum = provider;
|
|
1115
|
+
const accounts = await provider.request({ method: "eth_requestAccounts" });
|
|
1116
|
+
const account = accounts && accounts[0];
|
|
1117
|
+
if (!account) throw new Error("No wallet account was selected.");
|
|
1118
|
+
if (!config.chainIdHex) return account;
|
|
1119
|
+
try { await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId: config.chainIdHex }] }); }
|
|
1120
|
+
catch (err) {
|
|
1121
|
+
const cur = await provider.request({ method: "eth_chainId" });
|
|
1122
|
+
if (String(cur).toLowerCase() !== String(config.chainIdHex).toLowerCase()) throw err;
|
|
1123
|
+
}
|
|
1124
|
+
return account;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
async function runWalletFlow() {
|
|
1128
|
+
approve.disabled = true;
|
|
1129
|
+
approve.hidden = true;
|
|
1130
|
+
cancel.disabled = false;
|
|
1131
|
+
errorSlot.innerHTML = "";
|
|
1132
|
+
try {
|
|
1133
|
+
const account = await ensureWallet();
|
|
1134
|
+
if (config.kind === "account") {
|
|
1135
|
+
setState("submitting");
|
|
1136
|
+
await post("/complete", { account });
|
|
1137
|
+
setState("done");
|
|
1138
|
+
closeSoon();
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
if (config.kind === "sign") {
|
|
1142
|
+
const prepared = config.message ? { message: config.message } : await post("/prepare", { account });
|
|
1143
|
+
showPreparedMessage(prepared.message);
|
|
1144
|
+
setState("approve");
|
|
1145
|
+
const signature = await walletRequest("personal_sign", [prepared.message, account]);
|
|
1146
|
+
setState("submitting");
|
|
1147
|
+
await post("/complete", { account, message: prepared.message, signature });
|
|
1148
|
+
setState("done");
|
|
1149
|
+
closeSoon();
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
if (config.kind === "sign-transaction") {
|
|
1153
|
+
const prepared = config.message ? { message: config.message } : await post("/prepare", { account });
|
|
1154
|
+
showPreparedMessage(prepared.message);
|
|
1155
|
+
setState("approve-sign", { account });
|
|
1156
|
+
const signature = await walletRequest("personal_sign", [prepared.message, account]);
|
|
1157
|
+
setState("preparing-transaction", { account });
|
|
1158
|
+
const txPayload = await post("/prepare-transaction", { account, message: prepared.message, signature });
|
|
1159
|
+
setState("approve-transaction", { account, tx: txPayload.tx });
|
|
1160
|
+
const tx = txPayload.tx || {};
|
|
1161
|
+
const txHash = await walletRequest("eth_sendTransaction", [{ from: account, to: tx.to, data: tx.data, value: tx.value }]);
|
|
1162
|
+
setState("submitting", { account, tx, txHash });
|
|
1163
|
+
await post("/complete", { account, txHash });
|
|
1164
|
+
setState("done", { account, tx, txHash });
|
|
1165
|
+
closeSoon(TX_CLOSE_DELAY_MS);
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
if (config.kind === "transaction") {
|
|
1169
|
+
setState("approve", { account, tx: config.tx });
|
|
1170
|
+
const txHash = await walletRequest("eth_sendTransaction", [{ from: account, to: config.tx.to, data: config.tx.data, value: config.tx.value }]);
|
|
1171
|
+
setState("submitting", { account, tx: config.tx, txHash });
|
|
1172
|
+
await post("/complete", { account, txHash });
|
|
1173
|
+
setState("done", { account, tx: config.tx, txHash });
|
|
1174
|
+
closeSoon(TX_CLOSE_DELAY_MS);
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
throw new Error("Unknown wallet request type.");
|
|
1178
|
+
} catch (err) {
|
|
1179
|
+
approve.disabled = false;
|
|
1180
|
+
approve.hidden = false;
|
|
1181
|
+
cancel.disabled = false;
|
|
1182
|
+
setState("error", { message: (err && err.message) || String(err) });
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
async function cancelFlow() {
|
|
1187
|
+
approve.disabled = true;
|
|
1188
|
+
cancel.disabled = true;
|
|
1189
|
+
await post("/cancel", {}).catch(() => { });
|
|
1190
|
+
setState("done");
|
|
1191
|
+
statusText.textContent = "cancelled · returning";
|
|
1192
|
+
closeSoon(CANCEL_CLOSE_DELAY_MS);
|
|
1193
|
+
}
|
|
1194
|
+
approve.onclick = runWalletFlow;
|
|
1195
|
+
cancel.onclick = cancelFlow;
|
|
1196
|
+
window.addEventListener("keydown", (e) => {
|
|
1197
|
+
if (e.key === "Escape") { e.preventDefault(); cancelFlow(); }
|
|
1198
|
+
else if (e.key === "Enter" && !approve.hidden && !approve.disabled) { e.preventDefault(); runWalletFlow(); }
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1201
|
+
applyFlowChrome();
|
|
1202
|
+
if (!window.__WALLET_PREVIEW__) {
|
|
1203
|
+
window.addEventListener("load", () => setTimeout(runWalletFlow, 150));
|
|
1204
|
+
} else {
|
|
1205
|
+
window.__walletPreview = { setState, setConfig: (c) => { Object.assign(config, c); applyFlowChrome(); } };
|
|
1206
|
+
setState("connecting");
|
|
1207
|
+
}
|
|
1208
|
+
</script>
|
|
1209
|
+
</body>
|
|
1210
|
+
|
|
1211
|
+
</html>
|