@mysten-incubation/dev-wallet 0.0.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.
Files changed (213) hide show
  1. package/README.md +250 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.107.0/helpers/decorate.mjs +10 -0
  3. package/dist/adapters/base-adapter.d.mts +33 -0
  4. package/dist/adapters/base-adapter.d.mts.map +1 -0
  5. package/dist/adapters/base-adapter.mjs +77 -0
  6. package/dist/adapters/base-adapter.mjs.map +1 -0
  7. package/dist/adapters/browser.d.mts +8 -0
  8. package/dist/adapters/browser.mjs +8 -0
  9. package/dist/adapters/build-managed-account.d.mts +12 -0
  10. package/dist/adapters/build-managed-account.d.mts.map +1 -0
  11. package/dist/adapters/build-managed-account.mjs +30 -0
  12. package/dist/adapters/build-managed-account.mjs.map +1 -0
  13. package/dist/adapters/idb-store.mjs +73 -0
  14. package/dist/adapters/idb-store.mjs.map +1 -0
  15. package/dist/adapters/in-memory-adapter.d.mts +16 -0
  16. package/dist/adapters/in-memory-adapter.d.mts.map +1 -0
  17. package/dist/adapters/in-memory-adapter.mjs +44 -0
  18. package/dist/adapters/in-memory-adapter.mjs.map +1 -0
  19. package/dist/adapters/passkey-adapter.d.mts +31 -0
  20. package/dist/adapters/passkey-adapter.d.mts.map +1 -0
  21. package/dist/adapters/passkey-adapter.mjs +87 -0
  22. package/dist/adapters/passkey-adapter.mjs.map +1 -0
  23. package/dist/adapters/remote-cli-adapter.d.mts +65 -0
  24. package/dist/adapters/remote-cli-adapter.d.mts.map +1 -0
  25. package/dist/adapters/remote-cli-adapter.mjs +299 -0
  26. package/dist/adapters/remote-cli-adapter.mjs.map +1 -0
  27. package/dist/adapters/webcrypto-adapter.d.mts +20 -0
  28. package/dist/adapters/webcrypto-adapter.d.mts.map +1 -0
  29. package/dist/adapters/webcrypto-adapter.mjs +68 -0
  30. package/dist/adapters/webcrypto-adapter.mjs.map +1 -0
  31. package/dist/bin/cli.d.mts +1 -0
  32. package/dist/bin/cli.mjs +183 -0
  33. package/dist/bin/cli.mjs.map +1 -0
  34. package/dist/client/dev-wallet-client.d.mts +57 -0
  35. package/dist/client/dev-wallet-client.d.mts.map +1 -0
  36. package/dist/client/dev-wallet-client.mjs +223 -0
  37. package/dist/client/dev-wallet-client.mjs.map +1 -0
  38. package/dist/client/index.d.mts +3 -0
  39. package/dist/client/index.mjs +4 -0
  40. package/dist/client/request-handler.d.mts +42 -0
  41. package/dist/client/request-handler.d.mts.map +1 -0
  42. package/dist/client/request-handler.mjs +115 -0
  43. package/dist/client/request-handler.mjs.map +1 -0
  44. package/dist/index.d.mts +5 -0
  45. package/dist/index.mjs +4 -0
  46. package/dist/react/components.d.mts +32 -0
  47. package/dist/react/components.d.mts.map +1 -0
  48. package/dist/react/components.mjs +53 -0
  49. package/dist/react/components.mjs.map +1 -0
  50. package/dist/react/context.d.mts +22 -0
  51. package/dist/react/context.d.mts.map +1 -0
  52. package/dist/react/context.mjs +25 -0
  53. package/dist/react/context.mjs.map +1 -0
  54. package/dist/react/index.d.mts +4 -0
  55. package/dist/react/index.mjs +5 -0
  56. package/dist/react/useDevWallet.d.mts +38 -0
  57. package/dist/react/useDevWallet.d.mts.map +1 -0
  58. package/dist/react/useDevWallet.mjs +89 -0
  59. package/dist/react/useDevWallet.mjs.map +1 -0
  60. package/dist/server/cli-signing-middleware.d.mts +22 -0
  61. package/dist/server/cli-signing-middleware.d.mts.map +1 -0
  62. package/dist/server/cli-signing-middleware.mjs +117 -0
  63. package/dist/server/cli-signing-middleware.mjs.map +1 -0
  64. package/dist/server/index.d.mts +2 -0
  65. package/dist/server/index.mjs +3 -0
  66. package/dist/standalone/assets/in-memory-adapter-CBF4h2KD.js +1 -0
  67. package/dist/standalone/assets/main-VE4olb-Q.js +2841 -0
  68. package/dist/standalone/assets/webcrypto-adapter-DysAubFb.js +1 -0
  69. package/dist/standalone/bookmarklet.js +5 -0
  70. package/dist/standalone/index.html +48 -0
  71. package/dist/types.d.mts +55 -0
  72. package/dist/types.d.mts.map +1 -0
  73. package/dist/ui/copy-controller.mjs +43 -0
  74. package/dist/ui/copy-controller.mjs.map +1 -0
  75. package/dist/ui/dev-wallet-account-selector.d.mts +24 -0
  76. package/dist/ui/dev-wallet-account-selector.d.mts.map +1 -0
  77. package/dist/ui/dev-wallet-account-selector.mjs +268 -0
  78. package/dist/ui/dev-wallet-account-selector.mjs.map +1 -0
  79. package/dist/ui/dev-wallet-accounts.d.mts +29 -0
  80. package/dist/ui/dev-wallet-accounts.d.mts.map +1 -0
  81. package/dist/ui/dev-wallet-accounts.mjs +524 -0
  82. package/dist/ui/dev-wallet-accounts.mjs.map +1 -0
  83. package/dist/ui/dev-wallet-balances.d.mts +26 -0
  84. package/dist/ui/dev-wallet-balances.d.mts.map +1 -0
  85. package/dist/ui/dev-wallet-balances.mjs +130 -0
  86. package/dist/ui/dev-wallet-balances.mjs.map +1 -0
  87. package/dist/ui/dev-wallet-connect.d.mts +31 -0
  88. package/dist/ui/dev-wallet-connect.d.mts.map +1 -0
  89. package/dist/ui/dev-wallet-connect.mjs +225 -0
  90. package/dist/ui/dev-wallet-connect.mjs.map +1 -0
  91. package/dist/ui/dev-wallet-dropdown.d.mts +27 -0
  92. package/dist/ui/dev-wallet-dropdown.d.mts.map +1 -0
  93. package/dist/ui/dev-wallet-dropdown.mjs +121 -0
  94. package/dist/ui/dev-wallet-dropdown.mjs.map +1 -0
  95. package/dist/ui/dev-wallet-network-badge.d.mts +21 -0
  96. package/dist/ui/dev-wallet-network-badge.d.mts.map +1 -0
  97. package/dist/ui/dev-wallet-network-badge.mjs +121 -0
  98. package/dist/ui/dev-wallet-network-badge.mjs.map +1 -0
  99. package/dist/ui/dev-wallet-new-account.d.mts +31 -0
  100. package/dist/ui/dev-wallet-new-account.d.mts.map +1 -0
  101. package/dist/ui/dev-wallet-new-account.mjs +577 -0
  102. package/dist/ui/dev-wallet-new-account.mjs.map +1 -0
  103. package/dist/ui/dev-wallet-objects.d.mts +26 -0
  104. package/dist/ui/dev-wallet-objects.d.mts.map +1 -0
  105. package/dist/ui/dev-wallet-objects.mjs +276 -0
  106. package/dist/ui/dev-wallet-objects.mjs.map +1 -0
  107. package/dist/ui/dev-wallet-panel.d.mts +22 -0
  108. package/dist/ui/dev-wallet-panel.d.mts.map +1 -0
  109. package/dist/ui/dev-wallet-panel.mjs +192 -0
  110. package/dist/ui/dev-wallet-panel.mjs.map +1 -0
  111. package/dist/ui/dev-wallet-popup.d.mts +36 -0
  112. package/dist/ui/dev-wallet-popup.d.mts.map +1 -0
  113. package/dist/ui/dev-wallet-popup.mjs +137 -0
  114. package/dist/ui/dev-wallet-popup.mjs.map +1 -0
  115. package/dist/ui/dev-wallet-settings.d.mts +33 -0
  116. package/dist/ui/dev-wallet-settings.d.mts.map +1 -0
  117. package/dist/ui/dev-wallet-settings.mjs +635 -0
  118. package/dist/ui/dev-wallet-settings.mjs.map +1 -0
  119. package/dist/ui/dev-wallet-signing-modal.d.mts +32 -0
  120. package/dist/ui/dev-wallet-signing-modal.d.mts.map +1 -0
  121. package/dist/ui/dev-wallet-signing-modal.mjs +115 -0
  122. package/dist/ui/dev-wallet-signing-modal.mjs.map +1 -0
  123. package/dist/ui/dev-wallet-signing.d.mts +25 -0
  124. package/dist/ui/dev-wallet-signing.d.mts.map +1 -0
  125. package/dist/ui/dev-wallet-signing.mjs +544 -0
  126. package/dist/ui/dev-wallet-signing.mjs.map +1 -0
  127. package/dist/ui/dev-wallet-standalone.d.mts +23 -0
  128. package/dist/ui/dev-wallet-standalone.d.mts.map +1 -0
  129. package/dist/ui/dev-wallet-standalone.mjs +129 -0
  130. package/dist/ui/dev-wallet-standalone.mjs.map +1 -0
  131. package/dist/ui/dev-wallet-tab-bar.d.mts +19 -0
  132. package/dist/ui/dev-wallet-tab-bar.d.mts.map +1 -0
  133. package/dist/ui/dev-wallet-tab-bar.mjs +143 -0
  134. package/dist/ui/dev-wallet-tab-bar.mjs.map +1 -0
  135. package/dist/ui/index.d.mts +17 -0
  136. package/dist/ui/index.mjs +18 -0
  137. package/dist/ui/mount.d.mts +11 -0
  138. package/dist/ui/mount.d.mts.map +1 -0
  139. package/dist/ui/mount.mjs +17 -0
  140. package/dist/ui/mount.mjs.map +1 -0
  141. package/dist/ui/styles.mjs +250 -0
  142. package/dist/ui/styles.mjs.map +1 -0
  143. package/dist/ui/transaction-analyzer.mjs +58 -0
  144. package/dist/ui/transaction-analyzer.mjs.map +1 -0
  145. package/dist/ui/utils.mjs +98 -0
  146. package/dist/ui/utils.mjs.map +1 -0
  147. package/dist/ui/wallet-controller.mjs +275 -0
  148. package/dist/ui/wallet-controller.mjs.map +1 -0
  149. package/dist/wallet/constants.mjs +11 -0
  150. package/dist/wallet/constants.mjs.map +1 -0
  151. package/dist/wallet/dev-wallet.d.mts +118 -0
  152. package/dist/wallet/dev-wallet.d.mts.map +1 -0
  153. package/dist/wallet/dev-wallet.mjs +424 -0
  154. package/dist/wallet/dev-wallet.mjs.map +1 -0
  155. package/dist/wallet/initializer.d.mts +63 -0
  156. package/dist/wallet/initializer.d.mts.map +1 -0
  157. package/dist/wallet/initializer.mjs +75 -0
  158. package/dist/wallet/initializer.mjs.map +1 -0
  159. package/dist/wallet/signing.d.mts +35 -0
  160. package/dist/wallet/signing.d.mts.map +1 -0
  161. package/dist/wallet/signing.mjs +69 -0
  162. package/dist/wallet/signing.mjs.map +1 -0
  163. package/package.json +124 -0
  164. package/src/adapters/base-adapter.ts +93 -0
  165. package/src/adapters/browser.ts +15 -0
  166. package/src/adapters/build-managed-account.ts +33 -0
  167. package/src/adapters/idb-store.ts +87 -0
  168. package/src/adapters/in-memory-adapter.ts +51 -0
  169. package/src/adapters/passkey-adapter.ts +120 -0
  170. package/src/adapters/remote-cli-adapter.ts +388 -0
  171. package/src/adapters/webcrypto-adapter.ts +96 -0
  172. package/src/app/bookmarklet-entry.ts +77 -0
  173. package/src/app/index.html +48 -0
  174. package/src/app/main.ts +245 -0
  175. package/src/app/tsconfig.json +3 -0
  176. package/src/bin/cli.ts +214 -0
  177. package/src/client/dev-wallet-client.ts +280 -0
  178. package/src/client/index.ts +7 -0
  179. package/src/client/request-handler.ts +161 -0
  180. package/src/index.ts +19 -0
  181. package/src/react/components.ts +64 -0
  182. package/src/react/context.ts +38 -0
  183. package/src/react/index.ts +16 -0
  184. package/src/react/useDevWallet.ts +118 -0
  185. package/src/server/cli-signing-middleware.ts +146 -0
  186. package/src/server/index.ts +8 -0
  187. package/src/types.ts +58 -0
  188. package/src/ui/copy-controller.ts +49 -0
  189. package/src/ui/dev-wallet-account-selector.ts +283 -0
  190. package/src/ui/dev-wallet-accounts.ts +578 -0
  191. package/src/ui/dev-wallet-balances.ts +171 -0
  192. package/src/ui/dev-wallet-connect.ts +259 -0
  193. package/src/ui/dev-wallet-dropdown.ts +138 -0
  194. package/src/ui/dev-wallet-network-badge.ts +128 -0
  195. package/src/ui/dev-wallet-new-account.ts +662 -0
  196. package/src/ui/dev-wallet-objects.ts +336 -0
  197. package/src/ui/dev-wallet-panel.ts +207 -0
  198. package/src/ui/dev-wallet-popup.ts +169 -0
  199. package/src/ui/dev-wallet-settings.ts +692 -0
  200. package/src/ui/dev-wallet-signing-modal.ts +137 -0
  201. package/src/ui/dev-wallet-signing.ts +624 -0
  202. package/src/ui/dev-wallet-standalone.ts +136 -0
  203. package/src/ui/dev-wallet-tab-bar.ts +151 -0
  204. package/src/ui/index.ts +26 -0
  205. package/src/ui/mount.ts +21 -0
  206. package/src/ui/styles.ts +252 -0
  207. package/src/ui/transaction-analyzer.ts +60 -0
  208. package/src/ui/utils.ts +118 -0
  209. package/src/ui/wallet-controller.ts +340 -0
  210. package/src/wallet/constants.ts +17 -0
  211. package/src/wallet/dev-wallet.ts +597 -0
  212. package/src/wallet/initializer.ts +124 -0
  213. package/src/wallet/signing.ts +85 -0
