@mysten-incubation/dev-wallet 0.5.1 → 0.6.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 (68) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +7 -4
  3. package/dist/client/connected-apps.d.mts +35 -0
  4. package/dist/client/connected-apps.d.mts.map +1 -0
  5. package/dist/client/connected-apps.mjs +50 -0
  6. package/dist/client/connected-apps.mjs.map +1 -0
  7. package/dist/client/dev-wallet-client.mjs +1 -1
  8. package/dist/client/dev-wallet-client.mjs.map +1 -1
  9. package/dist/client/index.d.mts +2 -1
  10. package/dist/client/index.mjs +2 -1
  11. package/dist/client/request-handler.d.mts +7 -0
  12. package/dist/client/request-handler.d.mts.map +1 -1
  13. package/dist/client/request-handler.mjs +17 -2
  14. package/dist/client/request-handler.mjs.map +1 -1
  15. package/dist/standalone/assets/{in-memory-adapter-Ban2kRYS.js → in-memory-adapter-uuWG4K4k.js} +1 -1
  16. package/dist/standalone/assets/main-CKYv0eR6.js +7 -0
  17. package/dist/standalone/assets/{webcrypto-adapter-Ddqn-RAu.js → webcrypto-adapter-5ShaPc_M.js} +1 -1
  18. package/dist/standalone/bookmarklet.js +1 -1
  19. package/dist/standalone/index.html +1 -1
  20. package/dist/ui/dev-wallet-balances.d.mts.map +1 -1
  21. package/dist/ui/dev-wallet-balances.mjs +20 -13
  22. package/dist/ui/dev-wallet-balances.mjs.map +1 -1
  23. package/dist/ui/dev-wallet-connect-guide.d.mts +29 -0
  24. package/dist/ui/dev-wallet-connect-guide.d.mts.map +1 -0
  25. package/dist/ui/dev-wallet-connect-guide.mjs +386 -0
  26. package/dist/ui/dev-wallet-connect-guide.mjs.map +1 -0
  27. package/dist/ui/dev-wallet-connected-apps.d.mts +27 -0
  28. package/dist/ui/dev-wallet-connected-apps.d.mts.map +1 -0
  29. package/dist/ui/dev-wallet-connected-apps.mjs +164 -0
  30. package/dist/ui/dev-wallet-connected-apps.mjs.map +1 -0
  31. package/dist/ui/dev-wallet-panel.d.mts.map +1 -1
  32. package/dist/ui/dev-wallet-panel.mjs +0 -9
  33. package/dist/ui/dev-wallet-panel.mjs.map +1 -1
  34. package/dist/ui/dev-wallet-settings.d.mts +8 -2
  35. package/dist/ui/dev-wallet-settings.d.mts.map +1 -1
  36. package/dist/ui/dev-wallet-settings.mjs +86 -171
  37. package/dist/ui/dev-wallet-settings.mjs.map +1 -1
  38. package/dist/ui/dev-wallet-standalone.d.mts +7 -2
  39. package/dist/ui/dev-wallet-standalone.d.mts.map +1 -1
  40. package/dist/ui/dev-wallet-standalone.mjs +68 -222
  41. package/dist/ui/dev-wallet-standalone.mjs.map +1 -1
  42. package/dist/ui/index.d.mts +3 -1
  43. package/dist/ui/index.mjs +3 -1
  44. package/dist/ui/wallet-controller.mjs +15 -3
  45. package/dist/ui/wallet-controller.mjs.map +1 -1
  46. package/dist/wallet/dev-wallet.d.mts +15 -3
  47. package/dist/wallet/dev-wallet.d.mts.map +1 -1
  48. package/dist/wallet/dev-wallet.mjs +94 -30
  49. package/dist/wallet/dev-wallet.mjs.map +1 -1
  50. package/dist/wallet/persisted.mjs +20 -0
  51. package/dist/wallet/persisted.mjs.map +1 -0
  52. package/package.json +6 -6
  53. package/src/app/main.ts +6 -2
  54. package/src/client/connected-apps.ts +79 -0
  55. package/src/client/dev-wallet-client.ts +2 -1
  56. package/src/client/index.ts +2 -0
  57. package/src/client/request-handler.ts +24 -1
  58. package/src/ui/dev-wallet-balances.ts +25 -13
  59. package/src/ui/dev-wallet-connect-guide.ts +428 -0
  60. package/src/ui/dev-wallet-connected-apps.ts +191 -0
  61. package/src/ui/dev-wallet-panel.ts +0 -9
  62. package/src/ui/dev-wallet-settings.ts +101 -179
  63. package/src/ui/dev-wallet-standalone.ts +80 -231
  64. package/src/ui/index.ts +2 -0
  65. package/src/ui/wallet-controller.ts +23 -3
  66. package/src/wallet/dev-wallet.ts +130 -39
  67. package/src/wallet/persisted.ts +24 -0
  68. package/dist/standalone/assets/main-xfzarPod.js +0 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @mysten-incubation/dev-wallet
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - aac3fb5: Standalone wallet and hosted-wallet fixes.
8
+
9
+ - **Breaking:** `DevWalletConfig.persistNetworks` is renamed to `persistState`. It now also
10
+ persists the active network and the UI's active account, under a versioned `dev-wallet:state:v1`
11
+ key. Networks saved under the old `dev-wallet:networks` key aren't migrated. Invalid saved state
12
+ is ignored with a warning.
13
+ - **Breaking:** `<dev-wallet-standalone>`'s `bookmarkletOrigin` is renamed to `walletOrigin`. It
14
+ now defaults to the page origin.
15
+ - New `DevWallet.activeAccount` / `setActiveAccount()`.
16
+ - New connected-apps tracking: `ConnectedAppsStore` (in `/client`), which you pass to
17
+ `parseWalletRequest({ connectedApps })` and `<dev-wallet-standalone>.connectedApps`. Approved
18
+ connects are recorded, and signing requests from a disconnected origin are rejected.
19
+ - The standalone page centers the wallet, with a tabbed connect guide on the left (bookmarklet
20
+ steps, console script, dApp Kit snippet) and connected apps on the right. On narrow screens both
21
+ move to the top of the Settings tab. New elements: `<dev-wallet-connect-guide>` and
22
+ `<dev-wallet-connected-apps>`. The page drops the embed snippet, the stale `v0.1.0` badge, and
23
+ the "Running" indicator. On phones, the bookmarklet tab shows copy-and-edit steps for iOS or
24
+ Android.
25
+ - The `serve` wallet configures the devnet and localnet faucets, so the Faucet button works there.
26
+ After a faucet request, the balance refreshes once the transfer lands, not before.
27
+ - Custom networks in Settings take an optional faucet URL. `addNetwork(name, url, null)` now
28
+ clears a network's faucet (omitting the argument leaves it unchanged), and faucet URLs are
29
+ persisted.
30
+ - Fix: switching networks didn't re-render the wallet UI, so the badge, balances, and Faucet
31
+ button stayed on the previous network.
32
+ - Remove the non-functional "Manage" button from the balances list.
33
+ - `DevWalletClient` identifies the requesting dApp in approval popups by its `document.title`
34
+ (falling back to its host) instead of the wallet's own name.
35
+
3
36
  ## 0.5.1
4
37
 
5
38
  ### Patch Changes
