@mysten-incubation/dev-wallet 0.0.1 → 0.3.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 (182) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/LICENSE +189 -0
  3. package/dist/_virtual/{_@oxc-project_runtime@0.107.0 → _@oxc-project_runtime@0.127.0}/helpers/decorate.mjs +2 -3
  4. package/dist/adapters/base-adapter.mjs +6 -7
  5. package/dist/adapters/base-adapter.mjs.map +1 -1
  6. package/dist/adapters/browser.d.mts +4 -1
  7. package/dist/adapters/browser.mjs +4 -2
  8. package/dist/adapters/build-managed-account.mjs +8 -10
  9. package/dist/adapters/build-managed-account.mjs.map +1 -1
  10. package/dist/adapters/devstack-adapter.d.mts +111 -0
  11. package/dist/adapters/devstack-adapter.d.mts.map +1 -0
  12. package/dist/adapters/devstack-adapter.mjs +224 -0
  13. package/dist/adapters/devstack-adapter.mjs.map +1 -0
  14. package/dist/adapters/devstack-paths.d.mts +11 -0
  15. package/dist/adapters/devstack-paths.d.mts.map +1 -0
  16. package/dist/adapters/devstack-paths.mjs +11 -0
  17. package/dist/adapters/devstack-paths.mjs.map +1 -0
  18. package/dist/adapters/fork-relay.d.mts +109 -0
  19. package/dist/adapters/fork-relay.d.mts.map +1 -0
  20. package/dist/adapters/fork-relay.mjs +208 -0
  21. package/dist/adapters/fork-relay.mjs.map +1 -0
  22. package/dist/adapters/idb-store.mjs +12 -16
  23. package/dist/adapters/idb-store.mjs.map +1 -1
  24. package/dist/adapters/in-memory-adapter.mjs +4 -10
  25. package/dist/adapters/in-memory-adapter.mjs.map +1 -1
  26. package/dist/adapters/passkey-adapter.mjs +4 -12
  27. package/dist/adapters/passkey-adapter.mjs.map +1 -1
  28. package/dist/adapters/remote-cli-adapter.mjs +37 -72
  29. package/dist/adapters/remote-cli-adapter.mjs.map +1 -1
  30. package/dist/adapters/webcrypto-adapter.mjs +2 -4
  31. package/dist/adapters/webcrypto-adapter.mjs.map +1 -1
  32. package/dist/bin/cli.mjs +9 -22
  33. package/dist/bin/cli.mjs.map +1 -1
  34. package/dist/client/dev-wallet-client.mjs +13 -28
  35. package/dist/client/dev-wallet-client.mjs.map +1 -1
  36. package/dist/client/index.mjs +1 -2
  37. package/dist/client/request-handler.mjs +36 -42
  38. package/dist/client/request-handler.mjs.map +1 -1
  39. package/dist/index.mjs +1 -2
  40. package/dist/react/components.d.mts +9 -9
  41. package/dist/react/components.d.mts.map +1 -1
  42. package/dist/react/components.mjs +2 -5
  43. package/dist/react/components.mjs.map +1 -1
  44. package/dist/react/context.d.mts +3 -3
  45. package/dist/react/context.d.mts.map +1 -1
  46. package/dist/react/context.mjs +3 -8
  47. package/dist/react/context.mjs.map +1 -1
  48. package/dist/react/index.mjs +1 -2
  49. package/dist/react/useDevWallet.d.mts +3 -0
  50. package/dist/react/useDevWallet.d.mts.map +1 -1
  51. package/dist/react/useDevWallet.mjs +9 -14
  52. package/dist/react/useDevWallet.mjs.map +1 -1
  53. package/dist/server/cli-signing-middleware.mjs +7 -20
  54. package/dist/server/cli-signing-middleware.mjs.map +1 -1
  55. package/dist/server/index.mjs +1 -2
  56. package/dist/standalone/assets/{in-memory-adapter-CBF4h2KD.js → in-memory-adapter-qRkNfj9O.js} +1 -1
  57. package/dist/standalone/assets/main-DDltQnzR.js +3954 -0
  58. package/dist/standalone/assets/{webcrypto-adapter-DysAubFb.js → webcrypto-adapter-FejcrL9x.js} +1 -1
  59. package/dist/standalone/index.html +11 -12
  60. package/dist/ui/copy-controller.mjs +3 -3
  61. package/dist/ui/copy-controller.mjs.map +1 -1
  62. package/dist/ui/dev-wallet-account-selector.d.mts +3 -4
  63. package/dist/ui/dev-wallet-account-selector.d.mts.map +1 -1
  64. package/dist/ui/dev-wallet-account-selector.mjs +48 -25
  65. package/dist/ui/dev-wallet-account-selector.mjs.map +1 -1
  66. package/dist/ui/dev-wallet-accounts.d.mts +9 -4
  67. package/dist/ui/dev-wallet-accounts.d.mts.map +1 -1
  68. package/dist/ui/dev-wallet-accounts.mjs +62 -140
  69. package/dist/ui/dev-wallet-accounts.mjs.map +1 -1
  70. package/dist/ui/dev-wallet-balances.d.mts +10 -3
  71. package/dist/ui/dev-wallet-balances.d.mts.map +1 -1
  72. package/dist/ui/dev-wallet-balances.mjs +241 -43
  73. package/dist/ui/dev-wallet-balances.mjs.map +1 -1
  74. package/dist/ui/dev-wallet-connect.d.mts +3 -3
  75. package/dist/ui/dev-wallet-connect.d.mts.map +1 -1
  76. package/dist/ui/dev-wallet-connect.mjs +24 -16
  77. package/dist/ui/dev-wallet-connect.mjs.map +1 -1
  78. package/dist/ui/dev-wallet-dropdown.d.mts +3 -3
  79. package/dist/ui/dev-wallet-dropdown.d.mts.map +1 -1
  80. package/dist/ui/dev-wallet-dropdown.mjs +37 -47
  81. package/dist/ui/dev-wallet-dropdown.mjs.map +1 -1
  82. package/dist/ui/dev-wallet-fork-panel.d.mts +43 -0
  83. package/dist/ui/dev-wallet-fork-panel.d.mts.map +1 -0
  84. package/dist/ui/dev-wallet-fork-panel.mjs +500 -0
  85. package/dist/ui/dev-wallet-fork-panel.mjs.map +1 -0
  86. package/dist/ui/dev-wallet-network-badge.d.mts +3 -4
  87. package/dist/ui/dev-wallet-network-badge.d.mts.map +1 -1
  88. package/dist/ui/dev-wallet-network-badge.mjs +52 -21
  89. package/dist/ui/dev-wallet-network-badge.mjs.map +1 -1
  90. package/dist/ui/dev-wallet-new-account.d.mts +3 -4
  91. package/dist/ui/dev-wallet-new-account.d.mts.map +1 -1
  92. package/dist/ui/dev-wallet-new-account.mjs +31 -105
  93. package/dist/ui/dev-wallet-new-account.mjs.map +1 -1
  94. package/dist/ui/dev-wallet-objects.d.mts +3 -3
  95. package/dist/ui/dev-wallet-objects.d.mts.map +1 -1
  96. package/dist/ui/dev-wallet-objects.mjs +76 -39
  97. package/dist/ui/dev-wallet-objects.mjs.map +1 -1
  98. package/dist/ui/dev-wallet-panel.d.mts +24 -4
  99. package/dist/ui/dev-wallet-panel.d.mts.map +1 -1
  100. package/dist/ui/dev-wallet-panel.mjs +247 -64
  101. package/dist/ui/dev-wallet-panel.mjs.map +1 -1
  102. package/dist/ui/dev-wallet-popup.d.mts +3 -5
  103. package/dist/ui/dev-wallet-popup.d.mts.map +1 -1
  104. package/dist/ui/dev-wallet-popup.mjs +19 -15
  105. package/dist/ui/dev-wallet-popup.mjs.map +1 -1
  106. package/dist/ui/dev-wallet-settings.d.mts +3 -4
  107. package/dist/ui/dev-wallet-settings.d.mts.map +1 -1
  108. package/dist/ui/dev-wallet-settings.mjs +149 -97
  109. package/dist/ui/dev-wallet-settings.mjs.map +1 -1
  110. package/dist/ui/dev-wallet-signing-modal.d.mts +11 -4
  111. package/dist/ui/dev-wallet-signing-modal.d.mts.map +1 -1
  112. package/dist/ui/dev-wallet-signing-modal.mjs +46 -18
  113. package/dist/ui/dev-wallet-signing-modal.mjs.map +1 -1
  114. package/dist/ui/dev-wallet-signing.d.mts +9 -3
  115. package/dist/ui/dev-wallet-signing.d.mts.map +1 -1
  116. package/dist/ui/dev-wallet-signing.mjs +119 -130
  117. package/dist/ui/dev-wallet-signing.mjs.map +1 -1
  118. package/dist/ui/dev-wallet-standalone.d.mts +8 -3
  119. package/dist/ui/dev-wallet-standalone.d.mts.map +1 -1
  120. package/dist/ui/dev-wallet-standalone.mjs +303 -38
  121. package/dist/ui/dev-wallet-standalone.mjs.map +1 -1
  122. package/dist/ui/dev-wallet-tab-bar.d.mts +13 -5
  123. package/dist/ui/dev-wallet-tab-bar.d.mts.map +1 -1
  124. package/dist/ui/dev-wallet-tab-bar.mjs +143 -82
  125. package/dist/ui/dev-wallet-tab-bar.mjs.map +1 -1
  126. package/dist/ui/index.d.mts +3 -2
  127. package/dist/ui/index.mjs +2 -2
  128. package/dist/ui/mount.d.mts +14 -1
  129. package/dist/ui/mount.d.mts.map +1 -1
  130. package/dist/ui/mount.mjs +5 -2
  131. package/dist/ui/mount.mjs.map +1 -1
  132. package/dist/ui/styles.mjs +428 -66
  133. package/dist/ui/styles.mjs.map +1 -1
  134. package/dist/ui/transaction-analyzer.mjs +19 -30
  135. package/dist/ui/transaction-analyzer.mjs.map +1 -1
  136. package/dist/ui/utils.d.mts +59 -0
  137. package/dist/ui/utils.d.mts.map +1 -0
  138. package/dist/ui/utils.mjs +42 -15
  139. package/dist/ui/utils.mjs.map +1 -1
  140. package/dist/ui/wallet-controller.mjs +89 -20
  141. package/dist/ui/wallet-controller.mjs.map +1 -1
  142. package/dist/wallet/constants.d.mts +9 -0
  143. package/dist/wallet/constants.d.mts.map +1 -0
  144. package/dist/wallet/constants.mjs +1 -1
  145. package/dist/wallet/dev-wallet.mjs +42 -99
  146. package/dist/wallet/dev-wallet.mjs.map +1 -1
  147. package/dist/wallet/initializer.d.mts +3 -0
  148. package/dist/wallet/initializer.d.mts.map +1 -1
  149. package/dist/wallet/initializer.mjs +9 -14
  150. package/dist/wallet/initializer.mjs.map +1 -1
  151. package/dist/wallet/signing.mjs +8 -21
  152. package/dist/wallet/signing.mjs.map +1 -1
  153. package/package.json +8 -6
  154. package/src/adapters/browser.ts +21 -0
  155. package/src/adapters/devstack-adapter.ts +342 -0
  156. package/src/adapters/devstack-paths.ts +15 -0
  157. package/src/adapters/fork-relay.ts +321 -0
  158. package/src/app/index.html +10 -11
  159. package/src/react/useDevWallet.ts +5 -1
  160. package/src/ui/dev-wallet-account-selector.ts +44 -17
  161. package/src/ui/dev-wallet-accounts.ts +87 -124
  162. package/src/ui/dev-wallet-balances.ts +248 -27
  163. package/src/ui/dev-wallet-connect.ts +19 -8
  164. package/src/ui/dev-wallet-dropdown.ts +7 -5
  165. package/src/ui/dev-wallet-fork-panel.ts +591 -0
  166. package/src/ui/dev-wallet-network-badge.ts +49 -10
  167. package/src/ui/dev-wallet-new-account.ts +21 -62
  168. package/src/ui/dev-wallet-objects.ts +59 -19
  169. package/src/ui/dev-wallet-panel.ts +261 -42
  170. package/src/ui/dev-wallet-popup.ts +12 -6
  171. package/src/ui/dev-wallet-settings.ts +159 -94
  172. package/src/ui/dev-wallet-signing-modal.ts +47 -7
  173. package/src/ui/dev-wallet-signing.ts +124 -97
  174. package/src/ui/dev-wallet-standalone.ts +310 -22
  175. package/src/ui/dev-wallet-tab-bar.ts +132 -70
  176. package/src/ui/index.ts +3 -0
  177. package/src/ui/mount.ts +23 -1
  178. package/src/ui/styles.ts +434 -58
  179. package/src/ui/utils.ts +66 -0
  180. package/src/ui/wallet-controller.ts +103 -5
  181. package/src/wallet/initializer.ts +7 -1
  182. package/dist/standalone/assets/main-VE4olb-Q.js +0 -2841
