@mysten-incubation/dev-wallet 0.0.0 → 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.
- package/CHANGELOG.md +32 -0
- package/LICENSE +189 -0
- package/dist/_virtual/{_@oxc-project_runtime@0.107.0 → _@oxc-project_runtime@0.127.0}/helpers/decorate.mjs +2 -3
- package/dist/adapters/base-adapter.mjs +6 -7
- package/dist/adapters/base-adapter.mjs.map +1 -1
- package/dist/adapters/browser.d.mts +4 -1
- package/dist/adapters/browser.mjs +4 -2
- package/dist/adapters/build-managed-account.mjs +8 -10
- package/dist/adapters/build-managed-account.mjs.map +1 -1
- package/dist/adapters/devstack-adapter.d.mts +111 -0
- package/dist/adapters/devstack-adapter.d.mts.map +1 -0
- package/dist/adapters/devstack-adapter.mjs +224 -0
- package/dist/adapters/devstack-adapter.mjs.map +1 -0
- package/dist/adapters/devstack-paths.d.mts +12 -0
- package/dist/adapters/devstack-paths.d.mts.map +1 -0
- package/dist/adapters/devstack-paths.mjs +12 -0
- package/dist/adapters/devstack-paths.mjs.map +1 -0
- package/dist/adapters/fork-relay.d.mts +109 -0
- package/dist/adapters/fork-relay.d.mts.map +1 -0
- package/dist/adapters/fork-relay.mjs +208 -0
- package/dist/adapters/fork-relay.mjs.map +1 -0
- package/dist/adapters/idb-store.mjs +12 -16
- package/dist/adapters/idb-store.mjs.map +1 -1
- package/dist/adapters/in-memory-adapter.mjs +4 -10
- package/dist/adapters/in-memory-adapter.mjs.map +1 -1
- package/dist/adapters/passkey-adapter.mjs +4 -12
- package/dist/adapters/passkey-adapter.mjs.map +1 -1
- package/dist/adapters/remote-cli-adapter.mjs +37 -72
- package/dist/adapters/remote-cli-adapter.mjs.map +1 -1
- package/dist/adapters/webcrypto-adapter.mjs +2 -4
- package/dist/adapters/webcrypto-adapter.mjs.map +1 -1
- package/dist/bin/cli.mjs +9 -22
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/client/dev-wallet-client.mjs +13 -28
- package/dist/client/dev-wallet-client.mjs.map +1 -1
- package/dist/client/index.mjs +1 -2
- package/dist/client/request-handler.mjs +36 -42
- package/dist/client/request-handler.mjs.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/react/components.d.mts +9 -9
- package/dist/react/components.d.mts.map +1 -1
- package/dist/react/components.mjs +2 -5
- package/dist/react/components.mjs.map +1 -1
- package/dist/react/context.d.mts +3 -3
- package/dist/react/context.d.mts.map +1 -1
- package/dist/react/context.mjs +3 -8
- package/dist/react/context.mjs.map +1 -1
- package/dist/react/index.mjs +1 -2
- package/dist/react/useDevWallet.d.mts +3 -0
- package/dist/react/useDevWallet.d.mts.map +1 -1
- package/dist/react/useDevWallet.mjs +9 -14
- package/dist/react/useDevWallet.mjs.map +1 -1
- package/dist/server/cli-signing-middleware.mjs +7 -20
- package/dist/server/cli-signing-middleware.mjs.map +1 -1
- package/dist/server/index.mjs +1 -2
- package/dist/standalone/assets/{in-memory-adapter-CBF4h2KD.js → in-memory-adapter-qRkNfj9O.js} +1 -1
- package/dist/standalone/assets/main-DDltQnzR.js +3954 -0
- package/dist/standalone/assets/{webcrypto-adapter-DysAubFb.js → webcrypto-adapter-FejcrL9x.js} +1 -1
- package/dist/standalone/index.html +11 -12
- package/dist/ui/copy-controller.mjs +3 -3
- package/dist/ui/copy-controller.mjs.map +1 -1
- package/dist/ui/dev-wallet-account-selector.d.mts +3 -4
- package/dist/ui/dev-wallet-account-selector.d.mts.map +1 -1
- package/dist/ui/dev-wallet-account-selector.mjs +48 -25
- package/dist/ui/dev-wallet-account-selector.mjs.map +1 -1
- package/dist/ui/dev-wallet-accounts.d.mts +9 -4
- package/dist/ui/dev-wallet-accounts.d.mts.map +1 -1
- package/dist/ui/dev-wallet-accounts.mjs +62 -140
- package/dist/ui/dev-wallet-accounts.mjs.map +1 -1
- package/dist/ui/dev-wallet-balances.d.mts +10 -3
- package/dist/ui/dev-wallet-balances.d.mts.map +1 -1
- package/dist/ui/dev-wallet-balances.mjs +241 -43
- package/dist/ui/dev-wallet-balances.mjs.map +1 -1
- package/dist/ui/dev-wallet-connect.d.mts +3 -3
- package/dist/ui/dev-wallet-connect.d.mts.map +1 -1
- package/dist/ui/dev-wallet-connect.mjs +24 -16
- package/dist/ui/dev-wallet-connect.mjs.map +1 -1
- package/dist/ui/dev-wallet-dropdown.d.mts +3 -3
- package/dist/ui/dev-wallet-dropdown.d.mts.map +1 -1
- package/dist/ui/dev-wallet-dropdown.mjs +37 -47
- package/dist/ui/dev-wallet-dropdown.mjs.map +1 -1
- package/dist/ui/dev-wallet-fork-panel.d.mts +43 -0
- package/dist/ui/dev-wallet-fork-panel.d.mts.map +1 -0
- package/dist/ui/dev-wallet-fork-panel.mjs +500 -0
- package/dist/ui/dev-wallet-fork-panel.mjs.map +1 -0
- package/dist/ui/dev-wallet-network-badge.d.mts +3 -4
- package/dist/ui/dev-wallet-network-badge.d.mts.map +1 -1
- package/dist/ui/dev-wallet-network-badge.mjs +52 -21
- package/dist/ui/dev-wallet-network-badge.mjs.map +1 -1
- package/dist/ui/dev-wallet-new-account.d.mts +3 -4
- package/dist/ui/dev-wallet-new-account.d.mts.map +1 -1
- package/dist/ui/dev-wallet-new-account.mjs +31 -105
- package/dist/ui/dev-wallet-new-account.mjs.map +1 -1
- package/dist/ui/dev-wallet-objects.d.mts +3 -3
- package/dist/ui/dev-wallet-objects.d.mts.map +1 -1
- package/dist/ui/dev-wallet-objects.mjs +76 -39
- package/dist/ui/dev-wallet-objects.mjs.map +1 -1
- package/dist/ui/dev-wallet-panel.d.mts +24 -4
- package/dist/ui/dev-wallet-panel.d.mts.map +1 -1
- package/dist/ui/dev-wallet-panel.mjs +247 -64
- package/dist/ui/dev-wallet-panel.mjs.map +1 -1
- package/dist/ui/dev-wallet-popup.d.mts +3 -5
- package/dist/ui/dev-wallet-popup.d.mts.map +1 -1
- package/dist/ui/dev-wallet-popup.mjs +19 -15
- package/dist/ui/dev-wallet-popup.mjs.map +1 -1
- package/dist/ui/dev-wallet-settings.d.mts +3 -4
- package/dist/ui/dev-wallet-settings.d.mts.map +1 -1
- package/dist/ui/dev-wallet-settings.mjs +149 -97
- package/dist/ui/dev-wallet-settings.mjs.map +1 -1
- package/dist/ui/dev-wallet-signing-modal.d.mts +11 -4
- package/dist/ui/dev-wallet-signing-modal.d.mts.map +1 -1
- package/dist/ui/dev-wallet-signing-modal.mjs +46 -18
- package/dist/ui/dev-wallet-signing-modal.mjs.map +1 -1
- package/dist/ui/dev-wallet-signing.d.mts +9 -3
- package/dist/ui/dev-wallet-signing.d.mts.map +1 -1
- package/dist/ui/dev-wallet-signing.mjs +119 -130
- package/dist/ui/dev-wallet-signing.mjs.map +1 -1
- package/dist/ui/dev-wallet-standalone.d.mts +8 -3
- package/dist/ui/dev-wallet-standalone.d.mts.map +1 -1
- package/dist/ui/dev-wallet-standalone.mjs +303 -38
- package/dist/ui/dev-wallet-standalone.mjs.map +1 -1
- package/dist/ui/dev-wallet-tab-bar.d.mts +13 -5
- package/dist/ui/dev-wallet-tab-bar.d.mts.map +1 -1
- package/dist/ui/dev-wallet-tab-bar.mjs +143 -82
- package/dist/ui/dev-wallet-tab-bar.mjs.map +1 -1
- package/dist/ui/index.d.mts +3 -2
- package/dist/ui/index.mjs +2 -2
- package/dist/ui/mount.d.mts +14 -1
- package/dist/ui/mount.d.mts.map +1 -1
- package/dist/ui/mount.mjs +5 -2
- package/dist/ui/mount.mjs.map +1 -1
- package/dist/ui/styles.mjs +428 -66
- package/dist/ui/styles.mjs.map +1 -1
- package/dist/ui/transaction-analyzer.mjs +19 -30
- package/dist/ui/transaction-analyzer.mjs.map +1 -1
- package/dist/ui/utils.d.mts +59 -0
- package/dist/ui/utils.d.mts.map +1 -0
- package/dist/ui/utils.mjs +42 -15
- package/dist/ui/utils.mjs.map +1 -1
- package/dist/ui/wallet-controller.mjs +89 -20
- package/dist/ui/wallet-controller.mjs.map +1 -1
- package/dist/wallet/constants.d.mts +9 -0
- package/dist/wallet/constants.d.mts.map +1 -0
- package/dist/wallet/constants.mjs +1 -1
- package/dist/wallet/dev-wallet.mjs +42 -99
- package/dist/wallet/dev-wallet.mjs.map +1 -1
- package/dist/wallet/initializer.d.mts +3 -0
- package/dist/wallet/initializer.d.mts.map +1 -1
- package/dist/wallet/initializer.mjs +9 -14
- package/dist/wallet/initializer.mjs.map +1 -1
- package/dist/wallet/signing.mjs +8 -21
- package/dist/wallet/signing.mjs.map +1 -1
- package/package.json +125 -123
- package/src/adapters/browser.ts +21 -0
- package/src/adapters/devstack-adapter.ts +342 -0
- package/src/adapters/devstack-paths.ts +16 -0
- package/src/adapters/fork-relay.ts +321 -0
- package/src/app/index.html +10 -11
- package/src/react/useDevWallet.ts +5 -1
- package/src/ui/dev-wallet-account-selector.ts +44 -17
- package/src/ui/dev-wallet-accounts.ts +87 -124
- package/src/ui/dev-wallet-balances.ts +248 -27
- package/src/ui/dev-wallet-connect.ts +19 -8
- package/src/ui/dev-wallet-dropdown.ts +7 -5
- package/src/ui/dev-wallet-fork-panel.ts +591 -0
- package/src/ui/dev-wallet-network-badge.ts +49 -10
- package/src/ui/dev-wallet-new-account.ts +21 -62
- package/src/ui/dev-wallet-objects.ts +59 -19
- package/src/ui/dev-wallet-panel.ts +261 -42
- package/src/ui/dev-wallet-popup.ts +12 -6
- package/src/ui/dev-wallet-settings.ts +159 -94
- package/src/ui/dev-wallet-signing-modal.ts +47 -7
- package/src/ui/dev-wallet-signing.ts +124 -97
- package/src/ui/dev-wallet-standalone.ts +310 -22
- package/src/ui/dev-wallet-tab-bar.ts +132 -70
- package/src/ui/index.ts +3 -0
- package/src/ui/mount.ts +23 -1
- package/src/ui/styles.ts +434 -58
- package/src/ui/utils.ts +66 -0
- package/src/ui/wallet-controller.ts +103 -5
- package/src/wallet/initializer.ts +7 -1
- package/dist/standalone/assets/main-VE4olb-Q.js +0 -2841
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getNetworkFromChain } from "./constants.mjs";
|
|
2
2
|
import { executeSigning } from "./signing.mjs";
|
|
3
3
|
import { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
4
4
|
import { mitt } from "@mysten/utils";
|
|
5
5
|
import { SUI_CHAINS, getWallets } from "@mysten/wallet-standard";
|
|
6
|
-
|
|
7
6
|
//#region src/wallet/dev-wallet.ts
|
|
8
7
|
const DEFAULT_WALLET_NAME = "Dev Wallet";
|
|
9
8
|
const NETWORK_STORAGE_KEY = "dev-wallet:networks";
|
|
@@ -39,16 +38,14 @@ var DevWallet = class {
|
|
|
39
38
|
#connectListeners;
|
|
40
39
|
#destroyed = false;
|
|
41
40
|
constructor(config) {
|
|
42
|
-
if (config.adapters.length === 0)
|
|
43
|
-
console.warn("[dev-wallet] No adapters provided. The wallet will have no accounts.");
|
|
44
|
-
}
|
|
41
|
+
if (config.adapters.length === 0) console.warn("[dev-wallet] No adapters provided. The wallet will have no accounts.");
|
|
45
42
|
this.#adapters = config.adapters;
|
|
46
43
|
this.#persistNetworks = config.persistNetworks ?? false;
|
|
47
44
|
this.#networkUrls = this.#loadNetworkUrls(config.networks ?? DEFAULT_NETWORK_URLS);
|
|
48
45
|
this.#clients = {};
|
|
49
46
|
this.#activeNetwork = config.activeNetwork ?? Object.keys(this.#networkUrls)[0] ?? "";
|
|
50
47
|
this.#name = config.name ?? DEFAULT_WALLET_NAME;
|
|
51
|
-
this.#icon = config.icon ??
|
|
48
|
+
this.#icon = config.icon ?? "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCIgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0Ij4KICA8ZGVmcz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0id2FsbGV0R3JhZCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiM2MzY2RjEiIC8+CiAgICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6IzI1NjNFQiIgLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImZsYXBHcmFkIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIxMDAlIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzgxOENGOCIgLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjojNEY0NkU1IiAvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICA8L2RlZnM+CiAgPCEtLSBTaGFkb3cgLS0+CiAgPHJlY3QgeD0iOSIgeT0iMjEiIHdpZHRoPSI1MCIgaGVpZ2h0PSIzNiIgcng9IjYiIHJ5PSI2IiBmaWxsPSIjMDAwIiBvcGFjaXR5PSIwLjEiIC8+CiAgPCEtLSBXYWxsZXQgYm9keSAtLT4KICA8cmVjdCB4PSI2IiB5PSIxOCIgd2lkdGg9IjUwIiBoZWlnaHQ9IjM2IiByeD0iNiIgcnk9IjYiIGZpbGw9InVybCgjd2FsbGV0R3JhZCkiIC8+CiAgPCEtLSBGbGFwIC0tPgogIDxwYXRoIGQ9Ik02IDI2IEw2IDIyIEM2IDE1IDggMTIgMTQgMTIgTDQ2IDEyIEM1MiAxMiA1NiAxNSA1NiAyMiBMNTYgMjYgWiIgZmlsbD0idXJsKCNmbGFwR3JhZCkiIC8+CiAgPCEtLSBDbGFzcCAtLT4KICA8cmVjdCB4PSI0MiIgeT0iMzAiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxMiIgcng9IjQiIHJ5PSI0IiBmaWxsPSIjNDMzOENBIiAvPgogIDwhLS0gR29sZCBjb2luIGluIGNsYXNwIC0tPgogIDxjaXJjbGUgY3g9IjQ4IiBjeT0iMzYiIHI9IjMuNSIgZmlsbD0iI0ZDRDM0RCIgLz4KICA8Y2lyY2xlIGN4PSI0OCIgY3k9IjM2IiByPSIyIiBmaWxsPSIjRjU5RTBCIiAvPgogIDwhLS0gRW1ib3NzZWQgRFcgdGV4dCAtLT4KICA8dGV4dCB4PSIyNiIgeT0iNDUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmIiBmb250LXdlaWdodD0iOTAwIiBmb250LXNpemU9IjE4IiBmaWxsPSIjMzczMEEzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIiBsZXR0ZXItc3BhY2luZz0iMiI+RFc8L3RleHQ+CiAgPHRleHQgeD0iMjYiIHk9IjQ0IiBmb250LWZhbWlseT0iQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZiIgZm9udC13ZWlnaHQ9IjkwMCIgZm9udC1zaXplPSIxOCIgZmlsbD0iI0M3RDJGRSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGxlIiBsZXR0ZXItc3BhY2luZz0iMiI+RFc8L3RleHQ+Cjwvc3ZnPgo=";
|
|
52
49
|
this.#autoApprove = config.autoApprove ?? false;
|
|
53
50
|
this.#autoConnect = config.autoConnect ?? false;
|
|
54
51
|
this.#clientFactory = config.clientFactory ?? ((network, url) => new SuiGrpcClient({
|
|
@@ -59,9 +56,9 @@ var DevWallet = class {
|
|
|
59
56
|
this.#events = mitt();
|
|
60
57
|
this.#unsubscribeAdapters = [];
|
|
61
58
|
this.#pendingRequest = null;
|
|
62
|
-
this.#requestListeners = new Set();
|
|
59
|
+
this.#requestListeners = /* @__PURE__ */ new Set();
|
|
63
60
|
this.#pendingConnect = null;
|
|
64
|
-
this.#connectListeners = new Set();
|
|
61
|
+
this.#connectListeners = /* @__PURE__ */ new Set();
|
|
65
62
|
this.#setupAdapterListeners();
|
|
66
63
|
}
|
|
67
64
|
get version() {
|
|
@@ -115,13 +112,11 @@ var DevWallet = class {
|
|
|
115
112
|
return this.#adapters;
|
|
116
113
|
}
|
|
117
114
|
getAdapterForAccount(address) {
|
|
118
|
-
return this.#adapters.find((a) => a.getAccount(address) !==
|
|
115
|
+
return this.#adapters.find((a) => a.getAccount(address) !== void 0);
|
|
119
116
|
}
|
|
120
117
|
/** Eagerly creates and returns clients for all configured networks. Prefer `getClient()` or `activeClient` for single-network access. */
|
|
121
118
|
get clients() {
|
|
122
|
-
for (const name of Object.keys(this.#networkUrls))
|
|
123
|
-
this.#ensureClient(name);
|
|
124
|
-
}
|
|
119
|
+
for (const name of Object.keys(this.#networkUrls)) this.#ensureClient(name);
|
|
125
120
|
return { ...this.#clients };
|
|
126
121
|
}
|
|
127
122
|
getClient(network) {
|
|
@@ -142,9 +137,7 @@ var DevWallet = class {
|
|
|
142
137
|
}
|
|
143
138
|
/** Switch the active network. Emits a `change` event. */
|
|
144
139
|
setActiveNetwork(network) {
|
|
145
|
-
if (!this.#networkUrls[network]) {
|
|
146
|
-
throw new Error(`No client for network "${network}". Available: ${this.availableNetworks.join(", ")}`);
|
|
147
|
-
}
|
|
140
|
+
if (!this.#networkUrls[network]) throw new Error(`No client for network "${network}". Available: ${this.availableNetworks.join(", ")}`);
|
|
148
141
|
this.#activeNetwork = network;
|
|
149
142
|
this.#events.emit("change", { accounts: this.#accounts });
|
|
150
143
|
}
|
|
@@ -155,9 +148,7 @@ var DevWallet = class {
|
|
|
155
148
|
} catch {
|
|
156
149
|
throw new Error(`Invalid URL: ${url}`);
|
|
157
150
|
}
|
|
158
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
159
|
-
throw new Error(`Invalid URL: must use http or https (got ${parsed.protocol})`);
|
|
160
|
-
}
|
|
151
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error(`Invalid URL: must use http or https (got ${parsed.protocol})`);
|
|
161
152
|
this.#networkUrls[name] = url;
|
|
162
153
|
this.#clients[name] = this.#clientFactory(name, url);
|
|
163
154
|
this.#saveNetworkUrls();
|
|
@@ -166,36 +157,27 @@ var DevWallet = class {
|
|
|
166
157
|
removeNetwork(name) {
|
|
167
158
|
delete this.#networkUrls[name];
|
|
168
159
|
delete this.#clients[name];
|
|
169
|
-
if (this.#activeNetwork === name)
|
|
170
|
-
this.#activeNetwork = Object.keys(this.#networkUrls)[0] ?? "";
|
|
171
|
-
}
|
|
160
|
+
if (this.#activeNetwork === name) this.#activeNetwork = Object.keys(this.#networkUrls)[0] ?? "";
|
|
172
161
|
this.#saveNetworkUrls();
|
|
173
162
|
this.#events.emit("change", { accounts: this.#accounts });
|
|
174
163
|
}
|
|
175
164
|
/** Register this wallet with the wallet-standard registry. Returns an unregister function. */
|
|
176
165
|
register() {
|
|
177
|
-
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production")
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
const walletsApi = getWallets();
|
|
181
|
-
return walletsApi.register(this);
|
|
166
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") console.warn("[@mysten-incubation/dev-wallet] DevWallet is intended for development only. Do not use in production.");
|
|
167
|
+
return getWallets().register(this);
|
|
182
168
|
}
|
|
183
169
|
/** Reject any pending requests, unsubscribe from adapters, destroy them, and clear all listeners. */
|
|
184
170
|
destroy() {
|
|
185
171
|
this.#destroyed = true;
|
|
186
|
-
for (const unsub of this.#unsubscribeAdapters)
|
|
187
|
-
unsub();
|
|
188
|
-
}
|
|
172
|
+
for (const unsub of this.#unsubscribeAdapters) unsub();
|
|
189
173
|
this.#unsubscribeAdapters = [];
|
|
190
|
-
for (const adapter of this.#adapters)
|
|
191
|
-
adapter.destroy();
|
|
192
|
-
}
|
|
174
|
+
for (const adapter of this.#adapters) adapter.destroy();
|
|
193
175
|
if (this.#pendingRequest) {
|
|
194
|
-
this.#pendingRequest.reject(new Error("Wallet destroyed."));
|
|
176
|
+
this.#pendingRequest.reject(/* @__PURE__ */ new Error("Wallet destroyed."));
|
|
195
177
|
this.#pendingRequest = null;
|
|
196
178
|
}
|
|
197
179
|
if (this.#pendingConnect) {
|
|
198
|
-
this.#pendingConnect.reject(new Error("Wallet destroyed."));
|
|
180
|
+
this.#pendingConnect.reject(/* @__PURE__ */ new Error("Wallet destroyed."));
|
|
199
181
|
this.#pendingConnect = null;
|
|
200
182
|
}
|
|
201
183
|
this.#requestListeners.clear();
|
|
@@ -205,9 +187,7 @@ var DevWallet = class {
|
|
|
205
187
|
/** Sign the pending request using the account's adapter signer and resolve the promise. */
|
|
206
188
|
async approveRequest() {
|
|
207
189
|
const request = this.#pendingRequest;
|
|
208
|
-
if (!request)
|
|
209
|
-
throw new Error("No pending request to approve.");
|
|
210
|
-
}
|
|
190
|
+
if (!request) throw new Error("No pending request to approve.");
|
|
211
191
|
try {
|
|
212
192
|
const result = await this.#executeSigning(request.type, request.account, request.chain, request.data);
|
|
213
193
|
this.#pendingRequest = null;
|
|
@@ -221,9 +201,7 @@ var DevWallet = class {
|
|
|
221
201
|
}
|
|
222
202
|
rejectRequest(reason) {
|
|
223
203
|
const request = this.#pendingRequest;
|
|
224
|
-
if (!request)
|
|
225
|
-
throw new Error("No pending request to reject.");
|
|
226
|
-
}
|
|
204
|
+
if (!request) throw new Error("No pending request to reject.");
|
|
227
205
|
this.#pendingRequest = null;
|
|
228
206
|
this.#notifyRequestListeners();
|
|
229
207
|
request.reject(new Error(reason ?? "Request rejected by user."));
|
|
@@ -242,9 +220,7 @@ var DevWallet = class {
|
|
|
242
220
|
/** Expose the given addresses to the dApp. Pass an empty array to expose all accounts. */
|
|
243
221
|
approveConnect(selectedAddresses) {
|
|
244
222
|
const request = this.#pendingConnect;
|
|
245
|
-
if (!request)
|
|
246
|
-
throw new Error("No pending connect request to approve.");
|
|
247
|
-
}
|
|
223
|
+
if (!request) throw new Error("No pending connect request to approve.");
|
|
248
224
|
const selected = selectedAddresses.length > 0 ? this.#accounts.filter((a) => selectedAddresses.includes(a.address)) : [...this.#accounts];
|
|
249
225
|
this.#pendingConnect = null;
|
|
250
226
|
this.#notifyConnectListeners();
|
|
@@ -252,9 +228,7 @@ var DevWallet = class {
|
|
|
252
228
|
}
|
|
253
229
|
rejectConnect(reason) {
|
|
254
230
|
const request = this.#pendingConnect;
|
|
255
|
-
if (!request)
|
|
256
|
-
throw new Error("No pending connect request to reject.");
|
|
257
|
-
}
|
|
231
|
+
if (!request) throw new Error("No pending connect request to reject.");
|
|
258
232
|
this.#pendingConnect = null;
|
|
259
233
|
this.#notifyConnectListeners();
|
|
260
234
|
request.reject(new Error(reason ?? "Connection rejected by user."));
|
|
@@ -268,15 +242,11 @@ var DevWallet = class {
|
|
|
268
242
|
}
|
|
269
243
|
#notifyRequestListeners() {
|
|
270
244
|
const request = this.#pendingRequest;
|
|
271
|
-
for (const listener of this.#requestListeners)
|
|
272
|
-
listener(request);
|
|
273
|
-
}
|
|
245
|
+
for (const listener of this.#requestListeners) listener(request);
|
|
274
246
|
}
|
|
275
247
|
#notifyConnectListeners() {
|
|
276
248
|
const request = this.#pendingConnect;
|
|
277
|
-
for (const listener of this.#connectListeners)
|
|
278
|
-
listener(request);
|
|
279
|
-
}
|
|
249
|
+
for (const listener of this.#connectListeners) listener(request);
|
|
280
250
|
}
|
|
281
251
|
#aggregateAccounts() {
|
|
282
252
|
return this.#adapters.flatMap((a) => a.getAccounts().map((acc) => acc.walletAccount));
|
|
@@ -295,12 +265,8 @@ var DevWallet = class {
|
|
|
295
265
|
return () => this.#events.off(event, listener);
|
|
296
266
|
};
|
|
297
267
|
#connect = async () => {
|
|
298
|
-
if (this.#autoConnect) {
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
if (this.#pendingConnect) {
|
|
302
|
-
return Promise.reject(new Error("A connect request is already pending."));
|
|
303
|
-
}
|
|
268
|
+
if (this.#autoConnect) return { accounts: this.accounts };
|
|
269
|
+
if (this.#pendingConnect) return Promise.reject(/* @__PURE__ */ new Error("A connect request is already pending."));
|
|
304
270
|
return new Promise((resolve, reject) => {
|
|
305
271
|
this.#pendingConnect = {
|
|
306
272
|
id: crypto.randomUUID(),
|
|
@@ -313,22 +279,16 @@ var DevWallet = class {
|
|
|
313
279
|
#disconnect = async () => {};
|
|
314
280
|
#getClientForChain(chain) {
|
|
315
281
|
const network = getNetworkFromChain(chain);
|
|
316
|
-
if (!network) {
|
|
317
|
-
throw new Error(`Invalid chain identifier: ${chain}`);
|
|
318
|
-
}
|
|
282
|
+
if (!network) throw new Error(`Invalid chain identifier: ${chain}`);
|
|
319
283
|
return this.#ensureClient(network);
|
|
320
284
|
}
|
|
321
285
|
#loadNetworkUrls(defaults) {
|
|
322
|
-
if (!this.#persistNetworks || typeof localStorage === "undefined") {
|
|
323
|
-
return { ...defaults };
|
|
324
|
-
}
|
|
286
|
+
if (!this.#persistNetworks || typeof localStorage === "undefined") return { ...defaults };
|
|
325
287
|
try {
|
|
326
288
|
const raw = localStorage.getItem(NETWORK_STORAGE_KEY);
|
|
327
289
|
if (raw) {
|
|
328
290
|
const parsed = JSON.parse(raw);
|
|
329
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed))
|
|
330
|
-
return parsed;
|
|
331
|
-
}
|
|
291
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return parsed;
|
|
332
292
|
}
|
|
333
293
|
} catch {}
|
|
334
294
|
return { ...defaults };
|
|
@@ -340,9 +300,7 @@ var DevWallet = class {
|
|
|
340
300
|
#ensureClient(network) {
|
|
341
301
|
if (!this.#clients[network]) {
|
|
342
302
|
const url = this.#networkUrls[network];
|
|
343
|
-
if (!url) {
|
|
344
|
-
throw new Error(`No client for network "${network}". Available: ${this.availableNetworks.join(", ")}`);
|
|
345
|
-
}
|
|
303
|
+
if (!url) throw new Error(`No client for network "${network}". Available: ${this.availableNetworks.join(", ")}`);
|
|
346
304
|
this.#clients[network] = this.#clientFactory(network, url);
|
|
347
305
|
}
|
|
348
306
|
return this.#clients[network];
|
|
@@ -356,43 +314,28 @@ var DevWallet = class {
|
|
|
356
314
|
throw new Error(`No account found for address "${address}". Available addresses: ${allAddresses.join(", ")}`);
|
|
357
315
|
}
|
|
358
316
|
#shouldAutoApprove(type, account, chain, data) {
|
|
359
|
-
|
|
360
|
-
if (
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
return this.#autoApprove({
|
|
368
|
-
type,
|
|
369
|
-
account,
|
|
370
|
-
chain,
|
|
371
|
-
data
|
|
372
|
-
});
|
|
373
|
-
}
|
|
317
|
+
if (this.getAdapterForAccount(account.address)?.allowAutoSign === false) return false;
|
|
318
|
+
if (this.#autoApprove === true) return true;
|
|
319
|
+
if (typeof this.#autoApprove === "function") return this.#autoApprove({
|
|
320
|
+
type,
|
|
321
|
+
account,
|
|
322
|
+
chain,
|
|
323
|
+
data
|
|
324
|
+
});
|
|
374
325
|
return false;
|
|
375
326
|
}
|
|
376
327
|
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
328
|
return executeSigning({
|
|
380
329
|
type,
|
|
381
|
-
signer,
|
|
330
|
+
signer: this.#getSigner(account.address),
|
|
382
331
|
data,
|
|
383
|
-
client
|
|
332
|
+
client: type !== "sign-personal-message" ? this.#getClientForChain(chain) : void 0
|
|
384
333
|
});
|
|
385
334
|
}
|
|
386
335
|
#enqueueRequest(type, account, chain, data) {
|
|
387
|
-
if (this.#destroyed)
|
|
388
|
-
|
|
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
|
-
}
|
|
336
|
+
if (this.#destroyed) return Promise.reject(/* @__PURE__ */ new Error("Wallet has been destroyed."));
|
|
337
|
+
if (this.#shouldAutoApprove(type, account, chain, data)) return this.#executeSigning(type, account, chain, data);
|
|
338
|
+
if (this.#pendingRequest) return Promise.reject(/* @__PURE__ */ new Error("A signing request is already pending."));
|
|
396
339
|
return new Promise((resolve, reject) => {
|
|
397
340
|
this.#pendingRequest = {
|
|
398
341
|
id: crypto.randomUUID(),
|
|
@@ -418,7 +361,7 @@ var DevWallet = class {
|
|
|
418
361
|
return this.#enqueueRequest("sign-and-execute-transaction", input.account, input.chain, txJson);
|
|
419
362
|
};
|
|
420
363
|
};
|
|
421
|
-
|
|
422
364
|
//#endregion
|
|
423
365
|
export { DEFAULT_NETWORK_URLS, DevWallet };
|
|
366
|
+
|
|
424
367
|
//# sourceMappingURL=dev-wallet.mjs.map
|
|
@@ -1 +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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"}
|
|
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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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SignerAdapter } from "../types.mjs";
|
|
2
2
|
import { AutoApprovePolicy, DevWallet } from "./dev-wallet.mjs";
|
|
3
|
+
import { DevWalletDockStyle } from "../ui/dev-wallet-panel.mjs";
|
|
3
4
|
import { WalletIcon } from "@mysten/wallet-standard";
|
|
4
5
|
import { ClientWithCoreApi } from "@mysten/sui/client";
|
|
5
6
|
|
|
@@ -21,6 +22,8 @@ interface DevWalletInitializerConfig {
|
|
|
21
22
|
createInitialAccount?: boolean;
|
|
22
23
|
/** Mount the floating wallet drawer UI. Defaults to false. */
|
|
23
24
|
mountUI?: boolean;
|
|
25
|
+
/** Floating dock presentation when `mountUI` is true. Defaults to `corner-pill`. */
|
|
26
|
+
dockStyle?: DevWalletDockStyle;
|
|
24
27
|
/** Container element for the UI drawer. Defaults to document.body. */
|
|
25
28
|
container?: HTMLElement;
|
|
26
29
|
/** Called with the DevWallet instance after creation. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initializer.d.mts","names":[],"sources":["../../src/wallet/initializer.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"initializer.d.mts","names":[],"sources":["../../src/wallet/initializer.ts"],"mappings":";;;;;;;;;AAeA;;;UAAiB,0BAAA;EAChB,QAAA,EAAU,aAAA;EACV,IAAA;EACA,IAAA,GAAO,UAAA;EACP,WAAA,GAAc,iBAAA;EACd,WAAA;EAYoC;EAVpC,cAAA;EANA;EAQA,oBAAA;EAPA;EASA,OAAA;EARO;EAUP,SAAA,GAAY,kBAAA;EATE;EAWd,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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DevWallet } from "./dev-wallet.mjs";
|
|
2
|
-
|
|
3
2
|
//#region src/wallet/initializer.ts
|
|
4
3
|
/**
|
|
5
4
|
* Creates a wallet initializer for `createDAppKit({ walletInitializers: [...] })`.
|
|
@@ -29,22 +28,15 @@ function devWalletInitializer(config) {
|
|
|
29
28
|
id: "dev-wallet-initializer",
|
|
30
29
|
async initialize({ networks, getClient }) {
|
|
31
30
|
const { autoInitialize = true, createInitialAccount = true, mountUI = false } = config;
|
|
32
|
-
if (autoInitialize)
|
|
33
|
-
await Promise.all(config.adapters.map((a) => a.initialize()));
|
|
34
|
-
}
|
|
31
|
+
if (autoInitialize) await Promise.all(config.adapters.map((a) => a.initialize()));
|
|
35
32
|
if (createInitialAccount) {
|
|
36
|
-
|
|
37
|
-
if (!hasAccounts) {
|
|
33
|
+
if (!config.adapters.some((a) => a.getAccounts().length > 0)) {
|
|
38
34
|
const creatableAdapter = config.adapters.find((a) => a.createAccount && a.getAccounts().length === 0);
|
|
39
|
-
if (creatableAdapter?.createAccount) {
|
|
40
|
-
await creatableAdapter.createAccount({ label: "Dev Account" });
|
|
41
|
-
}
|
|
35
|
+
if (creatableAdapter?.createAccount) await creatableAdapter.createAccount({ label: "Dev Account" });
|
|
42
36
|
}
|
|
43
37
|
}
|
|
44
38
|
const networkUrls = {};
|
|
45
|
-
for (const network of networks) {
|
|
46
|
-
networkUrls[network] = `dapp-kit://${network}`;
|
|
47
|
-
}
|
|
39
|
+
for (const network of networks) networkUrls[network] = `dapp-kit://${network}`;
|
|
48
40
|
const wallet = new DevWallet({
|
|
49
41
|
adapters: config.adapters,
|
|
50
42
|
networks: networkUrls,
|
|
@@ -58,7 +50,10 @@ function devWalletInitializer(config) {
|
|
|
58
50
|
let unmountUI;
|
|
59
51
|
if (mountUI && typeof document !== "undefined") {
|
|
60
52
|
const { mountDevWallet } = await import("../ui/mount.mjs");
|
|
61
|
-
unmountUI = mountDevWallet(wallet, {
|
|
53
|
+
unmountUI = mountDevWallet(wallet, {
|
|
54
|
+
container: config.container,
|
|
55
|
+
dockStyle: config.dockStyle
|
|
56
|
+
});
|
|
62
57
|
}
|
|
63
58
|
const unregister = wallet.register();
|
|
64
59
|
return { unregister() {
|
|
@@ -69,7 +64,7 @@ function devWalletInitializer(config) {
|
|
|
69
64
|
}
|
|
70
65
|
};
|
|
71
66
|
}
|
|
72
|
-
|
|
73
67
|
//#endregion
|
|
74
68
|
export { devWalletInitializer };
|
|
69
|
+
|
|
75
70
|
//# sourceMappingURL=initializer.mjs.map
|
|
@@ -1 +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.
|
|
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 { DevWalletDockStyle } from '../ui/dev-wallet-panel.js';\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/** Floating dock presentation when `mountUI` is true. Defaults to `corner-pill`. */\n\tdockStyle?: DevWalletDockStyle;\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, {\n\t\t\t\t\tcontainer: config.container,\n\t\t\t\t\tdockStyle: config.dockStyle,\n\t\t\t\t});\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":";;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,SAAgB,qBAAqB,QAMnC;AACD,QAAO;EACN,IAAI;EACJ,MAAM,WAAW,EAAE,UAAU,aAAa;GACzC,MAAM,EAAE,iBAAiB,MAAM,uBAAuB,MAAM,UAAU,UAAU;AAGhF,OAAI,eACH,OAAM,QAAQ,IAAI,OAAO,SAAS,KAAK,MAAM,EAAE,YAAY,CAAC,CAAC;AAI9D,OAAI,sBAEH;QAAI,CADgB,OAAO,SAAS,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EACpE,EAAa;KACjB,MAAM,mBAAmB,OAAO,SAAS,MACvC,MAAM,EAAE,iBAAiB,EAAE,aAAa,CAAC,WAAW,EACrD;AACD,SAAI,kBAAkB,cACrB,OAAM,iBAAiB,cAAc,EAAE,OAAO,eAAe,CAAC;;;GASjE,MAAM,cAAsC,EAAE;AAC9C,QAAK,MAAM,WAAW,SACrB,aAAY,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;KAClC,WAAW,OAAO;KAClB,WAAW,OAAO;KAClB,CAAC;;GAGH,MAAM,aAAa,OAAO,UAAU;AACpC,UAAO,EACN,aAAa;AACZ,iBAAa;AACb,gBAAY;AACZ,WAAO,SAAS;MAEjB;;EAEF"}
|
package/dist/wallet/signing.mjs
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { Transaction } from "@mysten/sui/transactions";
|
|
2
2
|
import { fromBase64, toBase64 } from "@mysten/sui/utils";
|
|
3
|
-
|
|
4
3
|
//#region src/wallet/signing.ts
|
|
5
4
|
async function executeSigning({ type, signer, data, client }) {
|
|
6
5
|
switch (type) {
|
|
7
6
|
case "sign-personal-message": {
|
|
8
|
-
if (!(data instanceof Uint8Array))
|
|
9
|
-
throw new Error("sign-personal-message expects data to be a Uint8Array");
|
|
10
|
-
}
|
|
7
|
+
if (!(data instanceof Uint8Array)) throw new Error("sign-personal-message expects data to be a Uint8Array");
|
|
11
8
|
const { bytes, signature } = await signer.signPersonalMessage(data);
|
|
12
9
|
return {
|
|
13
10
|
type,
|
|
@@ -17,11 +14,8 @@ async function executeSigning({ type, signer, data, client }) {
|
|
|
17
14
|
}
|
|
18
15
|
case "sign-transaction": {
|
|
19
16
|
if (!client) throw new Error("No client provided for sign-transaction");
|
|
20
|
-
if (typeof data !== "string")
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
const tx = Transaction.from(data);
|
|
24
|
-
const { bytes, signature } = await tx.sign({
|
|
17
|
+
if (typeof data !== "string") throw new Error("sign-transaction expects data to be a JSON string");
|
|
18
|
+
const { bytes, signature } = await Transaction.from(data).sign({
|
|
25
19
|
client,
|
|
26
20
|
signer
|
|
27
21
|
});
|
|
@@ -33,11 +27,8 @@ async function executeSigning({ type, signer, data, client }) {
|
|
|
33
27
|
}
|
|
34
28
|
case "sign-and-execute-transaction": {
|
|
35
29
|
if (!client) throw new Error("No client provided for sign-and-execute-transaction");
|
|
36
|
-
if (typeof data !== "string")
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
const tx = Transaction.from(data);
|
|
40
|
-
const { bytes, signature } = await tx.sign({
|
|
30
|
+
if (typeof data !== "string") throw new Error("sign-and-execute-transaction expects data to be a JSON string");
|
|
31
|
+
const { bytes, signature } = await Transaction.from(data).sign({
|
|
41
32
|
client,
|
|
42
33
|
signer
|
|
43
34
|
});
|
|
@@ -47,12 +38,8 @@ async function executeSigning({ type, signer, data, client }) {
|
|
|
47
38
|
include: { effects: true }
|
|
48
39
|
});
|
|
49
40
|
const txResult = result.Transaction ?? result.FailedTransaction;
|
|
50
|
-
if (!txResult)
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
if (!txResult.status.success) {
|
|
54
|
-
throw new Error(txResult.status.error?.message ?? "Transaction execution failed");
|
|
55
|
-
}
|
|
41
|
+
if (!txResult) throw new Error("Transaction execution returned empty result");
|
|
42
|
+
if (!txResult.status.success) throw new Error(txResult.status.error?.message ?? "Transaction execution failed");
|
|
56
43
|
return {
|
|
57
44
|
type,
|
|
58
45
|
bytes,
|
|
@@ -63,7 +50,7 @@ async function executeSigning({ type, signer, data, client }) {
|
|
|
63
50
|
}
|
|
64
51
|
}
|
|
65
52
|
}
|
|
66
|
-
|
|
67
53
|
//#endregion
|
|
68
54
|
export { executeSigning };
|
|
55
|
+
|
|
69
56
|
//# sourceMappingURL=signing.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signing.mjs","names":[],"sources":["../../src/wallet/signing.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { Transaction } from '@mysten/sui/transactions';\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\n\ntype SigningRequestType =\n\t| 'sign-personal-message'\n\t| 'sign-transaction'\n\t| 'sign-and-execute-transaction';\n\ninterface ExecuteSigningOptions {\n\ttype: SigningRequestType;\n\tsigner: Signer;\n\tdata: string | Uint8Array;\n\tclient?: ClientWithCoreApi;\n}\n\nexport type SigningResult =\n\t| { type: 'sign-personal-message'; bytes: string; signature: string }\n\t| { type: 'sign-transaction'; bytes: string; signature: string }\n\t| {\n\t\t\ttype: 'sign-and-execute-transaction';\n\t\t\tbytes: string;\n\t\t\tsignature: string;\n\t\t\tdigest: string;\n\t\t\teffects: string;\n\t };\n\n// Shared between the embedded DevWallet and the standalone popup request-handler.\nexport async function executeSigning({\n\ttype,\n\tsigner,\n\tdata,\n\tclient,\n}: ExecuteSigningOptions): Promise<SigningResult> {\n\tswitch (type) {\n\t\tcase 'sign-personal-message': {\n\t\t\tif (!(data instanceof Uint8Array)) {\n\t\t\t\tthrow new Error('sign-personal-message expects data to be a Uint8Array');\n\t\t\t}\n\t\t\tconst { bytes, signature } = await signer.signPersonalMessage(data);\n\t\t\treturn { type, bytes, signature };\n\t\t}\n\t\tcase 'sign-transaction': {\n\t\t\tif (!client) throw new Error('No client provided for sign-transaction');\n\t\t\tif (typeof data !== 'string') {\n\t\t\t\tthrow new Error('sign-transaction expects data to be a JSON string');\n\t\t\t}\n\t\t\tconst tx = Transaction.from(data);\n\t\t\tconst { bytes, signature } = await tx.sign({ client, signer });\n\t\t\treturn { type, bytes, signature };\n\t\t}\n\t\tcase 'sign-and-execute-transaction': {\n\t\t\tif (!client) throw new Error('No client provided for sign-and-execute-transaction');\n\t\t\tif (typeof data !== 'string') {\n\t\t\t\tthrow new Error('sign-and-execute-transaction expects data to be a JSON string');\n\t\t\t}\n\t\t\tconst tx = Transaction.from(data);\n\t\t\tconst { bytes, signature } = await tx.sign({ client, signer });\n\t\t\tconst result = await client.core.executeTransaction({\n\t\t\t\ttransaction: fromBase64(bytes),\n\t\t\t\tsignatures: [signature],\n\t\t\t\tinclude: { effects: true },\n\t\t\t});\n\t\t\tconst txResult = result.Transaction ?? result.FailedTransaction;\n\t\t\tif (!txResult) {\n\t\t\t\tthrow new Error('Transaction execution returned empty result');\n\t\t\t}\n\t\t\tif (!txResult.status.success) {\n\t\t\t\tthrow new Error(txResult.status.error?.message ?? 'Transaction execution failed');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttype,\n\t\t\t\tbytes,\n\t\t\t\tsignature,\n\t\t\t\tdigest: txResult.digest,\n\t\t\t\t// Empty string when effects BCS is unavailable — the wallet-standard protocol requires a string\n\t\t\t\teffects: txResult.effects?.bcs ? toBase64(txResult.effects.bcs) : '',\n\t\t\t};\n\t\t}\n\t}\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"signing.mjs","names":[],"sources":["../../src/wallet/signing.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { Transaction } from '@mysten/sui/transactions';\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\n\ntype SigningRequestType =\n\t| 'sign-personal-message'\n\t| 'sign-transaction'\n\t| 'sign-and-execute-transaction';\n\ninterface ExecuteSigningOptions {\n\ttype: SigningRequestType;\n\tsigner: Signer;\n\tdata: string | Uint8Array;\n\tclient?: ClientWithCoreApi;\n}\n\nexport type SigningResult =\n\t| { type: 'sign-personal-message'; bytes: string; signature: string }\n\t| { type: 'sign-transaction'; bytes: string; signature: string }\n\t| {\n\t\t\ttype: 'sign-and-execute-transaction';\n\t\t\tbytes: string;\n\t\t\tsignature: string;\n\t\t\tdigest: string;\n\t\t\teffects: string;\n\t };\n\n// Shared between the embedded DevWallet and the standalone popup request-handler.\nexport async function executeSigning({\n\ttype,\n\tsigner,\n\tdata,\n\tclient,\n}: ExecuteSigningOptions): Promise<SigningResult> {\n\tswitch (type) {\n\t\tcase 'sign-personal-message': {\n\t\t\tif (!(data instanceof Uint8Array)) {\n\t\t\t\tthrow new Error('sign-personal-message expects data to be a Uint8Array');\n\t\t\t}\n\t\t\tconst { bytes, signature } = await signer.signPersonalMessage(data);\n\t\t\treturn { type, bytes, signature };\n\t\t}\n\t\tcase 'sign-transaction': {\n\t\t\tif (!client) throw new Error('No client provided for sign-transaction');\n\t\t\tif (typeof data !== 'string') {\n\t\t\t\tthrow new Error('sign-transaction expects data to be a JSON string');\n\t\t\t}\n\t\t\tconst tx = Transaction.from(data);\n\t\t\tconst { bytes, signature } = await tx.sign({ client, signer });\n\t\t\treturn { type, bytes, signature };\n\t\t}\n\t\tcase 'sign-and-execute-transaction': {\n\t\t\tif (!client) throw new Error('No client provided for sign-and-execute-transaction');\n\t\t\tif (typeof data !== 'string') {\n\t\t\t\tthrow new Error('sign-and-execute-transaction expects data to be a JSON string');\n\t\t\t}\n\t\t\tconst tx = Transaction.from(data);\n\t\t\tconst { bytes, signature } = await tx.sign({ client, signer });\n\t\t\tconst result = await client.core.executeTransaction({\n\t\t\t\ttransaction: fromBase64(bytes),\n\t\t\t\tsignatures: [signature],\n\t\t\t\tinclude: { effects: true },\n\t\t\t});\n\t\t\tconst txResult = result.Transaction ?? result.FailedTransaction;\n\t\t\tif (!txResult) {\n\t\t\t\tthrow new Error('Transaction execution returned empty result');\n\t\t\t}\n\t\t\tif (!txResult.status.success) {\n\t\t\t\tthrow new Error(txResult.status.error?.message ?? 'Transaction execution failed');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttype,\n\t\t\t\tbytes,\n\t\t\t\tsignature,\n\t\t\t\tdigest: txResult.digest,\n\t\t\t\t// Empty string when effects BCS is unavailable — the wallet-standard protocol requires a string\n\t\t\t\teffects: txResult.effects?.bcs ? toBase64(txResult.effects.bcs) : '',\n\t\t\t};\n\t\t}\n\t}\n}\n"],"mappings":";;;AAgCA,eAAsB,eAAe,EACpC,MACA,QACA,MACA,UACiD;AACjD,SAAQ,MAAR;EACC,KAAK,yBAAyB;AAC7B,OAAI,EAAE,gBAAgB,YACrB,OAAM,IAAI,MAAM,wDAAwD;GAEzE,MAAM,EAAE,OAAO,cAAc,MAAM,OAAO,oBAAoB,KAAK;AACnE,UAAO;IAAE;IAAM;IAAO;IAAW;;EAElC,KAAK,oBAAoB;AACxB,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,0CAA0C;AACvE,OAAI,OAAO,SAAS,SACnB,OAAM,IAAI,MAAM,oDAAoD;GAGrE,MAAM,EAAE,OAAO,cAAc,MADlB,YAAY,KAAK,KACO,CAAG,KAAK;IAAE;IAAQ;IAAQ,CAAC;AAC9D,UAAO;IAAE;IAAM;IAAO;IAAW;;EAElC,KAAK,gCAAgC;AACpC,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,sDAAsD;AACnF,OAAI,OAAO,SAAS,SACnB,OAAM,IAAI,MAAM,gEAAgE;GAGjF,MAAM,EAAE,OAAO,cAAc,MADlB,YAAY,KAAK,KACO,CAAG,KAAK;IAAE;IAAQ;IAAQ,CAAC;GAC9D,MAAM,SAAS,MAAM,OAAO,KAAK,mBAAmB;IACnD,aAAa,WAAW,MAAM;IAC9B,YAAY,CAAC,UAAU;IACvB,SAAS,EAAE,SAAS,MAAM;IAC1B,CAAC;GACF,MAAM,WAAW,OAAO,eAAe,OAAO;AAC9C,OAAI,CAAC,SACJ,OAAM,IAAI,MAAM,8CAA8C;AAE/D,OAAI,CAAC,SAAS,OAAO,QACpB,OAAM,IAAI,MAAM,SAAS,OAAO,OAAO,WAAW,+BAA+B;AAElF,UAAO;IACN;IACA;IACA;IACA,QAAQ,SAAS;IAEjB,SAAS,SAAS,SAAS,MAAM,SAAS,SAAS,QAAQ,IAAI,GAAG;IAClE"}
|