@mysten-incubation/dev-wallet 0.0.1 → 0.2.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 +25 -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 +12 -0
  15. package/dist/adapters/devstack-paths.d.mts.map +1 -0
  16. package/dist/adapters/devstack-paths.mjs +12 -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 +16 -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
@@ -6,6 +6,7 @@ import { customElement, property } from 'lit/decorators.js';
6
6
 
7
7
  import type { DevWallet } from '../wallet/dev-wallet.js';
8
8
  import { connectDialogStyles, sharedStyles } from './styles.js';
9
+ import type { CoinRecord } from './utils.js';
9
10
  import { WalletController } from './wallet-controller.js';
10
11
 
11
12
  @customElement('dev-wallet-standalone')
@@ -15,36 +16,187 @@ export class DevWalletStandalone extends LitElement {
15
16
  connectDialogStyles,
16
17
  css`
17
18
  :host {
18
- display: flex;
19
- justify-content: center;
20
- padding: 24px 16px;
19
+ display: block;
21
20
  min-height: 100vh;
22
21
  box-sizing: border-box;
22
+ padding: 24px;
23
+ color: var(--dev-wallet-foreground);
24
+ background-color: var(--dev-wallet-bg-0);
25
+ background-image:
26
+ linear-gradient(var(--dev-wallet-border) 1px, transparent 1px),
27
+ linear-gradient(90deg, var(--dev-wallet-border) 1px, transparent 1px);
28
+ background-size: 32px 32px;
29
+ background-position: -1px -1px;
30
+ }
31
+
32
+ .standalone-layout {
33
+ width: 100%;
34
+ max-width: 1220px;
35
+ min-height: calc(100vh - 48px);
36
+ margin: 0 auto;
37
+ padding: 24px 0;
38
+ display: grid;
39
+ grid-template-columns: minmax(240px, 1fr) 480px minmax(260px, 1fr);
40
+ gap: 20px;
41
+ align-items: start;
42
+ }
43
+
44
+ .rail {
45
+ min-width: 0;
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: 16px;
49
+ padding-top: 6px;
50
+ }
51
+
52
+ .wordmark {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 10px;
56
+ }
57
+
58
+ .logo-mark {
59
+ width: 28px;
60
+ height: 28px;
61
+ border-radius: 9px;
62
+ display: inline-flex;
63
+ align-items: center;
64
+ justify-content: center;
65
+ color: var(--dev-wallet-primary-foreground);
66
+ background:
67
+ radial-gradient(circle at 35% 25%, rgba(255, 255, 255, 0.5), transparent 24px),
68
+ linear-gradient(135deg, var(--dev-wallet-primary), var(--dev-wallet-teal));
69
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16);
70
+ }
71
+
72
+ .logo-mark svg {
73
+ width: 18px;
74
+ height: 18px;
75
+ }
76
+
77
+ .wordmark-title {
78
+ display: flex;
79
+ flex-direction: column;
80
+ line-height: 1.1;
81
+ }
82
+
83
+ .wordmark-title strong {
84
+ font-size: 16px;
85
+ font-weight: var(--dev-wallet-font-weight-semibold);
86
+ }
87
+
88
+ .version {
89
+ font-family: var(--dev-wallet-font-mono);
90
+ font-size: 9px;
91
+ letter-spacing: 0.12em;
92
+ text-transform: uppercase;
93
+ color: var(--dev-wallet-text-3);
94
+ }
95
+
96
+ .rail-section {
97
+ display: flex;
98
+ flex-direction: column;
99
+ gap: 8px;
100
+ }
101
+
102
+ .rail-title {
103
+ font-family: var(--dev-wallet-font-mono);
104
+ font-size: 10px;
105
+ font-weight: var(--dev-wallet-font-weight-medium);
106
+ letter-spacing: 0.14em;
107
+ text-transform: uppercase;
108
+ color: var(--dev-wallet-text-3);
109
+ }
110
+
111
+ .code {
112
+ margin: 0;
113
+ overflow: auto;
114
+ white-space: pre;
115
+ padding: 10px 12px;
116
+ border-radius: var(--dev-wallet-radius);
117
+ border: 1px solid var(--dev-wallet-border);
118
+ background: var(--dev-wallet-bg-0);
119
+ color: var(--dev-wallet-foreground);
120
+ font-family: var(--dev-wallet-font-mono);
121
+ font-size: 11.5px;
122
+ line-height: 1.55;
123
+ }
124
+
125
+ .status-list {
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: 6px;
129
+ }
130
+
131
+ .status-row {
132
+ display: flex;
133
+ align-items: center;
134
+ gap: 8px;
135
+ min-width: 0;
136
+ padding: 8px 10px;
137
+ border-radius: var(--dev-wallet-radius-lg);
138
+ border: 1px solid var(--dev-wallet-border);
139
+ background: color-mix(in srgb, var(--dev-wallet-bg-1) 88%, transparent);
140
+ }
141
+
142
+ .status-dot {
143
+ width: 7px;
144
+ height: 7px;
145
+ border-radius: 999px;
146
+ background: var(--dev-wallet-status-connected);
147
+ flex-shrink: 0;
148
+ }
149
+
150
+ .status-dot.mute {
151
+ background: var(--dev-wallet-text-3);
152
+ }
153
+
154
+ .status-copy {
155
+ min-width: 0;
156
+ display: flex;
157
+ flex-direction: column;
158
+ gap: 1px;
159
+ }
160
+
161
+ .status-copy strong {
162
+ font-size: 12px;
163
+ font-weight: var(--dev-wallet-font-weight-medium);
164
+ }
165
+
166
+ .status-copy span {
167
+ font-family: var(--dev-wallet-font-mono);
168
+ font-size: 10.5px;
169
+ color: var(--dev-wallet-text-3);
170
+ overflow: hidden;
171
+ text-overflow: ellipsis;
172
+ white-space: nowrap;
23
173
  }
24
174
 
25
175
  .card {
26
176
  width: 100%;
27
177
  max-width: 480px;
28
178
  border-radius: var(--dev-wallet-radius-xl);
29
- background: var(--dev-wallet-background);
30
- border: 1px solid var(--dev-wallet-border);
31
- box-shadow: var(--dev-wallet-shadow-lg);
179
+ background: var(--dev-wallet-surface);
180
+ border: 1px solid var(--dev-wallet-border-2);
181
+ box-shadow: var(--dev-wallet-shadow-drawer);
32
182
  overflow: hidden;
33
183
  display: flex;
34
184
  flex-direction: column;
35
185
  height: min(640px, calc(100vh - 48px));
186
+ min-height: 540px;
36
187
  }
37
188
 
38
189
  .card-header {
39
190
  display: flex;
40
- justify-content: space-between;
41
191
  align-items: center;
42
- padding: 16px 20px;
192
+ gap: 8px;
193
+ padding: 10px 14px;
43
194
  border-bottom: 1px solid var(--dev-wallet-border);
195
+ background: var(--dev-wallet-bg-1);
44
196
  }
45
197
 
46
198
  .card-title {
47
- font-size: 17px;
199
+ font-size: 12.5px;
48
200
  font-weight: var(--dev-wallet-font-weight-semibold);
49
201
  color: var(--dev-wallet-foreground);
50
202
  }
@@ -53,6 +205,7 @@ export class DevWalletStandalone extends LitElement {
53
205
  display: flex;
54
206
  align-items: center;
55
207
  gap: 8px;
208
+ margin-left: auto;
56
209
  }
57
210
 
58
211
  .status-dot {
@@ -63,22 +216,52 @@ export class DevWalletStandalone extends LitElement {
63
216
  }
64
217
 
65
218
  .status-text {
66
- font-size: 11px;
219
+ font-family: var(--dev-wallet-font-mono);
220
+ font-size: 10.5px;
67
221
  color: var(--dev-wallet-muted-foreground);
68
222
  }
69
223
 
70
224
  .card-body {
71
- padding: 16px 20px;
72
225
  overflow-y: auto;
73
226
  flex: 1;
227
+ min-height: 0;
228
+ background: var(--dev-wallet-bg-0);
74
229
  }
75
230
 
76
231
  .section {
77
- margin-bottom: 16px;
232
+ padding: 14px;
233
+ border-bottom: 1px solid var(--dev-wallet-border);
78
234
  }
79
235
 
80
236
  .section:last-child {
81
- margin-bottom: 0;
237
+ border-bottom: 0;
238
+ }
239
+
240
+ @media (max-width: 1020px) {
241
+ .standalone-layout {
242
+ grid-template-columns: minmax(0, 480px);
243
+ justify-content: center;
244
+ }
245
+
246
+ .rail {
247
+ display: none;
248
+ }
249
+ }
250
+
251
+ @media (max-width: 560px) {
252
+ :host {
253
+ padding: 12px;
254
+ }
255
+
256
+ .standalone-layout {
257
+ min-height: calc(100vh - 24px);
258
+ padding: 0;
259
+ }
260
+
261
+ .card {
262
+ height: calc(100vh - 24px);
263
+ min-height: 0;
264
+ }
82
265
  }
83
266
  `,
84
267
  ];