@@ -0,0 +1,692 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import type { ReadonlyWalletAccount } from '@mysten/wallet-standard';
5
+ import { css, html, LitElement, nothing } from 'lit';
6
+ import { customElement, property, state } from 'lit/decorators.js';
7
+
8
+ import type { DevWallet } from '../wallet/dev-wallet.js';
9
+ import type { SignerAdapter } from '../types.js';
10
+ import { sectionHeaderStyles, sharedStyles } from './styles.js';
11
+ import { emitEvent, formatAddress, getErrorMessage, NETWORK_COLORS } from './utils.js';
12
+ import './dev-wallet-accounts.js';
13
+
14
+ @customElement('dev-wallet-settings')
15
+ export class DevWalletSettings extends LitElement {
16
+ static override styles = [
17
+ sharedStyles,
18
+ sectionHeaderStyles,
19
+ css`
20
+ :host {
21
+ display: block;
22
+ }
23
+
24
+ .section {
25
+ margin-bottom: 20px;
26
+ }
27
+
28
+ .section:last-child {
29
+ margin-bottom: 0;
30
+ }
31
+
32
+ .network-list {
33
+ display: flex;
34
+ flex-direction: column;
35
+ gap: 4px;
36
+ }
37
+
38
+ .network-item {
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 8px;
42
+ padding: 8px 12px;
43
+ border-radius: var(--dev-wallet-radius-sm);
44
+ border: 1px solid var(--dev-wallet-border);
45
+ background: var(--dev-wallet-secondary);
46
+ }
47
+
48
+ .network-item.active {
49
+ border-color: var(--dev-wallet-primary);
50
+ }
51
+
52
+ .network-dot {
53
+ width: 8px;
54
+ height: 8px;
55
+ border-radius: 50%;
56
+ flex-shrink: 0;
57
+ }
58
+
59
+ .network-name {
60
+ flex: 1;
61
+ font-size: 13px;
62
+ font-weight: var(--dev-wallet-font-weight-medium);
63
+ color: var(--dev-wallet-foreground);
64
+ }
65
+
66
+ .network-info {
67
+ flex: 1;
68
+ min-width: 0;
69
+ }
70
+
71
+ .network-url {
72
+ font-size: 10px;
73
+ color: var(--dev-wallet-muted-foreground);
74
+ font-family: var(--dev-wallet-font-mono);
75
+ overflow: hidden;
76
+ text-overflow: ellipsis;
77
+ white-space: nowrap;
78
+ }
79
+
80
+ .network-url-input {
81
+ width: 100%;
82
+ padding: 3px 6px;
83
+ border-radius: var(--dev-wallet-radius-xs);
84
+ border: 1px solid var(--dev-wallet-primary);
85
+ background: var(--dev-wallet-background);
86
+ color: var(--dev-wallet-foreground);
87
+ font-size: 10px;
88
+ font-family: var(--dev-wallet-font-mono);
89
+ outline: none;
90
+ box-sizing: border-box;
91
+ }
92
+
93
+ .network-actions {
94
+ display: flex;
95
+ gap: 2px;
96
+ flex-shrink: 0;
97
+ }
98
+
99
+ .btn-icon {
100
+ width: 22px;
101
+ height: 22px;
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ border-radius: var(--dev-wallet-radius-xs);
106
+ font-size: 11px;
107
+ color: var(--dev-wallet-muted-foreground);
108
+ }
109
+
110
+ .btn-icon:hover {
111
+ background: var(--dev-wallet-border);
112
+ color: var(--dev-wallet-foreground);
113
+ }
114
+
115
+ .btn-icon-danger:hover {
116
+ color: var(--dev-wallet-destructive);
117
+ }
118
+
119
+ .network-active-badge {
120
+ font-size: 9px;
121
+ padding: 1px 5px;
122
+ border-radius: var(--dev-wallet-radius-2xs);
123
+ background: color-mix(in oklab, var(--dev-wallet-primary) 15%, transparent);
124
+ color: var(--dev-wallet-primary);
125
+ font-weight: var(--dev-wallet-font-weight-semibold);
126
+ text-transform: uppercase;
127
+ }
128
+
129
+ .add-network-form {
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: 8px;
133
+ margin-top: 8px;
134
+ padding: 12px;
135
+ border-radius: var(--dev-wallet-radius-sm);
136
+ border: 1px dashed var(--dev-wallet-border);
137
+ background: var(--dev-wallet-secondary);
138
+ }
139
+
140
+ .form-input {
141
+ width: 100%;
142
+ padding: 6px 8px;
143
+ border-radius: var(--dev-wallet-radius-xs);
144
+ border: 1px solid var(--dev-wallet-input);
145
+ background: var(--dev-wallet-background);
146
+ color: var(--dev-wallet-foreground);
147
+ font-size: 12px;
148
+ font-family: inherit;
149
+ outline: none;
150
+ box-sizing: border-box;
151
+ }
152
+
153
+ .form-input:focus {
154
+ border-color: var(--dev-wallet-primary);
155
+ }
156
+
157
+ .form-input::placeholder {
158
+ color: var(--dev-wallet-muted-foreground);
159
+ }
160
+
161
+ .form-actions {
162
+ display: flex;
163
+ gap: 6px;
164
+ }
165
+
166
+ .btn-sm {
167
+ padding: 5px 10px;
168
+ border-radius: var(--dev-wallet-radius-xs);
169
+ font-size: 11px;
170
+ font-weight: var(--dev-wallet-font-weight-medium);
171
+ }
172
+
173
+ .btn-add {
174
+ background: var(--dev-wallet-primary);
175
+ color: var(--dev-wallet-primary-foreground);
176
+ }
177
+
178
+ .btn-add:disabled {
179
+ opacity: 0.5;
180
+ }
181
+
182
+ .btn-cancel {
183
+ background: var(--dev-wallet-secondary);
184
+ color: var(--dev-wallet-foreground);
185
+ border: 1px solid var(--dev-wallet-border);
186
+ }
187
+
188
+ .btn-toggle {
189
+ font-size: 12px;
190
+ color: var(--dev-wallet-primary);
191
+ padding: 4px 0;
192
+ margin-top: 4px;
193
+ }
194
+
195
+ .btn-toggle:hover {
196
+ text-decoration: underline;
197
+ }
198
+
199
+ .cli-section-column {
200
+ flex-direction: column;
201
+ align-items: flex-start;
202
+ gap: 6px;
203
+ }
204
+
205
+ .cli-header-row {
206
+ display: flex;
207
+ align-items: center;
208
+ gap: 8px;
209
+ width: 100%;
210
+ }
211
+
212
+ .cli-accounts-list {
213
+ width: 100%;
214
+ padding-left: 16px;
215
+ }
216
+
217
+ .cli-accounts-list .network-url {
218
+ padding: 2px 0;
219
+ }
220
+
221
+ .cli-hint {
222
+ padding-left: 16px;
223
+ margin-top: 0;
224
+ font-size: 12px;
225
+ }
226
+
227
+ .cli-unpaired-hint {
228
+ margin-top: 8px;
229
+ }
230
+
231
+ .about {
232
+ font-size: 12px;
233
+ color: var(--dev-wallet-muted-foreground);
234
+ line-height: 1.5;
235
+ }
236
+
237
+ .error {
238
+ font-size: 11px;
239
+ color: var(--dev-wallet-destructive);
240
+ margin-top: 4px;
241
+ }
242
+
243
+ .bookmarklet-link-wrapper {
244
+ margin-top: 8px;
245
+ }
246
+
247
+ .bookmarklet-link {
248
+ display: inline-flex;
249
+ align-items: center;
250
+ gap: 6px;
251
+ padding: 8px 14px;
252
+ border-radius: var(--dev-wallet-radius-sm);
253
+ background: var(--dev-wallet-primary);
254
+ color: var(--dev-wallet-primary-foreground);
255
+ font-size: 13px;
256
+ font-weight: var(--dev-wallet-font-weight-semibold);
257
+ text-decoration: none;
258
+ cursor: grab;
259
+ user-select: none;
260
+ }
261
+
262
+ .bookmarklet-link:hover {
263
+ opacity: 0.9;
264
+ }
265
+
266
+ .bookmarklet-link:active {
267
+ cursor: grabbing;
268
+ }
269
+
270
+ .bookmarklet-url {
271
+ font-family: var(--dev-wallet-font-mono);
272
+ font-size: 10px;
273
+ color: var(--dev-wallet-muted-foreground);
274
+ word-break: break-all;
275
+ user-select: all;
276
+ }
277
+
278
+ .console-snippet {
279
+ position: relative;
280
+ margin-top: 8px;
281
+ padding: 10px 12px;
282
+ border-radius: var(--dev-wallet-radius-sm);
283
+ background: var(--dev-wallet-secondary);
284
+ border: 1px solid var(--dev-wallet-border);
285
+ font-family: var(--dev-wallet-font-mono);
286
+ font-size: 11px;
287
+ color: var(--dev-wallet-foreground);
288
+ line-height: 1.5;
289
+ white-space: pre-wrap;
290
+ word-break: break-all;
291
+ user-select: all;
292
+ }
293
+
294
+ .btn-copy {
295
+ position: absolute;
296
+ top: 6px;
297
+ right: 6px;
298
+ padding: 3px 8px;
299
+ border-radius: var(--dev-wallet-radius-xs);
300
+ background: var(--dev-wallet-border);
301
+ color: var(--dev-wallet-muted-foreground);
302
+ font-size: 10px;
303
+ font-family: inherit;
304
+ cursor: pointer;
305
+ }
306
+
307
+ .btn-copy:hover {
308
+ background: var(--dev-wallet-input);
309
+ color: var(--dev-wallet-foreground);
310
+ }
311
+ `,
312
+ ];
313
+
314
+ @property({ attribute: false })
315
+ wallet: DevWallet | null = null;
316
+
317
+ @property({ attribute: false })
318
+ accounts: readonly ReadonlyWalletAccount[] = [];
319
+
320
+ @property({ attribute: false })
321
+ adapters: SignerAdapter[] = [];
322
+
323
+ @property({ type: String })
324
+ activeAddress = '';
325
+
326
+ @property({ type: String })
327
+ bookmarkletOrigin = '';
328
+
329
+ @state()
330
+ private _showAddNetwork = false;
331
+
332
+ @state()
333
+ private _networkName = '';
334
+
335
+ @state()
336
+ private _networkUrl = '';
337
+
338
+ @state()
339
+ private _error: string | null = null;
340
+
341
+ @state()
342
+ private _editingNetwork: string | null = null;
343
+
344
+ @state()
345
+ private _editingUrl = '';
346
+
347
+ @state()
348
+ private _copied = false;
349
+
350
+ override render() {
351
+ return html`
352
+ <div class="section">${this.#renderNetworks()}</div>
353
+ ${this.#hasCliAdapter()
354
+ ? html`<div class="section">${this.#renderCliSigner()}</div>`
355
+ : nothing}
356
+ <div class="section">${this.#renderAccounts()}</div>
357
+ <div class="section">${this.#renderBookmarklet()}</div>
358
+ <div class="section">${this.#renderAbout()}</div>
359
+ `;
360
+ }
361
+
362
+ #renderNetworks() {
363
+ if (!this.wallet) return nothing;
364
+
365
+ const networks = this.wallet.availableNetworks;
366
+ const activeNetwork = this.wallet.activeNetwork;
367
+ const urls = this.wallet.networkUrls;
368
+
369
+ return html`
370
+ <h3 class="section-header">Networks</h3>
371
+ <div class="network-list">
372
+ ${networks.map((name) => {
373
+ const color = NETWORK_COLORS[name] ?? '#6b7280';
374
+ const isActive = name === activeNetwork;
375
+ const isEditing = this._editingNetwork === name;
376
+ return html`
377
+ <div class="network-item ${isActive ? 'active' : ''}">
378
+ <span class="network-dot" style="background: ${color}"></span>
379
+ <div class="network-info">
380
+ <span class="network-name">${name}</span>
381
+ ${isEditing
382
+ ? html`<input
383
+ class="network-url-input"
384
+ type="text"
385
+ .value=${this._editingUrl}
386
+ @input=${(e: InputEvent) => {
387
+ this._editingUrl = (e.target as HTMLInputElement).value;
388
+ }}
389
+ @keydown=${(e: KeyboardEvent) => {
390
+ if (e.key === 'Enter') this.#saveNetworkUrl(name);
391
+ if (e.key === 'Escape') this.#cancelEditNetwork();
392
+ }}
393
+ />`
394
+ : html`<span class="network-url" title=${urls[name] ?? ''}
395
+ >${urls[name] ?? ''}</span
396
+ >`}
397
+ </div>
398
+ <div class="network-actions">
399
+ ${isEditing
400
+ ? html`
401
+ <button
402
+ class="btn-icon"
403
+ title="Save"
404
+ aria-label="Save URL"
405
+ @click=${() => this.#saveNetworkUrl(name)}
406
+ >
407
+ &#10003;
408
+ </button>
409
+ <button
410
+ class="btn-icon"
411
+ title="Cancel"
412
+ aria-label="Cancel editing"
413
+ @click=${this.#cancelEditNetwork}
414
+ >
415
+ &#10005;
416
+ </button>
417
+ `
418
+ : html`
419
+ <button
420
+ class="btn-icon"
421
+ title="Edit URL"
422
+ aria-label="Edit network URL"
423
+ @click=${() => this.#startEditNetwork(name, urls[name] ?? '')}
424
+ >
425
+ &#9998;
426
+ </button>
427
+ ${!isActive
428
+ ? html`<button
429
+ class="btn-icon btn-icon-danger"
430
+ title="Remove"
431
+ aria-label="Remove network"
432
+ @click=${() => this.#removeNetwork(name)}
433
+ >
434
+ &#10005;
435
+ </button>`
436
+ : nothing}
437
+ `}
438
+ ${isActive ? html`<span class="network-active-badge">Active</span>` : nothing}
439
+ </div>
440
+ </div>
441
+ `;
442
+ })}
443
+ </div>
444
+ ${this._showAddNetwork
445
+ ? this.#renderAddNetworkForm()
446
+ : html`
447
+ <button
448
+ class="btn-toggle"
449
+ @click=${() => {
450
+ this._showAddNetwork = true;
451
+ }}
452
+ >
453
+ + Add Network
454
+ </button>
455
+ `}
456
+ `;
457
+ }
458
+
459
+ #renderAddNetworkForm() {
460
+ return html`
461
+ <div class="add-network-form">
462
+ <input
463
+ class="form-input"
464
+ type="text"
465
+ placeholder="Network name (e.g. custom)"
466
+ .value=${this._networkName}
467
+ @input=${(e: InputEvent) => {
468
+ this._networkName = (e.target as HTMLInputElement).value;
469
+ this._error = null;
470
+ }}
471
+ />
472
+ <input
473
+ class="form-input"
474
+ type="text"
475
+ placeholder="gRPC URL (e.g. http://localhost:9000)"
476
+ .value=${this._networkUrl}
477
+ @input=${(e: InputEvent) => {
478
+ this._networkUrl = (e.target as HTMLInputElement).value;
479
+ this._error = null;
480
+ }}
481
+ @keydown=${(e: KeyboardEvent) => {
482
+ if (e.key === 'Enter') this.#addNetwork();
483
+ if (e.key === 'Escape') this.#cancelAddNetwork();
484
+ }}
485
+ />
486
+ ${this._error ? html`<div class="error">${this._error}</div>` : nothing}
487
+ <div class="form-actions">
488
+ <button
489
+ class="btn-sm btn-add"
490
+ ?disabled=${!this._networkName.trim() || !this._networkUrl.trim()}
491
+ @click=${this.#addNetwork}
492
+ >
493
+ Add
494
+ </button>
495
+ <button class="btn-sm btn-cancel" @click=${this.#cancelAddNetwork}>Cancel</button>
496
+ </div>
497
+ </div>
498
+ `;
499
+ }
500
+
501
+ #hasCliAdapter(): boolean {
502
+ return this.adapters.some((a) => a.id === 'remote-cli');
503
+ }
504
+
505
+ #renderCliSigner() {
506
+ const cliAdapter = this.adapters.find((a) => a.id === 'remote-cli');
507
+ if (!cliAdapter) return nothing;
508
+
509
+ const isPaired = 'isPaired' in cliAdapter && (cliAdapter as { isPaired: boolean }).isPaired;
510
+ const cliAccounts = cliAdapter.getAccounts();
511
+
512
+ return html`
513
+ <h3 class="section-header">CLI Signer</h3>
514
+ ${isPaired
515
+ ? html`
516
+ <div class="network-item active cli-section-column">
517
+ <div class="cli-header-row">
518
+ <span
519
+ class="network-dot"
520
+ style="background: var(--dev-wallet-status-connected)"
521
+ ></span>
522
+ <span class="network-name">Connected</span>
523
+ ${cliAccounts.length > 0
524
+ ? html`<span class="network-active-badge">${cliAccounts.length} imported</span>`
525
+ : nothing}
526
+ </div>
527
+ ${cliAccounts.length > 0
528
+ ? html`<div class="cli-accounts-list">
529
+ ${cliAccounts.map(
530
+ (acc) => html`
531
+ <div class="network-url">${acc.label} (${formatAddress(acc.address)})</div>
532
+ `,
533
+ )}
534
+ </div>`
535
+ : html`<div class="about cli-hint">Use + Add above to import CLI accounts.</div>`}
536
+ </div>
537
+ `
538
+ : html`
539
+ <div class="network-item">
540
+ <span
541
+ class="network-dot"
542
+ style="background: var(--dev-wallet-status-disconnected)"
543
+ ></span>
544
+ <span class="network-name" style="color: var(--dev-wallet-muted-foreground)"
545
+ >Not connected</span
546
+ >
547
+ </div>
548
+ <div class="about cli-unpaired-hint">
549
+ Open the token URL from your terminal to connect CLI accounts.
550
+ </div>
551
+ `}
552
+ `;
553
+ }
554
+
555
+ #renderAccounts() {
556
+ return html`
557
+ <dev-wallet-accounts
558
+ exportparts="account-list: accounts-account-list, add-button: accounts-add-button, empty-state: accounts-empty-state"
559
+ .accounts=${this.accounts}
560
+ .adapters=${this.adapters}
561
+ .activeAddress=${this.activeAddress}
562
+ ></dev-wallet-accounts>
563
+ `;
564
+ }
565
+
566
+ #renderBookmarklet() {
567
+ if (!this.bookmarkletOrigin) return nothing;
568
+ const origin = this.bookmarkletOrigin;
569
+
570
+ const bookmarkletJs = `${origin}/bookmarklet.js`;
571
+ const bookmarkletHref = `javascript:void(document.head.appendChild(Object.assign(document.createElement('script'),{src:'${bookmarkletJs}'})))`;
572
+ const consoleSnippet = `var s=document.createElement('script');s.src='${bookmarkletJs}';document.head.appendChild(s);`;
573
+
574
+ return html`
575
+ <h3 class="section-header">Bookmarklet</h3>
576
+ <div class="about">
577
+ Drag this link to your bookmarks bar, then click it on any dApp to inject the wallet:
578
+ </div>
579
+ <div class="bookmarklet-link-wrapper">
580
+ <a
581
+ class="bookmarklet-link"
582
+ href=${bookmarkletHref}
583
+ title="Drag to bookmarks bar"
584
+ @click=${(e: MouseEvent) => e.preventDefault()}
585
+ >
586
+ Dev Wallet
587
+ </a>
588
+ </div>
589
+ <div class="about" style="margin-top: 12px">Or paste this in the browser console:</div>
590
+ <div class="console-snippet">
591
+ ${consoleSnippet}
592
+ <button class="btn-copy" @click=${() => this.#copySnippet(consoleSnippet)}>
593
+ ${this._copied ? 'Copied!' : 'Copy'}
594
+ </button>
595
+ </div>
596
+ <div class="about" style="margin-top: 8px">
597
+ Or add this script to your page:<br />
598
+ <code class="bookmarklet-url">${bookmarkletJs}</code>
599
+ </div>
600
+ `;
601
+ }
602
+
603
+ #copySnippet(text: string) {
604
+ navigator.clipboard.writeText(text).then(() => {
605
+ this._copied = true;
606
+ setTimeout(() => {
607
+ this._copied = false;
608
+ }, 2000);
609
+ });
610
+ }
611
+
612
+ #renderAbout() {
613
+ return html`
614
+ <h3 class="section-header">About</h3>
615
+ <div class="about">
616
+ <strong>${this.wallet?.name ?? 'Dev Wallet'}</strong><br />
617
+ A development wallet for testing Sui dApps.<br />
618
+ ${this.wallet
619
+ ? html`${this.wallet.accounts.length} account(s) across ${this.wallet.adapters.length}
620
+ adapter(s)`
621
+ : nothing}
622
+ </div>
623
+ `;
624
+ }
625
+
626
+ #addNetwork() {
627
+ if (!this.wallet) return;
628
+
629
+ const name = this._networkName.trim();
630
+ const url = this._networkUrl.trim();
631
+
632
+ if (!name || !url) return;
633
+
634
+ if (this.wallet.availableNetworks.includes(name)) {
635
+ this._error = `Network "${name}" already exists`;
636
+ return;
637
+ }
638
+
639
+ try {
640
+ this.wallet.addNetwork(name, url);
641
+ this._networkName = '';
642
+ this._networkUrl = '';
643
+ this._showAddNetwork = false;
644
+ this._error = null;
645
+ emitEvent(this, 'network-added', { name, url });
646
+ } catch (err) {
647
+ this._error = getErrorMessage(err, 'Failed to add network');
648
+ }
649
+ }
650
+
651
+ #cancelAddNetwork() {
652
+ this._showAddNetwork = false;
653
+ this._networkName = '';
654
+ this._networkUrl = '';
655
+ this._error = null;
656
+ }
657
+
658
+ #startEditNetwork(name: string, url: string) {
659
+ this._editingNetwork = name;
660
+ this._editingUrl = url;
661
+ }
662
+
663
+ #saveNetworkUrl(name: string) {
664
+ if (!this.wallet) return;
665
+ const url = this._editingUrl.trim();
666
+ if (!url) return;
667
+
668
+ try {
669
+ this.wallet.addNetwork(name, url);
670
+ this._editingNetwork = null;
671
+ this._editingUrl = '';
672
+ } catch (error) {
673
+ this._error = error instanceof Error ? error.message : 'Invalid URL';
674
+ }
675
+ }
676
+
677
+ #cancelEditNetwork() {
678
+ this._editingNetwork = null;
679
+ this._editingUrl = '';
680
+ }
681
+
682
+ #removeNetwork(name: string) {
683
+ if (!this.wallet) return;
684
+ this.wallet.removeNetwork(name);
685
+ }
686
+ }
687
+
688
+ declare global {
689
+ interface HTMLElementTagNameMap {
690
+ 'dev-wallet-settings': DevWalletSettings;
691
+ }
692
+ }