package/README.md CHANGED
@@ -227,10 +227,13 @@ signature with that address, the transaction bytes are sent to the local `sui ke
227
227
 
228
228
  ### Bookmarklet
229
229
 
230
- The standalone wallet also serves a bookmarklet for quick injection into any dApp. You can find it
231
- in the **Settings** tab drag it to your bookmarks bar, or copy the console snippet from the
232
- terminal output. Clicking the bookmarklet on any page registers the standalone wallet without
233
- needing to modify the dApp's source code.
230
+ The standalone wallet also serves a bookmarklet that adds it to any dApp without code changes. Drag
231
+ the **Dev Wallet** button from the wallet page (or its Settings tab on small screens) to your
232
+ bookmarks bar, or copy the console script shown next to it.
233
+
234
+ A hosted copy of the standalone wallet, without CLI signing, runs at
235
+ <https://sui-dev-wallet.vercel.app>. See the
236
+ [Hosted wallet guide](https://ts-sdks-incubation.vercel.app/dev-wallet/guides/hosted-wallet).
234
237
 
235
238
  ## Imports
236
239
 
@@ -0,0 +1,35 @@
1
+ //#region src/client/connected-apps.d.ts
2
+ /** localStorage key for the connected-apps list. Bump the suffix on shape changes. */
3
+ declare const CONNECTED_APPS_STORAGE_KEY = "dev-wallet:connected-apps:v1";
4
+ /** A dApp the user approved a connection for in the standalone wallet. */
5
+ interface ConnectedApp {
6
+ /** The dApp's origin — the identity sessions are scoped to. */
7
+ origin: string;
8
+ /** Display name the dApp sent (its page title). */
9
+ name: string;
10
+ /** Addresses shared with the dApp. */
11
+ accounts: string[];
12
+ /** Milliseconds since epoch of the latest approval. */
13
+ connectedAt: number;
14
+ }
15
+ /**
16
+ * Connected dApps for a standalone wallet, stored in the wallet origin's
17
+ * localStorage so the popup (which records connections) and the wallet page
18
+ * (which lists them) share it. Removing an app makes the popup reject that
19
+ * origin's signing requests until it reconnects.
20
+ */
21
+ declare class ConnectedAppsStore {
22
+ #private;
23
+ constructor(storage?: Storage);
24
+ /** Connected apps, most recently connected first. */
25
+ list(): ConnectedApp[];
26
+ has(origin: string): boolean;
27
+ /** Add an app, or replace the entry for its origin. */
28
+ record(app: ConnectedApp): void;
29
+ remove(origin: string): void;
30
+ /** Call `callback` when another window (e.g. the signing popup) changes the list. */
31
+ subscribe(callback: () => void): () => void;
32
+ }
33
+ //#endregion
34
+ export { CONNECTED_APPS_STORAGE_KEY, ConnectedApp, ConnectedAppsStore };
35
+ //# sourceMappingURL=connected-apps.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connected-apps.d.mts","names":[],"sources":["../../src/client/connected-apps.ts"],"mappings":";;cAMa,0BAAA;;UAGI,YAAA;EAHsB;EAKtC,MAAA;EAFgB;EAIhB,IAAA;;EAEA,QAAA;EAJA;EAMA,WAAA;AAAA;;;AAAW;AAqBZ;;;cAAa,kBAAA;EAAA;cAGA,OAAA,GAAS,OAAA;EAiBG;EAZxB,IAAA,IAAQ,YAAA;EAOR,GAAA,CAAI,MAAA;;EAKJ,MAAA,CAAO,GAAA,EAAK,YAAA;EAIZ,MAAA,CAAO,MAAA;EAhBP;EAqBA,SAAA,CAAU,QAAA;AAAA"}
@@ -0,0 +1,50 @@
1
+ import { readPersisted } from "../wallet/persisted.mjs";
2
+ //#region src/client/connected-apps.ts
3
+ /** localStorage key for the connected-apps list. Bump the suffix on shape changes. */
4
+ const CONNECTED_APPS_STORAGE_KEY = "dev-wallet:connected-apps:v1";
5
+ function isConnectedApp(value) {
6
+ if (typeof value !== "object" || value === null) return false;
7
+ const app = value;
8
+ return typeof app.origin === "string" && typeof app.name === "string" && Array.isArray(app.accounts) && app.accounts.every((a) => typeof a === "string") && typeof app.connectedAt === "number";
9
+ }
10
+ /**
11
+ * Connected dApps for a standalone wallet, stored in the wallet origin's
12
+ * localStorage so the popup (which records connections) and the wallet page
13
+ * (which lists them) share it. Removing an app makes the popup reject that
14
+ * origin's signing requests until it reconnects.
15
+ */
16
+ var ConnectedAppsStore = class {
17
+ #storage;
18
+ constructor(storage = localStorage) {
19
+ this.#storage = storage;
20
+ }
21
+ /** Connected apps, most recently connected first. */
22
+ list() {
23
+ return (readPersisted(this.#storage, CONNECTED_APPS_STORAGE_KEY, (value) => Array.isArray(value) && value.every(isConnectedApp) ? value : null) ?? []).sort((a, b) => b.connectedAt - a.connectedAt);
24
+ }
25
+ has(origin) {
26
+ return this.list().some((app) => app.origin === origin);
27
+ }
28
+ /** Add an app, or replace the entry for its origin. */
29
+ record(app) {
30
+ this.#write([app, ...this.list().filter((a) => a.origin !== app.origin)]);
31
+ }
32
+ remove(origin) {
33
+ this.#write(this.list().filter((a) => a.origin !== origin));
34
+ }
35
+ /** Call `callback` when another window (e.g. the signing popup) changes the list. */
36
+ subscribe(callback) {
37
+ const onStorage = (e) => {
38
+ if (e.key === "dev-wallet:connected-apps:v1" || e.key === null) callback();
39
+ };
40
+ window.addEventListener("storage", onStorage);
41
+ return () => window.removeEventListener("storage", onStorage);
42
+ }
43
+ #write(apps) {
44
+ this.#storage.setItem(CONNECTED_APPS_STORAGE_KEY, JSON.stringify(apps));
45
+ }
46
+ };
47
+ //#endregion
48
+ export { CONNECTED_APPS_STORAGE_KEY, ConnectedAppsStore };
49
+
50
+ //# sourceMappingURL=connected-apps.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connected-apps.mjs","names":["#storage","#write"],"sources":["../../src/client/connected-apps.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { readPersisted } from '../wallet/persisted.js';\n\n/** localStorage key for the connected-apps list. Bump the suffix on shape changes. */\nexport const CONNECTED_APPS_STORAGE_KEY = 'dev-wallet:connected-apps:v1';\n\n/** A dApp the user approved a connection for in the standalone wallet. */\nexport interface ConnectedApp {\n\t/** The dApp's origin — the identity sessions are scoped to. */\n\torigin: string;\n\t/** Display name the dApp sent (its page title). */\n\tname: string;\n\t/** Addresses shared with the dApp. */\n\taccounts: string[];\n\t/** Milliseconds since epoch of the latest approval. */\n\tconnectedAt: number;\n}\n\nfunction isConnectedApp(value: unknown): value is ConnectedApp {\n\tif (typeof value !== 'object' || value === null) return false;\n\tconst app = value as Record<string, unknown>;\n\treturn (\n\t\ttypeof app.origin === 'string' &&\n\t\ttypeof app.name === 'string' &&\n\t\tArray.isArray(app.accounts) &&\n\t\tapp.accounts.every((a) => typeof a === 'string') &&\n\t\ttypeof app.connectedAt === 'number'\n\t);\n}\n\n/**\n * Connected dApps for a standalone wallet, stored in the wallet origin's\n * localStorage so the popup (which records connections) and the wallet page\n * (which lists them) share it. Removing an app makes the popup reject that\n * origin's signing requests until it reconnects.\n */\nexport class ConnectedAppsStore {\n\treadonly #storage: Storage;\n\n\tconstructor(storage: Storage = localStorage) {\n\t\tthis.#storage = storage;\n\t}\n\n\t/** Connected apps, most recently connected first. */\n\tlist(): ConnectedApp[] {\n\t\tconst apps = readPersisted(this.#storage, CONNECTED_APPS_STORAGE_KEY, (value) =>\n\t\t\tArray.isArray(value) && value.every(isConnectedApp) ? value : null,\n\t\t);\n\t\treturn (apps ?? []).sort((a, b) => b.connectedAt - a.connectedAt);\n\t}\n\n\thas(origin: string): boolean {\n\t\treturn this.list().some((app) => app.origin === origin);\n\t}\n\n\t/** Add an app, or replace the entry for its origin. */\n\trecord(app: ConnectedApp): void {\n\t\tthis.#write([app, ...this.list().filter((a) => a.origin !== app.origin)]);\n\t}\n\n\tremove(origin: string): void {\n\t\tthis.#write(this.list().filter((a) => a.origin !== origin));\n\t}\n\n\t/** Call `callback` when another window (e.g. the signing popup) changes the list. */\n\tsubscribe(callback: () => void): () => void {\n\t\tconst onStorage = (e: StorageEvent) => {\n\t\t\tif (e.key === CONNECTED_APPS_STORAGE_KEY || e.key === null) callback();\n\t\t};\n\t\twindow.addEventListener('storage', onStorage);\n\t\treturn () => window.removeEventListener('storage', onStorage);\n\t}\n\n\t#write(apps: ConnectedApp[]): void {\n\t\tthis.#storage.setItem(CONNECTED_APPS_STORAGE_KEY, JSON.stringify(apps));\n\t}\n}\n"],"mappings":";;;AAMA,MAAa,6BAA6B;AAc1C,SAAS,eAAe,OAAuC;CAC9D,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,MAAM;CACZ,OACC,OAAO,IAAI,WAAW,YACtB,OAAO,IAAI,SAAS,YACpB,MAAM,QAAQ,IAAI,QAAQ,KAC1B,IAAI,SAAS,OAAO,MAAM,OAAO,MAAM,QAAQ,KAC/C,OAAO,IAAI,gBAAgB;AAE7B;;;;;;;AAQA,IAAa,qBAAb,MAAgC;CAC/B;CAEA,YAAY,UAAmB,cAAc;EAC5C,KAAKA,WAAW;CACjB;;CAGA,OAAuB;EAItB,QAHa,cAAc,KAAKA,UAAU,6BAA6B,UACtE,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,cAAc,IAAI,QAAQ,IAEvD,KAAQ,CAAC,EAAA,CAAG,MAAM,GAAG,MAAM,EAAE,cAAc,EAAE,WAAW;CACjE;CAEA,IAAI,QAAyB;EAC5B,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,QAAQ,IAAI,WAAW,MAAM;CACvD;;CAGA,OAAO,KAAyB;EAC/B,KAAKC,OAAO,CAAC,KAAK,GAAG,KAAK,KAAK,CAAC,CAAC,QAAQ,MAAM,EAAE,WAAW,IAAI,MAAM,CAAC,CAAC;CACzE;CAEA,OAAO,QAAsB;EAC5B,KAAKA,OAAO,KAAK,KAAK,CAAC,CAAC,QAAQ,MAAM,EAAE,WAAW,MAAM,CAAC;CAC3D;;CAGA,UAAU,UAAkC;EAC3C,MAAM,aAAa,MAAoB;GACtC,IAAI,EAAE,QAAA,kCAAsC,EAAE,QAAQ,MAAM,SAAS;EACtE;EACA,OAAO,iBAAiB,WAAW,SAAS;EAC5C,aAAa,OAAO,oBAAoB,WAAW,SAAS;CAC7D;CAEA,OAAO,MAA4B;EAClC,KAAKD,SAAS,QAAQ,4BAA4B,KAAK,UAAU,IAAI,CAAC;CACvE;AACD"}
@@ -164,7 +164,7 @@ var DevWalletClient = class DevWalletClient {
164
164
  };
165
165
  #createChannel() {
166
166
  return new DappPostMessageChannel({
167
- appName: this.#name,
167
+ appName: globalThis.document?.title || globalThis.location?.host || this.#name,
168
168
  hostOrigin: this.#origin
169
169
  });
170
170
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dev-wallet-client.mjs","names":["#name","#icon","#origin","#sessionKey","#events","#tryRestoreSession","#accounts","#connect","#on","#disconnect","#signPersonalMessage","#signTransaction","#signAndExecuteTransaction","#createChannel","#setSession","#setAccountsFromSession","#clearSession","#getSession"],"sources":["../../src/client/dev-wallet-client.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\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\tWalletIcon,\n} from '@mysten/wallet-standard';\nimport { getWallets, ReadonlyWalletAccount, SUI_CHAINS } from '@mysten/wallet-standard';\nimport { DappPostMessageChannel, decodeJwtSession } from '@mysten/window-wallet-core';\n\nimport { DEFAULT_WALLET_ICON, type WalletEventsMap } from '../wallet/constants.js';\n\nconst DEFAULT_WALLET_NAME = 'Dev Wallet (Web)';\nconst DEFAULT_ORIGIN = 'http://localhost:5174';\n\n/**\n * Creates a wallet initializer that can be passed to `createDAppKit({ walletInitializers: [...] })`.\n *\n * This registers a {@link DevWalletClient} that communicates with a standalone\n * dev wallet server via PostMessage popups.\n *\n * @example\n * ```ts\n * import { createDAppKit } from '@mysten/dapp-kit-react';\n * import { devWalletClientInitializer } from '@mysten-incubation/dev-wallet/client';\n *\n * const dAppKit = createDAppKit({\n * networks: ['devnet'],\n * walletInitializers: [\n * devWalletClientInitializer({ origin: 'http://localhost:5174' }),\n * ],\n * });\n * ```\n */\nexport function devWalletClientInitializer(options?: DevWalletClientOptions): {\n\tid: string;\n\tinitialize(): { unregister: () => void };\n} {\n\treturn {\n\t\tid: 'dev-wallet-client-initializer',\n\t\tinitialize() {\n\t\t\tconst unregister = DevWalletClient.register(options);\n\t\t\treturn { unregister };\n\t\t},\n\t};\n}\n\nconst WALLET_FEATURES = [\n\t'sui:signTransaction',\n\t'sui:signAndExecuteTransaction',\n\t'sui:signPersonalMessage',\n] as const;\n\n/**\n * Options for creating a DevWalletClient.\n */\nexport interface DevWalletClientOptions {\n\t/** Display name for the wallet. Defaults to 'Dev Wallet (Web)'. */\n\tname?: string;\n\t/** Data URI icon for the wallet. */\n\ticon?: WalletIcon;\n\t/** Origin of the dev wallet web app. Defaults to 'http://localhost:5174'. */\n\torigin?: string;\n}\n\n/**\n * Wallet-standard wallet that communicates with a standalone DevWallet\n * web app via PostMessage popups (started via `npx @mysten-incubation/dev-wallet serve`).\n */\nexport class DevWalletClient implements Wallet {\n\treadonly #name: string;\n\treadonly #icon: WalletIcon;\n\treadonly #origin: string;\n\treadonly #sessionKey: string;\n\t#accounts: ReadonlyWalletAccount[] = [];\n\t#events: Emitter<WalletEventsMap>;\n\n\tconstructor(options?: DevWalletClientOptions) {\n\t\tthis.#name = options?.name ?? DEFAULT_WALLET_NAME;\n\t\tthis.#icon = options?.icon ?? DEFAULT_WALLET_ICON;\n\t\tthis.#origin = options?.origin ?? DEFAULT_ORIGIN;\n\t\tthis.#sessionKey = `dev-wallet:session:${this.#origin}`;\n\t\tthis.#events = mitt();\n\t\tthis.#tryRestoreSession();\n\t}\n\n\tstatic register(options?: DevWalletClientOptions): () => void {\n\t\tconst wallet = new DevWalletClient(options);\n\t\tconst wallets = getWallets();\n\t\treturn wallets.register(wallet);\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#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\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({ type: 'connect' });\n\n\t\tthis.#setSession(response.session);\n\t\tthis.#setAccountsFromSession(response.session);\n\n\t\treturn { accounts: this.accounts };\n\t};\n\n\t#disconnect: StandardDisconnectMethod = async () => {\n\t\tthis.#clearSession();\n\t\tthis.#accounts = [];\n\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t};\n\n\t#signPersonalMessage: SuiSignPersonalMessageMethod = async (input) => {\n\t\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({\n\t\t\ttype: 'sign-personal-message',\n\t\t\tmessage: toBase64(input.message),\n\t\t\taddress: input.account.address,\n\t\t\tchain: input.chain ?? input.account.chains[0] ?? 'sui:unknown',\n\t\t\tsession: this.#getSession(),\n\t\t});\n\n\t\treturn { bytes: response.bytes, signature: response.signature };\n\t};\n\n\t#signTransaction: SuiSignTransactionMethod = async (input) => {\n\t\tconst txJson = await input.transaction.toJSON();\n\t\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({\n\t\t\ttype: 'sign-transaction',\n\t\t\ttransaction: txJson,\n\t\t\taddress: input.account.address,\n\t\t\tchain: input.chain,\n\t\t\tsession: this.#getSession(),\n\t\t});\n\n\t\treturn { bytes: response.bytes, signature: response.signature };\n\t};\n\n\t#signAndExecuteTransaction: SuiSignAndExecuteTransactionMethod = async (input) => {\n\t\tconst txJson = await input.transaction.toJSON();\n\t\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({\n\t\t\ttype: 'sign-and-execute-transaction',\n\t\t\ttransaction: txJson,\n\t\t\taddress: input.account.address,\n\t\t\tchain: input.chain,\n\t\t\tsession: this.#getSession(),\n\t\t});\n\n\t\treturn {\n\t\t\tbytes: response.bytes,\n\t\t\tsignature: response.signature,\n\t\t\tdigest: response.digest,\n\t\t\teffects: response.effects,\n\t\t};\n\t};\n\n\t#createChannel(): DappPostMessageChannel {\n\t\treturn new DappPostMessageChannel({\n\t\t\tappName: this.#name,\n\t\t\thostOrigin: this.#origin,\n\t\t});\n\t}\n\n\t#getSession(): string {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\tthrow new Error('No active session. Call connect() first.');\n\t\t}\n\t\tconst session = localStorage.getItem(this.#sessionKey);\n\t\tif (!session) {\n\t\t\tthrow new Error('No active session. Call connect() first.');\n\t\t}\n\t\treturn session;\n\t}\n\n\t#setSession(session: string): void {\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.setItem(this.#sessionKey, session);\n\t\t}\n\t}\n\n\t#clearSession(): void {\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.removeItem(this.#sessionKey);\n\t\t}\n\t}\n\n\t#setAccountsFromSession(session: string): void {\n\t\tconst decoded = decodeJwtSession(session);\n\t\tthis.#accounts = decoded.payload.accounts.map(\n\t\t\t(account: { address: string; publicKey: string; label?: string }) =>\n\t\t\t\tnew ReadonlyWalletAccount({\n\t\t\t\t\taddress: account.address,\n\t\t\t\t\tpublicKey: account.publicKey ? fromBase64(account.publicKey) : new Uint8Array(0),\n\t\t\t\t\tchains: [...SUI_CHAINS],\n\t\t\t\t\tfeatures: [...WALLET_FEATURES],\n\t\t\t\t\tlabel: account.label,\n\t\t\t\t}),\n\t\t);\n\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t}\n\n\t#tryRestoreSession(): void {\n\t\tif (typeof localStorage === 'undefined') return;\n\t\tconst session = localStorage.getItem(this.#sessionKey);\n\t\tif (!session) return;\n\n\t\ttry {\n\t\t\tthis.#setAccountsFromSession(session);\n\t\t} catch {\n\t\t\tthis.#clearSession();\n\t\t}\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dev-wallet-client.mjs","names":["#name","#icon","#origin","#sessionKey","#events","#tryRestoreSession","#accounts","#connect","#on","#disconnect","#signPersonalMessage","#signTransaction","#signAndExecuteTransaction","#createChannel","#setSession","#setAccountsFromSession","#clearSession","#getSession"],"sources":["../../src/client/dev-wallet-client.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\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\tWalletIcon,\n} from '@mysten/wallet-standard';\nimport { getWallets, ReadonlyWalletAccount, SUI_CHAINS } from '@mysten/wallet-standard';\nimport { DappPostMessageChannel, decodeJwtSession } from '@mysten/window-wallet-core';\n\nimport { DEFAULT_WALLET_ICON, type WalletEventsMap } from '../wallet/constants.js';\n\nconst DEFAULT_WALLET_NAME = 'Dev Wallet (Web)';\nconst DEFAULT_ORIGIN = 'http://localhost:5174';\n\n/**\n * Creates a wallet initializer that can be passed to `createDAppKit({ walletInitializers: [...] })`.\n *\n * This registers a {@link DevWalletClient} that communicates with a standalone\n * dev wallet server via PostMessage popups.\n *\n * @example\n * ```ts\n * import { createDAppKit } from '@mysten/dapp-kit-react';\n * import { devWalletClientInitializer } from '@mysten-incubation/dev-wallet/client';\n *\n * const dAppKit = createDAppKit({\n * networks: ['devnet'],\n * walletInitializers: [\n * devWalletClientInitializer({ origin: 'http://localhost:5174' }),\n * ],\n * });\n * ```\n */\nexport function devWalletClientInitializer(options?: DevWalletClientOptions): {\n\tid: string;\n\tinitialize(): { unregister: () => void };\n} {\n\treturn {\n\t\tid: 'dev-wallet-client-initializer',\n\t\tinitialize() {\n\t\t\tconst unregister = DevWalletClient.register(options);\n\t\t\treturn { unregister };\n\t\t},\n\t};\n}\n\nconst WALLET_FEATURES = [\n\t'sui:signTransaction',\n\t'sui:signAndExecuteTransaction',\n\t'sui:signPersonalMessage',\n] as const;\n\n/**\n * Options for creating a DevWalletClient.\n */\nexport interface DevWalletClientOptions {\n\t/** Display name for the wallet. Defaults to 'Dev Wallet (Web)'. */\n\tname?: string;\n\t/** Data URI icon for the wallet. */\n\ticon?: WalletIcon;\n\t/** Origin of the dev wallet web app. Defaults to 'http://localhost:5174'. */\n\torigin?: string;\n}\n\n/**\n * Wallet-standard wallet that communicates with a standalone DevWallet\n * web app via PostMessage popups (started via `npx @mysten-incubation/dev-wallet serve`).\n */\nexport class DevWalletClient implements Wallet {\n\treadonly #name: string;\n\treadonly #icon: WalletIcon;\n\treadonly #origin: string;\n\treadonly #sessionKey: string;\n\t#accounts: ReadonlyWalletAccount[] = [];\n\t#events: Emitter<WalletEventsMap>;\n\n\tconstructor(options?: DevWalletClientOptions) {\n\t\tthis.#name = options?.name ?? DEFAULT_WALLET_NAME;\n\t\tthis.#icon = options?.icon ?? DEFAULT_WALLET_ICON;\n\t\tthis.#origin = options?.origin ?? DEFAULT_ORIGIN;\n\t\tthis.#sessionKey = `dev-wallet:session:${this.#origin}`;\n\t\tthis.#events = mitt();\n\t\tthis.#tryRestoreSession();\n\t}\n\n\tstatic register(options?: DevWalletClientOptions): () => void {\n\t\tconst wallet = new DevWalletClient(options);\n\t\tconst wallets = getWallets();\n\t\treturn wallets.register(wallet);\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#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\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({ type: 'connect' });\n\n\t\tthis.#setSession(response.session);\n\t\tthis.#setAccountsFromSession(response.session);\n\n\t\treturn { accounts: this.accounts };\n\t};\n\n\t#disconnect: StandardDisconnectMethod = async () => {\n\t\tthis.#clearSession();\n\t\tthis.#accounts = [];\n\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t};\n\n\t#signPersonalMessage: SuiSignPersonalMessageMethod = async (input) => {\n\t\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({\n\t\t\ttype: 'sign-personal-message',\n\t\t\tmessage: toBase64(input.message),\n\t\t\taddress: input.account.address,\n\t\t\tchain: input.chain ?? input.account.chains[0] ?? 'sui:unknown',\n\t\t\tsession: this.#getSession(),\n\t\t});\n\n\t\treturn { bytes: response.bytes, signature: response.signature };\n\t};\n\n\t#signTransaction: SuiSignTransactionMethod = async (input) => {\n\t\tconst txJson = await input.transaction.toJSON();\n\t\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({\n\t\t\ttype: 'sign-transaction',\n\t\t\ttransaction: txJson,\n\t\t\taddress: input.account.address,\n\t\t\tchain: input.chain,\n\t\t\tsession: this.#getSession(),\n\t\t});\n\n\t\treturn { bytes: response.bytes, signature: response.signature };\n\t};\n\n\t#signAndExecuteTransaction: SuiSignAndExecuteTransactionMethod = async (input) => {\n\t\tconst txJson = await input.transaction.toJSON();\n\t\tconst channel = this.#createChannel();\n\t\tconst response = await channel.send({\n\t\t\ttype: 'sign-and-execute-transaction',\n\t\t\ttransaction: txJson,\n\t\t\taddress: input.account.address,\n\t\t\tchain: input.chain,\n\t\t\tsession: this.#getSession(),\n\t\t});\n\n\t\treturn {\n\t\t\tbytes: response.bytes,\n\t\t\tsignature: response.signature,\n\t\t\tdigest: response.digest,\n\t\t\teffects: response.effects,\n\t\t};\n\t};\n\n\t#createChannel(): DappPostMessageChannel {\n\t\treturn new DappPostMessageChannel({\n\t\t\t// Identifies the requesting dApp in the wallet's approval popup.\n\t\t\tappName: globalThis.document?.title || globalThis.location?.host || this.#name,\n\t\t\thostOrigin: this.#origin,\n\t\t});\n\t}\n\n\t#getSession(): string {\n\t\tif (typeof localStorage === 'undefined') {\n\t\t\tthrow new Error('No active session. Call connect() first.');\n\t\t}\n\t\tconst session = localStorage.getItem(this.#sessionKey);\n\t\tif (!session) {\n\t\t\tthrow new Error('No active session. Call connect() first.');\n\t\t}\n\t\treturn session;\n\t}\n\n\t#setSession(session: string): void {\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.setItem(this.#sessionKey, session);\n\t\t}\n\t}\n\n\t#clearSession(): void {\n\t\tif (typeof localStorage !== 'undefined') {\n\t\t\tlocalStorage.removeItem(this.#sessionKey);\n\t\t}\n\t}\n\n\t#setAccountsFromSession(session: string): void {\n\t\tconst decoded = decodeJwtSession(session);\n\t\tthis.#accounts = decoded.payload.accounts.map(\n\t\t\t(account: { address: string; publicKey: string; label?: string }) =>\n\t\t\t\tnew ReadonlyWalletAccount({\n\t\t\t\t\taddress: account.address,\n\t\t\t\t\tpublicKey: account.publicKey ? fromBase64(account.publicKey) : new Uint8Array(0),\n\t\t\t\t\tchains: [...SUI_CHAINS],\n\t\t\t\t\tfeatures: [...WALLET_FEATURES],\n\t\t\t\t\tlabel: account.label,\n\t\t\t\t}),\n\t\t);\n\t\tthis.#events.emit('change', { accounts: this.#accounts });\n\t}\n\n\t#tryRestoreSession(): void {\n\t\tif (typeof localStorage === 'undefined') return;\n\t\tconst session = localStorage.getItem(this.#sessionKey);\n\t\tif (!session) return;\n\n\t\ttry {\n\t\t\tthis.#setAccountsFromSession(session);\n\t\t} catch {\n\t\t\tthis.#clearSession();\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  import { DevWalletClient, DevWalletClientOptions, devWalletClientInitializer } from "./dev-wallet-client.mjs";
2
+ import { CONNECTED_APPS_STORAGE_KEY, ConnectedApp, ConnectedAppsStore } from "./connected-apps.mjs";
2
3
  import { HandleRequestOptions, PendingWalletRequest, parseWalletRequest } from "./request-handler.mjs";
3
- export { DevWalletClient, type DevWalletClientOptions, type HandleRequestOptions, type PendingWalletRequest, devWalletClientInitializer, parseWalletRequest };
4
+ export { CONNECTED_APPS_STORAGE_KEY, type ConnectedApp, ConnectedAppsStore, DevWalletClient, type DevWalletClientOptions, type HandleRequestOptions, type PendingWalletRequest, devWalletClientInitializer, parseWalletRequest };
@@ -1,3 +1,4 @@
1
1
  import { DevWalletClient, devWalletClientInitializer } from "./dev-wallet-client.mjs";
2
2
  import { parseWalletRequest } from "./request-handler.mjs";
3
- export { DevWalletClient, devWalletClientInitializer, parseWalletRequest };
3
+ import { CONNECTED_APPS_STORAGE_KEY, ConnectedAppsStore } from "./connected-apps.mjs";
4
+ export { CONNECTED_APPS_STORAGE_KEY, ConnectedAppsStore, DevWalletClient, devWalletClientInitializer, parseWalletRequest };
@@ -1,4 +1,5 @@
1
1
  import { SignerAdapter } from "../types.mjs";
2
+ import { ConnectedAppsStore } from "./connected-apps.mjs";
2
3
  import { ClientWithCoreApi } from "@mysten/sui/client";
3
4
 
4
5
  //#region src/client/request-handler.d.ts
@@ -35,6 +36,12 @@ interface HandleRequestOptions {
35
36
  getClient?: (network: string) => ClientWithCoreApi | undefined;
36
37
  /** URL hash containing the encoded request. Defaults to window.location.hash. */
37
38
  hash?: string;
39
+ /**
40
+ * Tracks connected dApps. When set, approved connects are recorded here and
41
+ * signing requests from an origin that isn't in the store are rejected, so
42
+ * removing an app disconnects it.
43
+ */
44
+ connectedApps?: ConnectedAppsStore;
38
45
  }
39
46
  declare function parseWalletRequest(options: HandleRequestOptions): PendingWalletRequest;
40
47
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"request-handler.d.mts","names":[],"sources":["../../src/client/request-handler.ts"],"mappings":";;;;;;AAiBA;;;;UAAiB,oBAAA;EAChB,IAAA;EACA,OAAA;EACA,MAAA;EACA,OAAA;EACA,KAAA;EACA,IAAA,YAAgB,UAAA;EAMhB;;;;;EAAA,OAAA,CAAQ,OAAA;IAAY,iBAAA;EAAA,IAAiC,OAAO;EAK5C;EAHhB,MAAA,CAAO,MAAA;AAAA;AAAA,UAGS,oBAAA;EAIF;EAFd,QAAA,EAAU,aAAA;EAIuB;EAFjC,YAAA,EAAc,SAAA,GAAY,UAAA;EAEwB;EAAlD,SAAA,IAAa,OAAA,aAAoB,iBAAA;EAJvB;EAMV,IAAA;AAAA;AAAA,iBAGe,kBAAA,CAAmB,OAAA,EAAS,oBAAA,GAAuB,oBAAoB"}
1
+ {"version":3,"file":"request-handler.d.mts","names":[],"sources":["../../src/client/request-handler.ts"],"mappings":";;;;;;;AAkBA;;;;UAAiB,oBAAA;EAChB,IAAA;EACA,OAAA;EACA,MAAA;EACA,OAAA;EACA,KAAA;EACA,IAAA,YAAgB,UAAA;EAMhB;;;;;EAAA,OAAA,CAAQ,OAAA;IAAY,iBAAA;EAAA,IAAiC,OAAO;EAK5C;EAHhB,MAAA,CAAO,MAAA;AAAA;AAAA,UAGS,oBAAA;EAIF;EAFd,QAAA,EAAU,aAAA;EAIuB;EAFjC,YAAA,EAAc,SAAA,GAAY,UAAA;EAUQ;EARlC,SAAA,IAAa,OAAA,aAAoB,iBAAA;EAJjC;EAMA,IAAA;EAJA;;;;;EAUA,aAAA,GAAgB,kBAAA;AAAA;AAAA,iBAGD,kBAAA,CAAmB,OAAA,EAAS,oBAAA,GAAuB,oBAAoB"}
@@ -9,6 +9,7 @@ function parseWalletRequest(options) {
9
9
  const channel = WalletPostMessageChannel.fromUrlHash(hash);
10
10
  const requestData = channel.getRequestData();
11
11
  const payload = requestData.payload;
12
+ const appOrigin = new URL(requestData.appUrl).origin;
12
13
  if (payload.type === "connect") return {
13
14
  type: "connect",
14
15
  appName: requestData.appName,
@@ -20,11 +21,18 @@ function parseWalletRequest(options) {
20
21
  label: a.label
21
22
  })));
