@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,424 @@
1
+ import { DEFAULT_WALLET_ICON, getNetworkFromChain } from "./constants.mjs";
2
+ import { executeSigning } from "./signing.mjs";
3
+ import { SuiGrpcClient } from "@mysten/sui/grpc";
4
+ import { mitt } from "@mysten/utils";
5
+ import { SUI_CHAINS, getWallets } from "@mysten/wallet-standard";
6
+
7
+ //#region src/wallet/dev-wallet.ts
8
+ const DEFAULT_WALLET_NAME = "Dev Wallet";
9
+ const NETWORK_STORAGE_KEY = "dev-wallet:networks";
10
+ /**
11
+ * Default gRPC endpoint URLs for standard Sui networks (devnet, testnet, localnet).
12
+ */
13
+ const DEFAULT_NETWORK_URLS = {
14
+ devnet: "https://fullnode.devnet.sui.io:443",
15
+ testnet: "https://fullnode.testnet.sui.io:443",
16
+ localnet: "http://127.0.0.1:9000"
17
+ };
18
+ /**
19
+ * wallet-standard Wallet implementation for development. All signing requests are queued
20
+ * and require explicit approval — either via the UI or programmatically via `approveRequest()`.
21
+ */
22
+ var DevWallet = class {
23
+ #adapters;
24
+ #networkUrls;
25
+ #clients;
26
+ #activeNetwork;
27
+ #name;
28
+ #icon;
29
+ #autoApprove;
30
+ #autoConnect;
31
+ #clientFactory;
32
+ #persistNetworks;
33
+ #accounts;
34
+ #events;
35
+ #unsubscribeAdapters;
36
+ #pendingRequest;
37
+ #requestListeners;
38
+ #pendingConnect;
39
+ #connectListeners;
40
+ #destroyed = false;
41
+ constructor(config) {
42
+ if (config.adapters.length === 0) {
43
+ console.warn("[dev-wallet] No adapters provided. The wallet will have no accounts.");
44
+ }
45
+ this.#adapters = config.adapters;
46
+ this.#persistNetworks = config.persistNetworks ?? false;
47
+ this.#networkUrls = this.#loadNetworkUrls(config.networks ?? DEFAULT_NETWORK_URLS);
48
+ this.#clients = {};
49
+ this.#activeNetwork = config.activeNetwork ?? Object.keys(this.#networkUrls)[0] ?? "";
50
+ this.#name = config.name ?? DEFAULT_WALLET_NAME;
51
+ this.#icon = config.icon ?? DEFAULT_WALLET_ICON;
52
+ this.#autoApprove = config.autoApprove ?? false;
53
+ this.#autoConnect = config.autoConnect ?? false;
54
+ this.#clientFactory = config.clientFactory ?? ((network, url) => new SuiGrpcClient({
55
+ baseUrl: url,
56
+ network
57
+ }));
58
+ this.#accounts = this.#aggregateAccounts();
59
+ this.#events = mitt();
60
+ this.#unsubscribeAdapters = [];
61
+ this.#pendingRequest = null;
62
+ this.#requestListeners = new Set();
63
+ this.#pendingConnect = null;
64
+ this.#connectListeners = new Set();
65
+ this.#setupAdapterListeners();
66
+ }
67
+ get version() {
68
+ return "1.0.0";
69
+ }
70
+ get name() {
71
+ return this.#name;
72
+ }
73
+ get icon() {
74
+ return this.#icon;
75
+ }
76
+ get chains() {
77
+ return SUI_CHAINS;
78
+ }
79
+ get accounts() {
80
+ return this.#accounts;
81
+ }
82
+ get features() {
83
+ return {
84
+ "standard:connect": {
85
+ version: "1.0.0",
86
+ connect: this.#connect
87
+ },
88
+ "standard:events": {
89
+ version: "1.0.0",
90
+ on: this.#on
91
+ },
92
+ "standard:disconnect": {
93
+ version: "1.0.0",
94
+ disconnect: this.#disconnect
95
+ },
96
+ "sui:signPersonalMessage": {
97
+ version: "1.1.0",
98
+ signPersonalMessage: this.#signPersonalMessage
99
+ },
100
+ "sui:signTransaction": {
101
+ version: "2.0.0",
102
+ signTransaction: this.#signTransaction
103
+ },
104
+ "sui:signAndExecuteTransaction": {
105
+ version: "2.0.0",
106
+ signAndExecuteTransaction: this.#signAndExecuteTransaction
107
+ }
108
+ };
109
+ }
110
+ /** The current pending signing request, or null if none. */
111
+ get pendingRequest() {
112
+ return this.#pendingRequest;
113
+ }
114
+ get adapters() {
115
+ return this.#adapters;
116
+ }
117
+ getAdapterForAccount(address) {
118
+ return this.#adapters.find((a) => a.getAccount(address) !== undefined);
119
+ }
120
+ /** Eagerly creates and returns clients for all configured networks. Prefer `getClient()` or `activeClient` for single-network access. */
121
+ get clients() {
122
+ for (const name of Object.keys(this.#networkUrls)) {
123
+ this.#ensureClient(name);
124
+ }
125
+ return { ...this.#clients };
126
+ }
127
+ getClient(network) {
128
+ return this.#ensureClient(network);
129
+ }
130
+ get networkUrls() {
131
+ return { ...this.#networkUrls };
132
+ }
133
+ get activeNetwork() {
134
+ return this.#activeNetwork;
135
+ }
136
+ get activeClient() {
137
+ if (!this.#activeNetwork || !this.#networkUrls[this.#activeNetwork]) return null;
138
+ return this.#ensureClient(this.#activeNetwork);
139
+ }
140
+ get availableNetworks() {
141
+ return Object.keys(this.#networkUrls);
142
+ }
143
+ /** Switch the active network. Emits a `change` event. */
144
+ setActiveNetwork(network) {
145
+ if (!this.#networkUrls[network]) {
146
+ throw new Error(`No client for network "${network}". Available: ${this.availableNetworks.join(", ")}`);
147
+ }
148
+ this.#activeNetwork = network;
149
+ this.#events.emit("change", { accounts: this.#accounts });
150
+ }
151
+ addNetwork(name, url) {
152
+ let parsed;
153
+ try {
154
+ parsed = new URL(url);
155
+ } catch {
156
+ throw new Error(`Invalid URL: ${url}`);
157
+ }
158
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
159
+ throw new Error(`Invalid URL: must use http or https (got ${parsed.protocol})`);
160
+ }
161
+ this.#networkUrls[name] = url;
162
+ this.#clients[name] = this.#clientFactory(name, url);
163
+ this.#saveNetworkUrls();
164
+ this.#events.emit("change", { accounts: this.#accounts });
165
+ }
166
+ removeNetwork(name) {
167
+ delete this.#networkUrls[name];
168
+ delete this.#clients[name];
169
+ if (this.#activeNetwork === name) {
170
+ this.#activeNetwork = Object.keys(this.#networkUrls)[0] ?? "";
171
+ }
172
+ this.#saveNetworkUrls();
173
+ this.#events.emit("change", { accounts: this.#accounts });
174
+ }
175
+ /** Register this wallet with the wallet-standard registry. Returns an unregister function. */
176
+ register() {
177
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
178
+ console.warn("[@mysten-incubation/dev-wallet] DevWallet is intended for development only. Do not use in production.");
179
+ }
180
+ const walletsApi = getWallets();
181
+ return walletsApi.register(this);
182
+ }
183
+ /** Reject any pending requests, unsubscribe from adapters, destroy them, and clear all listeners. */
184
+ destroy() {
185
+ this.#destroyed = true;
186
+ for (const unsub of this.#unsubscribeAdapters) {
187
+ unsub();
188
+ }
189
+ this.#unsubscribeAdapters = [];
190
+ for (const adapter of this.#adapters) {
191
+ adapter.destroy();
192
+ }
193
+ if (this.#pendingRequest) {
194
+ this.#pendingRequest.reject(new Error("Wallet destroyed."));
195
+ this.#pendingRequest = null;
196
+ }
197
+ if (this.#pendingConnect) {
198
+ this.#pendingConnect.reject(new Error("Wallet destroyed."));
199
+ this.#pendingConnect = null;
200
+ }
201
+ this.#requestListeners.clear();
202
+ this.#connectListeners.clear();
203
+ this.#events.all.clear();
204
+ }
205
+ /** Sign the pending request using the account's adapter signer and resolve the promise. */
206
+ async approveRequest() {
207
+ const request = this.#pendingRequest;
208
+ if (!request) {
209
+ throw new Error("No pending request to approve.");
210
+ }
211
+ try {
212
+ const result = await this.#executeSigning(request.type, request.account, request.chain, request.data);
213
+ this.#pendingRequest = null;
214
+ this.#notifyRequestListeners();
215
+ request.resolve(result);
216
+ } catch (error) {
217
+ this.#pendingRequest = null;
218
+ this.#notifyRequestListeners();
219
+ request.reject(error instanceof Error ? error : new Error(String(error)));
220
+ }
221
+ }
222
+ rejectRequest(reason) {
223
+ const request = this.#pendingRequest;
224
+ if (!request) {
225
+ throw new Error("No pending request to reject.");
226
+ }
227
+ this.#pendingRequest = null;
228
+ this.#notifyRequestListeners();
229
+ request.reject(new Error(reason ?? "Request rejected by user."));
230
+ }
231
+ /** Subscribe to pending request changes. Returns an unsubscribe function. */
232
+ onRequestChange(callback) {
233
+ this.#requestListeners.add(callback);
234
+ return () => {
235
+ this.#requestListeners.delete(callback);
236
+ };
237
+ }
238
+ /** The current pending connect request, or null if none. */
239
+ get pendingConnect() {
240
+ return this.#pendingConnect;
241
+ }
242
+ /** Expose the given addresses to the dApp. Pass an empty array to expose all accounts. */
243
+ approveConnect(selectedAddresses) {
244
+ const request = this.#pendingConnect;
245
+ if (!request) {
246
+ throw new Error("No pending connect request to approve.");
247
+ }
248
+ const selected = selectedAddresses.length > 0 ? this.#accounts.filter((a) => selectedAddresses.includes(a.address)) : [...this.#accounts];
249
+ this.#pendingConnect = null;
250
+ this.#notifyConnectListeners();
251
+ request.resolve({ accounts: selected });
252
+ }
253
+ rejectConnect(reason) {
254
+ const request = this.#pendingConnect;
255
+ if (!request) {
256
+ throw new Error("No pending connect request to reject.");
257
+ }
258
+ this.#pendingConnect = null;
259
+ this.#notifyConnectListeners();
260
+ request.reject(new Error(reason ?? "Connection rejected by user."));
261
+ }
262
+ /** Subscribe to pending connect request changes. Returns an unsubscribe function. */
263
+ onConnectChange(callback) {
264
+ this.#connectListeners.add(callback);
265
+ return () => {
266
+ this.#connectListeners.delete(callback);
267
+ };
268
+ }
269
+ #notifyRequestListeners() {
270
+ const request = this.#pendingRequest;
271
+ for (const listener of this.#requestListeners) {
272
+ listener(request);
273
+ }
274
+ }
275
+ #notifyConnectListeners() {
276
+ const request = this.#pendingConnect;
277
+ for (const listener of this.#connectListeners) {
278
+ listener(request);
279
+ }
280
+ }
281
+ #aggregateAccounts() {
282
+ return this.#adapters.flatMap((a) => a.getAccounts().map((acc) => acc.walletAccount));
283
+ }
284
+ #setupAdapterListeners() {
285
+ for (const adapter of this.#adapters) {
286
+ const unsub = adapter.onAccountsChanged(() => {
287
+ this.#accounts = this.#aggregateAccounts();
288
+ this.#events.emit("change", { accounts: this.#accounts });
289
+ });
290
+ this.#unsubscribeAdapters.push(unsub);
291
+ }
292
+ }
293
+ #on = (event, listener) => {
294
+ this.#events.on(event, listener);
295
+ return () => this.#events.off(event, listener);
296
+ };
297
+ #connect = async () => {
298
+ if (this.#autoConnect) {
299
+ return { accounts: this.accounts };
300
+ }
301
+ if (this.#pendingConnect) {
302
+ return Promise.reject(new Error("A connect request is already pending."));
303
+ }
304
+ return new Promise((resolve, reject) => {
305
+ this.#pendingConnect = {
306
+ id: crypto.randomUUID(),
307
+ resolve,
308
+ reject
309
+ };
310
+ this.#notifyConnectListeners();
311
+ });
312
+ };
313
+ #disconnect = async () => {};
314
+ #getClientForChain(chain) {
315
+ const network = getNetworkFromChain(chain);
316
+ if (!network) {
317
+ throw new Error(`Invalid chain identifier: ${chain}`);
318
+ }
319
+ return this.#ensureClient(network);
320
+ }
321
+ #loadNetworkUrls(defaults) {
322
+ if (!this.#persistNetworks || typeof localStorage === "undefined") {
323
+ return { ...defaults };
324
+ }
325
+ try {
326
+ const raw = localStorage.getItem(NETWORK_STORAGE_KEY);
327
+ if (raw) {
328
+ const parsed = JSON.parse(raw);
329
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
330
+ return parsed;
331
+ }
332
+ }
333
+ } catch {}
334
+ return { ...defaults };
335
+ }
336
+ #saveNetworkUrls() {
337
+ if (!this.#persistNetworks || typeof localStorage === "undefined") return;
338
+ localStorage.setItem(NETWORK_STORAGE_KEY, JSON.stringify(this.#networkUrls));
339
+ }
340
+ #ensureClient(network) {
341
+ if (!this.#clients[network]) {
342
+ const url = this.#networkUrls[network];
343
+ if (!url) {
344
+ throw new Error(`No client for network "${network}". Available: ${this.availableNetworks.join(", ")}`);
345
+ }
346
+ this.#clients[network] = this.#clientFactory(network, url);
347
+ }
348
+ return this.#clients[network];
349
+ }
350
+ #getSigner(address) {
351
+ for (const adapter of this.#adapters) {
352
+ const account = adapter.getAccount(address);
353
+ if (account) return account.signer;
354
+ }
355
+ const allAddresses = this.#adapters.flatMap((a) => a.getAccounts().map((acc) => acc.address));
356
+ throw new Error(`No account found for address "${address}". Available addresses: ${allAddresses.join(", ")}`);
357
+ }
358
+ #shouldAutoApprove(type, account, chain, data) {
359
+ const adapter = this.getAdapterForAccount(account.address);
360
+ if (adapter?.allowAutoSign === false) {
361
+ return false;
362
+ }
363
+ if (this.#autoApprove === true) {
364
+ return true;
365
+ }
366
+ if (typeof this.#autoApprove === "function") {
367
+ return this.#autoApprove({
368
+ type,
369
+ account,
370
+ chain,
371
+ data
372
+ });
373
+ }
374
+ return false;
375
+ }
376
+ async #executeSigning(type, account, chain, data) {
377
+ const signer = this.#getSigner(account.address);
378
+ const client = type !== "sign-personal-message" ? this.#getClientForChain(chain) : undefined;
379
+ return executeSigning({
380
+ type,
381
+ signer,
382
+ data,
383
+ client
384
+ });
385
+ }
386
+ #enqueueRequest(type, account, chain, data) {
387
+ if (this.#destroyed) {
388
+ return Promise.reject(new Error("Wallet has been destroyed."));
389
+ }
390
+ if (this.#shouldAutoApprove(type, account, chain, data)) {
391
+ return this.#executeSigning(type, account, chain, data);
392
+ }
393
+ if (this.#pendingRequest) {
394
+ return Promise.reject(new Error("A signing request is already pending."));
395
+ }
396
+ return new Promise((resolve, reject) => {
397
+ this.#pendingRequest = {
398
+ id: crypto.randomUUID(),
399
+ type,
400
+ account,
401
+ chain,
402
+ data,
403
+ resolve,
404
+ reject
405
+ };
406
+ this.#notifyRequestListeners();
407
+ });
408
+ }
409
+ #signPersonalMessage = async (input) => {
410
+ return this.#enqueueRequest("sign-personal-message", input.account, input.chain ?? "sui:unknown", input.message);
411
+ };
412
+ #signTransaction = async (input) => {
413
+ const txJson = await input.transaction.toJSON();
414
+ return this.#enqueueRequest("sign-transaction", input.account, input.chain, txJson);
415
+ };
416
+ #signAndExecuteTransaction = async (input) => {
417
+ const txJson = await input.transaction.toJSON();
418
+ return this.#enqueueRequest("sign-and-execute-transaction", input.account, input.chain, txJson);
419
+ };
420
+ };
421
+
422
+ //#endregion
423
+ export { DEFAULT_NETWORK_URLS, DevWallet };
424
+ //# sourceMappingURL=dev-wallet.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-wallet.mjs","names":["#adapters","#name","#icon","#autoApprove","#autoConnect","#clientFactory","#persistNetworks","#networkUrls","#loadNetworkUrls","#clients","#activeNetwork","#accounts","#aggregateAccounts","#events","#unsubscribeAdapters","#pendingRequest","#requestListeners","#pendingConnect","#connectListeners","#setupAdapterListeners","#connect","#on","#disconnect","#signPersonalMessage","#signTransaction","#signAndExecuteTransaction","#ensureClient","#saveNetworkUrls","#destroyed","#executeSigning","#notifyRequestListeners","#notifyConnectListeners","#getSigner","#getClientForChain","#shouldAutoApprove","#enqueueRequest"],"sources":["../../src/wallet/dev-wallet.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '@mysten/sui/client';\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\nimport { mitt, type Emitter } from '@mysten/utils';\nimport type {\n\tStandardConnectFeature,\n\tStandardConnectMethod,\n\tStandardDisconnectFeature,\n\tStandardDisconnectMethod,\n\tStandardEventsFeature,\n\tStandardEventsOnMethod,\n\tSuiFeatures,\n\tSuiSignAndExecuteTransactionMethod,\n\tSuiSignPersonalMessageMethod,\n\tSuiSignTransactionMethod,\n\tWallet,\n\tWalletAccount,\n\tWalletIcon,\n} from '@mysten/wallet-standard';\nimport { getWallets, ReadonlyWalletAccount, SUI_CHAINS } from '@mysten/wallet-standard';\n\nimport type { SignerAdapter } from '../types.js';\nimport { DEFAULT_WALLET_ICON, getNetworkFromChain, type WalletEventsMap } from './constants.js';\nimport { type SigningResult, executeSigning } from './signing.js';\n\nconst DEFAULT_WALLET_NAME = 'Dev Wallet';\nconst NETWORK_STORAGE_KEY = 'dev-wallet:networks';\n\n/**\n * Default gRPC endpoint URLs for standard Sui networks (devnet, testnet, localnet).\n */\nexport const DEFAULT_NETWORK_URLS = {\n\tdevnet: 'https://fullnode.devnet.sui.io:443',\n\ttestnet: 'https://fullnode.testnet.sui.io:443',\n\tlocalnet: 'http://127.0.0.1:9000',\n} as const;\n\n/** A pending signing request waiting for user approval via the wallet UI. */\nexport interface WalletRequest {\n\tid: string;\n\ttype: 'sign-transaction' | 'sign-and-execute-transaction' | 'sign-personal-message';\n\taccount: WalletAccount;\n\tchain: string;\n\t/** Transaction JSON string for sign/execute, Uint8Array for personal messages. */\n\tdata: string | Uint8Array;\n\tresolve: (result: SigningResult) => void;\n\treject: (error: Error) => void;\n}\n\n/** Public view of a pending signing request, omitting internal resolve/reject callbacks. */\nexport type PendingSigningRequest = Omit<WalletRequest, 'resolve' | 'reject'>;\n\nexport interface ConnectRequest {\n\tid: string;\n\tresolve: (result: { accounts: readonly WalletAccount[] }) => void;\n\treject: (error: Error) => void;\n}\n\n/** Public view of a pending connect request, omitting internal resolve/reject callbacks. */\nexport type PendingConnectRequest = Omit<ConnectRequest, 'resolve' | 'reject'>;\n\n/**\n * Auto-approval policy for signing requests.\n * `true` approves all requests; a function is called per-request and returns `true` to approve.\n */\nexport type AutoApprovePolicy =\n\t| boolean\n\t| ((request: {\n\t\t\ttype: WalletRequest['type'];\n\t\t\taccount: WalletAccount;\n\t\t\tchain: string;\n\t\t\tdata: string | Uint8Array;\n\t }) => boolean);\n\nexport interface DevWalletConfig {\n\tadapters: SignerAdapter[];\n\t/** Network URLs by name (network → gRPC endpoint). Defaults to devnet, testnet, and localnet. */\n\tnetworks?: Record<string, string>;\n\t/** Display name for the wallet. Defaults to 'Dev Wallet'. */\n\tname?: string;\n\ticon?: WalletIcon;\n\t/** Initially active network. Defaults to the first key in `networks`. */\n\tactiveNetwork?: string;\n\t/**\n\t * When set, matching requests are signed immediately without queuing for user approval.\n\t * `true` approves everything; a function is called per-request for fine-grained control.\n\t */\n\tautoApprove?: AutoApprovePolicy;\n\t/** When true, connect requests resolve immediately with all accounts. */\n\tautoConnect?: boolean;\n\t/** Factory to create a client for a given network. Defaults to SuiGrpcClient. */\n\tclientFactory?: (network: string, url: string) => ClientWithCoreApi;\n\t/**\n\t * Persist network URLs to localStorage so custom configurations survive page reloads\n\t * and are shared with popup windows.\n\t */\n\tpersistNetworks?: boolean;\n}\n\n/**\n * wallet-standard Wallet implementation for development. All signing requests are queued\n * and require explicit approval — either via the UI or programmatically via `approveRequest()`.\n */\nexport class DevWallet implements Wallet {\n\treadonly #adapters: SignerAdapter[];\n\t#networkUrls: Record<string, string>;\n\t#clients: Record<string, ClientWithCoreApi>;\n\t#activeNetwork: string;\n\treadonly #name: string;\n\treadonly #icon: WalletIcon;\n\treadonly #autoApprove: AutoApprovePolicy;\n\treadonly #autoConnect: boolean;\n\treadonly #clientFactory: (network: string, url: string) => ClientWithCoreApi;\n\treadonly #persistNetworks: boolean;\n\t#accounts: ReadonlyWalletAccount[];\n\t#events: Emitter<WalletEventsMap>;\n\t#unsubscribeAdapters: (() => void)[];\n\t#pendingRequest: WalletRequest | null;\n\t#requestListeners: Set<(request: PendingSigningRequest | null) => void>;\n\t#pendingConnect: ConnectRequest | null;\n\t#connectListeners: Set<(request: PendingConnectRequest | null) => void>;\n\t#destroyed = false;\n\n\tconstructor(config: DevWalletConfig) {\n\t\tif (config.adapters.length === 0) {\n\t\t\tconsole.warn('[dev-wallet] No adapters provided. The wallet will have no accounts.');\n\t\t}\n\t\tthis.#adapters = config.adapters;\n\t\tthis.#persistNetworks = config.persistNetworks ?? false;\n\t\tthis.#networkUrls = this.#loadNetworkUrls(config.networks ?? DEFAULT_NETWORK_URLS);\n\t\tthis.#clients = {};\n\t\tthis.#activeNetwork = config.activeNetwork ?? Object.keys(this.#networkUrls)[0] ?? '';\n\t\tthis.#name = config.name ?? DEFAULT_WALLET_NAME;\n\t\tthis.#icon = config.icon ?? DEFAULT_WALLET_ICON;\n\t\tthis.#autoApprove = config.autoApprove ?? false;\n\t\tthis.#autoConnect = config.autoConnect ?? false;\n\t\tthis.#clientFactory =\n\t\t\tconfig.clientFactory ?? ((network, url) => new SuiGrpcClient({ baseUrl: url, network }));\n\t\tthis.#accounts = this.#aggregateAccounts();\n\t\tthis.#events = mitt();\n\t\tthis.#unsubscribeAdapters = [];\n\t\tthis.#pendingRequest = null;\n\t\tthis.#requestListeners = new Set();\n\t\tthis.#pendingConnect = null;\n\t\tthis.#connectListeners = new Set();\n\n\t\tthis.#setupAdapterListeners();\n\t}\n\n\tget version() {\n\t\treturn '1.0.0' as const;\n\t}\n\n\tget name() {\n\t\treturn this.#name;\n\t}\n\n\tget icon() {\n\t\treturn this.#icon;\n\t}\n\n\tget chains() {\n\t\treturn SUI_CHAINS;\n\t}\n\n\tget accounts(): readonly ReadonlyWalletAccount[] {\n\t\treturn this.#accounts;\n\t}\n\n\tget features(): StandardConnectFeature &\n\t\tStandardEventsFeature &\n\t\tStandardDisconnectFeature &\n\t\tSuiFeatures {\n\t\treturn {\n\t\t\t'standard:connect': {\n\t\t\t\tversion: '1.0.0',\n\t\t\t\tconnect: this.#connect,\n\t\t\t},\n\t\t\t'standard:events': {\n\t\t\t\tversion: '1.0.0',\n\t\t\t\ton: this.#on,\n\t\t\t},\n\t\t\t'standard:disconnect': {\n\t\t\t\tversion: '1.0.0',\n\t\t\t\tdisconnect: this.#disconnect,\n\t\t\t},\n\t\t\t'sui:signPersonalMessage': {\n\t\t\t\tversion: '1.1.0',\n\t\t\t\tsignPersonalMessage: this.#signPersonalMessage,\n\t\t\t},\n\t\t\t'sui:signTransaction': {\n\t\t\t\tversion: '2.0.0',\n\t\t\t\tsignTransaction: this.#signTransaction,\n\t\t\t},\n\t\t\t'sui:signAndExecuteTransaction': {\n\t\t\t\tversion: '2.0.0',\n\t\t\t\tsignAndExecuteTransaction: this.#signAndExecuteTransaction,\n\t\t\t},\n\t\t};\n\t}\n\n\t/** The current pending signing request, or null if none. */\n\tget pendingRequest(): PendingSigningRequest | null {\n\t\treturn this.#pendingRequest;\n\t}\n\n\tget adapters(): readonly SignerAdapter[] {\n\t\treturn this.#adapters;\n\t}\n\n\tgetAdapterForAccount(address: string): SignerAdapter | undefined {\n\t\treturn this.#adapters.find((a) => a.getAccount(address) !== undefined);\n\t}\n\n\t/** Eagerly creates and returns clients for all configured networks. Prefer `getClient()` or `activeClient` for single-network access. */\n\tget clients(): Record<string, ClientWithCoreApi> {\n\t\tfor (const name of Object.keys(this.#networkUrls)) {\n\t\t\tthis.#ensureClient(name);\n\t\t}\n\t\treturn { ...this.#clients };\n\t}\n\n\tgetClient(network: string): ClientWithCoreApi {\n\t\treturn this.#ensureClient(network);\n\t}\n\n\tget networkUrls(): Record<string, string> {\n\t\treturn { ...this.#networkUrls };\n\t}\n\n\tget activeNetwork(): string {\n\t\treturn this.#activeNetwork;\n\t}\n\n\tget activeClient(): ClientWithCoreApi | null {\n\t\tif (!this.#activeNetwork || !this.#networkUrls[this.#activeNetwork]) return null;\n\t\treturn this.#ensureClient(this.#activeNetwork);\n\t}\n\n\tget availableNetworks(): string[] {\n\t\treturn Object.keys(this.#networkUrls);\n\t}\n\n\t/** Switch the active network. Emits a `change` event. */\n\tsetActiveNetwork(network: string): void {\n\t\tif (!this.#networkUrls[network]) {\n\t\t\tthrow new Error(\n\t\t\t\t`No client for network \"${network}\". Available: ${this.availableNetworks.join(', ')}`,\n\t\t\t);\n\t\t}\n\t\tthis.#activeNetwork = network;\n\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t}\n\n\taddNetwork(name: string, url: string): void {\n\t\tlet parsed: URL;\n\t\ttry {\n\t\t\tparsed = new URL(url);\n\t\t} catch {\n\t\t\tthrow new Error(`Invalid URL: ${url}`);\n\t\t}\n\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n\t\t\tthrow new Error(`Invalid URL: must use http or https (got ${parsed.protocol})`);\n\t\t}\n\t\tthis.#networkUrls[name] = url;\n\t\tthis.#clients[name] = this.#clientFactory(name, url);\n\t\tthis.#saveNetworkUrls();\n\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t}\n\n\tremoveNetwork(name: string): void {\n\t\tdelete this.#networkUrls[name];\n\t\tdelete this.#clients[name];\n\t\tif (this.#activeNetwork === name) {\n\t\t\tthis.#activeNetwork = Object.keys(this.#networkUrls)[0] ?? '';\n\t\t}\n\t\tthis.#saveNetworkUrls();\n\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t}\n\n\t/** Register this wallet with the wallet-standard registry. Returns an unregister function. */\n\tregister(): () => void {\n\t\tif (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') {\n\t\t\tconsole.warn(\n\t\t\t\t'[@mysten-incubation/dev-wallet] DevWallet is intended for development only. Do not use in production.',\n\t\t\t);\n\t\t}\n\t\tconst walletsApi = getWallets();\n\t\treturn walletsApi.register(this);\n\t}\n\n\t/** Reject any pending requests, unsubscribe from adapters, destroy them, and clear all listeners. */\n\tdestroy(): void {\n\t\tthis.#destroyed = true;\n\t\tfor (const unsub of this.#unsubscribeAdapters) {\n\t\t\tunsub();\n\t\t}\n\t\tthis.#unsubscribeAdapters = [];\n\t\tfor (const adapter of this.#adapters) {\n\t\t\tadapter.destroy();\n\t\t}\n\t\tif (this.#pendingRequest) {\n\t\t\tthis.#pendingRequest.reject(new Error('Wallet destroyed.'));\n\t\t\tthis.#pendingRequest = null;\n\t\t}\n\t\tif (this.#pendingConnect) {\n\t\t\tthis.#pendingConnect.reject(new Error('Wallet destroyed.'));\n\t\t\tthis.#pendingConnect = null;\n\t\t}\n\t\tthis.#requestListeners.clear();\n\t\tthis.#connectListeners.clear();\n\t\tthis.#events.all.clear();\n\t}\n\n\t/** Sign the pending request using the account's adapter signer and resolve the promise. */\n\tasync approveRequest(): Promise<void> {\n\t\tconst request = this.#pendingRequest;\n\t\tif (!request) {\n\t\t\tthrow new Error('No pending request to approve.');\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await this.#executeSigning(\n\t\t\t\trequest.type,\n\t\t\t\trequest.account,\n\t\t\t\trequest.chain,\n\t\t\t\trequest.data,\n\t\t\t);\n\t\t\tthis.#pendingRequest = null;\n\t\t\tthis.#notifyRequestListeners();\n\t\t\trequest.resolve(result);\n\t\t} catch (error) {\n\t\t\tthis.#pendingRequest = null;\n\t\t\tthis.#notifyRequestListeners();\n\t\t\trequest.reject(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t}\n\n\trejectRequest(reason?: string): void {\n\t\tconst request = this.#pendingRequest;\n\t\tif (!request) {\n\t\t\tthrow new Error('No pending request to reject.');\n\t\t}\n\t\tthis.#pendingRequest = null;\n\t\tthis.#notifyRequestListeners();\n\t\trequest.reject(new Error(reason ?? 'Request rejected by user.'));\n\t}\n\n\t/** Subscribe to pending request changes. Returns an unsubscribe function. */\n\tonRequestChange(callback: (request: PendingSigningRequest | null) => void): () => void {\n\t\tthis.#requestListeners.add(callback);\n\t\treturn () => {\n\t\t\tthis.#requestListeners.delete(callback);\n\t\t};\n\t}\n\n\t/** The current pending connect request, or null if none. */\n\tget pendingConnect(): PendingConnectRequest | null {\n\t\treturn this.#pendingConnect;\n\t}\n\n\t/** Expose the given addresses to the dApp. Pass an empty array to expose all accounts. */\n\tapproveConnect(selectedAddresses: string[]): void {\n\t\tconst request = this.#pendingConnect;\n\t\tif (!request) {\n\t\t\tthrow new Error('No pending connect request to approve.');\n\t\t}\n\n\t\tconst selected =\n\t\t\tselectedAddresses.length > 0\n\t\t\t\t? this.#accounts.filter((a) => selectedAddresses.includes(a.address))\n\t\t\t\t: [...this.#accounts];\n\n\t\tthis.#pendingConnect = null;\n\t\tthis.#notifyConnectListeners();\n\t\trequest.resolve({ accounts: selected });\n\t}\n\n\trejectConnect(reason?: string): void {\n\t\tconst request = this.#pendingConnect;\n\t\tif (!request) {\n\t\t\tthrow new Error('No pending connect request to reject.');\n\t\t}\n\t\tthis.#pendingConnect = null;\n\t\tthis.#notifyConnectListeners();\n\t\trequest.reject(new Error(reason ?? 'Connection rejected by user.'));\n\t}\n\n\t/** Subscribe to pending connect request changes. Returns an unsubscribe function. */\n\tonConnectChange(callback: (request: PendingConnectRequest | null) => void): () => void {\n\t\tthis.#connectListeners.add(callback);\n\t\treturn () => {\n\t\t\tthis.#connectListeners.delete(callback);\n\t\t};\n\t}\n\n\t#notifyRequestListeners() {\n\t\tconst request = this.#pendingRequest;\n\t\tfor (const listener of this.#requestListeners) {\n\t\t\tlistener(request);\n\t\t}\n\t}\n\n\t#notifyConnectListeners() {\n\t\tconst request = this.#pendingConnect;\n\t\tfor (const listener of this.#connectListeners) {\n\t\t\tlistener(request);\n\t\t}\n\t}\n\n\t#aggregateAccounts(): ReadonlyWalletAccount[] {\n\t\treturn this.#adapters.flatMap((a) => a.getAccounts().map((acc) => acc.walletAccount));\n\t}\n\n\t#setupAdapterListeners() {\n\t\tfor (const adapter of this.#adapters) {\n\t\t\tconst unsub = adapter.onAccountsChanged(() => {\n\t\t\t\tthis.#accounts = this.#aggregateAccounts();\n\t\t\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t\t\t});\n\t\t\tthis.#unsubscribeAdapters.push(unsub);\n\t\t}\n\t}\n\n\t#on: StandardEventsOnMethod = (event, listener) => {\n\t\tthis.#events.on(event, listener);\n\t\treturn () => this.#events.off(event, listener);\n\t};\n\n\t#connect: StandardConnectMethod = async () => {\n\t\t// Auto-connect: return all accounts immediately\n\t\tif (this.#autoConnect) {\n\t\t\treturn { accounts: this.accounts };\n\t\t}\n\n\t\t// Queue a connect request for user to select accounts\n\t\tif (this.#pendingConnect) {\n\t\t\treturn Promise.reject(new Error('A connect request is already pending.'));\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.#pendingConnect = {\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t};\n\t\t\tthis.#notifyConnectListeners();\n\t\t});\n\t};\n\n\t#disconnect: StandardDisconnectMethod = async () => {\n\t\t// Disconnecting ends the dApp session but does not affect wallet state.\n\t\t// The wallet retains its accounts and adapter subscriptions.\n\t};\n\n\t#getClientForChain(chain: string) {\n\t\tconst network = getNetworkFromChain(chain);\n\t\tif (!network) {\n\t\t\tthrow new Error(`Invalid chain identifier: ${chain}`);\n\t\t}\n\t\treturn this.#ensureClient(network);\n\t}\n\n\t#loadNetworkUrls(defaults: Record<string, string>): Record<string, string> {\n\t\tif (!this.#persistNetworks || typeof localStorage === 'undefined') {\n\t\t\treturn { ...defaults };\n\t\t}\n\t\ttry {\n\t\t\tconst raw = localStorage.getItem(NETWORK_STORAGE_KEY);\n\t\t\tif (raw) {\n\t\t\t\tconst parsed = JSON.parse(raw);\n\t\t\t\tif (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n\t\t\t\t\treturn parsed as Record<string, string>;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Corrupted data — fall through to defaults\n\t\t}\n\t\treturn { ...defaults };\n\t}\n\n\t#saveNetworkUrls(): void {\n\t\tif (!this.#persistNetworks || typeof localStorage === 'undefined') return;\n\t\tlocalStorage.setItem(NETWORK_STORAGE_KEY, JSON.stringify(this.#networkUrls));\n\t}\n\n\t#ensureClient(network: string): ClientWithCoreApi {\n\t\tif (!this.#clients[network]) {\n\t\t\tconst url = this.#networkUrls[network];\n\t\t\tif (!url) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No client for network \"${network}\". Available: ${this.availableNetworks.join(', ')}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.#clients[network] = this.#clientFactory(network, url);\n\t\t}\n\t\treturn this.#clients[network];\n\t}\n\n\t#getSigner(address: string) {\n\t\tfor (const adapter of this.#adapters) {\n\t\t\tconst account = adapter.getAccount(address);\n\t\t\tif (account) return account.signer;\n\t\t}\n\t\tconst allAddresses = this.#adapters.flatMap((a) => a.getAccounts().map((acc) => acc.address));\n\t\tthrow new Error(\n\t\t\t`No account found for address \"${address}\". Available addresses: ${allAddresses.join(', ')}`,\n\t\t);\n\t}\n\n\t#shouldAutoApprove(\n\t\ttype: WalletRequest['type'],\n\t\taccount: WalletAccount,\n\t\tchain: string,\n\t\tdata: string | Uint8Array,\n\t): boolean {\n\t\t// Check adapter-level opt-out first — CLI adapters never auto-sign\n\t\tconst adapter = this.getAdapterForAccount(account.address);\n\t\tif (adapter?.allowAutoSign === false) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.#autoApprove === true) {\n\t\t\treturn true;\n\t\t}\n\t\tif (typeof this.#autoApprove === 'function') {\n\t\t\treturn this.#autoApprove({ type, account, chain, data });\n\t\t}\n\t\treturn false;\n\t}\n\n\tasync #executeSigning(\n\t\ttype: WalletRequest['type'],\n\t\taccount: WalletAccount,\n\t\tchain: string,\n\t\tdata: string | Uint8Array,\n\t) {\n\t\tconst signer = this.#getSigner(account.address);\n\t\tconst client = type !== 'sign-personal-message' ? this.#getClientForChain(chain) : undefined;\n\t\treturn executeSigning({ type, signer, data, client });\n\t}\n\n\t#enqueueRequest<T extends WalletRequest['type']>(\n\t\ttype: T,\n\t\taccount: WalletAccount,\n\t\tchain: string,\n\t\tdata: string | Uint8Array,\n\t): Promise<Extract<SigningResult, { type: T }>> {\n\t\ttype Result = Extract<SigningResult, { type: T }>;\n\t\tif (this.#destroyed) {\n\t\t\treturn Promise.reject(new Error('Wallet has been destroyed.'));\n\t\t}\n\t\tif (this.#shouldAutoApprove(type, account, chain, data)) {\n\t\t\treturn this.#executeSigning(type, account, chain, data) as Promise<Result>;\n\t\t}\n\n\t\t// Only one request at a time — subsequent requests are immediately rejected.\n\t\t// DApps that batch transactions should serialize their signing calls.\n\t\tif (this.#pendingRequest) {\n\t\t\treturn Promise.reject(new Error('A signing request is already pending.'));\n\t\t}\n\n\t\treturn new Promise<Result>((resolve, reject) => {\n\t\t\tthis.#pendingRequest = {\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\ttype,\n\t\t\t\taccount,\n\t\t\t\tchain,\n\t\t\t\tdata,\n\t\t\t\tresolve: resolve as (result: SigningResult) => void,\n\t\t\t\treject,\n\t\t\t};\n\t\t\tthis.#notifyRequestListeners();\n\t\t});\n\t}\n\n\t#signPersonalMessage: SuiSignPersonalMessageMethod = async (input) => {\n\t\treturn this.#enqueueRequest(\n\t\t\t'sign-personal-message',\n\t\t\tinput.account,\n\t\t\tinput.chain ?? 'sui:unknown',\n\t\t\tinput.message,\n\t\t);\n\t};\n\n\t#signTransaction: SuiSignTransactionMethod = async (input) => {\n\t\tconst txJson = await input.transaction.toJSON();\n\t\treturn this.#enqueueRequest('sign-transaction', input.account, input.chain, txJson);\n\t};\n\n\t#signAndExecuteTransaction: SuiSignAndExecuteTransactionMethod = async (input) => {\n\t\tconst txJson = await input.transaction.toJSON();\n\t\treturn this.#enqueueRequest('sign-and-execute-transaction', input.account, input.chain, txJson);\n\t};\n}\n"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { SignerAdapter } from "../types.mjs";
2
+ import { AutoApprovePolicy, DevWallet } from "./dev-wallet.mjs";
3
+ import { WalletIcon } from "@mysten/wallet-standard";
4
+ import { ClientWithCoreApi } from "@mysten/sui/client";
5
+
6
+ //#region src/wallet/initializer.d.ts
7
+ /**
8
+ * Configuration for the dev wallet initializer.
9
+ * Unlike {@link DevWalletConfig}, `networks` and `clientFactory` are omitted — they come
10
+ * from the dApp Kit context at initialization time.
11
+ */
12
+ interface DevWalletInitializerConfig {
13
+ adapters: SignerAdapter[];
14
+ name?: string;
15
+ icon?: WalletIcon;
16
+ autoApprove?: AutoApprovePolicy;
17
+ autoConnect?: boolean;
18
+ /** Call `adapter.initialize()` automatically. Defaults to true. */
19
+ autoInitialize?: boolean;
20
+ /** Create an initial account after initialization if no accounts exist. Defaults to true. */
21
+ createInitialAccount?: boolean;
22
+ /** Mount the floating wallet drawer UI. Defaults to false. */
23
+ mountUI?: boolean;
24
+ /** Container element for the UI drawer. Defaults to document.body. */
25
+ container?: HTMLElement;
26
+ /** Called with the DevWallet instance after creation. */
27
+ onWalletCreated?: (wallet: DevWallet) => void;
28
+ }
29
+ /**
30
+ * Creates a wallet initializer for `createDAppKit({ walletInitializers: [...] })`.
31
+ * The wallet uses dApp Kit's networks and client factory and is unregistered when dApp Kit tears down.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { createDAppKit } from '@mysten/dapp-kit-react';
36
+ * import { devWalletInitializer } from '@mysten-incubation/dev-wallet';
37
+ * import { WebCryptoSignerAdapter } from '@mysten-incubation/dev-wallet/adapters';
38
+ *
39
+ * const dAppKit = createDAppKit({
40
+ * networks: ['devnet', 'testnet'],
41
+ * createClient(network) { ... },
42
+ * walletInitializers: [
43
+ * devWalletInitializer({
44
+ * adapters: [new WebCryptoSignerAdapter()],
45
+ * autoConnect: true,
46
+ * mountUI: true,
47
+ * }),
48
+ * ],
49
+ * });
50
+ * ```
51
+ */
52
+ declare function devWalletInitializer(config: DevWalletInitializerConfig): {
53
+ id: string;
54
+ initialize(input: {
55
+ networks: readonly string[];
56
+ getClient: (network?: string) => ClientWithCoreApi;
57
+ }): Promise<{
58
+ unregister: () => void;
59
+ }>;
60
+ };
61
+ //#endregion
62
+ export { DevWalletInitializerConfig, devWalletInitializer };
63
+ //# sourceMappingURL=initializer.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initializer.d.mts","names":[],"sources":["../../src/wallet/initializer.ts"],"mappings":";;;;;;;;AAcA;;;UAAiB,0BAAA;EAChB,QAAA,EAAU,aAAA;EACV,IAAA;EACA,IAAA,GAAO,UAAA;EACP,WAAA,GAAc,iBAAA;EACd,WAAA;EAUoC;EARpC,cAAA;EANU;EAQV,oBAAA;EANA;EAQA,OAAA;EAPA;EASA,SAAA,GAAY,WAAA;EARZ;EAUA,eAAA,IAAmB,MAAA,EAAQ,SAAA;AAAA;;;;;;;;;AA0B5B;;;;;;;;;;;;;;;iBAAgB,oBAAA,CAAqB,MAAA,EAAQ,0BAAA;EAC5C,EAAA;EACA,UAAA,CAAW,KAAA;IACV,QAAA;IACA,SAAA,GAAY,OAAA,cAAqB,iBAAA;EAAA,IAC9B,OAAA;IAAU,UAAA;EAAA;AAAA"}
@@ -0,0 +1,75 @@
1
+ import { DevWallet } from "./dev-wallet.mjs";
2
+
3
+ //#region src/wallet/initializer.ts
4
+ /**
5
+ * Creates a wallet initializer for `createDAppKit({ walletInitializers: [...] })`.
6
+ * The wallet uses dApp Kit's networks and client factory and is unregistered when dApp Kit tears down.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { createDAppKit } from '@mysten/dapp-kit-react';
11
+ * import { devWalletInitializer } from '@mysten-incubation/dev-wallet';
12
+ * import { WebCryptoSignerAdapter } from '@mysten-incubation/dev-wallet/adapters';
13
+ *
14
+ * const dAppKit = createDAppKit({
15
+ * networks: ['devnet', 'testnet'],
16
+ * createClient(network) { ... },
17
+ * walletInitializers: [
18
+ * devWalletInitializer({
19
+ * adapters: [new WebCryptoSignerAdapter()],
20
+ * autoConnect: true,
21
+ * mountUI: true,
22
+ * }),
23
+ * ],
24
+ * });
25
+ * ```
26
+ */
27
+ function devWalletInitializer(config) {
28
+ return {
29
+ id: "dev-wallet-initializer",
30
+ async initialize({ networks, getClient }) {
31
+ const { autoInitialize = true, createInitialAccount = true, mountUI = false } = config;
32
+ if (autoInitialize) {
33
+ await Promise.all(config.adapters.map((a) => a.initialize()));
34
+ }
35
+ if (createInitialAccount) {
36
+ const hasAccounts = config.adapters.some((a) => a.getAccounts().length > 0);
37
+ if (!hasAccounts) {
38
+ const creatableAdapter = config.adapters.find((a) => a.createAccount && a.getAccounts().length === 0);
39
+ if (creatableAdapter?.createAccount) {
40
+ await creatableAdapter.createAccount({ label: "Dev Account" });
41
+ }
42
+ }
43
+ }
44
+ const networkUrls = {};
45
+ for (const network of networks) {
46
+ networkUrls[network] = `dapp-kit://${network}`;
47
+ }
48
+ const wallet = new DevWallet({
49
+ adapters: config.adapters,
50
+ networks: networkUrls,
51
+ name: config.name,
52
+ icon: config.icon,
53
+ autoApprove: config.autoApprove,
54
+ autoConnect: config.autoConnect,
55
+ clientFactory: (network) => getClient(network)
56
+ });
57
+ config.onWalletCreated?.(wallet);
58
+ let unmountUI;
59
+ if (mountUI && typeof document !== "undefined") {
60
+ const { mountDevWallet } = await import("../ui/mount.mjs");
61
+ unmountUI = mountDevWallet(wallet, { container: config.container });
62
+ }
63
+ const unregister = wallet.register();
64
+ return { unregister() {
65
+ unmountUI?.();
66
+ unregister();
67
+ wallet.destroy();
68
+ } };
69
+ }
70
+ };
71
+ }
72
+
73
+ //#endregion
74
+ export { devWalletInitializer };
75
+ //# sourceMappingURL=initializer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initializer.mjs","names":[],"sources":["../../src/wallet/initializer.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '@mysten/sui/client';\nimport type { WalletIcon } from '@mysten/wallet-standard';\n\nimport type { SignerAdapter } from '../types.js';\nimport { DevWallet, type AutoApprovePolicy } from './dev-wallet.js';\n\n/**\n * Configuration for the dev wallet initializer.\n * Unlike {@link DevWalletConfig}, `networks` and `clientFactory` are omitted — they come\n * from the dApp Kit context at initialization time.\n */\nexport interface DevWalletInitializerConfig {\n\tadapters: SignerAdapter[];\n\tname?: string;\n\ticon?: WalletIcon;\n\tautoApprove?: AutoApprovePolicy;\n\tautoConnect?: boolean;\n\t/** Call `adapter.initialize()` automatically. Defaults to true. */\n\tautoInitialize?: boolean;\n\t/** Create an initial account after initialization if no accounts exist. Defaults to true. */\n\tcreateInitialAccount?: boolean;\n\t/** Mount the floating wallet drawer UI. Defaults to false. */\n\tmountUI?: boolean;\n\t/** Container element for the UI drawer. Defaults to document.body. */\n\tcontainer?: HTMLElement;\n\t/** Called with the DevWallet instance after creation. */\n\tonWalletCreated?: (wallet: DevWallet) => void;\n}\n\n/**\n * Creates a wallet initializer for `createDAppKit({ walletInitializers: [...] })`.\n * The wallet uses dApp Kit's networks and client factory and is unregistered when dApp Kit tears down.\n *\n * @example\n * ```ts\n * import { createDAppKit } from '@mysten/dapp-kit-react';\n * import { devWalletInitializer } from '@mysten-incubation/dev-wallet';\n * import { WebCryptoSignerAdapter } from '@mysten-incubation/dev-wallet/adapters';\n *\n * const dAppKit = createDAppKit({\n * networks: ['devnet', 'testnet'],\n * createClient(network) { ... },\n * walletInitializers: [\n * devWalletInitializer({\n * adapters: [new WebCryptoSignerAdapter()],\n * autoConnect: true,\n * mountUI: true,\n * }),\n * ],\n * });\n * ```\n */\nexport function devWalletInitializer(config: DevWalletInitializerConfig): {\n\tid: string;\n\tinitialize(input: {\n\t\tnetworks: readonly string[];\n\t\tgetClient: (network?: string) => ClientWithCoreApi;\n\t}): Promise<{ unregister: () => void }>;\n} {\n\treturn {\n\t\tid: 'dev-wallet-initializer',\n\t\tasync initialize({ networks, getClient }) {\n\t\t\tconst { autoInitialize = true, createInitialAccount = true, mountUI = false } = config;\n\n\t\t\t// Initialize adapters\n\t\t\tif (autoInitialize) {\n\t\t\t\tawait Promise.all(config.adapters.map((a) => a.initialize()));\n\t\t\t}\n\n\t\t\t// Create initial account if needed\n\t\t\tif (createInitialAccount) {\n\t\t\t\tconst hasAccounts = config.adapters.some((a) => a.getAccounts().length > 0);\n\t\t\t\tif (!hasAccounts) {\n\t\t\t\t\tconst creatableAdapter = config.adapters.find(\n\t\t\t\t\t\t(a) => a.createAccount && a.getAccounts().length === 0,\n\t\t\t\t\t);\n\t\t\t\t\tif (creatableAdapter?.createAccount) {\n\t\t\t\t\t\tawait creatableAdapter.createAccount({ label: 'Dev Account' });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Map dApp Kit networks to DevWallet format.\n\t\t\t// DevWallet needs a Record<string, string> of network name → URL, but\n\t\t\t// the clientFactory we provide delegates to getClient, so the URLs are\n\t\t\t// never actually used. We use placeholder values.\n\t\t\tconst networkUrls: Record<string, string> = {};\n\t\t\tfor (const network of networks) {\n\t\t\t\tnetworkUrls[network] = `dapp-kit://${network}`;\n\t\t\t}\n\n\t\t\tconst wallet = new DevWallet({\n\t\t\t\tadapters: config.adapters,\n\t\t\t\tnetworks: networkUrls,\n\t\t\t\tname: config.name,\n\t\t\t\ticon: config.icon,\n\t\t\t\tautoApprove: config.autoApprove,\n\t\t\t\tautoConnect: config.autoConnect,\n\t\t\t\tclientFactory: (network) => getClient(network),\n\t\t\t});\n\n\t\t\tconfig.onWalletCreated?.(wallet);\n\n\t\t\t// Mount UI if requested\n\t\t\tlet unmountUI: (() => void) | undefined;\n\t\t\tif (mountUI && typeof document !== 'undefined') {\n\t\t\t\tconst { mountDevWallet } = await import('../ui/mount.js');\n\t\t\t\tunmountUI = mountDevWallet(wallet, { container: config.container });\n\t\t\t}\n\n\t\t\tconst unregister = wallet.register();\n\t\t\treturn {\n\t\t\t\tunregister() {\n\t\t\t\t\tunmountUI?.();\n\t\t\t\t\tunregister();\n\t\t\t\t\twallet.destroy();\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,SAAgB,qBAAqB,QAMnC;AACD,QAAO;EACN,IAAI;EACJ,MAAM,WAAW,EAAE,UAAU,aAAa;GACzC,MAAM,EAAE,iBAAiB,MAAM,uBAAuB,MAAM,UAAU,UAAU;AAGhF,OAAI,gBAAgB;AACnB,UAAM,QAAQ,IAAI,OAAO,SAAS,KAAK,MAAM,EAAE,YAAY,CAAC,CAAC;;AAI9D,OAAI,sBAAsB;IACzB,MAAM,cAAc,OAAO,SAAS,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EAAE;AAC3E,QAAI,CAAC,aAAa;KACjB,MAAM,mBAAmB,OAAO,SAAS,MACvC,MAAM,EAAE,iBAAiB,EAAE,aAAa,CAAC,WAAW,EACrD;AACD,SAAI,kBAAkB,eAAe;AACpC,YAAM,iBAAiB,cAAc,EAAE,OAAO,eAAe,CAAC;;;;GASjE,MAAM,cAAsC,EAAE;AAC9C,QAAK,MAAM,WAAW,UAAU;AAC/B,gBAAY,WAAW,cAAc;;GAGtC,MAAM,SAAS,IAAI,UAAU;IAC5B,UAAU,OAAO;IACjB,UAAU;IACV,MAAM,OAAO;IACb,MAAM,OAAO;IACb,aAAa,OAAO;IACpB,aAAa,OAAO;IACpB,gBAAgB,YAAY,UAAU,QAAQ;IAC9C,CAAC;AAEF,UAAO,kBAAkB,OAAO;GAGhC,IAAI;AACJ,OAAI,WAAW,OAAO,aAAa,aAAa;IAC/C,MAAM,EAAE,mBAAmB,MAAM,OAAO;AACxC,gBAAY,eAAe,QAAQ,EAAE,WAAW,OAAO,WAAW,CAAC;;GAGpE,MAAM,aAAa,OAAO,UAAU;AACpC,UAAO,EACN,aAAa;AACZ,iBAAa;AACb,gBAAY;AACZ,WAAO,SAAS;MAEjB;;EAEF"}
@@ -0,0 +1,35 @@
1
+ import { Signer } from "@mysten/sui/cryptography";
2
+ import { ClientWithCoreApi } from "@mysten/sui/client";
3
+
4
+ //#region src/wallet/signing.d.ts
5
+ type SigningRequestType = 'sign-personal-message' | 'sign-transaction' | 'sign-and-execute-transaction';
6
+ interface ExecuteSigningOptions {
7
+ type: SigningRequestType;
8
+ signer: Signer;
9
+ data: string | Uint8Array;
10
+ client?: ClientWithCoreApi;
11
+ }
12
+ type SigningResult = {
13
+ type: 'sign-personal-message';
14
+ bytes: string;
15
+ signature: string;
16
+ } | {
17
+ type: 'sign-transaction';
18
+ bytes: string;
19
+ signature: string;
20
+ } | {
21
+ type: 'sign-and-execute-transaction';
22
+ bytes: string;
23
+ signature: string;
24
+ digest: string;
25
+ effects: string;
26
+ };
27
+ declare function executeSigning({
28
+ type,
29
+ signer,
30
+ data,
31
+ client
32
+ }: ExecuteSigningOptions): Promise<SigningResult>;
33
+ //#endregion
34
+ export { SigningResult };
35
+ //# sourceMappingURL=signing.d.mts.map