@@ -7,8 +7,28 @@ import { customElement, property, state } from 'lit/decorators.js';
7
7
 
8
8
  import type { SignerAdapter } from '../types.js';
9
9
  import { CopyController } from './copy-controller.js';
10
- import { actionButtonStyles, sectionHeaderStyles, sharedStyles } from './styles.js';
11
- import { emitEvent, findAdapterForAddress, formatAddress, getErrorMessage } from './utils.js';
10
+ import {
11
+ actionButtonStyles,
12
+ avatarStyles,
13
+ badgeStyles,
14
+ cardItemStyles,
15
+ copyableTextStyles,
16
+ dialogStyles,
17
+ formInputStyles,
18
+ iconButtonStyles,
19
+ inlineErrorStyles,
20
+ listContainerStyles,
21
+ monoTruncateStyles,
22
+ sectionHeaderStyles,
23
+ sharedStyles,
24
+ } from './styles.js';
25
+ import {
26
+ emitEvent,
27
+ findAdapterForAddress,
28
+ formatAddress,
29
+ getErrorMessage,
30
+ isForkNetwork,
31
+ } from './utils.js';
12
32
  import './dev-wallet-new-account.js';
13
33
 
14
34
  @customElement('dev-wallet-accounts')
@@ -17,11 +37,17 @@ export class DevWalletAccounts extends LitElement {
17
37
  sharedStyles,
18
38
  sectionHeaderStyles,
19
39
  actionButtonStyles,
40
+ cardItemStyles,
41
+ listContainerStyles,
42
+ copyableTextStyles,
43
+ monoTruncateStyles,
44
+ iconButtonStyles,
45
+ inlineErrorStyles,
46
+ badgeStyles,
47
+ avatarStyles,
48
+ dialogStyles,
49
+ formInputStyles,
20
50
  css`
21
- :host {
22
- display: block;
23
- }
24
-
25
51
  .accounts-header {
26
52
  display: flex;
27
53
  justify-content: space-between;
@@ -34,30 +60,22 @@ export class DevWalletAccounts extends LitElement {
34
60
  }
35
61
 
36
62
  .add-btn {
63
+ height: 26px;
37
64
  font-size: 12px;
38
65
  color: var(--dev-wallet-primary);
39
- padding: 4px 8px;
40
- border-radius: var(--dev-wallet-radius-sm);
66
+ padding: 0 8px;
67
+ border-radius: var(--dev-wallet-radius);
68
+ border: 1px solid var(--dev-wallet-border);
41
69
  }
42
70
 
43
71
  .add-btn:hover {
44
- background: color-mix(in oklab, var(--dev-wallet-primary) 15%, transparent);
45
- }
46
-
47
- .account-list {
48
- display: flex;
49
- flex-direction: column;
50
- gap: 4px;
72
+ background: var(--dev-wallet-accent-fade);
73
+ border-color: var(--dev-wallet-border-strong);
51
74
  }
52
75
 
53
76
  .account-item {
54
- display: flex;
55
- align-items: center;
56
77
  gap: 10px;
57
- padding: 10px 12px;
58
- border-radius: var(--dev-wallet-radius-sm);
59
- border: 1px solid var(--dev-wallet-border);
60
- background: var(--dev-wallet-secondary);
78
+ padding: 9px 10px;
61
79
  width: 100%;
62
80
  text-align: left;
63
81
  }
@@ -67,22 +85,13 @@ export class DevWalletAccounts extends LitElement {
67
85
  }
68
86
 
69
87
  .account-item.active {
70
- border-color: var(--dev-wallet-primary);
71
- background: color-mix(in oklab, var(--dev-wallet-primary) 10%, var(--dev-wallet-secondary));
88
+ background: var(--dev-wallet-accent-fade);
72
89
  }
73
90
 
74
91
  .account-avatar {
75
92
  width: 32px;
76
93
  height: 32px;
77
- border-radius: 50%;
78
- background: var(--dev-wallet-primary);
79
- display: flex;
80
- align-items: center;
81
- justify-content: center;
82
94
  font-size: 14px;
83
- font-weight: var(--dev-wallet-font-weight-semibold);
84
- color: var(--dev-wallet-primary-foreground);
85
- flex-shrink: 0;
86
95
  }
87
96
 
88
97
  .account-info {
@@ -93,28 +102,11 @@ export class DevWalletAccounts extends LitElement {
93
102
  .account-label {
94
103
  font-size: 14px;
95
104
  font-weight: var(--dev-wallet-font-weight-medium);
96
- color: var(--dev-wallet-foreground);
97
105
  }
98
106
 
99
107
  .account-address {
100
108
  font-size: 12px;
101
- color: var(--dev-wallet-muted-foreground);
102
- font-family: var(--dev-wallet-font-mono);
103
- overflow: hidden;
104
- text-overflow: ellipsis;
105
- white-space: nowrap;
106
- cursor: pointer;
107
- border-radius: var(--dev-wallet-radius-2xs);
108
109
  padding: 1px 2px;
109
- transition: background 0.15s;
110
- }
111
-
112
- .account-address:hover {
113
- background: color-mix(in oklab, var(--dev-wallet-primary) 15%, transparent);
114
- }
115
-
116
- .account-address.copied {
117
- color: var(--dev-wallet-positive);
118
110
  }
119
111
 
120
112
  .account-label-row {
@@ -123,26 +115,28 @@ export class DevWalletAccounts extends LitElement {
123
115
  gap: 4px;
124
116
  }
125
117
 
126
- .edit-label-btn {
118
+ .edit-label-btn,
119
+ .delete-btn {
127
120
  width: 18px;
128
121
  height: 18px;
129
- display: inline-flex;
130
- align-items: center;
131
- justify-content: center;
132
122
  border-radius: var(--dev-wallet-radius-2xs);
133
123
  font-size: 11px;
134
- color: var(--dev-wallet-muted-foreground);
135
124
  opacity: 0;
136
125
  transition: opacity 0.15s;
137
126
  }
138
127
 
139
- .account-item:hover .edit-label-btn {
128
+ .delete-btn {
129
+ flex-shrink: 0;
130
+ }
131
+
132
+ .account-item:hover .edit-label-btn,
133
+ .account-item:hover .delete-btn {
140
134
  opacity: 1;
141
135
  }
142
136
 
143
- .edit-label-btn:hover {
144
- background: var(--dev-wallet-border);
145
- color: var(--dev-wallet-foreground);
137
+ .delete-btn:hover {
138
+ background: color-mix(in oklab, var(--dev-wallet-destructive) 20%, transparent);
139
+ color: var(--dev-wallet-destructive);
146
140
  }
147
141
 
148
142
  .edit-label-input {
@@ -150,75 +144,23 @@ export class DevWalletAccounts extends LitElement {
150
144
  border-radius: var(--dev-wallet-radius-2xs);
151
145
  border: 1px solid var(--dev-wallet-primary);
152
146
  background: var(--dev-wallet-background);
153
- color: var(--dev-wallet-foreground);
154
147
  font-size: 13px;
155
- font-family: inherit;
156
- outline: none;
157
- width: 100%;
158
148
  }
159
149
 
160
150
  .account-badge {
161
- font-size: 10px;
162
- padding: 1px 6px;
163
- border-radius: var(--dev-wallet-radius-xs);
164
- background: var(--dev-wallet-secondary);
165
- border: 1px solid var(--dev-wallet-border);
166
- color: var(--dev-wallet-muted-foreground);
167
- font-weight: var(--dev-wallet-font-weight-medium);
168
- text-transform: uppercase;
169
- letter-spacing: 0.3px;
170
- white-space: nowrap;
171
- }
172
-
173
- .delete-btn {
174
- width: 18px;
175
- height: 18px;
151
+ height: 16px;
176
152
  display: inline-flex;
177
153
  align-items: center;
178
- justify-content: center;
179
- border-radius: var(--dev-wallet-radius-2xs);
180
- font-size: 11px;
181
- color: var(--dev-wallet-muted-foreground);
182
- opacity: 0;
183
- transition: opacity 0.15s;
184
- flex-shrink: 0;
185
- }
186
-
187
- .account-item:hover .delete-btn {
188
- opacity: 1;
189
- }
190
-
191
- .delete-btn:hover {
192
- background: color-mix(in oklab, var(--dev-wallet-destructive) 20%, transparent);
193
- color: var(--dev-wallet-destructive);
194
- }
195
-
196
- .confirm-dialog:not([open]) {
197
- display: none;
154
+ padding: 0 5px;
155
+ border-radius: 999px;
156
+ background: var(--dev-wallet-bg-3);
157
+ border: 1px solid var(--dev-wallet-border);
158
+ color: var(--dev-wallet-text-3);
198
159
  }
199
160
 
200
161
  .confirm-dialog {
201
162
  width: 300px;
202
- max-width: calc(100vw - 32px);
203
- border-radius: var(--dev-wallet-radius-xl);
204
- background: var(--dev-wallet-background);
205
- border: 1px solid var(--dev-wallet-border);
206
- box-shadow: var(--dev-wallet-shadow-lg);
207
163
  padding: 20px;
208
- display: flex;
209
- flex-direction: column;
210
- color: inherit;
211
- }
212
-
213
- .confirm-dialog::backdrop {
214
- background: color-mix(in oklab, oklch(0 0 0) 50%, transparent);
215
- }
216
-
217
- .confirm-title {
218
- font-size: 16px;
219
- font-weight: var(--dev-wallet-font-weight-semibold);
220
- color: var(--dev-wallet-foreground);
221
- margin-bottom: 12px;
222
164
  }
223
165
 
224
166
  .confirm-body {
@@ -230,8 +172,8 @@ export class DevWalletAccounts extends LitElement {
230
172
 
231
173
  .confirm-account {
232
174
  padding: 8px 10px;
233
- border-radius: var(--dev-wallet-radius-sm);
234
- background: var(--dev-wallet-secondary);
175
+ border-radius: var(--dev-wallet-radius-lg);
176
+ background: var(--dev-wallet-bg-2);
235
177
  border: 1px solid var(--dev-wallet-border);
236
178
  margin-bottom: 16px;
237
179
  }
@@ -244,8 +186,6 @@ export class DevWalletAccounts extends LitElement {
244
186
 
245
187
  .confirm-account-address {
246
188
  font-size: 11px;
247
- color: var(--dev-wallet-muted-foreground);
248
- font-family: var(--dev-wallet-font-mono);
249
189
  }
250
190
 
251
191
  .confirm-actions {
@@ -254,8 +194,6 @@ export class DevWalletAccounts extends LitElement {
254
194
  }
255
195
 
256
196
  .confirm-error {
257
- color: var(--dev-wallet-destructive);
258
- font-size: 12px;
259
197
  margin-bottom: 8px;
260
198
  }
261
199
 
@@ -277,6 +215,14 @@ export class DevWalletAccounts extends LitElement {
277
215
  @property({ type: String })
278
216
  activeAddress = '';
279
217
 
218
+ /** Phase 4 P4.20 — when set to a `*-fork` literal, the panel
219
+ * surfaces a warning on the "+ Add" button (or hides it outright
220
+ * when no fork-compatible funding path exists). Fork stacks have
221
+ * no faucet; arbitrary fresh accounts can't be funded without an
222
+ * impersonation seed already configured at the supervisor level. */
223
+ @property({ type: String })
224
+ network = '';
225
+
280
226
  @state()
281
227
  private _dialogOpen = false;
282
228
 
@@ -307,12 +253,29 @@ export class DevWalletAccounts extends LitElement {
307
253
  a.listAvailableAccounts),
308
254
  );
309
255
 
256
+ // Phase 4 P4.20 — fork-mode networks have no faucet, and the
257
+ // supervisor's impersonation seed set is fixed at apply time.
258
+ // We can't fund a fresh account from the browser side, so the
259
+ // "+ Add" button either renders disabled with a tooltip
260
+ // (canAdd still true because the adapter contract supports
261
+ // account creation) or — pragmatically — stays clickable but
262
+ // surfaces a warning marker on the button.
263
+ const fork = this.network !== '' && isForkNetwork(this.network);
264
+
310
265
  return html`
311
266
  <div class="accounts-header">
312
267
  <h3 class="section-header">Accounts</h3>
313
268
  ${canAdd
314
- ? html`<button class="add-btn" part="add-button" @click=${this.#openDialog}>
315
- + Add
269
+ ? html`<button
270
+ class="add-btn"
271
+ part="add-button"
272
+ ?disabled=${fork}
273
+ title=${fork
274
+ ? `Disabled on ${this.network}: fork networks have no faucet — fund seed addresses via Sui({fork:{seed:{addresses}}}) instead.`
275
+ : ''}
276
+ @click=${this.#openDialog}
277
+ >
278
+ + Add${fork ? ' (fork: no faucet)' : ''}
316
279
  </button>`
317
280
  : nothing}
318
281
  </div>
@@ -539,7 +502,7 @@ export class DevWalletAccounts extends LitElement {
539
502
  this.#cancelDelete();
540
503
  }}
541
504
  >
542
- <div class="confirm-title">Remove Account</div>
505
+ <div class="dialog-title">Remove Account</div>
543
506
  <div class="confirm-body">
544
507
  ${imported
545
508
  ? 'This will remove the imported account from your wallet. You can re-import it later.'
@@ -6,7 +6,15 @@ import { css, html, LitElement, nothing } from 'lit';
6
6
  import { customElement, property, state } from 'lit/decorators.js';
7
7
 
8
8
  import { sectionHeaderStyles, sharedStyles, stateStyles } from './styles.js';
9
- import { formatCoinBalance, getCoinSymbol } from './utils.js';
9
+ import type { CoinManifestEntry, CoinRecord } from './utils.js';
10
+ import {
11
+ formatAddress,
12
+ formatCoinBalance,
13
+ getCoinSymbol,
14
+ indexCoinsByType,
15
+ isSuiCoinType,
16
+ lookupCoinByType,
17
+ } from './utils.js';
10
18
 
11
19
  interface CoinBalance {
12
20
  coinType: string;
@@ -29,29 +37,176 @@ export class DevWalletBalances extends LitElement {
29
37
  .balance-list {
30
38
  display: flex;
31
39
  flex-direction: column;
32
- gap: 4px;
40
+ gap: 2px;
33
41
  }
34
42
 
35
43
  .balance-item {
36
44
  display: flex;
37
- justify-content: space-between;
38
45
  align-items: center;
39
- padding: 10px 12px;
40
- border-radius: var(--dev-wallet-radius-sm);
41
- border: 1px solid var(--dev-wallet-border);
42
- background: var(--dev-wallet-secondary);
46
+ gap: 10px;
47
+ padding: 8px 2px;
48
+ border-radius: var(--dev-wallet-radius);
49
+ background: transparent;
50
+ transition: background 120ms;
51
+ }
52
+
53
+ .balance-item:hover {
54
+ background: var(--dev-wallet-bg-hover);
55
+ }
56
+
57
+ .balance-main {
58
+ flex: 1;
59
+ min-width: 0;
60
+ }
61
+
62
+ .token-icon {
63
+ width: 28px;
64
+ height: 28px;
65
+ border-radius: 50%;
66
+ display: inline-flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ flex-shrink: 0;
70
+ background: linear-gradient(135deg, var(--dev-wallet-primary), var(--dev-wallet-teal));
71
+ color: #fff;
72
+ font-family: var(--dev-wallet-font-mono);
73
+ font-size: 10px;
74
+ font-weight: var(--dev-wallet-font-weight-semibold);
75
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15);
43
76
  }
44
77
 
45
78
  .balance-symbol {
46
- font-size: 14px;
79
+ font-size: 12px;
47
80
  font-weight: var(--dev-wallet-font-weight-medium);
48
81
  color: var(--dev-wallet-foreground);
49
82
  }
50
83
 
51
- .balance-amount {
52
- font-size: 14px;
84
+ .balance-name {
85
+ font-size: 11px;
86
+ color: var(--dev-wallet-text-3);
87
+ overflow: hidden;
88
+ text-overflow: ellipsis;
89
+ white-space: nowrap;
90
+ }
91
+
92
+ .balance-amount-stack {
93
+ display: flex;
94
+ flex-direction: column;
95
+ align-items: flex-end;
96
+ gap: 1px;
97
+ font-size: 12px;
53
98
  color: var(--dev-wallet-foreground);
54
99
  font-family: var(--dev-wallet-font-mono);
100
+ font-variant-numeric: tabular-nums;
101
+ }
102
+
103
+ .balance-amount-symbol {
104
+ font-size: 10.5px;
105
+ color: var(--dev-wallet-text-3);
106
+ }
107
+
108
+ .coins-header {
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: space-between;
112
+ gap: 8px;
113
+ }
114
+
115
+ .coins-header .section-header {
116
+ margin-bottom: 0;
117
+ }
118
+
119
+ .manage-btn,
120
+ .action-btn {
121
+ height: 30px;
122
+ padding: 0 10px;
123
+ border-radius: var(--dev-wallet-radius);
124
+ border: 1px solid var(--dev-wallet-border);
125
+ background: transparent;
126
+ color: var(--dev-wallet-text-2);
127
+ font-size: 12px;
128
+ font-weight: var(--dev-wallet-font-weight-medium);
129
+ }
130
+
131
+ .manage-btn:hover,
132
+ .action-btn:hover:not(:disabled) {
133
+ background: var(--dev-wallet-bg-hover);
134
+ border-color: var(--dev-wallet-border-strong);
135
+ color: var(--dev-wallet-foreground);
136
+ }
137
+
138
+ .manage-btn:disabled {
139
+ opacity: 0.48;
140
+ cursor: not-allowed;
141
+ }
142
+
143
+ .balance-hero {
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: space-between;
147
+ gap: 12px;
148
+ margin-bottom: 18px;
149
+ padding: 16px;
150
+ border: 1px solid var(--dev-wallet-border);
151
+ border-radius: var(--dev-wallet-radius-lg);
152
+ background:
153
+ radial-gradient(
154
+ circle at 20% 0%,
155
+ color-mix(in srgb, var(--dev-wallet-primary) 18%, transparent),
156
+ transparent 42%
157
+ ),
158
+ var(--dev-wallet-surface);
159
+ }
160
+
161
+ .hero-copy {
162
+ min-width: 0;
163
+ }
164
+
165
+ .hero-balance {
166
+ display: flex;
167
+ align-items: baseline;
168
+ gap: 8px;
169
+ }
170
+
171
+ .hero-value {
172
+ font-size: 30px;
173
+ line-height: 1;
174
+ font-weight: var(--dev-wallet-font-weight-semibold);
175
+ font-variant-numeric: tabular-nums;
176
+ letter-spacing: 0;
177
+ }
178
+
179
+ .hero-unit {
180
+ font-family: var(--dev-wallet-font-mono);
181
+ font-size: 13px;
182
+ color: var(--dev-wallet-text-2);
183
+ }
184
+
185
+ .hero-note {
186
+ margin-top: 6px;
187
+ font-size: 12px;
188
+ color: var(--dev-wallet-text-3);
189
+ overflow: hidden;
190
+ text-overflow: ellipsis;
191
+ white-space: nowrap;
192
+ }
193
+
194
+ .empty-wallet {
195
+ text-align: left;
196
+ padding: 16px;
197
+ }
198
+
199
+ .empty-title {
200
+ font-size: 13px;
201
+ font-weight: var(--dev-wallet-font-weight-semibold);
202
+ color: var(--dev-wallet-foreground);
203
+ }
204
+
205
+ .empty-copy {
206
+ margin-top: 6px;
207
+ font-size: 12px;
208
+ line-height: 1.45;
209
+ color: var(--dev-wallet-text-2);
55
210
  }
56
211
  `,
57
212
  ];
@@ -62,6 +217,16 @@ export class DevWalletBalances extends LitElement {
62
217
  @property({ attribute: false })
63
218
  client: ClientWithCoreApi | null = null;
64
219
 
220
+ @property({ type: String })
221
+ network = '';
222
+
223
+ /** Optional pre-seeded coin metadata — pass the generated `coins`
224
+ * constant from devstack codegen (`src/generated/coins.ts`) to skip
225
+ * per-coin `getCoinMetadata` RPC waterfalls on UI load. Unknown coin
226
+ * types fall through to an RPC fetch as before. */
227
+ @property({ attribute: false })
228
+ coins: CoinRecord | null = null;
229
+
65
230
  @state()
66
231
  private _balances: CoinBalance[] = [];
67
232
 
@@ -74,6 +239,8 @@ export class DevWalletBalances extends LitElement {
74
239
  #lastFetchedAddress = '';
75
240
  #lastFetchedClient: ClientWithCoreApi | null = null;
76
241
  #fetchGeneration = 0;
242
+ #coinIndex: ReadonlyMap<string, CoinManifestEntry> = new Map();
243
+ #lastCoinsRef: CoinRecord | null = null;
77
244
 
78
245
  /** Re-fetch balances for the current address/client. */
79
246
  refresh() {
@@ -83,6 +250,10 @@ export class DevWalletBalances extends LitElement {
83
250
  }
84
251
 
85
252
  override willUpdate(changedProperties: Map<string, unknown>) {
253
+ if (changedProperties.has('coins') && this.coins !== this.#lastCoinsRef) {
254
+ this.#coinIndex = indexCoinsByType(this.coins);
255
+ this.#lastCoinsRef = this.coins;
256
+ }
86
257
  if (
87
258
  (changedProperties.has('address') || changedProperties.has('client')) &&
88
259
  this.address &&
@@ -98,8 +269,29 @@ export class DevWalletBalances extends LitElement {
98
269
  return nothing;
99
270
  }
100
271
 
272
+ const suiBalance = this._balances.find(
273
+ (balance) => isSuiCoinType(balance.coinType) || balance.symbol === 'SUI',
274
+ );
275
+ const formattedSui = suiBalance
276
+ ? formatCoinBalance(suiBalance.totalBalance, suiBalance.decimals)
277
+ : '0.0000';
278
+ const networkLabel = this.network || 'active network';
279
+
101
280
  return html`
102
- <h3 class="section-header">Balances</h3>
281
+ <div class="balance-hero">
282
+ <div class="hero-copy">
283
+ <div class="hero-balance">
284
+ <span class="hero-value">${formattedSui}</span>
285
+ <span class="hero-unit">SUI</span>
286
+ </div>
287
+ <div class="hero-note">${formatAddress(this.address)} · ${networkLabel}</div>
288
+ </div>
289
+ <button class="action-btn" @click=${this.refresh}>Refresh</button>
290
+ </div>
291
+ <div class="coins-header">
292
+ <h3 class="section-header">Coins · ${this._balances.length}</h3>
293
+ <button class="manage-btn" disabled>Manage</button>
294
+ </div>
103
295
  ${this._loading
104
296
  ? html`<div class="loading" part="loading" aria-live="polite">Loading...</div>`
105
297
  : this._error
@@ -107,19 +299,34 @@ export class DevWalletBalances extends LitElement {
107
299
  ${this._error}
108
300
  </div>`
109
301
  : this._balances.length === 0
110
- ? html`<div class="empty-state" part="empty-state">No balances</div>`
302
+ ? html`<div class="empty-state empty-wallet" part="empty-state">
303
+ <div class="empty-title">No balances on ${networkLabel}</div>
304
+ <div class="empty-copy">
305
+ Fund ${formatAddress(this.address)} from your local faucet or devstack seed, then
306
+ refresh balances here.
307
+ </div>
308
+ </div>`
111
309
  : html`
112
310
  <div class="balance-list" part="balance-list">
113
- ${this._balances.map(
114
- (balance) => html`
311
+ ${this._balances.map((balance) => {
312
+ const seed = lookupCoinByType(this.#coinIndex, balance.coinType);
313
+ const name = seed?.displayName ?? balance.symbol;
314
+ return html`
115
315
  <div class="balance-item">
116
- <span class="balance-symbol">${balance.symbol}</span>
117
- <span class="balance-amount"
118
- >${formatCoinBalance(balance.totalBalance, balance.decimals)}</span
119
- >
316
+ <span class="token-icon">${balance.symbol.slice(0, 3)}</span>
317
+ <span class="balance-main">
318
+ <div class="balance-symbol">${balance.symbol}</div>
319
+ <div class="balance-name">${name}</div>
320
+ </span>
321
+ <span class="balance-amount-stack">
322
+ <span class="balance-amount">
323
+ ${formatCoinBalance(balance.totalBalance, balance.decimals)}
324
+ </span>
325
+ <span class="balance-amount-symbol">${balance.symbol}</span>
326
+ </span>
120
327
  </div>
121
- `,
122
- )}
328
+ `;
329
+ })}
123
330
  </div>
124
331
  `}
125
332
  `;
@@ -137,21 +344,35 @@ export class DevWalletBalances extends LitElement {
137
344
 
138
345
  if (generation !== this.#fetchGeneration) return;
139
346
 
347
+ // Pre-seed metadata from the generated `coins` record. Each
348
+ // balance with a known coinType skips the per-coin RPC entirely;
349
+ // only the (typically empty) remainder hits the network.
350
+ const preseeded = balances.map((b) => lookupCoinByType(this.#coinIndex, b.coinType));
140
351
  const metadataResults = await Promise.all(
141
- balances.map((b) =>
142
- this.client!.core.getCoinMetadata({ coinType: b.coinType }).catch(() => null),
143
- ),
352
+ balances.map((b, i) => {
353
+ if (preseeded[i] !== undefined) return null;
354
+ return this.client!.core.getCoinMetadata({ coinType: b.coinType }).catch(() => null);
355
+ }),
144
356
  );
145
357
 
146
358
  if (generation !== this.#fetchGeneration) return;
147
- this._balances = balances.map(
148
- (b, i): CoinBalance => ({
359
+ this._balances = balances.map((b, i): CoinBalance => {
360
+ const seed = preseeded[i];
361
+ if (seed !== undefined) {
362
+ return {
363
+ coinType: b.coinType,
364
+ symbol: seed.symbol ?? getCoinSymbol(b.coinType),
365
+ totalBalance: b.balance,
366
+ decimals: seed.decimals,
367
+ };
368
+ }
369
+ return {
149
370
  coinType: b.coinType,
150
371
  symbol: metadataResults[i]?.coinMetadata?.symbol ?? getCoinSymbol(b.coinType),
151
372
  totalBalance: b.balance,
152
373
  decimals: metadataResults[i]?.coinMetadata?.decimals ?? 0,
153
- }),
154
- );
374
+ };
375
+ });
155
376
  } catch {
156
377
  if (generation !== this.#fetchGeneration) return;
157
378
  this._error = 'Failed to load balances';