@mysten-incubation/dev-wallet 0.2.0 → 0.4.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 (150) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/dist/_virtual/{_@oxc-project_runtime@0.127.0/helpers → _@oxc-project_runtime@0.135.0/helpers/esm}/decorate.mjs +1 -1
  3. package/dist/adapters/base-adapter.d.mts.map +1 -1
  4. package/dist/adapters/base-adapter.mjs.map +1 -1
  5. package/dist/adapters/build-managed-account.mjs.map +1 -1
  6. package/dist/adapters/devstack-adapter.d.mts.map +1 -1
  7. package/dist/adapters/devstack-adapter.mjs.map +1 -1
  8. package/dist/adapters/devstack-paths.d.mts +0 -1
  9. package/dist/adapters/devstack-paths.d.mts.map +1 -1
  10. package/dist/adapters/devstack-paths.mjs +1 -2
  11. package/dist/adapters/devstack-paths.mjs.map +1 -1
  12. package/dist/adapters/fork-relay.d.mts.map +1 -1
  13. package/dist/adapters/fork-relay.mjs.map +1 -1
  14. package/dist/adapters/idb-store.mjs.map +1 -1
  15. package/dist/adapters/in-memory-adapter.d.mts.map +1 -1
  16. package/dist/adapters/in-memory-adapter.mjs.map +1 -1
  17. package/dist/adapters/passkey-adapter.d.mts.map +1 -1
  18. package/dist/adapters/passkey-adapter.mjs.map +1 -1
  19. package/dist/adapters/remote-cli-adapter.d.mts.map +1 -1
  20. package/dist/adapters/remote-cli-adapter.mjs.map +1 -1
  21. package/dist/adapters/webcrypto-adapter.d.mts.map +1 -1
  22. package/dist/adapters/webcrypto-adapter.mjs.map +1 -1
  23. package/dist/bin/cli.mjs.map +1 -1
  24. package/dist/client/dev-wallet-client.d.mts.map +1 -1
  25. package/dist/client/dev-wallet-client.mjs.map +1 -1
  26. package/dist/client/request-handler.d.mts.map +1 -1
  27. package/dist/client/request-handler.mjs.map +1 -1
  28. package/dist/index.d.mts +2 -1
  29. package/dist/index.mjs +2 -1
  30. package/dist/inject/index.d.mts +61 -0
  31. package/dist/inject/index.d.mts.map +1 -0
  32. package/dist/inject/index.mjs +61 -0
  33. package/dist/inject/index.mjs.map +1 -0
  34. package/dist/react/components.d.mts +6 -8
  35. package/dist/react/components.d.mts.map +1 -1
  36. package/dist/react/components.mjs.map +1 -1
  37. package/dist/react/context.d.mts +2 -3
  38. package/dist/react/context.d.mts.map +1 -1
  39. package/dist/react/context.mjs.map +1 -1
  40. package/dist/react/useDevWallet.d.mts +3 -11
  41. package/dist/react/useDevWallet.d.mts.map +1 -1
  42. package/dist/react/useDevWallet.mjs +14 -36
  43. package/dist/react/useDevWallet.mjs.map +1 -1
  44. package/dist/server/cli-signing-middleware.d.mts.map +1 -1
  45. package/dist/server/cli-signing-middleware.mjs.map +1 -1
  46. package/dist/standalone/assets/base-adapter-DET6CP7z.js +1 -0
  47. package/dist/standalone/assets/in-memory-adapter-CX7xym4e.js +1 -0
  48. package/dist/standalone/assets/main-CuOnBmaa.js +7 -0
  49. package/dist/standalone/assets/webcrypto-adapter-CUQmbHDy.js +1 -0
  50. package/dist/standalone/bookmarklet.js +5 -5
  51. package/dist/standalone/index.html +2 -1
  52. package/dist/types.d.mts.map +1 -1
  53. package/dist/ui/copy-controller.mjs.map +1 -1
  54. package/dist/ui/dev-wallet-account-selector.d.mts +2 -3
  55. package/dist/ui/dev-wallet-account-selector.d.mts.map +1 -1
  56. package/dist/ui/dev-wallet-account-selector.mjs +1 -1
  57. package/dist/ui/dev-wallet-account-selector.mjs.map +1 -1
  58. package/dist/ui/dev-wallet-accounts.d.mts +2 -3
  59. package/dist/ui/dev-wallet-accounts.d.mts.map +1 -1
  60. package/dist/ui/dev-wallet-accounts.mjs +1 -1
  61. package/dist/ui/dev-wallet-accounts.mjs.map +1 -1
  62. package/dist/ui/dev-wallet-balances.d.mts +2 -3
  63. package/dist/ui/dev-wallet-balances.d.mts.map +1 -1
  64. package/dist/ui/dev-wallet-balances.mjs +1 -1
  65. package/dist/ui/dev-wallet-balances.mjs.map +1 -1
  66. package/dist/ui/dev-wallet-connect.d.mts +2 -3
  67. package/dist/ui/dev-wallet-connect.d.mts.map +1 -1
  68. package/dist/ui/dev-wallet-connect.mjs +1 -1
  69. package/dist/ui/dev-wallet-connect.mjs.map +1 -1
  70. package/dist/ui/dev-wallet-dropdown.d.mts +2 -3
  71. package/dist/ui/dev-wallet-dropdown.d.mts.map +1 -1
  72. package/dist/ui/dev-wallet-dropdown.mjs +1 -1
  73. package/dist/ui/dev-wallet-dropdown.mjs.map +1 -1
  74. package/dist/ui/dev-wallet-fork-panel.d.mts +2 -3
  75. package/dist/ui/dev-wallet-fork-panel.d.mts.map +1 -1
  76. package/dist/ui/dev-wallet-fork-panel.mjs +1 -1
  77. package/dist/ui/dev-wallet-fork-panel.mjs.map +1 -1
  78. package/dist/ui/dev-wallet-network-badge.d.mts +2 -3
  79. package/dist/ui/dev-wallet-network-badge.d.mts.map +1 -1
  80. package/dist/ui/dev-wallet-network-badge.mjs +1 -1
  81. package/dist/ui/dev-wallet-network-badge.mjs.map +1 -1
  82. package/dist/ui/dev-wallet-new-account.d.mts +2 -3
  83. package/dist/ui/dev-wallet-new-account.d.mts.map +1 -1
  84. package/dist/ui/dev-wallet-new-account.mjs +1 -1
  85. package/dist/ui/dev-wallet-new-account.mjs.map +1 -1
  86. package/dist/ui/dev-wallet-objects.d.mts +2 -3
  87. package/dist/ui/dev-wallet-objects.d.mts.map +1 -1
  88. package/dist/ui/dev-wallet-objects.mjs +1 -1
  89. package/dist/ui/dev-wallet-objects.mjs.map +1 -1
  90. package/dist/ui/dev-wallet-panel.d.mts +2 -3
  91. package/dist/ui/dev-wallet-panel.d.mts.map +1 -1
  92. package/dist/ui/dev-wallet-panel.mjs +1 -1
  93. package/dist/ui/dev-wallet-panel.mjs.map +1 -1
  94. package/dist/ui/dev-wallet-popup.d.mts +2 -3
  95. package/dist/ui/dev-wallet-popup.d.mts.map +1 -1
  96. package/dist/ui/dev-wallet-popup.mjs +1 -1
  97. package/dist/ui/dev-wallet-popup.mjs.map +1 -1
  98. package/dist/ui/dev-wallet-settings.d.mts +2 -3
  99. package/dist/ui/dev-wallet-settings.d.mts.map +1 -1
  100. package/dist/ui/dev-wallet-settings.mjs +1 -1
  101. package/dist/ui/dev-wallet-settings.mjs.map +1 -1
  102. package/dist/ui/dev-wallet-signing-modal.d.mts +2 -3
  103. package/dist/ui/dev-wallet-signing-modal.d.mts.map +1 -1
  104. package/dist/ui/dev-wallet-signing-modal.mjs +1 -1
  105. package/dist/ui/dev-wallet-signing-modal.mjs.map +1 -1
  106. package/dist/ui/dev-wallet-signing.d.mts +2 -3
  107. package/dist/ui/dev-wallet-signing.d.mts.map +1 -1
  108. package/dist/ui/dev-wallet-signing.mjs +2 -1
  109. package/dist/ui/dev-wallet-signing.mjs.map +1 -1
  110. package/dist/ui/dev-wallet-standalone.d.mts +2 -3
  111. package/dist/ui/dev-wallet-standalone.d.mts.map +1 -1
  112. package/dist/ui/dev-wallet-standalone.mjs +1 -1
  113. package/dist/ui/dev-wallet-standalone.mjs.map +1 -1
  114. package/dist/ui/dev-wallet-tab-bar.d.mts +1 -2
  115. package/dist/ui/dev-wallet-tab-bar.d.mts.map +1 -1
  116. package/dist/ui/dev-wallet-tab-bar.mjs +1 -1
  117. package/dist/ui/dev-wallet-tab-bar.mjs.map +1 -1
  118. package/dist/ui/mount.mjs.map +1 -1
  119. package/dist/ui/styles.mjs.map +1 -1
  120. package/dist/ui/transaction-analyzer.mjs.map +1 -1
  121. package/dist/ui/utils.d.mts.map +1 -1
  122. package/dist/ui/utils.mjs.map +1 -1
  123. package/dist/ui/wallet-controller.mjs.map +1 -1
  124. package/dist/wallet/constants.d.mts.map +1 -1
  125. package/dist/wallet/constants.mjs.map +1 -1
  126. package/dist/wallet/dev-wallet.d.mts +19 -0
  127. package/dist/wallet/dev-wallet.d.mts.map +1 -1
  128. package/dist/wallet/dev-wallet.mjs +58 -2
  129. package/dist/wallet/dev-wallet.mjs.map +1 -1
  130. package/dist/wallet/initializer.d.mts.map +1 -1
  131. package/dist/wallet/initializer.mjs +10 -26
  132. package/dist/wallet/initializer.mjs.map +1 -1
  133. package/dist/wallet/mount-and-register.d.mts +44 -0
  134. package/dist/wallet/mount-and-register.d.mts.map +1 -0
  135. package/dist/wallet/mount-and-register.mjs +46 -0
  136. package/dist/wallet/mount-and-register.mjs.map +1 -0
  137. package/dist/wallet/signing.d.mts.map +1 -1
  138. package/dist/wallet/signing.mjs.map +1 -1
  139. package/package.json +26 -22
  140. package/src/adapters/devstack-paths.ts +0 -1
  141. package/src/index.ts +5 -0
  142. package/src/inject/index.ts +183 -0
  143. package/src/react/useDevWallet.ts +26 -71
  144. package/src/ui/dev-wallet-signing.ts +2 -0
  145. package/src/wallet/dev-wallet.ts +75 -2
  146. package/src/wallet/initializer.ts +16 -42
  147. package/src/wallet/mount-and-register.ts +93 -0
  148. package/dist/standalone/assets/in-memory-adapter-qRkNfj9O.js +0 -1
  149. package/dist/standalone/assets/main-DDltQnzR.js +0 -3954
  150. package/dist/standalone/assets/webcrypto-adapter-FejcrL9x.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,172 @@
1
1
  # @mysten-incubation/dev-wallet
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9e1e1be: Dev wallet: explicit test-only connect, no pre-connect or storage seeding.
8
+
9
+ The injected dev wallet no longer seeds dApp Kit's localStorage to fake an auto-connect to a
10
+ specific account on page load. A fresh page now loads disconnected, and dApp Kit's own
11
+ `autoConnect` does only what it's meant to — re-connect a genuine prior session.
12
+
13
+ A new devstack `/dapp-kit` entrypoint exports `registerDAppKitForTesting(dAppKit)`, which the app
14
+ wires DEV-only after `createDAppKit(...)`. It publishes the `connectAs` slot that drives a REAL
15
+ connection through dApp Kit's public API (`connectWallet` / `switchAccount`, resolving accounts by
16
+ label) instead of narrowing/widening the wallet's exposed accounts to exploit reconciliation. The
17
+ dev wallet auto-approves `standard:connect` only when signing is auto-approved (the headless-e2e
18
+ `DEVSTACK_AUTO_APPROVE` signal); in normal dev a human approves the connect. This fixes wallet
19
+ connection under `@mysten/dapp-kit-core` ≥1.6, whose rewritten auto-connect state machine broke
20
+ the old storage-seeding approach.
21
+
22
+ - 11c258a: Auto-inject the devstack dev wallet via the Vite plugin.
23
+
24
+ `@mysten-incubation/dev-wallet` adds a `/inject` entry (`registerDevstackDevWallet`) that
25
+ constructs the dev wallet from a devstack stack's config and registers it on the page via the
26
+ wallet-standard window protocol (plus the Playwright `connectAs` slot). The devstack Vite plugin
27
+ uses it to inject + register the dev wallet in DEV only, so dapp-kit apps discover it through
28
+ wallet-standard with no app-side wiring — apps no longer need a `dapp-kit.dev.ts` or any
29
+ `@devstack-dev` import, and production builds carry no dev-wallet code. The dev wallet exposes all
30
+ of its accounts to the dApp while `connectAs` still drives the active account.
31
+
32
+ - 9e1e1be: The injected devstack dev wallet now bundles a `WebCryptoSignerAdapter` alongside the
33
+ stack's server-resolved accounts, so users can create their own accounts from the wallet UI.
34
+ Created accounts persist across reloads in IndexedDB via non-extractable WebCrypto keys (not
35
+ in-memory), and the stack's `alice`/`bob`/`carol` accounts remain available.
36
+ - 9e1e1be: Disambiguate the conflated `chain` concept into three precise ones: `network` (the
37
+ network name — `localnet`/`testnet`/…), `chainId` (the genesis-digest chain identifier, unique per
38
+ spun-up network), and the wallet-standard `sui:<network>` chain name (derived only at the
39
+ dev-wallet wallet-standard boundary — `sui:` never appears in devstack internals).
40
+
41
+ **Breaking.** The substrate `Identity`/manifest field `chain` is now `network` and holds the bare
42
+ network name (previously a `sui:`-prefixed string). The network parser accepts only canonical
43
+ names — the `local` shorthand and the `sui:`-prefixed alias table are removed (use `localnet`);
44
+ `network ⇄ chain id` is now just a `sui:` prefix, not a lookup table. The sui plugin's resolved
45
+ value, on-disk cache-dir keys, and `chain-probe:`/`faucet:request:` capability keys now key on the
46
+ genesis-digest `chainId`. The generated `config.ts` active-network key is `localnet` (was
47
+ `local`), and `config.networks.<net>` / `byNetwork.<net>` are keyed by network name. The
48
+ dev-wallet `registerDevstackDevWallet` config and `DevWalletConfig` take `network` instead of
49
+ `chain`. The dashboard GraphQL surfaces `chainId` (sui) and `network` (deepbook) instead of
50
+ `chain`. Known walrus/deepbook deployments and the deepbook DEEP-funding gate now key on the
51
+ network name — fixing a latent bug where the gate compared a genesis digest against the
52
+ `'sui:testnet'` literal and was dead for every non-literal value.
53
+
54
+ On-disk state keyed by the old `sui:local` chain brand is invalidated; run `devstack wipe` on
55
+ existing local stacks after upgrading.
56
+
57
+ ## 0.3.0
58
+
59
+ ### Minor Changes
60
+
61
+ - b6af6d2: Devstack: thorough-review remediation pass plus follow-up cleanup round.
62
+
63
+ Highlights:
64
+ - `runStack({ layers })` replaced by `runStack({ extendContext })`. Custom context extension now
65
+ goes through a typed seam.
66
+ - `executeSuiTx` returns a discriminated union (`$kind: 'ExecutedSuccess' | 'ExecutedFailure'`).
67
+ On-chain failure is a value, not an error. Plugins that previously caught the failure-tag in the
68
+ error channel must dispatch on `$kind` instead.
69
+ - New substrate helper `signAndDispatch` compacts the
70
+ `withTransactionSigner → build → sign → execute → $kind dispatch` pattern across five publisher
71
+ plugins.
72
+ - Supervisor module (1.8k LOC) split into 11 per-concern modules under
73
+ `substrate/runtime/supervisor/`. No behavior change.
74
+ - New `built-in-plugin-layers.ts` lives in `orchestrators/`, not `runtime/` — `run.ts` lifted into
75
+ `orchestrators/` similarly. Layer composition now lives at L3 only.
76
+ - New L0 helper `routed-url.ts` for `renderUrl`/`routedHostname`; L3 router/hostname.ts retained
77
+ as an intra-L3 adapter.
78
+ - Docker image builds now stamp ownership labels (`expectedImageOwnershipLabels`); prune can reach
79
+ previously-unlabelled images. New `BuildOptions.labels` on the container-runtime contract.
80
+ - Sweep evicts own endpoints and surfaces remaining `ForeignNetworkHolder` rather than failing
81
+ silently.
82
+ - Per-app shared-stack pinning: `_per-app_` stacks (e.g. shared chain-build cache) are pinned
83
+ while any app sibling is live.
84
+ - `atomicWriteFile` cleanup is now whole-pipeline (open/write/fsync/rename) via `Effect.onError`,
85
+ not rename-only.
86
+ - `cross-process-lock` typed errors: `StackLockTimeoutError | StackLockIoError` in the E channel;
87
+ no more `Effect.orDie`.
88
+ - Plugin-domain span/log keys namespaced via per-plugin `spans.ts` files.
89
+ - `ChainOperation` typed seam removed (zero plugin adoption signal); `ClientWithCoreApi` is the
90
+ sanctioned SDK cast at plugin boundaries.
91
+ - ARCHITECTURE.md / STYLE_GUIDE.md rewritten to describe current state (537→308, 894→477 lines).
92
+ - New style-enforcement tests: `l4-boundary`, `no-unknown-as` (globs every plugin barrel),
93
+ `plugin-boundary`, `span-attr-namespace`, `substrate/name-blindness`.
94
+
95
+ Dead-code purge and substrate race fixes:
96
+ - Orphan modules removed (no consumers): `orchestrators/codegen/extras.ts` (inlined into
97
+ `runtime-composition.ts`); `plugins/deepbook/routable.ts` + the `DEEPBOOK_ENTRYPOINTS`
98
+ aggregation; `plugins/sui/live-faucet-strategy.ts` (`suiLiveStrategy`, `LIVE_FAUCET_URLS`,
99
+ `SuiLiveNetwork`, `SuiLiveStrategyOptions`); `plugins/sui/seed-objects.ts`
100
+ (`SeedObjectsAccumulator`, `makeSeedObjectsAccumulator`, `SEED_OBJECTS_CAPABILITY_KEY`). The sui
101
+ plugin's emitted-capability count drops from 5 to 4.
102
+ - `plugins/walrus/faucet-strategy.ts`: `makeWalFaucetContribution` removed;
103
+ `makeWalFaucetStrategy` unaffected.
104
+ - `orchestrators/router/index.ts`: unused `STATIC_PROVIDER_FILENAME` export removed.
105
+ - `plugins/sui/fork-orchestration.ts`: `ForkGuardedSdk<Sdk>` derived type alias removed;
106
+ `wrapWithForkGuard` now returns `Sdk` directly (behavior identical).
107
+ - Capability-sink registration race fixed: install + finalizer wrapped in `Effect.uninterruptible`
108
+ so an interrupt between `Ref.modify` and `addFinalizer` cannot leak the sink past scope close.
109
+ - Cross-process command channel short-read fix: `readSync` may short-return on NFS / cross-FS;
110
+ offset advances by `bytesRead` rather than the requested length, with a clean bail on
111
+ `bytesRead <= 0`.
112
+ - Cross-process roster PID-recycle hazard fixed: `heartbeat` / `release` / `setIntent` now match
113
+ holders via `(pid, hostname, startTime)` triple via a new `isOwnEntry` helper (was matching
114
+ `(pid, hostname)` only).
115
+ - Background snapshot interrupt now awaits via `Fiber.interrupt(fiber)` (was fire-and-forget
116
+ `fiber.interruptUnsafe()`) so a follow-up capture can't start while the previous fiber is still
117
+ inside `pauseAndCommit` / `saveImages`.
118
+ - CLI restructure: `cli/main.ts` (1338 LOC) split into per-verb wirings under
119
+ `cli/wirings/{up,apply,snapshot,wipe,prune}.ts` plus shared `build-verb-layers.ts` /
120
+ `identity.ts` / `config-loader.ts` helpers. `main.ts` is now argv → identity → deps → dispatch
121
+ only (~290 LOC).
122
+ - Cross-process command-channel `ack` / `error` records gain an optional `payload: unknown` field
123
+ plumbed through `awaitCompletion`. `snapshot.capture` now carries the captured metadata (or
124
+ failure summary / skipped reason) on the reply directly — the CLI no longer tail-fibers
125
+ `events.ndjson` for the completion event.
126
+ - Repo-wide Prettier reformat.
127
+
128
+ User-visible behavior changes (minor-bump rationale):
129
+ - **Pyth types removed from the root barrel.** `PythFeed`, `PythHandle`, `PythOptions`,
130
+ `PythPackageMember`, and `PythPriceFeedId` no longer re-export from
131
+ `@mysten-incubation/devstack`. They remain reachable via the `DeepbookLocalOptions.pyth` field
132
+ chain. The value helpers (`pythPriceFeedId`, `DEEP_PRICE_FEED_ID`, `SUI_PRICE_FEED_ID`,
133
+ `USDC_PRICE_FEED_ID`) are kept because `examples/deepbook-trader/devstack.config.ts` is the
134
+ market-maker case the architecture permits.
135
+ - **Postgres password format changed.** `derivePassword(app, stack, stackRoot)` now incorporates
136
+ the stack's on-disk runtime root and an sha256 short hash. Existing dev databases created
137
+ against the previous `pg-${app+stack}` format will fail to authenticate on first `pg_isready`
138
+ probe. Delete the existing container (`docker rm -f`) and let devstack recreate it.
139
+ Multi-checkout shells of the same `(app, stack)` now derive distinct passwords by design.
140
+ - **CLI argv-parse failures now exit with code 64 (`USAGE`), not 1 (`GENERIC`).** Tests / CI
141
+ scripts that pattern-match exit codes for "user error vs internal error" should treat 64 the
142
+ same way they treat the `--help` exit code. `--json` mode now also emits a structured envelope
143
+ for these failures instead of plain stderr.
144
+ - **`DevstackOptions.stateDir` is now honored.** The field was declared on the type but silently
145
+ ignored by `runStack` (only `runtimeRoot` was read). Programs that set
146
+ `defineDevstack({ stateDir })` previously had no effect; they now do.
147
+ - **CLI now honors `config.options.stateDir` / `defineDevstack({ stateDir })`.** The `devstack`
148
+ CLI loads the config best-effort before resolving identity and feeds its `stateDir` into the
149
+ runtime-root ladder. Precedence: `--state-dir` flag > `config.options.stateDir` >
150
+ `$DEVSTACK_STATE_DIR` > `<cwd>/.devstack`. The `--state-dir` flag still wins, and no-config
151
+ verbs (`prune`, `wipe`) keep resolving without a config.
152
+ - **`setNetworkEnv` now save/restores `process.env.DEVSTACK_NETWORK`.** In-process CLI invocations
153
+ (tests, embedded use) no longer leak `--network` env state into subsequent calls. Single-process
154
+ CLI semantics are unchanged.
155
+ - **`stringifyCause` renamed to `formatUnknownError`.** Plugins importing the substrate helper
156
+ directly need to update their import (canonical path:
157
+ `substrate/runtime/format-unknown-error.ts`). The function's behavior is unchanged.
158
+ - **Wallet endpoint constant unified.** `WALLET_ENDPOINT_ALIAS` removed; `WALLET_ENDPOINT_KEY` is
159
+ the single canonical name. All exports surface through the same module paths.
160
+ - **`EndpointEntry.wireProtocol`, `Endpoint.wireProtocol`, `ResolvedEndpoint.wireProtocol`**
161
+ narrowed from `'http' | 'h2c' | string` to `'http' | 'h2c' | 'tcp'`. Persisted manifests and
162
+ projections now reject other values at decode time. Plugins emitting custom wire protocols (none
163
+ ship today) would need to extend the literal union.
164
+
165
+ dev-wallet:
166
+ - `DEVSTACK_WALLET_HTTP_PATH.EXECUTE` removed (devstack-side `/execute` endpoint deleted; the
167
+ dapp-kit / dev-wallet path bypasses it and the protocol shape didn't match the Sui Wallet
168
+ Standard).
169
+
3
170
  ## 0.2.0
