@shieldedtech/moth-wallet 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +62 -0
  2. package/dist/contract/args-parser.d.ts +29 -0
  3. package/dist/contract/args-parser.d.ts.map +1 -0
  4. package/dist/contract/args-parser.js +123 -0
  5. package/dist/contract/args-parser.js.map +1 -0
  6. package/dist/contract/artifact-loader.d.ts +26 -0
  7. package/dist/contract/artifact-loader.d.ts.map +1 -0
  8. package/dist/contract/artifact-loader.js +129 -0
  9. package/dist/contract/artifact-loader.js.map +1 -0
  10. package/dist/contract/call.d.ts +32 -0
  11. package/dist/contract/call.d.ts.map +1 -0
  12. package/dist/contract/call.js +245 -0
  13. package/dist/contract/call.js.map +1 -0
  14. package/dist/contract/deploy.d.ts +36 -0
  15. package/dist/contract/deploy.d.ts.map +1 -0
  16. package/dist/contract/deploy.js +388 -0
  17. package/dist/contract/deploy.js.map +1 -0
  18. package/dist/contract/fungible-token.d.ts +40 -0
  19. package/dist/contract/fungible-token.d.ts.map +1 -0
  20. package/dist/contract/fungible-token.js +88 -0
  21. package/dist/contract/fungible-token.js.map +1 -0
  22. package/dist/contract/initial-private-state.d.ts +18 -0
  23. package/dist/contract/initial-private-state.d.ts.map +1 -0
  24. package/dist/contract/initial-private-state.js +44 -0
  25. package/dist/contract/initial-private-state.js.map +1 -0
  26. package/dist/contract/maintenance.d.ts +72 -0
  27. package/dist/contract/maintenance.d.ts.map +1 -0
  28. package/dist/contract/maintenance.js +430 -0
  29. package/dist/contract/maintenance.js.map +1 -0
  30. package/dist/contract/state.d.ts +16 -0
  31. package/dist/contract/state.d.ts.map +1 -0
  32. package/dist/contract/state.js +18 -0
  33. package/dist/contract/state.js.map +1 -0
  34. package/dist/contract/witness-loader.d.ts +3 -0
  35. package/dist/contract/witness-loader.d.ts.map +1 -0
  36. package/dist/contract/witness-loader.js +27 -0
  37. package/dist/contract/witness-loader.js.map +1 -0
  38. package/dist/daemon/api-keys.d.ts +66 -0
  39. package/dist/daemon/api-keys.d.ts.map +1 -0
  40. package/dist/daemon/api-keys.js +222 -0
  41. package/dist/daemon/api-keys.js.map +1 -0
  42. package/dist/daemon/audit-log.d.ts +65 -0
  43. package/dist/daemon/audit-log.d.ts.map +1 -0
  44. package/dist/daemon/audit-log.js +73 -0
  45. package/dist/daemon/audit-log.js.map +1 -0
  46. package/dist/daemon/client.d.ts +63 -0
  47. package/dist/daemon/client.d.ts.map +1 -0
  48. package/dist/daemon/client.js +214 -0
  49. package/dist/daemon/client.js.map +1 -0
  50. package/dist/daemon/confirmation-queue.d.ts +46 -0
  51. package/dist/daemon/confirmation-queue.d.ts.map +1 -0
  52. package/dist/daemon/confirmation-queue.js +92 -0
  53. package/dist/daemon/confirmation-queue.js.map +1 -0
  54. package/dist/daemon/index.d.ts +23 -0
  55. package/dist/daemon/index.d.ts.map +1 -0
  56. package/dist/daemon/index.js +26 -0
  57. package/dist/daemon/index.js.map +1 -0
  58. package/dist/daemon/protocol.d.ts +40 -0
  59. package/dist/daemon/protocol.d.ts.map +1 -0
  60. package/dist/daemon/protocol.js +104 -0
  61. package/dist/daemon/protocol.js.map +1 -0
  62. package/dist/daemon/server.d.ts +158 -0
  63. package/dist/daemon/server.d.ts.map +1 -0
  64. package/dist/daemon/server.js +297 -0
  65. package/dist/daemon/server.js.map +1 -0
  66. package/dist/daemon/wallet-handlers.d.ts +37 -0
  67. package/dist/daemon/wallet-handlers.d.ts.map +1 -0
  68. package/dist/daemon/wallet-handlers.js +533 -0
  69. package/dist/daemon/wallet-handlers.js.map +1 -0
  70. package/dist/daemon/wallet-rpc-parsers.d.ts +14 -0
  71. package/dist/daemon/wallet-rpc-parsers.d.ts.map +1 -0
  72. package/dist/daemon/wallet-rpc-parsers.js +259 -0
  73. package/dist/daemon/wallet-rpc-parsers.js.map +1 -0
  74. package/dist/daemon/wallet-rpc-types.d.ts +138 -0
  75. package/dist/daemon/wallet-rpc-types.d.ts.map +1 -0
  76. package/dist/daemon/wallet-rpc-types.js +11 -0
  77. package/dist/daemon/wallet-rpc-types.js.map +1 -0
  78. package/dist/diagnostics/fs-timing-store.d.ts +29 -0
  79. package/dist/diagnostics/fs-timing-store.d.ts.map +1 -0
  80. package/dist/diagnostics/fs-timing-store.js +81 -0
  81. package/dist/diagnostics/fs-timing-store.js.map +1 -0
  82. package/dist/diagnostics/timings.d.ts +64 -0
  83. package/dist/diagnostics/timings.d.ts.map +1 -0
  84. package/dist/diagnostics/timings.js +100 -0
  85. package/dist/diagnostics/timings.js.map +1 -0
  86. package/dist/index.d.ts +37 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +47 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/network/indexer-client.d.ts +66 -0
  91. package/dist/network/indexer-client.d.ts.map +1 -0
  92. package/dist/network/indexer-client.js +112 -0
  93. package/dist/network/indexer-client.js.map +1 -0
  94. package/dist/network/node-client.d.ts +27 -0
  95. package/dist/network/node-client.d.ts.map +1 -0
  96. package/dist/network/node-client.js +94 -0
  97. package/dist/network/node-client.js.map +1 -0
  98. package/dist/proof/client.d.ts +15 -0
  99. package/dist/proof/client.d.ts.map +1 -0
  100. package/dist/proof/client.js +77 -0
  101. package/dist/proof/client.js.map +1 -0
  102. package/dist/proof/provider.d.ts +12 -0
  103. package/dist/proof/provider.d.ts.map +1 -0
  104. package/dist/proof/provider.js +96 -0
  105. package/dist/proof/provider.js.map +1 -0
  106. package/dist/providers/index.d.ts +2 -0
  107. package/dist/providers/index.d.ts.map +1 -0
  108. package/dist/providers/index.js +2 -0
  109. package/dist/providers/index.js.map +1 -0
  110. package/dist/providers/midnight-provider.d.ts +11 -0
  111. package/dist/providers/midnight-provider.d.ts.map +1 -0
  112. package/dist/providers/midnight-provider.js +30 -0
  113. package/dist/providers/midnight-provider.js.map +1 -0
  114. package/dist/storage/adapter.d.ts +8 -0
  115. package/dist/storage/adapter.d.ts.map +1 -0
  116. package/dist/storage/adapter.js +2 -0
  117. package/dist/storage/adapter.js.map +1 -0
  118. package/dist/storage/fs-adapter.d.ts +14 -0
  119. package/dist/storage/fs-adapter.d.ts.map +1 -0
  120. package/dist/storage/fs-adapter.js +126 -0
  121. package/dist/storage/fs-adapter.js.map +1 -0
  122. package/dist/storage/safe-path.d.ts +13 -0
  123. package/dist/storage/safe-path.d.ts.map +1 -0
  124. package/dist/storage/safe-path.js +35 -0
  125. package/dist/storage/safe-path.js.map +1 -0
  126. package/dist/sync/activity.d.ts +53 -0
  127. package/dist/sync/activity.d.ts.map +1 -0
  128. package/dist/sync/activity.js +92 -0
  129. package/dist/sync/activity.js.map +1 -0
  130. package/dist/sync/dust-registration-estimate.d.ts +54 -0
  131. package/dist/sync/dust-registration-estimate.d.ts.map +1 -0
  132. package/dist/sync/dust-registration-estimate.js +103 -0
  133. package/dist/sync/dust-registration-estimate.js.map +1 -0
  134. package/dist/sync/node-sync-store.d.ts +10 -0
  135. package/dist/sync/node-sync-store.d.ts.map +1 -0
  136. package/dist/sync/node-sync-store.js +42 -0
  137. package/dist/sync/node-sync-store.js.map +1 -0
  138. package/dist/sync/operations.d.ts +138 -0
  139. package/dist/sync/operations.d.ts.map +1 -0
  140. package/dist/sync/operations.js +395 -0
  141. package/dist/sync/operations.js.map +1 -0
  142. package/dist/sync/preseed-parts.d.ts +18 -0
  143. package/dist/sync/preseed-parts.d.ts.map +1 -0
  144. package/dist/sync/preseed-parts.js +33 -0
  145. package/dist/sync/preseed-parts.js.map +1 -0
  146. package/dist/sync/preseed.d.ts +95 -0
  147. package/dist/sync/preseed.d.ts.map +1 -0
  148. package/dist/sync/preseed.js +365 -0
  149. package/dist/sync/preseed.js.map +1 -0
  150. package/dist/sync/progress.d.ts +45 -0
  151. package/dist/sync/progress.d.ts.map +1 -0
  152. package/dist/sync/progress.js +51 -0
  153. package/dist/sync/progress.js.map +1 -0
  154. package/dist/sync/sdk-dedup.d.ts +53 -0
  155. package/dist/sync/sdk-dedup.d.ts.map +1 -0
  156. package/dist/sync/sdk-dedup.js +134 -0
  157. package/dist/sync/sdk-dedup.js.map +1 -0
  158. package/dist/sync/sync-store.d.ts +33 -0
  159. package/dist/sync/sync-store.d.ts.map +1 -0
  160. package/dist/sync/sync-store.js +45 -0
  161. package/dist/sync/sync-store.js.map +1 -0
  162. package/dist/sync/wallet-sync.d.ts +153 -0
  163. package/dist/sync/wallet-sync.d.ts.map +1 -0
  164. package/dist/sync/wallet-sync.js +943 -0
  165. package/dist/sync/wallet-sync.js.map +1 -0
  166. package/dist/types/errors.d.ts +18 -0
  167. package/dist/types/errors.d.ts.map +1 -0
  168. package/dist/types/errors.js +33 -0
  169. package/dist/types/errors.js.map +1 -0
  170. package/dist/types/exit-codes.d.ts +8 -0
  171. package/dist/types/exit-codes.d.ts.map +1 -0
  172. package/dist/types/exit-codes.js +7 -0
  173. package/dist/types/exit-codes.js.map +1 -0
  174. package/dist/types/index.d.ts +6 -0
  175. package/dist/types/index.d.ts.map +1 -0
  176. package/dist/types/index.js +3 -0
  177. package/dist/types/index.js.map +1 -0
  178. package/dist/types/network.d.ts +65 -0
  179. package/dist/types/network.d.ts.map +1 -0
  180. package/dist/types/network.js +108 -0
  181. package/dist/types/network.js.map +1 -0
  182. package/dist/types/tokens.d.ts +3 -0
  183. package/dist/types/tokens.d.ts.map +1 -0
  184. package/dist/types/tokens.js +11 -0
  185. package/dist/types/tokens.js.map +1 -0
  186. package/dist/types/transaction.d.ts +13 -0
  187. package/dist/types/transaction.d.ts.map +1 -0
  188. package/dist/types/transaction.js +2 -0
  189. package/dist/types/transaction.js.map +1 -0
  190. package/dist/types/wallet.d.ts +82 -0
  191. package/dist/types/wallet.d.ts.map +1 -0
  192. package/dist/types/wallet.js +2 -0
  193. package/dist/types/wallet.js.map +1 -0
  194. package/dist/wallet/address-validate.d.ts +7 -0
  195. package/dist/wallet/address-validate.d.ts.map +1 -0
  196. package/dist/wallet/address-validate.js +28 -0
  197. package/dist/wallet/address-validate.js.map +1 -0
  198. package/dist/wallet/address.d.ts +32 -0
  199. package/dist/wallet/address.d.ts.map +1 -0
  200. package/dist/wallet/address.js +107 -0
  201. package/dist/wallet/address.js.map +1 -0
  202. package/dist/wallet/app-secret.d.ts +15 -0
  203. package/dist/wallet/app-secret.d.ts.map +1 -0
  204. package/dist/wallet/app-secret.js +45 -0
  205. package/dist/wallet/app-secret.js.map +1 -0
  206. package/dist/wallet/balance-format.d.ts +12 -0
  207. package/dist/wallet/balance-format.d.ts.map +1 -0
  208. package/dist/wallet/balance-format.js +51 -0
  209. package/dist/wallet/balance-format.js.map +1 -0
  210. package/dist/wallet/batch-transfer.d.ts +36 -0
  211. package/dist/wallet/batch-transfer.d.ts.map +1 -0
  212. package/dist/wallet/batch-transfer.js +93 -0
  213. package/dist/wallet/batch-transfer.js.map +1 -0
  214. package/dist/wallet/keystore.d.ts +16 -0
  215. package/dist/wallet/keystore.d.ts.map +1 -0
  216. package/dist/wallet/keystore.js +76 -0
  217. package/dist/wallet/keystore.js.map +1 -0
  218. package/dist/wallet/manager.d.ts +77 -0
  219. package/dist/wallet/manager.d.ts.map +1 -0
  220. package/dist/wallet/manager.js +474 -0
  221. package/dist/wallet/manager.js.map +1 -0
  222. package/dist/wallet/mnemonic.d.ts +5 -0
  223. package/dist/wallet/mnemonic.d.ts.map +1 -0
  224. package/dist/wallet/mnemonic.js +28 -0
  225. package/dist/wallet/mnemonic.js.map +1 -0
  226. package/dist/wallet/sign-message.d.ts +20 -0
  227. package/dist/wallet/sign-message.d.ts.map +1 -0
  228. package/dist/wallet/sign-message.js +58 -0
  229. package/dist/wallet/sign-message.js.map +1 -0
  230. package/package.json +55 -0