@@ -90,6 +273,12 @@ export class DevWalletStandalone extends LitElement {
90
273
  @property({ type: String })
91
274
  bookmarkletOrigin = '';
92
275
 
276
+ /** Optional pre-seeded coin metadata. Pass the generated `coins`
277
+ * constant from devstack codegen to skip per-coin RPC fetches in the
278
+ * balances list and signing modal. */
279
+ @property({ attribute: false })
280
+ coins: CoinRecord | null = null;
281
+
93
282
  #ctrl = new WalletController(this);
94
283
 
95
284
  override willUpdate(changedProperties: Map<string, unknown>) {
@@ -99,6 +288,9 @@ export class DevWalletStandalone extends LitElement {
99
288
  if (changedProperties.has('bookmarkletOrigin')) {
100
289
  this.#ctrl.bookmarkletOrigin = this.bookmarkletOrigin;
101
290
  }
291
+ if (changedProperties.has('coins')) {
292
+ this.#ctrl.coins = this.coins;
293
+ }
102
294
  }
103
295
 
104
296
  override updated() {
@@ -112,21 +304,117 @@ export class DevWalletStandalone extends LitElement {
112
304
 
113
305
  override render() {
114
306
  return html`
115
- <div class="card" part="card">
116
- <div class="card-header">
117
- <span class="card-title">${this.wallet?.name ?? 'Dev Wallet'}</span>
118
- <div class="header-right">
119
- ${this.#ctrl.renderNetworkBadge()}
120
- <span class="status-dot"></span>
121
- <span class="status-text">Running</span>
307
+ <div class="standalone-layout">
308
+ <aside class="rail">${this.#renderLeftRail()}</aside>
309
+ <div class="card" part="card">
310
+ <div class="card-header">
311
+ <span class="logo-mark">${this.#walletIcon}</span>
312
+ <span class="wordmark-title">
313
+ <span class="card-title">${this.wallet?.name ?? 'Dev Wallet'}</span>
314
+ <span class="version">v0.1.0</span>
315
+ </span>
316
+ <div class="header-right">
317
+ ${this.#ctrl.renderNetworkBadge()}
318
+ <span class="status-dot"></span>
319
+ <span class="status-text">Running</span>
320
+ </div>
122
321
  </div>
322
+ ${this.#ctrl.renderTabBar()}
323
+ <div class="card-body">${this.#ctrl.renderTabContent()}</div>
123
324
  </div>
124
- <div class="card-body">${this.#ctrl.renderTabContent()}</div>
125
- ${this.#ctrl.renderTabBar()}
325
+ <aside class="rail">${this.#renderRightRail()}</aside>
126
326
  </div>
127
327
  ${this.#ctrl.renderSigningModal()} ${this.#ctrl.renderConnectPicker()}
128
328
  `;
129
329
  }
330
+
331
+ #renderLeftRail() {
332
+ const origin = this.bookmarkletOrigin || globalThis.location?.origin || 'http://localhost:5174';
333
+ const quickStart = `npx @mysten-incubation/dev-wallet serve\n${origin}`;
334
+ const clientSnippet = `createDAppKit({
335
+ walletInitializers: [
336
+ devWalletClientInitializer({
337
+ origin: '${origin}'
338
+ })
339
+ ]
340
+ })`;
341
+ const embeddingSnippet = `createDAppKit({
342
+ networks: ['devnet'],
343
+ walletInitializers: [
344
+ devWalletInitializer({
345
+ adapters: [
346
+ new WebCryptoSignerAdapter()
347
+ ],
348
+ autoConnect: true,
349
+ mountUI: true
350
+ })
351
+ ]
352
+ })`;
353
+ return html`
354
+ <div class="wordmark">
355
+ <span class="logo-mark">${this.#walletIcon}</span>
356
+ <span class="wordmark-title">
357
+ <strong>Dev Wallet</strong>
358
+ <span class="version">v0.1.0</span>
359
+ </span>
360
+ </div>
361
+ <div class="rail-section">
362
+ <div class="rail-title">Quick Start</div>
363
+ <pre class="code">${quickStart}</pre>
364
+ </div>
365
+ <div class="rail-section">
366
+ <div class="rail-title">Embed Wallet</div>
367
+ <pre class="code">${embeddingSnippet}</pre>
368
+ </div>
369
+ <div class="rail-section">
370
+ <div class="rail-title">Standalone Client</div>
371
+ <pre class="code">${clientSnippet}</pre>
372
+ </div>
373
+ <div class="rail-section">
374
+ <div class="rail-title">Bookmarklet Endpoint</div>
375
+ <pre class="code">${origin}/bookmarklet.js</pre>
376
+ </div>
377
+ `;
378
+ }
379
+
380
+ #renderRightRail() {
381
+ const activeNetwork = this.wallet?.activeNetwork ?? 'devnet';
382
+ const networkUrl = this.wallet?.networkUrls[activeNetwork] ?? 'client configured by dApp Kit';
383
+ const accountCount = this.wallet?.accounts.length ?? 0;
384
+ const adapterCount = this.wallet?.adapters.length ?? 0;
385
+ const adapterNames =
386
+ this.wallet?.adapters.map((adapter) => adapter.name).join(', ') ?? 'No adapters';
387
+ return html`
388
+ <div class="rail-section">
389
+ <div class="rail-title">Wallet Status</div>
390
+ <div class="status-list">
391
+ <div class="status-row">
392
+ <span class="status-dot"></span>
393
+ <span class="status-copy">
394
+ <strong>Network: ${activeNetwork}</strong>
395
+ <span>${networkUrl}</span>
396
+ </span>
397
+ </div>
398
+ <div class="status-row">
399
+ <span class="status-dot mute"></span>
400
+ <span class="status-copy">
401
+ <strong>${accountCount} account(s)</strong>
402
+ <span>${adapterCount} adapter(s): ${adapterNames}</span>
403
+ </span>
404
+ </div>
405
+ </div>
406
+ </div>
407
+ `;
408
+ }
409
+
410
+ get #walletIcon() {
411
+ return html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
412
+ <rect x="2" y="6" width="20" height="14" rx="2.5" />
413
+ <path d="M2 10h20" />
414
+ <rect x="15" y="12" width="5" height="4" rx="1" />
415
+ <circle cx="17.5" cy="14" r="0.5" fill="currentColor" stroke="none" />
416
+ </svg>`;
417
+ }
130
418
  }
131
419
 
132
420
  declare global {
@@ -1,12 +1,83 @@
1
1
  // Copyright (c) Mysten Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { css, html, LitElement } from 'lit';
4
+ import { css, html, LitElement, type TemplateResult } from 'lit';
5
5
  import { customElement, property } from 'lit/decorators.js';
6
6
 
7
7
  import { sharedStyles } from './styles.js';
8
8
 
9
- export type TabId = 'assets' | 'objects' | 'settings';
9
+ /** Built-in tab ids. */
10
+ export type BuiltinTabId = 'assets' | 'objects' | 'fork' | 'settings';
11
+ export type TabId = BuiltinTabId;
12
+
13
+ interface TabSpec {
14
+ id: TabId;
15
+ label: string;
16
+ icon: TemplateResult;
17
+ }
18
+
19
+ const ASSETS_ICON = html`<svg
20
+ viewBox="0 0 24 24"
21
+ fill="none"
22
+ stroke="currentColor"
23
+ stroke-width="2"
24
+ >
25
+ <rect x="2" y="4" width="20" height="16" rx="2" />
26
+ <path d="M16 12h.01" />
27
+ </svg>`;
28
+
29
+ const OBJECTS_ICON = html`<svg
30
+ viewBox="0 0 24 24"
31
+ fill="none"
32
+ stroke="currentColor"
33
+ stroke-width="2"
34
+ >
35
+ <rect x="3" y="3" width="7" height="7" rx="1" />
36
+ <rect x="14" y="3" width="7" height="7" rx="1" />
37
+ <rect x="3" y="14" width="7" height="7" rx="1" />
38
+ <rect x="14" y="14" width="7" height="7" rx="1" />
39
+ </svg>`;
40
+
41
+ const SETTINGS_ICON = html`<svg
42
+ viewBox="0 0 24 24"
43
+ fill="none"
44
+ stroke="currentColor"
45
+ stroke-width="2"
46
+ >
47
+ <circle cx="12" cy="12" r="3" />
48
+ <path
49
+ d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"
50
+ />
51
+ </svg>`;
52
+
53
+ // Phase 5 Subtopic 6 — fork-controls tab icon. Branching shape signals
54
+ // the "fork" semantic without overlapping with the existing wallet
55
+ // glyphs; rendered only when the active manifest's `meta.runtime`
56
+ // resolves to `'forked'` (see `wallet-controller.renderTabBar`).
57
+ const FORK_ICON = html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
58
+ <circle cx="6" cy="6" r="2" />
59
+ <circle cx="6" cy="18" r="2" />
60
+ <circle cx="18" cy="12" r="2" />
61
+ <path d="M6 8v8" />
62
+ <path d="M6 12h6" />
63
+ <path d="M12 12l4-2" />
64
+ <path d="M12 12l4 2" />
65
+ </svg>`;
66
+
67
+ const BUILTIN_TABS: TabSpec[] = [
68
+ { id: 'assets', label: 'Home', icon: ASSETS_ICON },
69
+ { id: 'objects', label: 'Objects', icon: OBJECTS_ICON },
70
+ { id: 'settings', label: 'Settings', icon: SETTINGS_ICON },
71
+ ];
72
+
73
+ /** Built-in tabs plus the fork-controls tab. Returned when the host
74
+ * controller signals fork-mode availability via the `showFork` prop. */
75
+ const TABS_WITH_FORK: TabSpec[] = [
76
+ { id: 'assets', label: 'Home', icon: ASSETS_ICON },
77
+ { id: 'objects', label: 'Objects', icon: OBJECTS_ICON },
78
+ { id: 'fork', label: 'Fork', icon: FORK_ICON },
79
+ { id: 'settings', label: 'Settings', icon: SETTINGS_ICON },
80
+ ];
10
81
 
11
82
  @customElement('dev-wallet-tab-bar')
12
83
  export class DevWalletTabBar extends LitElement {
@@ -15,39 +86,56 @@ export class DevWalletTabBar extends LitElement {
15
86
  css`
16
87
  :host {
17
88
  display: block;
18
- border-top: 1px solid var(--dev-wallet-border);
89
+ border-bottom: 1px solid var(--dev-wallet-border);
90
+ background: var(--dev-wallet-surface);
19
91
  }
20
92
 
21
93
  .tab-bar {
22
94
  display: flex;
23
- height: 40px;
95
+ align-items: stretch;
96
+ min-height: 38px;
97
+ overflow-x: auto;
98
+ padding: 0 6px;
24
99
  }
25
100
 
26
101
  .tab {
27
- flex: 1;
102
+ position: relative;
28
103
  display: flex;
29
104
  align-items: center;
30
105
  justify-content: center;
31
- gap: 4px;
32
- font-size: 11px;
106
+ gap: 6px;
107
+ min-width: 0;
108
+ height: 38px;
109
+ padding: 0 14px;
110
+ font-size: 12px;
33
111
  font-weight: var(--dev-wallet-font-weight-medium);
34
- color: var(--dev-wallet-muted-foreground);
35
- transition: color 0.15s;
36
- border-top: 2px solid transparent;
112
+ color: var(--dev-wallet-text-2);
113
+ transition:
114
+ color 120ms,
115
+ background 120ms;
116
+ border-bottom: 2px solid transparent;
117
+ white-space: nowrap;
37
118
  }
38
119
 
39
120
  .tab:hover {
40
121
  color: var(--dev-wallet-foreground);
122
+ background: var(--dev-wallet-bg-hover);
41
123
  }
42
124
 
43
125
  .tab[aria-selected='true'] {
44
- color: var(--dev-wallet-primary);
45
- border-top-color: var(--dev-wallet-primary);
126
+ color: var(--dev-wallet-foreground);
127
+ border-bottom-color: var(--dev-wallet-primary);
46
128
  }
47
129
 
48
130
  .tab svg {
49
- width: 16px;
50
- height: 16px;
131
+ width: 13px;
132
+ height: 13px;
133
+ flex-shrink: 0;
134
+ }
135
+
136
+ .tab:last-child {
137
+ margin-left: auto;
138
+ padding: 0 10px;
51
139
  }
52
140
  `,
53
141
  ];
@@ -55,67 +143,40 @@ export class DevWalletTabBar extends LitElement {
55
143
  @property({ type: String })
56
144
  active: TabId = 'assets';
57
145
 
146
+ /** Phase 5 Subtopic 6 — when true, the bar surfaces a "Fork" tab
147
+ * between Objects and Settings. The host controller toggles this
148
+ * on whenever the active stack's manifest reports
149
+ * `meta.runtime === 'forked'`. Off by default so bundled-mode
150
+ * apps don't accidentally expose admin RPCs. */
151
+ @property({ type: Boolean, attribute: 'show-fork' })
152
+ showFork = false;
153
+
58
154
  override render() {
155
+ const tabs: TabSpec[] = this.showFork ? TABS_WITH_FORK : BUILTIN_TABS;
59
156
  return html`
60
157
  <nav class="tab-bar" part="tab-bar" role="tablist" aria-label="Wallet navigation">
61
- <button
62
- class="tab"
63
- part="tab"
64
- role="tab"
65
- aria-selected=${this.active === 'assets'}
66
- tabindex=${this.active === 'assets' ? 0 : -1}
67
- @click=${() => this.#select('assets')}
68
- @keydown=${this.#handleKeydown}
69
- >
70
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
71
- <rect x="2" y="4" width="20" height="16" rx="2" />
72
- <path d="M16 12h.01" />
73
- </svg>
74
- Assets
75
- </button>
76
- <button
77
- class="tab"
78
- part="tab"
79
- role="tab"
80
- aria-selected=${this.active === 'objects'}
81
- tabindex=${this.active === 'objects' ? 0 : -1}
82
- @click=${() => this.#select('objects')}
83
- @keydown=${this.#handleKeydown}
84
- >
85
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
86
- <rect x="3" y="3" width="7" height="7" rx="1" />
87
- <rect x="14" y="3" width="7" height="7" rx="1" />
88
- <rect x="3" y="14" width="7" height="7" rx="1" />
89
- <rect x="14" y="14" width="7" height="7" rx="1" />
90
- </svg>
91
- Objects
92
- </button>
93
- <button
94
- class="tab"
95
- part="tab"
96
- role="tab"
97
- aria-selected=${this.active === 'settings'}
98
- tabindex=${this.active === 'settings' ? 0 : -1}
99
- @click=${() => this.#select('settings')}
100
- @keydown=${this.#handleKeydown}
101
- >
102
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
103
- <circle cx="12" cy="12" r="3" />
104
- <path
105
- d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"
106
- />
107
- </svg>
108
- Settings
109
- </button>
158
+ ${tabs.map(
159
+ (tab) => html`
160
+ <button
161
+ class="tab"
162
+ part="tab"
163
+ role="tab"
164
+ aria-selected=${this.active === tab.id}
165
+ tabindex=${this.active === tab.id ? 0 : -1}
166
+ @click=${() => this.#select(tab.id)}
167
+ @keydown=${(e: KeyboardEvent) => this.#handleKeydown(e, tabs)}
168
+ >
169
+ ${tab.icon} ${tab.label}
170
+ </button>
171
+ `,
172
+ )}
110
173
  </nav>
111
174
  `;
112
175
  }
113
176
 
114
- #handleKeydown(e: KeyboardEvent) {
115
- const tabs: TabId[] = ['assets', 'objects', 'settings'];
116
- const currentIndex = tabs.indexOf(this.active);
177
+ #handleKeydown(e: KeyboardEvent, tabs: TabSpec[]): void {
178
+ const currentIndex = tabs.findIndex((t) => t.id === this.active);
117
179
  let newIndex = -1;
118
-
119
180
  if (e.key === 'ArrowRight') {
120
181
  e.preventDefault();
121
182
  newIndex = (currentIndex + 1) % tabs.length;
@@ -123,15 +184,16 @@ export class DevWalletTabBar extends LitElement {
123
184
  e.preventDefault();
124
185
  newIndex = (currentIndex - 1 + tabs.length) % tabs.length;
125
186
  }
126
-
127
187
  if (newIndex !== -1) {
128
- this.#select(tabs[newIndex]);
188
+ const next = tabs[newIndex];
189
+ if (next === undefined) return;
190
+ this.#select(next.id);
129
191
  const buttons = this.shadowRoot?.querySelectorAll<HTMLButtonElement>('.tab');
130
192
  buttons?.[newIndex]?.focus();
131
193
  }
132
194
  }
133
195
 
134
- #select(tab: TabId) {
196
+ #select(tab: TabId): void {
135
197
  if (tab !== this.active) {
136
198
  this.dispatchEvent(
137
199
  new CustomEvent('tab-changed', {
package/src/ui/index.ts CHANGED
@@ -22,5 +22,8 @@ export { DevWalletDropdown } from './dev-wallet-dropdown.js';
22
22
  export { DevWalletNetworkBadge } from './dev-wallet-network-badge.js';
23
23
  /** @internal — not intended for direct use by consumers */
24
24
  export { DevWalletTabBar } from './dev-wallet-tab-bar.js';
25
+ /** Phase 5 Subtopic 6 — fork-controls panel. Surfaced so apps that
26
+ * build their own panel layout can mount it standalone. */
27
+ export { DevWalletForkPanel } from './dev-wallet-fork-panel.js';
25
28
 
26
29
  export { mountDevWallet } from './mount.js';