4
171
 
5
172
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.127.0/helpers/decorate.js
1
+ //#region \0@oxc-project+runtime@0.135.0/helpers/esm/decorate.js
2
2
  function __decorate(decorators, target, key, desc) {
3
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1 +1 @@
1
- {"version":3,"file":"base-adapter.d.mts","names":[],"sources":["../../src/adapters/base-adapter.ts"],"mappings":";;;;;AAYA;;;;uBAAsB,iBAAA,YAA6B,aAAA;EAAA;oBAChC,EAAA;EAAA,kBACA,IAAA;EAAA,SACT,aAAA;EAAA,SAKA,UAAA,CAAA,GAAc,OAAA;EAEvB,WAAA,CAAA,GAAe,cAAA;EAIf,UAAA,CAAW,OAAA,WAAkB,cAAA;EAI7B,iBAAA,CAAkB,QAAA,GAAW,QAAA,EAAU,cAAA;EAOvC,OAAA,CAAA;EAAA,cAOc,SAAA,CAAA,YAAsB,cAAA;EAAA,UAI1B,kBAAA,CAAmB,QAAA,EAAU,cAAA;EAAA,UAK7B,UAAA,CAAW,OAAA,EAAS,cAAA;EAAA,UAKpB,sBAAA,CAAuB,OAAA;EA3CxB;EAAA,UAoDC,cAAA,CAAe,OAAA,UAAiB,OAAA,EAAS,cAAA;EA/C5B;EAAA,UAwDb,cAAA,CAAe,OAAA,UAAiB,KAAA;EAAA,UAMhC,eAAA,CAAA;EAAA,UAIA,eAAA,CAAA;AAAA"}
1
+ {"version":3,"file":"base-adapter.d.mts","names":[],"sources":["../../src/adapters/base-adapter.ts"],"mappings":";;;;;AAYA;;;;uBAAsB,iBAAA,YAA6B,aAAA;EAAA;oBAChC,EAAA;EAAA,kBACA,IAAA;EAAA,SACT,aAAA;EAAA,SAKA,UAAA,IAAc,OAAA;EAEvB,WAAA,IAAe,cAAA;EAIf,UAAA,CAAW,OAAA,WAAkB,cAAA;EAI7B,iBAAA,CAAkB,QAAA,GAAW,QAAA,EAAU,cAAA;EAOvC,OAAA;EAAA,cAOc,SAAA,aAAsB,cAAA;EAAA,UAI1B,kBAAA,CAAmB,QAAA,EAAU,cAAA;EAAA,UAK7B,UAAA,CAAW,OAAA,EAAS,cAAA;EAAA,UAKpB,sBAAA,CAAuB,OAAA;EA3CxB;EAAA,UAoDC,cAAA,CAAe,OAAA,UAAiB,OAAA,EAAS,cAAA;EA/C5B;EAAA,UAwDb,cAAA,CAAe,OAAA,UAAiB,KAAA;EAAA,UAMhC,eAAA;EAAA,UAIA,eAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"base-adapter.mjs","names":["#accounts","#listeners"],"sources":["../../src/adapters/base-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ManagedAccount, SignerAdapter } from '../types.js';\nimport { buildManagedAccount } from './build-managed-account.js';\n\n/**\n * Abstract base class implementing the shared boilerplate of {@link SignerAdapter}.\n *\n * Subclasses only need to implement `initialize()`, `id`, and `name`.\n * All account list management, listener notification, and cleanup are handled here.\n */\nexport abstract class BaseSignerAdapter implements SignerAdapter {\n\tabstract readonly id: string;\n\tabstract readonly name: string;\n\treadonly allowAutoSign: boolean = true;\n\n\t#accounts: ManagedAccount[] = [];\n\t#listeners = new Set<(accounts: ManagedAccount[]) => void>();\n\n\tabstract initialize(): Promise<void>;\n\n\tgetAccounts(): ManagedAccount[] {\n\t\treturn [...this.#accounts];\n\t}\n\n\tgetAccount(address: string): ManagedAccount | undefined {\n\t\treturn this.#accounts.find((account) => account.address === address);\n\t}\n\n\tonAccountsChanged(callback: (accounts: ManagedAccount[]) => void): () => void {\n\t\tthis.#listeners.add(callback);\n\t\treturn () => {\n\t\t\tthis.#listeners.delete(callback);\n\t\t};\n\t}\n\n\tdestroy(): void {\n\t\tthis.#accounts = [];\n\t\tthis.#listeners.clear();\n\t}\n\n\t// ── Protected helpers for subclasses ─────────────────────────────────────\n\n\tprotected get _accounts(): readonly ManagedAccount[] {\n\t\treturn this.#accounts;\n\t}\n\n\tprotected setInitialAccounts(accounts: ManagedAccount[]): void {\n\t\tthis.#accounts = accounts;\n\t\tthis.notifyListeners();\n\t}\n\n\tprotected addAccount(account: ManagedAccount): void {\n\t\tthis.#accounts.push(account);\n\t\tthis.notifyListeners();\n\t}\n\n\tprotected removeAccountByAddress(address: string): boolean {\n\t\tconst index = this.#accounts.findIndex((a) => a.address === address);\n\t\tif (index === -1) return false;\n\t\tthis.#accounts.splice(index, 1);\n\t\tthis.notifyListeners();\n\t\treturn true;\n\t}\n\n\t/** Replace an account by address (e.g. after rename). */\n\tprotected replaceAccount(address: string, account: ManagedAccount): boolean {\n\t\tconst index = this.#accounts.findIndex((a) => a.address === address);\n\t\tif (index === -1) return false;\n\t\tthis.#accounts[index] = account;\n\t\tthis.notifyListeners();\n\t\treturn true;\n\t}\n\n\t/** Rename an account by rebuilding its ManagedAccount with a new label. */\n\tprotected _performRename(address: string, label: string): boolean {\n\t\tconst account = this.getAccount(address);\n\t\tif (!account) return false;\n\t\treturn this.replaceAccount(address, buildManagedAccount(account.signer, address, label));\n\t}\n\n\tprotected getDefaultLabel(): string {\n\t\treturn `Account ${this.getAccounts().length + 1}`;\n\t}\n\n\tprotected notifyListeners(): void {\n\t\tconst accounts = this.getAccounts();\n\t\tfor (const listener of this.#listeners) {\n\t\t\tlistener(accounts);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;AAYA,IAAsB,oBAAtB,MAAiE;;uBAG9B;mBAEJ,EAAE;oCACnB,IAAI,KAA2C;;CAD5D;CACA;CAIA,cAAgC;AAC/B,SAAO,CAAC,GAAG,MAAA,SAAe;;CAG3B,WAAW,SAA6C;AACvD,SAAO,MAAA,SAAe,MAAM,YAAY,QAAQ,YAAY,QAAQ;;CAGrE,kBAAkB,UAA4D;AAC7E,QAAA,UAAgB,IAAI,SAAS;AAC7B,eAAa;AACZ,SAAA,UAAgB,OAAO,SAAS;;;CAIlC,UAAgB;AACf,QAAA,WAAiB,EAAE;AACnB,QAAA,UAAgB,OAAO;;CAKxB,IAAc,YAAuC;AACpD,SAAO,MAAA;;CAGR,mBAA6B,UAAkC;AAC9D,QAAA,WAAiB;AACjB,OAAK,iBAAiB;;CAGvB,WAAqB,SAA+B;AACnD,QAAA,SAAe,KAAK,QAAQ;AAC5B,OAAK,iBAAiB;;CAGvB,uBAAiC,SAA0B;EAC1D,MAAM,QAAQ,MAAA,SAAe,WAAW,MAAM,EAAE,YAAY,QAAQ;AACpE,MAAI,UAAU,GAAI,QAAO;AACzB,QAAA,SAAe,OAAO,OAAO,EAAE;AAC/B,OAAK,iBAAiB;AACtB,SAAO;;;CAIR,eAAyB,SAAiB,SAAkC;EAC3E,MAAM,QAAQ,MAAA,SAAe,WAAW,MAAM,EAAE,YAAY,QAAQ;AACpE,MAAI,UAAU,GAAI,QAAO;AACzB,QAAA,SAAe,SAAS;AACxB,OAAK,iBAAiB;AACtB,SAAO;;;CAIR,eAAyB,SAAiB,OAAwB;EACjE,MAAM,UAAU,KAAK,WAAW,QAAQ;AACxC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,KAAK,eAAe,SAAS,oBAAoB,QAAQ,QAAQ,SAAS,MAAM,CAAC;;CAGzF,kBAAoC;AACnC,SAAO,WAAW,KAAK,aAAa,CAAC,SAAS;;CAG/C,kBAAkC;EACjC,MAAM,WAAW,KAAK,aAAa;AACnC,OAAK,MAAM,YAAY,MAAA,UACtB,UAAS,SAAS"}
1
+ {"version":3,"file":"base-adapter.mjs","names":["#accounts","#listeners"],"sources":["../../src/adapters/base-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ManagedAccount, SignerAdapter } from '../types.js';\nimport { buildManagedAccount } from './build-managed-account.js';\n\n/**\n * Abstract base class implementing the shared boilerplate of {@link SignerAdapter}.\n *\n * Subclasses only need to implement `initialize()`, `id`, and `name`.\n * All account list management, listener notification, and cleanup are handled here.\n */\nexport abstract class BaseSignerAdapter implements SignerAdapter {\n\tabstract readonly id: string;\n\tabstract readonly name: string;\n\treadonly allowAutoSign: boolean = true;\n\n\t#accounts: ManagedAccount[] = [];\n\t#listeners = new Set<(accounts: ManagedAccount[]) => void>();\n\n\tabstract initialize(): Promise<void>;\n\n\tgetAccounts(): ManagedAccount[] {\n\t\treturn [...this.#accounts];\n\t}\n\n\tgetAccount(address: string): ManagedAccount | undefined {\n\t\treturn this.#accounts.find((account) => account.address === address);\n\t}\n\n\tonAccountsChanged(callback: (accounts: ManagedAccount[]) => void): () => void {\n\t\tthis.#listeners.add(callback);\n\t\treturn () => {\n\t\t\tthis.#listeners.delete(callback);\n\t\t};\n\t}\n\n\tdestroy(): void {\n\t\tthis.#accounts = [];\n\t\tthis.#listeners.clear();\n\t}\n\n\t// ── Protected helpers for subclasses ─────────────────────────────────────\n\n\tprotected get _accounts(): readonly ManagedAccount[] {\n\t\treturn this.#accounts;\n\t}\n\n\tprotected setInitialAccounts(accounts: ManagedAccount[]): void {\n\t\tthis.#accounts = accounts;\n\t\tthis.notifyListeners();\n\t}\n\n\tprotected addAccount(account: ManagedAccount): void {\n\t\tthis.#accounts.push(account);\n\t\tthis.notifyListeners();\n\t}\n\n\tprotected removeAccountByAddress(address: string): boolean {\n\t\tconst index = this.#accounts.findIndex((a) => a.address === address);\n\t\tif (index === -1) return false;\n\t\tthis.#accounts.splice(index, 1);\n\t\tthis.notifyListeners();\n\t\treturn true;\n\t}\n\n\t/** Replace an account by address (e.g. after rename). */\n\tprotected replaceAccount(address: string, account: ManagedAccount): boolean {\n\t\tconst index = this.#accounts.findIndex((a) => a.address === address);\n\t\tif (index === -1) return false;\n\t\tthis.#accounts[index] = account;\n\t\tthis.notifyListeners();\n\t\treturn true;\n\t}\n\n\t/** Rename an account by rebuilding its ManagedAccount with a new label. */\n\tprotected _performRename(address: string, label: string): boolean {\n\t\tconst account = this.getAccount(address);\n\t\tif (!account) return false;\n\t\treturn this.replaceAccount(address, buildManagedAccount(account.signer, address, label));\n\t}\n\n\tprotected getDefaultLabel(): string {\n\t\treturn `Account ${this.getAccounts().length + 1}`;\n\t}\n\n\tprotected notifyListeners(): void {\n\t\tconst accounts = this.getAccounts();\n\t\tfor (const listener of this.#listeners) {\n\t\t\tlistener(accounts);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;AAYA,IAAsB,oBAAtB,MAAiE;;uBAG9B;mBAEJ,CAAC;oCAClB,IAAI,IAA0C;;CAD3D;CACA;CAIA,cAAgC;EAC/B,OAAO,CAAC,GAAG,KAAKA,SAAS;CAC1B;CAEA,WAAW,SAA6C;EACvD,OAAO,KAAKA,UAAU,MAAM,YAAY,QAAQ,YAAY,OAAO;CACpE;CAEA,kBAAkB,UAA4D;EAC7E,KAAKC,WAAW,IAAI,QAAQ;EAC5B,aAAa;GACZ,KAAKA,WAAW,OAAO,QAAQ;EAChC;CACD;CAEA,UAAgB;EACf,KAAKD,YAAY,CAAC;EAClB,KAAKC,WAAW,MAAM;CACvB;CAIA,IAAc,YAAuC;EACpD,OAAO,KAAKD;CACb;CAEA,mBAA6B,UAAkC;EAC9D,KAAKA,YAAY;EACjB,KAAK,gBAAgB;CACtB;CAEA,WAAqB,SAA+B;EACnD,KAAKA,UAAU,KAAK,OAAO;EAC3B,KAAK,gBAAgB;CACtB;CAEA,uBAAiC,SAA0B;EAC1D,MAAM,QAAQ,KAAKA,UAAU,WAAW,MAAM,EAAE,YAAY,OAAO;EACnE,IAAI,UAAU,IAAI,OAAO;EACzB,KAAKA,UAAU,OAAO,OAAO,CAAC;EAC9B,KAAK,gBAAgB;EACrB,OAAO;CACR;;CAGA,eAAyB,SAAiB,SAAkC;EAC3E,MAAM,QAAQ,KAAKA,UAAU,WAAW,MAAM,EAAE,YAAY,OAAO;EACnE,IAAI,UAAU,IAAI,OAAO;EACzB,KAAKA,UAAU,SAAS;EACxB,KAAK,gBAAgB;EACrB,OAAO;CACR;;CAGA,eAAyB,SAAiB,OAAwB;EACjE,MAAM,UAAU,KAAK,WAAW,OAAO;EACvC,IAAI,CAAC,SAAS,OAAO;EACrB,OAAO,KAAK,eAAe,SAAS,oBAAoB,QAAQ,QAAQ,SAAS,KAAK,CAAC;CACxF;CAEA,kBAAoC;EACnC,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,SAAS;CAC/C;CAEA,kBAAkC;EACjC,MAAM,WAAW,KAAK,YAAY;EAClC,KAAK,MAAM,YAAY,KAAKC,YAC3B,SAAS,QAAQ;CAEnB;AACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"build-managed-account.mjs","names":[],"sources":["../../src/adapters/build-managed-account.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Signer } from '@mysten/sui/cryptography';\nimport type { IdentifierString } from '@mysten/wallet-standard';\nimport { ReadonlyWalletAccount, SUI_CHAINS } from '@mysten/wallet-standard';\n\nimport type { ManagedAccount } from '../types.js';\n\nconst DEFAULT_FEATURES: IdentifierString[] = [\n\t'sui:signTransaction',\n\t'sui:signAndExecuteTransaction',\n\t'sui:signPersonalMessage',\n];\n\n/**\n * Build a {@link ManagedAccount} from a signer, address, label, and optional feature list.\n */\nexport function buildManagedAccount(\n\tsigner: Signer,\n\taddress: string,\n\tlabel: string,\n\tfeatures?: readonly IdentifierString[],\n): ManagedAccount {\n\tconst walletAccount = new ReadonlyWalletAccount({\n\t\taddress,\n\t\tlabel,\n\t\tpublicKey: signer.getPublicKey().toSuiBytes(),\n\t\tchains: [...SUI_CHAINS],\n\t\tfeatures: [...(features ?? DEFAULT_FEATURES)],\n\t});\n\treturn { address, label, signer, walletAccount };\n}\n"],"mappings":";;AASA,MAAM,mBAAuC;CAC5C;CACA;CACA;CACA;;;;AAKD,SAAgB,oBACf,QACA,SACA,OACA,UACiB;AAQjB,QAAO;EAAE;EAAS;EAAO;EAAQ,mBAPP,sBAAsB;GAC/C;GACA;GACA,WAAW,OAAO,cAAc,CAAC,YAAY;GAC7C,QAAQ,CAAC,GAAG,WAAW;GACvB,UAAU,CAAC,GAAI,YAAY,iBAAkB;GAC7C,CACgC;EAAe"}
1
+ {"version":3,"file":"build-managed-account.mjs","names":[],"sources":["../../src/adapters/build-managed-account.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Signer } from '@mysten/sui/cryptography';\nimport type { IdentifierString } from '@mysten/wallet-standard';\nimport { ReadonlyWalletAccount, SUI_CHAINS } from '@mysten/wallet-standard';\n\nimport type { ManagedAccount } from '../types.js';\n\nconst DEFAULT_FEATURES: IdentifierString[] = [\n\t'sui:signTransaction',\n\t'sui:signAndExecuteTransaction',\n\t'sui:signPersonalMessage',\n];\n\n/**\n * Build a {@link ManagedAccount} from a signer, address, label, and optional feature list.\n */\nexport function buildManagedAccount(\n\tsigner: Signer,\n\taddress: string,\n\tlabel: string,\n\tfeatures?: readonly IdentifierString[],\n): ManagedAccount {\n\tconst walletAccount = new ReadonlyWalletAccount({\n\t\taddress,\n\t\tlabel,\n\t\tpublicKey: signer.getPublicKey().toSuiBytes(),\n\t\tchains: [...SUI_CHAINS],\n\t\tfeatures: [...(features ?? DEFAULT_FEATURES)],\n\t});\n\treturn { address, label, signer, walletAccount };\n}\n"],"mappings":";;AASA,MAAM,mBAAuC;CAC5C;CACA;CACA;AACD;;;;AAKA,SAAgB,oBACf,QACA,SACA,OACA,UACiB;CAQjB,OAAO;EAAE;EAAS;EAAO;EAAQ,mBAPP,sBAAsB;GAC/C;GACA;GACA,WAAW,OAAO,aAAa,CAAC,CAAC,WAAW;GAC5C,QAAQ,CAAC,GAAG,UAAU;GACtB,UAAU,CAAC,GAAI,YAAY,gBAAiB;EAC7C,CACiC;CAAc;AAChD"}
@@ -1 +1 @@
1
- {"version":3,"file":"devstack-adapter.d.mts","names":[],"sources":["../../src/adapters/devstack-adapter.ts"],"mappings":";;;;;AAiEA;;;;cAAa,mBAAA,SAA4B,MAAA;EAAA;cAO5B,OAAA;IACX,OAAA;IACA,SAAA,EAAW,SAAA;IACX,MAAA,EAAQ,eAAA;IACR,YAAA;IACA,SAAA;EAAA;EAUK,IAAA,CAAK,MAAA,EAAQ,UAAA,GAAa,OAAA,CAAQ,UAAA,CAAW,WAAA;EAOnD,YAAA,CAAA,GAAgB,eAAA;EAIhB,YAAA,CAAA,GAAgB,SAAA;EAIP,YAAA,CAAA;EAIM,eAAA,CAAgB,KAAA,EAAO,UAAA,GAAU,OAAA;;;;EAqCjC,mBAAA,CAAoB,KAAA,EAAO,UAAA,GAAU,OAAA;;;;;UAyCpC,4BAAA;EA3Gf;;EA8GD,YAAA;EApGmB;;EAuGnB,KAAA;EAvGwC;EAyGxC,IAAA;AAAA;;;;;;;;;;;;;;;;;;;AARD;;cA+Ba,qBAAA,SAA8B,iBAAA;EAAA;WACjC,EAAA;EAAA,SACA,IAAA;EAAA,SACA,aAAA;cAKG,OAAA,EAAS,4BAAA;EAYf,UAAA,CAAA,GAAc,OAAA;EAaX,OAAA,CAAA;AAAA;;;;;;;;;;iBAyCM,kBAAA,CAAmB,SAAA;;;;;;;;UAsBlB,uBAAA;EAChB,GAAA;IACC,MAAA;MACC,GAAA;MACA,OAAA;IAAA;EAAA;AAAA;;;;;;;;;;AAiBH;;;iBAAgB,iCAAA,CACf,QAAA,EAAU,uBAAA,GACR,qBAAA"}
1
+ {"version":3,"file":"devstack-adapter.d.mts","names":[],"sources":["../../src/adapters/devstack-adapter.ts"],"mappings":";;;;;AAiEA;;;;cAAa,mBAAA,SAA4B,MAAA;EAAA;cAO5B,OAAA;IACX,OAAA;IACA,SAAA,EAAW,SAAA;IACX,MAAA,EAAQ,eAAA;IACR,YAAA;IACA,SAAA;EAAA;EAUK,IAAA,CAAK,MAAA,EAAQ,UAAA,GAAa,OAAA,CAAQ,UAAA,CAAW,WAAA;EAOnD,YAAA,IAAgB,eAAA;EAIhB,YAAA,IAAgB,SAAA;EAIP,YAAA;EAIM,eAAA,CAAgB,KAAA,EAAO,UAAA,GAAU,OAAA;;;;EAqCjC,mBAAA,CAAoB,KAAA,EAAO,UAAA,GAAU,OAAA;;;;;UAyCpC,4BAAA;EA3Gf;;EA8GD,YAAA;EApGmB;;EAuGnB,KAAA;EAvGwC;EAyGxC,IAAA;AAAA;;;;;;;;;;;;;;;;;;;AARD;;cA+Ba,qBAAA,SAA8B,iBAAA;EAAA;WACjC,EAAA;EAAA,SACA,IAAA;EAAA,SACA,aAAA;cAKG,OAAA,EAAS,4BAAA;EAYf,UAAA,IAAc,OAAA;EAaX,OAAA;AAAA;;;;;;;;;;iBAyCM,kBAAA,CAAmB,SAA6B;;;;;;;;UAsB/C,uBAAA;EAChB,GAAA;IACC,MAAA;MACC,GAAA;MACA,OAAA;IAAA;EAAA;AAAA;;;;;;;;;AAAO;AAiBV;;;iBAAgB,iCAAA,CACf,QAAA,EAAU,uBAAA,GACR,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"devstack-adapter.mjs","names":["#address","#publicKey","#scheme","#serverOrigin","#authToken","#fetchAccounts"],"sources":["../../src/adapters/devstack-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n//\n// Devstack signer adapter — exposes accounts resolved by `devstack up`'s\n// `wallet()` plugin to dApp Kit, signing transactions over HTTP so\n// private keys never enter the frontend bundle. Mirrors RemoteCliAdapter's\n// out-of-process model; the difference is the source of accounts (devstack\n// resolved signers vs `sui keytool list`) and the endpoint paths.\n\nimport { Signer } from '@mysten/sui/cryptography';\nimport type { PublicKey, SignatureScheme } from '@mysten/sui/cryptography';\nimport { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519';\nimport { Secp256k1PublicKey } from '@mysten/sui/keypairs/secp256k1';\nimport { Secp256r1PublicKey } from '@mysten/sui/keypairs/secp256r1';\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\n\nimport type { ManagedAccount } from '../types.js';\nimport { BaseSignerAdapter } from './base-adapter.js';\nimport { buildManagedAccount } from './build-managed-account.js';\nimport { DEVSTACK_WALLET_HTTP_PATH } from './devstack-paths.js';\n\nconst DEVSTACK_WALLET_FEATURES = [\n\t'sui:signTransaction',\n\t'sui:signAndExecuteTransaction',\n\t'sui:signPersonalMessage',\n] as const;\n\ninterface ServerAccountInfo {\n\tname: string;\n\taddress: string;\n\tscheme: SignatureScheme;\n\tpublicKey: string;\n}\n\nclass AuthError extends Error {\n\tconstructor() {\n\t\tsuper('Unauthorized');\n\t\tthis.name = 'AuthError';\n\t}\n}\n\nfunction publicKeyForScheme(base64: string, scheme: SignatureScheme | string): PublicKey {\n\tconst bytes = fromBase64(base64);\n\t// The devstack server's wallet-app endpoint surfaces the scheme in\n\t// the lowercase form it standardised at the Account boundary\n\t// (`'ed25519'`, `'secp256k1'`, `'secp256r1'`). The Sui SDK's\n\t// `SignatureScheme` union is mixed-case (`'ED25519'`, `'Secp256k1'`,\n\t// …). Normalise to lowercase before matching so either casing parses.\n\tswitch (String(scheme).toLowerCase()) {\n\t\tcase 'ed25519':\n\t\t\treturn new Ed25519PublicKey(bytes);\n\t\tcase 'secp256k1':\n\t\t\treturn new Secp256k1PublicKey(bytes);\n\t\tcase 'secp256r1':\n\t\t\treturn new Secp256r1PublicKey(bytes);\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported key scheme: ${scheme}`);\n\t}\n}\n\n/**\n * Signer that delegates transaction signing to the devstack wallet-app\n * over HTTP. Mirrors {@link CliProxySigner} but talks to the\n * `wallet()` plugin's endpoints under `/api/v1/devstack/*`.\n */\nexport class DevstackProxySigner extends Signer {\n\t#address: string;\n\t#publicKey: PublicKey;\n\t#scheme: SignatureScheme;\n\t#serverOrigin: string;\n\t#authToken: string | null;\n\n\tconstructor(options: {\n\t\taddress: string;\n\t\tpublicKey: PublicKey;\n\t\tscheme: SignatureScheme;\n\t\tserverOrigin: string;\n\t\tauthToken?: string | null;\n\t}) {\n\t\tsuper();\n\t\tthis.#address = options.address;\n\t\tthis.#publicKey = options.publicKey;\n\t\tthis.#scheme = options.scheme;\n\t\tthis.#serverOrigin = options.serverOrigin;\n\t\tthis.#authToken = options.authToken ?? null;\n\t}\n\n\tasync sign(_bytes: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n\t\tthrow new Error(\n\t\t\t'DevstackProxySigner does not support raw digest signing. ' +\n\t\t\t\t'Use signTransaction (the wallet-app signs BCS-serialized TransactionData).',\n\t\t);\n\t}\n\n\tgetKeyScheme(): SignatureScheme {\n\t\treturn this.#scheme;\n\t}\n\n\tgetPublicKey(): PublicKey {\n\t\treturn this.#publicKey;\n\t}\n\n\toverride toSuiAddress(): string {\n\t\treturn this.#address;\n\t}\n\n\toverride async signTransaction(bytes: Uint8Array) {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst requestBytes = toBase64(bytes);\n\t\tconst res = await fetch(`${this.#serverOrigin}${DEVSTACK_WALLET_HTTP_PATH.SIGN_TRANSACTION}`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders,\n\t\t\tbody: JSON.stringify({\n\t\t\t\taddress: this.#address,\n\t\t\t\tbytes: requestBytes,\n\t\t\t}),\n\t\t});\n\t\tif (!res.ok) {\n\t\t\tconst body = await res.json().catch(() => ({}));\n\t\t\tconst message = (body as { error?: unknown }).error;\n\t\t\tthrow new Error(\n\t\t\t\t`Devstack signing failed: ${typeof message === 'string' ? message : res.statusText}`,\n\t\t\t);\n\t\t}\n\t\tconst { bytes: responseBytes, signature } = (await res.json()) as {\n\t\t\tbytes?: string;\n\t\t\tsignature?: string;\n\t\t};\n\t\tif (typeof responseBytes !== 'string' || responseBytes.length === 0) {\n\t\t\tthrow new Error('Devstack signing failed: server returned invalid signed bytes');\n\t\t}\n\t\tif (typeof signature !== 'string' || signature.length === 0) {\n\t\t\tthrow new Error('Devstack signing failed: server returned invalid signature');\n\t\t}\n\t\treturn {\n\t\t\tbytes: responseBytes,\n\t\t\tsignature,\n\t\t};\n\t}\n\n\toverride async signPersonalMessage(bytes: Uint8Array) {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst res = await fetch(\n\t\t\t`${this.#serverOrigin}${DEVSTACK_WALLET_HTTP_PATH.SIGN_PERSONAL_MESSAGE}`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders,\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\taddress: this.#address,\n\t\t\t\t\tbytes: toBase64(bytes),\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\t\tif (!res.ok) {\n\t\t\tconst body = await res.json().catch(() => ({}));\n\t\t\tconst message = (body as { error?: unknown }).error;\n\t\t\tthrow new Error(\n\t\t\t\t`Devstack personal-message signing failed: ${\n\t\t\t\t\ttypeof message === 'string' ? message : res.statusText\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tconst { bytes: responseBytes, signature } = (await res.json()) as {\n\t\t\tbytes?: string;\n\t\t\tsignature?: string;\n\t\t};\n\t\tif (typeof responseBytes !== 'string' || responseBytes.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t'Devstack personal-message signing failed: server returned invalid signed bytes',\n\t\t\t);\n\t\t}\n\t\tif (typeof signature !== 'string' || signature.length === 0) {\n\t\t\tthrow new Error('Devstack personal-message signing failed: server returned no signature');\n\t\t}\n\t\treturn { bytes: responseBytes, signature };\n\t}\n}\n\nexport interface DevstackSignerAdapterOptions {\n\t/** Wallet-app origin (e.g. `http://localhost:9420`). Read from the\n\t * matching endpoint entry on the active manifest. */\n\tserverOrigin: string;\n\t/** Bearer token. Parse `?token=<hex>` from the manifest entry's\n\t * `pairUrl`. Omit if the wallet-app runs without auth. */\n\ttoken?: string | null;\n\t/** Override the adapter's display name. Defaults to `'Devstack'`. */\n\tname?: string;\n}\n\n/**\n * {@link SignerAdapter} that surfaces every account resolved by `devstack up`\n * (including `cliSigner`/`envSigner`/`generatedKeypair` slots) without\n * shipping their private keys into the frontend bundle. All signing happens\n * server-side via the `wallet()` plugin.\n *\n * The simplest construction uses devstack's generated `dapp-kit-config.ts`,\n * which bakes the wallet adapter wiring at codegen time — apps spread\n * `devstackDappKitConfig` into `createDAppKit(...)` and never touch the\n * adapter directly.\n *\n * To construct one manually (e.g. from a non-manifest source):\n *\n * ```ts\n * const adapter = new DevstackSignerAdapter({\n * serverOrigin: 'http://localhost:9420',\n * token: '<bearer hex>',\n * });\n * ```\n */\nexport class DevstackSignerAdapter extends BaseSignerAdapter {\n\treadonly id = 'devstack';\n\treadonly name: string;\n\treadonly allowAutoSign = true;\n\n\t#serverOrigin: string;\n\t#authToken: string | null;\n\n\tconstructor(options: DevstackSignerAdapterOptions) {\n\t\tsuper();\n\t\ttry {\n\t\t\tnew URL(options.serverOrigin);\n\t\t} catch {\n\t\t\tthrow new Error(`DevstackSignerAdapter: invalid serverOrigin \"${options.serverOrigin}\"`);\n\t\t}\n\t\tthis.#serverOrigin = options.serverOrigin;\n\t\tthis.#authToken = options.token ?? null;\n\t\tthis.name = options.name ?? 'Devstack';\n\t}\n\n\tasync initialize(): Promise<void> {\n\t\ttry {\n\t\t\tconst accounts = await this.#fetchAccounts();\n\t\t\tthis.setInitialAccounts(accounts);\n\t\t} catch (error) {\n\t\t\tif (error instanceof AuthError) {\n\t\t\t\tconsole.warn('[dev-wallet] devstack adapter: unauthorized — skipping account import');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconsole.warn('[dev-wallet] devstack adapter: initialization failed:', error);\n\t\t}\n\t}\n\n\toverride destroy(): void {\n\t\tthis.#authToken = null;\n\t\tsuper.destroy();\n\t}\n\n\tasync #fetchAccounts(): Promise<ManagedAccount[]> {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst res = await fetch(`${this.#serverOrigin}${DEVSTACK_WALLET_HTTP_PATH.ACCOUNTS}`, {\n\t\t\theaders,\n\t\t});\n\t\tif (res.status === 401 || res.status === 403) throw new AuthError();\n\t\tif (!res.ok) {\n\t\t\tthrow new Error(`Failed to fetch devstack accounts: ${res.statusText}`);\n\t\t}\n\t\tconst { accounts } = (await res.json()) as { accounts: ServerAccountInfo[] };\n\t\treturn accounts.map((info) => {\n\t\t\tconst publicKey = publicKeyForScheme(info.publicKey, info.scheme);\n\t\t\tconst signer = new DevstackProxySigner({\n\t\t\t\taddress: info.address,\n\t\t\t\tpublicKey,\n\t\t\t\tscheme: info.scheme,\n\t\t\t\tserverOrigin: this.#serverOrigin,\n\t\t\t\tauthToken: this.#authToken,\n\t\t\t});\n\t\t\treturn buildManagedAccount(signer, info.address, info.name, DEVSTACK_WALLET_FEATURES);\n\t\t});\n\t}\n}\n\n/**\n * Pull the bearer token off a paired URL produced by the `wallet()`\n * plugin. Returns `null` if the input is undefined, malformed, or\n * carries a `<redacted>` placeholder (the manifest's pairUrl carries\n * the redacted form; the real token lives in a sibling 0o600 file the\n * consumer reads separately).\n *\n * The token rides in the URL fragment as `#token=<hex>`.\n */\nexport function parseDevstackToken(pairedUrl: string | undefined): string | null {\n\tif (pairedUrl === undefined) return null;\n\ttry {\n\t\tconst url = new URL(pairedUrl);\n\t\tconst hash = url.hash; // e.g. \"#token=abcd\"\n\t\tif (hash.length <= 1) return null;\n\t\tconst params = new URLSearchParams(hash.slice(1));\n\t\tconst token = params.get('token');\n\t\tif (token === null || token === '<redacted>') return null;\n\t\treturn token;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** Narrow input — the only field the adapter consumes is\n * `app.wallet.{url, pairUrl}`. Codegen emits exactly this shape so\n * generated `dapp-kit-config.ts` doesn't have to fabricate placeholder\n * manifest fields (`stack.app`, `coins`, etc.) just to satisfy the\n * full `Manifest` type. Mirrors a slice of `AppManifest` from\n * `@mysten-incubation/devstack` without importing it (dev-wallet\n * doesn't depend on devstack — circular). */\nexport interface DevstackAdapterManifest {\n\tapp?: {\n\t\twallet?: {\n\t\t\turl: string;\n\t\t\tpairUrl?: string;\n\t\t};\n\t};\n}\n\n/**\n * Convenience: read the wallet-app endpoint off a devstack manifest and\n * build a configured adapter, or return `null` when the entry isn't\n * present (no `wallet(...)` in the stack, or it hasn't come up yet).\n *\n * The wallet entry's `pairUrl` carries the `#token=…` fragment used to\n * extract the bearer token. The full `Manifest` shape from\n * `@mysten-incubation/devstack` is structurally compatible with\n * {@link DevstackAdapterManifest}, so\n * `createDevstackAdapterFromManifest(devstackManifest)` typechecks\n * without a cast.\n */\nexport function createDevstackAdapterFromManifest(\n\tmanifest: DevstackAdapterManifest,\n): DevstackSignerAdapter | null {\n\tconst wallet = manifest.app?.wallet;\n\tif (wallet === undefined) return null;\n\treturn new DevstackSignerAdapter({\n\t\tserverOrigin: wallet.url,\n\t\ttoken: parseDevstackToken(wallet.pairUrl),\n\t});\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"devstack-adapter.mjs","names":["#address","#publicKey","#scheme","#serverOrigin","#authToken","#fetchAccounts"],"sources":["../../src/adapters/devstack-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n//\n// Devstack signer adapter — exposes accounts resolved by `devstack up`'s\n// `wallet()` plugin to dApp Kit, signing transactions over HTTP so\n// private keys never enter the frontend bundle. Mirrors RemoteCliAdapter's\n// out-of-process model; the difference is the source of accounts (devstack\n// resolved signers vs `sui keytool list`) and the endpoint paths.\n\nimport { Signer } from '@mysten/sui/cryptography';\nimport type { PublicKey, SignatureScheme } from '@mysten/sui/cryptography';\nimport { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519';\nimport { Secp256k1PublicKey } from '@mysten/sui/keypairs/secp256k1';\nimport { Secp256r1PublicKey } from '@mysten/sui/keypairs/secp256r1';\nimport { fromBase64, toBase64 } from '@mysten/sui/utils';\n\nimport type { ManagedAccount } from '../types.js';\nimport { BaseSignerAdapter } from './base-adapter.js';\nimport { buildManagedAccount } from './build-managed-account.js';\nimport { DEVSTACK_WALLET_HTTP_PATH } from './devstack-paths.js';\n\nconst DEVSTACK_WALLET_FEATURES = [\n\t'sui:signTransaction',\n\t'sui:signAndExecuteTransaction',\n\t'sui:signPersonalMessage',\n] as const;\n\ninterface ServerAccountInfo {\n\tname: string;\n\taddress: string;\n\tscheme: SignatureScheme;\n\tpublicKey: string;\n}\n\nclass AuthError extends Error {\n\tconstructor() {\n\t\tsuper('Unauthorized');\n\t\tthis.name = 'AuthError';\n\t}\n}\n\nfunction publicKeyForScheme(base64: string, scheme: SignatureScheme | string): PublicKey {\n\tconst bytes = fromBase64(base64);\n\t// The devstack server's wallet-app endpoint surfaces the scheme in\n\t// the lowercase form it standardised at the Account boundary\n\t// (`'ed25519'`, `'secp256k1'`, `'secp256r1'`). The Sui SDK's\n\t// `SignatureScheme` union is mixed-case (`'ED25519'`, `'Secp256k1'`,\n\t// …). Normalise to lowercase before matching so either casing parses.\n\tswitch (String(scheme).toLowerCase()) {\n\t\tcase 'ed25519':\n\t\t\treturn new Ed25519PublicKey(bytes);\n\t\tcase 'secp256k1':\n\t\t\treturn new Secp256k1PublicKey(bytes);\n\t\tcase 'secp256r1':\n\t\t\treturn new Secp256r1PublicKey(bytes);\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported key scheme: ${scheme}`);\n\t}\n}\n\n/**\n * Signer that delegates transaction signing to the devstack wallet-app\n * over HTTP. Mirrors {@link CliProxySigner} but talks to the\n * `wallet()` plugin's endpoints under `/api/v1/devstack/*`.\n */\nexport class DevstackProxySigner extends Signer {\n\t#address: string;\n\t#publicKey: PublicKey;\n\t#scheme: SignatureScheme;\n\t#serverOrigin: string;\n\t#authToken: string | null;\n\n\tconstructor(options: {\n\t\taddress: string;\n\t\tpublicKey: PublicKey;\n\t\tscheme: SignatureScheme;\n\t\tserverOrigin: string;\n\t\tauthToken?: string | null;\n\t}) {\n\t\tsuper();\n\t\tthis.#address = options.address;\n\t\tthis.#publicKey = options.publicKey;\n\t\tthis.#scheme = options.scheme;\n\t\tthis.#serverOrigin = options.serverOrigin;\n\t\tthis.#authToken = options.authToken ?? null;\n\t}\n\n\tasync sign(_bytes: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n\t\tthrow new Error(\n\t\t\t'DevstackProxySigner does not support raw digest signing. ' +\n\t\t\t\t'Use signTransaction (the wallet-app signs BCS-serialized TransactionData).',\n\t\t);\n\t}\n\n\tgetKeyScheme(): SignatureScheme {\n\t\treturn this.#scheme;\n\t}\n\n\tgetPublicKey(): PublicKey {\n\t\treturn this.#publicKey;\n\t}\n\n\toverride toSuiAddress(): string {\n\t\treturn this.#address;\n\t}\n\n\toverride async signTransaction(bytes: Uint8Array) {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst requestBytes = toBase64(bytes);\n\t\tconst res = await fetch(`${this.#serverOrigin}${DEVSTACK_WALLET_HTTP_PATH.SIGN_TRANSACTION}`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders,\n\t\t\tbody: JSON.stringify({\n\t\t\t\taddress: this.#address,\n\t\t\t\tbytes: requestBytes,\n\t\t\t}),\n\t\t});\n\t\tif (!res.ok) {\n\t\t\tconst body = await res.json().catch(() => ({}));\n\t\t\tconst message = (body as { error?: unknown }).error;\n\t\t\tthrow new Error(\n\t\t\t\t`Devstack signing failed: ${typeof message === 'string' ? message : res.statusText}`,\n\t\t\t);\n\t\t}\n\t\tconst { bytes: responseBytes, signature } = (await res.json()) as {\n\t\t\tbytes?: string;\n\t\t\tsignature?: string;\n\t\t};\n\t\tif (typeof responseBytes !== 'string' || responseBytes.length === 0) {\n\t\t\tthrow new Error('Devstack signing failed: server returned invalid signed bytes');\n\t\t}\n\t\tif (typeof signature !== 'string' || signature.length === 0) {\n\t\t\tthrow new Error('Devstack signing failed: server returned invalid signature');\n\t\t}\n\t\treturn {\n\t\t\tbytes: responseBytes,\n\t\t\tsignature,\n\t\t};\n\t}\n\n\toverride async signPersonalMessage(bytes: Uint8Array) {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst res = await fetch(\n\t\t\t`${this.#serverOrigin}${DEVSTACK_WALLET_HTTP_PATH.SIGN_PERSONAL_MESSAGE}`,\n\t\t\t{\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders,\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\taddress: this.#address,\n\t\t\t\t\tbytes: toBase64(bytes),\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\t\tif (!res.ok) {\n\t\t\tconst body = await res.json().catch(() => ({}));\n\t\t\tconst message = (body as { error?: unknown }).error;\n\t\t\tthrow new Error(\n\t\t\t\t`Devstack personal-message signing failed: ${\n\t\t\t\t\ttypeof message === 'string' ? message : res.statusText\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tconst { bytes: responseBytes, signature } = (await res.json()) as {\n\t\t\tbytes?: string;\n\t\t\tsignature?: string;\n\t\t};\n\t\tif (typeof responseBytes !== 'string' || responseBytes.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t'Devstack personal-message signing failed: server returned invalid signed bytes',\n\t\t\t);\n\t\t}\n\t\tif (typeof signature !== 'string' || signature.length === 0) {\n\t\t\tthrow new Error('Devstack personal-message signing failed: server returned no signature');\n\t\t}\n\t\treturn { bytes: responseBytes, signature };\n\t}\n}\n\nexport interface DevstackSignerAdapterOptions {\n\t/** Wallet-app origin (e.g. `http://localhost:9420`). Read from the\n\t * matching endpoint entry on the active manifest. */\n\tserverOrigin: string;\n\t/** Bearer token. Parse `?token=<hex>` from the manifest entry's\n\t * `pairUrl`. Omit if the wallet-app runs without auth. */\n\ttoken?: string | null;\n\t/** Override the adapter's display name. Defaults to `'Devstack'`. */\n\tname?: string;\n}\n\n/**\n * {@link SignerAdapter} that surfaces every account resolved by `devstack up`\n * (including `cliSigner`/`envSigner`/`generatedKeypair` slots) without\n * shipping their private keys into the frontend bundle. All signing happens\n * server-side via the `wallet()` plugin.\n *\n * The simplest construction uses devstack's generated `dapp-kit-config.ts`,\n * which bakes the wallet adapter wiring at codegen time — apps spread\n * `devstackDappKitConfig` into `createDAppKit(...)` and never touch the\n * adapter directly.\n *\n * To construct one manually (e.g. from a non-manifest source):\n *\n * ```ts\n * const adapter = new DevstackSignerAdapter({\n * serverOrigin: 'http://localhost:9420',\n * token: '<bearer hex>',\n * });\n * ```\n */\nexport class DevstackSignerAdapter extends BaseSignerAdapter {\n\treadonly id = 'devstack';\n\treadonly name: string;\n\treadonly allowAutoSign = true;\n\n\t#serverOrigin: string;\n\t#authToken: string | null;\n\n\tconstructor(options: DevstackSignerAdapterOptions) {\n\t\tsuper();\n\t\ttry {\n\t\t\tnew URL(options.serverOrigin);\n\t\t} catch {\n\t\t\tthrow new Error(`DevstackSignerAdapter: invalid serverOrigin \"${options.serverOrigin}\"`);\n\t\t}\n\t\tthis.#serverOrigin = options.serverOrigin;\n\t\tthis.#authToken = options.token ?? null;\n\t\tthis.name = options.name ?? 'Devstack';\n\t}\n\n\tasync initialize(): Promise<void> {\n\t\ttry {\n\t\t\tconst accounts = await this.#fetchAccounts();\n\t\t\tthis.setInitialAccounts(accounts);\n\t\t} catch (error) {\n\t\t\tif (error instanceof AuthError) {\n\t\t\t\tconsole.warn('[dev-wallet] devstack adapter: unauthorized — skipping account import');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconsole.warn('[dev-wallet] devstack adapter: initialization failed:', error);\n\t\t}\n\t}\n\n\toverride destroy(): void {\n\t\tthis.#authToken = null;\n\t\tsuper.destroy();\n\t}\n\n\tasync #fetchAccounts(): Promise<ManagedAccount[]> {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst res = await fetch(`${this.#serverOrigin}${DEVSTACK_WALLET_HTTP_PATH.ACCOUNTS}`, {\n\t\t\theaders,\n\t\t});\n\t\tif (res.status === 401 || res.status === 403) throw new AuthError();\n\t\tif (!res.ok) {\n\t\t\tthrow new Error(`Failed to fetch devstack accounts: ${res.statusText}`);\n\t\t}\n\t\tconst { accounts } = (await res.json()) as { accounts: ServerAccountInfo[] };\n\t\treturn accounts.map((info) => {\n\t\t\tconst publicKey = publicKeyForScheme(info.publicKey, info.scheme);\n\t\t\tconst signer = new DevstackProxySigner({\n\t\t\t\taddress: info.address,\n\t\t\t\tpublicKey,\n\t\t\t\tscheme: info.scheme,\n\t\t\t\tserverOrigin: this.#serverOrigin,\n\t\t\t\tauthToken: this.#authToken,\n\t\t\t});\n\t\t\treturn buildManagedAccount(signer, info.address, info.name, DEVSTACK_WALLET_FEATURES);\n\t\t});\n\t}\n}\n\n/**\n * Pull the bearer token off a paired URL produced by the `wallet()`\n * plugin. Returns `null` if the input is undefined, malformed, or\n * carries a `<redacted>` placeholder (the manifest's pairUrl carries\n * the redacted form; the real token lives in a sibling 0o600 file the\n * consumer reads separately).\n *\n * The token rides in the URL fragment as `#token=<hex>`.\n */\nexport function parseDevstackToken(pairedUrl: string | undefined): string | null {\n\tif (pairedUrl === undefined) return null;\n\ttry {\n\t\tconst url = new URL(pairedUrl);\n\t\tconst hash = url.hash; // e.g. \"#token=abcd\"\n\t\tif (hash.length <= 1) return null;\n\t\tconst params = new URLSearchParams(hash.slice(1));\n\t\tconst token = params.get('token');\n\t\tif (token === null || token === '<redacted>') return null;\n\t\treturn token;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** Narrow input — the only field the adapter consumes is\n * `app.wallet.{url, pairUrl}`. Codegen emits exactly this shape so\n * generated `dapp-kit-config.ts` doesn't have to fabricate placeholder\n * manifest fields (`stack.app`, `coins`, etc.) just to satisfy the\n * full `Manifest` type. Mirrors a slice of `AppManifest` from\n * `@mysten-incubation/devstack` without importing it (dev-wallet\n * doesn't depend on devstack — circular). */\nexport interface DevstackAdapterManifest {\n\tapp?: {\n\t\twallet?: {\n\t\t\turl: string;\n\t\t\tpairUrl?: string;\n\t\t};\n\t};\n}\n\n/**\n * Convenience: read the wallet-app endpoint off a devstack manifest and\n * build a configured adapter, or return `null` when the entry isn't\n * present (no `wallet(...)` in the stack, or it hasn't come up yet).\n *\n * The wallet entry's `pairUrl` carries the `#token=…` fragment used to\n * extract the bearer token. The full `Manifest` shape from\n * `@mysten-incubation/devstack` is structurally compatible with\n * {@link DevstackAdapterManifest}, so\n * `createDevstackAdapterFromManifest(devstackManifest)` typechecks\n * without a cast.\n */\nexport function createDevstackAdapterFromManifest(\n\tmanifest: DevstackAdapterManifest,\n): DevstackSignerAdapter | null {\n\tconst wallet = manifest.app?.wallet;\n\tif (wallet === undefined) return null;\n\treturn new DevstackSignerAdapter({\n\t\tserverOrigin: wallet.url,\n\t\ttoken: parseDevstackToken(wallet.pairUrl),\n\t});\n}\n"],"mappings":"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"}
@@ -4,7 +4,6 @@ declare const DEVSTACK_WALLET_HTTP_PATH: {
4
4
  readonly ACCOUNTS: "/api/v1/devstack/accounts";
5
5
  readonly SIGN_TRANSACTION: "/api/v1/devstack/sign-transaction";
6
6
  readonly SIGN_PERSONAL_MESSAGE: "/api/v1/devstack/sign-personal-message";
7
- readonly EXECUTE: "/api/v1/devstack/execute";
8
7
  };
9
8
  type DevstackWalletHttpPathValue = (typeof DEVSTACK_WALLET_HTTP_PATH)[keyof typeof DEVSTACK_WALLET_HTTP_PATH];
10
9
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"devstack-paths.d.mts","names":[],"sources":["../../src/adapters/devstack-paths.ts"],"mappings":";cAMa,yBAAA;EAAA;;;;;;KAQD,2BAAA,WACH,yBAAA,eAAwC,yBAAA"}
1
+ {"version":3,"file":"devstack-paths.d.mts","names":[],"sources":["../../src/adapters/devstack-paths.ts"],"mappings":";cAMa,yBAAA;EAAA;;;;;KAOD,2BAAA,WACH,yBAAA,eAAwC,yBAAyB"}
@@ -3,8 +3,7 @@ const DEVSTACK_WALLET_HTTP_PATH = {
3
3
  HEALTH: "/api/v1/devstack/health",
4
4
  ACCOUNTS: "/api/v1/devstack/accounts",
5
5
  SIGN_TRANSACTION: "/api/v1/devstack/sign-transaction",
6
- SIGN_PERSONAL_MESSAGE: "/api/v1/devstack/sign-personal-message",
7
- EXECUTE: "/api/v1/devstack/execute"
6
+ SIGN_PERSONAL_MESSAGE: "/api/v1/devstack/sign-personal-message"
8
7
  };
9
8
  //#endregion
10
9
  export { DEVSTACK_WALLET_HTTP_PATH };
@@ -1 +1 @@
1
- {"version":3,"file":"devstack-paths.mjs","names":[],"sources":["../../src/adapters/devstack-paths.ts"],"sourcesContent":["// Mirror of `packages/devstack/src/plugins/wallet/protocol.ts` `WalletHttpPath`.\n// Duplicated here rather than imported because devstack already\n// (peer-)depends on `@mysten-incubation/dev-wallet` for codegen-emitted\n// wallet glue, and adding the reverse edge would close the workspace\n// cycle and break turbo's build ordering.\n\nexport const DEVSTACK_WALLET_HTTP_PATH = {\n\tHEALTH: '/api/v1/devstack/health',\n\tACCOUNTS: '/api/v1/devstack/accounts',\n\tSIGN_TRANSACTION: '/api/v1/devstack/sign-transaction',\n\tSIGN_PERSONAL_MESSAGE: '/api/v1/devstack/sign-personal-message',\n\tEXECUTE: '/api/v1/devstack/execute',\n} as const;\n\nexport type DevstackWalletHttpPathValue =\n\t(typeof DEVSTACK_WALLET_HTTP_PATH)[keyof typeof DEVSTACK_WALLET_HTTP_PATH];\n"],"mappings":";AAMA,MAAa,4BAA4B;CACxC,QAAQ;CACR,UAAU;CACV,kBAAkB;CAClB,uBAAuB;CACvB,SAAS;CACT"}
1
+ {"version":3,"file":"devstack-paths.mjs","names":[],"sources":["../../src/adapters/devstack-paths.ts"],"sourcesContent":["// Mirror of `packages/devstack/src/plugins/wallet/protocol.ts` `WalletHttpPath`.\n// Duplicated here rather than imported because devstack already\n// (peer-)depends on `@mysten-incubation/dev-wallet` for codegen-emitted\n// wallet glue, and adding the reverse edge would close the workspace\n// cycle and break turbo's build ordering.\n\nexport const DEVSTACK_WALLET_HTTP_PATH = {\n\tHEALTH: '/api/v1/devstack/health',\n\tACCOUNTS: '/api/v1/devstack/accounts',\n\tSIGN_TRANSACTION: '/api/v1/devstack/sign-transaction',\n\tSIGN_PERSONAL_MESSAGE: '/api/v1/devstack/sign-personal-message',\n} as const;\n\nexport type DevstackWalletHttpPathValue =\n\t(typeof DEVSTACK_WALLET_HTTP_PATH)[keyof typeof DEVSTACK_WALLET_HTTP_PATH];\n"],"mappings":";AAMA,MAAa,4BAA4B;CACxC,QAAQ;CACR,UAAU;CACV,kBAAkB;CAClB,uBAAuB;AACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"fork-relay.d.mts","names":[],"sources":["../../src/adapters/fork-relay.ts"],"mappings":";cASa,oBAAA;EAAA;;;;;;;;;;AAcb;;UAAiB,UAAA;EAAA,SACP,UAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;EAAA;;EAAA,SAGA,QAAA;AAAA;AAKV;;AAAA,UAAiB,qBAAA;EAAA,SACP,OAAA;EAAA,SACA,KAAA;EAAA;;;EAAA,SAIA,MAAA;AAAA;AAAA,UAGO,gBAAA;;;;WAIP,YAAA;EAKe;EAAA,SAHf,KAAA;AAAA;AAAA,cAGJ,kBAAA,SAA2B,KAAA;EAAA,SAEf,MAAA;cAAA,MAAA,UAChB,OAAA;AAAA;;KAQU,eAAA;EAAA,SACE,EAAA;EAAA,SAAmB,KAAA,EAAO,CAAA;AAAA;EAAA,SAC1B,EAAA;EAAA,SAAoB,KAAA;EAAA,SAAwB,MAAA;AAAA;;;;;;;;AA6B1D;;;;cAAa,SAAA;EAAA;cAIA,OAAA,EAAS,gBAAA;EAAA,IAUjB,YAAA,CAAA;EAIE,SAAA,CAAA,GAAa,OAAA,CAAQ,eAAA,CAAgB,UAAA;EAcrC,YAAA,CAAa,UAAA,WAAqB,OAAA,CAAQ,eAAA,CAAgB,UAAA;EAoB1D,iBAAA,CAAkB,KAAA,WAAgB,OAAA,CAAQ,eAAA,CAAgB,UAAA;EAoB1D,kBAAA,CAAA,GAAsB,OAAA,CAAQ,eAAA,CAAgB,qBAAA;EApBZ;;;EAoClC,gBAAA,CACL,OAAA,UACA,MAAA,YACE,OAAA,CAAQ,eAAA,CAAgB,qBAAA;AAAA;;;;;UAyEX,iBAAA;EAAA,SACP,GAAA;IAAA,SACC,MAAA;MAAA,SACC,GAAA;MAAA,SACA,OAAA;IAAA;EAAA;EAAA,SAGF,IAAA;IA3IH;;IAAA,SA8II,OAAA;IA9IsC;;IAAA,SAiJtC,QAAA;EAAA;AAAA;;;;;;;;;iBAkCK,2BAAA,CAA4B,QAAA,EAAU,iBAAA,GAAoB,SAAA"}
1
+ {"version":3,"file":"fork-relay.d.mts","names":[],"sources":["../../src/adapters/fork-relay.ts"],"mappings":";cASa,oBAAA;EAAA;;;;;;;;;;AAcb;;UAAiB,UAAA;EAAA,SACP,UAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;EAAA;;EAAA,SAGA,QAAA;AAAA;AAKV;;AAAA,UAAiB,qBAAA;EAAA,SACP,OAAA;EAAA,SACA,KAAA;EAAA;;;EAAA,SAIA,MAAA;AAAA;AAAA,UAGO,gBAAA;;;AAMF;WAFL,YAAA;EAKe;EAAA,SAHf,KAAK;AAAA;AAAA,cAGT,kBAAA,SAA2B,KAAK;EAAA,SAEpB,MAAA;cAAA,MAAA,UAChB,OAAA;AAAA;;KAQU,eAAA;EAAA,SACE,EAAA;EAAA,SAAmB,KAAA,EAAO,CAAC;AAAA;EAAA,SAC3B,EAAA;EAAA,SAAoB,KAAA;EAAA,SAAwB,MAAA;AAAA;;;;;;;AAAM;AA6BhE;;;;cAAa,SAAA;EAAA;cAIA,OAAA,EAAS,gBAAA;EAAA,IAUjB,YAAA;EAIE,SAAA,IAAa,OAAA,CAAQ,eAAA,CAAgB,UAAA;EAcrC,YAAA,CAAa,UAAA,WAAqB,OAAA,CAAQ,eAAA,CAAgB,UAAA;EAoB1D,iBAAA,CAAkB,KAAA,WAAgB,OAAA,CAAQ,eAAA,CAAgB,UAAA;EAoB1D,kBAAA,IAAsB,OAAA,CAAQ,eAAA,CAAgB,qBAAA;EApBZ;;;EAoClC,gBAAA,CACL,OAAA,UACA,MAAA,YACE,OAAA,CAAQ,eAAA,CAAgB,qBAAA;AAAA;;;;;UAyEX,iBAAA;EAAA,SACP,GAAA;IAAA,SACC,MAAA;MAAA,SACC,GAAA;MAAA,SACA,OAAA;IAAA;EAAA;EAAA,SAGF,IAAA;IA3IH;;IAAA,SA8II,OAAA;IA9IsC;;IAAA,SAiJtC,QAAA;EAAA;AAAA;;;;;;;;;iBAkCK,2BAAA,CAA4B,QAAA,EAAU,iBAAA,GAAoB,SAAS"}
@@ -1 +1 @@
1
- {"version":3,"file":"fork-relay.mjs","names":["#serverOrigin","#authToken","#request"],"sources":["../../src/adapters/fork-relay.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n//\n// Browser-side relay for sui-fork admin RPCs. A compatible devstack\n// wallet endpoint can proxy a curated subset of the fork-control surface\n// (status read, advance-clock, advance-checkpoint, impersonation slot\n// list) over HTTP so the fork panel does not have to ship a gRPC\n// client into the browser bundle.\n\nexport const FORK_RELAY_HTTP_PATH = {\n\tSTATUS: '/api/v1/devstack/fork/status',\n\tADVANCE_CLOCK: '/api/v1/devstack/fork/advance-clock',\n\tADVANCE_CHECKPOINT: '/api/v1/devstack/fork/advance-checkpoint',\n\tIMPERSONATIONS: '/api/v1/devstack/fork/impersonations',\n} as const;\n\n/** Snapshot of the fork's current head state.\n *\n * Mirrors the body of `ForkControl.getStatus()` minus the unused\n * heartbeat fields. `clockMs` is a Unix-ms timestamp (the value\n * `clock::timestamp_ms()` returns on chain); `checkpoint` is the\n * latest sealed sequence number.\n */\nexport interface ForkStatus {\n\treadonly checkpoint: bigint;\n\treadonly clockMs: bigint;\n\treadonly autoTickMs?: number;\n\t/** Best-effort label of the upstream the fork is pointed at, e.g.\n\t * `'mainnet'` or `'testnet'`. Sourced from the devstack manifest. */\n\treadonly upstream?: string;\n}\n\n/** A single impersonation slot resolved by devstack — typically every\n * address that was passed to `Sui({fork:{impersonate:[…]}})`. */\nexport interface ForkImpersonationSlot {\n\treadonly address: string;\n\treadonly label?: string;\n\t/** Whether the wallet currently routes user-driven tx signing through\n\t * the `executeImpersonated` path for this address. The dev-wallet\n\t * server stores the toggle so it persists across page reloads. */\n\treadonly active: boolean;\n}\n\nexport interface ForkRelayOptions {\n\t/** Wallet-app origin (e.g. `http://localhost:9420`). Same value\n\t * `DevstackSignerAdapter` consumes — read from the manifest entry's\n\t * `app.wallet.url`. */\n\treadonly serverOrigin: string;\n\t/** Bearer token. Same parsing rules as `DevstackSignerAdapter`. */\n\treadonly token?: string | null;\n}\n\nclass ForkRelayHttpError extends Error {\n\tconstructor(\n\t\tpublic readonly status: number,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'ForkRelayHttpError';\n\t}\n}\n\n/** Tagged result so callers can render an inline error without throwing. */\nexport type ForkRelayResult<T> =\n\t| { readonly ok: true; readonly value: T }\n\t| { readonly ok: false; readonly error: string; readonly status?: number };\n\nfunction isForkStatusBody(\n\tvalue: unknown,\n): value is { checkpoint: string; clockMs: string; autoTickMs?: number; upstream?: string } {\n\tif (value === null || typeof value !== 'object') return false;\n\tconst v = value as Record<string, unknown>;\n\treturn typeof v.checkpoint === 'string' && typeof v.clockMs === 'string';\n}\n\nfunction isImpersonationsBody(\n\tvalue: unknown,\n): value is { slots: { address: string; label?: string; active: boolean }[] } {\n\tif (value === null || typeof value !== 'object') return false;\n\tconst slots = (value as { slots?: unknown }).slots;\n\treturn Array.isArray(slots);\n}\n\n/**\n * Thin HTTP client for the fork admin relay. Stateless — each call\n * issues a fresh `fetch`. The UI layer (`dev-wallet-fork-panel`)\n * polls `getStatus` on a low cadence and only refreshes after action\n * verbs land, so the lack of caching here is intentional.\n *\n * @example\n * const relay = new ForkRelay({ serverOrigin, token });\n * const status = await relay.getStatus();\n * if (status.ok) console.log(`clock=${status.value.clockMs}ms`);\n */\nexport class ForkRelay {\n\t#serverOrigin: string;\n\t#authToken: string | null;\n\n\tconstructor(options: ForkRelayOptions) {\n\t\ttry {\n\t\t\tnew URL(options.serverOrigin);\n\t\t} catch {\n\t\t\tthrow new Error(`ForkRelay: invalid serverOrigin \"${options.serverOrigin}\"`);\n\t\t}\n\t\tthis.#serverOrigin = options.serverOrigin;\n\t\tthis.#authToken = options.token ?? null;\n\t}\n\n\tget serverOrigin(): string {\n\t\treturn this.#serverOrigin;\n\t}\n\n\tasync getStatus(): Promise<ForkRelayResult<ForkStatus>> {\n\t\treturn this.#request('GET', FORK_RELAY_HTTP_PATH.STATUS, undefined, (body) => {\n\t\t\tif (!isForkStatusBody(body)) {\n\t\t\t\tthrow new Error('Malformed fork status response');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcheckpoint: BigInt(body.checkpoint),\n\t\t\t\tclockMs: BigInt(body.clockMs),\n\t\t\t\tautoTickMs: body.autoTickMs,\n\t\t\t\tupstream: body.upstream,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync advanceClock(durationMs: number): Promise<ForkRelayResult<ForkStatus>> {\n\t\tif (!Number.isFinite(durationMs) || durationMs <= 0 || !Number.isInteger(durationMs)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `advanceClock: durationMs must be a positive integer (got ${durationMs})`,\n\t\t\t};\n\t\t}\n\t\treturn this.#request('POST', FORK_RELAY_HTTP_PATH.ADVANCE_CLOCK, { durationMs }, (body) => {\n\t\t\tif (!isForkStatusBody(body)) {\n\t\t\t\tthrow new Error('Malformed advance-clock response');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcheckpoint: BigInt(body.checkpoint),\n\t\t\t\tclockMs: BigInt(body.clockMs),\n\t\t\t\tautoTickMs: body.autoTickMs,\n\t\t\t\tupstream: body.upstream,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync advanceCheckpoint(count: number): Promise<ForkRelayResult<ForkStatus>> {\n\t\tif (!Number.isFinite(count) || count <= 0 || !Number.isInteger(count)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `advanceCheckpoint: count must be a positive integer (got ${count})`,\n\t\t\t};\n\t\t}\n\t\treturn this.#request('POST', FORK_RELAY_HTTP_PATH.ADVANCE_CHECKPOINT, { count }, (body) => {\n\t\t\tif (!isForkStatusBody(body)) {\n\t\t\t\tthrow new Error('Malformed advance-checkpoint response');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcheckpoint: BigInt(body.checkpoint),\n\t\t\t\tclockMs: BigInt(body.clockMs),\n\t\t\t\tautoTickMs: body.autoTickMs,\n\t\t\t\tupstream: body.upstream,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync listImpersonations(): Promise<ForkRelayResult<ForkImpersonationSlot[]>> {\n\t\treturn this.#request('GET', FORK_RELAY_HTTP_PATH.IMPERSONATIONS, undefined, (body) => {\n\t\t\tif (!isImpersonationsBody(body)) {\n\t\t\t\tthrow new Error('Malformed impersonations response');\n\t\t\t}\n\t\t\treturn body.slots.map((s) => ({\n\t\t\t\taddress: s.address,\n\t\t\t\tlabel: s.label,\n\t\t\t\tactive: s.active,\n\t\t\t}));\n\t\t});\n\t}\n\n\t/** Toggle the impersonation slot identified by `address`. The server\n\t * is the source of truth — the response carries the resulting slot\n\t * list so the panel re-renders consistently. */\n\tasync setImpersonation(\n\t\taddress: string,\n\t\tactive: boolean,\n\t): Promise<ForkRelayResult<ForkImpersonationSlot[]>> {\n\t\treturn this.#request(\n\t\t\t'POST',\n\t\t\tFORK_RELAY_HTTP_PATH.IMPERSONATIONS,\n\t\t\t{ address, active },\n\t\t\t(body) => {\n\t\t\t\tif (!isImpersonationsBody(body)) {\n\t\t\t\t\tthrow new Error('Malformed impersonations response');\n\t\t\t\t}\n\t\t\t\treturn body.slots.map((s) => ({\n\t\t\t\t\taddress: s.address,\n\t\t\t\t\tlabel: s.label,\n\t\t\t\t\tactive: s.active,\n\t\t\t\t}));\n\t\t\t},\n\t\t);\n\t}\n\n\tasync #request<T>(\n\t\tmethod: 'GET' | 'POST',\n\t\tpath: string,\n\t\tbody: unknown,\n\t\tparse: (raw: unknown) => T,\n\t): Promise<ForkRelayResult<T>> {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst init: RequestInit = { method, headers };\n\t\tif (method === 'POST' && body !== undefined) {\n\t\t\tinit.body = JSON.stringify(body);\n\t\t}\n\t\tlet res: Response;\n\t\ttry {\n\t\t\tres = await fetch(`${this.#serverOrigin}${path}`, init);\n\t\t} catch (cause) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `Network error: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t};\n\t\t}\n\t\tif (!res.ok) {\n\t\t\tconst text = await res.text().catch(() => res.statusText);\n\t\t\treturn { ok: false, error: text || res.statusText, status: res.status };\n\t\t}\n\t\tlet parsedBody: unknown;\n\t\ttry {\n\t\t\tparsedBody = await res.json();\n\t\t} catch (cause) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `Invalid JSON response: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t\tstatus: res.status,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\treturn { ok: true, value: parse(parsedBody) };\n\t\t} catch (cause) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: cause instanceof Error ? cause.message : String(cause),\n\t\t\t\tstatus: res.status,\n\t\t\t};\n\t\t}\n\t}\n}\n\nexport { ForkRelayHttpError };\n\n/** Narrow input mirroring `DevstackAdapterManifest` — enough to\n * discover the wallet endpoint + fork-mode flag without pulling in\n * the full devstack `Manifest` type (no reverse dependency edge,\n * same reasoning as `devstack-adapter.ts`). */\nexport interface ForkRelayManifest {\n\treadonly app?: {\n\t\treadonly wallet?: {\n\t\t\treadonly url: string;\n\t\t\treadonly pairUrl?: string;\n\t\t};\n\t};\n\treadonly meta?: {\n\t\t/** Devstack's `meta.runtime` is `'bundled' | 'forked'`. Only\n\t\t * `'forked'` triggers fork-controls construction. */\n\t\treadonly runtime?: string;\n\t\t/** Optional upstream label (`'mainnet'`, `'testnet'`, …) used\n\t\t * by the panel banner. */\n\t\treadonly upstream?: string;\n\t};\n}\n\n/** Parse the bearer token off the manifest's `pairUrl`. Duplicates the\n * logic in `devstack-adapter.ts` rather than importing it because the\n * fork-relay module must remain dependency-free from the adapter\n * layer (it's also consumed by codegen-emitted glue that doesn't pull\n * in the signer adapter bundle). */\nfunction tokenFromPairUrl(pairedUrl: string | undefined): string | null {\n\tif (pairedUrl === undefined) return null;\n\ttry {\n\t\tconst url = new URL(pairedUrl);\n\t\tif (url.hash.length > 1) {\n\t\t\tconst params = new URLSearchParams(url.hash.slice(1));\n\t\t\tconst fromHash = params.get('token');\n\t\t\tif (fromHash !== null && fromHash !== '<redacted>') return fromHash;\n\t\t}\n\t\tconst fromQuery = url.searchParams.get('token');\n\t\tif (fromQuery !== null && fromQuery !== '<redacted>') return fromQuery;\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Build a configured {@link ForkRelay} from a devstack manifest, or\n * `null` when fork-mode isn't active (bundled stack, no wallet entry,\n * or the manifest hasn't loaded yet).\n *\n * Codegen-emitted browser glue calls this and forwards the result to\n * `<dev-wallet-panel forkRelay={…}>`.\n */\nexport function createForkRelayFromManifest(manifest: ForkRelayManifest): ForkRelay | null {\n\tif (manifest.meta?.runtime !== 'forked') return null;\n\tconst wallet = manifest.app?.wallet;\n\tif (wallet === undefined) return null;\n\ttry {\n\t\treturn new ForkRelay({\n\t\t\tserverOrigin: wallet.url,\n\t\t\ttoken: tokenFromPairUrl(wallet.pairUrl),\n\t\t});\n\t} catch {\n\t\t// `new URL(…)` failure surfaces as a thrown Error — swallow it\n\t\t// here rather than propagating, the calling app shouldn't\n\t\t// blow up just because the manifest's wallet URL is malformed.\n\t\treturn null;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fork-relay.mjs","names":["#serverOrigin","#authToken","#request"],"sources":["../../src/adapters/fork-relay.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n//\n// Browser-side relay for sui-fork admin RPCs. A compatible devstack\n// wallet endpoint can proxy a curated subset of the fork-control surface\n// (status read, advance-clock, advance-checkpoint, impersonation slot\n// list) over HTTP so the fork panel does not have to ship a gRPC\n// client into the browser bundle.\n\nexport const FORK_RELAY_HTTP_PATH = {\n\tSTATUS: '/api/v1/devstack/fork/status',\n\tADVANCE_CLOCK: '/api/v1/devstack/fork/advance-clock',\n\tADVANCE_CHECKPOINT: '/api/v1/devstack/fork/advance-checkpoint',\n\tIMPERSONATIONS: '/api/v1/devstack/fork/impersonations',\n} as const;\n\n/** Snapshot of the fork's current head state.\n *\n * Mirrors the body of `ForkControl.getStatus()` minus the unused\n * heartbeat fields. `clockMs` is a Unix-ms timestamp (the value\n * `clock::timestamp_ms()` returns on chain); `checkpoint` is the\n * latest sealed sequence number.\n */\nexport interface ForkStatus {\n\treadonly checkpoint: bigint;\n\treadonly clockMs: bigint;\n\treadonly autoTickMs?: number;\n\t/** Best-effort label of the upstream the fork is pointed at, e.g.\n\t * `'mainnet'` or `'testnet'`. Sourced from the devstack manifest. */\n\treadonly upstream?: string;\n}\n\n/** A single impersonation slot resolved by devstack — typically every\n * address that was passed to `Sui({fork:{impersonate:[…]}})`. */\nexport interface ForkImpersonationSlot {\n\treadonly address: string;\n\treadonly label?: string;\n\t/** Whether the wallet currently routes user-driven tx signing through\n\t * the `executeImpersonated` path for this address. The dev-wallet\n\t * server stores the toggle so it persists across page reloads. */\n\treadonly active: boolean;\n}\n\nexport interface ForkRelayOptions {\n\t/** Wallet-app origin (e.g. `http://localhost:9420`). Same value\n\t * `DevstackSignerAdapter` consumes — read from the manifest entry's\n\t * `app.wallet.url`. */\n\treadonly serverOrigin: string;\n\t/** Bearer token. Same parsing rules as `DevstackSignerAdapter`. */\n\treadonly token?: string | null;\n}\n\nclass ForkRelayHttpError extends Error {\n\tconstructor(\n\t\tpublic readonly status: number,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'ForkRelayHttpError';\n\t}\n}\n\n/** Tagged result so callers can render an inline error without throwing. */\nexport type ForkRelayResult<T> =\n\t| { readonly ok: true; readonly value: T }\n\t| { readonly ok: false; readonly error: string; readonly status?: number };\n\nfunction isForkStatusBody(\n\tvalue: unknown,\n): value is { checkpoint: string; clockMs: string; autoTickMs?: number; upstream?: string } {\n\tif (value === null || typeof value !== 'object') return false;\n\tconst v = value as Record<string, unknown>;\n\treturn typeof v.checkpoint === 'string' && typeof v.clockMs === 'string';\n}\n\nfunction isImpersonationsBody(\n\tvalue: unknown,\n): value is { slots: { address: string; label?: string; active: boolean }[] } {\n\tif (value === null || typeof value !== 'object') return false;\n\tconst slots = (value as { slots?: unknown }).slots;\n\treturn Array.isArray(slots);\n}\n\n/**\n * Thin HTTP client for the fork admin relay. Stateless — each call\n * issues a fresh `fetch`. The UI layer (`dev-wallet-fork-panel`)\n * polls `getStatus` on a low cadence and only refreshes after action\n * verbs land, so the lack of caching here is intentional.\n *\n * @example\n * const relay = new ForkRelay({ serverOrigin, token });\n * const status = await relay.getStatus();\n * if (status.ok) console.log(`clock=${status.value.clockMs}ms`);\n */\nexport class ForkRelay {\n\t#serverOrigin: string;\n\t#authToken: string | null;\n\n\tconstructor(options: ForkRelayOptions) {\n\t\ttry {\n\t\t\tnew URL(options.serverOrigin);\n\t\t} catch {\n\t\t\tthrow new Error(`ForkRelay: invalid serverOrigin \"${options.serverOrigin}\"`);\n\t\t}\n\t\tthis.#serverOrigin = options.serverOrigin;\n\t\tthis.#authToken = options.token ?? null;\n\t}\n\n\tget serverOrigin(): string {\n\t\treturn this.#serverOrigin;\n\t}\n\n\tasync getStatus(): Promise<ForkRelayResult<ForkStatus>> {\n\t\treturn this.#request('GET', FORK_RELAY_HTTP_PATH.STATUS, undefined, (body) => {\n\t\t\tif (!isForkStatusBody(body)) {\n\t\t\t\tthrow new Error('Malformed fork status response');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcheckpoint: BigInt(body.checkpoint),\n\t\t\t\tclockMs: BigInt(body.clockMs),\n\t\t\t\tautoTickMs: body.autoTickMs,\n\t\t\t\tupstream: body.upstream,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync advanceClock(durationMs: number): Promise<ForkRelayResult<ForkStatus>> {\n\t\tif (!Number.isFinite(durationMs) || durationMs <= 0 || !Number.isInteger(durationMs)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `advanceClock: durationMs must be a positive integer (got ${durationMs})`,\n\t\t\t};\n\t\t}\n\t\treturn this.#request('POST', FORK_RELAY_HTTP_PATH.ADVANCE_CLOCK, { durationMs }, (body) => {\n\t\t\tif (!isForkStatusBody(body)) {\n\t\t\t\tthrow new Error('Malformed advance-clock response');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcheckpoint: BigInt(body.checkpoint),\n\t\t\t\tclockMs: BigInt(body.clockMs),\n\t\t\t\tautoTickMs: body.autoTickMs,\n\t\t\t\tupstream: body.upstream,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync advanceCheckpoint(count: number): Promise<ForkRelayResult<ForkStatus>> {\n\t\tif (!Number.isFinite(count) || count <= 0 || !Number.isInteger(count)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `advanceCheckpoint: count must be a positive integer (got ${count})`,\n\t\t\t};\n\t\t}\n\t\treturn this.#request('POST', FORK_RELAY_HTTP_PATH.ADVANCE_CHECKPOINT, { count }, (body) => {\n\t\t\tif (!isForkStatusBody(body)) {\n\t\t\t\tthrow new Error('Malformed advance-checkpoint response');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcheckpoint: BigInt(body.checkpoint),\n\t\t\t\tclockMs: BigInt(body.clockMs),\n\t\t\t\tautoTickMs: body.autoTickMs,\n\t\t\t\tupstream: body.upstream,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync listImpersonations(): Promise<ForkRelayResult<ForkImpersonationSlot[]>> {\n\t\treturn this.#request('GET', FORK_RELAY_HTTP_PATH.IMPERSONATIONS, undefined, (body) => {\n\t\t\tif (!isImpersonationsBody(body)) {\n\t\t\t\tthrow new Error('Malformed impersonations response');\n\t\t\t}\n\t\t\treturn body.slots.map((s) => ({\n\t\t\t\taddress: s.address,\n\t\t\t\tlabel: s.label,\n\t\t\t\tactive: s.active,\n\t\t\t}));\n\t\t});\n\t}\n\n\t/** Toggle the impersonation slot identified by `address`. The server\n\t * is the source of truth — the response carries the resulting slot\n\t * list so the panel re-renders consistently. */\n\tasync setImpersonation(\n\t\taddress: string,\n\t\tactive: boolean,\n\t): Promise<ForkRelayResult<ForkImpersonationSlot[]>> {\n\t\treturn this.#request(\n\t\t\t'POST',\n\t\t\tFORK_RELAY_HTTP_PATH.IMPERSONATIONS,\n\t\t\t{ address, active },\n\t\t\t(body) => {\n\t\t\t\tif (!isImpersonationsBody(body)) {\n\t\t\t\t\tthrow new Error('Malformed impersonations response');\n\t\t\t\t}\n\t\t\t\treturn body.slots.map((s) => ({\n\t\t\t\t\taddress: s.address,\n\t\t\t\t\tlabel: s.label,\n\t\t\t\t\tactive: s.active,\n\t\t\t\t}));\n\t\t\t},\n\t\t);\n\t}\n\n\tasync #request<T>(\n\t\tmethod: 'GET' | 'POST',\n\t\tpath: string,\n\t\tbody: unknown,\n\t\tparse: (raw: unknown) => T,\n\t): Promise<ForkRelayResult<T>> {\n\t\tconst headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (this.#authToken !== null) {\n\t\t\theaders['Authorization'] = `Bearer ${this.#authToken}`;\n\t\t}\n\t\tconst init: RequestInit = { method, headers };\n\t\tif (method === 'POST' && body !== undefined) {\n\t\t\tinit.body = JSON.stringify(body);\n\t\t}\n\t\tlet res: Response;\n\t\ttry {\n\t\t\tres = await fetch(`${this.#serverOrigin}${path}`, init);\n\t\t} catch (cause) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `Network error: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t};\n\t\t}\n\t\tif (!res.ok) {\n\t\t\tconst text = await res.text().catch(() => res.statusText);\n\t\t\treturn { ok: false, error: text || res.statusText, status: res.status };\n\t\t}\n\t\tlet parsedBody: unknown;\n\t\ttry {\n\t\t\tparsedBody = await res.json();\n\t\t} catch (cause) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `Invalid JSON response: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t\tstatus: res.status,\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\treturn { ok: true, value: parse(parsedBody) };\n\t\t} catch (cause) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: cause instanceof Error ? cause.message : String(cause),\n\t\t\t\tstatus: res.status,\n\t\t\t};\n\t\t}\n\t}\n}\n\nexport { ForkRelayHttpError };\n\n/** Narrow input mirroring `DevstackAdapterManifest` — enough to\n * discover the wallet endpoint + fork-mode flag without pulling in\n * the full devstack `Manifest` type (no reverse dependency edge,\n * same reasoning as `devstack-adapter.ts`). */\nexport interface ForkRelayManifest {\n\treadonly app?: {\n\t\treadonly wallet?: {\n\t\t\treadonly url: string;\n\t\t\treadonly pairUrl?: string;\n\t\t};\n\t};\n\treadonly meta?: {\n\t\t/** Devstack's `meta.runtime` is `'bundled' | 'forked'`. Only\n\t\t * `'forked'` triggers fork-controls construction. */\n\t\treadonly runtime?: string;\n\t\t/** Optional upstream label (`'mainnet'`, `'testnet'`, …) used\n\t\t * by the panel banner. */\n\t\treadonly upstream?: string;\n\t};\n}\n\n/** Parse the bearer token off the manifest's `pairUrl`. Duplicates the\n * logic in `devstack-adapter.ts` rather than importing it because the\n * fork-relay module must remain dependency-free from the adapter\n * layer (it's also consumed by codegen-emitted glue that doesn't pull\n * in the signer adapter bundle). */\nfunction tokenFromPairUrl(pairedUrl: string | undefined): string | null {\n\tif (pairedUrl === undefined) return null;\n\ttry {\n\t\tconst url = new URL(pairedUrl);\n\t\tif (url.hash.length > 1) {\n\t\t\tconst params = new URLSearchParams(url.hash.slice(1));\n\t\t\tconst fromHash = params.get('token');\n\t\t\tif (fromHash !== null && fromHash !== '<redacted>') return fromHash;\n\t\t}\n\t\tconst fromQuery = url.searchParams.get('token');\n\t\tif (fromQuery !== null && fromQuery !== '<redacted>') return fromQuery;\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Build a configured {@link ForkRelay} from a devstack manifest, or\n * `null` when fork-mode isn't active (bundled stack, no wallet entry,\n * or the manifest hasn't loaded yet).\n *\n * Codegen-emitted browser glue calls this and forwards the result to\n * `<dev-wallet-panel forkRelay={…}>`.\n */\nexport function createForkRelayFromManifest(manifest: ForkRelayManifest): ForkRelay | null {\n\tif (manifest.meta?.runtime !== 'forked') return null;\n\tconst wallet = manifest.app?.wallet;\n\tif (wallet === undefined) return null;\n\ttry {\n\t\treturn new ForkRelay({\n\t\t\tserverOrigin: wallet.url,\n\t\t\ttoken: tokenFromPairUrl(wallet.pairUrl),\n\t\t});\n\t} catch {\n\t\t// `new URL(…)` failure surfaces as a thrown Error — swallow it\n\t\t// here rather than propagating, the calling app shouldn't\n\t\t// blow up just because the manifest's wallet URL is malformed.\n\t\treturn null;\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"idb-store.mjs","names":["#dbName","#storeName","#withTx","#open","#db"],"sources":["../../src/adapters/idb-store.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Minimal IndexedDB key-value store replacing the `idb-keyval` package.\n *\n * The database connection is opened lazily on first use and reused for all\n * subsequent operations.\n */\nexport class IDBStore {\n\t#dbName: string;\n\t#storeName: string;\n\t#db: Promise<IDBDatabase> | null = null;\n\n\tconstructor(dbName: string, storeName: string) {\n\t\tthis.#dbName = dbName;\n\t\tthis.#storeName = storeName;\n\t}\n\n\tget<T>(key: IDBValidKey): Promise<T | undefined> {\n\t\treturn this.#withTx('readonly', (s) => s.get(key) as IDBRequest<T | undefined>);\n\t}\n\n\tasync set(key: IDBValidKey, value: unknown): Promise<void> {\n\t\tawait this.#withTx('readwrite', (s) => s.put(value, key));\n\t}\n\n\tdel(key: IDBValidKey): Promise<void> {\n\t\treturn this.#withTx('readwrite', (s) => s.delete(key) as IDBRequest<void>);\n\t}\n\n\tentries<K extends IDBValidKey, V>(): Promise<[K, V][]> {\n\t\treturn this.#open().then(\n\t\t\t(db) =>\n\t\t\t\tnew Promise((resolve, reject) => {\n\t\t\t\t\tconst tx = db.transaction(this.#storeName, 'readonly');\n\t\t\t\t\tconst objectStore = tx.objectStore(this.#storeName);\n\t\t\t\t\tconst results: [K, V][] = [];\n\t\t\t\t\tconst cursor = objectStore.openCursor();\n\t\t\t\t\tcursor.onsuccess = () => {\n\t\t\t\t\t\tconst c = cursor.result;\n\t\t\t\t\t\tif (c) {\n\t\t\t\t\t\t\tresults.push([c.key as K, c.value as V]);\n\t\t\t\t\t\t\tc.continue();\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\ttx.oncomplete = () => resolve(results);\n\t\t\t\t\ttx.onerror = () => reject(tx.error);\n\t\t\t\t}),\n\t\t);\n\t}\n\n\t#open(): Promise<IDBDatabase> {\n\t\tif (!this.#db) {\n\t\t\tthis.#db = new Promise((resolve, reject) => {\n\t\t\t\tconst request = indexedDB.open(this.#dbName);\n\t\t\t\trequest.onupgradeneeded = () => {\n\t\t\t\t\tif (!request.result.objectStoreNames.contains(this.#storeName)) {\n\t\t\t\t\t\trequest.result.createObjectStore(this.#storeName);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\trequest.onsuccess = () => resolve(request.result);\n\t\t\t\trequest.onerror = () => {\n\t\t\t\t\tthis.#db = null;\n\t\t\t\t\treject(request.error);\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\t\treturn this.#db;\n\t}\n\n\t#withTx<T>(\n\t\tmode: IDBTransactionMode,\n\t\tfn: (objectStore: IDBObjectStore) => IDBRequest<T>,\n\t): Promise<T> {\n\t\treturn this.#open().then(\n\t\t\t(db) =>\n\t\t\t\tnew Promise((resolve, reject) => {\n\t\t\t\t\tconst tx = db.transaction(this.#storeName, mode);\n\t\t\t\t\tconst req = fn(tx.objectStore(this.#storeName));\n\t\t\t\t\ttx.oncomplete = () => resolve(req.result);\n\t\t\t\t\ttx.onerror = () => reject(tx.error);\n\t\t\t\t\ttx.onabort = () => reject(tx.error);\n\t\t\t\t}),\n\t\t);\n\t}\n}\n"],"mappings":";;;;;;;AASA,IAAa,WAAb,MAAsB;CACrB;CACA;CACA,MAAmC;CAEnC,YAAY,QAAgB,WAAmB;AAC9C,QAAA,SAAe;AACf,QAAA,YAAkB;;CAGnB,IAAO,KAA0C;AAChD,SAAO,MAAA,OAAa,aAAa,MAAM,EAAE,IAAI,IAAI,CAA8B;;CAGhF,MAAM,IAAI,KAAkB,OAA+B;AAC1D,QAAM,MAAA,OAAa,cAAc,MAAM,EAAE,IAAI,OAAO,IAAI,CAAC;;CAG1D,IAAI,KAAiC;AACpC,SAAO,MAAA,OAAa,cAAc,MAAM,EAAE,OAAO,IAAI,CAAqB;;CAG3E,UAAuD;AACtD,SAAO,MAAA,MAAY,CAAC,MAClB,OACA,IAAI,SAAS,SAAS,WAAW;GAChC,MAAM,KAAK,GAAG,YAAY,MAAA,WAAiB,WAAW;GACtD,MAAM,cAAc,GAAG,YAAY,MAAA,UAAgB;GACnD,MAAM,UAAoB,EAAE;GAC5B,MAAM,SAAS,YAAY,YAAY;AACvC,UAAO,kBAAkB;IACxB,MAAM,IAAI,OAAO;AACjB,QAAI,GAAG;AACN,aAAQ,KAAK,CAAC,EAAE,KAAU,EAAE,MAAW,CAAC;AACxC,OAAE,UAAU;;;AAGd,MAAG,mBAAmB,QAAQ,QAAQ;AACtC,MAAG,gBAAgB,OAAO,GAAG,MAAM;IAClC,CACH;;CAGF,QAA8B;AAC7B,MAAI,CAAC,MAAA,GACJ,OAAA,KAAW,IAAI,SAAS,SAAS,WAAW;GAC3C,MAAM,UAAU,UAAU,KAAK,MAAA,OAAa;AAC5C,WAAQ,wBAAwB;AAC/B,QAAI,CAAC,QAAQ,OAAO,iBAAiB,SAAS,MAAA,UAAgB,CAC7D,SAAQ,OAAO,kBAAkB,MAAA,UAAgB;;AAGnD,WAAQ,kBAAkB,QAAQ,QAAQ,OAAO;AACjD,WAAQ,gBAAgB;AACvB,UAAA,KAAW;AACX,WAAO,QAAQ,MAAM;;IAErB;AAEH,SAAO,MAAA;;CAGR,QACC,MACA,IACa;AACb,SAAO,MAAA,MAAY,CAAC,MAClB,OACA,IAAI,SAAS,SAAS,WAAW;GAChC,MAAM,KAAK,GAAG,YAAY,MAAA,WAAiB,KAAK;GAChD,MAAM,MAAM,GAAG,GAAG,YAAY,MAAA,UAAgB,CAAC;AAC/C,MAAG,mBAAmB,QAAQ,IAAI,OAAO;AACzC,MAAG,gBAAgB,OAAO,GAAG,MAAM;AACnC,MAAG,gBAAgB,OAAO,GAAG,MAAM;IAClC,CACH"}
1
+ {"version":3,"file":"idb-store.mjs","names":["#dbName","#storeName","#withTx","#open","#db"],"sources":["../../src/adapters/idb-store.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Minimal IndexedDB key-value store replacing the `idb-keyval` package.\n *\n * The database connection is opened lazily on first use and reused for all\n * subsequent operations.\n */\nexport class IDBStore {\n\t#dbName: string;\n\t#storeName: string;\n\t#db: Promise<IDBDatabase> | null = null;\n\n\tconstructor(dbName: string, storeName: string) {\n\t\tthis.#dbName = dbName;\n\t\tthis.#storeName = storeName;\n\t}\n\n\tget<T>(key: IDBValidKey): Promise<T | undefined> {\n\t\treturn this.#withTx('readonly', (s) => s.get(key) as IDBRequest<T | undefined>);\n\t}\n\n\tasync set(key: IDBValidKey, value: unknown): Promise<void> {\n\t\tawait this.#withTx('readwrite', (s) => s.put(value, key));\n\t}\n\n\tdel(key: IDBValidKey): Promise<void> {\n\t\treturn this.#withTx('readwrite', (s) => s.delete(key) as IDBRequest<void>);\n\t}\n\n\tentries<K extends IDBValidKey, V>(): Promise<[K, V][]> {\n\t\treturn this.#open().then(\n\t\t\t(db) =>\n\t\t\t\tnew Promise((resolve, reject) => {\n\t\t\t\t\tconst tx = db.transaction(this.#storeName, 'readonly');\n\t\t\t\t\tconst objectStore = tx.objectStore(this.#storeName);\n\t\t\t\t\tconst results: [K, V][] = [];\n\t\t\t\t\tconst cursor = objectStore.openCursor();\n\t\t\t\t\tcursor.onsuccess = () => {\n\t\t\t\t\t\tconst c = cursor.result;\n\t\t\t\t\t\tif (c) {\n\t\t\t\t\t\t\tresults.push([c.key as K, c.value as V]);\n\t\t\t\t\t\t\tc.continue();\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\ttx.oncomplete = () => resolve(results);\n\t\t\t\t\ttx.onerror = () => reject(tx.error);\n\t\t\t\t}),\n\t\t);\n\t}\n\n\t#open(): Promise<IDBDatabase> {\n\t\tif (!this.#db) {\n\t\t\tthis.#db = new Promise((resolve, reject) => {\n\t\t\t\tconst request = indexedDB.open(this.#dbName);\n\t\t\t\trequest.onupgradeneeded = () => {\n\t\t\t\t\tif (!request.result.objectStoreNames.contains(this.#storeName)) {\n\t\t\t\t\t\trequest.result.createObjectStore(this.#storeName);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\trequest.onsuccess = () => resolve(request.result);\n\t\t\t\trequest.onerror = () => {\n\t\t\t\t\tthis.#db = null;\n\t\t\t\t\treject(request.error);\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\t\treturn this.#db;\n\t}\n\n\t#withTx<T>(\n\t\tmode: IDBTransactionMode,\n\t\tfn: (objectStore: IDBObjectStore) => IDBRequest<T>,\n\t): Promise<T> {\n\t\treturn this.#open().then(\n\t\t\t(db) =>\n\t\t\t\tnew Promise((resolve, reject) => {\n\t\t\t\t\tconst tx = db.transaction(this.#storeName, mode);\n\t\t\t\t\tconst req = fn(tx.objectStore(this.#storeName));\n\t\t\t\t\ttx.oncomplete = () => resolve(req.result);\n\t\t\t\t\ttx.onerror = () => reject(tx.error);\n\t\t\t\t\ttx.onabort = () => reject(tx.error);\n\t\t\t\t}),\n\t\t);\n\t}\n}\n"],"mappings":";;;;;;;AASA,IAAa,WAAb,MAAsB;CACrB;CACA;CACA,MAAmC;CAEnC,YAAY,QAAgB,WAAmB;EAC9C,KAAKA,UAAU;EACf,KAAKC,aAAa;CACnB;CAEA,IAAO,KAA0C;EAChD,OAAO,KAAKC,QAAQ,aAAa,MAAM,EAAE,IAAI,GAAG,CAA8B;CAC/E;CAEA,MAAM,IAAI,KAAkB,OAA+B;EAC1D,MAAM,KAAKA,QAAQ,cAAc,MAAM,EAAE,IAAI,OAAO,GAAG,CAAC;CACzD;CAEA,IAAI,KAAiC;EACpC,OAAO,KAAKA,QAAQ,cAAc,MAAM,EAAE,OAAO,GAAG,CAAqB;CAC1E;CAEA,UAAuD;EACtD,OAAO,KAAKC,MAAM,CAAC,CAAC,MAClB,OACA,IAAI,SAAS,SAAS,WAAW;GAChC,MAAM,KAAK,GAAG,YAAY,KAAKF,YAAY,UAAU;GACrD,MAAM,cAAc,GAAG,YAAY,KAAKA,UAAU;GAClD,MAAM,UAAoB,CAAC;GAC3B,MAAM,SAAS,YAAY,WAAW;GACtC,OAAO,kBAAkB;IACxB,MAAM,IAAI,OAAO;IACjB,IAAI,GAAG;KACN,QAAQ,KAAK,CAAC,EAAE,KAAU,EAAE,KAAU,CAAC;KACvC,EAAE,SAAS;IACZ;GACD;GACA,GAAG,mBAAmB,QAAQ,OAAO;GACrC,GAAG,gBAAgB,OAAO,GAAG,KAAK;EACnC,CAAC,CACH;CACD;CAEA,QAA8B;EAC7B,IAAI,CAAC,KAAKG,KACT,KAAKA,MAAM,IAAI,SAAS,SAAS,WAAW;GAC3C,MAAM,UAAU,UAAU,KAAK,KAAKJ,OAAO;GAC3C,QAAQ,wBAAwB;IAC/B,IAAI,CAAC,QAAQ,OAAO,iBAAiB,SAAS,KAAKC,UAAU,GAC5D,QAAQ,OAAO,kBAAkB,KAAKA,UAAU;GAElD;GACA,QAAQ,kBAAkB,QAAQ,QAAQ,MAAM;GAChD,QAAQ,gBAAgB;IACvB,KAAKG,MAAM;IACX,OAAO,QAAQ,KAAK;GACrB;EACD,CAAC;EAEF,OAAO,KAAKA;CACb;CAEA,QACC,MACA,IACa;EACb,OAAO,KAAKD,MAAM,CAAC,CAAC,MAClB,OACA,IAAI,SAAS,SAAS,WAAW;GAChC,MAAM,KAAK,GAAG,YAAY,KAAKF,YAAY,IAAI;GAC/C,MAAM,MAAM,GAAG,GAAG,YAAY,KAAKA,UAAU,CAAC;GAC9C,GAAG,mBAAmB,QAAQ,IAAI,MAAM;GACxC,GAAG,gBAAgB,OAAO,GAAG,KAAK;GAClC,GAAG,gBAAgB,OAAO,GAAG,KAAK;EACnC,CAAC,CACH;CACD;AACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-adapter.d.mts","names":[],"sources":["../../src/adapters/in-memory-adapter.ts"],"mappings":";;;;cASa,qBAAA,SAA8B,iBAAA;EAAA,SACjC,EAAA;EAAA,SACA,IAAA;EAEH,UAAA,CAAA,GAAc,OAAA;EAId,aAAA,CAAc,OAAA,GAAU,oBAAA,GAAuB,OAAA,CAAQ,cAAA;EAUvD,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,cAAA;EAgBtD,aAAA,CAAc,OAAA,UAAiB,KAAA,WAAgB,OAAA;EAI/C,aAAA,CAAc,OAAA,WAAkB,OAAA;AAAA"}
1
+ {"version":3,"file":"in-memory-adapter.d.mts","names":[],"sources":["../../src/adapters/in-memory-adapter.ts"],"mappings":";;;;cASa,qBAAA,SAA8B,iBAAA;EAAA,SACjC,EAAA;EAAA,SACA,IAAA;EAEH,UAAA,IAAc,OAAA;EAId,aAAA,CAAc,OAAA,GAAU,oBAAA,GAAuB,OAAA,CAAQ,cAAA;EAUvD,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,cAAA;EAgBtD,aAAA,CAAc,OAAA,UAAiB,KAAA,WAAgB,OAAA;EAI/C,aAAA,CAAc,OAAA,WAAkB,OAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-adapter.mjs","names":[],"sources":["../../src/adapters/in-memory-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\n\nimport type { CreateAccountOptions, ImportAccountOptions, ManagedAccount } from '../types.js';\nimport { BaseSignerAdapter } from './base-adapter.js';\nimport { buildManagedAccount } from './build-managed-account.js';\n\nexport class InMemorySignerAdapter extends BaseSignerAdapter {\n\treadonly id = 'in-memory';\n\treadonly name = 'In-Memory Signer';\n\n\tasync initialize(): Promise<void> {\n\t\t// No-op for in-memory adapter\n\t}\n\n\tasync createAccount(options?: CreateAccountOptions): Promise<ManagedAccount> {\n\t\tconst keypair = new Ed25519Keypair();\n\t\tconst address = keypair.getPublicKey().toSuiAddress();\n\t\tconst label = options?.label ?? this.getDefaultLabel();\n\n\t\tconst managedAccount = buildManagedAccount(keypair, address, label);\n\t\tthis.addAccount(managedAccount);\n\t\treturn managedAccount;\n\t}\n\n\tasync importAccount(options: ImportAccountOptions): Promise<ManagedAccount> {\n\t\tconst signer = options.signer;\n\t\tif (!signer) {\n\t\t\tthrow new Error('In-memory adapter requires a signer to import');\n\t\t}\n\t\tconst address = signer.toSuiAddress();\n\n\t\tconst existing = this.getAccount(address);\n\t\tif (existing) return existing;\n\n\t\tconst label = options.label ?? this.getDefaultLabel();\n\t\tconst managedAccount = buildManagedAccount(signer, address, label);\n\t\tthis.addAccount(managedAccount);\n\t\treturn managedAccount;\n\t}\n\n\tasync renameAccount(address: string, label: string): Promise<boolean> {\n\t\treturn this._performRename(address, label);\n\t}\n\n\tasync removeAccount(address: string): Promise<boolean> {\n\t\treturn this.removeAccountByAddress(address);\n\t}\n}\n"],"mappings":";;;;AASA,IAAa,wBAAb,cAA2C,kBAAkB;;;YAC9C;cACE;;CAEhB,MAAM,aAA4B;CAIlC,MAAM,cAAc,SAAyD;EAC5E,MAAM,UAAU,IAAI,gBAAgB;EAIpC,MAAM,iBAAiB,oBAAoB,SAH3B,QAAQ,cAAc,CAAC,cAGa,EAFtC,SAAS,SAAS,KAAK,iBAAiB,CAEa;AACnE,OAAK,WAAW,eAAe;AAC/B,SAAO;;CAGR,MAAM,cAAc,SAAwD;EAC3E,MAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,OACJ,OAAM,IAAI,MAAM,gDAAgD;EAEjE,MAAM,UAAU,OAAO,cAAc;EAErC,MAAM,WAAW,KAAK,WAAW,QAAQ;AACzC,MAAI,SAAU,QAAO;EAGrB,MAAM,iBAAiB,oBAAoB,QAAQ,SADrC,QAAQ,SAAS,KAAK,iBAAiB,CACa;AAClE,OAAK,WAAW,eAAe;AAC/B,SAAO;;CAGR,MAAM,cAAc,SAAiB,OAAiC;AACrE,SAAO,KAAK,eAAe,SAAS,MAAM;;CAG3C,MAAM,cAAc,SAAmC;AACtD,SAAO,KAAK,uBAAuB,QAAQ"}
1
+ {"version":3,"file":"in-memory-adapter.mjs","names":[],"sources":["../../src/adapters/in-memory-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\n\nimport type { CreateAccountOptions, ImportAccountOptions, ManagedAccount } from '../types.js';\nimport { BaseSignerAdapter } from './base-adapter.js';\nimport { buildManagedAccount } from './build-managed-account.js';\n\nexport class InMemorySignerAdapter extends BaseSignerAdapter {\n\treadonly id = 'in-memory';\n\treadonly name = 'In-Memory Signer';\n\n\tasync initialize(): Promise<void> {\n\t\t// No-op for in-memory adapter\n\t}\n\n\tasync createAccount(options?: CreateAccountOptions): Promise<ManagedAccount> {\n\t\tconst keypair = new Ed25519Keypair();\n\t\tconst address = keypair.getPublicKey().toSuiAddress();\n\t\tconst label = options?.label ?? this.getDefaultLabel();\n\n\t\tconst managedAccount = buildManagedAccount(keypair, address, label);\n\t\tthis.addAccount(managedAccount);\n\t\treturn managedAccount;\n\t}\n\n\tasync importAccount(options: ImportAccountOptions): Promise<ManagedAccount> {\n\t\tconst signer = options.signer;\n\t\tif (!signer) {\n\t\t\tthrow new Error('In-memory adapter requires a signer to import');\n\t\t}\n\t\tconst address = signer.toSuiAddress();\n\n\t\tconst existing = this.getAccount(address);\n\t\tif (existing) return existing;\n\n\t\tconst label = options.label ?? this.getDefaultLabel();\n\t\tconst managedAccount = buildManagedAccount(signer, address, label);\n\t\tthis.addAccount(managedAccount);\n\t\treturn managedAccount;\n\t}\n\n\tasync renameAccount(address: string, label: string): Promise<boolean> {\n\t\treturn this._performRename(address, label);\n\t}\n\n\tasync removeAccount(address: string): Promise<boolean> {\n\t\treturn this.removeAccountByAddress(address);\n\t}\n}\n"],"mappings":";;;;AASA,IAAa,wBAAb,cAA2C,kBAAkB;;;YAC9C;cACE;;CAEhB,MAAM,aAA4B,CAElC;CAEA,MAAM,cAAc,SAAyD;EAC5E,MAAM,UAAU,IAAI,eAAe;EAInC,MAAM,iBAAiB,oBAAoB,SAH3B,QAAQ,aAAa,CAAC,CAAC,aAGa,GAFtC,SAAS,SAAS,KAAK,gBAAgB,CAEa;EAClE,KAAK,WAAW,cAAc;EAC9B,OAAO;CACR;CAEA,MAAM,cAAc,SAAwD;EAC3E,MAAM,SAAS,QAAQ;EACvB,IAAI,CAAC,QACJ,MAAM,IAAI,MAAM,+CAA+C;EAEhE,MAAM,UAAU,OAAO,aAAa;EAEpC,MAAM,WAAW,KAAK,WAAW,OAAO;EACxC,IAAI,UAAU,OAAO;EAGrB,MAAM,iBAAiB,oBAAoB,QAAQ,SADrC,QAAQ,SAAS,KAAK,gBAAgB,CACa;EACjE,KAAK,WAAW,cAAc;EAC9B,OAAO;CACR;CAEA,MAAM,cAAc,SAAiB,OAAiC;EACrE,OAAO,KAAK,eAAe,SAAS,KAAK;CAC1C;CAEA,MAAM,cAAc,SAAmC;EACtD,OAAO,KAAK,uBAAuB,OAAO;CAC3C;AACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"passkey-adapter.d.mts","names":[],"sources":["../../src/adapters/passkey-adapter.ts"],"mappings":";;;;;;;AAgCA;;;;;cAAa,oBAAA,SAA6B,iBAAA;EAAA;WAChC,EAAA;EAAA,SACA,IAAA;EAAA,SACA,aAAA;cAKG,OAAA;IAAY,MAAA;IAAiB,SAAA;IAAoB,QAAA,GAAW,eAAA;EAAA;EAiBlE,UAAA,CAAA,GAAc,OAAA;EAAA,UAsBD,eAAA,CAAA;EAIb,aAAA,CAAc,OAAA,GAAU,oBAAA,GAAoB,OAAA,CAAA,cAAA;EAY5C,aAAA,CAAc,OAAA,UAAiB,KAAA,WAAgB,OAAA;EAM/C,aAAA,CAAc,OAAA,WAAkB,OAAA;AAAA"}
1
+ {"version":3,"file":"passkey-adapter.d.mts","names":[],"sources":["../../src/adapters/passkey-adapter.ts"],"mappings":";;;;;;;AAgCA;;;;;cAAa,oBAAA,SAA6B,iBAAA;EAAA;WAChC,EAAA;EAAA,SACA,IAAA;EAAA,SACA,aAAA;cAKG,OAAA;IAAY,MAAA;IAAiB,SAAA;IAAoB,QAAA,GAAW,eAAA;EAAA;EAiBlE,UAAA,IAAc,OAAA;EAAA,UAsBD,eAAA;EAIb,aAAA,CAAc,OAAA,GAAU,oBAAA,GAAoB,OAAA,CAAA,cAAA;EAY5C,aAAA,CAAc,OAAA,UAAiB,KAAA,WAAgB,OAAA;EAM/C,aAAA,CAAc,OAAA,WAAkB,OAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"passkey-adapter.mjs","names":["#store","#provider","#getProvider","#saveMeta"],"sources":["../../src/adapters/passkey-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { PasskeyKeypair } from '@mysten/sui/keypairs/passkey';\nimport type { PasskeyProvider } from '@mysten/sui/keypairs/passkey';\n\nimport type { CreateAccountOptions } from '../types.js';\nimport { BaseSignerAdapter } from './base-adapter.js';\nimport { buildManagedAccount } from './build-managed-account.js';\nimport { IDBStore } from './idb-store.js';\n\n/** Metadata stored in IndexedDB for each passkey account. */\ninterface StoredPasskeyMeta {\n\taddress: string;\n\tlabel: string;\n\t/** Compressed secp256r1 public key (33 bytes, stored as number array). */\n\tpublicKeyBytes: number[];\n\t/** WebAuthn credential ID (stored as number array). Used to constrain credential selection during signing. */\n\tcredentialId?: number[];\n}\n\nconst DEFAULT_DB_NAME = 'dev-wallet-passkey';\nconst DEFAULT_STORE_NAME = 'accounts';\nconst META_KEY = '__passkey_accounts__';\n\n/**\n * Signer adapter backed by WebAuthn passkeys. Each signing operation triggers a\n * browser biometric/PIN prompt. Account metadata is persisted in IndexedDB;\n * private keys are managed by the browser/OS and never enter JavaScript.\n *\n * Browser only — requires `navigator.credentials` and `indexedDB`.\n */\nexport class PasskeySignerAdapter extends BaseSignerAdapter {\n\treadonly id = 'passkey';\n\treadonly name = 'Passkey Signer';\n\treadonly allowAutoSign = false;\n\n\t#store: IDBStore;\n\t#provider: PasskeyProvider | null;\n\n\tconstructor(options?: { dbName?: string; storeName?: string; provider?: PasskeyProvider }) {\n\t\tsuper();\n\t\tthis.#store = new IDBStore(\n\t\t\toptions?.dbName ?? DEFAULT_DB_NAME,\n\t\t\toptions?.storeName ?? DEFAULT_STORE_NAME,\n\t\t);\n\t\t// Allow injecting a custom provider (useful for testing)\n\t\tthis.#provider = options?.provider ?? null;\n\t}\n\n\t#getProvider(): PasskeyProvider {\n\t\tif (!this.#provider) {\n\t\t\tthrow new Error('PasskeySignerAdapter not initialized. Call initialize() first.');\n\t\t}\n\t\treturn this.#provider;\n\t}\n\n\tasync initialize(): Promise<void> {\n\t\tif (!this.#provider) {\n\t\t\tconst { BrowserPasskeyProvider } = await import('@mysten/sui/keypairs/passkey');\n\t\t\tthis.#provider = new BrowserPasskeyProvider('Dev Wallet Passkey', {\n\t\t\t\trp: { id: globalThis.location?.hostname },\n\t\t\t});\n\t\t}\n\n\t\tconst stored = await this.#store.get<StoredPasskeyMeta[]>(META_KEY);\n\t\tif (!stored) return;\n\n\t\tconst provider = this.#getProvider();\n\t\tthis.setInitialAccounts(\n\t\t\tstored.map((meta) => {\n\t\t\t\tconst publicKeyBytes = new Uint8Array(meta.publicKeyBytes);\n\t\t\t\tconst credentialId = meta.credentialId ? new Uint8Array(meta.credentialId) : undefined;\n\t\t\t\tconst signer = new PasskeyKeypair(publicKeyBytes, provider, credentialId);\n\t\t\t\treturn buildManagedAccount(signer, meta.address, meta.label);\n\t\t\t}),\n\t\t);\n\t}\n\n\tprotected override getDefaultLabel(): string {\n\t\treturn `Passkey Account ${this.getAccounts().length + 1}`;\n\t}\n\n\tasync createAccount(options?: CreateAccountOptions) {\n\t\tconst signer = await PasskeyKeypair.getPasskeyInstance(this.#getProvider());\n\t\tconst address = signer.toSuiAddress();\n\t\tconst label = options?.label ?? this.getDefaultLabel();\n\n\t\tconst managedAccount = buildManagedAccount(signer, address, label);\n\t\tthis.addAccount(managedAccount);\n\t\tawait this.#saveMeta();\n\n\t\treturn managedAccount;\n\t}\n\n\tasync renameAccount(address: string, label: string): Promise<boolean> {\n\t\tif (!this._performRename(address, label)) return false;\n\t\tawait this.#saveMeta();\n\t\treturn true;\n\t}\n\n\tasync removeAccount(address: string): Promise<boolean> {\n\t\tif (!this.removeAccountByAddress(address)) return false;\n\t\tawait this.#saveMeta();\n\t\treturn true;\n\t}\n\n\tasync #saveMeta(): Promise<void> {\n\t\tconst meta: StoredPasskeyMeta[] = this.getAccounts().map((a) => {\n\t\t\tconst credentialId = (a.signer as PasskeyKeypair).getCredentialId?.();\n\t\t\treturn {\n\t\t\t\taddress: a.address,\n\t\t\t\tlabel: a.label,\n\t\t\t\tpublicKeyBytes: [...a.signer.getPublicKey().toRawBytes()],\n\t\t\t\t...(credentialId && { credentialId: [...credentialId] }),\n\t\t\t};\n\t\t});\n\t\tawait this.#store.set(META_KEY, meta);\n\t}\n}\n"],"mappings":";;;;;AAqBA,MAAM,kBAAkB;AACxB,MAAM,qBAAqB;AAC3B,MAAM,WAAW;;;;;;;;AASjB,IAAa,uBAAb,cAA0C,kBAAkB;CAK3D;CACA;CAEA,YAAY,SAA+E;AAC1F,SAAO;YARM;cACE;uBACS;AAOxB,QAAA,QAAc,IAAI,SACjB,SAAS,UAAU,iBACnB,SAAS,aAAa,mBACtB;AAED,QAAA,WAAiB,SAAS,YAAY;;CAGvC,eAAgC;AAC/B,MAAI,CAAC,MAAA,SACJ,OAAM,IAAI,MAAM,iEAAiE;AAElF,SAAO,MAAA;;CAGR,MAAM,aAA4B;AACjC,MAAI,CAAC,MAAA,UAAgB;GACpB,MAAM,EAAE,2BAA2B,MAAM,OAAO;AAChD,SAAA,WAAiB,IAAI,uBAAuB,sBAAsB,EACjE,IAAI,EAAE,IAAI,WAAW,UAAU,UAAU,EACzC,CAAC;;EAGH,MAAM,SAAS,MAAM,MAAA,MAAY,IAAyB,SAAS;AACnE,MAAI,CAAC,OAAQ;EAEb,MAAM,WAAW,MAAA,aAAmB;AACpC,OAAK,mBACJ,OAAO,KAAK,SAAS;AAIpB,UAAO,oBAAoB,IADR,eAAe,IAFP,WAAW,KAAK,eAET,EAAgB,UAD7B,KAAK,eAAe,IAAI,WAAW,KAAK,aAAa,GAAG,OAElD,EAAQ,KAAK,SAAS,KAAK,MAAM;IAC3D,CACF;;CAGF,kBAA6C;AAC5C,SAAO,mBAAmB,KAAK,aAAa,CAAC,SAAS;;CAGvD,MAAM,cAAc,SAAgC;EACnD,MAAM,SAAS,MAAM,eAAe,mBAAmB,MAAA,aAAmB,CAAC;EAI3E,MAAM,iBAAiB,oBAAoB,QAH3B,OAAO,cAG4B,EAFrC,SAAS,SAAS,KAAK,iBAAiB,CAEY;AAClE,OAAK,WAAW,eAAe;AAC/B,QAAM,MAAA,UAAgB;AAEtB,SAAO;;CAGR,MAAM,cAAc,SAAiB,OAAiC;AACrE,MAAI,CAAC,KAAK,eAAe,SAAS,MAAM,CAAE,QAAO;AACjD,QAAM,MAAA,UAAgB;AACtB,SAAO;;CAGR,MAAM,cAAc,SAAmC;AACtD,MAAI,CAAC,KAAK,uBAAuB,QAAQ,CAAE,QAAO;AAClD,QAAM,MAAA,UAAgB;AACtB,SAAO;;CAGR,OAAA,WAAiC;EAChC,MAAM,OAA4B,KAAK,aAAa,CAAC,KAAK,MAAM;GAC/D,MAAM,eAAgB,EAAE,OAA0B,mBAAmB;AACrE,UAAO;IACN,SAAS,EAAE;IACX,OAAO,EAAE;IACT,gBAAgB,CAAC,GAAG,EAAE,OAAO,cAAc,CAAC,YAAY,CAAC;IACzD,GAAI,gBAAgB,EAAE,cAAc,CAAC,GAAG,aAAa,EAAE;IACvD;IACA;AACF,QAAM,MAAA,MAAY,IAAI,UAAU,KAAK"}
1
+ {"version":3,"file":"passkey-adapter.mjs","names":["#store","#provider","#getProvider","#saveMeta"],"sources":["../../src/adapters/passkey-adapter.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { PasskeyKeypair } from '@mysten/sui/keypairs/passkey';\nimport type { PasskeyProvider } from '@mysten/sui/keypairs/passkey';\n\nimport type { CreateAccountOptions } from '../types.js';\nimport { BaseSignerAdapter } from './base-adapter.js';\nimport { buildManagedAccount } from './build-managed-account.js';\nimport { IDBStore } from './idb-store.js';\n\n/** Metadata stored in IndexedDB for each passkey account. */\ninterface StoredPasskeyMeta {\n\taddress: string;\n\tlabel: string;\n\t/** Compressed secp256r1 public key (33 bytes, stored as number array). */\n\tpublicKeyBytes: number[];\n\t/** WebAuthn credential ID (stored as number array). Used to constrain credential selection during signing. */\n\tcredentialId?: number[];\n}\n\nconst DEFAULT_DB_NAME = 'dev-wallet-passkey';\nconst DEFAULT_STORE_NAME = 'accounts';\nconst META_KEY = '__passkey_accounts__';\n\n/**\n * Signer adapter backed by WebAuthn passkeys. Each signing operation triggers a\n * browser biometric/PIN prompt. Account metadata is persisted in IndexedDB;\n * private keys are managed by the browser/OS and never enter JavaScript.\n *\n * Browser only — requires `navigator.credentials` and `indexedDB`.\n */\nexport class PasskeySignerAdapter extends BaseSignerAdapter {\n\treadonly id = 'passkey';\n\treadonly name = 'Passkey Signer';\n\treadonly allowAutoSign = false;\n\n\t#store: IDBStore;\n\t#provider: PasskeyProvider | null;\n\n\tconstructor(options?: { dbName?: string; storeName?: string; provider?: PasskeyProvider }) {\n\t\tsuper();\n\t\tthis.#store = new IDBStore(\n\t\t\toptions?.dbName ?? DEFAULT_DB_NAME,\n\t\t\toptions?.storeName ?? DEFAULT_STORE_NAME,\n\t\t);\n\t\t// Allow injecting a custom provider (useful for testing)\n\t\tthis.#provider = options?.provider ?? null;\n\t}\n\n\t#getProvider(): PasskeyProvider {\n\t\tif (!this.#provider) {\n\t\t\tthrow new Error('PasskeySignerAdapter not initialized. Call initialize() first.');\n\t\t}\n\t\treturn this.#provider;\n\t}\n\n\tasync initialize(): Promise<void> {\n\t\tif (!this.#provider) {\n\t\t\tconst { BrowserPasskeyProvider } = await import('@mysten/sui/keypairs/passkey');\n\t\t\tthis.#provider = new BrowserPasskeyProvider('Dev Wallet Passkey', {\n\t\t\t\trp: { id: globalThis.location?.hostname },\n\t\t\t});\n\t\t}\n\n\t\tconst stored = await this.#store.get<StoredPasskeyMeta[]>(META_KEY);\n\t\tif (!stored) return;\n\n\t\tconst provider = this.#getProvider();\n\t\tthis.setInitialAccounts(\n\t\t\tstored.map((meta) => {\n\t\t\t\tconst publicKeyBytes = new Uint8Array(meta.publicKeyBytes);\n\t\t\t\tconst credentialId = meta.credentialId ? new Uint8Array(meta.credentialId) : undefined;\n\t\t\t\tconst signer = new PasskeyKeypair(publicKeyBytes, provider, credentialId);\n\t\t\t\treturn buildManagedAccount(signer, meta.address, meta.label);\n\t\t\t}),\n\t\t);\n\t}\n\n\tprotected override getDefaultLabel(): string {\n\t\treturn `Passkey Account ${this.getAccounts().length + 1}`;\n\t}\n\n\tasync createAccount(options?: CreateAccountOptions) {\n\t\tconst signer = await PasskeyKeypair.getPasskeyInstance(this.#getProvider());\n\t\tconst address = signer.toSuiAddress();\n\t\tconst label = options?.label ?? this.getDefaultLabel();\n\n\t\tconst managedAccount = buildManagedAccount(signer, address, label);\n\t\tthis.addAccount(managedAccount);\n\t\tawait this.#saveMeta();\n\n\t\treturn managedAccount;\n\t}\n\n\tasync renameAccount(address: string, label: string): Promise<boolean> {\n\t\tif (!this._performRename(address, label)) return false;\n\t\tawait this.#saveMeta();\n\t\treturn true;\n\t}\n\n\tasync removeAccount(address: string): Promise<boolean> {\n\t\tif (!this.removeAccountByAddress(address)) return false;\n\t\tawait this.#saveMeta();\n\t\treturn true;\n\t}\n\n\tasync #saveMeta(): Promise<void> {\n\t\tconst meta: StoredPasskeyMeta[] = this.getAccounts().map((a) => {\n\t\t\tconst credentialId = (a.signer as PasskeyKeypair).getCredentialId?.();\n\t\t\treturn {\n\t\t\t\taddress: a.address,\n\t\t\t\tlabel: a.label,\n\t\t\t\tpublicKeyBytes: [...a.signer.getPublicKey().toRawBytes()],\n\t\t\t\t...(credentialId && { credentialId: [...credentialId] }),\n\t\t\t};\n\t\t});\n\t\tawait this.#store.set(META_KEY, meta);\n\t}\n}\n"],"mappings":";;;;;AAqBA,MAAM,kBAAkB;AACxB,MAAM,qBAAqB;AAC3B,MAAM,WAAW;;;;;;;;AASjB,IAAa,uBAAb,cAA0C,kBAAkB;CAK3D;CACA;CAEA,YAAY,SAA+E;EAC1F,MAAM;YARO;cACE;uBACS;EAOxB,KAAKA,SAAS,IAAI,SACjB,SAAS,UAAU,iBACnB,SAAS,aAAa,kBACvB;EAEA,KAAKC,YAAY,SAAS,YAAY;CACvC;CAEA,eAAgC;EAC/B,IAAI,CAAC,KAAKA,WACT,MAAM,IAAI,MAAM,gEAAgE;EAEjF,OAAO,KAAKA;CACb;CAEA,MAAM,aAA4B;EACjC,IAAI,CAAC,KAAKA,WAAW;GACpB,MAAM,EAAE,2BAA2B,MAAM,OAAO;GAChD,KAAKA,YAAY,IAAI,uBAAuB,sBAAsB,EACjE,IAAI,EAAE,IAAI,WAAW,UAAU,SAAS,EACzC,CAAC;EACF;EAEA,MAAM,SAAS,MAAM,KAAKD,OAAO,IAAyB,QAAQ;EAClE,IAAI,CAAC,QAAQ;EAEb,MAAM,WAAW,KAAKE,aAAa;EACnC,KAAK,mBACJ,OAAO,KAAK,SAAS;GAIpB,OAAO,oBAAoB,IADR,eAAe,IAFP,WAAW,KAAK,cAET,GAAgB,UAD7B,KAAK,eAAe,IAAI,WAAW,KAAK,YAAY,IAAI,MAElD,GAAQ,KAAK,SAAS,KAAK,KAAK;EAC5D,CAAC,CACF;CACD;CAEA,kBAA6C;EAC5C,OAAO,mBAAmB,KAAK,YAAY,CAAC,CAAC,SAAS;CACvD;CAEA,MAAM,cAAc,SAAgC;EACnD,MAAM,SAAS,MAAM,eAAe,mBAAmB,KAAKA,aAAa,CAAC;EAI1E,MAAM,iBAAiB,oBAAoB,QAH3B,OAAO,aAG4B,GAFrC,SAAS,SAAS,KAAK,gBAAgB,CAEY;EACjE,KAAK,WAAW,cAAc;EAC9B,MAAM,KAAKC,UAAU;EAErB,OAAO;CACR;CAEA,MAAM,cAAc,SAAiB,OAAiC;EACrE,IAAI,CAAC,KAAK,eAAe,SAAS,KAAK,GAAG,OAAO;EACjD,MAAM,KAAKA,UAAU;EACrB,OAAO;CACR;CAEA,MAAM,cAAc,SAAmC;EACtD,IAAI,CAAC,KAAK,uBAAuB,OAAO,GAAG,OAAO;EAClD,MAAM,KAAKA,UAAU;EACrB,OAAO;CACR;CAEA,MAAMA,YAA2B;EAChC,MAAM,OAA4B,KAAK,YAAY,CAAC,CAAC,KAAK,MAAM;GAC/D,MAAM,eAAgB,EAAE,OAA0B,kBAAkB;GACpE,OAAO;IACN,SAAS,EAAE;IACX,OAAO,EAAE;IACT,gBAAgB,CAAC,GAAG,EAAE,OAAO,aAAa,CAAC,CAAC,WAAW,CAAC;IACxD,GAAI,gBAAgB,EAAE,cAAc,CAAC,GAAG,YAAY,EAAE;GACvD;EACD,CAAC;EACD,MAAM,KAAKH,OAAO,IAAI,UAAU,IAAI;CACrC;AACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"remote-cli-adapter.d.mts","names":[],"sources":["../../src/adapters/remote-cli-adapter.ts"],"mappings":";;;;;;AAqEA;;;;;;cAAa,cAAA,SAAuB,MAAA;EAAA;cAOvB,OAAA;IACX,OAAA;IACA,SAAA,EAAW,SAAA;IACX,MAAA,EAAQ,eAAA;IACR,YAAA;IACA,SAAA;EAAA;EAUK,IAAA,CAAK,MAAA,EAAQ,UAAA,GAAa,OAAA,CAAQ,UAAA,CAAW,WAAA;EAOnD,YAAA,CAAA,GAAgB,eAAA;EAIhB,YAAA,CAAA,GAAgB,SAAA;EAIP,YAAA,CAAA;EAIM,eAAA,CAAgB,KAAA,EAAO,UAAA,GAAU,OAAA;;;;EA8BjC,mBAAA,CAAoB,MAAA,EAAQ,UAAA,GAAa,OAAA;AAAA;;;;;;;;cAgB5C,gBAAA,SAAyB,iBAAA;EAAA;WAC5B,EAAA;EAAA,SACA,IAAA;EAAA,SACA,aAAA;EAAA,UAEU,eAAA,CAAA;EAAA,OAOZ,UAAA,CAAW,MAAA;EAAA,WAKP,WAAA,CAAA;EAAA,WAIA,SAAA,CAAA;cASC,OAAA;IAAY,YAAA;IAAuB,KAAA;EAAA;EAAA,IAgB3C,QAAA,CAAA;EAIE,UAAA,CAAA,GAAc,OAAA;EAyBd,qBAAA,CAAA,GAAyB,OAAA,CAC9B,KAAA;IAAQ,OAAA;IAAiB,MAAA;IAAgB,KAAA;EAAA;EAgBpC,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,cAAA;EA2BtD,aAAA,CAAc,OAAA,WAAkB,OAAA;EAQ7B,OAAA,CAAA;AAAA"}
1
+ {"version":3,"file":"remote-cli-adapter.d.mts","names":[],"sources":["../../src/adapters/remote-cli-adapter.ts"],"mappings":";;;;;;AAqEA;;;;;;cAAa,cAAA,SAAuB,MAAA;EAAA;cAOvB,OAAA;IACX,OAAA;IACA,SAAA,EAAW,SAAA;IACX,MAAA,EAAQ,eAAA;IACR,YAAA;IACA,SAAA;EAAA;EAUK,IAAA,CAAK,MAAA,EAAQ,UAAA,GAAa,OAAA,CAAQ,UAAA,CAAW,WAAA;EAOnD,YAAA,IAAgB,eAAA;EAIhB,YAAA,IAAgB,SAAA;EAIP,YAAA;EAIM,eAAA,CAAgB,KAAA,EAAO,UAAA,GAAU,OAAA;;;;EA8BjC,mBAAA,CAAoB,MAAA,EAAQ,UAAA,GAAa,OAAA;AAAA;;;;;;;;cAgB5C,gBAAA,SAAyB,iBAAA;EAAA;WAC5B,EAAA;EAAA,SACA,IAAA;EAAA,SACA,aAAA;EAAA,UAEU,eAAA;EAAA,OAOZ,UAAA,CAAW,MAAA;EAAA,WAKP,WAAA;EAAA,WAIA,SAAA;cASC,OAAA;IAAY,YAAA;IAAuB,KAAA;EAAA;EAAA,IAgB3C,QAAA;EAIE,UAAA,IAAc,OAAA;EAyBd,qBAAA,IAAyB,OAAA,CAC9B,KAAA;IAAQ,OAAA;IAAiB,MAAA;IAAgB,KAAA;EAAA;EAgBpC,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,cAAA;EA2BtD,aAAA,CAAc,OAAA,WAAkB,OAAA;EAQ7B,OAAA;AAAA"}