@@ -0,0 +1,158 @@
1
+ import { type Server } from 'node:net';
2
+ /**
3
+ * Transport binding. Stage 1 supports only `unix`. Stage 2 adds
4
+ * `tcp` for loopback / private-network exposure; the JSON-RPC frame
5
+ * format and verb surface stay identical. See
6
+ * docs/spec/wallet-service/01-architecture.md D-ARCH-1.
7
+ */
8
+ export type DaemonBind = {
9
+ readonly transport: 'unix';
10
+ readonly socketPath: string;
11
+ } | {
12
+ readonly transport: 'tcp';
13
+ readonly host: string;
14
+ readonly port: number;
15
+ };
16
+ /**
17
+ * Stage-2.5 scope set. Each API key declares which of these it
18
+ * holds; the daemon's per-method gate checks the required scope
19
+ * (declared by the handler factory) against the connection's set.
20
+ *
21
+ * 'read' → getState (and any other read-only verbs we add)
22
+ * 'write' → every L3-gated write verb (transfer, deploy, call,
23
+ * dust, maintenance, submitTransaction, clearSyncCache)
24
+ *
25
+ * Unix connections without an auth handler skip the scope check —
26
+ * kernel UID is the AuthN and granular scoping inside a single UID
27
+ * is theatre. The check only fires on connections that actually
28
+ * authenticated through `auth`.
29
+ */
30
+ export type Scope = 'read' | 'write';
31
+ export type ConnectionContext = {
32
+ /** Numeric id local to the daemon; useful for logs. */
33
+ readonly id: number;
34
+ /** Transport this connection arrived on. Reserved for stage-2
35
+ * AuthN to enforce "Bearer required on TCP, not on Unix" rules. */
36
+ readonly remote: 'unix' | 'tcp';
37
+ /** Best-effort peer label — `unix` for Unix sockets, the
38
+ * `host:port` of the peer for TCP. */
39
+ readonly peer?: string;
40
+ /** API key id once the `auth` RPC succeeds on this connection.
41
+ * Absent on the Unix transport (kernel UID is the AuthN there)
42
+ * and on TCP connections that haven't authenticated yet — those
43
+ * are blocked from every method besides `auth` and `version`. */
44
+ apiKeyId?: string;
45
+ /** Friendly label of the authenticated key, stamped at `auth`
46
+ * time. Surfaced in audit log + connect logs. */
47
+ apiKeyLabel?: string;
48
+ /** Scope set carried by the authenticated key. Used by the
49
+ * per-method gate to enforce read vs write. */
50
+ scopes?: readonly Scope[];
51
+ };
52
+ /**
53
+ * Stage-2 AuthN hook. Takes the wire token (`<id>.<secret>` shape
54
+ * generated by `moth daemon key gen`), returns the authenticated
55
+ * identity on success or null on any failure. The server only
56
+ * accepts an `auth` RPC on a connection when this handler is set;
57
+ * once it has accepted one, all other methods carry the resulting
58
+ * `apiKeyId` in their ConnectionContext.
59
+ *
60
+ * Unix-transport daemons typically run without an auth handler —
61
+ * kernel UID on the 0600 socket is sufficient. TCP daemons MUST
62
+ * supply one or `startDaemon` refuses to bind.
63
+ */
64
+ export type AuthHandler = (token: string) => Promise<AuthResult | null> | AuthResult | null;
65
+ export interface AuthResult {
66
+ readonly apiKeyId: string;
67
+ readonly label?: string;
68
+ readonly scopes?: readonly string[];
69
+ }
70
+ export type RpcHandler<P = unknown, R = unknown> = ((params: P, ctx: ConnectionContext) => Promise<R> | R) & {
71
+ /**
72
+ * Scope required to invoke this handler when an auth handler is
73
+ * configured. When absent, defaults to `'write'` — every
74
+ * historically-existing handler is treated as a write op so a
75
+ * read-only key cannot accidentally unlock spend verbs. The
76
+ * `version` and `auth` built-ins are always reachable regardless
77
+ * of scope (the gate special-cases them).
78
+ */
79
+ scope?: Scope;
80
+ };
81
+ export interface DaemonOptions {
82
+ /**
83
+ * Transport binding. Use either this OR the legacy `socketPath`
84
+ * field (mutually exclusive). When both are absent, startDaemon
85
+ * throws.
86
+ */
87
+ readonly bind?: DaemonBind;
88
+ /**
89
+ * Legacy Unix-socket path. Equivalent to
90
+ * `bind: {transport: 'unix', socketPath}`. Kept for backwards
91
+ * compatibility with stage-1 call sites; new code should prefer
92
+ * `bind`.
93
+ */
94
+ readonly socketPath?: string;
95
+ /** Map of method name → handler. The reserved method `version` is
96
+ * installed automatically and cannot be overridden. */
97
+ readonly handlers: Readonly<Record<string, RpcHandler>>;
98
+ /** Daemon build identifier surfaced in the `version` handshake. */
99
+ readonly daemonVersion: string;
100
+ /** Optional logger hook. Defaults to silent. */
101
+ readonly onLog?: (level: 'info' | 'warn' | 'error', msg: string) => void;
102
+ /**
103
+ * Stage-2 AuthN handler. When set, the daemon installs an `auth`
104
+ * RPC and gates every other method behind a successful auth call
105
+ * on the same connection. When omitted, the daemon accepts every
106
+ * connection unauthenticated (the stage-1 / Unix-transport model).
107
+ *
108
+ * **TCP transport requires this**: `startDaemon` throws if
109
+ * `bind.transport === 'tcp'` and `auth` is undefined. Without it,
110
+ * exposing the daemon's write verbs over the network would have
111
+ * no AuthN at all.
112
+ */
113
+ readonly auth?: AuthHandler;
114
+ /**
115
+ * Fired on every `auth` RPC outcome so the host can write a
116
+ * permanent audit record of authentication successes and failures
117
+ * (the live log alone leaves no lasting trail of break-in attempts).
118
+ */
119
+ readonly onAuthEvent?: (event: {
120
+ readonly outcome: 'success' | 'failure';
121
+ readonly apiKeyId?: string;
122
+ readonly peer?: string;
123
+ }) => void;
124
+ /**
125
+ * Fired on inbound client activity (connect + each data chunk). The
126
+ * host uses this to drive an idle auto-lock so a long-running daemon
127
+ * isn't a permanently-unlocked key.
128
+ */
129
+ readonly onActivity?: () => void;
130
+ }
131
+ export interface DaemonHandle {
132
+ /** Normalised binding the daemon listens on. */
133
+ readonly bind: DaemonBind;
134
+ /**
135
+ * Legacy: Unix socket path if `bind.transport === 'unix'`, else
136
+ * empty string. Preserved so existing callers reading
137
+ * `handle.socketPath` keep working.
138
+ */
139
+ readonly socketPath: string;
140
+ /**
141
+ * Operator-friendly label of where the daemon is listening, e.g.
142
+ * `unix:///Users/.../wallet.sock` or `tcp://127.0.0.1:8765`.
143
+ */
144
+ readonly listenAddress: string;
145
+ /** Stop accepting new connections, close all active ones, and
146
+ * clean transport-specific artifacts (the Unix socket file).
147
+ * Resolves once everything is torn down. */
148
+ close(): Promise<void>;
149
+ }
150
+ export declare function startDaemon(opts: DaemonOptions): Promise<DaemonHandle>;
151
+ /** Test-only helper. Exported for unit tests that need to bind a temporary
152
+ * socket without ensuring the directory exists. Production code should
153
+ * always go through startDaemon. */
154
+ export declare function _stat(path: string): Promise<{
155
+ mode: number;
156
+ }>;
157
+ export type { Server };
158
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,297 @@
1
+ // Daemon server: binds a Unix-domain socket, applies L1 filesystem perms,
2
+ // accepts client connections, and dispatches RPC requests to registered
3
+ // handlers.
4
+ //
5
+ // Threat model addressed by this layer:
6
+ // - Other users on the same machine connecting to the socket — blocked
7
+ // at the kernel by 0600 socket-file perms inside a 0700 directory,
8
+ // both owned by the daemon's UID.
9
+ // - Stale socket file from a crashed previous daemon — detected on bind
10
+ // and removed only after probing that no one is actually listening.
11
+ //
12
+ // Per-operation confirmation (L3) is the handler's responsibility — server
13
+ // passes the connection context through so handlers can ask the TUI to
14
+ // surface a modal and only return after user consent.
15
+ import { createServer } from 'node:net';
16
+ import { chmod, mkdir, stat, unlink, access } from 'node:fs/promises';
17
+ import { createConnection } from 'node:net';
18
+ import { dirname } from 'node:path';
19
+ import { encodeFrame, FrameDecoder, PROTOCOL_VERSION, DaemonProtocolError, } from './protocol.js';
20
+ export async function startDaemon(opts) {
21
+ const { handlers, daemonVersion } = opts;
22
+ const log = opts.onLog ?? (() => { });
23
+ // Normalise the binding. Accept either `bind` (new shape) or the
24
+ // legacy `socketPath` string.
25
+ const bind = opts.bind
26
+ ? opts.bind
27
+ : opts.socketPath
28
+ ? { transport: 'unix', socketPath: opts.socketPath }
29
+ : (() => {
30
+ throw new Error('startDaemon: either `bind` or `socketPath` is required');
31
+ })();
32
+ // Stage-2 invariant: TCP must have an auth handler. Without it the
33
+ // operator would be exposing every write verb (transfer, deploy,
34
+ // call, dust, maintenance) to anyone who can reach the port.
35
+ // Unix transport stays optional — kernel UID on the 0600 socket
36
+ // is sufficient AuthN for the local-only model.
37
+ if (bind.transport === 'tcp' && !opts.auth) {
38
+ throw new Error('startDaemon: TCP transport requires an `auth` handler. Provision API keys via `moth daemon key gen` and pass the resulting ApiKeyStore-backed handler.');
39
+ }
40
+ // Per-transport pre-listen work (Unix only — directory perms,
41
+ // stale-file reap).
42
+ if (bind.transport === 'unix') {
43
+ await ensureSocketDir(dirname(bind.socketPath));
44
+ await reapStaleSocket(bind.socketPath, log);
45
+ }
46
+ const builtins = {
47
+ version: () => ({ protocol: PROTOCOL_VERSION, daemon: daemonVersion }),
48
+ };
49
+ if (opts.auth) {
50
+ builtins.auth = async (rawParams, ctx) => {
51
+ const params = rawParams;
52
+ if (typeof params?.token !== 'string' || params.token.length === 0) {
53
+ throw new DaemonProtocolError('INVALID_PARAMS', 'auth.token must be a non-empty string');
54
+ }
55
+ const result = await opts.auth(params.token);
56
+ if (!result) {
57
+ opts.onAuthEvent?.({ outcome: 'failure', peer: ctx.peer });
58
+ throw new DaemonProtocolError('UNAUTHORIZED', 'auth failed');
59
+ }
60
+ opts.onAuthEvent?.({ outcome: 'success', apiKeyId: result.apiKeyId, peer: ctx.peer });
61
+ // Mutate the per-connection context. attachConnectionHandlers
62
+ // hands the same `ctx` object to every subsequent dispatch, so
63
+ // gating later methods on `ctx.apiKeyId` is sufficient.
64
+ ctx.apiKeyId = result.apiKeyId;
65
+ ctx.apiKeyLabel = result.label;
66
+ // Normalise scopes to the typed set. Unknown scopes are
67
+ // silently dropped — they could never satisfy a known
68
+ // requirement anyway.
69
+ const VALID = ['read', 'write'];
70
+ const parsed = (result.scopes ?? ['write'])
71
+ .filter((s) => VALID.includes(s));
72
+ ctx.scopes = parsed;
73
+ log('info', `client ${ctx.id} authed as key ${result.apiKeyId} (${result.label ?? '-'}) scopes=[${parsed.join(',')}]`);
74
+ return { apiKeyId: result.apiKeyId, label: result.label, scopes: parsed };
75
+ };
76
+ }
77
+ const allHandlers = { ...handlers, ...builtins };
78
+ // Methods always reachable without auth. `version` is the
79
+ // handshake (clients call it before auth to verify protocol
80
+ // version), `auth` itself obviously can't require auth.
81
+ const ALWAYS_OPEN = new Set(['version', 'auth']);
82
+ // Wrap every other handler with an auth + scope check when auth
83
+ // is on. The auth check is per-call on the connection context (not
84
+ // per method registration), so a single connection that
85
+ // successfully authenticates unlocks every method it has scope for
86
+ // for the rest of its lifetime. The scope check looks at the
87
+ // handler's declared `scope` (defaulting to 'write' when absent,
88
+ // so a new handler without the annotation cannot be accidentally
89
+ // called by a read-only key).
90
+ const gated = {};
91
+ for (const [name, h] of Object.entries(allHandlers)) {
92
+ if (ALWAYS_OPEN.has(name) || !opts.auth) {
93
+ gated[name] = h;
94
+ continue;
95
+ }
96
+ const required = h.scope ?? 'write';
97
+ const wrapper = async (params, ctx) => {
98
+ if (!ctx.apiKeyId) {
99
+ throw new DaemonProtocolError('UNAUTHORIZED', `method "${name}" requires authentication — call \`auth\` with a valid \`<id>.<secret>\` token first`);
100
+ }
101
+ if (ctx.scopes && !ctx.scopes.includes(required)) {
102
+ throw new DaemonProtocolError('UNAUTHORIZED', `method "${name}" requires the "${required}" scope; key ${ctx.apiKeyId} has [${(ctx.scopes ?? []).join(', ')}]`);
103
+ }
104
+ return h(params, ctx);
105
+ };
106
+ // Forward the scope annotation in case a future inspector reads
107
+ // it back off the gated map.
108
+ wrapper.scope = required;
109
+ gated[name] = wrapper;
110
+ }
111
+ const server = createServer();
112
+ let nextConnId = 1;
113
+ const liveSockets = new Set();
114
+ server.on('connection', (sock) => {
115
+ const remote = bind.transport === 'tcp' ? 'tcp' : 'unix';
116
+ const peer = bind.transport === 'tcp'
117
+ ? `${sock.remoteAddress ?? '?'}:${sock.remotePort ?? '?'}`
118
+ : 'unix';
119
+ const ctx = { id: nextConnId++, remote, peer };
120
+ liveSockets.add(sock);
121
+ opts.onActivity?.();
122
+ log('info', `client ${ctx.id} connected (${peer})`);
123
+ attachConnectionHandlers(sock, ctx, gated, log, opts.onActivity);
124
+ sock.on('close', () => {
125
+ liveSockets.delete(sock);
126
+ log('info', `client ${ctx.id} disconnected`);
127
+ });
128
+ });
129
+ server.on('error', (err) => {
130
+ log('error', `daemon server error: ${err.message}`);
131
+ });
132
+ await new Promise((resolve, reject) => {
133
+ const onListen = () => {
134
+ server.off('error', onError);
135
+ resolve();
136
+ };
137
+ const onError = (err) => {
138
+ server.off('listening', onListen);
139
+ reject(err);
140
+ };
141
+ server.once('listening', onListen);
142
+ server.once('error', onError);
143
+ if (bind.transport === 'unix') {
144
+ server.listen(bind.socketPath);
145
+ }
146
+ else {
147
+ // TCP: bind to the requested host (caller is responsible for
148
+ // restricting to loopback — 127.0.0.1 — at stage 2; only
149
+ // stage-3 deployments behind a reverse proxy should bind 0.0.0.0
150
+ // and rely on the proxy's firewall + AuthN for safety).
151
+ server.listen(bind.port, bind.host);
152
+ }
153
+ });
154
+ let listenAddress;
155
+ if (bind.transport === 'unix') {
156
+ // L1: tighten the socket file to owner-only access. createServer
157
+ // doesn't do this for us; the file is created with the process
158
+ // umask, which is typically too permissive. The TCP transport
159
+ // has no equivalent — relies on loopback bind + AuthN at stage 2.
160
+ await chmod(bind.socketPath, 0o600);
161
+ listenAddress = `unix://${bind.socketPath}`;
162
+ }
163
+ else {
164
+ listenAddress = `tcp://${bind.host}:${bind.port}`;
165
+ }
166
+ log('info', `daemon listening at ${listenAddress}`);
167
+ return {
168
+ bind,
169
+ socketPath: bind.transport === 'unix' ? bind.socketPath : '',
170
+ listenAddress,
171
+ async close() {
172
+ log('info', 'daemon shutting down');
173
+ for (const sock of liveSockets)
174
+ sock.destroy();
175
+ liveSockets.clear();
176
+ await new Promise((resolve) => server.close(() => resolve()));
177
+ if (bind.transport === 'unix') {
178
+ await unlink(bind.socketPath).catch(() => { });
179
+ }
180
+ },
181
+ };
182
+ }
183
+ async function ensureSocketDir(dir) {
184
+ await mkdir(dir, { recursive: true, mode: 0o700 });
185
+ // chmod separately so that an existing dir gets its perms tightened too;
186
+ // mkdir({mode}) only applies to newly-created directories.
187
+ await chmod(dir, 0o700);
188
+ }
189
+ /**
190
+ * If the socket file already exists, probe whether anyone is actually
191
+ * listening. If a peer accepts our connect, fail loud — another daemon is
192
+ * alive. If the connect is refused or times out quickly, treat the file as
193
+ * a leftover from a crashed previous instance and unlink it.
194
+ */
195
+ async function reapStaleSocket(socketPath, log) {
196
+ try {
197
+ await access(socketPath);
198
+ }
199
+ catch {
200
+ return; // no file, nothing to reap
201
+ }
202
+ const alive = await probeListener(socketPath);
203
+ if (alive) {
204
+ throw new Error(`another moth daemon is already listening at ${socketPath}; refusing to bind`);
205
+ }
206
+ log('warn', `removing stale socket at ${socketPath}`);
207
+ await unlink(socketPath).catch(() => { });
208
+ }
209
+ function probeListener(socketPath) {
210
+ return new Promise((resolve) => {
211
+ const probe = createConnection(socketPath);
212
+ const cleanup = (alive) => {
213
+ probe.removeAllListeners();
214
+ probe.destroy();
215
+ resolve(alive);
216
+ };
217
+ probe.once('connect', () => cleanup(true));
218
+ probe.once('error', () => cleanup(false));
219
+ // Defensive: 2s is plenty for a local socket; if we hang past that
220
+ // assume something is wrong and treat as dead so the daemon can boot.
221
+ setTimeout(() => cleanup(false), 2000).unref();
222
+ });
223
+ }
224
+ function attachConnectionHandlers(sock, ctx, handlers, log, onActivity) {
225
+ const decoder = new FrameDecoder();
226
+ sock.on('data', async (chunk) => {
227
+ onActivity?.();
228
+ let frames;
229
+ try {
230
+ frames = decoder.push(chunk);
231
+ }
232
+ catch (err) {
233
+ log('warn', `client ${ctx.id} sent malformed frame: ${err.message}`);
234
+ sock.destroy();
235
+ return;
236
+ }
237
+ for (const frame of frames) {
238
+ if (frame.type !== 'request') {
239
+ // Servers don't currently accept response frames from clients —
240
+ // the protocol is request/response, not bidirectional RPC.
241
+ sendFrame(sock, {
242
+ id: frame.id,
243
+ type: 'response',
244
+ error: { code: 'INVALID_REQUEST', message: 'server only accepts requests' },
245
+ });
246
+ continue;
247
+ }
248
+ await dispatchRequest(sock, ctx, frame, handlers, log);
249
+ }
250
+ });
251
+ sock.on('error', (err) => {
252
+ log('warn', `client ${ctx.id} socket error: ${err.message}`);
253
+ });
254
+ }
255
+ async function dispatchRequest(sock, ctx, req, handlers, log) {
256
+ const handler = handlers[req.method];
257
+ if (!handler) {
258
+ sendFrame(sock, errorResponse(req.id, 'METHOD_NOT_FOUND', `no handler for ${req.method}`));
259
+ return;
260
+ }
261
+ try {
262
+ const result = await handler(req.params, ctx);
263
+ sendFrame(sock, { id: req.id, type: 'response', result });
264
+ }
265
+ catch (err) {
266
+ const message = err instanceof Error ? err.message : String(err);
267
+ // Preserve the handler's intended RpcErrorCode when it threw a
268
+ // DaemonProtocolError — otherwise clients can't distinguish e.g.
269
+ // UNAUTHORIZED, INVALID_PARAMS, METHOD_NOT_FOUND from a generic
270
+ // INTERNAL_ERROR. Any other error class is mapped to INTERNAL_ERROR
271
+ // so a buggy handler can't leak unexpected codes onto the wire.
272
+ const code = err instanceof DaemonProtocolError ? err.code : 'INTERNAL_ERROR';
273
+ log('warn', `client ${ctx.id} method ${req.method} threw [${code}]: ${message}`);
274
+ sendFrame(sock, errorResponse(req.id, code, message));
275
+ }
276
+ }
277
+ function errorResponse(id, code, message) {
278
+ return { id, type: 'response', error: { code, message } };
279
+ }
280
+ function sendFrame(sock, frame) {
281
+ if (sock.destroyed || !sock.writable)
282
+ return;
283
+ try {
284
+ sock.write(encodeFrame(frame));
285
+ }
286
+ catch {
287
+ // socket errors will surface via the 'error' listener; nothing to do here
288
+ }
289
+ }
290
+ /** Test-only helper. Exported for unit tests that need to bind a temporary
291
+ * socket without ensuring the directory exists. Production code should
292
+ * always go through startDaemon. */
293
+ export async function _stat(path) {
294
+ const s = await stat(path);
295
+ return { mode: s.mode };
296
+ }
297
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { WalletFacade } from '@midnightntwrk/wallet-sdk/facade';
2
+ import type { ConfirmationQueue } from './confirmation-queue.js';
3
+ import type { RpcHandler } from './server.js';
4
+ import type { AuditLog } from './audit-log.js';
5
+ import type { WalletKeys } from '../sync/operations.js';
6
+ import type { WalletBalances } from '../sync/wallet-sync.js';
7
+ import type { NetworkConfig } from '../types/network.js';
8
+ export interface WalletHandlerDeps {
9
+ /** Identifier echoed in modal payloads. */
10
+ readonly walletName: string;
11
+ /** Network config — also identifies which socket-bound wallet this is. */
12
+ readonly network: NetworkConfig;
13
+ /** Returns the live WalletFacade or null when not yet ready. */
14
+ readonly getFacade: () => WalletFacade | null;
15
+ /** Returns the typed key bundle or null when not yet ready. */
16
+ readonly getWalletKeys: () => WalletKeys | null;
17
+ /** Returns the latest WalletBalances snapshot or null. */
18
+ readonly getBalances: () => WalletBalances | null;
19
+ /** Queue used to surface L3 confirmation prompts. */
20
+ readonly queue: ConfirmationQueue;
21
+ /** Logger forwarded to long-running operation progress callbacks. */
22
+ readonly log?: (level: 'info' | 'warn' | 'error', msg: string) => void;
23
+ /** Optional persistent audit sink. Every write verb's
24
+ * request/decision/outcome is appended to it when present;
25
+ * omitted handlers run with stderr-only logging (stage 1). */
26
+ readonly auditLog?: AuditLog;
27
+ /** Per-transaction NIGHT spend cap (raw base units). When set (headless
28
+ * auto-approve mode), a NIGHT transfer above this is refused. Undefined
29
+ * in interactive hosts, where a human approves each transfer instead. */
30
+ readonly maxSpendRaw?: bigint;
31
+ }
32
+ /**
33
+ * Build the wallet daemon's RPC handler map. Same map for both hosting
34
+ * sites; differences are entirely in the deps object.
35
+ */
36
+ export declare function buildWalletHandlers(deps: WalletHandlerDeps): Record<string, RpcHandler>;
37
+ //# sourceMappingURL=wallet-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-handlers.d.ts","sourceRoot":"","sources":["../../src/daemon/wallet-handlers.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kCAAkC,CAAC;AAGnE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAC,UAAU,EAAoB,MAAM,aAAa,CAAC;AAC/D,OAAO,KAAK,EAAC,QAAQ,EAAgB,MAAM,gBAAgB,CAAC;AA0B5D,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAStD,OAAO,KAAK,EAAe,cAAc,EAAC,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAoBvD,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,YAAY,GAAG,IAAI,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,MAAM,UAAU,GAAG,IAAI,CAAC;IAChD,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IAClD,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE;;mEAE+D;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B;;8EAE0E;IAC1E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAsmBvF"}