@mysten-incubation/dev-wallet 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +250 -0
- package/dist/_virtual/_@oxc-project_runtime@0.107.0/helpers/decorate.mjs +10 -0
- package/dist/adapters/base-adapter.d.mts +33 -0
- package/dist/adapters/base-adapter.d.mts.map +1 -0
- package/dist/adapters/base-adapter.mjs +77 -0
- package/dist/adapters/base-adapter.mjs.map +1 -0
- package/dist/adapters/browser.d.mts +8 -0
- package/dist/adapters/browser.mjs +8 -0
- package/dist/adapters/build-managed-account.d.mts +12 -0
- package/dist/adapters/build-managed-account.d.mts.map +1 -0
- package/dist/adapters/build-managed-account.mjs +30 -0
- package/dist/adapters/build-managed-account.mjs.map +1 -0
- package/dist/adapters/idb-store.mjs +73 -0
- package/dist/adapters/idb-store.mjs.map +1 -0
- package/dist/adapters/in-memory-adapter.d.mts +16 -0
- package/dist/adapters/in-memory-adapter.d.mts.map +1 -0
- package/dist/adapters/in-memory-adapter.mjs +44 -0
- package/dist/adapters/in-memory-adapter.mjs.map +1 -0
- package/dist/adapters/passkey-adapter.d.mts +31 -0
- package/dist/adapters/passkey-adapter.d.mts.map +1 -0
- package/dist/adapters/passkey-adapter.mjs +87 -0
- package/dist/adapters/passkey-adapter.mjs.map +1 -0
- package/dist/adapters/remote-cli-adapter.d.mts +65 -0
- package/dist/adapters/remote-cli-adapter.d.mts.map +1 -0
- package/dist/adapters/remote-cli-adapter.mjs +299 -0
- package/dist/adapters/remote-cli-adapter.mjs.map +1 -0
- package/dist/adapters/webcrypto-adapter.d.mts +20 -0
- package/dist/adapters/webcrypto-adapter.d.mts.map +1 -0
- package/dist/adapters/webcrypto-adapter.mjs +68 -0
- package/dist/adapters/webcrypto-adapter.mjs.map +1 -0
- package/dist/bin/cli.d.mts +1 -0
- package/dist/bin/cli.mjs +183 -0
- package/dist/bin/cli.mjs.map +1 -0
- package/dist/client/dev-wallet-client.d.mts +57 -0
- package/dist/client/dev-wallet-client.d.mts.map +1 -0
- package/dist/client/dev-wallet-client.mjs +223 -0
- package/dist/client/dev-wallet-client.mjs.map +1 -0
- package/dist/client/index.d.mts +3 -0
- package/dist/client/index.mjs +4 -0
- package/dist/client/request-handler.d.mts +42 -0
- package/dist/client/request-handler.d.mts.map +1 -0
- package/dist/client/request-handler.mjs +115 -0
- package/dist/client/request-handler.mjs.map +1 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +4 -0
- package/dist/react/components.d.mts +32 -0
- package/dist/react/components.d.mts.map +1 -0
- package/dist/react/components.mjs +53 -0
- package/dist/react/components.mjs.map +1 -0
- package/dist/react/context.d.mts +22 -0
- package/dist/react/context.d.mts.map +1 -0
- package/dist/react/context.mjs +25 -0
- package/dist/react/context.mjs.map +1 -0
- package/dist/react/index.d.mts +4 -0
- package/dist/react/index.mjs +5 -0
- package/dist/react/useDevWallet.d.mts +38 -0
- package/dist/react/useDevWallet.d.mts.map +1 -0
- package/dist/react/useDevWallet.mjs +89 -0
- package/dist/react/useDevWallet.mjs.map +1 -0
- package/dist/server/cli-signing-middleware.d.mts +22 -0
- package/dist/server/cli-signing-middleware.d.mts.map +1 -0
- package/dist/server/cli-signing-middleware.mjs +117 -0
- package/dist/server/cli-signing-middleware.mjs.map +1 -0
- package/dist/server/index.d.mts +2 -0
- package/dist/server/index.mjs +3 -0
- package/dist/standalone/assets/in-memory-adapter-CBF4h2KD.js +1 -0
- package/dist/standalone/assets/main-VE4olb-Q.js +2841 -0
- package/dist/standalone/assets/webcrypto-adapter-DysAubFb.js +1 -0
- package/dist/standalone/bookmarklet.js +5 -0
- package/dist/standalone/index.html +48 -0
- package/dist/types.d.mts +55 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/ui/copy-controller.mjs +43 -0
- package/dist/ui/copy-controller.mjs.map +1 -0
- package/dist/ui/dev-wallet-account-selector.d.mts +24 -0
- package/dist/ui/dev-wallet-account-selector.d.mts.map +1 -0
- package/dist/ui/dev-wallet-account-selector.mjs +268 -0
- package/dist/ui/dev-wallet-account-selector.mjs.map +1 -0
- package/dist/ui/dev-wallet-accounts.d.mts +29 -0
- package/dist/ui/dev-wallet-accounts.d.mts.map +1 -0
- package/dist/ui/dev-wallet-accounts.mjs +524 -0
- package/dist/ui/dev-wallet-accounts.mjs.map +1 -0
- package/dist/ui/dev-wallet-balances.d.mts +26 -0
- package/dist/ui/dev-wallet-balances.d.mts.map +1 -0
- package/dist/ui/dev-wallet-balances.mjs +130 -0
- package/dist/ui/dev-wallet-balances.mjs.map +1 -0
- package/dist/ui/dev-wallet-connect.d.mts +31 -0
- package/dist/ui/dev-wallet-connect.d.mts.map +1 -0
- package/dist/ui/dev-wallet-connect.mjs +225 -0
- package/dist/ui/dev-wallet-connect.mjs.map +1 -0
- package/dist/ui/dev-wallet-dropdown.d.mts +27 -0
- package/dist/ui/dev-wallet-dropdown.d.mts.map +1 -0
- package/dist/ui/dev-wallet-dropdown.mjs +121 -0
- package/dist/ui/dev-wallet-dropdown.mjs.map +1 -0
- package/dist/ui/dev-wallet-network-badge.d.mts +21 -0
- package/dist/ui/dev-wallet-network-badge.d.mts.map +1 -0
- package/dist/ui/dev-wallet-network-badge.mjs +121 -0
- package/dist/ui/dev-wallet-network-badge.mjs.map +1 -0
- package/dist/ui/dev-wallet-new-account.d.mts +31 -0
- package/dist/ui/dev-wallet-new-account.d.mts.map +1 -0
- package/dist/ui/dev-wallet-new-account.mjs +577 -0
- package/dist/ui/dev-wallet-new-account.mjs.map +1 -0
- package/dist/ui/dev-wallet-objects.d.mts +26 -0
- package/dist/ui/dev-wallet-objects.d.mts.map +1 -0
- package/dist/ui/dev-wallet-objects.mjs +276 -0
- package/dist/ui/dev-wallet-objects.mjs.map +1 -0
- package/dist/ui/dev-wallet-panel.d.mts +22 -0
- package/dist/ui/dev-wallet-panel.d.mts.map +1 -0
- package/dist/ui/dev-wallet-panel.mjs +192 -0
- package/dist/ui/dev-wallet-panel.mjs.map +1 -0
- package/dist/ui/dev-wallet-popup.d.mts +36 -0
- package/dist/ui/dev-wallet-popup.d.mts.map +1 -0
- package/dist/ui/dev-wallet-popup.mjs +137 -0
- package/dist/ui/dev-wallet-popup.mjs.map +1 -0
- package/dist/ui/dev-wallet-settings.d.mts +33 -0
- package/dist/ui/dev-wallet-settings.d.mts.map +1 -0
- package/dist/ui/dev-wallet-settings.mjs +635 -0
- package/dist/ui/dev-wallet-settings.mjs.map +1 -0
- package/dist/ui/dev-wallet-signing-modal.d.mts +32 -0
- package/dist/ui/dev-wallet-signing-modal.d.mts.map +1 -0
- package/dist/ui/dev-wallet-signing-modal.mjs +115 -0
- package/dist/ui/dev-wallet-signing-modal.mjs.map +1 -0
- package/dist/ui/dev-wallet-signing.d.mts +25 -0
- package/dist/ui/dev-wallet-signing.d.mts.map +1 -0
- package/dist/ui/dev-wallet-signing.mjs +544 -0
- package/dist/ui/dev-wallet-signing.mjs.map +1 -0
- package/dist/ui/dev-wallet-standalone.d.mts +23 -0
- package/dist/ui/dev-wallet-standalone.d.mts.map +1 -0
- package/dist/ui/dev-wallet-standalone.mjs +129 -0
- package/dist/ui/dev-wallet-standalone.mjs.map +1 -0
- package/dist/ui/dev-wallet-tab-bar.d.mts +19 -0
- package/dist/ui/dev-wallet-tab-bar.d.mts.map +1 -0
- package/dist/ui/dev-wallet-tab-bar.mjs +143 -0
- package/dist/ui/dev-wallet-tab-bar.mjs.map +1 -0
- package/dist/ui/index.d.mts +17 -0
- package/dist/ui/index.mjs +18 -0
- package/dist/ui/mount.d.mts +11 -0
- package/dist/ui/mount.d.mts.map +1 -0
- package/dist/ui/mount.mjs +17 -0
- package/dist/ui/mount.mjs.map +1 -0
- package/dist/ui/styles.mjs +250 -0
- package/dist/ui/styles.mjs.map +1 -0
- package/dist/ui/transaction-analyzer.mjs +58 -0
- package/dist/ui/transaction-analyzer.mjs.map +1 -0
- package/dist/ui/utils.mjs +98 -0
- package/dist/ui/utils.mjs.map +1 -0
- package/dist/ui/wallet-controller.mjs +275 -0
- package/dist/ui/wallet-controller.mjs.map +1 -0
- package/dist/wallet/constants.mjs +11 -0
- package/dist/wallet/constants.mjs.map +1 -0
- package/dist/wallet/dev-wallet.d.mts +118 -0
- package/dist/wallet/dev-wallet.d.mts.map +1 -0
- package/dist/wallet/dev-wallet.mjs +424 -0
- package/dist/wallet/dev-wallet.mjs.map +1 -0
- package/dist/wallet/initializer.d.mts +63 -0
- package/dist/wallet/initializer.d.mts.map +1 -0
- package/dist/wallet/initializer.mjs +75 -0
- package/dist/wallet/initializer.mjs.map +1 -0
- package/dist/wallet/signing.d.mts +35 -0
- package/dist/wallet/signing.d.mts.map +1 -0
- package/dist/wallet/signing.mjs +69 -0
- package/dist/wallet/signing.mjs.map +1 -0
- package/package.json +124 -0
- package/src/adapters/base-adapter.ts +93 -0
- package/src/adapters/browser.ts +15 -0
- package/src/adapters/build-managed-account.ts +33 -0
- package/src/adapters/idb-store.ts +87 -0
- package/src/adapters/in-memory-adapter.ts +51 -0
- package/src/adapters/passkey-adapter.ts +120 -0
- package/src/adapters/remote-cli-adapter.ts +388 -0
- package/src/adapters/webcrypto-adapter.ts +96 -0
- package/src/app/bookmarklet-entry.ts +77 -0
- package/src/app/index.html +48 -0
- package/src/app/main.ts +245 -0
- package/src/app/tsconfig.json +3 -0
- package/src/bin/cli.ts +214 -0
- package/src/client/dev-wallet-client.ts +280 -0
- package/src/client/index.ts +7 -0
- package/src/client/request-handler.ts +161 -0
- package/src/index.ts +19 -0
- package/src/react/components.ts +64 -0
- package/src/react/context.ts +38 -0
- package/src/react/index.ts +16 -0
- package/src/react/useDevWallet.ts +118 -0
- package/src/server/cli-signing-middleware.ts +146 -0
- package/src/server/index.ts +8 -0
- package/src/types.ts +58 -0
- package/src/ui/copy-controller.ts +49 -0
- package/src/ui/dev-wallet-account-selector.ts +283 -0
- package/src/ui/dev-wallet-accounts.ts +578 -0
- package/src/ui/dev-wallet-balances.ts +171 -0
- package/src/ui/dev-wallet-connect.ts +259 -0
- package/src/ui/dev-wallet-dropdown.ts +138 -0
- package/src/ui/dev-wallet-network-badge.ts +128 -0
- package/src/ui/dev-wallet-new-account.ts +662 -0
- package/src/ui/dev-wallet-objects.ts +336 -0
- package/src/ui/dev-wallet-panel.ts +207 -0
- package/src/ui/dev-wallet-popup.ts +169 -0
- package/src/ui/dev-wallet-settings.ts +692 -0
- package/src/ui/dev-wallet-signing-modal.ts +137 -0
- package/src/ui/dev-wallet-signing.ts +624 -0
- package/src/ui/dev-wallet-standalone.ts +136 -0
- package/src/ui/dev-wallet-tab-bar.ts +151 -0
- package/src/ui/index.ts +26 -0
- package/src/ui/mount.ts +21 -0
- package/src/ui/styles.ts +252 -0
- package/src/ui/transaction-analyzer.ts +60 -0
- package/src/ui/utils.ts +118 -0
- package/src/ui/wallet-controller.ts +340 -0
- package/src/wallet/constants.ts +17 -0
- package/src/wallet/dev-wallet.ts +597 -0
- package/src/wallet/initializer.ts +124 -0
- package/src/wallet/signing.ts +85 -0
package/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# @mysten-incubation/dev-wallet
|
|
2
|
+
|
|
3
|
+
A development-only wallet for building and testing Sui dApps.
|
|
4
|
+
|
|
5
|
+
> [!WARNING] This wallet is for development and testing only. Do not use it to store real funds. A
|
|
6
|
+
> console warning is emitted automatically in production builds.
|
|
7
|
+
|
|
8
|
+
> [!CAUTION] **Pre-1.0:** This package is under active development. Minor versions may contain
|
|
9
|
+
> breaking changes until the API stabilizes at 1.0.
|
|
10
|
+
|
|
11
|
+
## Why use a dev wallet?
|
|
12
|
+
|
|
13
|
+
- **Localnet and custom networks** — production wallets don't connect to localnet. This wallet
|
|
14
|
+
connects to any network URL you give it.
|
|
15
|
+
- **Separate from mainnet credentials** — your dev keys never touch your real wallet. Ephemeral keys
|
|
16
|
+
disappear on page refresh; persistent keys stay scoped to the browser.
|
|
17
|
+
- **E2E testing without manual approval** — set `autoApprove: true` and the wallet signs
|
|
18
|
+
automatically. No click-through, no popups, works in headless CI.
|
|
19
|
+
- **Preserve assets across page loads** — use the WebCrypto adapter and your faucet coins survive
|
|
20
|
+
browser refresh.
|
|
21
|
+
- **No browser extension required** — embed the wallet directly in your app. Perfect for demos,
|
|
22
|
+
tutorials, and hackathons where asking users to install a wallet extension is friction.
|
|
23
|
+
- **Same account you publish contracts from** — connect to the `sui` CLI and sign transactions with
|
|
24
|
+
the same address that ran `sui move publish`, so you can access AdminCap and other owned objects.
|
|
25
|
+
- **Works across multiple apps** — run the wallet as a standalone web app and connect any number of
|
|
26
|
+
dApps to it via popup.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @mysten-incubation/dev-wallet
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
A single `devWalletInitializer` call covers most use cases. Tweak the options for your scenario:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { createDAppKit } from '@mysten/dapp-kit-react';
|
|
40
|
+
import { devWalletInitializer } from '@mysten-incubation/dev-wallet';
|
|
41
|
+
import { WebCryptoSignerAdapter } from '@mysten-incubation/dev-wallet/adapters';
|
|
42
|
+
|
|
43
|
+
const dAppKit = createDAppKit({
|
|
44
|
+
networks: ['devnet', 'testnet', 'localnet'],
|
|
45
|
+
walletInitializers: [
|
|
46
|
+
devWalletInitializer({
|
|
47
|
+
// Keys persist in IndexedDB — faucet once, keep your coins across reloads
|
|
48
|
+
adapters: [new WebCryptoSignerAdapter()],
|
|
49
|
+
// Skip the wallet picker — connect immediately on load
|
|
50
|
+
autoConnect: true,
|
|
51
|
+
// Show the floating wallet panel (accounts, balances, objects)
|
|
52
|
+
mountUI: true,
|
|
53
|
+
// Auto-create an account on first visit (default: true)
|
|
54
|
+
createInitialAccount: true,
|
|
55
|
+
// Sign without approval modals — great for E2E tests and CI
|
|
56
|
+
// autoApprove: true,
|
|
57
|
+
}),
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Pick your setup
|
|
63
|
+
|
|
64
|
+
### dApp Kit plugin (easiest)
|
|
65
|
+
|
|
66
|
+
If your app uses `@mysten/dapp-kit-react`, embed the wallet directly. It inherits your dApp Kit
|
|
67
|
+
network config automatically.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { createDAppKit } from '@mysten/dapp-kit-react';
|
|
71
|
+
import { devWalletInitializer } from '@mysten-incubation/dev-wallet';
|
|
72
|
+
import { WebCryptoSignerAdapter } from '@mysten-incubation/dev-wallet/adapters';
|
|
73
|
+
|
|
74
|
+
const dAppKit = createDAppKit({
|
|
75
|
+
networks: ['devnet', 'testnet', 'localnet'],
|
|
76
|
+
walletInitializers: [
|
|
77
|
+
devWalletInitializer({
|
|
78
|
+
adapters: [new WebCryptoSignerAdapter()],
|
|
79
|
+
autoConnect: true,
|
|
80
|
+
mountUI: true,
|
|
81
|
+
}),
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The wallet appears in the dApp Kit wallet picker. An initial account is created automatically.
|
|
87
|
+
|
|
88
|
+
### Standalone wallet
|
|
89
|
+
|
|
90
|
+
Run a self-contained wallet as a separate web app — signing works via popup, same as a production
|
|
91
|
+
browser wallet.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npx @mysten-incubation/dev-wallet serve
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Register it through `walletInitializers` using `devWalletClientInitializer`:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { createDAppKit } from '@mysten/dapp-kit-react';
|
|
101
|
+
import { devWalletClientInitializer } from '@mysten-incubation/dev-wallet/client';
|
|
102
|
+
|
|
103
|
+
const dAppKit = createDAppKit({
|
|
104
|
+
networks: ['devnet'],
|
|
105
|
+
walletInitializers: [devWalletClientInitializer({ origin: 'http://localhost:5174' })],
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Or register directly without dApp Kit:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { DevWalletClient } from '@mysten-incubation/dev-wallet/client';
|
|
113
|
+
|
|
114
|
+
DevWalletClient.register({ origin: 'http://localhost:5174' });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The default port is 5174. Use `--port` to set a different port.
|
|
118
|
+
|
|
119
|
+
The standalone wallet includes WebCrypto and InMemory adapters by default. If `sui` is on your PATH,
|
|
120
|
+
the CLI adapter is also available — so you can sign with the same address you published contracts
|
|
121
|
+
from. Great for teams, multi-app development, and when you can't modify the dApp source.
|
|
122
|
+
|
|
123
|
+
### Manual setup (no framework)
|
|
124
|
+
|
|
125
|
+
If you're not using dApp Kit or React, create and register the wallet directly. Localnet, devnet,
|
|
126
|
+
and testnet are configured out of the box — no URLs needed.
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { DevWallet } from '@mysten-incubation/dev-wallet';
|
|
130
|
+
import { WebCryptoSignerAdapter } from '@mysten-incubation/dev-wallet/adapters';
|
|
131
|
+
import { mountDevWallet } from '@mysten-incubation/dev-wallet/ui';
|
|
132
|
+
|
|
133
|
+
const adapter = new WebCryptoSignerAdapter();
|
|
134
|
+
await adapter.initialize();
|
|
135
|
+
await adapter.createAccount({ label: 'Dev Account' });
|
|
136
|
+
|
|
137
|
+
const wallet = new DevWallet({ adapters: [adapter] });
|
|
138
|
+
wallet.register();
|
|
139
|
+
mountDevWallet(wallet);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Which adapter should I use?
|
|
143
|
+
|
|
144
|
+
| Adapter | Keys stored | Persists across reload | Best for | Caveats |
|
|
145
|
+
| ------------------------ | ----------------------- | ---------------------- | ----------------------------------------------- | -------------------------------- |
|
|
146
|
+
| `InMemorySignerAdapter` | Memory (Ed25519) | No | Quick prototyping, throwaway tests | New keys every page load |
|
|
147
|
+
| `WebCryptoSignerAdapter` | IndexedDB (Secp256r1) | Yes | Persistent dev wallet, keeping faucet coins | Browser-scoped, not exportable |
|
|
148
|
+
| `RemoteCliAdapter` | `sui` CLI keystore | Yes (via CLI) | Using same address you published contracts from | No personal message signing |
|
|
149
|
+
| `PasskeySignerAdapter` | OS keychain (Secp256r1) | Yes | Testing passkey/biometric flows | Requires user gesture every sign |
|
|
150
|
+
|
|
151
|
+
**Start here:** `WebCryptoSignerAdapter` — keys persist across page reloads, faucet once and keep
|
|
152
|
+
your coins. Best default for development.
|
|
153
|
+
|
|
154
|
+
**Fully ephemeral:** `InMemorySignerAdapter` — fresh keys every page load. Useful when you
|
|
155
|
+
specifically need a guaranteed clean slate.
|
|
156
|
+
|
|
157
|
+
**Match your deployed contracts:** `RemoteCliAdapter` — use the same address that ran
|
|
158
|
+
`sui move publish`.
|
|
159
|
+
|
|
160
|
+
You can use multiple adapters at the same time. The wallet aggregates accounts from all of them:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
devWalletInitializer({
|
|
164
|
+
adapters: [new WebCryptoSignerAdapter(), new InMemorySignerAdapter()],
|
|
165
|
+
mountUI: true,
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Options reference
|
|
170
|
+
|
|
171
|
+
Options for `devWalletInitializer` (dApp Kit plugin) and `DevWallet` constructor:
|
|
172
|
+
|
|
173
|
+
| Option | Type | Default | Description |
|
|
174
|
+
| ---------------------- | --------------------------------- | ------------------------- | --------------------------------------------------------------------------------------------- |
|
|
175
|
+
| `adapters` | `BaseSignerAdapter[]` | _(required)_ | Signer adapters that provide accounts and signing |
|
|
176
|
+
| `autoConnect` | `boolean` | `false` | Skip wallet picker — connect the first available account on load |
|
|
177
|
+
| `autoApprove` | `boolean \| (request) => boolean` | `false` | Sign without showing the approval modal. Pass a function for fine-grained control (see below) |
|
|
178
|
+
| `mountUI` | `boolean` | `false` | Show the floating wallet panel (accounts, balances, objects) |
|
|
179
|
+
| `createInitialAccount` | `boolean` | `true` | Auto-create an account on first visit if the adapter has none |
|
|
180
|
+
| `name` | `string` | `'Dev Wallet'` | Wallet name shown in the wallet picker |
|
|
181
|
+
| `networks` | `Record<string, string>` | devnet, testnet, localnet | Custom network URLs (only needed for non-default networks like staging) |
|
|
182
|
+
|
|
183
|
+
### Fine-grained `autoApprove`
|
|
184
|
+
|
|
185
|
+
Pass a function to approve only specific request types or chains:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
devWalletInitializer({
|
|
189
|
+
adapters: [new WebCryptoSignerAdapter()],
|
|
190
|
+
autoApprove: (request) => request.type === 'sign-transaction',
|
|
191
|
+
autoConnect: true,
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Note: `RemoteCliAdapter` and `PasskeySignerAdapter` never auto-sign regardless of this setting.
|
|
196
|
+
|
|
197
|
+
## Using the CLI adapter
|
|
198
|
+
|
|
199
|
+
The Remote CLI adapter connects to your local `sui` CLI over HTTP. Private keys never leave the
|
|
200
|
+
`sui` binary — only transaction bytes are sent for signing.
|
|
201
|
+
|
|
202
|
+
The easiest way is the standalone wallet:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npx @mysten-incubation/dev-wallet serve
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The terminal prints a URL with an auth token (e.g. `http://localhost:5174/?token=abc123`). Open it
|
|
209
|
+
in your browser — the token is saved automatically so popups can authenticate with the CLI signer.
|
|
210
|
+
|
|
211
|
+
To import a CLI account:
|
|
212
|
+
|
|
213
|
+
1. Click the **+** button on the Accounts tab (or go to Settings to verify the CLI Signer shows
|
|
214
|
+
"Connected")
|
|
215
|
+
2. Switch to the **Import** tab in the Add Account dialog
|
|
216
|
+
3. Select the address you want from the list (these come from your `sui` keystore)
|
|
217
|
+
4. Click **Import**
|
|
218
|
+
|
|
219
|
+
The imported account now appears alongside your other wallet accounts. When a dApp requests a
|
|
220
|
+
signature with that address, the transaction bytes are sent to the local `sui keytool sign` command
|
|
221
|
+
— your private key never leaves the CLI.
|
|
222
|
+
|
|
223
|
+
> **Note:** The CLI signer supports transaction signing only. Personal message signing
|
|
224
|
+
> (`sui keytool sign` only accepts TransactionData) will show an error. Use a WebCrypto or InMemory
|
|
225
|
+
> account for `signPersonalMessage`.
|
|
226
|
+
|
|
227
|
+
### Bookmarklet
|
|
228
|
+
|
|
229
|
+
The standalone wallet also serves a bookmarklet for quick injection into any dApp. You can find it
|
|
230
|
+
in the **Settings** tab — drag it to your bookmarks bar, or copy the console snippet from the
|
|
231
|
+
terminal output. Clicking the bookmarklet on any page registers the standalone wallet without
|
|
232
|
+
needing to modify the dApp's source code.
|
|
233
|
+
|
|
234
|
+
## Imports
|
|
235
|
+
|
|
236
|
+
| Import | What you get |
|
|
237
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
238
|
+
| `@mysten-incubation/dev-wallet` | `DevWallet`, `devWalletInitializer`, `DEFAULT_NETWORK_URLS`, config types |
|
|
239
|
+
| `@mysten-incubation/dev-wallet/adapters` | `InMemorySignerAdapter`, `WebCryptoSignerAdapter`, `PasskeySignerAdapter`, `RemoteCliAdapter`, `BaseSignerAdapter` |
|
|
240
|
+
| `@mysten-incubation/dev-wallet/ui` | `mountDevWallet()`, Lit web components |
|
|
241
|
+
| `@mysten-incubation/dev-wallet/react` | `useDevWallet` hook, `DevWalletProvider`, React-wrapped Lit components |
|
|
242
|
+
| `@mysten-incubation/dev-wallet/client` | `DevWalletClient`, `devWalletClientInitializer` for standalone wallet popup mode |
|
|
243
|
+
| `@mysten-incubation/dev-wallet/server` | `parseWalletRequest()`, `createCliSigningMiddleware()` for standalone wallet and CLI signing |
|
|
244
|
+
|
|
245
|
+
## Limitations
|
|
246
|
+
|
|
247
|
+
- **Not for production** — emits a console warning when `NODE_ENV=production`
|
|
248
|
+
- **RemoteCLI cannot sign personal messages** — `sui keytool sign` only supports transaction data
|
|
249
|
+
- **RemoteCLI and Passkey never auto-sign** — they always require explicit interaction, regardless
|
|
250
|
+
of the `autoApprove` setting
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region \0@oxc-project+runtime@0.107.0/helpers/decorate.js
|
|
2
|
+
function __decorate(decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { __decorate };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ManagedAccount, SignerAdapter } from "../types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/base-adapter.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Abstract base class implementing the shared boilerplate of {@link SignerAdapter}.
|
|
6
|
+
*
|
|
7
|
+
* Subclasses only need to implement `initialize()`, `id`, and `name`.
|
|
8
|
+
* All account list management, listener notification, and cleanup are handled here.
|
|
9
|
+
*/
|
|
10
|
+
declare abstract class BaseSignerAdapter implements SignerAdapter {
|
|
11
|
+
#private;
|
|
12
|
+
abstract readonly id: string;
|
|
13
|
+
abstract readonly name: string;
|
|
14
|
+
readonly allowAutoSign: boolean;
|
|
15
|
+
abstract initialize(): Promise<void>;
|
|
16
|
+
getAccounts(): ManagedAccount[];
|
|
17
|
+
getAccount(address: string): ManagedAccount | undefined;
|
|
18
|
+
onAccountsChanged(callback: (accounts: ManagedAccount[]) => void): () => void;
|
|
19
|
+
destroy(): void;
|
|
20
|
+
protected get _accounts(): readonly ManagedAccount[];
|
|
21
|
+
protected setInitialAccounts(accounts: ManagedAccount[]): void;
|
|
22
|
+
protected addAccount(account: ManagedAccount): void;
|
|
23
|
+
protected removeAccountByAddress(address: string): boolean;
|
|
24
|
+
/** Replace an account by address (e.g. after rename). */
|
|
25
|
+
protected replaceAccount(address: string, account: ManagedAccount): boolean;
|
|
26
|
+
/** Rename an account by rebuilding its ManagedAccount with a new label. */
|
|
27
|
+
protected _performRename(address: string, label: string): boolean;
|
|
28
|
+
protected getDefaultLabel(): string;
|
|
29
|
+
protected notifyListeners(): void;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { BaseSignerAdapter };
|
|
33
|
+
//# sourceMappingURL=base-adapter.d.mts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { buildManagedAccount } from "./build-managed-account.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/base-adapter.ts
|
|
4
|
+
/**
|
|
5
|
+
* Abstract base class implementing the shared boilerplate of {@link SignerAdapter}.
|
|
6
|
+
*
|
|
7
|
+
* Subclasses only need to implement `initialize()`, `id`, and `name`.
|
|
8
|
+
* All account list management, listener notification, and cleanup are handled here.
|
|
9
|
+
*/
|
|
10
|
+
var BaseSignerAdapter = class {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.allowAutoSign = true;
|
|
13
|
+
}
|
|
14
|
+
#accounts = [];
|
|
15
|
+
#listeners = new Set();
|
|
16
|
+
getAccounts() {
|
|
17
|
+
return [...this.#accounts];
|
|
18
|
+
}
|
|
19
|
+
getAccount(address) {
|
|
20
|
+
return this.#accounts.find((account) => account.address === address);
|
|
21
|
+
}
|
|
22
|
+
onAccountsChanged(callback) {
|
|
23
|
+
this.#listeners.add(callback);
|
|
24
|
+
return () => {
|
|
25
|
+
this.#listeners.delete(callback);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
destroy() {
|
|
29
|
+
this.#accounts = [];
|
|
30
|
+
this.#listeners.clear();
|
|
31
|
+
}
|
|
32
|
+
get _accounts() {
|
|
33
|
+
return this.#accounts;
|
|
34
|
+
}
|
|
35
|
+
setInitialAccounts(accounts) {
|
|
36
|
+
this.#accounts = accounts;
|
|
37
|
+
this.notifyListeners();
|
|
38
|
+
}
|
|
39
|
+
addAccount(account) {
|
|
40
|
+
this.#accounts.push(account);
|
|
41
|
+
this.notifyListeners();
|
|
42
|
+
}
|
|
43
|
+
removeAccountByAddress(address) {
|
|
44
|
+
const index = this.#accounts.findIndex((a) => a.address === address);
|
|
45
|
+
if (index === -1) return false;
|
|
46
|
+
this.#accounts.splice(index, 1);
|
|
47
|
+
this.notifyListeners();
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
/** Replace an account by address (e.g. after rename). */
|
|
51
|
+
replaceAccount(address, account) {
|
|
52
|
+
const index = this.#accounts.findIndex((a) => a.address === address);
|
|
53
|
+
if (index === -1) return false;
|
|
54
|
+
this.#accounts[index] = account;
|
|
55
|
+
this.notifyListeners();
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
/** Rename an account by rebuilding its ManagedAccount with a new label. */
|
|
59
|
+
_performRename(address, label) {
|
|
60
|
+
const account = this.getAccount(address);
|
|
61
|
+
if (!account) return false;
|
|
62
|
+
return this.replaceAccount(address, buildManagedAccount(account.signer, address, label));
|
|
63
|
+
}
|
|
64
|
+
getDefaultLabel() {
|
|
65
|
+
return `Account ${this.getAccounts().length + 1}`;
|
|
66
|
+
}
|
|
67
|
+
notifyListeners() {
|
|
68
|
+
const accounts = this.getAccounts();
|
|
69
|
+
for (const listener of this.#listeners) {
|
|
70
|
+
listener(accounts);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
export { BaseSignerAdapter };
|
|
77
|
+
//# sourceMappingURL=base-adapter.mjs.map
|
|
@@ -0,0 +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;;CAElC,YAA8B,EAAE;CAChC,aAAa,IAAI,KAA2C;CAI5D,cAAgC;AAC/B,SAAO,CAAC,GAAG,MAAKA,SAAU;;CAG3B,WAAW,SAA6C;AACvD,SAAO,MAAKA,SAAU,MAAM,YAAY,QAAQ,YAAY,QAAQ;;CAGrE,kBAAkB,UAA4D;AAC7E,QAAKC,UAAW,IAAI,SAAS;AAC7B,eAAa;AACZ,SAAKA,UAAW,OAAO,SAAS;;;CAIlC,UAAgB;AACf,QAAKD,WAAY,EAAE;AACnB,QAAKC,UAAW,OAAO;;CAKxB,IAAc,YAAuC;AACpD,SAAO,MAAKD;;CAGb,AAAU,mBAAmB,UAAkC;AAC9D,QAAKA,WAAY;AACjB,OAAK,iBAAiB;;CAGvB,AAAU,WAAW,SAA+B;AACnD,QAAKA,SAAU,KAAK,QAAQ;AAC5B,OAAK,iBAAiB;;CAGvB,AAAU,uBAAuB,SAA0B;EAC1D,MAAM,QAAQ,MAAKA,SAAU,WAAW,MAAM,EAAE,YAAY,QAAQ;AACpE,MAAI,UAAU,CAAC,EAAG,QAAO;AACzB,QAAKA,SAAU,OAAO,OAAO,EAAE;AAC/B,OAAK,iBAAiB;AACtB,SAAO;;;CAIR,AAAU,eAAe,SAAiB,SAAkC;EAC3E,MAAM,QAAQ,MAAKA,SAAU,WAAW,MAAM,EAAE,YAAY,QAAQ;AACpE,MAAI,UAAU,CAAC,EAAG,QAAO;AACzB,QAAKA,SAAU,SAAS;AACxB,OAAK,iBAAiB;AACtB,SAAO;;;CAIR,AAAU,eAAe,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,AAAU,kBAA0B;AACnC,SAAO,WAAW,KAAK,aAAa,CAAC,SAAS;;CAG/C,AAAU,kBAAwB;EACjC,MAAM,WAAW,KAAK,aAAa;AACnC,OAAK,MAAM,YAAY,MAAKC,WAAY;AACvC,YAAS,SAAS"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CreateAccountOptions, ImportAccountOptions, ManagedAccount, SignerAdapter } from "../types.mjs";
|
|
2
|
+
import { BaseSignerAdapter } from "./base-adapter.mjs";
|
|
3
|
+
import { buildManagedAccount } from "./build-managed-account.mjs";
|
|
4
|
+
import { InMemorySignerAdapter } from "./in-memory-adapter.mjs";
|
|
5
|
+
import { CliProxySigner, RemoteCliAdapter } from "./remote-cli-adapter.mjs";
|
|
6
|
+
import { WebCryptoSignerAdapter } from "./webcrypto-adapter.mjs";
|
|
7
|
+
import { PasskeySignerAdapter } from "./passkey-adapter.mjs";
|
|
8
|
+
export { BaseSignerAdapter, CliProxySigner, type CreateAccountOptions, type ImportAccountOptions, InMemorySignerAdapter, type ManagedAccount, PasskeySignerAdapter, RemoteCliAdapter, type SignerAdapter, WebCryptoSignerAdapter, buildManagedAccount };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { buildManagedAccount } from "./build-managed-account.mjs";
|
|
2
|
+
import { BaseSignerAdapter } from "./base-adapter.mjs";
|
|
3
|
+
import { InMemorySignerAdapter } from "./in-memory-adapter.mjs";
|
|
4
|
+
import { CliProxySigner, RemoteCliAdapter } from "./remote-cli-adapter.mjs";
|
|
5
|
+
import { WebCryptoSignerAdapter } from "./webcrypto-adapter.mjs";
|
|
6
|
+
import { PasskeySignerAdapter } from "./passkey-adapter.mjs";
|
|
7
|
+
|
|
8
|
+
export { BaseSignerAdapter, CliProxySigner, InMemorySignerAdapter, PasskeySignerAdapter, RemoteCliAdapter, WebCryptoSignerAdapter, buildManagedAccount };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ManagedAccount } from "../types.mjs";
|
|
2
|
+
import { IdentifierString } from "@mysten/wallet-standard";
|
|
3
|
+
import { Signer } from "@mysten/sui/cryptography";
|
|
4
|
+
|
|
5
|
+
//#region src/adapters/build-managed-account.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Build a {@link ManagedAccount} from a signer, address, label, and optional feature list.
|
|
8
|
+
*/
|
|
9
|
+
declare function buildManagedAccount(signer: Signer, address: string, label: string, features?: readonly IdentifierString[]): ManagedAccount;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { buildManagedAccount };
|
|
12
|
+
//# sourceMappingURL=build-managed-account.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-managed-account.d.mts","names":[],"sources":["../../src/adapters/build-managed-account.ts"],"mappings":";;;;;;;AAkBA;iBAAgB,mBAAA,CACf,MAAA,EAAQ,MAAA,EACR,OAAA,UACA,KAAA,UACA,QAAA,YAAoB,gBAAA,KAClB,cAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ReadonlyWalletAccount, SUI_CHAINS } from "@mysten/wallet-standard";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/build-managed-account.ts
|
|
4
|
+
const DEFAULT_FEATURES = [
|
|
5
|
+
"sui:signTransaction",
|
|
6
|
+
"sui:signAndExecuteTransaction",
|
|
7
|
+
"sui:signPersonalMessage"
|
|
8
|
+
];
|
|
9
|
+
/**
|
|
10
|
+
* Build a {@link ManagedAccount} from a signer, address, label, and optional feature list.
|
|
11
|
+
*/
|
|
12
|
+
function buildManagedAccount(signer, address, label, features) {
|
|
13
|
+
const walletAccount = new ReadonlyWalletAccount({
|
|
14
|
+
address,
|
|
15
|
+
label,
|
|
16
|
+
publicKey: signer.getPublicKey().toSuiBytes(),
|
|
17
|
+
chains: [...SUI_CHAINS],
|
|
18
|
+
features: [...features ?? DEFAULT_FEATURES]
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
address,
|
|
22
|
+
label,
|
|
23
|
+
signer,
|
|
24
|
+
walletAccount
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
export { buildManagedAccount };
|
|
30
|
+
//# sourceMappingURL=build-managed-account.mjs.map
|
|
@@ -0,0 +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;CACjB,MAAM,gBAAgB,IAAI,sBAAsB;EAC/C;EACA;EACA,WAAW,OAAO,cAAc,CAAC,YAAY;EAC7C,QAAQ,CAAC,GAAG,WAAW;EACvB,UAAU,CAAC,GAAI,YAAY,iBAAkB;EAC7C,CAAC;AACF,QAAO;EAAE;EAAS;EAAO;EAAQ;EAAe"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//#region src/adapters/idb-store.ts
|
|
2
|
+
/**
|
|
3
|
+
* Minimal IndexedDB key-value store replacing the `idb-keyval` package.
|
|
4
|
+
*
|
|
5
|
+
* The database connection is opened lazily on first use and reused for all
|
|
6
|
+
* subsequent operations.
|
|
7
|
+
*/
|
|
8
|
+
var IDBStore = class {
|
|
9
|
+
#dbName;
|
|
10
|
+
#storeName;
|
|
11
|
+
#db = null;
|
|
12
|
+
constructor(dbName, storeName) {
|
|
13
|
+
this.#dbName = dbName;
|
|
14
|
+
this.#storeName = storeName;
|
|
15
|
+
}
|
|
16
|
+
get(key) {
|
|
17
|
+
return this.#withTx("readonly", (s) => s.get(key));
|
|
18
|
+
}
|
|
19
|
+
async set(key, value) {
|
|
20
|
+
await this.#withTx("readwrite", (s) => s.put(value, key));
|
|
21
|
+
}
|
|
22
|
+
del(key) {
|
|
23
|
+
return this.#withTx("readwrite", (s) => s.delete(key));
|
|
24
|
+
}
|
|
25
|
+
entries() {
|
|
26
|
+
return this.#open().then((db) => new Promise((resolve, reject) => {
|
|
27
|
+
const tx = db.transaction(this.#storeName, "readonly");
|
|
28
|
+
const objectStore = tx.objectStore(this.#storeName);
|
|
29
|
+
const results = [];
|
|
30
|
+
const cursor = objectStore.openCursor();
|
|
31
|
+
cursor.onsuccess = () => {
|
|
32
|
+
const c = cursor.result;
|
|
33
|
+
if (c) {
|
|
34
|
+
results.push([c.key, c.value]);
|
|
35
|
+
c.continue();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
tx.oncomplete = () => resolve(results);
|
|
39
|
+
tx.onerror = () => reject(tx.error);
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
#open() {
|
|
43
|
+
if (!this.#db) {
|
|
44
|
+
this.#db = new Promise((resolve, reject) => {
|
|
45
|
+
const request = indexedDB.open(this.#dbName);
|
|
46
|
+
request.onupgradeneeded = () => {
|
|
47
|
+
if (!request.result.objectStoreNames.contains(this.#storeName)) {
|
|
48
|
+
request.result.createObjectStore(this.#storeName);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
request.onsuccess = () => resolve(request.result);
|
|
52
|
+
request.onerror = () => {
|
|
53
|
+
this.#db = null;
|
|
54
|
+
reject(request.error);
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return this.#db;
|
|
59
|
+
}
|
|
60
|
+
#withTx(mode, fn) {
|
|
61
|
+
return this.#open().then((db) => new Promise((resolve, reject) => {
|
|
62
|
+
const tx = db.transaction(this.#storeName, mode);
|
|
63
|
+
const req = fn(tx.objectStore(this.#storeName));
|
|
64
|
+
tx.oncomplete = () => resolve(req.result);
|
|
65
|
+
tx.onerror = () => reject(tx.error);
|
|
66
|
+
tx.onabort = () => reject(tx.error);
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { IDBStore };
|
|
73
|
+
//# sourceMappingURL=idb-store.mjs.map
|
|
@@ -0,0 +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,QAAKA,SAAU;AACf,QAAKC,YAAa;;CAGnB,IAAO,KAA0C;AAChD,SAAO,MAAKC,OAAQ,aAAa,MAAM,EAAE,IAAI,IAAI,CAA8B;;CAGhF,MAAM,IAAI,KAAkB,OAA+B;AAC1D,QAAM,MAAKA,OAAQ,cAAc,MAAM,EAAE,IAAI,OAAO,IAAI,CAAC;;CAG1D,IAAI,KAAiC;AACpC,SAAO,MAAKA,OAAQ,cAAc,MAAM,EAAE,OAAO,IAAI,CAAqB;;CAG3E,UAAuD;AACtD,SAAO,MAAKC,MAAO,CAAC,MAClB,OACA,IAAI,SAAS,SAAS,WAAW;GAChC,MAAM,KAAK,GAAG,YAAY,MAAKF,WAAY,WAAW;GACtD,MAAM,cAAc,GAAG,YAAY,MAAKA,UAAW;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,MAAKG,IAAK;AACd,SAAKA,KAAM,IAAI,SAAS,SAAS,WAAW;IAC3C,MAAM,UAAU,UAAU,KAAK,MAAKJ,OAAQ;AAC5C,YAAQ,wBAAwB;AAC/B,SAAI,CAAC,QAAQ,OAAO,iBAAiB,SAAS,MAAKC,UAAW,EAAE;AAC/D,cAAQ,OAAO,kBAAkB,MAAKA,UAAW;;;AAGnD,YAAQ,kBAAkB,QAAQ,QAAQ,OAAO;AACjD,YAAQ,gBAAgB;AACvB,WAAKG,KAAM;AACX,YAAO,QAAQ,MAAM;;KAErB;;AAEH,SAAO,MAAKA;;CAGb,QACC,MACA,IACa;AACb,SAAO,MAAKD,MAAO,CAAC,MAClB,OACA,IAAI,SAAS,SAAS,WAAW;GAChC,MAAM,KAAK,GAAG,YAAY,MAAKF,WAAY,KAAK;GAChD,MAAM,MAAM,GAAG,GAAG,YAAY,MAAKA,UAAW,CAAC;AAC/C,MAAG,mBAAmB,QAAQ,IAAI,OAAO;AACzC,MAAG,gBAAgB,OAAO,GAAG,MAAM;AACnC,MAAG,gBAAgB,OAAO,GAAG,MAAM;IAClC,CACH"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CreateAccountOptions, ImportAccountOptions, ManagedAccount } from "../types.mjs";
|
|
2
|
+
import { BaseSignerAdapter } from "./base-adapter.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/adapters/in-memory-adapter.d.ts
|
|
5
|
+
declare class InMemorySignerAdapter extends BaseSignerAdapter {
|
|
6
|
+
readonly id = "in-memory";
|
|
7
|
+
readonly name = "In-Memory Signer";
|
|
8
|
+
initialize(): Promise<void>;
|
|
9
|
+
createAccount(options?: CreateAccountOptions): Promise<ManagedAccount>;
|
|
10
|
+
importAccount(options: ImportAccountOptions): Promise<ManagedAccount>;
|
|
11
|
+
renameAccount(address: string, label: string): Promise<boolean>;
|
|
12
|
+
removeAccount(address: string): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { InMemorySignerAdapter };
|
|
16
|
+
//# sourceMappingURL=in-memory-adapter.d.mts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { buildManagedAccount } from "./build-managed-account.mjs";
|
|
2
|
+
import { BaseSignerAdapter } from "./base-adapter.mjs";
|
|
3
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
|
|
4
|
+
|
|
5
|
+
//#region src/adapters/in-memory-adapter.ts
|
|
6
|
+
var InMemorySignerAdapter = class extends BaseSignerAdapter {
|
|
7
|
+
constructor(..._args) {
|
|
8
|
+
super(..._args);
|
|
9
|
+
this.id = "in-memory";
|
|
10
|
+
this.name = "In-Memory Signer";
|
|
11
|
+
}
|
|
12
|
+
async initialize() {}
|
|
13
|
+
async createAccount(options) {
|
|
14
|
+
const keypair = new Ed25519Keypair();
|
|
15
|
+
const address = keypair.getPublicKey().toSuiAddress();
|
|
16
|
+
const label = options?.label ?? this.getDefaultLabel();
|
|
17
|
+
const managedAccount = buildManagedAccount(keypair, address, label);
|
|
18
|
+
this.addAccount(managedAccount);
|
|
19
|
+
return managedAccount;
|
|
20
|
+
}
|
|
21
|
+
async importAccount(options) {
|
|
22
|
+
const signer = options.signer;
|
|
23
|
+
if (!signer) {
|
|
24
|
+
throw new Error("In-memory adapter requires a signer to import");
|
|
25
|
+
}
|
|
26
|
+
const address = signer.toSuiAddress();
|
|
27
|
+
const existing = this.getAccount(address);
|
|
28
|
+
if (existing) return existing;
|
|
29
|
+
const label = options.label ?? this.getDefaultLabel();
|
|
30
|
+
const managedAccount = buildManagedAccount(signer, address, label);
|
|
31
|
+
this.addAccount(managedAccount);
|
|
32
|
+
return managedAccount;
|
|
33
|
+
}
|
|
34
|
+
async renameAccount(address, label) {
|
|
35
|
+
return this._performRename(address, label);
|
|
36
|
+
}
|
|
37
|
+
async removeAccount(address) {
|
|
38
|
+
return this.removeAccountByAddress(address);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { InMemorySignerAdapter };
|
|
44
|
+
//# sourceMappingURL=in-memory-adapter.mjs.map
|
|
@@ -0,0 +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;EACpC,MAAM,UAAU,QAAQ,cAAc,CAAC,cAAc;EACrD,MAAM,QAAQ,SAAS,SAAS,KAAK,iBAAiB;EAEtD,MAAM,iBAAiB,oBAAoB,SAAS,SAAS,MAAM;AACnE,OAAK,WAAW,eAAe;AAC/B,SAAO;;CAGR,MAAM,cAAc,SAAwD;EAC3E,MAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,QAAQ;AACZ,SAAM,IAAI,MAAM,gDAAgD;;EAEjE,MAAM,UAAU,OAAO,cAAc;EAErC,MAAM,WAAW,KAAK,WAAW,QAAQ;AACzC,MAAI,SAAU,QAAO;EAErB,MAAM,QAAQ,QAAQ,SAAS,KAAK,iBAAiB;EACrD,MAAM,iBAAiB,oBAAoB,QAAQ,SAAS,MAAM;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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CreateAccountOptions, ManagedAccount } from "../types.mjs";
|
|
2
|
+
import { BaseSignerAdapter } from "./base-adapter.mjs";
|
|
3
|
+
import { PasskeyProvider } from "@mysten/sui/keypairs/passkey";
|
|
4
|
+
|
|
5
|
+
//#region src/adapters/passkey-adapter.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Signer adapter backed by WebAuthn passkeys. Each signing operation triggers a
|
|
8
|
+
* browser biometric/PIN prompt. Account metadata is persisted in IndexedDB;
|
|
9
|
+
* private keys are managed by the browser/OS and never enter JavaScript.
|
|
10
|
+
*
|
|
11
|
+
* Browser only — requires `navigator.credentials` and `indexedDB`.
|
|
12
|
+
*/
|
|
13
|
+
declare class PasskeySignerAdapter extends BaseSignerAdapter {
|
|
14
|
+
#private;
|
|
15
|
+
readonly id = "passkey";
|
|
16
|
+
readonly name = "Passkey Signer";
|
|
17
|
+
readonly allowAutoSign = false;
|
|
18
|
+
constructor(options?: {
|
|
19
|
+
dbName?: string;
|
|
20
|
+
storeName?: string;
|
|
21
|
+
provider?: PasskeyProvider;
|
|
22
|
+
});
|
|
23
|
+
initialize(): Promise<void>;
|
|
24
|
+
protected getDefaultLabel(): string;
|
|
25
|
+
createAccount(options?: CreateAccountOptions): Promise<ManagedAccount>;
|
|
26
|
+
renameAccount(address: string, label: string): Promise<boolean>;
|
|
27
|
+
removeAccount(address: string): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { PasskeySignerAdapter };
|
|
31
|
+
//# sourceMappingURL=passkey-adapter.d.mts.map
|
|
@@ -0,0 +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"}
|