22
23
  const selected = approveOptions?.selectedAddresses;
23
- const session = await createJwtSession({ accounts: selected ? allAccounts.filter((a) => selected.includes(a.address)) : allAccounts }, {
24
+ const accounts = selected ? allAccounts.filter((a) => selected.includes(a.address)) : allAccounts;
25
+ const session = await createJwtSession({ accounts }, {
24
26
  secretKey: options.jwtSecretKey,
25
27
  expirationTime: "7d",
26
28
  issuer: "dev-wallet",
27
- audience: new URL(requestData.appUrl).origin
29
+ audience: appOrigin
30
+ });
31
+ options.connectedApps?.record({
32
+ origin: appOrigin,
33
+ name: requestData.appName,
34
+ accounts: accounts.map((a) => a.address),
35
+ connectedAt: Date.now()
28
36
  });
29
37
  channel.sendMessage({
30
38
  type: "resolve",
@@ -59,6 +67,13 @@ function parseWalletRequest(options) {
59
67
  });
60
68
  return;
61
69
  }
70
+ if (options.connectedApps && !options.connectedApps.has(appOrigin)) {
71
+ channel.sendMessage({
72
+ type: "reject",
73
+ reason: `${appOrigin} was disconnected from the wallet. Reconnect to continue.`
74
+ });
75
+ return;
76
+ }
62
77
  let account;
63
78
  for (const adapter of options.adapters) {
64
79
  account = adapter.getAccount(payload.address);
@@ -1 +1 @@
1
- {"version":3,"file":"request-handler.mjs","names":[],"sources":["../../src/client/request-handler.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '@mysten/sui/client';\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\nimport { createJwtSession, WalletPostMessageChannel } from '@mysten/window-wallet-core';\n\nimport type { SignerAdapter } from '../types.js';\nimport { getNetworkFromChain } from '../wallet/constants.js';\nimport { executeSigning } from '../wallet/signing.js';\n\n/**\n * A parsed wallet request with methods to approve or reject it.\n *\n * This is different from `PendingSigningRequest` (in dev-wallet.ts) — this interface\n * includes `approve()`/`reject()` methods and is specific to the standalone popup flow.\n */\nexport interface PendingWalletRequest {\n\ttype: 'connect' | 'sign-transaction' | 'sign-and-execute-transaction' | 'sign-personal-message';\n\tappName: string;\n\tappUrl: string;\n\taddress?: string;\n\tchain?: string;\n\tdata?: string | Uint8Array;\n\t/**\n\t * Approve the request.\n\t * For connect: creates a session with the selected accounts (or all if none specified).\n\t * For signing: signs with the adapter.\n\t */\n\tapprove(options?: { selectedAddresses?: string[] }): Promise<void>;\n\t/** Reject the request with an optional reason. */\n\treject(reason?: string): void;\n}\n\nexport interface HandleRequestOptions {\n\t/** The signer adapters providing accounts and signing capability. */\n\tadapters: SignerAdapter[];\n\t/** JWT secret key for session creation. */\n\tjwtSecretKey: CryptoKey | Uint8Array;\n\t/** Resolve a client for a given network name (needed for signAndExecute). */\n\tgetClient?: (network: string) => ClientWithCoreApi | undefined;\n\t/** URL hash containing the encoded request. Defaults to window.location.hash. */\n\thash?: string;\n}\n\nexport function parseWalletRequest(options: HandleRequestOptions): PendingWalletRequest {\n\tif (!options.hash && typeof window === 'undefined') {\n\t\tthrow new Error(\n\t\t\t'parseWalletRequest requires either options.hash or a browser environment with window.location',\n\t\t);\n\t}\n\tconst hash = options.hash ?? window.location.hash.slice(1);\n\tconst channel = WalletPostMessageChannel.fromUrlHash(hash);\n\tconst requestData = channel.getRequestData();\n\tconst payload = requestData.payload;\n\n\tif (payload.type === 'connect') {\n\t\treturn {\n\t\t\ttype: 'connect',\n\t\t\tappName: requestData.appName,\n\t\t\tappUrl: requestData.appUrl,\n\t\t\tasync approve(approveOptions?: { selectedAddresses?: string[] }) {\n\t\t\t\tconst allAccounts = options.adapters.flatMap((adapter) =>\n\t\t\t\t\tadapter.getAccounts().map((a) => ({\n\t\t\t\t\t\taddress: a.address,\n\t\t\t\t\t\tpublicKey: toBase64(a.signer.getPublicKey().toSuiBytes()),\n\t\t\t\t\t\tlabel: a.label,\n\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tconst selected = approveOptions?.selectedAddresses;\n\t\t\t\tconst accounts = selected\n\t\t\t\t\t? allAccounts.filter((a) => selected.includes(a.address))\n\t\t\t\t\t: allAccounts;\n\n\t\t\t\tconst session = await createJwtSession(\n\t\t\t\t\t{ accounts },\n\t\t\t\t\t{\n\t\t\t\t\t\tsecretKey: options.jwtSecretKey,\n\t\t\t\t\t\texpirationTime: '7d',\n\t\t\t\t\t\tissuer: 'dev-wallet',\n\t\t\t\t\t\taudience: new URL(requestData.appUrl).origin,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'resolve',\n\t\t\t\t\tdata: { type: 'connect', session },\n\t\t\t\t});\n\t\t\t},\n\t\t\treject(reason?: string) {\n\t\t\t\tchannel.sendMessage({ type: 'reject', reason });\n\t\t\t},\n\t\t};\n\t}\n\n\tconst messageData =\n\t\tpayload.type === 'sign-personal-message' ? fromBase64(payload.message) : payload.transaction;\n\n\treturn {\n\t\ttype: payload.type,\n\t\tappName: requestData.appName,\n\t\tappUrl: requestData.appUrl,\n\t\taddress: payload.address,\n\t\tchain: payload.chain,\n\t\tdata: messageData,\n\t\tasync approve() {\n\t\t\t// Verify JWT session before signing — ensures the dApp was previously\n\t\t\t// authorized for this account via a connect flow\n\t\t\ttry {\n\t\t\t\tawait channel.verifyJwtSession(options.jwtSecretKey);\n\t\t\t} catch (error) {\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'reject',\n\t\t\t\t\treason: `Session verification failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet account;\n\t\t\tfor (const adapter of options.adapters) {\n\t\t\t\taccount = adapter.getAccount(payload.address);\n\t\t\t\tif (account) break;\n\t\t\t}\n\t\t\tif (!account) {\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'reject',\n\t\t\t\t\treason: `Account ${payload.address} not found`,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst network = payload.chain ? getNetworkFromChain(payload.chain) : undefined;\n\t\t\t\tconst client = network ? options.getClient?.(network) : undefined;\n\t\t\t\tconst result = await executeSigning({\n\t\t\t\t\ttype: payload.type,\n\t\t\t\t\tsigner: account.signer,\n\t\t\t\t\tdata: messageData,\n\t\t\t\t\tclient,\n\t\t\t\t});\n\t\t\t\t// effects must be a string in the PostMessage protocol\n\t\t\t\tconst data =\n\t\t\t\t\tresult.type === 'sign-and-execute-transaction'\n\t\t\t\t\t\t? { ...result, effects: result.effects ?? '' }\n\t\t\t\t\t\t: result;\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'resolve',\n\t\t\t\t\tdata,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'reject',\n\t\t\t\t\treason: error instanceof Error ? error.message : String(error),\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\treject(reason?: string) {\n\t\t\tchannel.sendMessage({ type: 'reject', reason });\n\t\t},\n\t};\n}\n"],"mappings":";;;;;AA6CA,SAAgB,mBAAmB,SAAqD;CACvF,IAAI,CAAC,QAAQ,QAAQ,OAAO,WAAW,aACtC,MAAM,IAAI,MACT,+FACD;CAED,MAAM,OAAO,QAAQ,QAAQ,OAAO,SAAS,KAAK,MAAM,CAAC;CACzD,MAAM,UAAU,yBAAyB,YAAY,IAAI;CACzD,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,UAAU,YAAY;CAE5B,IAAI,QAAQ,SAAS,WACpB,OAAO;EACN,MAAM;EACN,SAAS,YAAY;EACrB,QAAQ,YAAY;EACpB,MAAM,QAAQ,gBAAmD;GAChE,MAAM,cAAc,QAAQ,SAAS,SAAS,YAC7C,QAAQ,YAAY,CAAC,CAAC,KAAK,OAAO;IACjC,SAAS,EAAE;IACX,WAAW,SAAS,EAAE,OAAO,aAAa,CAAC,CAAC,WAAW,CAAC;IACxD,OAAO,EAAE;GACV,EAAE,CACH;GACA,MAAM,WAAW,gBAAgB;GAKjC,MAAM,UAAU,MAAM,iBACrB,EAAE,UALc,WACd,YAAY,QAAQ,MAAM,SAAS,SAAS,EAAE,OAAO,CAAC,IACtD,YAGS,GACX;IACC,WAAW,QAAQ;IACnB,gBAAgB;IAChB,QAAQ;IACR,UAAU,IAAI,IAAI,YAAY,MAAM,CAAC,CAAC;GACvC,CACD;GAEA,QAAQ,YAAY;IACnB,MAAM;IACN,MAAM;KAAE,MAAM;KAAW;IAAQ;GAClC,CAAC;EACF;EACA,OAAO,QAAiB;GACvB,QAAQ,YAAY;IAAE,MAAM;IAAU;GAAO,CAAC;EAC/C;CACD;CAGD,MAAM,cACL,QAAQ,SAAS,0BAA0B,WAAW,QAAQ,OAAO,IAAI,QAAQ;CAElF,OAAO;EACN,MAAM,QAAQ;EACd,SAAS,YAAY;EACrB,QAAQ,YAAY;EACpB,SAAS,QAAQ;EACjB,OAAO,QAAQ;EACf,MAAM;EACN,MAAM,UAAU;GAGf,IAAI;IACH,MAAM,QAAQ,iBAAiB,QAAQ,YAAY;GACpD,SAAS,OAAO;IACf,QAAQ,YAAY;KACnB,MAAM;KACN,QAAQ,gCAAgC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;IAC9F,CAAC;IACD;GACD;GAEA,IAAI;GACJ,KAAK,MAAM,WAAW,QAAQ,UAAU;IACvC,UAAU,QAAQ,WAAW,QAAQ,OAAO;IAC5C,IAAI,SAAS;GACd;GACA,IAAI,CAAC,SAAS;IACb,QAAQ,YAAY;KACnB,MAAM;KACN,QAAQ,WAAW,QAAQ,QAAQ;IACpC,CAAC;IACD;GACD;GAEA,IAAI;IACH,MAAM,UAAU,QAAQ,QAAQ,oBAAoB,QAAQ,KAAK,IAAI;IACrE,MAAM,SAAS,UAAU,QAAQ,YAAY,OAAO,IAAI;IACxD,MAAM,SAAS,MAAM,eAAe;KACnC,MAAM,QAAQ;KACd,QAAQ,QAAQ;KAChB,MAAM;KACN;IACD,CAAC;IAED,MAAM,OACL,OAAO,SAAS,iCACb;KAAE,GAAG;KAAQ,SAAS,OAAO,WAAW;IAAG,IAC3C;IACJ,QAAQ,YAAY;KACnB,MAAM;KACN;IACD,CAAC;GACF,SAAS,OAAO;IACf,QAAQ,YAAY;KACnB,MAAM;KACN,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;IAC9D,CAAC;GACF;EACD;EACA,OAAO,QAAiB;GACvB,QAAQ,YAAY;IAAE,MAAM;IAAU;GAAO,CAAC;EAC/C;CACD;AACD"}
1
+ {"version":3,"file":"request-handler.mjs","names":[],"sources":["../../src/client/request-handler.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi } from '@mysten/sui/client';\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\nimport { createJwtSession, WalletPostMessageChannel } from '@mysten/window-wallet-core';\n\nimport type { SignerAdapter } from '../types.js';\nimport type { ConnectedAppsStore } from './connected-apps.js';\nimport { getNetworkFromChain } from '../wallet/constants.js';\nimport { executeSigning } from '../wallet/signing.js';\n\n/**\n * A parsed wallet request with methods to approve or reject it.\n *\n * This is different from `PendingSigningRequest` (in dev-wallet.ts) — this interface\n * includes `approve()`/`reject()` methods and is specific to the standalone popup flow.\n */\nexport interface PendingWalletRequest {\n\ttype: 'connect' | 'sign-transaction' | 'sign-and-execute-transaction' | 'sign-personal-message';\n\tappName: string;\n\tappUrl: string;\n\taddress?: string;\n\tchain?: string;\n\tdata?: string | Uint8Array;\n\t/**\n\t * Approve the request.\n\t * For connect: creates a session with the selected accounts (or all if none specified).\n\t * For signing: signs with the adapter.\n\t */\n\tapprove(options?: { selectedAddresses?: string[] }): Promise<void>;\n\t/** Reject the request with an optional reason. */\n\treject(reason?: string): void;\n}\n\nexport interface HandleRequestOptions {\n\t/** The signer adapters providing accounts and signing capability. */\n\tadapters: SignerAdapter[];\n\t/** JWT secret key for session creation. */\n\tjwtSecretKey: CryptoKey | Uint8Array;\n\t/** Resolve a client for a given network name (needed for signAndExecute). */\n\tgetClient?: (network: string) => ClientWithCoreApi | undefined;\n\t/** URL hash containing the encoded request. Defaults to window.location.hash. */\n\thash?: string;\n\t/**\n\t * Tracks connected dApps. When set, approved connects are recorded here and\n\t * signing requests from an origin that isn't in the store are rejected, so\n\t * removing an app disconnects it.\n\t */\n\tconnectedApps?: ConnectedAppsStore;\n}\n\nexport function parseWalletRequest(options: HandleRequestOptions): PendingWalletRequest {\n\tif (!options.hash && typeof window === 'undefined') {\n\t\tthrow new Error(\n\t\t\t'parseWalletRequest requires either options.hash or a browser environment with window.location',\n\t\t);\n\t}\n\tconst hash = options.hash ?? window.location.hash.slice(1);\n\tconst channel = WalletPostMessageChannel.fromUrlHash(hash);\n\tconst requestData = channel.getRequestData();\n\tconst payload = requestData.payload;\n\tconst appOrigin = new URL(requestData.appUrl).origin;\n\n\tif (payload.type === 'connect') {\n\t\treturn {\n\t\t\ttype: 'connect',\n\t\t\tappName: requestData.appName,\n\t\t\tappUrl: requestData.appUrl,\n\t\t\tasync approve(approveOptions?: { selectedAddresses?: string[] }) {\n\t\t\t\tconst allAccounts = options.adapters.flatMap((adapter) =>\n\t\t\t\t\tadapter.getAccounts().map((a) => ({\n\t\t\t\t\t\taddress: a.address,\n\t\t\t\t\t\tpublicKey: toBase64(a.signer.getPublicKey().toSuiBytes()),\n\t\t\t\t\t\tlabel: a.label,\n\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tconst selected = approveOptions?.selectedAddresses;\n\t\t\t\tconst accounts = selected\n\t\t\t\t\t? allAccounts.filter((a) => selected.includes(a.address))\n\t\t\t\t\t: allAccounts;\n\n\t\t\t\tconst session = await createJwtSession(\n\t\t\t\t\t{ accounts },\n\t\t\t\t\t{\n\t\t\t\t\t\tsecretKey: options.jwtSecretKey,\n\t\t\t\t\t\texpirationTime: '7d',\n\t\t\t\t\t\tissuer: 'dev-wallet',\n\t\t\t\t\t\taudience: appOrigin,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\toptions.connectedApps?.record({\n\t\t\t\t\torigin: appOrigin,\n\t\t\t\t\tname: requestData.appName,\n\t\t\t\t\taccounts: accounts.map((a) => a.address),\n\t\t\t\t\tconnectedAt: Date.now(),\n\t\t\t\t});\n\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'resolve',\n\t\t\t\t\tdata: { type: 'connect', session },\n\t\t\t\t});\n\t\t\t},\n\t\t\treject(reason?: string) {\n\t\t\t\tchannel.sendMessage({ type: 'reject', reason });\n\t\t\t},\n\t\t};\n\t}\n\n\tconst messageData =\n\t\tpayload.type === 'sign-personal-message' ? fromBase64(payload.message) : payload.transaction;\n\n\treturn {\n\t\ttype: payload.type,\n\t\tappName: requestData.appName,\n\t\tappUrl: requestData.appUrl,\n\t\taddress: payload.address,\n\t\tchain: payload.chain,\n\t\tdata: messageData,\n\t\tasync approve() {\n\t\t\t// Verify JWT session before signing — ensures the dApp was previously\n\t\t\t// authorized for this account via a connect flow\n\t\t\ttry {\n\t\t\t\tawait channel.verifyJwtSession(options.jwtSecretKey);\n\t\t\t} catch (error) {\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'reject',\n\t\t\t\t\treason: `Session verification failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (options.connectedApps && !options.connectedApps.has(appOrigin)) {\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'reject',\n\t\t\t\t\treason: `${appOrigin} was disconnected from the wallet. Reconnect to continue.`,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet account;\n\t\t\tfor (const adapter of options.adapters) {\n\t\t\t\taccount = adapter.getAccount(payload.address);\n\t\t\t\tif (account) break;\n\t\t\t}\n\t\t\tif (!account) {\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'reject',\n\t\t\t\t\treason: `Account ${payload.address} not found`,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst network = payload.chain ? getNetworkFromChain(payload.chain) : undefined;\n\t\t\t\tconst client = network ? options.getClient?.(network) : undefined;\n\t\t\t\tconst result = await executeSigning({\n\t\t\t\t\ttype: payload.type,\n\t\t\t\t\tsigner: account.signer,\n\t\t\t\t\tdata: messageData,\n\t\t\t\t\tclient,\n\t\t\t\t});\n\t\t\t\t// effects must be a string in the PostMessage protocol\n\t\t\t\tconst data =\n\t\t\t\t\tresult.type === 'sign-and-execute-transaction'\n\t\t\t\t\t\t? { ...result, effects: result.effects ?? '' }\n\t\t\t\t\t\t: result;\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'resolve',\n\t\t\t\t\tdata,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tchannel.sendMessage({\n\t\t\t\t\ttype: 'reject',\n\t\t\t\t\treason: error instanceof Error ? error.message : String(error),\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\treject(reason?: string) {\n\t\t\tchannel.sendMessage({ type: 'reject', reason });\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- import{G as e,J as t,K as n,R as r,Y as i,Z as a,dt as o,f as s,i as c,n as l,o as u,q as d,s as f,t as p,ut as m}from"./base-adapter-C5w5q7XZ.js";import{n as h,r as g}from"./main-xfzarPod.js";function _(t,r,i,o){e(t);let{c,dkLen:l,asyncTick:u}=d({dkLen:32,asyncTick:10},o);if(n(c,`c`),n(l,`dkLen`),n(u,`asyncTick`),c<1)throw Error(`iterations (c) must be >= 1`);if(l<1)throw Error(`"dkLen" must be >= 1`);if(l>(2**32-1)*t.outputLen)throw Error(`derived key too long`);let f=a(r,`password`),p=a(i,`salt`),m=new Uint8Array(l),h=s.create(t,f);return{c,dkLen:l,asyncTick:u,DK:m,PRF:h,PRFSalt:h._cloneInto().update(p)}}function v(e,n,r,i,a){return e.destroy(),n.destroy(),i&&i.destroy(),t(a),r}function y(e,t,n,r){let{c:a,dkLen:o,DK:s,PRF:c,PRFSalt:l}=_(e,t,n,r),u,d=new Uint8Array(4),f=i(d),p=new Uint8Array(c.outputLen);for(let e=1,t=0;t<o;e++,t+=c.outputLen){let n=s.subarray(t,t+c.outputLen);f.setInt32(0,e,!1),(u=l._cloneInto(u)).update(d).digestInto(p),n.set(p.subarray(0,n.length));for(let e=1;e<a;e++){c._cloneInto(u).update(p).digestInto(p);for(let e=0;e<n.length;e++)n[e]^=p[e]}}return v(c,l,s,u,p)}function b(e){if(typeof e!=`string`)throw TypeError(`invalid mnemonic type: `+typeof e);return e.normalize(`NFKD`)}function x(e){let t=b(e),n=t.split(` `);if(![12,15,18,21,24].includes(n.length))throw Error(`Invalid mnemonic`);return{nfkd:t,words:n}}var S=e=>b(`mnemonic`+e);function C(e,t=``){return y(r,x(e).nfkd,S(t),{c:2048,dkLen:64})}function w(e){return!!RegExp(`^m\\/44'\\/784'\\/[0-9]+'\\/[0-9]+'\\/[0-9]+'+$`).test(e)}function T(e){return C(e,``)}function E(e){return o(T(e))}var D=`ed25519 seed`,O=2147483648,k=RegExp(`^m(\\/[0-9]+')+$`),A=e=>e.replace(`'`,``),j=e=>{let t=s.create(r,new TextEncoder().encode(D)).update(m(e)).digest();return{key:t.slice(0,32),chainCode:t.slice(32)}},M=({key:e,chainCode:t},n)=>{let i=new ArrayBuffer(4);new DataView(i).setUint32(0,n);let a=new Uint8Array(1+e.length+i.byteLength);a.set(new Uint8Array(1).fill(0)),a.set(e,1),a.set(new Uint8Array(i,0,i.byteLength),e.length+1);let o=s.create(r,t).update(a).digest();return{key:o.slice(0,32),chainCode:o.slice(32)}},N=e=>k.test(e)?!e.split(`/`).slice(1).map(A).some(isNaN):!1,P=(e,t,n=O)=>{if(!N(e))throw Error(`Invalid derivation path`);let{key:r,chainCode:i}=j(t);return e.split(`/`).slice(1).map(A).map(e=>parseInt(e,10)).reduce((e,t)=>M(e,t+n),{key:r,chainCode:i})},F=`m/44'/784'/0'/0'/0'`,I=class e extends c{constructor(e){if(super(),e)this.keypair={publicKey:e.publicKey,secretKey:e.secretKey.slice(0,32)};else{let e=g.utils.randomSecretKey();this.keypair={publicKey:g.getPublicKey(e),secretKey:e}}}getKeyScheme(){return`ED25519`}static generate(){let t=g.utils.randomSecretKey();return new e({publicKey:g.getPublicKey(t),secretKey:t})}static fromSecretKey(t,n){if(typeof t==`string`){let e=u(t);if(e.scheme!==`ED25519`)throw Error(`Expected a ED25519 keypair, got ${e.scheme}`);return this.fromSecretKey(e.secretKey,n)}let r=t.length;if(r!==32)throw Error(`Wrong secretKey size. Expected 32 bytes, got ${r}.`);let i={publicKey:g.getPublicKey(t),secretKey:t};if(!n||!n.skipValidation){let e=new TextEncoder().encode(`sui validation`),n=g.sign(e,t);if(!g.verify(n,e,i.publicKey))throw Error(`provided secretKey is invalid`)}return new e(i)}getPublicKey(){return new h(this.keypair.publicKey)}getSecretKey(){return f(this.keypair.secretKey.slice(0,32),this.getKeyScheme())}async sign(e){return g.sign(e,this.keypair.secretKey)}static deriveKeypair(t,n){if(n??=F,!w(n))throw Error(`Invalid derivation path`);let{key:r}=P(n,E(t));return e.fromSecretKey(r)}static deriveKeypairFromSeed(t,n){if(n??=F,!w(n))throw Error(`Invalid derivation path`);let r=typeof t==`string`?t:o(t),{key:i}=P(n,r);return e.fromSecretKey(i)}},L=class extends p{constructor(...e){super(...e),this.id=`in-memory`,this.name=`In-Memory Signer`}async initialize(){}async createAccount(e){let t=new I,n=l(t,t.getPublicKey().toSuiAddress(),e?.label??this.getDefaultLabel());return this.addAccount(n),n}async importAccount(e){let t=e.signer;if(!t)throw Error(`In-memory adapter requires a signer to import`);let n=t.toSuiAddress(),r=this.getAccount(n);if(r)return r;let i=l(t,n,e.label??this.getDefaultLabel());return this.addAccount(i),i}async renameAccount(e,t){return this._performRename(e,t)}async removeAccount(e){return this.removeAccountByAddress(e)}};export{L as InMemorySignerAdapter};
1
+ import{G as e,J as t,K as n,R as r,Y as i,Z as a,dt as o,f as s,i as c,n as l,o as u,q as d,s as f,t as p,ut as m}from"./base-adapter-C5w5q7XZ.js";import{n as h,r as g}from"./main-CKYv0eR6.js";function _(t,r,i,o){e(t);let{c,dkLen:l,asyncTick:u}=d({dkLen:32,asyncTick:10},o);if(n(c,`c`),n(l,`dkLen`),n(u,`asyncTick`),c<1)throw Error(`iterations (c) must be >= 1`);if(l<1)throw Error(`"dkLen" must be >= 1`);if(l>(2**32-1)*t.outputLen)throw Error(`derived key too long`);let f=a(r,`password`),p=a(i,`salt`),m=new Uint8Array(l),h=s.create(t,f);return{c,dkLen:l,asyncTick:u,DK:m,PRF:h,PRFSalt:h._cloneInto().update(p)}}function v(e,n,r,i,a){return e.destroy(),n.destroy(),i&&i.destroy(),t(a),r}function y(e,t,n,r){let{c:a,dkLen:o,DK:s,PRF:c,PRFSalt:l}=_(e,t,n,r),u,d=new Uint8Array(4),f=i(d),p=new Uint8Array(c.outputLen);for(let e=1,t=0;t<o;e++,t+=c.outputLen){let n=s.subarray(t,t+c.outputLen);f.setInt32(0,e,!1),(u=l._cloneInto(u)).update(d).digestInto(p),n.set(p.subarray(0,n.length));for(let e=1;e<a;e++){c._cloneInto(u).update(p).digestInto(p);for(let e=0;e<n.length;e++)n[e]^=p[e]}}return v(c,l,s,u,p)}function b(e){if(typeof e!=`string`)throw TypeError(`invalid mnemonic type: `+typeof e);return e.normalize(`NFKD`)}function x(e){let t=b(e),n=t.split(` `);if(![12,15,18,21,24].includes(n.length))throw Error(`Invalid mnemonic`);return{nfkd:t,words:n}}var S=e=>b(`mnemonic`+e);function C(e,t=``){return y(r,x(e).nfkd,S(t),{c:2048,dkLen:64})}function w(e){return!!RegExp(`^m\\/44'\\/784'\\/[0-9]+'\\/[0-9]+'\\/[0-9]+'+$`).test(e)}function T(e){return C(e,``)}function E(e){return o(T(e))}var D=`ed25519 seed`,O=2147483648,k=RegExp(`^m(\\/[0-9]+')+$`),A=e=>e.replace(`'`,``),j=e=>{let t=s.create(r,new TextEncoder().encode(D)).update(m(e)).digest();return{key:t.slice(0,32),chainCode:t.slice(32)}},M=({key:e,chainCode:t},n)=>{let i=new ArrayBuffer(4);new DataView(i).setUint32(0,n);let a=new Uint8Array(1+e.length+i.byteLength);a.set(new Uint8Array(1).fill(0)),a.set(e,1),a.set(new Uint8Array(i,0,i.byteLength),e.length+1);let o=s.create(r,t).update(a).digest();return{key:o.slice(0,32),chainCode:o.slice(32)}},N=e=>k.test(e)?!e.split(`/`).slice(1).map(A).some(isNaN):!1,P=(e,t,n=O)=>{if(!N(e))throw Error(`Invalid derivation path`);let{key:r,chainCode:i}=j(t);return e.split(`/`).slice(1).map(A).map(e=>parseInt(e,10)).reduce((e,t)=>M(e,t+n),{key:r,chainCode:i})},F=`m/44'/784'/0'/0'/0'`,I=class e extends c{constructor(e){if(super(),e)this.keypair={publicKey:e.publicKey,secretKey:e.secretKey.slice(0,32)};else{let e=g.utils.randomSecretKey();this.keypair={publicKey:g.getPublicKey(e),secretKey:e}}}getKeyScheme(){return`ED25519`}static generate(){let t=g.utils.randomSecretKey();return new e({publicKey:g.getPublicKey(t),secretKey:t})}static fromSecretKey(t,n){if(typeof t==`string`){let e=u(t);if(e.scheme!==`ED25519`)throw Error(`Expected a ED25519 keypair, got ${e.scheme}`);return this.fromSecretKey(e.secretKey,n)}let r=t.length;if(r!==32)throw Error(`Wrong secretKey size. Expected 32 bytes, got ${r}.`);let i={publicKey:g.getPublicKey(t),secretKey:t};if(!n||!n.skipValidation){let e=new TextEncoder().encode(`sui validation`),n=g.sign(e,t);if(!g.verify(n,e,i.publicKey))throw Error(`provided secretKey is invalid`)}return new e(i)}getPublicKey(){return new h(this.keypair.publicKey)}getSecretKey(){return f(this.keypair.secretKey.slice(0,32),this.getKeyScheme())}async sign(e){return g.sign(e,this.keypair.secretKey)}static deriveKeypair(t,n){if(n??=F,!w(n))throw Error(`Invalid derivation path`);let{key:r}=P(n,E(t));return e.fromSecretKey(r)}static deriveKeypairFromSeed(t,n){if(n??=F,!w(n))throw Error(`Invalid derivation path`);let r=typeof t==`string`?t:o(t),{key:i}=P(n,r);return e.fromSecretKey(i)}},L=class extends p{constructor(...e){super(...e),this.id=`in-memory`,this.name=`In-Memory Signer`}async initialize(){}async createAccount(e){let t=new I,n=l(t,t.getPublicKey().toSuiAddress(),e?.label??this.getDefaultLabel());return this.addAccount(n),n}async importAccount(e){let t=e.signer;if(!t)throw Error(`In-memory adapter requires a signer to import`);let n=t.toSuiAddress(),r=this.getAccount(n);if(r)return r;let i=l(t,n,e.label??this.getDefaultLabel());return this.addAccount(i),i}async renameAccount(e,t){return this._performRename(e,t)}async removeAccount(e){return this.removeAccountByAddress(e)}};export{L as InMemorySignerAdapter};