@toon-protocol/townhouse 0.1.0-rc5

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/constants.js","../../../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js","../../../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/index.js","../../../node_modules/.pnpm/bufferutil@4.1.0/node_modules/bufferutil/fallback.js","../../../node_modules/.pnpm/bufferutil@4.1.0/node_modules/bufferutil/index.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/buffer-util.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/limiter.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js","../../../node_modules/.pnpm/utf-8-validate@5.0.10/node_modules/utf-8-validate/fallback.js","../../../node_modules/.pnpm/utf-8-validate@5.0.10/node_modules/utf-8-validate/index.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/validation.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/receiver.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/sender.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/event-target.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/extension.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/stream.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/subprotocol.js","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js","../src/config/defaults.ts","../src/config/validator.ts","../src/config/loader.ts","../src/connector/config-generator.ts","../src/docker/orchestrator.ts","../src/connector/admin-client.ts","../src/connector/transport-probe.ts","../src/wallet/storage.ts","../src/wallet/crypto.ts","../src/wallet/manager.ts","../../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs","../src/api/build-app.ts","../src/api/cors.ts","../src/api/routes/nodes.ts","../src/api/routes/wallet.ts","../src/chain/evm-rpc.ts","../src/chain/solana-rpc.ts","../src/chain/mina-graphql.ts","../src/api/routes/wallet-balances.ts","../src/api/routes/wallet-reveal.ts","../src/api/routes/wallet-withdraw.ts","../src/chain/evm-tx.ts","../src/api/config-mutex.ts","../src/api/routes/nodes-patch.ts","../src/api/routes/metrics-ws.ts","../src/api/routes/wizard.ts","../src/api/routes/transport.ts","../src/api/server.ts","../src/api/wizard-server.ts"],"sourcesContent":["'use strict';\n\nconst BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments'];\nconst hasBlob = typeof Blob !== 'undefined';\n\nif (hasBlob) BINARY_TYPES.push('blob');\n\nmodule.exports = {\n BINARY_TYPES,\n CLOSE_TIMEOUT: 30000,\n EMPTY_BUFFER: Buffer.alloc(0),\n GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',\n hasBlob,\n kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),\n kListener: Symbol('kListener'),\n kStatusCode: Symbol('status-code'),\n kWebSocket: Symbol('websocket'),\n NOOP: () => {}\n};\n","var fs = require('fs')\nvar path = require('path')\nvar os = require('os')\n\n// Workaround to fix webpack's build warnings: 'the request of a dependency is an expression'\nvar runtimeRequire = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require // eslint-disable-line\n\nvar vars = (process.config && process.config.variables) || {}\nvar prebuildsOnly = !!process.env.PREBUILDS_ONLY\nvar abi = process.versions.modules // TODO: support old node where this is undef\nvar runtime = isElectron() ? 'electron' : (isNwjs() ? 'node-webkit' : 'node')\n\nvar arch = process.env.npm_config_arch || os.arch()\nvar platform = process.env.npm_config_platform || os.platform()\nvar libc = process.env.LIBC || (isAlpine(platform) ? 'musl' : 'glibc')\nvar armv = process.env.ARM_VERSION || (arch === 'arm64' ? '8' : vars.arm_version) || ''\nvar uv = (process.versions.uv || '').split('.')[0]\n\nmodule.exports = load\n\nfunction load (dir) {\n return runtimeRequire(load.resolve(dir))\n}\n\nload.resolve = load.path = function (dir) {\n dir = path.resolve(dir || '.')\n\n try {\n var name = runtimeRequire(path.join(dir, 'package.json')).name.toUpperCase().replace(/-/g, '_')\n if (process.env[name + '_PREBUILD']) dir = process.env[name + '_PREBUILD']\n } catch (err) {}\n\n if (!prebuildsOnly) {\n var release = getFirst(path.join(dir, 'build/Release'), matchBuild)\n if (release) return release\n\n var debug = getFirst(path.join(dir, 'build/Debug'), matchBuild)\n if (debug) return debug\n }\n\n var prebuild = resolve(dir)\n if (prebuild) return prebuild\n\n var nearby = resolve(path.dirname(process.execPath))\n if (nearby) return nearby\n\n var target = [\n 'platform=' + platform,\n 'arch=' + arch,\n 'runtime=' + runtime,\n 'abi=' + abi,\n 'uv=' + uv,\n armv ? 'armv=' + armv : '',\n 'libc=' + libc,\n 'node=' + process.versions.node,\n process.versions.electron ? 'electron=' + process.versions.electron : '',\n typeof __webpack_require__ === 'function' ? 'webpack=true' : '' // eslint-disable-line\n ].filter(Boolean).join(' ')\n\n throw new Error('No native build was found for ' + target + '\\n loaded from: ' + dir + '\\n')\n\n function resolve (dir) {\n // Find matching \"prebuilds/<platform>-<arch>\" directory\n var tuples = readdirSync(path.join(dir, 'prebuilds')).map(parseTuple)\n var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0]\n if (!tuple) return\n\n // Find most specific flavor first\n var prebuilds = path.join(dir, 'prebuilds', tuple.name)\n var parsed = readdirSync(prebuilds).map(parseTags)\n var candidates = parsed.filter(matchTags(runtime, abi))\n var winner = candidates.sort(compareTags(runtime))[0]\n if (winner) return path.join(prebuilds, winner.file)\n }\n}\n\nfunction readdirSync (dir) {\n try {\n return fs.readdirSync(dir)\n } catch (err) {\n return []\n }\n}\n\nfunction getFirst (dir, filter) {\n var files = readdirSync(dir).filter(filter)\n return files[0] && path.join(dir, files[0])\n}\n\nfunction matchBuild (name) {\n return /\\.node$/.test(name)\n}\n\nfunction parseTuple (name) {\n // Example: darwin-x64+arm64\n var arr = name.split('-')\n if (arr.length !== 2) return\n\n var platform = arr[0]\n var architectures = arr[1].split('+')\n\n if (!platform) return\n if (!architectures.length) return\n if (!architectures.every(Boolean)) return\n\n return { name, platform, architectures }\n}\n\nfunction matchTuple (platform, arch) {\n return function (tuple) {\n if (tuple == null) return false\n if (tuple.platform !== platform) return false\n return tuple.architectures.includes(arch)\n }\n}\n\nfunction compareTuples (a, b) {\n // Prefer single-arch prebuilds over multi-arch\n return a.architectures.length - b.architectures.length\n}\n\nfunction parseTags (file) {\n var arr = file.split('.')\n var extension = arr.pop()\n var tags = { file: file, specificity: 0 }\n\n if (extension !== 'node') return\n\n for (var i = 0; i < arr.length; i++) {\n var tag = arr[i]\n\n if (tag === 'node' || tag === 'electron' || tag === 'node-webkit') {\n tags.runtime = tag\n } else if (tag === 'napi') {\n tags.napi = true\n } else if (tag.slice(0, 3) === 'abi') {\n tags.abi = tag.slice(3)\n } else if (tag.slice(0, 2) === 'uv') {\n tags.uv = tag.slice(2)\n } else if (tag.slice(0, 4) === 'armv') {\n tags.armv = tag.slice(4)\n } else if (tag === 'glibc' || tag === 'musl') {\n tags.libc = tag\n } else {\n continue\n }\n\n tags.specificity++\n }\n\n return tags\n}\n\nfunction matchTags (runtime, abi) {\n return function (tags) {\n if (tags == null) return false\n if (tags.runtime && tags.runtime !== runtime && !runtimeAgnostic(tags)) return false\n if (tags.abi && tags.abi !== abi && !tags.napi) return false\n if (tags.uv && tags.uv !== uv) return false\n if (tags.armv && tags.armv !== armv) return false\n if (tags.libc && tags.libc !== libc) return false\n\n return true\n }\n}\n\nfunction runtimeAgnostic (tags) {\n return tags.runtime === 'node' && tags.napi\n}\n\nfunction compareTags (runtime) {\n // Precedence: non-agnostic runtime, abi over napi, then by specificity.\n return function (a, b) {\n if (a.runtime !== b.runtime) {\n return a.runtime === runtime ? -1 : 1\n } else if (a.abi !== b.abi) {\n return a.abi ? -1 : 1\n } else if (a.specificity !== b.specificity) {\n return a.specificity > b.specificity ? -1 : 1\n } else {\n return 0\n }\n }\n}\n\nfunction isNwjs () {\n return !!(process.versions && process.versions.nw)\n}\n\nfunction isElectron () {\n if (process.versions && process.versions.electron) return true\n if (process.env.ELECTRON_RUN_AS_NODE) return true\n return typeof window !== 'undefined' && window.process && window.process.type === 'renderer'\n}\n\nfunction isAlpine (platform) {\n return platform === 'linux' && fs.existsSync('/etc/alpine-release')\n}\n\n// Exposed for unit tests\n// TODO: move to lib\nload.parseTags = parseTags\nload.matchTags = matchTags\nload.compareTags = compareTags\nload.parseTuple = parseTuple\nload.matchTuple = matchTuple\nload.compareTuples = compareTuples\n","const runtimeRequire = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require // eslint-disable-line\nif (typeof runtimeRequire.addon === 'function') { // if the platform supports native resolving prefer that\n module.exports = runtimeRequire.addon.bind(runtimeRequire)\n} else { // else use the runtime version here\n module.exports = require('./node-gyp-build.js')\n}\n","'use strict';\n\n/**\n * Masks a buffer using the given mask.\n *\n * @param {Buffer} source The buffer to mask\n * @param {Buffer} mask The mask to use\n * @param {Buffer} output The buffer where to store the result\n * @param {Number} offset The offset at which to start writing\n * @param {Number} length The number of bytes to mask.\n * @public\n */\nconst mask = (source, mask, output, offset, length) => {\n for (var i = 0; i < length; i++) {\n output[offset + i] = source[i] ^ mask[i & 3];\n }\n};\n\n/**\n * Unmasks a buffer using the given mask.\n *\n * @param {Buffer} buffer The buffer to unmask\n * @param {Buffer} mask The mask to use\n * @public\n */\nconst unmask = (buffer, mask) => {\n // Required until https://github.com/nodejs/node/issues/9006 is resolved.\n const length = buffer.length;\n for (var i = 0; i < length; i++) {\n buffer[i] ^= mask[i & 3];\n }\n};\n\nmodule.exports = { mask, unmask };\n","'use strict';\n\ntry {\n module.exports = require('node-gyp-build')(__dirname);\n} catch (e) {\n module.exports = require('./fallback');\n}\n","'use strict';\n\nconst { EMPTY_BUFFER } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\n\n/**\n * Merges an array of buffers into a new buffer.\n *\n * @param {Buffer[]} list The array of buffers to concat\n * @param {Number} totalLength The total length of buffers in the list\n * @return {Buffer} The resulting buffer\n * @public\n */\nfunction concat(list, totalLength) {\n if (list.length === 0) return EMPTY_BUFFER;\n if (list.length === 1) return list[0];\n\n const target = Buffer.allocUnsafe(totalLength);\n let offset = 0;\n\n for (let i = 0; i < list.length; i++) {\n const buf = list[i];\n target.set(buf, offset);\n offset += buf.length;\n }\n\n if (offset < totalLength) {\n return new FastBuffer(target.buffer, target.byteOffset, offset);\n }\n\n return target;\n}\n\n/**\n * Masks a buffer using the given mask.\n *\n * @param {Buffer} source The buffer to mask\n * @param {Buffer} mask The mask to use\n * @param {Buffer} output The buffer where to store the result\n * @param {Number} offset The offset at which to start writing\n * @param {Number} length The number of bytes to mask.\n * @public\n */\nfunction _mask(source, mask, output, offset, length) {\n for (let i = 0; i < length; i++) {\n output[offset + i] = source[i] ^ mask[i & 3];\n }\n}\n\n/**\n * Unmasks a buffer using the given mask.\n *\n * @param {Buffer} buffer The buffer to unmask\n * @param {Buffer} mask The mask to use\n * @public\n */\nfunction _unmask(buffer, mask) {\n for (let i = 0; i < buffer.length; i++) {\n buffer[i] ^= mask[i & 3];\n }\n}\n\n/**\n * Converts a buffer to an `ArrayBuffer`.\n *\n * @param {Buffer} buf The buffer to convert\n * @return {ArrayBuffer} Converted buffer\n * @public\n */\nfunction toArrayBuffer(buf) {\n if (buf.length === buf.buffer.byteLength) {\n return buf.buffer;\n }\n\n return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);\n}\n\n/**\n * Converts `data` to a `Buffer`.\n *\n * @param {*} data The data to convert\n * @return {Buffer} The buffer\n * @throws {TypeError}\n * @public\n */\nfunction toBuffer(data) {\n toBuffer.readOnly = true;\n\n if (Buffer.isBuffer(data)) return data;\n\n let buf;\n\n if (data instanceof ArrayBuffer) {\n buf = new FastBuffer(data);\n } else if (ArrayBuffer.isView(data)) {\n buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);\n } else {\n buf = Buffer.from(data);\n toBuffer.readOnly = false;\n }\n\n return buf;\n}\n\nmodule.exports = {\n concat,\n mask: _mask,\n toArrayBuffer,\n toBuffer,\n unmask: _unmask\n};\n\n/* istanbul ignore else */\nif (!process.env.WS_NO_BUFFER_UTIL) {\n try {\n const bufferUtil = require('bufferutil');\n\n module.exports.mask = function (source, mask, output, offset, length) {\n if (length < 48) _mask(source, mask, output, offset, length);\n else bufferUtil.mask(source, mask, output, offset, length);\n };\n\n module.exports.unmask = function (buffer, mask) {\n if (buffer.length < 32) _unmask(buffer, mask);\n else bufferUtil.unmask(buffer, mask);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst kDone = Symbol('kDone');\nconst kRun = Symbol('kRun');\n\n/**\n * A very simple job queue with adjustable concurrency. Adapted from\n * https://github.com/STRML/async-limiter\n */\nclass Limiter {\n /**\n * Creates a new `Limiter`.\n *\n * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed\n * to run concurrently\n */\n constructor(concurrency) {\n this[kDone] = () => {\n this.pending--;\n this[kRun]();\n };\n this.concurrency = concurrency || Infinity;\n this.jobs = [];\n this.pending = 0;\n }\n\n /**\n * Adds a job to the queue.\n *\n * @param {Function} job The job to run\n * @public\n */\n add(job) {\n this.jobs.push(job);\n this[kRun]();\n }\n\n /**\n * Removes a job from the queue and runs it if possible.\n *\n * @private\n */\n [kRun]() {\n if (this.pending === this.concurrency) return;\n\n if (this.jobs.length) {\n const job = this.jobs.shift();\n\n this.pending++;\n job(this[kDone]);\n }\n }\n}\n\nmodule.exports = Limiter;\n","'use strict';\n\nconst zlib = require('zlib');\n\nconst bufferUtil = require('./buffer-util');\nconst Limiter = require('./limiter');\nconst { kStatusCode } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\nconst TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);\nconst kPerMessageDeflate = Symbol('permessage-deflate');\nconst kTotalLength = Symbol('total-length');\nconst kCallback = Symbol('callback');\nconst kBuffers = Symbol('buffers');\nconst kError = Symbol('error');\n\n//\n// We limit zlib concurrency, which prevents severe memory fragmentation\n// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913\n// and https://github.com/websockets/ws/issues/1202\n//\n// Intentionally global; it's the global thread pool that's an issue.\n//\nlet zlibLimiter;\n\n/**\n * permessage-deflate implementation.\n */\nclass PerMessageDeflate {\n /**\n * Creates a PerMessageDeflate instance.\n *\n * @param {Object} [options] Configuration options\n * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support\n * for, or request, a custom client window size\n * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/\n * acknowledge disabling of client context takeover\n * @param {Number} [options.concurrencyLimit=10] The number of concurrent\n * calls to zlib\n * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the\n * use of a custom server window size\n * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept\n * disabling of server context takeover\n * @param {Number} [options.threshold=1024] Size (in bytes) below which\n * messages should not be compressed if context takeover is disabled\n * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on\n * deflate\n * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on\n * inflate\n * @param {Boolean} [isServer=false] Create the instance in either server or\n * client mode\n * @param {Number} [maxPayload=0] The maximum allowed message length\n */\n constructor(options, isServer, maxPayload) {\n this._maxPayload = maxPayload | 0;\n this._options = options || {};\n this._threshold =\n this._options.threshold !== undefined ? this._options.threshold : 1024;\n this._isServer = !!isServer;\n this._deflate = null;\n this._inflate = null;\n\n this.params = null;\n\n if (!zlibLimiter) {\n const concurrency =\n this._options.concurrencyLimit !== undefined\n ? this._options.concurrencyLimit\n : 10;\n zlibLimiter = new Limiter(concurrency);\n }\n }\n\n /**\n * @type {String}\n */\n static get extensionName() {\n return 'permessage-deflate';\n }\n\n /**\n * Create an extension negotiation offer.\n *\n * @return {Object} Extension parameters\n * @public\n */\n offer() {\n const params = {};\n\n if (this._options.serverNoContextTakeover) {\n params.server_no_context_takeover = true;\n }\n if (this._options.clientNoContextTakeover) {\n params.client_no_context_takeover = true;\n }\n if (this._options.serverMaxWindowBits) {\n params.server_max_window_bits = this._options.serverMaxWindowBits;\n }\n if (this._options.clientMaxWindowBits) {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n } else if (this._options.clientMaxWindowBits == null) {\n params.client_max_window_bits = true;\n }\n\n return params;\n }\n\n /**\n * Accept an extension negotiation offer/response.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Object} Accepted configuration\n * @public\n */\n accept(configurations) {\n configurations = this.normalizeParams(configurations);\n\n this.params = this._isServer\n ? this.acceptAsServer(configurations)\n : this.acceptAsClient(configurations);\n\n return this.params;\n }\n\n /**\n * Releases all resources used by the extension.\n *\n * @public\n */\n cleanup() {\n if (this._inflate) {\n this._inflate.close();\n this._inflate = null;\n }\n\n if (this._deflate) {\n const callback = this._deflate[kCallback];\n\n this._deflate.close();\n this._deflate = null;\n\n if (callback) {\n callback(\n new Error(\n 'The deflate stream was closed while data was being processed'\n )\n );\n }\n }\n }\n\n /**\n * Accept an extension negotiation offer.\n *\n * @param {Array} offers The extension negotiation offers\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsServer(offers) {\n const opts = this._options;\n const accepted = offers.find((params) => {\n if (\n (opts.serverNoContextTakeover === false &&\n params.server_no_context_takeover) ||\n (params.server_max_window_bits &&\n (opts.serverMaxWindowBits === false ||\n (typeof opts.serverMaxWindowBits === 'number' &&\n opts.serverMaxWindowBits > params.server_max_window_bits))) ||\n (typeof opts.clientMaxWindowBits === 'number' &&\n !params.client_max_window_bits)\n ) {\n return false;\n }\n\n return true;\n });\n\n if (!accepted) {\n throw new Error('None of the extension offers can be accepted');\n }\n\n if (opts.serverNoContextTakeover) {\n accepted.server_no_context_takeover = true;\n }\n if (opts.clientNoContextTakeover) {\n accepted.client_no_context_takeover = true;\n }\n if (typeof opts.serverMaxWindowBits === 'number') {\n accepted.server_max_window_bits = opts.serverMaxWindowBits;\n }\n if (typeof opts.clientMaxWindowBits === 'number') {\n accepted.client_max_window_bits = opts.clientMaxWindowBits;\n } else if (\n accepted.client_max_window_bits === true ||\n opts.clientMaxWindowBits === false\n ) {\n delete accepted.client_max_window_bits;\n }\n\n return accepted;\n }\n\n /**\n * Accept the extension negotiation response.\n *\n * @param {Array} response The extension negotiation response\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsClient(response) {\n const params = response[0];\n\n if (\n this._options.clientNoContextTakeover === false &&\n params.client_no_context_takeover\n ) {\n throw new Error('Unexpected parameter \"client_no_context_takeover\"');\n }\n\n if (!params.client_max_window_bits) {\n if (typeof this._options.clientMaxWindowBits === 'number') {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n }\n } else if (\n this._options.clientMaxWindowBits === false ||\n (typeof this._options.clientMaxWindowBits === 'number' &&\n params.client_max_window_bits > this._options.clientMaxWindowBits)\n ) {\n throw new Error(\n 'Unexpected or invalid parameter \"client_max_window_bits\"'\n );\n }\n\n return params;\n }\n\n /**\n * Normalize parameters.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Array} The offers/response with normalized parameters\n * @private\n */\n normalizeParams(configurations) {\n configurations.forEach((params) => {\n Object.keys(params).forEach((key) => {\n let value = params[key];\n\n if (value.length > 1) {\n throw new Error(`Parameter \"${key}\" must have only a single value`);\n }\n\n value = value[0];\n\n if (key === 'client_max_window_bits') {\n if (value !== true) {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (!this._isServer) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else if (key === 'server_max_window_bits') {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (\n key === 'client_no_context_takeover' ||\n key === 'server_no_context_takeover'\n ) {\n if (value !== true) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else {\n throw new Error(`Unknown parameter \"${key}\"`);\n }\n\n params[key] = value;\n });\n });\n\n return configurations;\n }\n\n /**\n * Decompress data. Concurrency limited.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n decompress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._decompress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Compress data. Concurrency limited.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n compress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._compress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Decompress data.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _decompress(data, fin, callback) {\n const endpoint = this._isServer ? 'client' : 'server';\n\n if (!this._inflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._inflate = zlib.createInflateRaw({\n ...this._options.zlibInflateOptions,\n windowBits\n });\n this._inflate[kPerMessageDeflate] = this;\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n this._inflate.on('error', inflateOnError);\n this._inflate.on('data', inflateOnData);\n }\n\n this._inflate[kCallback] = callback;\n\n this._inflate.write(data);\n if (fin) this._inflate.write(TRAILER);\n\n this._inflate.flush(() => {\n const err = this._inflate[kError];\n\n if (err) {\n this._inflate.close();\n this._inflate = null;\n callback(err);\n return;\n }\n\n const data = bufferUtil.concat(\n this._inflate[kBuffers],\n this._inflate[kTotalLength]\n );\n\n if (this._inflate._readableState.endEmitted) {\n this._inflate.close();\n this._inflate = null;\n } else {\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._inflate.reset();\n }\n }\n\n callback(null, data);\n });\n }\n\n /**\n * Compress data.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _compress(data, fin, callback) {\n const endpoint = this._isServer ? 'server' : 'client';\n\n if (!this._deflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._deflate = zlib.createDeflateRaw({\n ...this._options.zlibDeflateOptions,\n windowBits\n });\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n this._deflate.on('data', deflateOnData);\n }\n\n this._deflate[kCallback] = callback;\n\n this._deflate.write(data);\n this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {\n if (!this._deflate) {\n //\n // The deflate stream was closed while data was being processed.\n //\n return;\n }\n\n let data = bufferUtil.concat(\n this._deflate[kBuffers],\n this._deflate[kTotalLength]\n );\n\n if (fin) {\n data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4);\n }\n\n //\n // Ensure that the callback will not be called again in\n // `PerMessageDeflate#cleanup()`.\n //\n this._deflate[kCallback] = null;\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._deflate.reset();\n }\n\n callback(null, data);\n });\n }\n}\n\nmodule.exports = PerMessageDeflate;\n\n/**\n * The listener of the `zlib.DeflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction deflateOnData(chunk) {\n this[kBuffers].push(chunk);\n this[kTotalLength] += chunk.length;\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction inflateOnData(chunk) {\n this[kTotalLength] += chunk.length;\n\n if (\n this[kPerMessageDeflate]._maxPayload < 1 ||\n this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload\n ) {\n this[kBuffers].push(chunk);\n return;\n }\n\n this[kError] = new RangeError('Max payload size exceeded');\n this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';\n this[kError][kStatusCode] = 1009;\n this.removeListener('data', inflateOnData);\n\n //\n // The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the\n // fact that in Node.js versions prior to 13.10.0, the callback for\n // `zlib.flush()` is not called if `zlib.close()` is used. Utilizing\n // `zlib.reset()` ensures that either the callback is invoked or an error is\n // emitted.\n //\n this.reset();\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'error'` event.\n *\n * @param {Error} err The emitted error\n * @private\n */\nfunction inflateOnError(err) {\n //\n // There is no need to call `Zlib#close()` as the handle is automatically\n // closed when an error is emitted.\n //\n this[kPerMessageDeflate]._inflate = null;\n\n if (this[kError]) {\n this[kCallback](this[kError]);\n return;\n }\n\n err[kStatusCode] = 1007;\n this[kCallback](err);\n}\n","'use strict';\n\n/**\n * Checks if a given buffer contains only correct UTF-8.\n * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by\n * Markus Kuhn.\n *\n * @param {Buffer} buf The buffer to check\n * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`\n * @public\n */\nfunction isValidUTF8(buf) {\n const len = buf.length;\n let i = 0;\n\n while (i < len) {\n if ((buf[i] & 0x80) === 0x00) { // 0xxxxxxx\n i++;\n } else if ((buf[i] & 0xe0) === 0xc0) { // 110xxxxx 10xxxxxx\n if (\n i + 1 === len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i] & 0xfe) === 0xc0 // overlong\n ) {\n return false;\n }\n\n i += 2;\n } else if ((buf[i] & 0xf0) === 0xe0) { // 1110xxxx 10xxxxxx 10xxxxxx\n if (\n i + 2 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80 || // overlong\n buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0 // surrogate (U+D800 - U+DFFF)\n ) {\n return false;\n }\n\n i += 3;\n } else if ((buf[i] & 0xf8) === 0xf0) { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n if (\n i + 3 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i + 3] & 0xc0) !== 0x80 ||\n buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80 || // overlong\n buf[i] === 0xf4 && buf[i + 1] > 0x8f || buf[i] > 0xf4 // > U+10FFFF\n ) {\n return false;\n }\n\n i += 4;\n } else {\n return false;\n }\n }\n\n return true;\n}\n\nmodule.exports = isValidUTF8;\n","'use strict';\n\ntry {\n module.exports = require('node-gyp-build')(__dirname);\n} catch (e) {\n module.exports = require('./fallback');\n}\n","'use strict';\n\nconst { isUtf8 } = require('buffer');\n\nconst { hasBlob } = require('./constants');\n\n//\n// Allowed token characters:\n//\n// '!', '#', '$', '%', '&', ''', '*', '+', '-',\n// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'\n//\n// tokenChars[32] === 0 // ' '\n// tokenChars[33] === 1 // '!'\n// tokenChars[34] === 0 // '\"'\n// ...\n//\n// prettier-ignore\nconst tokenChars = [\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31\n 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63\n 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127\n];\n\n/**\n * Checks if a status code is allowed in a close frame.\n *\n * @param {Number} code The status code\n * @return {Boolean} `true` if the status code is valid, else `false`\n * @public\n */\nfunction isValidStatusCode(code) {\n return (\n (code >= 1000 &&\n code <= 1014 &&\n code !== 1004 &&\n code !== 1005 &&\n code !== 1006) ||\n (code >= 3000 && code <= 4999)\n );\n}\n\n/**\n * Checks if a given buffer contains only correct UTF-8.\n * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by\n * Markus Kuhn.\n *\n * @param {Buffer} buf The buffer to check\n * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`\n * @public\n */\nfunction _isValidUTF8(buf) {\n const len = buf.length;\n let i = 0;\n\n while (i < len) {\n if ((buf[i] & 0x80) === 0) {\n // 0xxxxxxx\n i++;\n } else if ((buf[i] & 0xe0) === 0xc0) {\n // 110xxxxx 10xxxxxx\n if (\n i + 1 === len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i] & 0xfe) === 0xc0 // Overlong\n ) {\n return false;\n }\n\n i += 2;\n } else if ((buf[i] & 0xf0) === 0xe0) {\n // 1110xxxx 10xxxxxx 10xxxxxx\n if (\n i + 2 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong\n (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)\n ) {\n return false;\n }\n\n i += 3;\n } else if ((buf[i] & 0xf8) === 0xf0) {\n // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n if (\n i + 3 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i + 3] & 0xc0) !== 0x80 ||\n (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong\n (buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||\n buf[i] > 0xf4 // > U+10FFFF\n ) {\n return false;\n }\n\n i += 4;\n } else {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Determines whether a value is a `Blob`.\n *\n * @param {*} value The value to be tested\n * @return {Boolean} `true` if `value` is a `Blob`, else `false`\n * @private\n */\nfunction isBlob(value) {\n return (\n hasBlob &&\n typeof value === 'object' &&\n typeof value.arrayBuffer === 'function' &&\n typeof value.type === 'string' &&\n typeof value.stream === 'function' &&\n (value[Symbol.toStringTag] === 'Blob' ||\n value[Symbol.toStringTag] === 'File')\n );\n}\n\nmodule.exports = {\n isBlob,\n isValidStatusCode,\n isValidUTF8: _isValidUTF8,\n tokenChars\n};\n\nif (isUtf8) {\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);\n };\n} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {\n try {\n const isValidUTF8 = require('utf-8-validate');\n\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst { Writable } = require('stream');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst {\n BINARY_TYPES,\n EMPTY_BUFFER,\n kStatusCode,\n kWebSocket\n} = require('./constants');\nconst { concat, toArrayBuffer, unmask } = require('./buffer-util');\nconst { isValidStatusCode, isValidUTF8 } = require('./validation');\n\nconst FastBuffer = Buffer[Symbol.species];\n\nconst GET_INFO = 0;\nconst GET_PAYLOAD_LENGTH_16 = 1;\nconst GET_PAYLOAD_LENGTH_64 = 2;\nconst GET_MASK = 3;\nconst GET_DATA = 4;\nconst INFLATING = 5;\nconst DEFER_EVENT = 6;\n\n/**\n * HyBi Receiver implementation.\n *\n * @extends Writable\n */\nclass Receiver extends Writable {\n /**\n * Creates a Receiver instance.\n *\n * @param {Object} [options] Options object\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {String} [options.binaryType=nodebuffer] The type for binary data\n * @param {Object} [options.extensions] An object containing the negotiated\n * extensions\n * @param {Boolean} [options.isServer=false] Specifies whether to operate in\n * client or server mode\n * @param {Number} [options.maxPayload=0] The maximum allowed message length\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n */\n constructor(options = {}) {\n super();\n\n this._allowSynchronousEvents =\n options.allowSynchronousEvents !== undefined\n ? options.allowSynchronousEvents\n : true;\n this._binaryType = options.binaryType || BINARY_TYPES[0];\n this._extensions = options.extensions || {};\n this._isServer = !!options.isServer;\n this._maxPayload = options.maxPayload | 0;\n this._skipUTF8Validation = !!options.skipUTF8Validation;\n this[kWebSocket] = undefined;\n\n this._bufferedBytes = 0;\n this._buffers = [];\n\n this._compressed = false;\n this._payloadLength = 0;\n this._mask = undefined;\n this._fragmented = 0;\n this._masked = false;\n this._fin = false;\n this._opcode = 0;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragments = [];\n\n this._errored = false;\n this._loop = false;\n this._state = GET_INFO;\n }\n\n /**\n * Implements `Writable.prototype._write()`.\n *\n * @param {Buffer} chunk The chunk of data to write\n * @param {String} encoding The character encoding of `chunk`\n * @param {Function} cb Callback\n * @private\n */\n _write(chunk, encoding, cb) {\n if (this._opcode === 0x08 && this._state == GET_INFO) return cb();\n\n this._bufferedBytes += chunk.length;\n this._buffers.push(chunk);\n this.startLoop(cb);\n }\n\n /**\n * Consumes `n` bytes from the buffered data.\n *\n * @param {Number} n The number of bytes to consume\n * @return {Buffer} The consumed bytes\n * @private\n */\n consume(n) {\n this._bufferedBytes -= n;\n\n if (n === this._buffers[0].length) return this._buffers.shift();\n\n if (n < this._buffers[0].length) {\n const buf = this._buffers[0];\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n\n return new FastBuffer(buf.buffer, buf.byteOffset, n);\n }\n\n const dst = Buffer.allocUnsafe(n);\n\n do {\n const buf = this._buffers[0];\n const offset = dst.length - n;\n\n if (n >= buf.length) {\n dst.set(this._buffers.shift(), offset);\n } else {\n dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n }\n\n n -= buf.length;\n } while (n > 0);\n\n return dst;\n }\n\n /**\n * Starts the parsing loop.\n *\n * @param {Function} cb Callback\n * @private\n */\n startLoop(cb) {\n this._loop = true;\n\n do {\n switch (this._state) {\n case GET_INFO:\n this.getInfo(cb);\n break;\n case GET_PAYLOAD_LENGTH_16:\n this.getPayloadLength16(cb);\n break;\n case GET_PAYLOAD_LENGTH_64:\n this.getPayloadLength64(cb);\n break;\n case GET_MASK:\n this.getMask();\n break;\n case GET_DATA:\n this.getData(cb);\n break;\n case INFLATING:\n case DEFER_EVENT:\n this._loop = false;\n return;\n }\n } while (this._loop);\n\n if (!this._errored) cb();\n }\n\n /**\n * Reads the first two bytes of a frame.\n *\n * @param {Function} cb Callback\n * @private\n */\n getInfo(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(2);\n\n if ((buf[0] & 0x30) !== 0x00) {\n const error = this.createError(\n RangeError,\n 'RSV2 and RSV3 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_2_3'\n );\n\n cb(error);\n return;\n }\n\n const compressed = (buf[0] & 0x40) === 0x40;\n\n if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n this._fin = (buf[0] & 0x80) === 0x80;\n this._opcode = buf[0] & 0x0f;\n this._payloadLength = buf[1] & 0x7f;\n\n if (this._opcode === 0x00) {\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fragmented) {\n const error = this.createError(\n RangeError,\n 'invalid opcode 0',\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._opcode = this._fragmented;\n } else if (this._opcode === 0x01 || this._opcode === 0x02) {\n if (this._fragmented) {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._compressed = compressed;\n } else if (this._opcode > 0x07 && this._opcode < 0x0b) {\n if (!this._fin) {\n const error = this.createError(\n RangeError,\n 'FIN must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_FIN'\n );\n\n cb(error);\n return;\n }\n\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (\n this._payloadLength > 0x7d ||\n (this._opcode === 0x08 && this._payloadLength === 1)\n ) {\n const error = this.createError(\n RangeError,\n `invalid payload length ${this._payloadLength}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n } else {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fin && !this._fragmented) this._fragmented = this._opcode;\n this._masked = (buf[1] & 0x80) === 0x80;\n\n if (this._isServer) {\n if (!this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n } else if (this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n\n if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;\n else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;\n else this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+16).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength16(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n this._payloadLength = this.consume(2).readUInt16BE(0);\n this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+64).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength64(cb) {\n if (this._bufferedBytes < 8) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(8);\n const num = buf.readUInt32BE(0);\n\n //\n // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned\n // if payload length is greater than this number.\n //\n if (num > Math.pow(2, 53 - 32) - 1) {\n const error = this.createError(\n RangeError,\n 'Unsupported WebSocket frame: payload length > 2^53 - 1',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);\n this.haveLength(cb);\n }\n\n /**\n * Payload length has been read.\n *\n * @param {Function} cb Callback\n * @private\n */\n haveLength(cb) {\n if (this._payloadLength && this._opcode < 0x08) {\n this._totalPayloadLength += this._payloadLength;\n if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n }\n\n if (this._masked) this._state = GET_MASK;\n else this._state = GET_DATA;\n }\n\n /**\n * Reads mask bytes.\n *\n * @private\n */\n getMask() {\n if (this._bufferedBytes < 4) {\n this._loop = false;\n return;\n }\n\n this._mask = this.consume(4);\n this._state = GET_DATA;\n }\n\n /**\n * Reads data bytes.\n *\n * @param {Function} cb Callback\n * @private\n */\n getData(cb) {\n let data = EMPTY_BUFFER;\n\n if (this._payloadLength) {\n if (this._bufferedBytes < this._payloadLength) {\n this._loop = false;\n return;\n }\n\n data = this.consume(this._payloadLength);\n\n if (\n this._masked &&\n (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0\n ) {\n unmask(data, this._mask);\n }\n }\n\n if (this._opcode > 0x07) {\n this.controlMessage(data, cb);\n return;\n }\n\n if (this._compressed) {\n this._state = INFLATING;\n this.decompress(data, cb);\n return;\n }\n\n if (data.length) {\n //\n // This message is not compressed so its length is the sum of the payload\n // length of all fragments.\n //\n this._messageLength = this._totalPayloadLength;\n this._fragments.push(data);\n }\n\n this.dataMessage(cb);\n }\n\n /**\n * Decompresses data.\n *\n * @param {Buffer} data Compressed data\n * @param {Function} cb Callback\n * @private\n */\n decompress(data, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n perMessageDeflate.decompress(data, this._fin, (err, buf) => {\n if (err) return cb(err);\n\n if (buf.length) {\n this._messageLength += buf.length;\n if (this._messageLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._fragments.push(buf);\n }\n\n this.dataMessage(cb);\n if (this._state === GET_INFO) this.startLoop(cb);\n });\n }\n\n /**\n * Handles a data message.\n *\n * @param {Function} cb Callback\n * @private\n */\n dataMessage(cb) {\n if (!this._fin) {\n this._state = GET_INFO;\n return;\n }\n\n const messageLength = this._messageLength;\n const fragments = this._fragments;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragmented = 0;\n this._fragments = [];\n\n if (this._opcode === 2) {\n let data;\n\n if (this._binaryType === 'nodebuffer') {\n data = concat(fragments, messageLength);\n } else if (this._binaryType === 'arraybuffer') {\n data = toArrayBuffer(concat(fragments, messageLength));\n } else if (this._binaryType === 'blob') {\n data = new Blob(fragments);\n } else {\n data = fragments;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit('message', data, true);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', data, true);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n } else {\n const buf = concat(fragments, messageLength);\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n if (this._state === INFLATING || this._allowSynchronousEvents) {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n }\n\n /**\n * Handles a control message.\n *\n * @param {Buffer} data Data to handle\n * @return {(Error|RangeError|undefined)} A possible error\n * @private\n */\n controlMessage(data, cb) {\n if (this._opcode === 0x08) {\n if (data.length === 0) {\n this._loop = false;\n this.emit('conclude', 1005, EMPTY_BUFFER);\n this.end();\n } else {\n const code = data.readUInt16BE(0);\n\n if (!isValidStatusCode(code)) {\n const error = this.createError(\n RangeError,\n `invalid status code ${code}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CLOSE_CODE'\n );\n\n cb(error);\n return;\n }\n\n const buf = new FastBuffer(\n data.buffer,\n data.byteOffset + 2,\n data.length - 2\n );\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n this._loop = false;\n this.emit('conclude', code, buf);\n this.end();\n }\n\n this._state = GET_INFO;\n return;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n\n /**\n * Builds an error object.\n *\n * @param {function(new:Error|RangeError)} ErrorCtor The error constructor\n * @param {String} message The error message\n * @param {Boolean} prefix Specifies whether or not to add a default prefix to\n * `message`\n * @param {Number} statusCode The status code\n * @param {String} errorCode The exposed error code\n * @return {(Error|RangeError)} The error\n * @private\n */\n createError(ErrorCtor, message, prefix, statusCode, errorCode) {\n this._loop = false;\n this._errored = true;\n\n const err = new ErrorCtor(\n prefix ? `Invalid WebSocket frame: ${message}` : message\n );\n\n Error.captureStackTrace(err, this.createError);\n err.code = errorCode;\n err[kStatusCode] = statusCode;\n return err;\n }\n}\n\nmodule.exports = Receiver;\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex\" }] */\n\n'use strict';\n\nconst { Duplex } = require('stream');\nconst { randomFillSync } = require('crypto');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants');\nconst { isBlob, isValidStatusCode } = require('./validation');\nconst { mask: applyMask, toBuffer } = require('./buffer-util');\n\nconst kByteLength = Symbol('kByteLength');\nconst maskBuffer = Buffer.alloc(4);\nconst RANDOM_POOL_SIZE = 8 * 1024;\nlet randomPool;\nlet randomPoolPointer = RANDOM_POOL_SIZE;\n\nconst DEFAULT = 0;\nconst DEFLATING = 1;\nconst GET_BLOB_DATA = 2;\n\n/**\n * HyBi Sender implementation.\n */\nclass Sender {\n /**\n * Creates a Sender instance.\n *\n * @param {Duplex} socket The connection socket\n * @param {Object} [extensions] An object containing the negotiated extensions\n * @param {Function} [generateMask] The function used to generate the masking\n * key\n */\n constructor(socket, extensions, generateMask) {\n this._extensions = extensions || {};\n\n if (generateMask) {\n this._generateMask = generateMask;\n this._maskBuffer = Buffer.alloc(4);\n }\n\n this._socket = socket;\n\n this._firstFragment = true;\n this._compress = false;\n\n this._bufferedBytes = 0;\n this._queue = [];\n this._state = DEFAULT;\n this.onerror = NOOP;\n this[kWebSocket] = undefined;\n }\n\n /**\n * Frames a piece of data according to the HyBi WebSocket protocol.\n *\n * @param {(Buffer|String)} data The data to frame\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @return {(Buffer|String)[]} The framed data\n * @public\n */\n static frame(data, options) {\n let mask;\n let merge = false;\n let offset = 2;\n let skipMasking = false;\n\n if (options.mask) {\n mask = options.maskBuffer || maskBuffer;\n\n if (options.generateMask) {\n options.generateMask(mask);\n } else {\n if (randomPoolPointer === RANDOM_POOL_SIZE) {\n /* istanbul ignore else */\n if (randomPool === undefined) {\n //\n // This is lazily initialized because server-sent frames must not\n // be masked so it may never be used.\n //\n randomPool = Buffer.alloc(RANDOM_POOL_SIZE);\n }\n\n randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);\n randomPoolPointer = 0;\n }\n\n mask[0] = randomPool[randomPoolPointer++];\n mask[1] = randomPool[randomPoolPointer++];\n mask[2] = randomPool[randomPoolPointer++];\n mask[3] = randomPool[randomPoolPointer++];\n }\n\n skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;\n offset = 6;\n }\n\n let dataLength;\n\n if (typeof data === 'string') {\n if (\n (!options.mask || skipMasking) &&\n options[kByteLength] !== undefined\n ) {\n dataLength = options[kByteLength];\n } else {\n data = Buffer.from(data);\n dataLength = data.length;\n }\n } else {\n dataLength = data.length;\n merge = options.mask && options.readOnly && !skipMasking;\n }\n\n let payloadLength = dataLength;\n\n if (dataLength >= 65536) {\n offset += 8;\n payloadLength = 127;\n } else if (dataLength > 125) {\n offset += 2;\n payloadLength = 126;\n }\n\n const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);\n\n target[0] = options.fin ? options.opcode | 0x80 : options.opcode;\n if (options.rsv1) target[0] |= 0x40;\n\n target[1] = payloadLength;\n\n if (payloadLength === 126) {\n target.writeUInt16BE(dataLength, 2);\n } else if (payloadLength === 127) {\n target[2] = target[3] = 0;\n target.writeUIntBE(dataLength, 4, 6);\n }\n\n if (!options.mask) return [target, data];\n\n target[1] |= 0x80;\n target[offset - 4] = mask[0];\n target[offset - 3] = mask[1];\n target[offset - 2] = mask[2];\n target[offset - 1] = mask[3];\n\n if (skipMasking) return [target, data];\n\n if (merge) {\n applyMask(data, mask, target, offset, dataLength);\n return [target];\n }\n\n applyMask(data, mask, data, 0, dataLength);\n return [target, data];\n }\n\n /**\n * Sends a close message to the other peer.\n *\n * @param {Number} [code] The status code component of the body\n * @param {(String|Buffer)} [data] The message component of the body\n * @param {Boolean} [mask=false] Specifies whether or not to mask the message\n * @param {Function} [cb] Callback\n * @public\n */\n close(code, data, mask, cb) {\n let buf;\n\n if (code === undefined) {\n buf = EMPTY_BUFFER;\n } else if (typeof code !== 'number' || !isValidStatusCode(code)) {\n throw new TypeError('First argument must be a valid error code number');\n } else if (data === undefined || !data.length) {\n buf = Buffer.allocUnsafe(2);\n buf.writeUInt16BE(code, 0);\n } else {\n const length = Buffer.byteLength(data);\n\n if (length > 123) {\n throw new RangeError('The message must not be greater than 123 bytes');\n }\n\n buf = Buffer.allocUnsafe(2 + length);\n buf.writeUInt16BE(code, 0);\n\n if (typeof data === 'string') {\n buf.write(data, 2);\n } else {\n buf.set(data, 2);\n }\n }\n\n const options = {\n [kByteLength]: buf.length,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x08,\n readOnly: false,\n rsv1: false\n };\n\n if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, buf, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(buf, options), cb);\n }\n }\n\n /**\n * Sends a ping message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n ping(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x09,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a pong message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n pong(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x0a,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a data message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Object} options Options object\n * @param {Boolean} [options.binary=false] Specifies whether `data` is binary\n * or text\n * @param {Boolean} [options.compress=false] Specifies whether or not to\n * compress `data`\n * @param {Boolean} [options.fin=false] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Function} [cb] Callback\n * @public\n */\n send(data, options, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n let opcode = options.binary ? 2 : 1;\n let rsv1 = options.compress;\n\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (this._firstFragment) {\n this._firstFragment = false;\n if (\n rsv1 &&\n perMessageDeflate &&\n perMessageDeflate.params[\n perMessageDeflate._isServer\n ? 'server_no_context_takeover'\n : 'client_no_context_takeover'\n ]\n ) {\n rsv1 = byteLength >= perMessageDeflate._threshold;\n }\n this._compress = rsv1;\n } else {\n rsv1 = false;\n opcode = 0;\n }\n\n if (options.fin) this._firstFragment = true;\n\n const opts = {\n [kByteLength]: byteLength,\n fin: options.fin,\n generateMask: this._generateMask,\n mask: options.mask,\n maskBuffer: this._maskBuffer,\n opcode,\n readOnly,\n rsv1\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, this._compress, opts, cb]);\n } else {\n this.getBlobData(data, this._compress, opts, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, this._compress, opts, cb]);\n } else {\n this.dispatch(data, this._compress, opts, cb);\n }\n }\n\n /**\n * Gets the contents of a blob as binary data.\n *\n * @param {Blob} blob The blob\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * the data\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n getBlobData(blob, compress, options, cb) {\n this._bufferedBytes += options[kByteLength];\n this._state = GET_BLOB_DATA;\n\n blob\n .arrayBuffer()\n .then((arrayBuffer) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while the blob was being read'\n );\n\n //\n // `callCallbacks` is called in the next tick to ensure that errors\n // that might be thrown in the callbacks behave like errors thrown\n // outside the promise chain.\n //\n process.nextTick(callCallbacks, this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n const data = toBuffer(arrayBuffer);\n\n if (!compress) {\n this._state = DEFAULT;\n this.sendFrame(Sender.frame(data, options), cb);\n this.dequeue();\n } else {\n this.dispatch(data, compress, options, cb);\n }\n })\n .catch((err) => {\n //\n // `onError` is called in the next tick for the same reason that\n // `callCallbacks` above is.\n //\n process.nextTick(onError, this, err, cb);\n });\n }\n\n /**\n * Dispatches a message.\n *\n * @param {(Buffer|String)} data The message to send\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * `data`\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n dispatch(data, compress, options, cb) {\n if (!compress) {\n this.sendFrame(Sender.frame(data, options), cb);\n return;\n }\n\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n this._bufferedBytes += options[kByteLength];\n this._state = DEFLATING;\n perMessageDeflate.compress(data, options.fin, (_, buf) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while data was being compressed'\n );\n\n callCallbacks(this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n this._state = DEFAULT;\n options.readOnly = false;\n this.sendFrame(Sender.frame(buf, options), cb);\n this.dequeue();\n });\n }\n\n /**\n * Executes queued send operations.\n *\n * @private\n */\n dequeue() {\n while (this._state === DEFAULT && this._queue.length) {\n const params = this._queue.shift();\n\n this._bufferedBytes -= params[3][kByteLength];\n Reflect.apply(params[0], this, params.slice(1));\n }\n }\n\n /**\n * Enqueues a send operation.\n *\n * @param {Array} params Send operation parameters.\n * @private\n */\n enqueue(params) {\n this._bufferedBytes += params[3][kByteLength];\n this._queue.push(params);\n }\n\n /**\n * Sends a frame.\n *\n * @param {(Buffer | String)[]} list The frame to send\n * @param {Function} [cb] Callback\n * @private\n */\n sendFrame(list, cb) {\n if (list.length === 2) {\n this._socket.cork();\n this._socket.write(list[0]);\n this._socket.write(list[1], cb);\n this._socket.uncork();\n } else {\n this._socket.write(list[0], cb);\n }\n }\n}\n\nmodule.exports = Sender;\n\n/**\n * Calls queued callbacks with an error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error to call the callbacks with\n * @param {Function} [cb] The first callback\n * @private\n */\nfunction callCallbacks(sender, err, cb) {\n if (typeof cb === 'function') cb(err);\n\n for (let i = 0; i < sender._queue.length; i++) {\n const params = sender._queue[i];\n const callback = params[params.length - 1];\n\n if (typeof callback === 'function') callback(err);\n }\n}\n\n/**\n * Handles a `Sender` error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error\n * @param {Function} [cb] The first pending callback\n * @private\n */\nfunction onError(sender, err, cb) {\n callCallbacks(sender, err, cb);\n sender.onerror(err);\n}\n","'use strict';\n\nconst { kForOnEventAttribute, kListener } = require('./constants');\n\nconst kCode = Symbol('kCode');\nconst kData = Symbol('kData');\nconst kError = Symbol('kError');\nconst kMessage = Symbol('kMessage');\nconst kReason = Symbol('kReason');\nconst kTarget = Symbol('kTarget');\nconst kType = Symbol('kType');\nconst kWasClean = Symbol('kWasClean');\n\n/**\n * Class representing an event.\n */\nclass Event {\n /**\n * Create a new `Event`.\n *\n * @param {String} type The name of the event\n * @throws {TypeError} If the `type` argument is not specified\n */\n constructor(type) {\n this[kTarget] = null;\n this[kType] = type;\n }\n\n /**\n * @type {*}\n */\n get target() {\n return this[kTarget];\n }\n\n /**\n * @type {String}\n */\n get type() {\n return this[kType];\n }\n}\n\nObject.defineProperty(Event.prototype, 'target', { enumerable: true });\nObject.defineProperty(Event.prototype, 'type', { enumerable: true });\n\n/**\n * Class representing a close event.\n *\n * @extends Event\n */\nclass CloseEvent extends Event {\n /**\n * Create a new `CloseEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {Number} [options.code=0] The status code explaining why the\n * connection was closed\n * @param {String} [options.reason=''] A human-readable string explaining why\n * the connection was closed\n * @param {Boolean} [options.wasClean=false] Indicates whether or not the\n * connection was cleanly closed\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kCode] = options.code === undefined ? 0 : options.code;\n this[kReason] = options.reason === undefined ? '' : options.reason;\n this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;\n }\n\n /**\n * @type {Number}\n */\n get code() {\n return this[kCode];\n }\n\n /**\n * @type {String}\n */\n get reason() {\n return this[kReason];\n }\n\n /**\n * @type {Boolean}\n */\n get wasClean() {\n return this[kWasClean];\n }\n}\n\nObject.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });\n\n/**\n * Class representing an error event.\n *\n * @extends Event\n */\nclass ErrorEvent extends Event {\n /**\n * Create a new `ErrorEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.error=null] The error that generated this event\n * @param {String} [options.message=''] The error message\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kError] = options.error === undefined ? null : options.error;\n this[kMessage] = options.message === undefined ? '' : options.message;\n }\n\n /**\n * @type {*}\n */\n get error() {\n return this[kError];\n }\n\n /**\n * @type {String}\n */\n get message() {\n return this[kMessage];\n }\n}\n\nObject.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });\nObject.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });\n\n/**\n * Class representing a message event.\n *\n * @extends Event\n */\nclass MessageEvent extends Event {\n /**\n * Create a new `MessageEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.data=null] The message content\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kData] = options.data === undefined ? null : options.data;\n }\n\n /**\n * @type {*}\n */\n get data() {\n return this[kData];\n }\n}\n\nObject.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });\n\n/**\n * This provides methods for emulating the `EventTarget` interface. It's not\n * meant to be used directly.\n *\n * @mixin\n */\nconst EventTarget = {\n /**\n * Register an event listener.\n *\n * @param {String} type A string representing the event type to listen for\n * @param {(Function|Object)} handler The listener to add\n * @param {Object} [options] An options object specifies characteristics about\n * the event listener\n * @param {Boolean} [options.once=false] A `Boolean` indicating that the\n * listener should be invoked at most once after being added. If `true`,\n * the listener would be automatically removed when invoked.\n * @public\n */\n addEventListener(type, handler, options = {}) {\n for (const listener of this.listeners(type)) {\n if (\n !options[kForOnEventAttribute] &&\n listener[kListener] === handler &&\n !listener[kForOnEventAttribute]\n ) {\n return;\n }\n }\n\n let wrapper;\n\n if (type === 'message') {\n wrapper = function onMessage(data, isBinary) {\n const event = new MessageEvent('message', {\n data: isBinary ? data : data.toString()\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'close') {\n wrapper = function onClose(code, message) {\n const event = new CloseEvent('close', {\n code,\n reason: message.toString(),\n wasClean: this._closeFrameReceived && this._closeFrameSent\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'error') {\n wrapper = function onError(error) {\n const event = new ErrorEvent('error', {\n error,\n message: error.message\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'open') {\n wrapper = function onOpen() {\n const event = new Event('open');\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else {\n return;\n }\n\n wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];\n wrapper[kListener] = handler;\n\n if (options.once) {\n this.once(type, wrapper);\n } else {\n this.on(type, wrapper);\n }\n },\n\n /**\n * Remove an event listener.\n *\n * @param {String} type A string representing the event type to remove\n * @param {(Function|Object)} handler The listener to remove\n * @public\n */\n removeEventListener(type, handler) {\n for (const listener of this.listeners(type)) {\n if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {\n this.removeListener(type, listener);\n break;\n }\n }\n }\n};\n\nmodule.exports = {\n CloseEvent,\n ErrorEvent,\n Event,\n EventTarget,\n MessageEvent\n};\n\n/**\n * Call an event listener\n *\n * @param {(Function|Object)} listener The listener to call\n * @param {*} thisArg The value to use as `this`` when calling the listener\n * @param {Event} event The event to pass to the listener\n * @private\n */\nfunction callListener(listener, thisArg, event) {\n if (typeof listener === 'object' && listener.handleEvent) {\n listener.handleEvent.call(listener, event);\n } else {\n listener.call(thisArg, event);\n }\n}\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Adds an offer to the map of extension offers or a parameter to the map of\n * parameters.\n *\n * @param {Object} dest The map of extension offers or parameters\n * @param {String} name The extension or parameter name\n * @param {(Object|Boolean|String)} elem The extension parameters or the\n * parameter value\n * @private\n */\nfunction push(dest, name, elem) {\n if (dest[name] === undefined) dest[name] = [elem];\n else dest[name].push(elem);\n}\n\n/**\n * Parses the `Sec-WebSocket-Extensions` header into an object.\n *\n * @param {String} header The field value of the header\n * @return {Object} The parsed object\n * @public\n */\nfunction parse(header) {\n const offers = Object.create(null);\n let params = Object.create(null);\n let mustUnescape = false;\n let isEscaping = false;\n let inQuotes = false;\n let extensionName;\n let paramName;\n let start = -1;\n let code = -1;\n let end = -1;\n let i = 0;\n\n for (; i < header.length; i++) {\n code = header.charCodeAt(i);\n\n if (extensionName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n const name = header.slice(start, end);\n if (code === 0x2c) {\n push(offers, name, params);\n params = Object.create(null);\n } else {\n extensionName = name;\n }\n\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (paramName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x20 || code === 0x09) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n push(params, header.slice(start, end), true);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n start = end = -1;\n } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {\n paramName = header.slice(start, i);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else {\n //\n // The value of a quoted-string after unescaping must conform to the\n // token ABNF, so only token characters are valid.\n // Ref: https://tools.ietf.org/html/rfc6455#section-9.1\n //\n if (isEscaping) {\n if (tokenChars[code] !== 1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n if (start === -1) start = i;\n else if (!mustUnescape) mustUnescape = true;\n isEscaping = false;\n } else if (inQuotes) {\n if (tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x22 /* '\"' */ && start !== -1) {\n inQuotes = false;\n end = i;\n } else if (code === 0x5c /* '\\' */) {\n isEscaping = true;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {\n inQuotes = true;\n } else if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (start !== -1 && (code === 0x20 || code === 0x09)) {\n if (end === -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n let value = header.slice(start, end);\n if (mustUnescape) {\n value = value.replace(/\\\\/g, '');\n mustUnescape = false;\n }\n push(params, paramName, value);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n paramName = undefined;\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n }\n\n if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n if (end === -1) end = i;\n const token = header.slice(start, end);\n if (extensionName === undefined) {\n push(offers, token, params);\n } else {\n if (paramName === undefined) {\n push(params, token, true);\n } else if (mustUnescape) {\n push(params, paramName, token.replace(/\\\\/g, ''));\n } else {\n push(params, paramName, token);\n }\n push(offers, extensionName, params);\n }\n\n return offers;\n}\n\n/**\n * Builds the `Sec-WebSocket-Extensions` header field value.\n *\n * @param {Object} extensions The map of extensions and parameters to format\n * @return {String} A string representing the given object\n * @public\n */\nfunction format(extensions) {\n return Object.keys(extensions)\n .map((extension) => {\n let configurations = extensions[extension];\n if (!Array.isArray(configurations)) configurations = [configurations];\n return configurations\n .map((params) => {\n return [extension]\n .concat(\n Object.keys(params).map((k) => {\n let values = params[k];\n if (!Array.isArray(values)) values = [values];\n return values\n .map((v) => (v === true ? k : `${k}=${v}`))\n .join('; ');\n })\n )\n .join('; ');\n })\n .join(', ');\n })\n .join(', ');\n}\n\nmodule.exports = { format, parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex|Readable$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst https = require('https');\nconst http = require('http');\nconst net = require('net');\nconst tls = require('tls');\nconst { randomBytes, createHash } = require('crypto');\nconst { Duplex, Readable } = require('stream');\nconst { URL } = require('url');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst Receiver = require('./receiver');\nconst Sender = require('./sender');\nconst { isBlob } = require('./validation');\n\nconst {\n BINARY_TYPES,\n CLOSE_TIMEOUT,\n EMPTY_BUFFER,\n GUID,\n kForOnEventAttribute,\n kListener,\n kStatusCode,\n kWebSocket,\n NOOP\n} = require('./constants');\nconst {\n EventTarget: { addEventListener, removeEventListener }\n} = require('./event-target');\nconst { format, parse } = require('./extension');\nconst { toBuffer } = require('./buffer-util');\n\nconst kAborted = Symbol('kAborted');\nconst protocolVersions = [8, 13];\nconst readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];\nconst subprotocolRegex = /^[!#$%&'*+\\-.0-9A-Z^_`|a-z~]+$/;\n\n/**\n * Class representing a WebSocket.\n *\n * @extends EventEmitter\n */\nclass WebSocket extends EventEmitter {\n /**\n * Create a new `WebSocket`.\n *\n * @param {(String|URL)} address The URL to which to connect\n * @param {(String|String[])} [protocols] The subprotocols\n * @param {Object} [options] Connection options\n */\n constructor(address, protocols, options) {\n super();\n\n this._binaryType = BINARY_TYPES[0];\n this._closeCode = 1006;\n this._closeFrameReceived = false;\n this._closeFrameSent = false;\n this._closeMessage = EMPTY_BUFFER;\n this._closeTimer = null;\n this._errorEmitted = false;\n this._extensions = {};\n this._paused = false;\n this._protocol = '';\n this._readyState = WebSocket.CONNECTING;\n this._receiver = null;\n this._sender = null;\n this._socket = null;\n\n if (address !== null) {\n this._bufferedAmount = 0;\n this._isServer = false;\n this._redirects = 0;\n\n if (protocols === undefined) {\n protocols = [];\n } else if (!Array.isArray(protocols)) {\n if (typeof protocols === 'object' && protocols !== null) {\n options = protocols;\n protocols = [];\n } else {\n protocols = [protocols];\n }\n }\n\n initAsClient(this, address, protocols, options);\n } else {\n this._autoPong = options.autoPong;\n this._closeTimeout = options.closeTimeout;\n this._isServer = true;\n }\n }\n\n /**\n * For historical reasons, the custom \"nodebuffer\" type is used by the default\n * instead of \"blob\".\n *\n * @type {String}\n */\n get binaryType() {\n return this._binaryType;\n }\n\n set binaryType(type) {\n if (!BINARY_TYPES.includes(type)) return;\n\n this._binaryType = type;\n\n //\n // Allow to change `binaryType` on the fly.\n //\n if (this._receiver) this._receiver._binaryType = type;\n }\n\n /**\n * @type {Number}\n */\n get bufferedAmount() {\n if (!this._socket) return this._bufferedAmount;\n\n return this._socket._writableState.length + this._sender._bufferedBytes;\n }\n\n /**\n * @type {String}\n */\n get extensions() {\n return Object.keys(this._extensions).join();\n }\n\n /**\n * @type {Boolean}\n */\n get isPaused() {\n return this._paused;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onclose() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onerror() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onopen() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onmessage() {\n return null;\n }\n\n /**\n * @type {String}\n */\n get protocol() {\n return this._protocol;\n }\n\n /**\n * @type {Number}\n */\n get readyState() {\n return this._readyState;\n }\n\n /**\n * @type {String}\n */\n get url() {\n return this._url;\n }\n\n /**\n * Set up the socket and the internal resources.\n *\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Object} options Options object\n * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.maxPayload=0] The maximum allowed message size\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\n setSocket(socket, head, options) {\n const receiver = new Receiver({\n allowSynchronousEvents: options.allowSynchronousEvents,\n binaryType: this.binaryType,\n extensions: this._extensions,\n isServer: this._isServer,\n maxPayload: options.maxPayload,\n skipUTF8Validation: options.skipUTF8Validation\n });\n\n const sender = new Sender(socket, this._extensions, options.generateMask);\n\n this._receiver = receiver;\n this._sender = sender;\n this._socket = socket;\n\n receiver[kWebSocket] = this;\n sender[kWebSocket] = this;\n socket[kWebSocket] = this;\n\n receiver.on('conclude', receiverOnConclude);\n receiver.on('drain', receiverOnDrain);\n receiver.on('error', receiverOnError);\n receiver.on('message', receiverOnMessage);\n receiver.on('ping', receiverOnPing);\n receiver.on('pong', receiverOnPong);\n\n sender.onerror = senderOnError;\n\n //\n // These methods may not be available if `socket` is just a `Duplex`.\n //\n if (socket.setTimeout) socket.setTimeout(0);\n if (socket.setNoDelay) socket.setNoDelay();\n\n if (head.length > 0) socket.unshift(head);\n\n socket.on('close', socketOnClose);\n socket.on('data', socketOnData);\n socket.on('end', socketOnEnd);\n socket.on('error', socketOnError);\n\n this._readyState = WebSocket.OPEN;\n this.emit('open');\n }\n\n /**\n * Emit the `'close'` event.\n *\n * @private\n */\n emitClose() {\n if (!this._socket) {\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n return;\n }\n\n if (this._extensions[PerMessageDeflate.extensionName]) {\n this._extensions[PerMessageDeflate.extensionName].cleanup();\n }\n\n this._receiver.removeAllListeners();\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n }\n\n /**\n * Start a closing handshake.\n *\n * +----------+ +-----------+ +----------+\n * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -\n * | +----------+ +-----------+ +----------+ |\n * +----------+ +-----------+ |\n * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING\n * +----------+ +-----------+ |\n * | | | +---+ |\n * +------------------------+-->|fin| - - - -\n * | +---+ | +---+\n * - - - - -|fin|<---------------------+\n * +---+\n *\n * @param {Number} [code] Status code explaining why the connection is closing\n * @param {(String|Buffer)} [data] The reason why the connection is\n * closing\n * @public\n */\n close(code, data) {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this.readyState === WebSocket.CLOSING) {\n if (\n this._closeFrameSent &&\n (this._closeFrameReceived || this._receiver._writableState.errorEmitted)\n ) {\n this._socket.end();\n }\n\n return;\n }\n\n this._readyState = WebSocket.CLOSING;\n this._sender.close(code, data, !this._isServer, (err) => {\n //\n // This error is handled by the `'error'` listener on the socket. We only\n // want to know if the close frame has been sent here.\n //\n if (err) return;\n\n this._closeFrameSent = true;\n\n if (\n this._closeFrameReceived ||\n this._receiver._writableState.errorEmitted\n ) {\n this._socket.end();\n }\n });\n\n setCloseTimer(this);\n }\n\n /**\n * Pause the socket.\n *\n * @public\n */\n pause() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = true;\n this._socket.pause();\n }\n\n /**\n * Send a ping.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the ping is sent\n * @public\n */\n ping(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.ping(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Send a pong.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the pong is sent\n * @public\n */\n pong(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.pong(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Resume the socket.\n *\n * @public\n */\n resume() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = false;\n if (!this._receiver._writableState.needDrain) this._socket.resume();\n }\n\n /**\n * Send a data message.\n *\n * @param {*} data The message to send\n * @param {Object} [options] Options object\n * @param {Boolean} [options.binary] Specifies whether `data` is binary or\n * text\n * @param {Boolean} [options.compress] Specifies whether or not to compress\n * `data`\n * @param {Boolean} [options.fin=true] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when data is written out\n * @public\n */\n send(data, options, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n const opts = {\n binary: typeof data !== 'string',\n mask: !this._isServer,\n compress: true,\n fin: true,\n ...options\n };\n\n if (!this._extensions[PerMessageDeflate.extensionName]) {\n opts.compress = false;\n }\n\n this._sender.send(data || EMPTY_BUFFER, opts, cb);\n }\n\n /**\n * Forcibly close the connection.\n *\n * @public\n */\n terminate() {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this._socket) {\n this._readyState = WebSocket.CLOSING;\n this._socket.destroy();\n }\n }\n}\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n[\n 'binaryType',\n 'bufferedAmount',\n 'extensions',\n 'isPaused',\n 'protocol',\n 'readyState',\n 'url'\n].forEach((property) => {\n Object.defineProperty(WebSocket.prototype, property, { enumerable: true });\n});\n\n//\n// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.\n// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface\n//\n['open', 'error', 'close', 'message'].forEach((method) => {\n Object.defineProperty(WebSocket.prototype, `on${method}`, {\n enumerable: true,\n get() {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) return listener[kListener];\n }\n\n return null;\n },\n set(handler) {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) {\n this.removeListener(method, listener);\n break;\n }\n }\n\n if (typeof handler !== 'function') return;\n\n this.addEventListener(method, handler, {\n [kForOnEventAttribute]: true\n });\n }\n });\n});\n\nWebSocket.prototype.addEventListener = addEventListener;\nWebSocket.prototype.removeEventListener = removeEventListener;\n\nmodule.exports = WebSocket;\n\n/**\n * Initialize a WebSocket client.\n *\n * @param {WebSocket} websocket The client to initialize\n * @param {(String|URL)} address The URL to which to connect\n * @param {Array} protocols The subprotocols\n * @param {Object} [options] Connection options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any\n * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple\n * times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait\n * for the closing handshake to finish after `websocket.close()` is called\n * @param {Function} [options.finishRequest] A function which can be used to\n * customize the headers of each http request before it is sent\n * @param {Boolean} [options.followRedirects=false] Whether or not to follow\n * redirects\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the\n * handshake request\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Number} [options.maxRedirects=10] The maximum number of redirects\n * allowed\n * @param {String} [options.origin] Value of the `Origin` or\n * `Sec-WebSocket-Origin` header\n * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable\n * permessage-deflate\n * @param {Number} [options.protocolVersion=13] Value of the\n * `Sec-WebSocket-Version` header\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\nfunction initAsClient(websocket, address, protocols, options) {\n const opts = {\n allowSynchronousEvents: true,\n autoPong: true,\n closeTimeout: CLOSE_TIMEOUT,\n protocolVersion: protocolVersions[1],\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: true,\n followRedirects: false,\n maxRedirects: 10,\n ...options,\n socketPath: undefined,\n hostname: undefined,\n protocol: undefined,\n timeout: undefined,\n method: 'GET',\n host: undefined,\n path: undefined,\n port: undefined\n };\n\n websocket._autoPong = opts.autoPong;\n websocket._closeTimeout = opts.closeTimeout;\n\n if (!protocolVersions.includes(opts.protocolVersion)) {\n throw new RangeError(\n `Unsupported protocol version: ${opts.protocolVersion} ` +\n `(supported versions: ${protocolVersions.join(', ')})`\n );\n }\n\n let parsedUrl;\n\n if (address instanceof URL) {\n parsedUrl = address;\n } else {\n try {\n parsedUrl = new URL(address);\n } catch (e) {\n throw new SyntaxError(`Invalid URL: ${address}`);\n }\n }\n\n if (parsedUrl.protocol === 'http:') {\n parsedUrl.protocol = 'ws:';\n } else if (parsedUrl.protocol === 'https:') {\n parsedUrl.protocol = 'wss:';\n }\n\n websocket._url = parsedUrl.href;\n\n const isSecure = parsedUrl.protocol === 'wss:';\n const isIpcUrl = parsedUrl.protocol === 'ws+unix:';\n let invalidUrlMessage;\n\n if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {\n invalidUrlMessage =\n 'The URL\\'s protocol must be one of \"ws:\", \"wss:\", ' +\n '\"http:\", \"https:\", or \"ws+unix:\"';\n } else if (isIpcUrl && !parsedUrl.pathname) {\n invalidUrlMessage = \"The URL's pathname is empty\";\n } else if (parsedUrl.hash) {\n invalidUrlMessage = 'The URL contains a fragment identifier';\n }\n\n if (invalidUrlMessage) {\n const err = new SyntaxError(invalidUrlMessage);\n\n if (websocket._redirects === 0) {\n throw err;\n } else {\n emitErrorAndClose(websocket, err);\n return;\n }\n }\n\n const defaultPort = isSecure ? 443 : 80;\n const key = randomBytes(16).toString('base64');\n const request = isSecure ? https.request : http.request;\n const protocolSet = new Set();\n let perMessageDeflate;\n\n opts.createConnection =\n opts.createConnection || (isSecure ? tlsConnect : netConnect);\n opts.defaultPort = opts.defaultPort || defaultPort;\n opts.port = parsedUrl.port || defaultPort;\n opts.host = parsedUrl.hostname.startsWith('[')\n ? parsedUrl.hostname.slice(1, -1)\n : parsedUrl.hostname;\n opts.headers = {\n ...opts.headers,\n 'Sec-WebSocket-Version': opts.protocolVersion,\n 'Sec-WebSocket-Key': key,\n Connection: 'Upgrade',\n Upgrade: 'websocket'\n };\n opts.path = parsedUrl.pathname + parsedUrl.search;\n opts.timeout = opts.handshakeTimeout;\n\n if (opts.perMessageDeflate) {\n perMessageDeflate = new PerMessageDeflate(\n opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},\n false,\n opts.maxPayload\n );\n opts.headers['Sec-WebSocket-Extensions'] = format({\n [PerMessageDeflate.extensionName]: perMessageDeflate.offer()\n });\n }\n if (protocols.length) {\n for (const protocol of protocols) {\n if (\n typeof protocol !== 'string' ||\n !subprotocolRegex.test(protocol) ||\n protocolSet.has(protocol)\n ) {\n throw new SyntaxError(\n 'An invalid or duplicated subprotocol was specified'\n );\n }\n\n protocolSet.add(protocol);\n }\n\n opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');\n }\n if (opts.origin) {\n if (opts.protocolVersion < 13) {\n opts.headers['Sec-WebSocket-Origin'] = opts.origin;\n } else {\n opts.headers.Origin = opts.origin;\n }\n }\n if (parsedUrl.username || parsedUrl.password) {\n opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;\n }\n\n if (isIpcUrl) {\n const parts = opts.path.split(':');\n\n opts.socketPath = parts[0];\n opts.path = parts[1];\n }\n\n let req;\n\n if (opts.followRedirects) {\n if (websocket._redirects === 0) {\n websocket._originalIpc = isIpcUrl;\n websocket._originalSecure = isSecure;\n websocket._originalHostOrSocketPath = isIpcUrl\n ? opts.socketPath\n : parsedUrl.host;\n\n const headers = options && options.headers;\n\n //\n // Shallow copy the user provided options so that headers can be changed\n // without mutating the original object.\n //\n options = { ...options, headers: {} };\n\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n options.headers[key.toLowerCase()] = value;\n }\n }\n } else if (websocket.listenerCount('redirect') === 0) {\n const isSameHost = isIpcUrl\n ? websocket._originalIpc\n ? opts.socketPath === websocket._originalHostOrSocketPath\n : false\n : websocket._originalIpc\n ? false\n : parsedUrl.host === websocket._originalHostOrSocketPath;\n\n if (!isSameHost || (websocket._originalSecure && !isSecure)) {\n //\n // Match curl 7.77.0 behavior and drop the following headers. These\n // headers are also dropped when following a redirect to a subdomain.\n //\n delete opts.headers.authorization;\n delete opts.headers.cookie;\n\n if (!isSameHost) delete opts.headers.host;\n\n opts.auth = undefined;\n }\n }\n\n //\n // Match curl 7.77.0 behavior and make the first `Authorization` header win.\n // If the `Authorization` header is set, then there is nothing to do as it\n // will take precedence.\n //\n if (opts.auth && !options.headers.authorization) {\n options.headers.authorization =\n 'Basic ' + Buffer.from(opts.auth).toString('base64');\n }\n\n req = websocket._req = request(opts);\n\n if (websocket._redirects) {\n //\n // Unlike what is done for the `'upgrade'` event, no early exit is\n // triggered here if the user calls `websocket.close()` or\n // `websocket.terminate()` from a listener of the `'redirect'` event. This\n // is because the user can also call `request.destroy()` with an error\n // before calling `websocket.close()` or `websocket.terminate()` and this\n // would result in an error being emitted on the `request` object with no\n // `'error'` event listeners attached.\n //\n websocket.emit('redirect', websocket.url, req);\n }\n } else {\n req = websocket._req = request(opts);\n }\n\n if (opts.timeout) {\n req.on('timeout', () => {\n abortHandshake(websocket, req, 'Opening handshake has timed out');\n });\n }\n\n req.on('error', (err) => {\n if (req === null || req[kAborted]) return;\n\n req = websocket._req = null;\n emitErrorAndClose(websocket, err);\n });\n\n req.on('response', (res) => {\n const location = res.headers.location;\n const statusCode = res.statusCode;\n\n if (\n location &&\n opts.followRedirects &&\n statusCode >= 300 &&\n statusCode < 400\n ) {\n if (++websocket._redirects > opts.maxRedirects) {\n abortHandshake(websocket, req, 'Maximum redirects exceeded');\n return;\n }\n\n req.abort();\n\n let addr;\n\n try {\n addr = new URL(location, address);\n } catch (e) {\n const err = new SyntaxError(`Invalid URL: ${location}`);\n emitErrorAndClose(websocket, err);\n return;\n }\n\n initAsClient(websocket, addr, protocols, options);\n } else if (!websocket.emit('unexpected-response', req, res)) {\n abortHandshake(\n websocket,\n req,\n `Unexpected server response: ${res.statusCode}`\n );\n }\n });\n\n req.on('upgrade', (res, socket, head) => {\n websocket.emit('upgrade', res);\n\n //\n // The user may have closed the connection from a listener of the\n // `'upgrade'` event.\n //\n if (websocket.readyState !== WebSocket.CONNECTING) return;\n\n req = websocket._req = null;\n\n const upgrade = res.headers.upgrade;\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n abortHandshake(websocket, socket, 'Invalid Upgrade header');\n return;\n }\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n if (res.headers['sec-websocket-accept'] !== digest) {\n abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');\n return;\n }\n\n const serverProt = res.headers['sec-websocket-protocol'];\n let protError;\n\n if (serverProt !== undefined) {\n if (!protocolSet.size) {\n protError = 'Server sent a subprotocol but none was requested';\n } else if (!protocolSet.has(serverProt)) {\n protError = 'Server sent an invalid subprotocol';\n }\n } else if (protocolSet.size) {\n protError = 'Server sent no subprotocol';\n }\n\n if (protError) {\n abortHandshake(websocket, socket, protError);\n return;\n }\n\n if (serverProt) websocket._protocol = serverProt;\n\n const secWebSocketExtensions = res.headers['sec-websocket-extensions'];\n\n if (secWebSocketExtensions !== undefined) {\n if (!perMessageDeflate) {\n const message =\n 'Server sent a Sec-WebSocket-Extensions header but no extension ' +\n 'was requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n let extensions;\n\n try {\n extensions = parse(secWebSocketExtensions);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n const extensionNames = Object.keys(extensions);\n\n if (\n extensionNames.length !== 1 ||\n extensionNames[0] !== PerMessageDeflate.extensionName\n ) {\n const message = 'Server indicated an extension that was not requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n try {\n perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n websocket._extensions[PerMessageDeflate.extensionName] =\n perMessageDeflate;\n }\n\n websocket.setSocket(socket, head, {\n allowSynchronousEvents: opts.allowSynchronousEvents,\n generateMask: opts.generateMask,\n maxPayload: opts.maxPayload,\n skipUTF8Validation: opts.skipUTF8Validation\n });\n });\n\n if (opts.finishRequest) {\n opts.finishRequest(req, websocket);\n } else {\n req.end();\n }\n}\n\n/**\n * Emit the `'error'` and `'close'` events.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {Error} The error to emit\n * @private\n */\nfunction emitErrorAndClose(websocket, err) {\n websocket._readyState = WebSocket.CLOSING;\n //\n // The following assignment is practically useless and is done only for\n // consistency.\n //\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n websocket.emitClose();\n}\n\n/**\n * Create a `net.Socket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {net.Socket} The newly created socket used to start the connection\n * @private\n */\nfunction netConnect(options) {\n options.path = options.socketPath;\n return net.connect(options);\n}\n\n/**\n * Create a `tls.TLSSocket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {tls.TLSSocket} The newly created socket used to start the connection\n * @private\n */\nfunction tlsConnect(options) {\n options.path = undefined;\n\n if (!options.servername && options.servername !== '') {\n options.servername = net.isIP(options.host) ? '' : options.host;\n }\n\n return tls.connect(options);\n}\n\n/**\n * Abort the handshake and emit an error.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to\n * abort or the socket to destroy\n * @param {String} message The error message\n * @private\n */\nfunction abortHandshake(websocket, stream, message) {\n websocket._readyState = WebSocket.CLOSING;\n\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshake);\n\n if (stream.setHeader) {\n stream[kAborted] = true;\n stream.abort();\n\n if (stream.socket && !stream.socket.destroyed) {\n //\n // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if\n // called after the request completed. See\n // https://github.com/websockets/ws/issues/1869.\n //\n stream.socket.destroy();\n }\n\n process.nextTick(emitErrorAndClose, websocket, err);\n } else {\n stream.destroy(err);\n stream.once('error', websocket.emit.bind(websocket, 'error'));\n stream.once('close', websocket.emitClose.bind(websocket));\n }\n}\n\n/**\n * Handle cases where the `ping()`, `pong()`, or `send()` methods are called\n * when the `readyState` attribute is `CLOSING` or `CLOSED`.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {*} [data] The data to send\n * @param {Function} [cb] Callback\n * @private\n */\nfunction sendAfterClose(websocket, data, cb) {\n if (data) {\n const length = isBlob(data) ? data.size : toBuffer(data).length;\n\n //\n // The `_bufferedAmount` property is used only when the peer is a client and\n // the opening handshake fails. Under these circumstances, in fact, the\n // `setSocket()` method is not called, so the `_socket` and `_sender`\n // properties are set to `null`.\n //\n if (websocket._socket) websocket._sender._bufferedBytes += length;\n else websocket._bufferedAmount += length;\n }\n\n if (cb) {\n const err = new Error(\n `WebSocket is not open: readyState ${websocket.readyState} ` +\n `(${readyStates[websocket.readyState]})`\n );\n process.nextTick(cb, err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'conclude'` event.\n *\n * @param {Number} code The status code\n * @param {Buffer} reason The reason for closing\n * @private\n */\nfunction receiverOnConclude(code, reason) {\n const websocket = this[kWebSocket];\n\n websocket._closeFrameReceived = true;\n websocket._closeMessage = reason;\n websocket._closeCode = code;\n\n if (websocket._socket[kWebSocket] === undefined) return;\n\n websocket._socket.removeListener('data', socketOnData);\n process.nextTick(resume, websocket._socket);\n\n if (code === 1005) websocket.close();\n else websocket.close(code, reason);\n}\n\n/**\n * The listener of the `Receiver` `'drain'` event.\n *\n * @private\n */\nfunction receiverOnDrain() {\n const websocket = this[kWebSocket];\n\n if (!websocket.isPaused) websocket._socket.resume();\n}\n\n/**\n * The listener of the `Receiver` `'error'` event.\n *\n * @param {(RangeError|Error)} err The emitted error\n * @private\n */\nfunction receiverOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket._socket[kWebSocket] !== undefined) {\n websocket._socket.removeListener('data', socketOnData);\n\n //\n // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See\n // https://github.com/websockets/ws/issues/1940.\n //\n process.nextTick(resume, websocket._socket);\n\n websocket.close(err[kStatusCode]);\n }\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'finish'` event.\n *\n * @private\n */\nfunction receiverOnFinish() {\n this[kWebSocket].emitClose();\n}\n\n/**\n * The listener of the `Receiver` `'message'` event.\n *\n * @param {Buffer|ArrayBuffer|Buffer[])} data The message\n * @param {Boolean} isBinary Specifies whether the message is binary or not\n * @private\n */\nfunction receiverOnMessage(data, isBinary) {\n this[kWebSocket].emit('message', data, isBinary);\n}\n\n/**\n * The listener of the `Receiver` `'ping'` event.\n *\n * @param {Buffer} data The data included in the ping frame\n * @private\n */\nfunction receiverOnPing(data) {\n const websocket = this[kWebSocket];\n\n if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);\n websocket.emit('ping', data);\n}\n\n/**\n * The listener of the `Receiver` `'pong'` event.\n *\n * @param {Buffer} data The data included in the pong frame\n * @private\n */\nfunction receiverOnPong(data) {\n this[kWebSocket].emit('pong', data);\n}\n\n/**\n * Resume a readable stream\n *\n * @param {Readable} stream The readable stream\n * @private\n */\nfunction resume(stream) {\n stream.resume();\n}\n\n/**\n * The `Sender` error event handler.\n *\n * @param {Error} The error\n * @private\n */\nfunction senderOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket.readyState === WebSocket.CLOSED) return;\n if (websocket.readyState === WebSocket.OPEN) {\n websocket._readyState = WebSocket.CLOSING;\n setCloseTimer(websocket);\n }\n\n //\n // `socket.end()` is used instead of `socket.destroy()` to allow the other\n // peer to finish sending queued data. There is no need to set a timer here\n // because `CLOSING` means that it is already set or not needed.\n //\n this._socket.end();\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * Set a timer to destroy the underlying raw socket of a WebSocket.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @private\n */\nfunction setCloseTimer(websocket) {\n websocket._closeTimer = setTimeout(\n websocket._socket.destroy.bind(websocket._socket),\n websocket._closeTimeout\n );\n}\n\n/**\n * The listener of the socket `'close'` event.\n *\n * @private\n */\nfunction socketOnClose() {\n const websocket = this[kWebSocket];\n\n this.removeListener('close', socketOnClose);\n this.removeListener('data', socketOnData);\n this.removeListener('end', socketOnEnd);\n\n websocket._readyState = WebSocket.CLOSING;\n\n //\n // The close frame might not have been received or the `'end'` event emitted,\n // for example, if the socket was destroyed due to an error. Ensure that the\n // `receiver` stream is closed after writing any remaining buffered data to\n // it. If the readable side of the socket is in flowing mode then there is no\n // buffered data as everything has been already written. If instead, the\n // socket is paused, any possible buffered data will be read as a single\n // chunk.\n //\n if (\n !this._readableState.endEmitted &&\n !websocket._closeFrameReceived &&\n !websocket._receiver._writableState.errorEmitted &&\n this._readableState.length !== 0\n ) {\n const chunk = this.read(this._readableState.length);\n\n websocket._receiver.write(chunk);\n }\n\n websocket._receiver.end();\n\n this[kWebSocket] = undefined;\n\n clearTimeout(websocket._closeTimer);\n\n if (\n websocket._receiver._writableState.finished ||\n websocket._receiver._writableState.errorEmitted\n ) {\n websocket.emitClose();\n } else {\n websocket._receiver.on('error', receiverOnFinish);\n websocket._receiver.on('finish', receiverOnFinish);\n }\n}\n\n/**\n * The listener of the socket `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction socketOnData(chunk) {\n if (!this[kWebSocket]._receiver.write(chunk)) {\n this.pause();\n }\n}\n\n/**\n * The listener of the socket `'end'` event.\n *\n * @private\n */\nfunction socketOnEnd() {\n const websocket = this[kWebSocket];\n\n websocket._readyState = WebSocket.CLOSING;\n websocket._receiver.end();\n this.end();\n}\n\n/**\n * The listener of the socket `'error'` event.\n *\n * @private\n */\nfunction socketOnError() {\n const websocket = this[kWebSocket];\n\n this.removeListener('error', socketOnError);\n this.on('error', NOOP);\n\n if (websocket) {\n websocket._readyState = WebSocket.CLOSING;\n this.destroy();\n }\n}\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^WebSocket$\" }] */\n'use strict';\n\nconst WebSocket = require('./websocket');\nconst { Duplex } = require('stream');\n\n/**\n * Emits the `'close'` event on a stream.\n *\n * @param {Duplex} stream The stream.\n * @private\n */\nfunction emitClose(stream) {\n stream.emit('close');\n}\n\n/**\n * The listener of the `'end'` event.\n *\n * @private\n */\nfunction duplexOnEnd() {\n if (!this.destroyed && this._writableState.finished) {\n this.destroy();\n }\n}\n\n/**\n * The listener of the `'error'` event.\n *\n * @param {Error} err The error\n * @private\n */\nfunction duplexOnError(err) {\n this.removeListener('error', duplexOnError);\n this.destroy();\n if (this.listenerCount('error') === 0) {\n // Do not suppress the throwing behavior.\n this.emit('error', err);\n }\n}\n\n/**\n * Wraps a `WebSocket` in a duplex stream.\n *\n * @param {WebSocket} ws The `WebSocket` to wrap\n * @param {Object} [options] The options for the `Duplex` constructor\n * @return {Duplex} The duplex stream\n * @public\n */\nfunction createWebSocketStream(ws, options) {\n let terminateOnDestroy = true;\n\n const duplex = new Duplex({\n ...options,\n autoDestroy: false,\n emitClose: false,\n objectMode: false,\n writableObjectMode: false\n });\n\n ws.on('message', function message(msg, isBinary) {\n const data =\n !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;\n\n if (!duplex.push(data)) ws.pause();\n });\n\n ws.once('error', function error(err) {\n if (duplex.destroyed) return;\n\n // Prevent `ws.terminate()` from being called by `duplex._destroy()`.\n //\n // - If the `'error'` event is emitted before the `'open'` event, then\n // `ws.terminate()` is a noop as no socket is assigned.\n // - Otherwise, the error is re-emitted by the listener of the `'error'`\n // event of the `Receiver` object. The listener already closes the\n // connection by calling `ws.close()`. This allows a close frame to be\n // sent to the other peer. If `ws.terminate()` is called right after this,\n // then the close frame might not be sent.\n terminateOnDestroy = false;\n duplex.destroy(err);\n });\n\n ws.once('close', function close() {\n if (duplex.destroyed) return;\n\n duplex.push(null);\n });\n\n duplex._destroy = function (err, callback) {\n if (ws.readyState === ws.CLOSED) {\n callback(err);\n process.nextTick(emitClose, duplex);\n return;\n }\n\n let called = false;\n\n ws.once('error', function error(err) {\n called = true;\n callback(err);\n });\n\n ws.once('close', function close() {\n if (!called) callback(err);\n process.nextTick(emitClose, duplex);\n });\n\n if (terminateOnDestroy) ws.terminate();\n };\n\n duplex._final = function (callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._final(callback);\n });\n return;\n }\n\n // If the value of the `_socket` property is `null` it means that `ws` is a\n // client websocket and the handshake failed. In fact, when this happens, a\n // socket is never assigned to the websocket. Wait for the `'error'` event\n // that will be emitted by the websocket.\n if (ws._socket === null) return;\n\n if (ws._socket._writableState.finished) {\n callback();\n if (duplex._readableState.endEmitted) duplex.destroy();\n } else {\n ws._socket.once('finish', function finish() {\n // `duplex` is not destroyed here because the `'end'` event will be\n // emitted on `duplex` after this `'finish'` event. The EOF signaling\n // `null` chunk is, in fact, pushed when the websocket emits `'close'`.\n callback();\n });\n ws.close();\n }\n };\n\n duplex._read = function () {\n if (ws.isPaused) ws.resume();\n };\n\n duplex._write = function (chunk, encoding, callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._write(chunk, encoding, callback);\n });\n return;\n }\n\n ws.send(chunk, callback);\n };\n\n duplex.on('end', duplexOnEnd);\n duplex.on('error', duplexOnError);\n return duplex;\n}\n\nmodule.exports = createWebSocketStream;\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.\n *\n * @param {String} header The field value of the header\n * @return {Set} The subprotocol names\n * @public\n */\nfunction parse(header) {\n const protocols = new Set();\n let start = -1;\n let end = -1;\n let i = 0;\n\n for (i; i < header.length; i++) {\n const code = header.charCodeAt(i);\n\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n\n const protocol = header.slice(start, end);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n\n if (start === -1 || end !== -1) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n const protocol = header.slice(start, i);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n return protocols;\n}\n\nmodule.exports = { parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst http = require('http');\nconst { Duplex } = require('stream');\nconst { createHash } = require('crypto');\n\nconst extension = require('./extension');\nconst PerMessageDeflate = require('./permessage-deflate');\nconst subprotocol = require('./subprotocol');\nconst WebSocket = require('./websocket');\nconst { CLOSE_TIMEOUT, GUID, kWebSocket } = require('./constants');\n\nconst keyRegex = /^[+/0-9A-Za-z]{22}==$/;\n\nconst RUNNING = 0;\nconst CLOSING = 1;\nconst CLOSED = 2;\n\n/**\n * Class representing a WebSocket server.\n *\n * @extends EventEmitter\n */\nclass WebSocketServer extends EventEmitter {\n /**\n * Create a `WebSocketServer` instance.\n *\n * @param {Object} options Configuration options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.backlog=511] The maximum length of the queue of\n * pending connections\n * @param {Boolean} [options.clientTracking=true] Specifies whether or not to\n * track clients\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to\n * wait for the closing handshake to finish after `websocket.close()` is\n * called\n * @param {Function} [options.handleProtocols] A hook to handle protocols\n * @param {String} [options.host] The hostname where to bind the server\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Boolean} [options.noServer=false] Enable no server mode\n * @param {String} [options.path] Accept only connections matching this path\n * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable\n * permessage-deflate\n * @param {Number} [options.port] The port where to bind the server\n * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S\n * server to use\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @param {Function} [options.verifyClient] A hook to reject connections\n * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`\n * class to use. It must be the `WebSocket` class or class that extends it\n * @param {Function} [callback] A listener for the `listening` event\n */\n constructor(options, callback) {\n super();\n\n options = {\n allowSynchronousEvents: true,\n autoPong: true,\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: false,\n handleProtocols: null,\n clientTracking: true,\n closeTimeout: CLOSE_TIMEOUT,\n verifyClient: null,\n noServer: false,\n backlog: null, // use default (511 as implemented in net.js)\n server: null,\n host: null,\n path: null,\n port: null,\n WebSocket,\n ...options\n };\n\n if (\n (options.port == null && !options.server && !options.noServer) ||\n (options.port != null && (options.server || options.noServer)) ||\n (options.server && options.noServer)\n ) {\n throw new TypeError(\n 'One and only one of the \"port\", \"server\", or \"noServer\" options ' +\n 'must be specified'\n );\n }\n\n if (options.port != null) {\n this._server = http.createServer((req, res) => {\n const body = http.STATUS_CODES[426];\n\n res.writeHead(426, {\n 'Content-Length': body.length,\n 'Content-Type': 'text/plain'\n });\n res.end(body);\n });\n this._server.listen(\n options.port,\n options.host,\n options.backlog,\n callback\n );\n } else if (options.server) {\n this._server = options.server;\n }\n\n if (this._server) {\n const emitConnection = this.emit.bind(this, 'connection');\n\n this._removeListeners = addListeners(this._server, {\n listening: this.emit.bind(this, 'listening'),\n error: this.emit.bind(this, 'error'),\n upgrade: (req, socket, head) => {\n this.handleUpgrade(req, socket, head, emitConnection);\n }\n });\n }\n\n if (options.perMessageDeflate === true) options.perMessageDeflate = {};\n if (options.clientTracking) {\n this.clients = new Set();\n this._shouldEmitClose = false;\n }\n\n this.options = options;\n this._state = RUNNING;\n }\n\n /**\n * Returns the bound address, the address family name, and port of the server\n * as reported by the operating system if listening on an IP socket.\n * If the server is listening on a pipe or UNIX domain socket, the name is\n * returned as a string.\n *\n * @return {(Object|String|null)} The address of the server\n * @public\n */\n address() {\n if (this.options.noServer) {\n throw new Error('The server is operating in \"noServer\" mode');\n }\n\n if (!this._server) return null;\n return this._server.address();\n }\n\n /**\n * Stop the server from accepting new connections and emit the `'close'` event\n * when all existing connections are closed.\n *\n * @param {Function} [cb] A one-time listener for the `'close'` event\n * @public\n */\n close(cb) {\n if (this._state === CLOSED) {\n if (cb) {\n this.once('close', () => {\n cb(new Error('The server is not running'));\n });\n }\n\n process.nextTick(emitClose, this);\n return;\n }\n\n if (cb) this.once('close', cb);\n\n if (this._state === CLOSING) return;\n this._state = CLOSING;\n\n if (this.options.noServer || this.options.server) {\n if (this._server) {\n this._removeListeners();\n this._removeListeners = this._server = null;\n }\n\n if (this.clients) {\n if (!this.clients.size) {\n process.nextTick(emitClose, this);\n } else {\n this._shouldEmitClose = true;\n }\n } else {\n process.nextTick(emitClose, this);\n }\n } else {\n const server = this._server;\n\n this._removeListeners();\n this._removeListeners = this._server = null;\n\n //\n // The HTTP/S server was created internally. Close it, and rely on its\n // `'close'` event.\n //\n server.close(() => {\n emitClose(this);\n });\n }\n }\n\n /**\n * See if a given request should be handled by this server instance.\n *\n * @param {http.IncomingMessage} req Request object to inspect\n * @return {Boolean} `true` if the request is valid, else `false`\n * @public\n */\n shouldHandle(req) {\n if (this.options.path) {\n const index = req.url.indexOf('?');\n const pathname = index !== -1 ? req.url.slice(0, index) : req.url;\n\n if (pathname !== this.options.path) return false;\n }\n\n return true;\n }\n\n /**\n * Handle a HTTP Upgrade request.\n *\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @public\n */\n handleUpgrade(req, socket, head, cb) {\n socket.on('error', socketOnError);\n\n const key = req.headers['sec-websocket-key'];\n const upgrade = req.headers.upgrade;\n const version = +req.headers['sec-websocket-version'];\n\n if (req.method !== 'GET') {\n const message = 'Invalid HTTP method';\n abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);\n return;\n }\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n const message = 'Invalid Upgrade header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (key === undefined || !keyRegex.test(key)) {\n const message = 'Missing or invalid Sec-WebSocket-Key header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (version !== 13 && version !== 8) {\n const message = 'Missing or invalid Sec-WebSocket-Version header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {\n 'Sec-WebSocket-Version': '13, 8'\n });\n return;\n }\n\n if (!this.shouldHandle(req)) {\n abortHandshake(socket, 400);\n return;\n }\n\n const secWebSocketProtocol = req.headers['sec-websocket-protocol'];\n let protocols = new Set();\n\n if (secWebSocketProtocol !== undefined) {\n try {\n protocols = subprotocol.parse(secWebSocketProtocol);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Protocol header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n const secWebSocketExtensions = req.headers['sec-websocket-extensions'];\n const extensions = {};\n\n if (\n this.options.perMessageDeflate &&\n secWebSocketExtensions !== undefined\n ) {\n const perMessageDeflate = new PerMessageDeflate(\n this.options.perMessageDeflate,\n true,\n this.options.maxPayload\n );\n\n try {\n const offers = extension.parse(secWebSocketExtensions);\n\n if (offers[PerMessageDeflate.extensionName]) {\n perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);\n extensions[PerMessageDeflate.extensionName] = perMessageDeflate;\n }\n } catch (err) {\n const message =\n 'Invalid or unacceptable Sec-WebSocket-Extensions header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n //\n // Optionally call external client verification handler.\n //\n if (this.options.verifyClient) {\n const info = {\n origin:\n req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],\n secure: !!(req.socket.authorized || req.socket.encrypted),\n req\n };\n\n if (this.options.verifyClient.length === 2) {\n this.options.verifyClient(info, (verified, code, message, headers) => {\n if (!verified) {\n return abortHandshake(socket, code || 401, message, headers);\n }\n\n this.completeUpgrade(\n extensions,\n key,\n protocols,\n req,\n socket,\n head,\n cb\n );\n });\n return;\n }\n\n if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);\n }\n\n this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);\n }\n\n /**\n * Upgrade the connection to WebSocket.\n *\n * @param {Object} extensions The accepted extensions\n * @param {String} key The value of the `Sec-WebSocket-Key` header\n * @param {Set} protocols The subprotocols\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @throws {Error} If called more than once with the same socket\n * @private\n */\n completeUpgrade(extensions, key, protocols, req, socket, head, cb) {\n //\n // Destroy the socket if the client has already sent a FIN packet.\n //\n if (!socket.readable || !socket.writable) return socket.destroy();\n\n if (socket[kWebSocket]) {\n throw new Error(\n 'server.handleUpgrade() was called more than once with the same ' +\n 'socket, possibly due to a misconfiguration'\n );\n }\n\n if (this._state > RUNNING) return abortHandshake(socket, 503);\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n const headers = [\n 'HTTP/1.1 101 Switching Protocols',\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Sec-WebSocket-Accept: ${digest}`\n ];\n\n const ws = new this.options.WebSocket(null, undefined, this.options);\n\n if (protocols.size) {\n //\n // Optionally call external protocol selection handler.\n //\n const protocol = this.options.handleProtocols\n ? this.options.handleProtocols(protocols, req)\n : protocols.values().next().value;\n\n if (protocol) {\n headers.push(`Sec-WebSocket-Protocol: ${protocol}`);\n ws._protocol = protocol;\n }\n }\n\n if (extensions[PerMessageDeflate.extensionName]) {\n const params = extensions[PerMessageDeflate.extensionName].params;\n const value = extension.format({\n [PerMessageDeflate.extensionName]: [params]\n });\n headers.push(`Sec-WebSocket-Extensions: ${value}`);\n ws._extensions = extensions;\n }\n\n //\n // Allow external modification/inspection of handshake headers.\n //\n this.emit('headers', headers, req);\n\n socket.write(headers.concat('\\r\\n').join('\\r\\n'));\n socket.removeListener('error', socketOnError);\n\n ws.setSocket(socket, head, {\n allowSynchronousEvents: this.options.allowSynchronousEvents,\n maxPayload: this.options.maxPayload,\n skipUTF8Validation: this.options.skipUTF8Validation\n });\n\n if (this.clients) {\n this.clients.add(ws);\n ws.on('close', () => {\n this.clients.delete(ws);\n\n if (this._shouldEmitClose && !this.clients.size) {\n process.nextTick(emitClose, this);\n }\n });\n }\n\n cb(ws, req);\n }\n}\n\nmodule.exports = WebSocketServer;\n\n/**\n * Add event listeners on an `EventEmitter` using a map of <event, listener>\n * pairs.\n *\n * @param {EventEmitter} server The event emitter\n * @param {Object.<String, Function>} map The listeners to add\n * @return {Function} A function that will remove the added listeners when\n * called\n * @private\n */\nfunction addListeners(server, map) {\n for (const event of Object.keys(map)) server.on(event, map[event]);\n\n return function removeListeners() {\n for (const event of Object.keys(map)) {\n server.removeListener(event, map[event]);\n }\n };\n}\n\n/**\n * Emit a `'close'` event on an `EventEmitter`.\n *\n * @param {EventEmitter} server The event emitter\n * @private\n */\nfunction emitClose(server) {\n server._state = CLOSED;\n server.emit('close');\n}\n\n/**\n * Handle socket errors.\n *\n * @private\n */\nfunction socketOnError() {\n this.destroy();\n}\n\n/**\n * Close the connection when preconditions are not fulfilled.\n *\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} [message] The HTTP response body\n * @param {Object} [headers] Additional HTTP response headers\n * @private\n */\nfunction abortHandshake(socket, code, message, headers) {\n //\n // The socket is writable unless the user destroyed or ended it before calling\n // `server.handleUpgrade()` or in the `verifyClient` function, which is a user\n // error. Handling this does not make much sense as the worst that can happen\n // is that some of the data written by the user might be discarded due to the\n // call to `socket.end()` below, which triggers an `'error'` event that in\n // turn causes the socket to be destroyed.\n //\n message = message || http.STATUS_CODES[code];\n headers = {\n Connection: 'close',\n 'Content-Type': 'text/html',\n 'Content-Length': Buffer.byteLength(message),\n ...headers\n };\n\n socket.once('finish', socket.destroy);\n\n socket.end(\n `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\\r\\n` +\n Object.keys(headers)\n .map((h) => `${h}: ${headers[h]}`)\n .join('\\r\\n') +\n '\\r\\n\\r\\n' +\n message\n );\n}\n\n/**\n * Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least\n * one listener for it, otherwise call `abortHandshake()`.\n *\n * @param {WebSocketServer} server The WebSocket server\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} message The HTTP response body\n * @param {Object} [headers] The HTTP response headers\n * @private\n */\nfunction abortHandshakeOrEmitwsClientError(\n server,\n req,\n socket,\n code,\n message,\n headers\n) {\n if (server.listenerCount('wsClientError')) {\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);\n\n server.emit('wsClientError', err, socket, req);\n } else {\n abortHandshake(socket, code, message, headers);\n }\n}\n","import type { TownhouseConfig } from './schema.js';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { DEFAULT_CONNECTOR_IMAGE } from '../constants.js';\n\n/**\n * Sensible default configuration. All nodes disabled by default —\n * operator must explicitly enable what they want to run.\n */\nexport function getDefaultConfig(): TownhouseConfig {\n return {\n nodes: {\n town: { enabled: false },\n mill: { enabled: false },\n dvm: { enabled: false },\n },\n wallet: {\n encrypted_path: join(homedir(), '.townhouse', 'wallet.enc'),\n },\n connector: {\n image: DEFAULT_CONNECTOR_IMAGE,\n adminPort: 9401,\n },\n transport: {\n mode: 'direct',\n },\n api: {\n port: 9400,\n host: '127.0.0.1',\n },\n logging: {\n level: 'info',\n },\n };\n}\n","/**\n * Runtime validation for Townhouse configuration.\n * Validates shape, narrows types, returns typed config or throws.\n */\n\nimport type { TownhouseConfig } from './schema.js';\n\nclass ConfigValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigValidationError';\n }\n}\n\nfunction assertObject(\n value: unknown,\n path: string\n): asserts value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new ConfigValidationError(`${path} must be a non-null object`);\n }\n}\n\nfunction assertBoolean(value: unknown, path: string): asserts value is boolean {\n if (typeof value !== 'boolean') {\n throw new ConfigValidationError(`${path} must be a boolean`);\n }\n}\n\nfunction assertString(value: unknown, path: string): asserts value is string {\n if (typeof value !== 'string') {\n throw new ConfigValidationError(`${path} must be a string`);\n }\n}\n\nfunction assertNumber(value: unknown, path: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new ConfigValidationError(`${path} must be a finite number`);\n }\n}\n\nfunction assertPort(value: number, path: string): void {\n if (!Number.isInteger(value) || value < 0 || value > 65535) {\n throw new ConfigValidationError(\n `${path} must be an integer in range 0..65535`\n );\n }\n}\n\nconst VALID_LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error']);\nconst VALID_TRANSPORT_MODES = new Set(['ator', 'direct']);\n\nfunction validateNodeConfig(\n raw: unknown,\n path: string\n): { enabled: boolean } & Record<string, unknown> {\n assertObject(raw, path);\n assertBoolean(raw['enabled'], `${path}.enabled`);\n\n if (raw['feePerEvent'] !== undefined) {\n assertNumber(raw['feePerEvent'], `${path}.feePerEvent`);\n }\n if (raw['feeBasisPoints'] !== undefined) {\n assertNumber(raw['feeBasisPoints'], `${path}.feeBasisPoints`);\n }\n if (raw['feePerJob'] !== undefined) {\n assertNumber(raw['feePerJob'], `${path}.feePerJob`);\n }\n if (raw['kindPricing'] !== undefined) {\n assertObject(raw['kindPricing'], `${path}.kindPricing`);\n for (const [k, v] of Object.entries(\n raw['kindPricing'] as Record<string, unknown>\n )) {\n // Keys must be positive-integer strings — prevents prototype-key\n // pollution (`__proto__`, `constructor`) and env-var key injection\n // (newlines / spaces) when the orchestrator emits KIND_PRICING_<k>.\n if (!/^[0-9]+$/.test(k)) {\n throw new ConfigValidationError(\n `${path}.kindPricing has invalid key \"${k}\" — must be a positive-integer string`\n );\n }\n assertNumber(v, `${path}.kindPricing.${k}`);\n if (!Number.isInteger(v as number) || (v as number) < 0) {\n throw new ConfigValidationError(\n `${path}.kindPricing.${k} must be a non-negative integer`\n );\n }\n if ((v as number) > Number.MAX_SAFE_INTEGER) {\n throw new ConfigValidationError(\n `${path}.kindPricing.${k} exceeds Number.MAX_SAFE_INTEGER`\n );\n }\n }\n }\n if (raw['image'] !== undefined) {\n assertString(raw['image'], `${path}.image`);\n }\n\n return raw as { enabled: boolean } & Record<string, unknown>;\n}\n\n/**\n * Validate raw input and return a typed TownhouseConfig.\n * Throws ConfigValidationError with descriptive messages on invalid input.\n */\nexport function validateConfig(raw: unknown): TownhouseConfig {\n assertObject(raw, 'config');\n\n // nodes\n assertObject(raw['nodes'], 'config.nodes');\n const nodes = raw['nodes'] as Record<string, unknown>;\n const town = validateNodeConfig(nodes['town'], 'config.nodes.town');\n const mill = validateNodeConfig(nodes['mill'], 'config.nodes.mill');\n const dvm = validateNodeConfig(nodes['dvm'], 'config.nodes.dvm');\n\n // wallet\n assertObject(raw['wallet'], 'config.wallet');\n const wallet = raw['wallet'] as Record<string, unknown>;\n assertString(wallet['encrypted_path'], 'config.wallet.encrypted_path');\n\n // connector\n assertObject(raw['connector'], 'config.connector');\n const connector = raw['connector'] as Record<string, unknown>;\n assertString(connector['image'], 'config.connector.image');\n assertNumber(connector['adminPort'], 'config.connector.adminPort');\n assertPort(connector['adminPort'] as number, 'config.connector.adminPort');\n\n // transport\n assertObject(raw['transport'], 'config.transport');\n const transport = raw['transport'] as Record<string, unknown>;\n assertString(transport['mode'], 'config.transport.mode');\n if (!VALID_TRANSPORT_MODES.has(transport['mode'] as string)) {\n throw new ConfigValidationError(\n `config.transport.mode must be one of: ${[...VALID_TRANSPORT_MODES].join(', ')}`\n );\n }\n if (transport['socksProxy'] !== undefined) {\n assertString(transport['socksProxy'], 'config.transport.socksProxy');\n }\n if (transport['externalUrl'] !== undefined) {\n assertString(transport['externalUrl'], 'config.transport.externalUrl');\n }\n // hiddenService is optional and only meaningful when mode='ator'. We\n // validate the inner shape unconditionally if present (a hiddenService\n // block under mode='direct' is operator confusion, not silent acceptance).\n if (transport['hiddenService'] !== undefined) {\n assertObject(transport['hiddenService'], 'config.transport.hiddenService');\n const hs = transport['hiddenService'] as Record<string, unknown>;\n assertString(hs['dir'], 'config.transport.hiddenService.dir');\n assertNumber(hs['port'], 'config.transport.hiddenService.port');\n assertPort(hs['port'] as number, 'config.transport.hiddenService.port');\n if (hs['externalUrl'] !== undefined) {\n assertString(\n hs['externalUrl'],\n 'config.transport.hiddenService.externalUrl'\n );\n }\n if (hs['startupTimeoutMs'] !== undefined) {\n assertNumber(\n hs['startupTimeoutMs'],\n 'config.transport.hiddenService.startupTimeoutMs'\n );\n }\n if (hs['stopTimeoutMs'] !== undefined) {\n assertNumber(\n hs['stopTimeoutMs'],\n 'config.transport.hiddenService.stopTimeoutMs'\n );\n }\n if (transport['mode'] !== 'ator') {\n throw new ConfigValidationError(\n 'config.transport.hiddenService is only valid when config.transport.mode is \"ator\"'\n );\n }\n }\n // relayHiddenService is the second optional HS — when set, the orchestrator\n // launches a parallel sidecar that forwards inbound .anyone traffic to the\n // town container's port 7100 so external Nostr clients can read the relay\n // without routing through ILP/BTP. Reuses HiddenServiceConfig shape.\n if (transport['relayHiddenService'] !== undefined) {\n assertObject(\n transport['relayHiddenService'],\n 'config.transport.relayHiddenService'\n );\n const hs = transport['relayHiddenService'] as Record<string, unknown>;\n assertString(hs['dir'], 'config.transport.relayHiddenService.dir');\n assertNumber(hs['port'], 'config.transport.relayHiddenService.port');\n assertPort(\n hs['port'] as number,\n 'config.transport.relayHiddenService.port'\n );\n if (hs['externalUrl'] !== undefined) {\n assertString(\n hs['externalUrl'],\n 'config.transport.relayHiddenService.externalUrl'\n );\n }\n if (hs['startupTimeoutMs'] !== undefined) {\n assertNumber(\n hs['startupTimeoutMs'],\n 'config.transport.relayHiddenService.startupTimeoutMs'\n );\n }\n if (hs['stopTimeoutMs'] !== undefined) {\n assertNumber(\n hs['stopTimeoutMs'],\n 'config.transport.relayHiddenService.stopTimeoutMs'\n );\n }\n }\n\n // mode='ator' requires SOMETHING to advertise: either explicit externalUrl\n // OR hiddenService (which makes externalUrl='auto' implicit). Without one\n // of these, the connector's socks5 transport rejects with \"missing\n // required field: transport.externalUrl\" and the connector fails to boot.\n if (\n transport['mode'] === 'ator' &&\n transport['externalUrl'] === undefined &&\n transport['hiddenService'] === undefined\n ) {\n throw new ConfigValidationError(\n 'config.transport.mode=\"ator\" requires either config.transport.externalUrl ' +\n '(operator-managed anon binary) or config.transport.hiddenService ' +\n '(connector-managed anon binary). Without one of these, the underlying ' +\n 'connector will reject the manifest at boot.'\n );\n }\n\n // api\n assertObject(raw['api'], 'config.api');\n const api = raw['api'] as Record<string, unknown>;\n assertNumber(api['port'], 'config.api.port');\n assertPort(api['port'] as number, 'config.api.port');\n assertString(api['host'], 'config.api.host');\n\n // logging\n assertObject(raw['logging'], 'config.logging');\n const logging = raw['logging'] as Record<string, unknown>;\n assertString(logging['level'], 'config.logging.level');\n if (!VALID_LOG_LEVELS.has(logging['level'] as string)) {\n throw new ConfigValidationError(\n `config.logging.level must be one of: ${[...VALID_LOG_LEVELS].join(', ')}`\n );\n }\n\n return {\n nodes: {\n town: {\n enabled: town['enabled'] as boolean,\n ...pickOptional(town, ['feePerEvent', 'image']),\n },\n mill: {\n enabled: mill['enabled'] as boolean,\n ...pickOptional(mill, ['feeBasisPoints', 'image']),\n },\n dvm: {\n enabled: dvm['enabled'] as boolean,\n ...pickOptional(dvm, ['feePerJob', 'kindPricing', 'image']),\n },\n },\n wallet: { encrypted_path: wallet['encrypted_path'] as string },\n connector: {\n image: connector['image'] as string,\n adminPort: connector['adminPort'] as number,\n },\n transport: {\n mode: transport['mode'] as 'ator' | 'direct',\n ...(transport['socksProxy'] !== undefined\n ? { socksProxy: transport['socksProxy'] as string }\n : {}),\n ...(transport['externalUrl'] !== undefined\n ? { externalUrl: transport['externalUrl'] as string }\n : {}),\n ...(transport['hiddenService'] !== undefined\n ? {\n hiddenService: transport['hiddenService'] as {\n dir: string;\n port: number;\n externalUrl?: string;\n startupTimeoutMs?: number;\n stopTimeoutMs?: number;\n },\n }\n : {}),\n ...(transport['relayHiddenService'] !== undefined\n ? {\n relayHiddenService: transport['relayHiddenService'] as {\n dir: string;\n port: number;\n externalUrl?: string;\n startupTimeoutMs?: number;\n stopTimeoutMs?: number;\n },\n }\n : {}),\n },\n api: {\n port: api['port'] as number,\n host: api['host'] as string,\n },\n logging: {\n level: logging['level'] as 'debug' | 'info' | 'warn' | 'error',\n },\n };\n}\n\nfunction pickOptional(\n obj: Record<string, unknown>,\n keys: string[]\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of keys) {\n if (obj[key] !== undefined) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\nexport { ConfigValidationError };\n","/**\n * Config file loader — reads YAML, validates, writes.\n */\n\nimport { readFileSync, writeFileSync, renameSync } from 'node:fs';\nimport { parse, stringify } from 'yaml';\nimport { validateConfig } from './validator.js';\nimport { getDefaultConfig } from './defaults.js';\nimport type { TownhouseConfig } from './schema.js';\n\n/**\n * Load and validate a Townhouse config from a YAML file.\n * Environment variables override YAML values for key settings:\n * - TOWNHOUSE_API_PORT\n * - TOWNHOUSE_TRANSPORT_MODE\n * - TOWNHOUSE_LOG_LEVEL\n */\nexport function loadConfig(configPath: string): TownhouseConfig {\n let rawText: string;\n try {\n rawText = readFileSync(configPath, 'utf-8');\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n throw new Error(`Config file not found: ${configPath}`);\n }\n throw err;\n }\n\n let parsed: unknown;\n try {\n parsed = parse(rawText);\n } catch {\n throw new Error(`Failed to parse YAML config at ${configPath}`);\n }\n\n // An empty YAML file parses to null — treat as empty object so defaults apply\n if (parsed === null || parsed === undefined) {\n parsed = {};\n }\n\n if (typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(\n `Config at ${configPath} must be a YAML mapping (object), not ${Array.isArray(parsed) ? 'an array' : typeof parsed}`\n );\n }\n\n // Deep-merge with defaults so partial configs work\n const defaults = getDefaultConfig();\n const merged = deepMerge(\n defaults as unknown as Record<string, unknown>,\n parsed as Record<string, unknown>\n );\n\n // Apply environment variable overrides\n applyEnvOverrides(merged);\n\n return validateConfig(merged);\n}\n\nfunction applyEnvOverrides(config: Record<string, unknown>): void {\n const env = process.env;\n\n if (env['TOWNHOUSE_API_PORT']) {\n const port = parseInt(env['TOWNHOUSE_API_PORT'], 10);\n if (!Number.isFinite(port) || port < 0 || port > 65535) {\n throw new Error('TOWNHOUSE_API_PORT must be 0..65535');\n }\n const api = config['api'] as Record<string, unknown> | undefined;\n if (api) {\n api['port'] = port;\n }\n }\n\n if (env['TOWNHOUSE_TRANSPORT_MODE']) {\n const mode = env['TOWNHOUSE_TRANSPORT_MODE'];\n if (mode !== 'ator' && mode !== 'direct') {\n throw new Error('TOWNHOUSE_TRANSPORT_MODE must be \"ator\" or \"direct\"');\n }\n const transport = config['transport'] as\n | Record<string, unknown>\n | undefined;\n if (transport) {\n transport['mode'] = mode;\n }\n }\n\n if (env['TOWNHOUSE_LOG_LEVEL']) {\n const level = env['TOWNHOUSE_LOG_LEVEL'];\n if (!['debug', 'info', 'warn', 'error'].includes(level)) {\n throw new Error(\n 'TOWNHOUSE_LOG_LEVEL must be one of: debug, info, warn, error'\n );\n }\n const logging = config['logging'] as Record<string, unknown> | undefined;\n if (logging) {\n logging['level'] = level;\n }\n }\n}\n\n/** Keys that must never be merged — prevents prototype pollution (CWE-1321). */\nconst DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Simple deep merge — target values are overwritten by source values.\n * Arrays are replaced, not concatenated.\n * Skips dangerous keys to prevent prototype pollution from crafted YAML.\n */\nfunction deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n if (DANGEROUS_KEYS.has(key)) {\n continue;\n }\n const sv = source[key];\n const tv = target[key];\n if (\n typeof sv === 'object' &&\n sv !== null &&\n !Array.isArray(sv) &&\n typeof tv === 'object' &&\n tv !== null &&\n !Array.isArray(tv)\n ) {\n result[key] = deepMerge(\n tv as Record<string, unknown>,\n sv as Record<string, unknown>\n );\n } else {\n result[key] = sv;\n }\n }\n return result;\n}\n\n/**\n * Save a config to a YAML file atomically.\n * Writes to a temp file first, then renames to the target (atomic on POSIX).\n */\nexport function saveConfig(configPath: string, config: TownhouseConfig): void {\n // Validate before saving\n const validated = validateConfig(config);\n\n // Serialize to YAML\n const yaml = stringify(validated);\n\n // Write to temp file first\n const tmpPath = configPath + '.tmp';\n writeFileSync(tmpPath, yaml, 'utf-8');\n\n // Atomic rename\n renameSync(tmpPath, configPath);\n}\n","/**\n * Connector Config Generator for Townhouse (Story 21.3).\n *\n * Generates runtime configuration for the standalone ILP connector\n * based on the Townhouse config and currently active nodes.\n */\n\nimport { stringify as yamlStringify } from 'yaml';\n\nimport type { TownhouseConfig } from '../config/schema.js';\nimport type { NodeType } from '../docker/types.js';\nimport { CONTAINER_PREFIX, NODE_BTP_PORT } from '../constants.js';\nimport type { ConnectorRuntimeConfig, PeerEntry } from './types.js';\n\n/** Default ILP address for the Townhouse connector */\nconst DEFAULT_ILP_ADDRESS = 'g.townhouse';\n\n/** Default ATOR SOCKS proxy address */\nexport const DEFAULT_ATOR_PROXY = 'socks5h://proxy.ator.io:9050';\n\n/** Default asset configuration for ILP peers */\nconst DEFAULT_ASSET_CODE = 'USD';\nconst DEFAULT_ASSET_SCALE = 6;\n\n/**\n * ConnectorConfigGenerator produces runtime configuration for the standalone\n * ILP connector based on Townhouse config and active node list.\n *\n * Key design: peer BTP URLs are deterministic Docker DNS names, so nodes\n * don't need to be running for config generation to work.\n */\nexport class ConnectorConfigGenerator {\n private readonly config: TownhouseConfig;\n\n constructor(config: TownhouseConfig) {\n this.config = config;\n }\n\n /**\n * Generate a ConnectorRuntimeConfig for the given set of active nodes.\n *\n * @param activeNodes - Node types currently running or about to start\n * @returns Typed configuration object (not serialized)\n */\n generate(activeNodes: NodeType[]): ConnectorRuntimeConfig {\n const peers = this.generatePeerList(activeNodes);\n const transport = this.generateTransportConfig();\n\n return {\n adminPort: this.config.connector.adminPort,\n ilpAddress: DEFAULT_ILP_ADDRESS,\n peers,\n transport,\n };\n }\n\n /**\n * Serialize a ConnectorRuntimeConfig into environment variable key-value pairs.\n *\n * @returns Record of env var name to string value\n */\n toEnvVars(runtimeConfig: ConnectorRuntimeConfig): Record<string, string> {\n const env: Record<string, string> = {\n CONNECTOR_ADMIN_PORT: String(runtimeConfig.adminPort),\n CONNECTOR_ILP_ADDRESS: runtimeConfig.ilpAddress,\n CONNECTOR_PEERS: JSON.stringify(runtimeConfig.peers),\n TRANSPORT_MODE: runtimeConfig.transport.mode,\n };\n\n if (runtimeConfig.transport.socksProxy) {\n env['SOCKS_PROXY'] = runtimeConfig.transport.socksProxy;\n }\n\n // Hidden-service env vars surface for tooling that wants the .anyone\n // address out-of-band (e.g., `townhouse status` reading the hostname\n // file). The connector itself reads these from the YAML config block\n // produced by toYaml(), not env.\n if (runtimeConfig.transport.hiddenService) {\n env['TRANSPORT_HIDDEN_SERVICE_DIR'] =\n runtimeConfig.transport.hiddenService.dir;\n env['TRANSPORT_HIDDEN_SERVICE_PORT'] = String(\n runtimeConfig.transport.hiddenService.port\n );\n }\n\n return env;\n }\n\n /**\n * Convert a ConnectorRuntimeConfig into the string[] format expected by\n * dockerode's container create API (Env option: ['KEY=VALUE', ...]).\n *\n * @returns Array of 'KEY=VALUE' strings\n */\n toEnvArray(runtimeConfig: ConnectorRuntimeConfig): string[] {\n const envVars = this.toEnvVars(runtimeConfig);\n return Object.entries(envVars).map(([key, value]) => `${key}=${value}`);\n }\n\n /**\n * Render a connector YAML config string the connector image at 3.3.x can\n * load via its `CONFIG_FILE` env var (default `./config.yaml`).\n *\n * The shape mirrors `docker/configs/townhouse-dev-connector.yaml` (the\n * working dev fixture) — peers list is empty because child nodes dial\n * INTO the connector at startup; the connector accepts BTP connections\n * (no-auth in dev) without needing pre-configured peer entries.\n *\n * Added in the orchestrator-bug-fix: env vars set on the container were\n * silently ignored by the connector image, which only reads from this\n * YAML file. Caller writes the returned string to disk and mounts it\n * at `/config/connector.yaml` in the container.\n */\n toYaml(runtimeConfig: ConnectorRuntimeConfig): string {\n // Translate operator-facing `mode: 'ator' | 'direct'` into the\n // connector's internal discriminated union (Epic 35 / Story 35.3):\n // { type: 'direct' }\n // → unchanged direct TCP\n // { type: 'socks5', socksProxy, externalUrl, managed, managedOptions? }\n // → SOCKS5 outbound + (optionally) managed inbound hidden service\n //\n // Historical bug we're fixing here: the previous shape was\n // `{ mode: 'ator', socksProxy }`, which the connector at 3.3.x\n // does NOT recognize. The connector's validateTransport() saw an\n // unknown `mode` field, defaulted `type` to 'direct', and silently\n // discarded socksProxy. Operators toggling mode='ator' got direct\n // traffic anyway. The new shape is what the connector actually reads.\n const transportBlock = this.buildConnectorTransportBlock(\n runtimeConfig.transport\n );\n\n const yamlObj: Record<string, unknown> = {\n nodeId: runtimeConfig.ilpAddress,\n btpServerPort: NODE_BTP_PORT,\n healthCheckPort: 8080,\n environment: 'development',\n deploymentMode: 'standalone',\n logLevel: this.config.logging?.level ?? 'info',\n adminApi: {\n enabled: true,\n port: runtimeConfig.adminPort,\n host: '0.0.0.0',\n // Permissive for the demo loopback environment. Production deployments\n // would lock this to specific operator IPs.\n allowedIPs: ['0.0.0.0/0'],\n },\n transport: transportBlock,\n peers: [],\n routes: [],\n };\n\n return yamlStringify(yamlObj);\n }\n\n // ── Private helpers ──\n\n /**\n * Translate the runtime config's transport block into the discriminated-\n * union shape the connector expects. See toYaml's note for why this was\n * silently broken before.\n */\n private buildConnectorTransportBlock(\n transport: ConnectorRuntimeConfig['transport']\n ): Record<string, unknown> {\n if (transport.mode === 'direct') {\n return { type: 'direct' };\n }\n const block: Record<string, unknown> = {\n type: 'socks5',\n socksProxy: transport.socksProxy ?? DEFAULT_ATOR_PROXY,\n };\n if (transport.hiddenService) {\n // Connector-managed inbound hidden service (Story 35.5). When\n // hiddenService is set, the connector spawns the anon binary itself\n // and resolves externalUrl from `${dir}/hostname` at boot.\n block['externalUrl'] = transport.externalUrl ?? 'auto';\n block['managed'] = true;\n const managedOptions: Record<string, unknown> = {\n hiddenServiceDir: transport.hiddenService.dir,\n hiddenServicePort: transport.hiddenService.port,\n };\n if (transport.hiddenService.startupTimeoutMs !== undefined) {\n managedOptions['startupTimeoutMs'] =\n transport.hiddenService.startupTimeoutMs;\n }\n if (transport.hiddenService.stopTimeoutMs !== undefined) {\n managedOptions['stopTimeoutMs'] = transport.hiddenService.stopTimeoutMs;\n }\n block['managedOptions'] = managedOptions;\n } else {\n // Operator manages anon externally — externalUrl is non-optional in\n // this branch; the validator enforces it upstream, so we trust it.\n // The connector also requires `managed: false` here.\n block['externalUrl'] = transport.externalUrl;\n block['managed'] = false;\n }\n return block;\n }\n\n /**\n * Generate PeerEntry list for each active node type.\n * BTP URLs use Docker DNS: btp+ws://townhouse-{type}:3000 // nosemgrep: javascript.lang.security.detect-insecure-websocket.detect-insecure-websocket\n */\n private generatePeerList(activeNodes: NodeType[]): PeerEntry[] {\n return activeNodes.map((type) => ({\n id: type,\n relation: 'child' as const,\n // nosemgrep: javascript.lang.security.detect-insecure-websocket.detect-insecure-websocket -- Docker-internal BTP URL, TLS unnecessary\n btpUrl: `btp+ws://${CONTAINER_PREFIX}${type}:${NODE_BTP_PORT}`,\n assetCode: DEFAULT_ASSET_CODE,\n assetScale: DEFAULT_ASSET_SCALE,\n }));\n }\n\n /**\n * Generate transport config from Townhouse config.\n * When mode is 'ator', includes SOCKS proxy (uses default if not configured).\n * Carries forward externalUrl + hiddenService when set; downstream\n * buildConnectorTransportBlock handles translation to the connector's\n * wire shape.\n */\n private generateTransportConfig(): ConnectorRuntimeConfig['transport'] {\n if (this.config.transport.mode === 'ator') {\n const transport: ConnectorRuntimeConfig['transport'] = {\n mode: 'ator',\n socksProxy: this.config.transport.socksProxy ?? DEFAULT_ATOR_PROXY,\n };\n if (this.config.transport.externalUrl !== undefined) {\n transport.externalUrl = this.config.transport.externalUrl;\n }\n if (this.config.transport.hiddenService !== undefined) {\n const hs = this.config.transport.hiddenService;\n transport.hiddenService = {\n dir: hs.dir,\n port: hs.port,\n ...(hs.externalUrl !== undefined\n ? { externalUrl: hs.externalUrl }\n : {}),\n ...(hs.startupTimeoutMs !== undefined\n ? { startupTimeoutMs: hs.startupTimeoutMs }\n : {}),\n ...(hs.stopTimeoutMs !== undefined\n ? { stopTimeoutMs: hs.stopTimeoutMs }\n : {}),\n };\n }\n return transport;\n }\n\n return { mode: 'direct' };\n }\n}\n","/**\n * Docker Orchestration Engine for Townhouse (Story 21.2).\n *\n * Manages the full container lifecycle: network creation, image pulling,\n * container creation/start/stop/removal, and health check polling.\n * Uses dockerode for programmatic Docker control with DI for testability.\n */\n\nimport { EventEmitter } from 'node:events';\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type Docker from 'dockerode';\nimport type { TownhouseConfig } from '../config/schema.js';\nimport { ConnectorConfigGenerator } from '../connector/config-generator.js';\nimport {\n CONTAINER_PREFIX,\n TOWN_HEALTH_PORT,\n MILL_HEALTH_PORT,\n DVM_HEALTH_PORT,\n} from '../constants.js';\nimport type { NodeType, HealthCheckOptions, BandwidthStats } from './types.js';\nimport type { WalletManager } from '../wallet/index.js';\n\n/** Nostr relay WebSocket port on Town containers (fixed by Dockerfile) */\nconst TOWN_RELAY_PORT = 7100;\n\n/** Container stats cache TTL in milliseconds */\nconst STATS_CACHE_TTL_MS = 5_000;\n\ninterface CachedStats {\n data: BandwidthStats | null;\n cachedAt: number;\n}\n\n/** Docker bridge network name */\nconst NETWORK_NAME = 'townhouse-net';\n\n/** Default images for node types (used when not overridden in config) */\nconst DEFAULT_NODE_IMAGES: Record<NodeType, string> = {\n town: 'toon:town',\n mill: 'toon:mill',\n dvm: 'toon:dvm',\n};\n\n/** Maximum number of start retries per container */\nconst MAX_START_RETRIES = 3;\n\n/** Internal connector port (Docker-internal, not exposed to host) */\nconst CONNECTOR_INTERNAL_PORT = 3000;\n\n/** Default ator sidecar image tag for relay hidden service publication. */\nconst RELAY_ATOR_SIDECAR_IMAGE = 'toon:townhouse-ator-sidecar';\n\n/**\n * SOCKS port for the relay-side ator sidecar. Distinct from the connector\n * HS sidecar's 9050 so the two can coexist on the same Docker network if\n * both transports are enabled.\n */\nconst RELAY_ATOR_SOCKS_PORT = 9051;\n\n/**\n * Normalize a Docker image reference to include an explicit tag.\n * Docker defaults to `:latest` when no tag is specified, but\n * `listImages()` RepoTags always include the explicit tag.\n * Without normalization, an untagged image like `nginx` would not\n * match `nginx:latest` in the local image cache check.\n */\nfunction normalizeImageTag(image: string): string {\n // If there's already a tag (contains ':' after the last '/'), return as-is.\n // Handle registry prefixes like ghcr.io/org/image:tag\n const lastSlash = image.lastIndexOf('/');\n const nameAndTag = lastSlash >= 0 ? image.slice(lastSlash + 1) : image;\n if (nameAndTag.includes(':')) {\n return image;\n }\n return `${image}:latest`;\n}\n\n/**\n * DockerOrchestrator manages the lifecycle of Townhouse containers.\n *\n * Constructor accepts a dockerode instance (DI for testability) and config.\n * Emits typed events defined in OrchestratorEvents: pullProgress,\n * containerState, and healthCheck.\n */\nexport class DockerOrchestrator extends EventEmitter {\n private readonly docker: Docker;\n private readonly config: TownhouseConfig;\n private readonly configGenerator: ConnectorConfigGenerator;\n private readonly walletManager: WalletManager | undefined;\n private activeNodes: NodeType[] = [];\n private readonly statsCache = new Map<string, CachedStats>();\n\n constructor(\n docker: Docker,\n config: TownhouseConfig,\n walletManager?: WalletManager\n ) {\n super();\n this.docker = docker;\n this.config = config;\n this.configGenerator = new ConnectorConfigGenerator(config);\n this.walletManager = walletManager;\n }\n\n /**\n * Orchestrate full startup sequence:\n * 1. Ensure network exists\n * 2. Pull images (with progress)\n * 3. Start connector, wait for health\n * 4. Start enabled node containers in parallel\n */\n async up(profiles: NodeType[]): Promise<void> {\n this.activeNodes = [...profiles];\n await this.ensureNetwork();\n await this.pullImages(profiles);\n await this.startConnector();\n await this.waitForHealth('townhouse-connector');\n\n // Start all node containers in parallel\n await Promise.all(profiles.map((type) => this.startNode(type)));\n\n // Optional: bring up the relay-side ator sidecar after town is started.\n // It forwards inbound HS traffic to the town container's relay WS port,\n // so it must be created after the town container exists in DNS.\n if (profiles.includes('town') && this.config.transport.relayHiddenService) {\n await this.startRelayAtorSidecar();\n }\n }\n\n /**\n * Regenerate connector config and restart the connector container\n * with updated environment variables (peer list).\n *\n * Sequence: emit connectorRestarting -> stop -> remove -> create -> start -> health -> emit connectorRestarted\n */\n async regenerateConnectorConfig(activeNodes: NodeType[]): Promise<void> {\n this.activeNodes = [...activeNodes];\n\n this.emit('connectorRestarting', { reason: 'peer list updated' });\n\n // Stop and remove existing connector.\n // Use separate try-catch blocks so a failed stop() (e.g. container in\n // Created/exited state) still allows remove() to run and clear the name.\n const connectorName = `${CONTAINER_PREFIX}connector`;\n const existingContainer = this.docker.getContainer(connectorName);\n try {\n await existingContainer.stop({ t: 5 });\n } catch {\n /* not running */\n }\n try {\n await existingContainer.remove();\n } catch {\n /* may not exist */\n }\n\n // Ensure the network exists — regenerate can be called independently of\n // up() (e.g. fee change), so we cannot assume ensureNetwork() already ran.\n await this.ensureNetwork();\n\n // Start new connector with updated config. Always emit connectorRestarted in\n // a finally block so WS clients clear the restarting state even when the\n // connector fails to start (prevents isRestarting stuck indefinitely in UI).\n try {\n await this.startConnector();\n await this.waitForHealth(connectorName);\n } finally {\n this.emit('connectorRestarted', { peers: activeNodes });\n }\n }\n\n /**\n * Hot-add a node after initial startup.\n * Starts the node container, then restarts the connector with updated peer list.\n */\n async addNode(type: NodeType): Promise<void> {\n if (!this.activeNodes.includes(type)) {\n this.activeNodes.push(type);\n }\n\n await this.startNode(type);\n await this.regenerateConnectorConfig(this.activeNodes);\n }\n\n /**\n * Hot-remove a node.\n * Stops the node container, then restarts the connector with updated peer list.\n */\n async removeNode(type: NodeType): Promise<void> {\n this.activeNodes = this.activeNodes.filter((n) => n !== type);\n\n const containerName = `${CONTAINER_PREFIX}${type}`;\n await this.stopAndRemove(containerName);\n await this.regenerateConnectorConfig(this.activeNodes);\n }\n\n /**\n * Graceful shutdown — stops containers in reverse order:\n * 1. Stop all node containers in parallel\n * 2. Stop connector\n * 3. Remove network\n */\n async down(): Promise<void> {\n const containers = await this.docker.listContainers({ all: true });\n\n // Find all townhouse containers\n const nodeContainerNames: string[] = [];\n let connectorName: string | undefined;\n\n for (const info of containers) {\n for (const name of info.Names) {\n const cleanName = name.startsWith('/') ? name.slice(1) : name;\n if (!cleanName.startsWith(CONTAINER_PREFIX)) continue;\n\n if (cleanName === `${CONTAINER_PREFIX}connector`) {\n connectorName = cleanName;\n } else {\n nodeContainerNames.push(cleanName);\n }\n }\n }\n\n // Stop nodes first (parallel)\n await Promise.all(\n nodeContainerNames.map((name) => this.stopAndRemove(name))\n );\n\n // Then stop connector\n if (connectorName) {\n await this.stopAndRemove(connectorName);\n }\n\n // Remove network\n await this.removeNetwork();\n }\n\n /**\n * Resolve the Nostr relay WebSocket URL for a Town node instance.\n *\n * Inspects the container's port bindings to get the host-bound port for\n * the relay WebSocket (7100/tcp). Falls back to the Docker-internal URL\n * when the server is running inside the Docker network or bindings are absent.\n *\n * @param nodeId - The `NodeInfo.id` value (e.g. 'town', 'dev-town-01')\n */\n async getNodeRelayEndpoint(nodeId: string): Promise<string> {\n const containerName = `${CONTAINER_PREFIX}${nodeId}`;\n try {\n const container = this.docker.getContainer(containerName);\n const info = await container.inspect();\n const portBindings = info.HostConfig?.PortBindings as\n | Record<string, { HostIp?: string; HostPort?: string }[] | null>\n | undefined;\n const binding = portBindings?.[`${TOWN_RELAY_PORT}/tcp`]?.[0];\n if (binding?.HostPort) {\n const host =\n binding.HostIp && binding.HostIp !== '0.0.0.0'\n ? binding.HostIp\n : '127.0.0.1';\n // nosemgrep: javascript.lang.security.detect-insecure-websocket -- operator-controlled host, not user input\n return `ws://${host}:${binding.HostPort}`;\n }\n } catch {\n // Container not found or inspect failed — fall through to Docker-internal fallback\n }\n // Docker-internal fallback (server running inside Docker network)\n // nosemgrep: javascript.lang.security.detect-insecure-websocket -- Docker-internal, TLS unnecessary\n return `ws://${containerName}:${TOWN_RELAY_PORT}`;\n }\n\n /**\n * Resolve the BLS health HTTP URL for a node instance.\n *\n * Inspects the container's port bindings to find the host-bound port for the\n * node's health endpoint. Falls back to Docker-internal URL when running\n * inside the Docker network or when bindings are absent.\n *\n * @param nodeId - The `NodeInfo.id` value (e.g. 'mill', 'dev-mill-01')\n * @param type - Node type (determines which internal port to use)\n */\n async getNodeHealthEndpoint(\n nodeId: string,\n type: 'town' | 'mill' | 'dvm'\n ): Promise<string> {\n const port =\n type === 'town'\n ? TOWN_HEALTH_PORT\n : type === 'mill'\n ? MILL_HEALTH_PORT\n : DVM_HEALTH_PORT;\n const containerName = `${CONTAINER_PREFIX}${nodeId}`;\n try {\n const container = this.docker.getContainer(containerName);\n const info = await container.inspect();\n const portBindings = info.HostConfig?.PortBindings as\n | Record<string, { HostIp?: string; HostPort?: string }[] | null>\n | undefined;\n const binding = portBindings?.[`${port}/tcp`]?.[0];\n if (binding?.HostPort) {\n const host =\n binding.HostIp && binding.HostIp !== '0.0.0.0'\n ? binding.HostIp\n : '127.0.0.1';\n return `http://${host}:${binding.HostPort}`;\n }\n } catch {\n // Container not found or inspect failed — fall through to Docker-internal fallback\n }\n return `http://${containerName}:${port}`;\n }\n\n /**\n * Fetch network I/O stats for a container.\n * Results are cached for 5 seconds to avoid per-request Docker API overhead.\n *\n * @param containerName - Full container name (e.g. 'townhouse-town')\n * @returns Bandwidth stats or null when container is not running\n */\n async getContainerStats(\n containerName: string\n ): Promise<BandwidthStats | null> {\n const cached = this.statsCache.get(containerName);\n if (cached && Date.now() - cached.cachedAt < STATS_CACHE_TTL_MS) {\n return cached.data;\n }\n\n try {\n const container = this.docker.getContainer(containerName);\n const stats = (await container.stats({\n stream: false,\n })) as unknown as Record<string, unknown>;\n\n const networks = stats['networks'] as\n | Record<string, { rx_bytes?: number; tx_bytes?: number }>\n | undefined;\n\n if (!networks) {\n const result: BandwidthStats = {\n bytesIn: 0,\n bytesOut: 0,\n sampleAt: Date.now(),\n };\n this.statsCache.set(containerName, {\n data: result,\n cachedAt: Date.now(),\n });\n return result;\n }\n\n let bytesIn = 0;\n let bytesOut = 0;\n for (const iface of Object.values(networks)) {\n bytesIn += iface.rx_bytes ?? 0;\n bytesOut += iface.tx_bytes ?? 0;\n }\n\n const result: BandwidthStats = {\n bytesIn,\n bytesOut,\n sampleAt: Date.now(),\n };\n this.statsCache.set(containerName, {\n data: result,\n cachedAt: Date.now(),\n });\n return result;\n } catch {\n // Container not running or stats unavailable\n this.statsCache.set(containerName, { data: null, cachedAt: Date.now() });\n return null;\n }\n }\n\n /**\n * Return status for all townhouse containers.\n *\n * Discovers both single-instance (townhouse-<type>) and multi-instance\n * (townhouse-<prefix>-<type>-<n>) containers. Multi-instance containers\n * are returned with a `name` matching their instance suffix so callers\n * can build per-instance NodeInfo entries (e.g. \"dev-town-01\").\n */\n async status(): Promise<\n {\n name: string;\n type: 'connector' | 'town' | 'mill' | 'dvm';\n state: string;\n health?: string;\n startedAt?: string;\n }[]\n > {\n const containers = await this.docker.listContainers({ all: true });\n const nodeTypes = ['town', 'mill', 'dvm'] as const;\n const allTypes = ['connector', ...nodeTypes] as const;\n\n // Collect all containers that belong to this townhouse instance\n const matching: {\n containerName: string;\n type: (typeof allTypes)[number];\n info: (typeof containers)[number];\n }[] = [];\n\n for (const c of containers) {\n for (const rawName of c.Names) {\n const name = rawName.startsWith('/') ? rawName.slice(1) : rawName;\n if (!name.startsWith(CONTAINER_PREFIX)) continue;\n const suffix = name.slice(CONTAINER_PREFIX.length); // e.g. \"town\", \"dev-town-01\"\n for (const type of allTypes) {\n if (\n suffix === type ||\n suffix.endsWith(`-${type}`) ||\n suffix.includes(`-${type}-`)\n ) {\n matching.push({ containerName: name, type, info: c });\n break;\n }\n }\n }\n }\n\n const results: {\n name: string;\n type: (typeof allTypes)[number];\n state: string;\n health?: string;\n startedAt?: string;\n }[] = [];\n\n for (const { containerName, type, info } of matching) {\n const suffix = containerName.slice(CONTAINER_PREFIX.length); // e.g. \"town\", \"dev-town-01\"\n let health: string | undefined;\n let startedAt: string | undefined;\n try {\n const container = this.docker.getContainer(containerName);\n const detail = await container.inspect();\n health = detail.State?.Health?.Status ?? undefined;\n startedAt = detail.State?.StartedAt ?? undefined;\n } catch {\n // Inspect may fail if container is being removed — skip health and startedAt\n }\n results.push({\n name: suffix, // \"town\" for single-instance, \"dev-town-01\" for multi\n type,\n state: info.State ?? 'stopped',\n ...(health !== undefined ? { health } : {}),\n ...(startedAt !== undefined ? { startedAt } : {}),\n });\n }\n\n // Ensure every type has at least one entry (stopped placeholder)\n for (const type of allTypes) {\n if (!results.some((r) => r.type === type)) {\n results.push({ name: type, type, state: 'stopped' });\n }\n }\n\n return results;\n }\n\n /**\n * Pull required images before starting containers.\n * Skips images that already exist locally.\n * Emits pullProgress events during download.\n */\n async pullImages(profiles: NodeType[]): Promise<void> {\n const imagesToPull = new Set<string>();\n\n // Always need the connector image\n imagesToPull.add(normalizeImageTag(this.config.connector.image));\n\n // Add node images\n for (const type of profiles) {\n const nodeConfig = this.config.nodes[type];\n const image = nodeConfig.image ?? DEFAULT_NODE_IMAGES[type];\n imagesToPull.add(normalizeImageTag(image));\n }\n\n // Pull the relay ator sidecar when the operator opted in. Built locally\n // by docker/townhouse-ator-sidecar — pull may 404, which is fine; the\n // operator must have built it before `townhouse up` (see README).\n if (profiles.includes('town') && this.config.transport.relayHiddenService) {\n imagesToPull.add(normalizeImageTag(RELAY_ATOR_SIDECAR_IMAGE));\n }\n\n // Check which images exist locally. Match against both RepoTags (tag-form\n // refs) and RepoDigests (digest-form refs); since DEFAULT_CONNECTOR_IMAGE\n // flipped to digest form (Story 45.2), RepoTags alone never matches it\n // and we'd re-pull on every up().\n const existingImages = await this.docker.listImages();\n const existingRefs = new Set<string>();\n for (const img of existingImages) {\n for (const tag of img.RepoTags ?? []) existingRefs.add(tag);\n for (const digest of img.RepoDigests ?? []) existingRefs.add(digest);\n }\n\n // Pull missing images\n for (const image of imagesToPull) {\n if (existingRefs.has(image)) {\n continue;\n }\n\n const stream = await this.docker.pull(image);\n await this.followPullProgress(image, stream);\n }\n }\n\n /**\n * Poll container health status via inspect().\n * Retries at configurable interval, throws on timeout.\n */\n async healthCheck(\n containerName: string,\n options?: HealthCheckOptions\n ): Promise<string> {\n const interval = options?.interval ?? 2000;\n const timeout = options?.timeout ?? 60000;\n const startTime = Date.now();\n let attempt = 0;\n\n while (Date.now() - startTime < timeout) {\n attempt++;\n try {\n const container = this.docker.getContainer(containerName);\n const info = await container.inspect();\n\n const healthStatus = info.State?.Health?.Status ?? 'none';\n\n this.emit('healthCheck', {\n name: containerName,\n status: healthStatus,\n attempt,\n });\n\n if (healthStatus === 'healthy') {\n return 'healthy';\n }\n } catch {\n // Transient inspect failure (Docker daemon hiccup) — retry within timeout\n this.emit('healthCheck', {\n name: containerName,\n status: 'error',\n attempt,\n });\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new Error(\n `Health check timeout: ${containerName} did not become healthy within ${timeout}ms`\n );\n }\n\n // ── Private helpers ──\n\n /**\n * Create the townhouse-net bridge network if it doesn't exist.\n */\n private async ensureNetwork(): Promise<void> {\n try {\n // Docker's name filter does substring matching, so we post-filter\n // with an exact Name comparison to avoid false positives.\n const networks = await this.docker.listNetworks({\n filters: { name: [NETWORK_NAME] },\n });\n\n const exists = networks.some(\n (n: { Name: string }) => n.Name === NETWORK_NAME\n );\n if (exists) return;\n\n await this.docker.createNetwork({\n Name: NETWORK_NAME,\n Driver: 'bridge',\n });\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n if (\n msg.includes('ENOENT') ||\n msg.includes('ECONNREFUSED') ||\n msg.includes('socket')\n ) {\n throw new Error(\n `Docker is not running or not available. Please start Docker and try again. (${msg})`\n );\n }\n throw error;\n }\n }\n\n /**\n * Start the connector container — always runs first.\n *\n * The connector image at 3.3.x reads its config from a YAML file pointed\n * to by the `CONFIG_FILE` env var (default `./config.yaml`). We write the\n * generated YAML to `<configDir>/connector.yaml` (sibling to wallet.enc),\n * mount it as `/config/connector.yaml`, and set CONFIG_FILE accordingly.\n *\n * (Env-var-based config was set on the container historically but the\n * connector image silently ignored them — see the YAML fix landing with\n * this comment block.)\n */\n private async startConnector(): Promise<void> {\n const name = `${CONTAINER_PREFIX}connector`;\n const env = this.buildConnectorEnv();\n env.push('CONFIG_FILE=/config/connector.yaml');\n\n // Write the YAML config beside the wallet so it's stable across restarts.\n const configDir = dirname(this.config.wallet.encrypted_path);\n mkdirSync(configDir, { recursive: true, mode: 0o700 });\n const yamlPath = join(configDir, 'connector.yaml');\n const runtimeConfig = this.configGenerator.generate(this.activeNodes);\n writeFileSync(yamlPath, this.configGenerator.toYaml(runtimeConfig), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n\n this.emit('containerState', { name, state: 'creating' });\n\n const container = await this.docker.createContainer({\n name,\n Image: this.config.connector.image,\n Env: env,\n ExposedPorts: {\n [`${CONNECTOR_INTERNAL_PORT}/tcp`]: {},\n [`${this.config.connector.adminPort}/tcp`]: {},\n },\n HostConfig: {\n NetworkMode: NETWORK_NAME,\n Binds: [`${yamlPath}:/config/connector.yaml:ro`],\n PortBindings: {\n [`${this.config.connector.adminPort}/tcp`]: [\n {\n HostIp: '127.0.0.1',\n HostPort: String(this.config.connector.adminPort),\n },\n ],\n },\n },\n });\n\n this.emit('containerState', { name, state: 'starting' });\n await container.start();\n this.emit('containerState', { name, state: 'running' });\n }\n\n /**\n * Start a node container (town, mill, or dvm).\n * Retries up to MAX_START_RETRIES on failure.\n */\n private async startNode(type: NodeType): Promise<void> {\n const name = `${CONTAINER_PREFIX}${type}`;\n const nodeConfig = this.config.nodes[type];\n const image = nodeConfig.image ?? DEFAULT_NODE_IMAGES[type];\n const env = this.buildNodeEnv(type);\n\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= MAX_START_RETRIES; attempt++) {\n try {\n this.emit('containerState', { name, state: 'creating' });\n\n const container = await this.docker.createContainer({\n name,\n Image: image,\n Env: env,\n HostConfig: {\n NetworkMode: NETWORK_NAME,\n },\n });\n\n this.emit('containerState', { name, state: 'starting' });\n await container.start();\n this.emit('containerState', { name, state: 'running' });\n return;\n } catch (error: unknown) {\n lastError = error instanceof Error ? error : new Error(String(error));\n this.emit('containerState', { name, state: 'error' });\n\n // Clean up failed container before retry\n try {\n const existing = this.docker.getContainer(name);\n await existing.remove({ force: true });\n } catch {\n // Container may not exist, ignore\n }\n }\n }\n\n throw new Error(\n `Failed to start container ${name} after ${MAX_START_RETRIES} restart attempts: ${lastError?.message}`\n );\n }\n\n /**\n * Wait for a container's health check to pass.\n */\n private async waitForHealth(containerName: string): Promise<void> {\n await this.healthCheck(containerName);\n }\n\n /**\n * Start the relay-side ator sidecar that publishes a v3 hidden service\n * forwarding inbound traffic to the town container's Nostr WebSocket port.\n *\n * The keypair directory is mounted read-write because the sidecar's\n * entrypoint writes the `hostname` file on first boot (see\n * docker/townhouse-ator-sidecar/Dockerfile). The town container picks up\n * the resulting .anyone URL via the operator-set externalUrl field.\n */\n private async startRelayAtorSidecar(): Promise<void> {\n const hsConfig = this.config.transport.relayHiddenService;\n if (!hsConfig) return;\n\n const name = `${CONTAINER_PREFIX}ator-sidecar-relay`;\n const env = [\n `HS_TARGET_HOST=${CONTAINER_PREFIX}town`,\n `HS_TARGET_PORT=${TOWN_RELAY_PORT}`,\n `HS_PORT=${hsConfig.port}`,\n `SOCKS_PORT=${RELAY_ATOR_SOCKS_PORT}`,\n ];\n\n this.emit('containerState', { name, state: 'creating' });\n\n const container = await this.docker.createContainer({\n name,\n Image: RELAY_ATOR_SIDECAR_IMAGE,\n Env: env,\n HostConfig: {\n NetworkMode: NETWORK_NAME,\n Binds: [`${hsConfig.dir}:/var/lib/anon/hs:rw`],\n },\n });\n\n this.emit('containerState', { name, state: 'starting' });\n await container.start();\n this.emit('containerState', { name, state: 'running' });\n }\n\n /**\n * Stop and remove a single container.\n */\n private async stopAndRemove(containerName: string): Promise<void> {\n try {\n const container = this.docker.getContainer(containerName);\n this.emit('containerState', { name: containerName, state: 'stopping' });\n await container.stop({ t: 10 });\n await container.remove();\n this.emit('containerState', { name: containerName, state: 'stopped' });\n } catch (error: unknown) {\n // Container may already be stopped/removed — only swallow expected errors\n const msg = error instanceof Error ? error.message : String(error);\n if (\n msg.includes('already stopped') ||\n msg.includes('not running') ||\n msg.includes('No such container') ||\n msg.includes('is not running') ||\n msg.includes('removal')\n ) {\n return;\n }\n // Emit error state with detail but don't throw — best-effort cleanup during shutdown\n this.emit('containerState', {\n name: containerName,\n state: 'error',\n detail: msg,\n });\n }\n }\n\n /**\n * Remove the townhouse-net network if it exists.\n */\n private async removeNetwork(): Promise<void> {\n try {\n const networks = await this.docker.listNetworks({\n filters: { name: [NETWORK_NAME] },\n });\n const netInfo = networks.find(\n (n: { Name: string }) => n.Name === NETWORK_NAME\n );\n if (netInfo) {\n const network = this.docker.getNetwork(netInfo.Id ?? netInfo.Name);\n await network.remove();\n }\n } catch {\n // Network may not exist, ignore\n }\n }\n\n /**\n * Build environment variables for the connector container.\n * Delegates to ConnectorConfigGenerator for consistent config generation.\n */\n private buildConnectorEnv(): string[] {\n const runtimeConfig = this.configGenerator.generate(this.activeNodes);\n return this.configGenerator.toEnvArray(runtimeConfig);\n }\n\n /**\n * Build environment variables for a node container.\n * If a WalletManager is provided, injects per-node identity keys.\n */\n private buildNodeEnv(type: NodeType): string[] {\n // nosemgrep: javascript.lang.security.detect-insecure-websocket.detect-insecure-websocket -- Docker-internal container-to-container URL, TLS unnecessary\n const connectorUrl = `ws://${CONTAINER_PREFIX}connector:${CONNECTOR_INTERNAL_PORT}`;\n const env: string[] = [`CONNECTOR_URL=${connectorUrl}`];\n\n switch (type) {\n case 'town': {\n const feePerEvent = this.config.nodes.town.feePerEvent;\n if (feePerEvent !== undefined) {\n env.push(`FEE_PER_EVENT=${feePerEvent}`);\n }\n // When the operator opts into a relay hidden service, the .anyone URL\n // is advertised via packages/town/src/cli.ts which reads\n // TOON_EXTERNAL_RELAY_URL into config.externalRelayUrl. We deliberately\n // do NOT set config.ator.enabled — that would bind the relay to\n // 127.0.0.1 inside the container, which the sidecar (reaching town via\n // Docker DNS) cannot then forward to.\n const relayHs = this.config.transport.relayHiddenService;\n if (relayHs?.externalUrl) {\n env.push(`TOON_EXTERNAL_RELAY_URL=${relayHs.externalUrl}`);\n }\n break;\n }\n case 'mill': {\n const feeBasisPoints = this.config.nodes.mill.feeBasisPoints;\n if (feeBasisPoints !== undefined) {\n env.push(`FEE_BASIS_POINTS=${feeBasisPoints}`);\n }\n break;\n }\n case 'dvm': {\n const feePerJob = this.config.nodes.dvm.feePerJob;\n if (feePerJob !== undefined) {\n env.push(`FEE_PER_JOB=${feePerJob}`);\n }\n const kindPricing = this.config.nodes.dvm.kindPricing;\n if (kindPricing) {\n for (const [kind, value] of Object.entries(kindPricing)) {\n env.push(`KIND_PRICING_${kind}=${value}`);\n }\n }\n // Arweave DVM (kind:5094) requires TURBO_TOKEN for authenticated\n // uploads. Without it, the entrypoint installs a stub adapter that\n // throws on first upload — dev-mode capped paths don't apply here.\n const turboToken = process.env['TURBO_TOKEN'];\n if (turboToken) {\n env.push(`TURBO_TOKEN=${turboToken}`);\n }\n break;\n }\n }\n\n // Inject wallet-derived identity keys if available\n if (this.walletManager) {\n try {\n const keys = this.walletManager.getNodeKeys(type);\n env.push(`NODE_NOSTR_PUBKEY=${keys.nostrPubkey}`);\n env.push(`NODE_EVM_ADDRESS=${keys.evmAddress}`);\n // Secret key as hex for the container to use for event signing\n const secretHex = Buffer.from(keys.nostrSecretKey).toString('hex');\n env.push(`NODE_NOSTR_SECRET_KEY=${secretHex}`);\n } catch {\n // Wallet not initialized — skip key injection (backward compatible)\n }\n }\n\n return env;\n }\n\n /**\n * Follow a Docker pull stream and emit progress events.\n */\n private async followPullProgress(\n image: string,\n stream: NodeJS.ReadableStream\n ): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.docker.modem.followProgress(\n stream,\n (err: Error | null) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n },\n (event: { status?: string; id?: string; progress?: string }) => {\n this.emit('pullProgress', {\n image,\n status: event.status ?? '',\n id: event.id,\n progress: event.progress,\n });\n }\n );\n });\n }\n}\n","/**\n * Connector Admin Client for Townhouse (Story 21.3, contract aligned in 21.7.5).\n *\n * HTTP client for the connector's admin API endpoints. Paths and response\n * shapes mirror the connector source-of-truth — see\n * `@toon-protocol/connector` `packages/connector/src/http/{types,admin-api}.ts`.\n *\n * Uses Node.js native fetch (available in Node 20+).\n *\n * Two distinct HTTP servers live on the connector image:\n * - healthCheckPort serves /health and /health/{live,ready}\n * - adminApi.port serves /admin/* (peers, metrics.json, routes, channels, …)\n *\n * The base URL passed to this client must point at whichever server hosts\n * the endpoint being called: pass the healthCheckPort base for `getHealth`\n * and the adminApi.port base for `getPeers` / `getMetrics`. In practice\n * Townhouse currently runs both ports on the same host, so callers either\n * construct two clients or hit a shared base URL when the ports overlap.\n */\n\nimport type {\n HealthResponse,\n MetricsResponse,\n PeerStatus,\n PeersResponse,\n PacketLogFilter,\n PacketLogEntry,\n PacketLogResponse,\n} from './types.js';\n\n/** Default request timeout in milliseconds (5 seconds) */\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nexport class ConnectorAdminClient {\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n\n /**\n * @param baseUrl - Base URL for the connector admin API (e.g., 'http://localhost:9402')\n * @param timeoutMs - Request timeout in milliseconds (default: 5000)\n */\n constructor(baseUrl: string, timeoutMs: number = DEFAULT_TIMEOUT_MS) {\n // Strip trailing slash to avoid double-slash in URL construction\n this.baseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n this.timeoutMs = timeoutMs;\n }\n\n /**\n * GET /health — returns the connector's HealthStatus from the healthCheckPort server.\n *\n * @throws Error when connector is not running, returns non-200, or shape is invalid\n */\n async getHealth(): Promise<HealthResponse> {\n const response = await this.fetch('/health');\n const body: unknown = await response.json();\n if (typeof body !== 'object' || body === null) {\n throw new Error('Connector admin API: invalid health response shape');\n }\n const obj = body as Record<string, unknown>;\n const status = obj['status'];\n if (\n status !== 'healthy' &&\n status !== 'unhealthy' &&\n status !== 'starting' &&\n status !== 'degraded'\n ) {\n throw new Error('Connector admin API: invalid health response shape');\n }\n if (\n typeof obj['uptime'] !== 'number' ||\n typeof obj['peersConnected'] !== 'number' ||\n typeof obj['totalPeers'] !== 'number' ||\n typeof obj['timestamp'] !== 'string'\n ) {\n throw new Error('Connector admin API: invalid health response shape');\n }\n return body as HealthResponse;\n }\n\n /**\n * GET /admin/metrics.json — returns the connector's per-peer ILP counters\n * with an aggregate rollup, mirroring `AdminMetricsJsonResponse`.\n *\n * @throws Error when connector is not running, returns non-200, or shape is invalid\n */\n async getMetrics(): Promise<MetricsResponse> {\n const response = await this.fetch('/admin/metrics.json');\n const body: unknown = await response.json();\n if (typeof body !== 'object' || body === null) {\n throw new Error('Connector admin API: invalid metrics response shape');\n }\n const obj = body as Record<string, unknown>;\n const aggregate = obj['aggregate'];\n if (\n typeof obj['uptimeSeconds'] !== 'number' ||\n typeof aggregate !== 'object' ||\n aggregate === null ||\n !Array.isArray(obj['peers']) ||\n typeof obj['timestamp'] !== 'string'\n ) {\n throw new Error('Connector admin API: invalid metrics response shape');\n }\n const agg = aggregate as Record<string, unknown>;\n if (\n typeof agg['packetsForwarded'] !== 'number' ||\n typeof agg['packetsRejected'] !== 'number' ||\n typeof agg['bytesSent'] !== 'number'\n ) {\n throw new Error('Connector admin API: invalid metrics response shape');\n }\n return body as MetricsResponse;\n }\n\n /**\n * GET /admin/peers — returns the connector's peer roster with route counts\n * and ILP addresses. Returns the unwrapped peers array (the wrapper's\n * nodeId / peerCount / connectedCount fields are dropped).\n *\n * @throws Error when connector is not running, returns non-200, or shape is invalid\n */\n async getPeers(): Promise<PeerStatus[]> {\n const response = await this.fetch('/admin/peers');\n const body: unknown = await response.json();\n if (typeof body !== 'object' || body === null) {\n throw new Error('Connector admin API: invalid peers response shape');\n }\n const obj = body as Record<string, unknown>;\n if (!Array.isArray(obj['peers'])) {\n throw new Error('Connector admin API: invalid peers response shape');\n }\n return (body as PeersResponse).peers;\n }\n\n /**\n * GET /packets — returns the connector's raw packet log filtered by the\n * given criteria. Used by the timeseries aggregation route (story 21.10).\n *\n * Townhouse-Side Contract: see packages/sdk/CONNECTOR_MIGRATION.md §getPacketLog.\n * If the connector image does not expose GET /packets, this method throws\n * with a `ConnectorEndpointNotFound` error code so the route can return 503.\n *\n * @throws Error with code='ConnectorEndpointNotFound' when connector returns 404\n * @throws Error when connector is not running, returns non-200, or shape is invalid\n */\n async getPacketLog(filter: PacketLogFilter = {}): Promise<PacketLogEntry[]> {\n const params = new URLSearchParams();\n if (filter.ilpAddress !== undefined)\n params.set('ilpAddress', filter.ilpAddress);\n if (filter.since !== undefined) params.set('since', String(filter.since));\n if (filter.limit !== undefined) params.set('limit', String(filter.limit));\n const path = params.toString()\n ? `/packets?${params.toString()}`\n : '/packets';\n\n let response: Response;\n try {\n response = await this.fetch(path);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes('404')) {\n const err = new Error(\n 'Connector does not expose GET /packets — endpoint not found'\n );\n (err as NodeJS.ErrnoException).code = 'ConnectorEndpointNotFound';\n throw err;\n }\n throw error;\n }\n\n const body: unknown = await response.json();\n if (!Array.isArray(body)) {\n throw new Error(\n 'Connector admin API: invalid packet log response shape — expected array'\n );\n }\n return body as PacketLogResponse;\n }\n\n // ── Private helpers ──\n\n /**\n * Perform an HTTP GET request to the connector admin API.\n * Wraps fetch with error handling for connection refused and non-200 responses.\n */\n private async fetch(path: string): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n let response: Response;\n try {\n response = await fetch(url, { signal: controller.signal });\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(\n `Connector admin API request timeout after ${this.timeoutMs}ms: ${url}`\n );\n }\n const msg = error instanceof Error ? error.message : String(error);\n throw new Error(`Connector admin API connection refused: ${msg}`);\n }\n\n if (!response.ok) {\n throw new Error(\n `Connector admin API error: ${response.status} ${response.statusText}`\n );\n }\n\n return response;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","/**\n * ATOR transport probe — periodically TCP-connects to the configured SOCKS5\n * proxy host:port and measures direct HTTPS latency for comparison.\n *\n * The probe answers a single operator question: \"is my configured ATOR proxy\n * contactable from this host?\" TCP connect is the right granularity — if the\n * TCP listener is up, the connector's real BTP traffic will succeed.\n *\n * The probe NEVER makes a real SOCKS5 handshake or proxied request — only a\n * plain TCP connect to the proxy host:port.\n */\n\nimport * as net from 'node:net';\nimport * as https from 'node:https';\nimport * as http from 'node:http';\n\nconst DEFAULT_INTERVAL_MS = 30_000;\nconst MIN_INTERVAL_MS = 1_000;\nconst PROBE_TIMEOUT_MS = 3_000;\nconst DEFAULT_DIRECT_PROBE_URL = 'https://1.1.1.1/';\n\nexport interface TransportProbeOptions {\n proxyUrl: string;\n intervalMs?: number;\n /** Override the direct-latency probe URL (for tests — avoids real network). */\n directProbeUrl?: string;\n}\n\nexport interface TransportProbeStatus {\n reachable: boolean;\n latencyProxyMs: number | null;\n latencyDirectMs: number | null;\n lastProbedAt: number;\n probeError: string | null;\n}\n\nexport class TransportProbe {\n private proxyUrl: string;\n private readonly intervalMs: number;\n private readonly directProbeUrl: string;\n\n private running = false;\n private timer: ReturnType<typeof setInterval> | null = null;\n\n private status: TransportProbeStatus = {\n reachable: true,\n latencyProxyMs: null,\n latencyDirectMs: null,\n lastProbedAt: 0,\n probeError: null,\n };\n\n constructor(opts: TransportProbeOptions) {\n this.proxyUrl = opts.proxyUrl;\n this.intervalMs = Math.max(\n MIN_INTERVAL_MS,\n opts.intervalMs ?? DEFAULT_INTERVAL_MS\n );\n this.directProbeUrl = opts.directProbeUrl ?? DEFAULT_DIRECT_PROBE_URL;\n }\n\n /** Start the probe loop. Idempotent — calling twice while running is a no-op. */\n start(): void {\n if (this.running) return;\n this.running = true;\n const tick = (): void => {\n void this.tick().catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[TransportProbe] tick failed: ${msg}`);\n });\n };\n // Run immediately on start, then on interval\n tick();\n this.timer = setInterval(tick, this.intervalMs);\n }\n\n /** Stop the probe loop. Idempotent. */\n stop(): void {\n this.running = false;\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n\n /** Returns the latest probe snapshot synchronously. Never blocks. */\n getStatus(): TransportProbeStatus {\n return { ...this.status };\n }\n\n /**\n * Update the target proxy URL.\n * The next tick will use the new URL; the current tick may complete against the old URL.\n */\n setProxyUrl(url: string): void {\n this.proxyUrl = url;\n }\n\n // ── Private probe logic ──────────────────────────────────────────────────\n\n private async tick(): Promise<void> {\n if (!this.running) return;\n\n const directMs = await this.probeDirectLatency();\n if (!this.running) return;\n\n if (!this.proxyUrl) {\n // Direct-mode: no proxy to probe\n const prev = this.status;\n this.status = {\n reachable: true,\n latencyProxyMs: null,\n latencyDirectMs: directMs,\n lastProbedAt: Date.now(),\n probeError: null,\n };\n this.logTransition(prev, this.status);\n return;\n }\n\n let host: string;\n let port: number;\n let hostPort: string;\n try {\n const parsed = new URL(this.proxyUrl);\n host = parsed.hostname;\n const rawPort = Number(parsed.port);\n if (\n !parsed.port ||\n !Number.isInteger(rawPort) ||\n rawPort < 1 ||\n rawPort > 65535\n ) {\n throw new Error('missing or invalid port');\n }\n port = rawPort;\n hostPort = `${host}:${port}`;\n } catch {\n const prev = this.status;\n this.status = {\n reachable: false,\n latencyProxyMs: null,\n latencyDirectMs: directMs,\n lastProbedAt: Date.now(),\n probeError: 'invalid_proxy_url',\n };\n this.logTransition(prev, this.status);\n return;\n }\n\n const { reachable, latencyMs, error } = await this.probeTcp(host, port);\n if (!this.running) return;\n const prev = this.status;\n this.status = {\n reachable,\n latencyProxyMs: latencyMs,\n latencyDirectMs: directMs,\n lastProbedAt: Date.now(),\n probeError: error ?? null,\n };\n this.logTransition(prev, this.status, hostPort);\n }\n\n private probeTcp(\n host: string,\n port: number\n ): Promise<{ reachable: boolean; latencyMs: number | null; error?: string }> {\n return new Promise((resolve) => {\n const start = Date.now();\n const socket = net.createConnection({ host, port });\n let settled = false;\n\n const settle = (result: {\n reachable: boolean;\n latencyMs: number | null;\n error?: string;\n }) => {\n if (settled) return;\n settled = true;\n try {\n socket.destroy();\n } catch {\n /* best-effort */\n }\n resolve(result);\n };\n\n const timeout = setTimeout(() => {\n settle({ reachable: false, latencyMs: null, error: 'timeout' });\n }, PROBE_TIMEOUT_MS);\n\n socket.once('connect', () => {\n clearTimeout(timeout);\n settle({ reachable: true, latencyMs: Date.now() - start });\n });\n\n socket.once('error', (err: NodeJS.ErrnoException) => {\n clearTimeout(timeout);\n settle({\n reachable: false,\n latencyMs: null,\n error: err.code ?? err.message,\n });\n });\n });\n }\n\n private probeDirectLatency(): Promise<number | null> {\n return new Promise((resolve) => {\n const start = Date.now();\n let settled = false;\n\n const settle = (ms: number | null) => {\n if (settled) return;\n settled = true;\n resolve(ms);\n };\n\n // Support both http:// (tests) and https:// (production)\n const isHttps = this.directProbeUrl.startsWith('https://');\n const requester = isHttps ? https : http;\n\n let req: http.ClientRequest | undefined;\n const timeout = setTimeout(() => {\n try {\n req?.destroy();\n } catch {\n /* best-effort */\n }\n settle(null);\n }, PROBE_TIMEOUT_MS);\n\n try {\n req = requester.request(\n this.directProbeUrl,\n { method: 'HEAD' },\n (res) => {\n clearTimeout(timeout);\n res.resume();\n settle(Date.now() - start);\n }\n );\n\n req.once('error', (err: NodeJS.ErrnoException) => {\n clearTimeout(timeout);\n console.debug(\n `[TransportProbe] direct latency probe failed: ${err.code ?? err.message}`\n );\n settle(null);\n });\n\n req.end();\n } catch (err) {\n clearTimeout(timeout);\n const msg = err instanceof Error ? err.message : String(err);\n console.debug(`[TransportProbe] direct latency probe threw: ${msg}`);\n settle(null);\n }\n });\n }\n\n private logTransition(\n prev: TransportProbeStatus,\n next: TransportProbeStatus,\n hostPort?: string\n ): void {\n // Suppress reachable→unreachable transition log on the very first probe;\n // the default initial state is reachable=true even before any probe ran.\n if (prev.lastProbedAt === 0) return;\n\n const target = hostPort ? ` (${hostPort})` : '';\n if (prev.reachable && !next.reachable) {\n console.warn(\n `[TransportProbe] proxy became unreachable${target}: ${next.probeError ?? 'unknown'}`\n );\n } else if (!prev.reachable && next.reachable) {\n console.debug(`[TransportProbe] proxy reachable${target}`);\n }\n // No per-tick info logs for the proxy host (see AC-22)\n }\n}\n","/**\n * Wallet file I/O for Townhouse (Story 21.4, Task 2.2).\n *\n * Persists encrypted wallet to disk with 0o600 permissions (owner-only).\n * Warns if existing file has world-readable permissions.\n */\n\nimport { writeFile, readFile, mkdir, stat } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { EncryptedWallet } from './types.js';\n\n/**\n * Save encrypted wallet to disk with restrictive permissions.\n * Creates parent directory if missing.\n */\nexport async function saveWallet(\n path: string,\n encrypted: EncryptedWallet\n): Promise<void> {\n const dir = dirname(path);\n await mkdir(dir, { recursive: true, mode: 0o700 });\n\n const data = JSON.stringify(encrypted, null, 2);\n await writeFile(path, data, { encoding: 'utf-8', mode: 0o600 });\n}\n\n/**\n * Load encrypted wallet from disk.\n * Returns null if file does not exist.\n * Warns (via returned flag) if file permissions are too open.\n */\nexport async function loadWallet(\n path: string\n): Promise<{ wallet: EncryptedWallet; permissionsWarning?: string } | null> {\n let data: string;\n try {\n data = await readFile(path, 'utf-8');\n } catch (err: unknown) {\n if (\n err instanceof Error &&\n 'code' in err &&\n (err as NodeJS.ErrnoException).code === 'ENOENT'\n ) {\n return null;\n }\n throw err;\n }\n\n // Check permissions\n let permissionsWarning: string | undefined;\n try {\n const stats = await stat(path);\n const mode = stats.mode & 0o777;\n if (mode & 0o077) {\n permissionsWarning = `Warning: wallet file ${path} has permissions ${mode.toString(8)} (should be 600)`;\n }\n } catch {\n // stat failure is non-fatal — skip permissions check\n }\n\n const wallet = JSON.parse(data) as EncryptedWallet;\n return { wallet, permissionsWarning };\n}\n","/**\n * Wallet encryption/decryption for Townhouse (Story 21.4, Task 2).\n *\n * Uses Node.js crypto: scrypt for KDF, AES-256-GCM for authenticated encryption.\n * The mnemonic is the plaintext being encrypted.\n */\n\nimport {\n scryptSync,\n createCipheriv,\n createDecipheriv,\n randomBytes,\n} from 'node:crypto';\nimport type { EncryptedWallet } from './types.js';\n\n/** scrypt parameters — N=2^17 (~0.5-1s on modern hardware), r=8, p=1 */\nconst SCRYPT_N = 2 ** 17;\nconst SCRYPT_R = 8;\nconst SCRYPT_P = 1;\nconst SCRYPT_KEY_LEN = 32;\n/** maxmem for scrypt: N * r * 128 * 2 (with headroom for Node.js overhead) */\nconst SCRYPT_MAXMEM = SCRYPT_N * SCRYPT_R * 256 + 32 * 1024 * 1024;\n\n/** Salt length in bytes */\nconst SALT_LEN = 32;\n\n/** AES-GCM IV length in bytes */\nconst IV_LEN = 12;\n\n/** AES-GCM authentication tag length in bytes (128-bit) */\nconst AUTH_TAG_LEN = 16;\n\n/**\n * Encrypt a mnemonic with a password using scrypt + AES-256-GCM.\n */\nexport function encryptWallet(\n mnemonic: string,\n password: string\n): EncryptedWallet {\n const salt = randomBytes(SALT_LEN);\n const iv = randomBytes(IV_LEN);\n\n const key = scryptSync(password, salt, SCRYPT_KEY_LEN, {\n N: SCRYPT_N,\n r: SCRYPT_R,\n p: SCRYPT_P,\n maxmem: SCRYPT_MAXMEM,\n });\n\n try {\n const cipher = createCipheriv('aes-256-gcm', key, iv, {\n authTagLength: AUTH_TAG_LEN,\n });\n const ciphertext = Buffer.concat([\n cipher.update(mnemonic, 'utf8'),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n\n return {\n salt: salt.toString('base64'),\n iv: iv.toString('base64'),\n ciphertext: ciphertext.toString('base64'),\n tag: tag.toString('base64'),\n };\n } finally {\n key.fill(0);\n }\n}\n\n/**\n * Decrypt an encrypted wallet with a password.\n * Throws on wrong password (GCM auth tag verification failure).\n */\nexport function decryptWallet(\n encrypted: EncryptedWallet,\n password: string\n): string {\n const salt = Buffer.from(encrypted.salt, 'base64');\n const iv = Buffer.from(encrypted.iv, 'base64');\n const ciphertext = Buffer.from(encrypted.ciphertext, 'base64');\n const tag = Buffer.from(encrypted.tag, 'base64');\n\n const key = scryptSync(password, salt, SCRYPT_KEY_LEN, {\n N: SCRYPT_N,\n r: SCRYPT_R,\n p: SCRYPT_P,\n maxmem: SCRYPT_MAXMEM,\n });\n\n try {\n const decipher = createDecipheriv('aes-256-gcm', key, iv, {\n authTagLength: AUTH_TAG_LEN,\n });\n decipher.setAuthTag(tag);\n\n try {\n const plaintext = Buffer.concat([\n decipher.update(ciphertext),\n decipher.final(),\n ]);\n return plaintext.toString('utf8');\n } catch {\n throw new Error(\n 'Decryption failed: wrong password or corrupted wallet file'\n );\n }\n } finally {\n key.fill(0);\n }\n}\n","/**\n * WalletManager — HD key derivation for Townhouse (Story 21.4, Task 1).\n *\n * Single BIP-39 mnemonic, deterministic HD derivation per node type.\n * Uses BIP-44 paths with distinct account indices per node type:\n * - Town: account 0\n * - Mill: account 1\n * - DVM: account 2\n *\n * Nostr keys use NIP-06 coin type 1237: m/44'/1237'/{account}'/0/0\n * EVM keys use standard coin type 60: m/44'/60'/{account}'/0/0\n */\n\nimport {\n generateMnemonic,\n validateMnemonic,\n mnemonicToSeedSync,\n} from '@scure/bip39';\nimport { wordlist } from '@scure/bip39/wordlists/english.js';\nimport { HDKey } from '@scure/bip32';\nimport { getPublicKey } from 'nostr-tools/pure';\nimport { bytesToHex } from '@noble/hashes/utils';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { secp256k1 } from '@noble/curves/secp256k1';\n\nimport type { NodeType } from '../docker/types.js';\nimport {\n ACCOUNT_INDEX_TOWN,\n ACCOUNT_INDEX_MILL,\n ACCOUNT_INDEX_DVM,\n} from '../constants.js';\nimport type {\n WalletManagerConfig,\n WalletState,\n NodeKeys,\n DerivedNodeKeys,\n NodeKeyInfo,\n} from './types.js';\nimport { deriveMillKeys } from '@toon-protocol/mill';\n\nconst BASE58_ALPHABET =\n '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\nfunction base58Encode(bytes: Uint8Array): string {\n let zeros = 0;\n for (let i = 0; i < bytes.length && bytes[i] === 0; i++) zeros++;\n let value = 0n;\n for (const byte of bytes) value = value * 256n + BigInt(byte);\n let result = '';\n while (value > 0n) {\n result = BASE58_ALPHABET[Number(value % 58n)] + result;\n value = value / 58n;\n }\n for (let i = 0; i < zeros; i++) result = '1' + result;\n return result || '1';\n}\n\n/** Map node type to account index */\nconst NODE_ACCOUNT_INDEX: Record<NodeType, number> = {\n town: ACCOUNT_INDEX_TOWN,\n mill: ACCOUNT_INDEX_MILL,\n dvm: ACCOUNT_INDEX_DVM,\n};\n\n/**\n * WalletManager handles mnemonic generation, key derivation, and in-memory\n * key lifecycle for Townhouse node operations.\n */\nexport class WalletManager {\n private readonly config: WalletManagerConfig;\n private state: WalletState | null = null;\n\n constructor(config: WalletManagerConfig) {\n this.config = config;\n }\n\n /** Path to the encrypted wallet file */\n get encryptedPath(): string {\n return this.config.encryptedPath;\n }\n\n /**\n * Generate a new 12-word BIP-39 mnemonic and derive all node keys.\n * Returns the mnemonic (for one-time display) and the derived state.\n */\n async generate(): Promise<{ mnemonic: string; state: WalletState }> {\n const mnemonic = generateMnemonic(wordlist, 128); // 128 bits = 12 words\n const state = await this.deriveAllKeys(mnemonic);\n this.state = state;\n return { mnemonic, state };\n }\n\n /**\n * Import an existing mnemonic (12 or 24 words) and derive all node keys.\n * Throws if mnemonic is invalid (wrong checksum, wrong word count, etc).\n */\n async fromMnemonic(mnemonic: string): Promise<WalletState> {\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\n 'Invalid BIP-39 mnemonic: checksum or word list validation failed'\n );\n }\n const state = await this.deriveAllKeys(mnemonic);\n this.state = state;\n return state;\n }\n\n /**\n * Get derived keys for a specific node type.\n * Throws if wallet has not been initialized (call generate() or fromMnemonic() first).\n */\n getNodeKeys(nodeType: NodeType): NodeKeys {\n if (!this.state) {\n throw new Error(\n 'Wallet not initialized. Call generate() or fromMnemonic() first.'\n );\n }\n return this.state.keys[nodeType];\n }\n\n /**\n * Get display-safe info for all node types (no secrets).\n */\n getAllKeys(): NodeKeyInfo[] {\n if (!this.state) {\n throw new Error(\n 'Wallet not initialized. Call generate() or fromMnemonic() first.'\n );\n }\n\n const state = this.state;\n const types: NodeType[] = ['town', 'mill', 'dvm'];\n return types.map((nodeType) => {\n const keys = state.keys[nodeType];\n const info: NodeKeyInfo = {\n nodeType,\n nostrPubkey: keys.nostrPubkey,\n evmAddress: keys.evmAddress,\n nostrDerivationPath: keys.nostrDerivationPath,\n evmDerivationPath: keys.evmDerivationPath,\n };\n if (nodeType === 'mill') {\n if (keys.solanaAddress) info.solanaAddress = keys.solanaAddress;\n if (keys.minaAddress) info.minaAddress = keys.minaAddress;\n }\n return info;\n });\n }\n\n /**\n * List keys for all node types (alias for getAllKeys for API compatibility).\n */\n listKeys(): NodeKeyInfo[] {\n return this.getAllKeys();\n }\n\n /**\n * Zero all in-memory key material. After calling lock(),\n * getNodeKeys() and getAllKeys() will throw.\n */\n lock(): void {\n if (!this.state) return;\n\n const types: NodeType[] = ['town', 'mill', 'dvm'];\n for (const nodeType of types) {\n const keys = this.state.keys[nodeType];\n keys.nostrSecretKey.fill(0);\n keys.evmPrivateKey.fill(0);\n }\n this.state = null;\n }\n\n /**\n * Derive keys for all node types from a mnemonic.\n */\n private async deriveAllKeys(mnemonic: string): Promise<WalletState> {\n let seed: Uint8Array | undefined;\n try {\n seed = mnemonicToSeedSync(mnemonic);\n const millBaseKeys = this.deriveNodeKeys(seed, 'mill');\n\n // Derive Solana and Mina addresses for the mill node using the same\n // account index as the WalletManager (ACCOUNT_INDEX_MILL = 1). These\n // public addresses are exposed by GET /nodes/mill/deposit-addresses.\n let solanaAddress: string | undefined;\n let minaAddress: string | undefined;\n try {\n const millChainKeys = await deriveMillKeys({\n mnemonic,\n chains: ['solana', 'mina'],\n accountIndex: ACCOUNT_INDEX_MILL,\n });\n if (millChainKeys.solana) {\n solanaAddress = base58Encode(millChainKeys.solana.publicKey);\n }\n if (millChainKeys.mina) {\n minaAddress = millChainKeys.mina.publicKey;\n }\n } catch {\n // deriveMillKeys failure (e.g., unsupported platform) should not\n // prevent wallet init — addresses are optional at derivation time.\n }\n\n const keys: DerivedNodeKeys = {\n town: this.deriveNodeKeys(seed, 'town'),\n mill: { ...millBaseKeys, solanaAddress, minaAddress },\n dvm: this.deriveNodeKeys(seed, 'dvm'),\n };\n return { keys };\n } finally {\n if (seed) seed.fill(0);\n }\n }\n\n /**\n * Derive Nostr + EVM keys for a specific node type.\n */\n private deriveNodeKeys(seed: Uint8Array, nodeType: NodeType): NodeKeys {\n const accountIndex = NODE_ACCOUNT_INDEX[nodeType];\n\n // Nostr key: NIP-06 path m/44'/1237'/{account}'/0/0\n const nostrPath = `m/44'/1237'/${accountIndex}'/0/0`;\n const nostrHdKey = HDKey.fromMasterSeed(seed).derive(nostrPath);\n if (!nostrHdKey.privateKey) {\n throw new Error(`Nostr private key missing at ${nostrPath}`);\n }\n const nostrSecretKey = new Uint8Array(nostrHdKey.privateKey);\n const nostrPubkey = getPublicKey(nostrSecretKey);\n\n // EVM key: standard path m/44'/60'/{account}'/0/0\n const evmPath = `m/44'/60'/${accountIndex}'/0/0`;\n const evmHdKey = HDKey.fromMasterSeed(seed).derive(evmPath);\n if (!evmHdKey.privateKey) {\n throw new Error(`EVM private key missing at ${evmPath}`);\n }\n const evmPrivateKey = new Uint8Array(evmHdKey.privateKey);\n const evmAddress = computeEvmAddress(evmPrivateKey);\n\n return {\n nostrPubkey,\n nostrSecretKey,\n evmAddress,\n evmPrivateKey,\n nostrDerivationPath: nostrPath,\n evmDerivationPath: evmPath,\n };\n }\n}\n\n/**\n * Compute EVM address from private key: uncompressed pubkey -> keccak256 -> last 20 bytes.\n */\nfunction computeEvmAddress(privateKey: Uint8Array): string {\n const uncompressed = secp256k1.getPublicKey(privateKey, false);\n const hash = keccak_256(uncompressed.slice(1));\n const addressHex = bytesToHex(hash.slice(-20));\n return toChecksumAddress(addressHex);\n}\n\n/**\n * EIP-55 checksum address encoding.\n */\nfunction toChecksumAddress(addressHex: string): string {\n const lower = addressHex.toLowerCase();\n const hashHex = bytesToHex(keccak_256(new TextEncoder().encode(lower)));\n let out = '0x';\n for (let i = 0; i < 40; i++) {\n const ch = lower.charAt(i);\n const hashNibble = parseInt(hashHex.charAt(i), 16);\n out += hashNibble >= 8 ? ch.toUpperCase() : ch;\n }\n return out;\n}\n","import createWebSocketStream from './lib/stream.js';\nimport Receiver from './lib/receiver.js';\nimport Sender from './lib/sender.js';\nimport WebSocket from './lib/websocket.js';\nimport WebSocketServer from './lib/websocket-server.js';\n\nexport { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer };\nexport default WebSocket;\n","/**\n * Shared Fastify instance builder — loopback validation + CORS + WebSocket + error handler.\n * Consumed by both createApiServer and createWizardApiServer.\n */\n\nimport Fastify, {\n type FastifyInstance,\n type FastifyServerOptions,\n type FastifyBaseLogger,\n} from 'fastify';\nimport cors from '@fastify/cors';\nimport websocket from '@fastify/websocket';\nimport { buildCorsOptions } from './cors.js';\n\n/** Allowed loopback hosts */\nexport const LOOPBACK_HOSTS = ['127.0.0.1', '::1', 'localhost'];\n\nexport interface FastifyBuildOptions {\n logger?: FastifyBaseLogger | boolean;\n /** Validated bind host — must be a loopback address in wizard mode */\n bindHost?: string;\n /** When true, throws if bindHost is non-loopback regardless of env var */\n requireLoopback?: boolean;\n}\n\n/**\n * Build a Fastify instance with shared middleware: CORS, WebSocket, and error handler.\n * Does NOT register any routes.\n *\n * SECURITY: Pino logger is configured with `redact` paths covering wizard-mode\n * secrets (mnemonic, password, password_confirm) so request-shape logging cannot\n * leak credentials even if the log level is bumped.\n */\nexport async function buildFastifyApp(\n opts: FastifyBuildOptions = {}\n): Promise<FastifyInstance> {\n const bindHost = opts.bindHost ?? '127.0.0.1';\n\n if (!LOOPBACK_HOSTS.includes(bindHost)) {\n if (opts.requireLoopback) {\n throw new Error(\n 'The wizard refuses remote bind for security. Edit ~/.townhouse/config.yaml after setup if you need remote API access.'\n );\n }\n if (process.env['TOWNHOUSE_API_ALLOW_REMOTE'] !== '1') {\n throw new Error(\n 'Townhouse API refuses to bind to non-loopback host without TOWNHOUSE_API_ALLOW_REMOTE=1'\n );\n }\n }\n\n // Build logger options. When the caller passes a boolean (the common path) we\n // attach Pino redact paths. A custom FastifyBaseLogger instance is opaque so\n // we trust the caller has already configured redaction.\n const loggerOpt = opts.logger ?? true;\n const logger: FastifyServerOptions['logger'] =\n typeof loggerOpt === 'boolean' && loggerOpt\n ? {\n redact: {\n paths: [\n 'req.body.mnemonic',\n 'req.body.password',\n 'req.body.password_confirm',\n 'res.body.mnemonic',\n 'mnemonic',\n 'password',\n 'password_confirm',\n ],\n censor: '[REDACTED]',\n },\n }\n : (loggerOpt as FastifyServerOptions['logger']);\n\n const app = Fastify({\n logger,\n bodyLimit: 16 * 1024,\n // SECURITY/CONTRACT: schemas with `additionalProperties: false` must REJECT\n // unknown keys with a 400, not silently strip them. Operators shipping a typo\n // should see a loud failure, not a no-op success.\n ajv: {\n customOptions: {\n removeAdditional: false,\n },\n },\n } as FastifyServerOptions);\n\n app.setErrorHandler((error, _request, reply) => {\n app.log.error(error);\n const err = error as {\n statusCode?: number;\n code?: string;\n message?: string;\n validation?: unknown;\n };\n const isCorsRejection = err.message === 'Origin not allowed';\n const statusCode = isCorsRejection ? 403 : (err.statusCode ?? 500);\n\n // SECURITY: 5xx responses always sanitized — err.message can carry payload\n // bits (validation context, file paths, partial inputs) and must not reach\n // the client. Only known-safe error classes (CORS rejection, Fastify\n // validation 4xx) get the original message.\n let message: string;\n if (isCorsRejection) {\n message = err.message ?? 'Origin not allowed';\n } else if (statusCode >= 400 && statusCode < 500 && err.validation) {\n message = err.message ?? 'Bad request';\n } else if (statusCode >= 400 && statusCode < 500) {\n message = err.message ?? 'Bad request';\n } else {\n message = 'Internal server error';\n }\n\n reply.status(statusCode).send({\n error: isCorsRejection\n ? 'origin_not_allowed'\n : (err.code ?? 'internal_error'),\n message,\n });\n });\n\n await app.register(cors, buildCorsOptions());\n await app.register(websocket);\n\n return app;\n}\n","/**\n * CORS configuration for Townhouse API.\n *\n * SECURITY: Only allows localhost origins (loopback only for v1).\n */\n\nimport type { FastifyCorsOptions } from '@fastify/cors';\n\n/**\n * Allowed localhost origins for CORS.\n */\nconst ALLOWED_ORIGINS = ['localhost', '127.0.0.1', '[::1]', '::1'];\n\n/**\n * Check if an origin host is allowed.\n */\nfunction isOriginAllowed(origin: string | undefined): boolean {\n // No origin header = curl, native fetch from file:// page = allowed\n if (!origin) {\n return true;\n }\n\n try {\n const url = new URL(origin);\n return ALLOWED_ORIGINS.includes(url.hostname);\n } catch {\n // Invalid origin = reject\n return false;\n }\n}\n\n/**\n * Build CORS options for Fastify.\n */\nexport function buildCorsOptions(): FastifyCorsOptions {\n return {\n origin: (origin, callback) => {\n // origin is the value of the Origin header, or undefined if not present\n\n if (isOriginAllowed(origin)) {\n callback(null, true);\n } else {\n // Reject with 403; Fastify will handle the response\n callback(new Error('Origin not allowed'), false);\n }\n },\n methods: ['GET', 'PATCH', 'OPTIONS', 'HEAD'],\n credentials: false,\n };\n}\n","/**\n * Node routes: GET /nodes, GET /nodes/:type, GET /nodes/:type/packets/timeseries,\n * GET /nodes/:type/bandwidth,\n * GET /nodes/:nodeId/health, GET /nodes/:nodeId/swaps/recent,\n * GET /nodes/:nodeId/deposit-addresses.\n *\n * `:type` routes are scoped per node kind ('town' | 'mill' | 'dvm').\n * `:nodeId` routes are scoped per running instance and accept either a\n * container name (e.g. 'dev-mill-01') or a type-level placeholder\n * ('mill' when no instance has started yet).\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type {\n ApiDeps,\n NodeInfo,\n MetricsPayload,\n BandwidthPayload,\n PacketTimeseriesPayload,\n TimeseriesBucket,\n NodeHealthPayload,\n MillSwapsRecentPayload,\n JobsRecentPayload,\n DepositAddressesPayload,\n DvmHealthResponse,\n} from '../types.js';\nimport type { NodeType, NodeState } from '../types.js';\nimport { CONTAINER_PREFIX } from '../../constants.js';\n\n/** Cache entry for health proxy responses */\ninterface HealthCacheEntry {\n payload: NodeHealthPayload;\n cachedAt: number;\n}\n\nconst HEALTH_CACHE_TTL_MS = 2_000;\n\n/**\n * Feature-detect the event `kind` from a connector packet log entry. The\n * connector contract's `PacketLogEntry` does not yet expose a `kind` field\n * (see `@toon-protocol/sdk` CONNECTOR_MIGRATION.md \"Townhouse-Side\n * Contract\"); when absent, packets group under bucket 0 (\"unattributed\")\n * so operators can see the shortfall instead of silent data loss.\n */\nexport function extractKindFromPacketEntry(entry: unknown): number {\n const kind = (entry as { kind?: unknown } | null)?.kind;\n return typeof kind === 'number' && Number.isFinite(kind) ? kind : 0;\n}\n\n/** Map raw Docker container state to the API's NodeState enum. */\nfunction mapDockerState(raw: string | undefined): NodeState {\n switch (raw) {\n case 'running':\n return 'running';\n case 'exited':\n case 'stopped':\n case 'created':\n case 'paused':\n return 'stopped';\n case undefined:\n return 'not-created';\n default:\n // 'restarting', 'removing', 'dead' → error\n return 'error';\n }\n}\n\n/** Build the mutable fee-field subset of a node's config, typed per node kind. */\nfunction pickMutableFees(\n type: NodeType,\n nodeConfig: {\n enabled: boolean;\n feePerEvent?: number;\n feeBasisPoints?: number;\n feePerJob?: number;\n }\n): {\n enabled: boolean;\n feePerEvent?: number;\n feeBasisPoints?: number;\n feePerJob?: number;\n} {\n switch (type) {\n case 'town':\n return {\n enabled: nodeConfig.enabled,\n feePerEvent: nodeConfig.feePerEvent,\n };\n case 'mill':\n return {\n enabled: nodeConfig.enabled,\n feeBasisPoints: nodeConfig.feeBasisPoints,\n };\n case 'dvm':\n return { enabled: nodeConfig.enabled, feePerJob: nodeConfig.feePerJob };\n }\n}\n\n/** Guard an ISO-8601 StartedAt and return uptime in seconds, or null if implausible. */\nfunction computeUptimeSeconds(\n startedAt: string | undefined,\n state: NodeState\n): number | null {\n if (state !== 'running' || !startedAt) return null;\n const started = new Date(startedAt).getTime();\n if (isNaN(started) || started <= 0) return null;\n const now = Date.now();\n const ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1000;\n if (started > now || now - started >= ONE_YEAR_MS) return null;\n return Math.floor((now - started) / 1000);\n}\n\n/**\n * Register node routes.\n */\nexport function registerNodeRoutes(app: FastifyInstance, deps: ApiDeps): void {\n const healthCache = new Map<string, HealthCacheEntry>();\n // GET /nodes - list all node types (multi-instance aware)\n app.get('/nodes', async (_request, _reply) => {\n const status = await deps.orchestrator.status();\n const nodes: NodeInfo[] = [];\n\n for (const type of ['town', 'mill', 'dvm'] as const) {\n const nodeConfig = deps.config.nodes[type];\n if (!nodeConfig) continue;\n\n const instances = status.filter((s) => s.type === type);\n\n if (instances.length === 0) {\n nodes.push({\n id: type,\n type,\n enabled: nodeConfig.enabled,\n state: 'not-created',\n uptimeSeconds: null,\n image: nodeConfig.image ?? `toon:${type}`,\n });\n continue;\n }\n\n for (const entry of instances) {\n const state = mapDockerState(entry.state);\n const uptimeSeconds = computeUptimeSeconds(entry.startedAt, state);\n nodes.push({\n id: entry.name, // \"town\" for single-instance, \"dev-town-01\" for multi\n type,\n enabled: nodeConfig.enabled,\n state,\n uptimeSeconds,\n image: nodeConfig.image ?? `toon:${type}`,\n });\n }\n }\n\n return nodes;\n });\n\n // GET /nodes/:type - get single node detail\n app.get<{ Params: { type: string } }>(\n '/nodes/:type',\n async (request, reply) => {\n const { type } = request.params;\n\n // Validate type - return 404 for unknown types (for AC #9)\n if (type !== 'town' && type !== 'mill' && type !== 'dvm') {\n return reply.status(404).send({\n error: 'unknown_node_type',\n type,\n });\n }\n\n const nodeConfig = deps.config.nodes[type as NodeType];\n if (!nodeConfig) {\n return reply.status(404).send({\n error: 'unknown_node_type',\n type,\n });\n }\n\n // Get status from orchestrator (use first matching instance for single-type endpoint)\n const status = await deps.orchestrator.status();\n const statusEntry = status.find((s) => s.type === type);\n const state: NodeState = statusEntry\n ? mapDockerState(statusEntry.state)\n : 'not-created';\n const uptimeSeconds = computeUptimeSeconds(statusEntry?.startedAt, state);\n\n // Get metrics from connector admin (degraded state on failure).\n // ConnectorAdminClient.getMetrics() returns the connector's\n // /admin/metrics.json shape verbatim — aggregate counters live under\n // `aggregate`, per-peer entries under `peers`. Narrowed MetricsPayload\n // here surfaces the aggregate rollup; per-peer breakdowns are available\n // to consumers that need them via metricsRes.peers.\n let metrics: MetricsPayload | null = null;\n try {\n const metricsRes = await deps.connectorAdmin.getMetrics();\n if (metricsRes) {\n metrics = {\n packetsForwarded: metricsRes.aggregate.packetsForwarded,\n packetsRejected: metricsRes.aggregate.packetsRejected,\n bytesSent: metricsRes.aggregate.bytesSent,\n attribution: 'aggregate',\n available: true,\n };\n }\n } catch {\n // Connector down - return degraded state\n metrics = {\n packetsForwarded: 0,\n packetsRejected: 0,\n bytesSent: 0,\n attribution: 'aggregate',\n available: false,\n };\n }\n\n // Build config subset (mutable fields) — per-type, typed safely\n const config = pickMutableFees(type as NodeType, nodeConfig);\n\n return {\n id: type,\n type,\n enabled: nodeConfig.enabled,\n state,\n uptimeSeconds,\n image: nodeConfig.image ?? `toon:${type}`,\n config,\n metrics,\n };\n }\n );\n\n // ── GET /nodes/:type/packets/timeseries ────────────────────────────────────\n\n app.get<{\n Params: { type: string };\n Querystring: { bucket?: string; since?: string };\n }>('/nodes/:type/packets/timeseries', async (request, reply) => {\n const { type } = request.params;\n const { bucket = 'hour', since } = request.query;\n\n if (type !== 'town' && type !== 'mill' && type !== 'dvm') {\n return reply.status(404).send({ error: 'unknown_node_type', type });\n }\n\n const supportedBuckets = ['hour', 'day', 'minute'];\n if (!supportedBuckets.includes(bucket)) {\n return reply.status(400).send({\n error: 'unsupported_bucket',\n message: `bucket must be one of: ${supportedBuckets.join(', ')}`,\n });\n }\n\n const sinceMs = since\n ? new Date(since).getTime()\n : Date.now() - 24 * 60 * 60 * 1000;\n if (isNaN(sinceMs)) {\n return reply\n .status(400)\n .send({ error: 'invalid_since', message: 'since must be ISO 8601' });\n }\n\n try {\n // Resolve the node's ILP address from the connector's peer roster so the\n // packet log is scoped to this node type only (AC-3 / Task 2.3).\n // Falls through without filter if peers are unavailable.\n let ilpAddress: string | undefined;\n try {\n const peers = await deps.connectorAdmin.getPeers();\n const peer = peers.find((p) => p.id === type);\n ilpAddress = peer?.ilpAddresses[0];\n } catch {\n // Connector peer list unavailable — return unfiltered data as fallback\n }\n\n const packets = await deps.connectorAdmin.getPacketLog({\n ilpAddress,\n since: sinceMs,\n limit: 10_000,\n });\n\n // Bucket the packet log by time\n const bucketMs =\n bucket === 'minute'\n ? 60_000\n : bucket === 'day'\n ? 24 * 60 * 60_000\n : /* hour */ 60 * 60_000;\n\n const countsMap = new Map<number, number>();\n for (const entry of packets) {\n const bucketTs = Math.floor(entry.ts / bucketMs) * bucketMs;\n countsMap.set(bucketTs, (countsMap.get(bucketTs) ?? 0) + 1);\n }\n\n const buckets: TimeseriesBucket[] = Array.from(countsMap.entries())\n .sort(([a], [b]) => a - b)\n .map(([ts, count]) => ({ ts, count }));\n\n const payload: PacketTimeseriesPayload = { buckets };\n return payload;\n } catch (error: unknown) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ConnectorEndpointNotFound') {\n return reply.status(503).send({\n error: 'connector_endpoint_not_found',\n message:\n 'Connector image does not expose GET /packets. See CONNECTOR_MIGRATION.md §getPacketLog.',\n });\n }\n // Connector down or other error\n return reply.status(503).send({\n error: 'connector_unavailable',\n message: 'Could not reach connector admin API',\n });\n }\n });\n\n // ── GET /nodes/:type/bandwidth ─────────────────────────────────────────────\n\n app.get<{ Params: { type: string } }>(\n '/nodes/:type/bandwidth',\n async (request, reply) => {\n const { type } = request.params;\n\n if (type !== 'town' && type !== 'mill' && type !== 'dvm') {\n return reply.status(404).send({ error: 'unknown_node_type', type });\n }\n\n const containerName = `${CONTAINER_PREFIX}${type}`;\n const stats = await deps.orchestrator.getContainerStats(containerName);\n\n if (stats === null) {\n return null;\n }\n\n const payload: BandwidthPayload = {\n bytesIn: stats.bytesIn,\n bytesOut: stats.bytesOut,\n sampleAt: stats.sampleAt,\n };\n return payload;\n }\n );\n\n // ── per-instance node resolution helper ───────────────────────────────────\n\n async function resolveNodeId(\n nodeId: string\n ): Promise<{ type: NodeType; instanceName: string } | null> {\n const status = await deps.orchestrator.status();\n const instance = status.find((s) => s.name === nodeId);\n if (instance) {\n return { type: instance.type as NodeType, instanceName: instance.name };\n }\n if (nodeId === 'town' || nodeId === 'mill' || nodeId === 'dvm') {\n return { type: nodeId, instanceName: nodeId };\n }\n return null;\n }\n\n // ── GET /nodes/:nodeId/health ──────────────────────────────────────────────\n\n app.get<{ Params: { nodeId: string } }>(\n '/nodes/:nodeId/health',\n async (request, reply) => {\n const { nodeId } = request.params;\n\n // Skip the type-level routes that share the prefix.\n if (nodeId === 'packets' || nodeId === 'bandwidth') {\n return reply.status(404).send({ error: 'unknown_node', nodeId });\n }\n\n const resolved = await resolveNodeId(nodeId);\n if (!resolved) {\n return reply.status(404).send({ error: 'unknown_node', nodeId });\n }\n\n const cacheKey = resolved.instanceName;\n const cached = healthCache.get(cacheKey);\n if (cached && Date.now() - cached.cachedAt < HEALTH_CACHE_TTL_MS) {\n return cached.payload;\n }\n\n try {\n const endpoint = await deps.orchestrator.getNodeHealthEndpoint(\n resolved.instanceName,\n resolved.type\n );\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 3_000);\n let res: Response;\n try {\n // nosemgrep: javascript.lang.security.detect-insecure-http -- Docker-internal, TLS unnecessary\n res = await fetch(`${endpoint}/health`, {\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeout);\n }\n if (!res.ok) {\n return reply.status(503).send({ error: 'node_unreachable' });\n }\n const payload = (await res.json()) as NodeHealthPayload;\n healthCache.set(cacheKey, { payload, cachedAt: Date.now() });\n return payload;\n } catch {\n return reply.status(503).send({ error: 'node_unreachable' });\n }\n }\n );\n\n // ── GET /nodes/:nodeId/swaps/recent ───────────────────────────────────────\n\n app.get<{\n Params: { nodeId: string };\n Querystring: { windowSec?: string };\n }>('/nodes/:nodeId/swaps/recent', async (request, reply) => {\n const { nodeId } = request.params;\n\n const resolved = await resolveNodeId(nodeId);\n if (!resolved) {\n return reply.status(404).send({ error: 'unknown_node', nodeId });\n }\n if (resolved.type !== 'mill') {\n return reply.status(404).send({\n error: 'swaps_only_for_mill',\n message: 'swaps/recent is only available for mill instances',\n });\n }\n\n const rawWindowSec = request.query.windowSec;\n // Reject scientific notation and non-decimal strings before parseInt\n // silently truncates them ('1e10' → 1).\n if (rawWindowSec !== undefined && !/^\\d+$/.test(rawWindowSec)) {\n return reply.status(400).send({\n error: 'invalid_window_sec',\n message: 'windowSec must be a non-negative integer (1–3600)',\n });\n }\n const windowSec =\n rawWindowSec !== undefined ? parseInt(rawWindowSec, 10) : 300;\n if (isNaN(windowSec) || windowSec < 1 || windowSec > 3600) {\n return reply.status(400).send({\n error: 'invalid_window_sec',\n message: 'windowSec must be 1–3600',\n });\n }\n\n // Resolve this instance's ILP address from connector peers.\n // If the peer is not registered yet, return an empty result rather than\n // an unfiltered packet log (which would include packets from every peer).\n let ilpAddress: string | undefined;\n try {\n const peers = await deps.connectorAdmin.getPeers();\n const peer = peers.find((p) => p.id === resolved.instanceName);\n ilpAddress = peer?.ilpAddresses[0];\n } catch {\n // Connector unavailable — handled in the next try block.\n }\n\n if (!ilpAddress) {\n const empty: MillSwapsRecentPayload = {\n count: 0,\n volume: '0',\n byPair: [],\n };\n return empty;\n }\n\n try {\n const packets = await deps.connectorAdmin.getPacketLog({\n ilpAddress,\n since: Date.now() - windowSec * 1_000,\n limit: 10_000,\n });\n\n const byPairMap = new Map<string, { count: number; volume: bigint }>();\n let totalVolume = 0n;\n\n for (const entry of packets) {\n totalVolume += BigInt(entry.amount ?? 0);\n const pairKey = `${entry.ilpAddressFrom ?? '?'}→${entry.ilpAddressTo ?? '?'}`;\n const existing = byPairMap.get(pairKey) ?? { count: 0, volume: 0n };\n byPairMap.set(pairKey, {\n count: existing.count + 1,\n volume: existing.volume + BigInt(entry.amount ?? 0),\n });\n }\n\n const byPair = Array.from(byPairMap.entries()).map(([pair, data]) => ({\n pair,\n count: data.count,\n volume: data.volume.toString(),\n }));\n\n const payload: MillSwapsRecentPayload = {\n count: packets.length,\n volume: totalVolume.toString(),\n byPair,\n };\n return payload;\n } catch (error: unknown) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ConnectorEndpointNotFound') {\n return reply.status(503).send({\n error: 'connector_endpoint_not_found',\n message:\n 'Connector image does not expose GET /packets. See CONNECTOR_MIGRATION.md.',\n });\n }\n return reply.status(503).send({ error: 'connector_unavailable' });\n }\n });\n\n // ── GET /nodes/:nodeId/jobs/recent ────────────────────────────────────────\n // Returns DVM job throughput for the requested window (default 300 s).\n // byKind is sourced from the DVM container's health endpoint (counter-shim,\n // the canonical source since the connector PacketLogEntry has no kind field).\n // volume is sourced from the connector packet log (amount sum).\n\n app.get<{\n Params: { nodeId: string };\n Querystring: { windowSec?: string };\n }>('/nodes/:nodeId/jobs/recent', async (request, reply) => {\n const { nodeId } = request.params;\n\n const resolved = await resolveNodeId(nodeId);\n if (!resolved) {\n return reply.status(404).send({ error: 'unknown_node', nodeId });\n }\n if (resolved.type !== 'dvm') {\n return reply.status(404).send({\n error: 'jobs_only_for_dvm',\n message: 'jobs/recent is only available for dvm instances',\n });\n }\n\n const rawWindowSec = request.query.windowSec;\n if (rawWindowSec !== undefined && !/^\\d+$/.test(rawWindowSec)) {\n return reply.status(400).send({\n error: 'invalid_window_sec',\n message: 'windowSec must be a non-negative integer (1–300)',\n });\n }\n const requestedWindowSec =\n rawWindowSec !== undefined ? parseInt(rawWindowSec, 10) : 300;\n // The DVM in-memory counter is fixed at a 5-minute (300 s) window,\n // so the byKind/byStatus/total fields can only honestly report the\n // last 300 s. Reject windows outside [1, 300] rather than silently\n // mixing windows across response fields.\n if (requestedWindowSec < 1 || requestedWindowSec > 300) {\n return reply.status(400).send({\n error: 'invalid_window_sec',\n message:\n 'windowSec must be 1–300 (DVM counter window is fixed at 5 min)',\n });\n }\n const windowSec = requestedWindowSec;\n\n // Resolve ILP address from connector peers\n let ilpAddress: string | undefined;\n let connectorDown = false;\n try {\n const peers = await deps.connectorAdmin.getPeers();\n const peer = peers.find((p) => p.id === resolved.instanceName);\n ilpAddress = peer?.ilpAddresses[0];\n } catch {\n connectorDown = true;\n }\n\n if (connectorDown) {\n return reply.status(503).send({ error: 'connector_unavailable' });\n }\n\n // Fetch DVM health for byKind and byStatus (the canonical counter source)\n let dvmHealth: DvmHealthResponse | null = null;\n try {\n const cached = healthCache.get(resolved.instanceName);\n if (cached && Date.now() - cached.cachedAt < HEALTH_CACHE_TTL_MS) {\n dvmHealth = cached.payload as DvmHealthResponse;\n } else {\n const endpoint = await deps.orchestrator.getNodeHealthEndpoint(\n resolved.instanceName,\n 'dvm'\n );\n // 3 s timeout mirrors the parallel /nodes/:nodeId/health route.\n // A hung DVM container otherwise blocks Fastify indefinitely.\n const healthController = new AbortController();\n const healthTimeout = setTimeout(() => healthController.abort(), 3_000);\n let healthRes: Response;\n try {\n // nosemgrep: javascript.lang.security.detect-insecure-http -- Docker-internal, TLS unnecessary\n healthRes = await fetch(`${endpoint}/health`, {\n signal: healthController.signal,\n });\n } finally {\n clearTimeout(healthTimeout);\n }\n if (healthRes.ok) {\n dvmHealth = (await healthRes.json()) as DvmHealthResponse;\n healthCache.set(resolved.instanceName, {\n payload: dvmHealth,\n cachedAt: Date.now(),\n });\n }\n }\n } catch {\n // Health fetch failed — degrade gracefully\n }\n\n const byStatus = dvmHealth?.jobsRecent?.byStatus ?? {\n processing: 0,\n success: 0,\n error: 0,\n partial: 0,\n };\n\n // Build byKind from DVM health counter (canonical) — group into JobsByKindEntry\n const byKindFromHealth = dvmHealth?.jobsRecent?.byKind ?? [];\n const byKindMap = new Map<number, { count: number; volume: bigint }>();\n for (const entry of byKindFromHealth) {\n byKindMap.set(entry.kind, { count: entry.count, volume: 0n });\n }\n\n if (!ilpAddress) {\n // ILP address unknown — return zero-volume result with health-sourced counters\n const payload: JobsRecentPayload = {\n count: dvmHealth?.jobsRecent?.total ?? 0,\n volume: '0',\n byKind: Array.from(byKindMap.entries()).map(([kind, d]) => ({\n kind,\n count: d.count,\n volume: '0',\n })),\n byStatus,\n };\n return payload;\n }\n\n try {\n const packets = await deps.connectorAdmin.getPacketLog({\n ilpAddress,\n since: Date.now() - windowSec * 1_000,\n limit: 10_000,\n });\n\n let totalVolume = 0n;\n for (const entry of packets) {\n totalVolume += BigInt(entry.amount ?? 0);\n // kind field: feature-detect — if absent, group under bucket 0 (unattributed)\n const kind = extractKindFromPacketEntry(entry);\n const existing = byKindMap.get(kind) ?? { count: 0, volume: 0n };\n // Only increment count from packet log if no DVM health data available;\n // prefer DVM counter for count, use packet log for volume only.\n byKindMap.set(kind, {\n count:\n byKindFromHealth.length > 0 ? existing.count : existing.count + 1,\n volume: existing.volume + BigInt(entry.amount ?? 0),\n });\n }\n\n const byKind = Array.from(byKindMap.entries()).map(([kind, d]) => ({\n kind,\n count: d.count,\n volume: d.volume.toString(),\n }));\n\n const payload: JobsRecentPayload = {\n count: dvmHealth?.jobsRecent?.total ?? packets.length,\n volume: totalVolume.toString(),\n byKind,\n byStatus,\n };\n return payload;\n } catch (error: unknown) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ConnectorEndpointNotFound') {\n return reply.status(503).send({\n error: 'connector_endpoint_not_found',\n message:\n 'Connector image does not expose GET /packets. See CONNECTOR_MIGRATION.md.',\n });\n }\n return reply.status(503).send({ error: 'connector_unavailable' });\n }\n });\n\n // ── GET /nodes/:nodeId/deposit-addresses ──────────────────────────────────\n\n app.get<{ Params: { nodeId: string } }>(\n '/nodes/:nodeId/deposit-addresses',\n async (request, reply) => {\n const { nodeId } = request.params;\n\n const resolved = await resolveNodeId(nodeId);\n if (!resolved) {\n return reply.status(404).send({ error: 'unknown_node', nodeId });\n }\n\n let keys;\n try {\n keys = deps.wallet.getNodeKeys(resolved.type);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n if (/not initialized/i.test(msg)) {\n return reply.status(503).send({ error: 'wallet_not_initialized' });\n }\n return reply.status(500).send({ error: 'wallet_error', message: msg });\n }\n\n const chains: DepositAddressesPayload['chains'] = [\n { family: 'evm', address: keys.evmAddress },\n ];\n\n if (resolved.type === 'mill') {\n if (keys.solanaAddress) {\n chains.push({ family: 'solana', address: keys.solanaAddress });\n }\n if (keys.minaAddress) {\n chains.push({ family: 'mina', address: keys.minaAddress });\n }\n }\n\n const payload: DepositAddressesPayload = { chains };\n return payload;\n }\n );\n}\n","/**\n * Wallet routes: GET /wallet\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type { ApiDeps } from '../types.js';\n\n/**\n * Register wallet routes.\n */\nexport function registerWalletRoutes(\n app: FastifyInstance,\n deps: ApiDeps\n): void {\n // GET /wallet - list all wallet keys (address-only, no secrets)\n app.get('/wallet', async (_request, _reply) => {\n // Returns NodeKeyInfo[] which has NO secrets\n const keys = deps.wallet.listKeys();\n return { keys };\n });\n}\n","/**\n * EVM JSON-RPC helpers for balance queries.\n * Uses native fetch + AbortController (no external deps).\n */\n\nconst TIMEOUT_MS = 3_000;\nconst HEX_ADDR_RE = /^0x[0-9a-fA-F]{40}$/;\n\n/** JSON-RPC request helper. The local 3s timeout always fires regardless of\n * whether the caller passes their own signal. */\nasync function rpcCall(\n rpcUrl: string,\n method: string,\n params: unknown[],\n signal?: AbortSignal\n): Promise<unknown> {\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(new Error('rpc_timeout')),\n TIMEOUT_MS\n );\n // Forward caller cancellation into our controller so the local timeout-driven\n // abort and the caller-driven abort both reach the underlying fetch.\n const onCallerAbort = signal\n ? () =>\n controller.abort(\n (signal.reason as Error | undefined) ?? new Error('aborted')\n )\n : null;\n if (signal && onCallerAbort) {\n if (signal.aborted) onCallerAbort();\n else signal.addEventListener('abort', onCallerAbort, { once: true });\n }\n\n try {\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),\n signal: controller.signal,\n });\n if (!res.ok)\n throw new Error(`EVM RPC ${method} failed: HTTP ${res.status}`);\n const data = (await res.json()) as {\n result?: string;\n error?: { message: string };\n };\n if (data.error)\n throw new Error(`EVM RPC ${method} error: ${data.error.message}`);\n return data.result;\n } finally {\n clearTimeout(timeout);\n if (signal && onCallerAbort) {\n signal.removeEventListener('abort', onCallerAbort);\n }\n }\n}\n\n/**\n * Get native ETH balance (wei) for an address.\n * Returns balance as decimal string.\n */\nexport async function getEvmBalance(\n rpcUrl: string,\n address: string\n): Promise<string> {\n if (!HEX_ADDR_RE.test(address)) {\n throw new Error(`getEvmBalance: invalid address shape (${address})`);\n }\n const hex = (await rpcCall(rpcUrl, 'eth_getBalance', [\n address,\n 'latest',\n ])) as string;\n return BigInt(hex).toString();\n}\n\n/**\n * Get ERC-20 token balance using balanceOf(address) selector.\n * Returns balance as decimal string.\n */\nexport async function getErc20Balance(\n rpcUrl: string,\n contractAddress: string,\n holderAddress: string\n): Promise<string> {\n if (!HEX_ADDR_RE.test(contractAddress)) {\n throw new Error(\n `getErc20Balance: invalid contract address (${contractAddress})`\n );\n }\n if (!HEX_ADDR_RE.test(holderAddress)) {\n throw new Error(\n `getErc20Balance: invalid holder address (${holderAddress})`\n );\n }\n // ABI-encode balanceOf(address): selector 0x70a08231 + padded address\n const paddedAddr = holderAddress\n .toLowerCase()\n .replace(/^0x/, '')\n .padStart(64, '0');\n const data = `0x70a08231${paddedAddr}`;\n\n const hex = (await rpcCall(rpcUrl, 'eth_call', [\n { to: contractAddress, data },\n 'latest',\n ])) as string;\n\n if (!hex || hex === '0x') return '0';\n return BigInt(hex).toString();\n}\n","/**\n * Solana JSON-RPC helpers for balance queries.\n * Uses native fetch + AbortController (no external deps).\n */\n\nconst TIMEOUT_MS = 3_000;\n\n/**\n * Get native SOL balance (lamports) for a base58 address.\n * Returns balance as decimal string.\n */\nexport async function getSolanaBalance(\n rpcUrl: string,\n address: string\n): Promise<string> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n try {\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'getBalance',\n params: [address],\n }),\n signal: controller.signal,\n });\n if (!res.ok)\n throw new Error(`Solana RPC getBalance failed: HTTP ${res.status}`);\n const data = (await res.json()) as {\n result?: { value?: number };\n error?: { message: string };\n };\n if (data.error) throw new Error(`Solana RPC error: ${data.error.message}`);\n const lamports = data.result?.value ?? 0;\n return BigInt(lamports).toString();\n } finally {\n clearTimeout(timeout);\n }\n}\n","/**\n * Mina GraphQL helpers for balance queries.\n * Uses native fetch + AbortController (no external deps).\n */\n\nconst TIMEOUT_MS = 3_000;\n\n/**\n * Get MINA balance (nanomina) for a base58check address.\n * Returns balance as decimal string in nanomina (scale 9).\n */\nexport async function getMinaBalance(\n graphqlUrl: string,\n address: string\n): Promise<string> {\n const query = `query GetBalance($pk: PublicKey!) {\n account(publicKey: $pk) {\n balance {\n total\n }\n }\n }`;\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n try {\n const res = await fetch(graphqlUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ query, variables: { pk: address } }),\n signal: controller.signal,\n });\n if (!res.ok) throw new Error(`Mina GraphQL failed: HTTP ${res.status}`);\n const data = (await res.json()) as {\n data?: { account?: { balance?: { total?: string } } };\n errors?: { message: string }[];\n };\n if (data.errors?.length)\n throw new Error(`Mina GraphQL error: ${data.errors[0]?.message}`);\n const total = data.data?.account?.balance?.total;\n if (!total) return '0';\n // total is returned as a decimal MINA string (e.g. \"1000.000000000\").\n // Reject malformed inputs (scientific notation, empty wholes, non-digits)\n // explicitly — a BigInt throw inside this function would surface as a\n // generic 503 instead of a clean `available:false / reason:bad_format`.\n if (!/^\\d+(\\.\\d+)?$/.test(total)) {\n throw new Error(`Mina balance: unsupported numeric format (${total})`);\n }\n const [whole = '0', frac = ''] = total.split('.');\n const fracPadded = frac.padEnd(9, '0').slice(0, 9) || '0';\n const nanomina = BigInt(whole) * 1_000_000_000n + BigInt(fracPadded);\n return nanomina.toString();\n } finally {\n clearTimeout(timeout);\n }\n}\n","/**\n * GET /api/wallet/balances\n *\n * Returns per-(nodeType × family × token) balance entries.\n * Per-RPC failure is partial — one bad chain never kills the whole response.\n * Server-side cache: 5 s TTL per (nodeType × address × token) to avoid\n * hammering RPCs and to keep `payload.ts` stable across cache-hit reads.\n * In-flight requests for the same key are deduped via a Promise map so two\n * parallel /balances calls don't double-call the upstream RPC.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type { ApiDeps } from '../types.js';\nimport type { WalletBalanceEntry, WalletBalancesPayload } from '../types.js';\nimport { getEvmBalance, getErc20Balance } from '../../chain/evm-rpc.js';\nimport { getSolanaBalance } from '../../chain/solana-rpc.js';\nimport { getMinaBalance } from '../../chain/mina-graphql.js';\nimport type { NodeKeyInfo } from '../../wallet/types.js';\n\n// ── Cache ─────────────────────────────────────────────────────────────────────\n\ninterface CacheEntry {\n entry: WalletBalanceEntry;\n ts: number;\n}\n\n// In-memory best-effort cache (restart-volatile; single-process).\nconst CACHE = new Map<string, CacheEntry>();\nconst INFLIGHT = new Map<string, Promise<WalletBalanceEntry>>();\nconst CACHE_TTL_MS = 5_000;\n\n/** Test hook: reset module-scope cache between vitest tests. */\nexport function resetWalletBalancesCache(): void {\n CACHE.clear();\n INFLIGHT.clear();\n}\n\nfunction getCachedEntry(key: string): CacheEntry | undefined {\n const hit = CACHE.get(key);\n if (!hit) return undefined;\n if (Date.now() - hit.ts > CACHE_TTL_MS) {\n CACHE.delete(key);\n return undefined;\n }\n return hit;\n}\n\nfunction setCached(key: string, entry: WalletBalanceEntry): CacheEntry {\n const cached = { entry, ts: Date.now() };\n CACHE.set(key, cached);\n return cached;\n}\n\n/** Wrap a fetcher with cache + in-flight dedup so two callers for the same key\n * share one upstream RPC call. */\nasync function memoize(\n key: string,\n fetcher: () => Promise<WalletBalanceEntry>\n): Promise<{ entry: WalletBalanceEntry; ts: number }> {\n const cached = getCachedEntry(key);\n if (cached) return cached;\n const inflight = INFLIGHT.get(key);\n if (inflight) {\n const entry = await inflight;\n const after = getCachedEntry(key);\n return after ?? { entry, ts: Date.now() };\n }\n const promise = (async () => {\n try {\n const entry = await fetcher();\n setCached(key, entry);\n return entry;\n } finally {\n INFLIGHT.delete(key);\n }\n })();\n INFLIGHT.set(key, promise);\n const entry = await promise;\n const after = getCachedEntry(key);\n return after ?? { entry, ts: Date.now() };\n}\n\n// ── Fetch helpers ─────────────────────────────────────────────────────────────\n\nfunction unavailable(\n nodeType: 'town' | 'mill' | 'dvm',\n family: WalletBalanceEntry['family'],\n token: WalletBalanceEntry['token'],\n address: string,\n scale: number,\n reason: string\n): WalletBalanceEntry {\n return {\n nodeType,\n family,\n token,\n address,\n balance: '0',\n scale,\n available: false,\n reason,\n };\n}\n\nasync function fetchEvmEth(\n rpcUrl: string,\n nodeType: 'town' | 'mill' | 'dvm',\n address: string\n): Promise<{ entry: WalletBalanceEntry; ts: number }> {\n const cacheKey = `evm:${nodeType}:${address}:ETH`;\n return memoize(cacheKey, async () => {\n try {\n const balance = await getEvmBalance(rpcUrl, address);\n return {\n nodeType,\n family: 'evm',\n token: 'ETH',\n address,\n balance,\n scale: 18,\n available: true,\n };\n } catch (e) {\n return unavailable(\n nodeType,\n 'evm',\n 'ETH',\n address,\n 18,\n e instanceof Error ? e.message : 'evm_rpc_error'\n );\n }\n });\n}\n\nasync function fetchEvmUsdc(\n rpcUrl: string,\n usdcAddress: string | undefined,\n nodeType: 'town' | 'mill' | 'dvm',\n address: string\n): Promise<{ entry: WalletBalanceEntry; ts: number }> {\n if (!usdcAddress || !/^0x[0-9a-fA-F]{40}$/.test(usdcAddress)) {\n // Don't cache config-drift — it should clear immediately when the env is fixed.\n return {\n entry: unavailable(\n nodeType,\n 'evm',\n 'USDC',\n address,\n 6,\n 'usdc_address_not_configured'\n ),\n ts: Date.now(),\n };\n }\n const cacheKey = `evm:${nodeType}:${address}:USDC`;\n return memoize(cacheKey, async () => {\n try {\n const balance = await getErc20Balance(rpcUrl, usdcAddress, address);\n return {\n nodeType,\n family: 'evm',\n token: 'USDC',\n address,\n balance,\n scale: 6,\n available: true,\n };\n } catch (e) {\n return unavailable(\n nodeType,\n 'evm',\n 'USDC',\n address,\n 6,\n e instanceof Error ? e.message : 'evm_rpc_error'\n );\n }\n });\n}\n\nasync function fetchSolana(\n rpcUrl: string,\n nodeType: 'town' | 'mill' | 'dvm',\n address: string\n): Promise<{ entry: WalletBalanceEntry; ts: number }> {\n const cacheKey = `solana:${nodeType}:${address}:SOL`;\n return memoize(cacheKey, async () => {\n try {\n const balance = await getSolanaBalance(rpcUrl, address);\n return {\n nodeType,\n family: 'solana',\n token: 'SOL',\n address,\n balance,\n scale: 9,\n available: true,\n };\n } catch (e) {\n return unavailable(\n nodeType,\n 'solana',\n 'SOL',\n address,\n 9,\n e instanceof Error ? e.message : 'solana_rpc_error'\n );\n }\n });\n}\n\nasync function fetchMina(\n graphqlUrl: string,\n nodeType: 'town' | 'mill' | 'dvm',\n address: string\n): Promise<{ entry: WalletBalanceEntry; ts: number }> {\n const cacheKey = `mina:${nodeType}:${address}:MINA`;\n return memoize(cacheKey, async () => {\n try {\n const balance = await getMinaBalance(graphqlUrl, address);\n return {\n nodeType,\n family: 'mina',\n token: 'MINA',\n address,\n balance,\n scale: 9,\n available: true,\n };\n } catch (e) {\n return unavailable(\n nodeType,\n 'mina',\n 'MINA',\n address,\n 9,\n e instanceof Error ? e.message : 'mina_graphql_error'\n );\n }\n });\n}\n\n// ── Route registration ────────────────────────────────────────────────────────\n\ninterface FetchTask {\n /** Identity of the (nodeType, family, token, address) so a thrown task can\n * still be reported with its original tuple instead of a fake town/ETH stub. */\n identity: {\n nodeType: 'town' | 'mill' | 'dvm';\n family: WalletBalanceEntry['family'];\n token: WalletBalanceEntry['token'];\n address: string;\n scale: number;\n };\n run: () => Promise<{ entry: WalletBalanceEntry; ts: number }>;\n}\n\nexport function registerWalletBalancesRoutes(\n app: FastifyInstance,\n deps: ApiDeps\n): void {\n app.get('/wallet/balances', async (_request, reply) => {\n let keys: NodeKeyInfo[];\n try {\n keys = deps.wallet.getAllKeys();\n } catch {\n return reply.status(503).send({ error: 'wallet_not_initialized' });\n }\n\n const anvil =\n process.env['TOWNHOUSE_DEV_ANVIL_RPC'] ?? 'http://127.0.0.1:28545';\n const solanaRpc =\n process.env['TOWNHOUSE_DEV_SOLANA_RPC'] ?? 'http://127.0.0.1:28899';\n const minaGraphql =\n process.env['TOWNHOUSE_DEV_MINA_GRAPHQL'] ??\n 'http://127.0.0.1:28085/graphql';\n const usdcAddress = process.env['TOON_USDC_ADDRESS'] || undefined;\n\n const tasks: FetchTask[] = [];\n for (const keyInfo of keys) {\n const nodeType = keyInfo.nodeType as 'town' | 'mill' | 'dvm';\n tasks.push({\n identity: {\n nodeType,\n family: 'evm',\n token: 'ETH',\n address: keyInfo.evmAddress,\n scale: 18,\n },\n run: () => fetchEvmEth(anvil, nodeType, keyInfo.evmAddress),\n });\n tasks.push({\n identity: {\n nodeType,\n family: 'evm',\n token: 'USDC',\n address: keyInfo.evmAddress,\n scale: 6,\n },\n run: () =>\n fetchEvmUsdc(anvil, usdcAddress, nodeType, keyInfo.evmAddress),\n });\n if (nodeType === 'mill' && keyInfo.solanaAddress) {\n const solAddr = keyInfo.solanaAddress;\n tasks.push({\n identity: {\n nodeType,\n family: 'solana',\n token: 'SOL',\n address: solAddr,\n scale: 9,\n },\n run: () => fetchSolana(solanaRpc, nodeType, solAddr),\n });\n }\n if (nodeType === 'mill' && keyInfo.minaAddress) {\n const minaAddr = keyInfo.minaAddress;\n tasks.push({\n identity: {\n nodeType,\n family: 'mina',\n token: 'MINA',\n address: minaAddr,\n scale: 9,\n },\n run: () => fetchMina(minaGraphql, nodeType, minaAddr),\n });\n }\n }\n\n const results = await Promise.allSettled(tasks.map((t) => t.run()));\n\n let oldestTs = Number.POSITIVE_INFINITY;\n const entries: WalletBalanceEntry[] = results.map((r, idx) => {\n if (r.status === 'fulfilled') {\n if (r.value.ts < oldestTs) oldestTs = r.value.ts;\n return r.value.entry;\n }\n // Rejection branch: capture the original task identity rather than a fake stub.\n const task = tasks[idx];\n if (!task) {\n throw new Error(`task missing for index ${idx}`);\n }\n const { nodeType, family, token, address, scale } = task.identity;\n const reason =\n r.reason instanceof Error ? r.reason.message : 'internal_error';\n return unavailable(nodeType, family, token, address, scale, reason);\n });\n\n // AC-2: cache-hit returns same `ts`. Use the oldest cached entry's ts so\n // back-to-back cached requests yield identical timestamps.\n const ts = oldestTs === Number.POSITIVE_INFINITY ? Date.now() : oldestTs;\n const payload: WalletBalancesPayload = { entries, ts };\n return payload;\n });\n}\n","/**\n * POST /api/wallet/reveal\n *\n * Password-gated seed-phrase reveal.\n * SECURITY: Mnemonic is never logged, never cached beyond the request lifecycle.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type { ApiDeps } from '../types.js';\nimport { loadWallet } from '../../wallet/storage.js';\nimport { decryptWallet } from '../../wallet/crypto.js';\n\nexport function registerWalletRevealRoutes(\n app: FastifyInstance,\n deps: ApiDeps\n): void {\n app.post('/wallet/reveal', async (request, reply) => {\n const body = request.body as { password?: unknown };\n\n if (\n !body ||\n typeof body.password !== 'string' ||\n body.password.length === 0 ||\n body.password.length > 256\n ) {\n return reply.status(400).send({\n error: 'invalid_request',\n message: 'password must be a non-empty string ≤ 256 characters',\n });\n }\n\n const walletPath = deps.config.wallet.encrypted_path;\n let loaded: Awaited<ReturnType<typeof loadWallet>>;\n try {\n loaded = await loadWallet(walletPath);\n } catch (e) {\n // ENOENT (or any \"file not found\" surface) is \"wallet not initialized\",\n // not \"corrupted\" — the user just hasn't run `townhouse init` yet.\n const code = (e as { code?: string } | null)?.code;\n if (code === 'ENOENT' || code === 'ENOTDIR') {\n return reply.status(503).send({ error: 'wallet_not_initialized' });\n }\n return reply.status(500).send({\n error: 'wallet_corrupted',\n message: 'Failed to read wallet file',\n });\n }\n\n if (!loaded) {\n return reply.status(503).send({ error: 'wallet_not_initialized' });\n }\n\n let wallet: typeof loaded.wallet;\n try {\n wallet = loaded.wallet;\n // Validate JSON structure: all required fields present\n if (!wallet.salt || !wallet.iv || !wallet.ciphertext || !wallet.tag) {\n return reply.status(500).send({\n error: 'wallet_corrupted',\n message: 'Wallet file is missing required fields',\n });\n }\n } catch {\n return reply.status(500).send({\n error: 'wallet_corrupted',\n message: 'Wallet file JSON is invalid',\n });\n }\n\n let mnemonic: string;\n try {\n mnemonic = decryptWallet(wallet, body.password);\n } catch {\n return reply.status(401).send({ error: 'invalid_password' });\n }\n\n // Return mnemonic directly — not stored in any module-scoped variable\n return reply.status(200).send({ mnemonic });\n });\n}\n","/**\n * POST /api/wallet/withdraw — EVM-only signed withdrawal (v1)\n * GET /api/wallet/transaction/:txHash — receipt polling\n *\n * SECURITY: Private keys and signed-tx hex are never logged.\n * Localhost-only boundary enforced by the API server bind address.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { isAddress } from 'viem';\nimport type {\n ApiDeps,\n WithdrawRequest,\n WithdrawSuccessResponse,\n WithdrawDryRunResponse,\n TransactionReceiptPayload,\n} from '../types.js';\nimport {\n signAndBroadcastEthTransfer,\n signAndBroadcastUsdcTransfer,\n getReceipt,\n estimateNativeTransferGas,\n estimateUsdcTransferGas,\n} from '../../chain/evm-tx.js';\nimport { getEvmBalance, getErc20Balance } from '../../chain/evm-rpc.js';\nimport type { NodeType } from '../../docker/types.js';\n\nconst NODE_TYPES = new Set<string>(['town', 'mill', 'dvm']);\n\n/** Map a thrown viem/fetch error to an \"RPC unreachable\" verdict.\n * Replaces brittle `e.message.includes('fetch')` substring matching, which\n * over-catches viem strings like \"could not fetch nonce\" (a real broadcast\n * failure, not a transport problem). */\nfunction isRpcUnreachable(e: unknown): boolean {\n if (!(e instanceof Error)) return false;\n // Node fetch / undici surface transport failures as TypeError with a `cause`\n // whose `code` is set to one of these. Anything else is a real broadcast\n // failure that should propagate as 500 broadcast_failed.\n const cause = (e as { cause?: { code?: string } }).cause;\n if (cause?.code) {\n return [\n 'ECONNREFUSED',\n 'ENOTFOUND',\n 'EAI_AGAIN',\n 'ETIMEDOUT',\n 'UND_ERR_CONNECT_TIMEOUT',\n ].includes(cause.code);\n }\n // Bare TypeError \"fetch failed\" (no cause attached, e.g. mocked failures in\n // tests) — match exact viem fetch-failure strings, not the looser substring.\n return (\n /^fetch failed$/i.test(e.message) || /HTTP request failed/i.test(e.message)\n );\n}\n\nexport function registerWalletWithdrawRoutes(\n app: FastifyInstance,\n deps: ApiDeps\n): void {\n // POST /wallet/withdraw\n app.post('/wallet/withdraw', async (request, reply) => {\n const body = request.body as Partial<WithdrawRequest>;\n\n // Validate nodeType\n if (!body.nodeType || !NODE_TYPES.has(body.nodeType)) {\n return reply.status(400).send({\n error: 'invalid_node_type',\n message: 'nodeType must be town, mill, or dvm',\n });\n }\n\n // v1: EVM-only; Solana/Mina → 501\n if (body.chainFamily === 'solana' || body.chainFamily === 'mina') {\n return reply.status(501).send({\n error: 'chain_not_supported_for_withdrawal',\n message: `${body.chainFamily} withdrawal coming soon — copy the address and use an external wallet for now`,\n supportedFamilies: ['evm'],\n });\n }\n if (body.chainFamily !== 'evm') {\n return reply.status(400).send({\n error: 'invalid_chain_family',\n message: 'chainFamily must be evm, solana, or mina',\n });\n }\n\n // Validate token\n if (body.token !== 'native' && body.token !== 'USDC') {\n return reply.status(400).send({\n error: 'invalid_token',\n message: 'token must be native or USDC',\n });\n }\n\n // Validate recipient — regex + viem isAddress for EIP-55\n const recipient = body.recipient ?? '';\n if (!/^0x[0-9a-fA-F]{40}$/.test(recipient)) {\n return reply\n .status(400)\n .send({ error: 'invalid_recipient', code: 'invalid_recipient_format' });\n }\n if (!isAddress(recipient)) {\n return reply.status(400).send({\n error: 'invalid_recipient',\n code: 'invalid_recipient_checksum',\n });\n }\n\n // Validate amount\n let amountBig: bigint;\n try {\n amountBig = BigInt(body.amount ?? '');\n if (amountBig <= 0n) throw new Error('non-positive');\n } catch {\n return reply.status(400).send({\n error: 'invalid_amount',\n message: 'amount must be a positive integer string (raw units)',\n });\n }\n\n const anvil =\n process.env['TOWNHOUSE_DEV_ANVIL_RPC'] ?? 'http://127.0.0.1:28545';\n const usdcAddress = (process.env['TOON_USDC_ADDRESS'] || undefined) as\n | `0x${string}`\n | undefined;\n\n // Get keys\n let nodeKeys: ReturnType<typeof deps.wallet.getNodeKeys>;\n try {\n nodeKeys = deps.wallet.getNodeKeys(body.nodeType as NodeType);\n } catch {\n return reply.status(503).send({ error: 'wallet_not_initialized' });\n }\n\n const evmAddress = nodeKeys.evmAddress as `0x${string}`;\n\n // USDC config is a server-side requirement, not user input — 503 not 400.\n if (body.token === 'USDC' && !usdcAddress) {\n return reply.status(503).send({\n error: 'usdc_address_not_configured',\n message: 'TOON_USDC_ADDRESS not set on server',\n });\n }\n // After the guard above, USDC requests have a valid usdcAddress.\n function requireUsdc(): `0x${string}` {\n if (!usdcAddress) {\n throw new Error('usdcAddress missing after guard');\n }\n return usdcAddress;\n }\n\n // Balance check + gas-aware native cap.\n let onChainBalance: bigint;\n let estimateForGuard: { gas: string; fee: string } | null = null;\n try {\n if (body.token === 'native') {\n onChainBalance = BigInt(await getEvmBalance(anvil, evmAddress));\n } else {\n // USDC — gas is paid in native ETH, not the USDC balance.\n onChainBalance = BigInt(\n await getErc20Balance(anvil, requireUsdc(), evmAddress)\n );\n }\n if (amountBig > onChainBalance) {\n return reply.status(400).send({\n error: 'insufficient_balance',\n code: 'insufficient_balance',\n });\n }\n // Native-only gas headroom check: a \"Max\" withdraw passes the raw\n // balance check then fails at broadcast with \"insufficient funds for\n // gas * price + value\". Reject early with a distinct code so the UI\n // can surface \"leave headroom for fees\".\n if (body.token === 'native') {\n try {\n estimateForGuard = await estimateNativeTransferGas(\n anvil,\n evmAddress,\n recipient as `0x${string}`,\n amountBig\n );\n const fee = BigInt(estimateForGuard.fee);\n if (amountBig + fee > onChainBalance) {\n return reply.status(400).send({\n error: 'insufficient_balance',\n code: 'insufficient_balance_for_gas',\n message:\n 'amount + estimated gas exceeds balance — leave headroom for fees',\n });\n }\n } catch {\n // Estimate unavailable — broadcast will surface the real reason.\n }\n }\n } catch (e) {\n if (isRpcUnreachable(e)) {\n return reply.status(503).send({ error: 'rpc_unreachable' });\n }\n throw e;\n }\n\n // dryRun: return gas estimate without broadcasting. Estimator must match\n // the broadcast path or the displayed fee under-reports for ERC-20.\n if (body.dryRun === true) {\n try {\n const est =\n body.token === 'native'\n ? (estimateForGuard ??\n (await estimateNativeTransferGas(\n anvil,\n evmAddress,\n recipient as `0x${string}`,\n amountBig\n )))\n : await estimateUsdcTransferGas(\n anvil,\n evmAddress,\n requireUsdc(),\n recipient as `0x${string}`,\n amountBig\n );\n const response: WithdrawDryRunResponse = {\n estimatedGas: est.gas,\n estimatedFee: est.fee,\n };\n return reply.status(200).send(response);\n } catch (e) {\n if (isRpcUnreachable(e)) {\n return reply.status(503).send({ error: 'rpc_unreachable' });\n }\n throw e;\n }\n }\n\n // Broadcast\n try {\n let txHash: `0x${string}`;\n let chainId: number;\n\n if (body.token === 'native') {\n const result = await signAndBroadcastEthTransfer(\n anvil,\n nodeKeys.evmPrivateKey,\n recipient as `0x${string}`,\n amountBig\n );\n txHash = result.txHash;\n chainId = result.chainId;\n } else {\n const result = await signAndBroadcastUsdcTransfer(\n anvil,\n requireUsdc(),\n nodeKeys.evmPrivateKey,\n recipient as `0x${string}`,\n amountBig\n );\n txHash = result.txHash;\n chainId = result.chainId;\n }\n\n const response: WithdrawSuccessResponse = { txHash, chainId };\n return reply.status(200).send(response);\n } catch (e) {\n if (isRpcUnreachable(e)) {\n return reply.status(503).send({ error: 'rpc_unreachable' });\n }\n const msg = e instanceof Error ? e.message : String(e);\n return reply\n .status(500)\n .send({ error: 'broadcast_failed', message: msg });\n }\n });\n\n // GET /wallet/transaction/:txHash\n app.get<{ Params: { txHash: string } }>(\n '/wallet/transaction/:txHash',\n async (request, reply) => {\n const { txHash } = request.params;\n\n if (!/^0x[0-9a-fA-F]{64}$/.test(txHash)) {\n return reply.status(400).send({\n error: 'invalid_tx_hash',\n message: 'txHash must be a 0x-prefixed 32-byte hex string',\n });\n }\n\n const anvil =\n process.env['TOWNHOUSE_DEV_ANVIL_RPC'] ?? 'http://127.0.0.1:28545';\n try {\n const receipt: TransactionReceiptPayload = await getReceipt(\n anvil,\n txHash as `0x${string}`\n );\n return reply.status(200).send(receipt);\n } catch (e) {\n if (isRpcUnreachable(e)) {\n return reply.status(503).send({ error: 'rpc_unreachable' });\n }\n throw e;\n }\n }\n );\n}\n","/**\n * EVM transaction construction and broadcast helpers.\n * Uses viem for EIP-1559 tx construction, signing, and receipt polling.\n * SECURITY: private keys are never logged.\n */\n\nimport {\n createWalletClient,\n createPublicClient,\n defineChain,\n encodeFunctionData,\n http,\n parseAbi,\n type Hash,\n} from 'viem';\nimport { privateKeyToAccount } from 'viem/accounts';\nimport type { TransactionReceiptPayload } from '../api/types.js';\n\nfunction toViemPrivkey(raw: Uint8Array): `0x${string}` {\n const hex = Buffer.from(raw).toString('hex');\n return `0x${hex}` as `0x${string}`;\n}\n\n/** Build a viem chain object pinned to the runtime-fetched chainId so EIP-155\n * replay protection is enforced. Refusing `chain: null` is the whole point. */\nfunction buildChain(rpcUrl: string, chainId: number) {\n return defineChain({\n id: chainId,\n name: `evm-${chainId}`,\n nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },\n rpcUrls: { default: { http: [rpcUrl] } },\n });\n}\n\nconst ERC20_ABI = parseAbi([\n 'function transfer(address to, uint256 amount) returns (bool)',\n]);\n\nexport async function signAndBroadcastEthTransfer(\n rpcUrl: string,\n privateKey: Uint8Array,\n recipient: `0x${string}`,\n amount: bigint\n): Promise<{ txHash: Hash; chainId: number }> {\n const account = privateKeyToAccount(toViemPrivkey(privateKey));\n const transport = http(rpcUrl);\n\n const publicClient = createPublicClient({ transport });\n const chainId = await publicClient.getChainId();\n const chain = buildChain(rpcUrl, chainId);\n\n const walletClient = createWalletClient({ account, transport, chain });\n\n const txHash = await walletClient.sendTransaction({\n to: recipient,\n value: amount,\n chain,\n });\n\n return { txHash, chainId };\n}\n\nexport async function signAndBroadcastUsdcTransfer(\n rpcUrl: string,\n usdcAddress: `0x${string}`,\n privateKey: Uint8Array,\n recipient: `0x${string}`,\n amount: bigint\n): Promise<{ txHash: Hash; chainId: number }> {\n const account = privateKeyToAccount(toViemPrivkey(privateKey));\n const transport = http(rpcUrl);\n\n const publicClient = createPublicClient({ transport });\n const chainId = await publicClient.getChainId();\n const chain = buildChain(rpcUrl, chainId);\n\n const walletClient = createWalletClient({ account, transport, chain });\n\n const txHash = await walletClient.writeContract({\n address: usdcAddress,\n abi: ERC20_ABI,\n functionName: 'transfer',\n args: [recipient, amount],\n chain,\n });\n\n return { txHash, chainId };\n}\n\nexport async function getReceipt(\n rpcUrl: string,\n txHash: Hash\n): Promise<TransactionReceiptPayload> {\n const publicClient = createPublicClient({ transport: http(rpcUrl) });\n try {\n const receipt = await publicClient.getTransactionReceipt({ hash: txHash });\n if (!receipt) return { status: 'pending', txHash };\n return {\n status: receipt.status === 'success' ? 'success' : 'reverted',\n blockNumber: Number(receipt.blockNumber),\n txHash,\n };\n } catch (e) {\n // Receipt not found yet\n if (e instanceof Error && e.message.includes('not found')) {\n return { status: 'pending', txHash };\n }\n throw e;\n }\n}\n\nexport async function estimateNativeTransferGas(\n rpcUrl: string,\n fromAddress: `0x${string}`,\n recipient: `0x${string}`,\n amount: bigint\n): Promise<{ gas: string; fee: string }> {\n const publicClient = createPublicClient({ transport: http(rpcUrl) });\n const [gas, gasPrice] = await Promise.all([\n publicClient.estimateGas({\n account: fromAddress,\n to: recipient,\n value: amount,\n }),\n publicClient.getGasPrice(),\n ]);\n const fee = gas * gasPrice;\n return { gas: gas.toString(), fee: fee.toString() };\n}\n\n/** Estimate gas for an ERC-20 `transfer(to, amount)` call.\n * Native transfer is ~21k; ERC-20 transfer is ~50-65k — using the native\n * estimator for USDC under-reports the fee by ~3×. */\nexport async function estimateUsdcTransferGas(\n rpcUrl: string,\n fromAddress: `0x${string}`,\n usdcAddress: `0x${string}`,\n recipient: `0x${string}`,\n amount: bigint\n): Promise<{ gas: string; fee: string }> {\n const publicClient = createPublicClient({ transport: http(rpcUrl) });\n const data = encodeFunctionData({\n abi: ERC20_ABI,\n functionName: 'transfer',\n args: [recipient, amount],\n });\n const [gas, gasPrice] = await Promise.all([\n publicClient.estimateGas({ account: fromAddress, to: usdcAddress, data }),\n publicClient.getGasPrice(),\n ]);\n const fee = gas * gasPrice;\n return { gas: gas.toString(), fee: fee.toString() };\n}\n","/**\n * Shared config-mutation mutex.\n *\n * Serializes concurrent PATCH /api/nodes/:type/config and PATCH /api/transport\n * mutations so they cannot race on the same config.yaml file.\n */\n\nlet isMutating = false;\n\n/**\n * Synchronous test-and-set acquire of the mutex. Returns true on success,\n * false if already held.\n *\n * Safety: relies on the JavaScript event-loop running the if-check and the\n * assignment in the same synchronous tick. Do NOT introduce an `await`\n * between the read and the write or this guard becomes racy.\n */\nexport function acquireConfigMutex(): boolean {\n if (isMutating) return false;\n isMutating = true;\n return true;\n}\n\nexport function releaseConfigMutex(): void {\n isMutating = false;\n}\n\n/** Reset for testing. */\nexport function resetConfigMutex(): void {\n isMutating = false;\n}\n","/**\n * Node configuration mutation routes: PATCH /nodes/:type/config\n */\n\nimport type { FastifyInstance, FastifySchema } from 'fastify';\nimport type { ApiDeps, NodeType } from '../types.js';\nimport { validateConfig } from '../../config/validator.js';\nimport { saveConfig } from '../../config/loader.js';\nimport {\n acquireConfigMutex,\n releaseConfigMutex,\n resetConfigMutex as _resetConfigMutex,\n} from '../config-mutex.js';\n\n/** Request body for PATCH /nodes/:type/config */\ninterface ConfigPatchBody {\n feePerEvent?: number;\n feeBasisPoints?: number;\n feePerJob?: number;\n kindPricing?: Record<string, number>;\n enabled?: boolean;\n}\n\n/**\n * JSON Schema for PATCH body — rejects unknown keys (typos) and enforces\n * numeric fee ceiling at JS Number.MAX_SAFE_INTEGER (2^53-1). Per Task 3.1 +\n * Dev Note \"Standard Guards\".\n */\nconst patchBodySchema: FastifySchema = {\n body: {\n type: 'object',\n additionalProperties: false,\n properties: {\n feePerEvent: { type: 'number', minimum: 0, maximum: 9007199254740991 },\n feeBasisPoints: { type: 'number', minimum: 0, maximum: 9007199254740991 },\n feePerJob: { type: 'number', minimum: 0, maximum: 9007199254740991 },\n kindPricing: {\n type: 'object',\n // Restrict keys to numeric strings (positive integers) to prevent\n // prototype pollution and env-var-injection attacks via arbitrary\n // keys (e.g. '__proto__', '5094\\nFOO=bar') that flow into\n // KIND_PRICING_<key> orchestrator env vars.\n propertyNames: { pattern: '^[0-9]+$' },\n additionalProperties: {\n type: 'integer',\n minimum: 0,\n maximum: 9007199254740991,\n },\n },\n enabled: { type: 'boolean' },\n },\n },\n};\n\n/**\n * Register config mutation routes.\n */\nexport function registerConfigPatchRoutes(\n app: FastifyInstance,\n deps: ApiDeps\n): void {\n app.patch<{ Params: { type: string }; Body: ConfigPatchBody }>(\n '/nodes/:type/config',\n { schema: patchBodySchema },\n async (request, reply) => {\n const { type } = request.params;\n const body = request.body ?? {};\n\n // Validate type\n if (type !== 'town' && type !== 'mill' && type !== 'dvm') {\n return reply.status(404).send({\n error: 'unknown_node_type',\n type,\n });\n }\n\n // kindPricing is only valid for dvm\n if (body.kindPricing !== undefined && type !== 'dvm') {\n return reply.status(400).send({\n error: 'invalid_field',\n message: `kindPricing not supported for type=${type}`,\n });\n }\n\n // Check mutex\n if (!acquireConfigMutex()) {\n return reply.status(409).send({\n error: 'config_mutation_in_flight',\n });\n }\n\n try {\n // Use the live reference — mutations applied to `deps.config` persist across requests\n const currentConfig = deps.config;\n const nodeConfig = currentConfig.nodes[type as NodeType];\n if (!nodeConfig) {\n return reply.status(404).send({\n error: 'unknown_node_type',\n type,\n });\n }\n\n // Deep merge the body into current config. kindPricing merges\n // per-key so a partial PATCH (e.g. `{ kindPricing: { '5094': 7 } }`)\n // does not clobber other already-set kinds in the persisted config.\n const existingKindPricing =\n (nodeConfig as { kindPricing?: Record<string, number> })\n .kindPricing ?? undefined;\n const mergedKindPricing =\n body.kindPricing !== undefined\n ? { ...(existingKindPricing ?? {}), ...body.kindPricing }\n : existingKindPricing;\n\n const mergedConfig = {\n ...currentConfig,\n nodes: {\n ...currentConfig.nodes,\n [type]: {\n ...nodeConfig,\n ...body,\n ...(mergedKindPricing !== undefined\n ? { kindPricing: mergedKindPricing }\n : {}),\n },\n },\n };\n\n // Validate merged config\n try {\n validateConfig(mergedConfig);\n } catch (validationError) {\n return reply.status(400).send({\n error: 'config_validation_error',\n message:\n validationError instanceof Error\n ? validationError.message\n : 'Invalid configuration',\n });\n }\n\n // Persist to disk\n await saveConfig(deps.configPath, mergedConfig);\n\n // Update in-memory config so subsequent requests see the new state.\n // Mutate in place on the same object reference the rest of the app holds.\n deps.config.nodes = mergedConfig.nodes;\n\n // Determine orchestrator action\n const nodeType = type as NodeType;\n const oldEnabled = nodeConfig.enabled;\n const newEnabled =\n body.enabled !== undefined ? body.enabled : oldEnabled;\n\n // D2 resolution (2026-04-21): run BOTH if enabled flips AND fee fields change\n if (oldEnabled !== newEnabled) {\n // Enabled was flipped\n if (newEnabled) {\n await deps.orchestrator.addNode(nodeType);\n } else {\n await deps.orchestrator.removeNode(nodeType);\n }\n }\n\n // Also regenerate if fee fields changed (even if enabled also changed)\n if (\n body.feePerEvent !== undefined ||\n body.feeBasisPoints !== undefined ||\n body.feePerJob !== undefined ||\n body.kindPricing !== undefined\n ) {\n // Fee fields changed - regenerate connector config\n const activeTypes = Object.entries(mergedConfig.nodes)\n .filter(([, config]) => config.enabled)\n .map(([type]) => type as NodeType);\n\n await deps.orchestrator.regenerateConnectorConfig(activeTypes);\n }\n\n // Return updated config subset (per-type, typed safely)\n const u = mergedConfig.nodes[type as NodeType] as {\n enabled: boolean;\n feePerEvent?: number;\n feeBasisPoints?: number;\n feePerJob?: number;\n kindPricing?: Record<string, number>;\n };\n if (nodeType === 'town') {\n return { enabled: u.enabled, feePerEvent: u.feePerEvent };\n } else if (nodeType === 'mill') {\n return { enabled: u.enabled, feeBasisPoints: u.feeBasisPoints };\n } else {\n return {\n enabled: u.enabled,\n feePerJob: u.feePerJob,\n kindPricing: u.kindPricing,\n };\n }\n } finally {\n releaseConfigMutex();\n }\n }\n );\n}\n\n/**\n * Reset the mutation mutex (for testing).\n * Re-exported from config-mutex.ts for backward compatibility with existing tests.\n */\nexport { _resetConfigMutex as resetConfigMutex };\n","/**\n * WebSocket metrics route: WS /metrics\n *\n * Supports an optional `?subscribe=...` query parameter for relay-event subscriptions.\n * Format: `?subscribe=relayEvents:<nodeId>,relayEvents:<nodeId2>,...`\n * For each `relayEvents:<nodeId>` subscription, the server opens an upstream WebSocket\n * to the Town container's relay and forwards Nostr events to the client.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { WebSocket } from 'ws';\nimport { decode as decodeToon } from '@toon-format/toon';\nimport type { ApiDeps, WsMessage, NostrEventPayload } from '../types.js';\n\n/** Maximum buffer size before dropping old messages */\nconst MAX_BUFFER_SIZE = 100;\n\n/** Track open WebSocket connections for graceful shutdown (AC #10) */\nconst openWebSockets = new Set<WebSocket>();\n\n/** Get the set of open WebSocket connections (for server.ts close()) */\nexport function getOpenWebSockets(): Set<WebSocket> {\n return openWebSockets;\n}\n\n/** Flush interval for message batching (ms) */\nconst FLUSH_INTERVAL_MS = 100;\n\n/** Metrics poll interval (ms) */\nconst METRICS_POLL_INTERVAL_MS = 1000;\n\n/** Heartbeat interval (ms) */\nconst HEARTBEAT_INTERVAL_MS = 15000;\n\n/**\n * Parse `relayEvents:<nodeId>` subscription tokens from the `?subscribe=` query param.\n * Returns an array of nodeIds to subscribe to.\n */\nfunction parseRelayEventSubscriptions(queryString: string): string[] {\n if (!queryString) return [];\n const params = new URLSearchParams(queryString);\n const subscribeParam = params.get('subscribe');\n if (!subscribeParam) return [];\n\n const nodeIds: string[] = [];\n for (const token of subscribeParam.split(',')) {\n const trimmed = token.trim();\n if (trimmed.startsWith('relayEvents:')) {\n const nodeId = trimmed.slice('relayEvents:'.length);\n if (nodeId) nodeIds.push(nodeId);\n }\n }\n return nodeIds;\n}\n\n/**\n * Register WebSocket metrics route.\n */\nexport function registerMetricsWsRoutes(\n app: FastifyInstance,\n deps: ApiDeps\n): void {\n // Register websocket plugin handler\n app.get('/metrics', { websocket: true }, (socket, request) => {\n const logger = deps.logger ?? app.log;\n logger.info({ client: request.ip }, 'WebSocket client connected');\n\n // Track this connection for graceful shutdown\n openWebSockets.add(socket);\n\n // Per-socket message buffer\n const messageBuffer: WsMessage[] = [];\n\n // Track timers for cleanup\n const timers: NodeJS.Timeout[] = [];\n\n // Per-client upstream relay WebSocket connections: nodeId → WebSocket\n const upstreamSockets = new Map<string, WebSocket>();\n\n // ── relayEvents subscriptions ─────────────────────────────────────────────\n const rawQuery = request.url.includes('?')\n ? request.url.slice(request.url.indexOf('?') + 1)\n : '';\n const relayNodeIds = parseRelayEventSubscriptions(rawQuery);\n\n // Open upstream WS for each subscribed nodeId (async, non-blocking)\n if (relayNodeIds.length > 0) {\n void (async () => {\n for (const nodeId of relayNodeIds) {\n if (socket.readyState !== WebSocket.OPEN) break;\n try {\n const relayUrl =\n await deps.orchestrator.getNodeRelayEndpoint(nodeId);\n const upstream = new WebSocket(relayUrl);\n upstreamSockets.set(nodeId, upstream);\n\n // Track the latest event timestamp for incremental polling.\n // Start 60 s back to show recent events on connect.\n let sinceTs = Math.floor(Date.now() / 1000) - 60;\n // Dedup events already forwarded in this session. Capped to prevent\n // unbounded memory growth on long-lived connections to busy relays.\n const MAX_SEEN_IDS = 10_000;\n const seenEventIds = new Set<string>();\n const subId = `live-${nodeId}`;\n\n function sendReq() {\n if (upstream.readyState === WebSocket.OPEN) {\n upstream.send(\n JSON.stringify([\n 'REQ',\n subId,\n {\n kinds: [0, 1, 6, 7, 9735],\n since: sinceTs,\n },\n ])\n );\n }\n }\n\n // Subscribe for live events once the upstream relay accepts the connection.\n // Also poll every 5 s via re-REQ so events stored via /handle-packet (which\n // currently do not trigger broadcastEvent in older relay builds) are surfaced.\n let pollTimer: NodeJS.Timeout | null = null;\n upstream.on('open', () => {\n sendReq();\n pollTimer = setInterval(sendReq, 5_000);\n });\n\n upstream.on('message', (data: Buffer | string) => {\n if (socket.readyState !== WebSocket.OPEN) return;\n try {\n const msg = JSON.parse(data.toString()) as unknown;\n let payload: NostrEventPayload | undefined;\n\n if (Array.isArray(msg) && msg[0] === 'EVENT' && msg[2]) {\n // Real relay: NIP-01 [\"EVENT\", sub_id, toon_string]\n payload = decodeToon(\n msg[2] as string\n ) as unknown as NostrEventPayload;\n } else if (\n msg !== null &&\n typeof msg === 'object' &&\n !Array.isArray(msg)\n ) {\n // Test stub: raw JSON event object\n payload = msg as NostrEventPayload;\n }\n\n if (payload) {\n const eventId = (payload as { id?: string }).id ?? '';\n if (eventId && seenEventIds.has(eventId)) return; // dedup\n if (eventId) {\n seenEventIds.add(eventId);\n if (seenEventIds.size > MAX_SEEN_IDS) {\n const oldest = seenEventIds.values().next().value;\n if (oldest !== undefined) seenEventIds.delete(oldest);\n }\n }\n // Advance sinceTs so the next poll only fetches newer events.\n const createdAt = (payload as { created_at?: number })\n .created_at;\n if (typeof createdAt === 'number' && createdAt >= sinceTs) {\n sinceTs = createdAt;\n }\n addToBuffer({\n type: 'relayEvents',\n nodeId,\n payload,\n ts: Date.now(),\n });\n }\n } catch {\n // Malformed or non-event message from upstream relay — skip\n }\n });\n\n upstream.on('error', (err) => {\n logger.warn({ err, nodeId }, 'Upstream relay WS error');\n });\n\n upstream.on('close', () => {\n if (pollTimer) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n upstreamSockets.delete(nodeId);\n // Notify the dashboard client so it can surface the AC-7 error UI\n // instead of silently showing an empty \"No events yet\" feed.\n addToBuffer({\n type: 'relayEventsStatus',\n nodeId,\n connected: false,\n ts: Date.now(),\n });\n });\n } catch (err) {\n logger.warn({ err, nodeId }, 'Failed to open upstream relay WS');\n }\n }\n })();\n }\n\n // ── Metrics poll ──────────────────────────────────────────────────────────\n let metricsPollPending = false;\n const metricsTimer = setInterval(async () => {\n if (metricsPollPending) {\n return; // Skip this poll, previous one still in flight\n }\n metricsPollPending = true;\n try {\n const metricsRes = await deps.connectorAdmin.getMetrics();\n if (metricsRes) {\n // ConnectorAdminClient.getMetrics() returns the connector's\n // /admin/metrics.json shape; aggregate counters live under `aggregate`.\n const payload = {\n packetsForwarded: metricsRes.aggregate.packetsForwarded,\n packetsRejected: metricsRes.aggregate.packetsRejected,\n bytesSent: metricsRes.aggregate.bytesSent,\n attribution: 'aggregate' as const,\n available: true,\n };\n addToBuffer({\n type: 'metrics',\n payload,\n ts: Date.now(),\n });\n }\n } catch {\n // Connector down or /metrics not available — add unavailable marker\n addToBuffer({\n type: 'metrics',\n payload: {\n packetsForwarded: 0,\n packetsRejected: 0,\n bytesSent: 0,\n attribution: 'aggregate',\n available: false,\n },\n ts: Date.now(),\n });\n } finally {\n metricsPollPending = false;\n }\n }, METRICS_POLL_INTERVAL_MS);\n timers.push(metricsTimer);\n\n // ── Container state event listeners ───────────────────────────────────────\n\n const onContainerState = (data: { name: string; state: string }) => {\n addToBuffer({\n type: 'nodeState',\n payload: data,\n ts: Date.now(),\n });\n };\n deps.orchestrator.on('containerState', onContainerState);\n\n // Pull progress events\n const onPullProgress = (data: {\n image: string;\n status: string;\n progress?: string;\n }) => {\n addToBuffer({\n type: 'nodeState',\n payload: { name: `pull:${data.image}`, state: data.status },\n ts: Date.now(),\n });\n };\n deps.orchestrator.on('pullProgress', onPullProgress);\n\n // Connector restart events (AC-12 in story 21.10)\n const onConnectorRestarting = () => {\n addToBuffer({\n type: 'connectorRestarting',\n ts: Date.now(),\n });\n };\n deps.orchestrator.on('connectorRestarting', onConnectorRestarting);\n\n const onConnectorRestarted = () => {\n addToBuffer({\n type: 'connectorRestarted',\n ts: Date.now(),\n });\n // Also emit legacy nodeState for backward compat with older clients\n addToBuffer({\n type: 'nodeState',\n payload: { name: 'connector', state: 'restarted' },\n ts: Date.now(),\n });\n };\n deps.orchestrator.on('connectorRestarted', onConnectorRestarted);\n\n // ── Heartbeat ─────────────────────────────────────────────────────────────\n\n const heartbeatTimer = setInterval(() => {\n addToBuffer({\n type: 'heartbeat',\n ts: Date.now(),\n });\n }, HEARTBEAT_INTERVAL_MS);\n timers.push(heartbeatTimer);\n\n // ── Flush ─────────────────────────────────────────────────────────────────\n\n const flushTimer = setInterval(() => {\n flushBuffer(socket);\n }, FLUSH_INTERVAL_MS);\n timers.push(flushTimer);\n\n // Add message to buffer with backpressure handling\n function addToBuffer(message: WsMessage): void {\n messageBuffer.push(message);\n\n // If buffer exceeds max, drop oldest metrics (keep latest)\n if (messageBuffer.length > MAX_BUFFER_SIZE) {\n const idx = messageBuffer.findIndex((m) => m.type === 'metrics');\n if (idx >= 0) {\n messageBuffer.splice(idx, 1);\n } else {\n messageBuffer.shift();\n }\n }\n }\n\n // Flush buffer with batching logic\n function flushBuffer(_ws: WebSocket): void {\n if (messageBuffer.length === 0) {\n return;\n }\n\n if (socket.readyState !== WebSocket.OPEN) {\n return;\n }\n\n if (messageBuffer.length === 1) {\n socket.send(JSON.stringify(messageBuffer[0]));\n } else {\n // Batch multiple messages\n const batch: WsMessage = {\n type: 'batch',\n messages: [...messageBuffer],\n ts: Date.now(),\n };\n socket.send(JSON.stringify(batch));\n }\n\n messageBuffer.length = 0;\n }\n\n // ── Incoming messages (unsubscribe) ──────────────────────────────────────\n\n socket.on('message', (data: Buffer | string) => {\n try {\n const msg = JSON.parse(data.toString()) as {\n type?: string;\n nodeId?: string;\n };\n if (msg.type === 'unsubscribe' && typeof msg.nodeId === 'string') {\n const upstream = upstreamSockets.get(msg.nodeId);\n if (upstream) {\n try {\n upstream.close();\n } catch {\n /* best-effort */\n }\n upstreamSockets.delete(msg.nodeId);\n }\n }\n } catch {\n // Malformed control message — ignore\n }\n });\n\n // ── Cleanup on disconnect ─────────────────────────────────────────────────\n\n socket.on('close', () => {\n logger.info({ client: request.ip }, 'WebSocket client disconnected');\n\n // Remove from tracking set\n openWebSockets.delete(socket);\n\n // Clear all timers\n for (const timer of timers) {\n clearInterval(timer);\n }\n\n // Remove orchestrator event listeners\n deps.orchestrator.off('containerState', onContainerState);\n deps.orchestrator.off('pullProgress', onPullProgress);\n deps.orchestrator.off('connectorRestarting', onConnectorRestarting);\n deps.orchestrator.off('connectorRestarted', onConnectorRestarted);\n\n // Close all upstream relay WebSocket connections\n for (const [, ws] of upstreamSockets) {\n try {\n ws.close();\n } catch {\n // best-effort\n }\n }\n upstreamSockets.clear();\n });\n\n // Handle socket errors\n socket.on('error', (error) => {\n logger.error({ err: error, client: request.ip }, 'WebSocket error');\n });\n });\n}\n","/**\n * Wizard API routes: GET /wizard/state, POST /wizard/mnemonic-preview,\n * POST /wizard/init, WS /wizard/progress.\n *\n * SECURITY: Mnemonic and password are never logged, never stored in module scope.\n */\n\nimport { existsSync, unlinkSync, chmodSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { FastifyInstance } from 'fastify';\nimport type { IncomingMessage } from 'node:http';\nimport { WebSocket } from 'ws';\nimport { generateMnemonic, validateMnemonic } from '@scure/bip39';\nimport { wordlist } from '@scure/bip39/wordlists/english.js';\nimport type { WizardInitRequest, WizardProgressMessage } from '../types.js';\nimport {\n WalletManager,\n encryptWallet,\n saveWallet,\n} from '../../wallet/index.js';\nimport { saveConfig } from '../../config/loader.js';\nimport { getDefaultConfig } from '../../config/defaults.js';\nimport type { TownhouseConfig } from '../../config/schema.js';\nimport type { NodeType } from '../../docker/types.js';\n\nexport interface WizardDeps {\n configPath: string;\n walletPath: string;\n}\n\nexport interface WizardTransitionState {\n mode: 'wizard' | 'normal';\n /** Buffered progress messages for late-connecting WS clients (wizard mode only) */\n progressBuffer?: WizardProgressMessage[];\n /** Active WS connections to forward events to (wizard mode only) */\n progressSockets?: Set<WebSocket>;\n /** Single in-flight init guard — prevents concurrent POST /wizard/init from racing past existsSync */\n initInFlight?: boolean;\n}\n\nexport type OnInitCallback = (\n config: TownhouseConfig,\n wallet: WalletManager,\n profiles: NodeType[]\n) => Promise<void>;\n\n/** Cap progress buffer to bound memory during long Docker pulls */\nexport const PROGRESS_BUFFER_MAX = 200;\n\n/** Allowed Origin hostnames for cross-origin WS upgrades on the wizard */\nconst ALLOWED_WS_ORIGIN_HOSTS = new Set([\n 'localhost',\n '127.0.0.1',\n '[::1]',\n '::1',\n]);\n\nfunction isAllowedWsOrigin(origin: string | undefined): boolean {\n if (!origin) return true; // same-origin WS request has no Origin header in some clients; the OS-level loopback bind already restricts\n try {\n const url = new URL(origin);\n return ALLOWED_WS_ORIGIN_HOSTS.has(url.hostname);\n } catch {\n return false;\n }\n}\n\n/**\n * Register wizard-scoped routes.\n * In 'wizard' mode: all wizard routes are active.\n * In 'normal' mode: only GET /wizard/state returns normal-mode payload; other routes refuse.\n */\nexport function registerWizardRoutes(\n app: FastifyInstance,\n deps: WizardDeps,\n state: WizardTransitionState,\n onInit?: OnInitCallback\n): void {\n // GET /wizard/state — registered in BOTH wizard and normal mode\n app.get('/wizard/state', async (_request, reply) => {\n const configExists = existsSync(deps.configPath);\n const walletExists = existsSync(deps.walletPath);\n // `containers_running` reflects whether the wizard server has transitioned\n // to normal mode (i.e., orchestrator.up() resolved at least once). It does\n // NOT track live container health — a container that dies post-transition\n // will not flip this back to false. The SPA uses this to know it can navigate\n // off /wizard, not as a liveness indicator.\n const containersRunning = state.mode === 'normal';\n\n return reply.status(200).send({\n config_exists: configExists,\n wallet_exists: walletExists,\n containers_running: containersRunning,\n mode: state.mode,\n ts: Date.now(),\n });\n });\n\n // POST /wizard/mnemonic-preview — stateless preview; disabled after transition\n app.post('/wizard/mnemonic-preview', async (_request, reply) => {\n if (state.mode === 'normal') {\n return reply.status(503).send({ error: 'wizard_already_completed' });\n }\n // SECURITY: mnemonic generated fresh per request, never logged, never stored\n const mnemonic = generateMnemonic(wordlist, 128);\n return reply.status(200).send({ mnemonic });\n });\n\n // POST /wizard/init — validate, write wallet + config, fire async launch\n app.post('/wizard/init', async (request, reply) => {\n if (state.mode === 'normal') {\n return reply.status(409).send({\n code: 'wizard_already_completed',\n message: 'Setup is already complete.',\n });\n }\n\n // Concurrent-init guard: serialize against double-clicks and parallel POSTs.\n // The `wallet.enc` write below also uses O_EXCL ('wx') as a TOCTOU backstop.\n if (state.initInFlight) {\n return reply.status(409).send({\n code: 'init_in_flight',\n message: 'A setup is already in progress.',\n });\n }\n state.initInFlight = true;\n\n try {\n const body = request.body as Partial<WizardInitRequest> | null;\n if (!body || typeof body !== 'object') {\n return reply\n .status(400)\n .send({ code: 'invalid_request', message: 'Request body required.' });\n }\n\n // Validate password — boundary-trim trailing whitespace check; passwords with leading/trailing\n // whitespace are silently corrupted by browser autofill and cannot be decrypted later.\n const password = body.password;\n if (\n typeof password !== 'string' ||\n password.length === 0 ||\n password.length > 256\n ) {\n return reply.status(400).send({\n code: 'password_invalid',\n message: 'password must be 1–256 characters.',\n });\n }\n if (password !== password.trim()) {\n return reply.status(400).send({\n code: 'password_invalid',\n message: 'password cannot have leading or trailing whitespace.',\n });\n }\n if (password !== body.password_confirm) {\n return reply.status(400).send({\n code: 'password_mismatch',\n message: 'Passwords do not match.',\n });\n }\n\n // Validate mnemonic_mode\n const mnemonicMode = body.mnemonic_mode;\n if (mnemonicMode !== 'generate' && mnemonicMode !== 'import') {\n return reply.status(400).send({\n code: 'mnemonic_mode_invalid',\n message: 'mnemonic_mode must be \"generate\" or \"import\".',\n });\n }\n\n // Validate mnemonic (both modes require a valid phrase — server validates regardless of source)\n const mnemonic = body.mnemonic;\n if (\n !mnemonic ||\n typeof mnemonic !== 'string' ||\n mnemonic.trim().length === 0\n ) {\n return reply\n .status(400)\n .send({ code: 'mnemonic_invalid', message: 'mnemonic is required.' });\n }\n if (!validateMnemonic(mnemonic.trim(), wordlist)) {\n return reply.status(400).send({\n code: 'mnemonic_invalid',\n message: 'Invalid BIP-39 mnemonic.',\n });\n }\n const cleanMnemonic = mnemonic.trim();\n\n // backup_ack enforcement (Risk R-022) — applies to both generate and import modes\n if (body.backup_ack !== true) {\n return reply.status(400).send({\n code: 'backup_not_acknowledged',\n message:\n 'You must confirm you have backed up your seed phrase before continuing.',\n });\n }\n\n // Validate nodes\n const nodes = body.nodes;\n if (!nodes || typeof nodes !== 'object') {\n return reply\n .status(400)\n .send({ code: 'no_nodes_selected', message: 'nodes is required.' });\n }\n const atLeastOne =\n nodes.town?.enabled || nodes.mill?.enabled || nodes.dvm?.enabled;\n if (!atLeastOne) {\n return reply.status(400).send({\n code: 'no_nodes_selected',\n message: 'At least one node must be enabled.',\n });\n }\n\n // Validate fee ranges\n if (nodes.town?.enabled && nodes.town.feePerEvent !== undefined) {\n if (\n !Number.isInteger(nodes.town.feePerEvent) ||\n nodes.town.feePerEvent < 0 ||\n nodes.town.feePerEvent > 1000\n ) {\n return reply.status(400).send({\n code: 'fee_out_of_range',\n message: 'nodes.town.feePerEvent must be 0–1000.',\n });\n }\n }\n if (nodes.mill?.enabled && nodes.mill.feeBasisPoints !== undefined) {\n if (\n !Number.isInteger(nodes.mill.feeBasisPoints) ||\n nodes.mill.feeBasisPoints < 0 ||\n nodes.mill.feeBasisPoints > 100\n ) {\n return reply.status(400).send({\n code: 'fee_out_of_range',\n message: 'nodes.mill.feeBasisPoints must be 0–100.',\n });\n }\n }\n if (nodes.dvm?.enabled && nodes.dvm.feePerJob !== undefined) {\n if (\n !Number.isInteger(nodes.dvm.feePerJob) ||\n nodes.dvm.feePerJob < 0 ||\n nodes.dvm.feePerJob > 100000\n ) {\n return reply.status(400).send({\n code: 'fee_out_of_range',\n message: 'nodes.dvm.feePerJob must be 0–100000.',\n });\n }\n }\n\n // Validate transport\n const transport = body.transport;\n if (\n !transport ||\n (transport.mode !== 'direct' && transport.mode !== 'ator')\n ) {\n return reply.status(400).send({\n code: 'transport_invalid',\n message: 'transport.mode must be \"direct\" or \"ator\".',\n });\n }\n\n // Conflict checks — TOCTOU-resilient: the wallet.enc write below uses O_EXCL ('wx').\n if (existsSync(deps.walletPath)) {\n return reply.status(409).send({\n code: 'wallet_already_exists',\n message: `A wallet already exists at ${deps.walletPath}. Delete it first.`,\n });\n }\n if (existsSync(deps.configPath)) {\n return reply.status(409).send({\n code: 'config_already_exists',\n message: `A config already exists at ${deps.configPath}. Delete it first.`,\n });\n }\n\n // Create + save wallet. saveWallet writes with mode 0o600 already.\n // Concurrent inits are serialized by `state.initInFlight` above; a stray\n // external process writing wallet.enc between existsSync and saveWallet\n // is an accepted edge case for v1 (single-machine localhost wizard).\n const walletManager = new WalletManager({\n encryptedPath: deps.walletPath,\n });\n await walletManager.fromMnemonic(cleanMnemonic);\n // SECURITY: encrypted immediately, plaintext mnemonic leaves scope after this call\n const encrypted = encryptWallet(cleanMnemonic, password);\n await saveWallet(deps.walletPath, encrypted);\n // Defensive chmod (saveWallet already sets 0o600 but a hostile umask on\n // exotic platforms could still produce a too-open file; cheap to assert).\n try {\n chmodSync(deps.walletPath, 0o600);\n } catch {\n /* best-effort */\n }\n\n // Build + save config — if this throws, roll back the wallet write.\n let config: TownhouseConfig;\n try {\n config = buildConfigFromRequest(\n body as WizardInitRequest,\n deps.configPath\n );\n saveConfig(deps.configPath, config);\n } catch (err) {\n try {\n unlinkSync(deps.walletPath);\n } catch {\n /* best-effort */\n }\n throw err;\n }\n\n // Return 202 before async launch — reply is sent first\n await reply.status(202).send({ status: 'launching' });\n\n // Fire-and-forget: transition to normal mode + start orchestrator.\n // On failure, roll back wallet+config so the operator can retry without\n // hitting 409 wallet_already_exists / config_already_exists.\n if (onInit) {\n const profiles: NodeType[] = [];\n if (nodes.town?.enabled) profiles.push('town');\n if (nodes.mill?.enabled) profiles.push('mill');\n if (nodes.dvm?.enabled) profiles.push('dvm');\n\n onInit(config, walletManager, profiles).catch((err: unknown) => {\n app.log.error({ err }, 'Wizard launch failed');\n try {\n unlinkSync(deps.walletPath);\n } catch {\n /* best-effort */\n }\n try {\n unlinkSync(deps.configPath);\n } catch {\n /* best-effort */\n }\n // Allow a fresh retry: clear the in-flight flag so the next POST passes the guard.\n state.initInFlight = false;\n const errMsg: WizardProgressMessage = {\n type: 'error',\n message: err instanceof Error ? err.message : String(err),\n ts: Date.now(),\n };\n if (state.progressBuffer) {\n state.progressBuffer.push(errMsg);\n if (state.progressBuffer.length > PROGRESS_BUFFER_MAX) {\n state.progressBuffer.splice(\n 0,\n state.progressBuffer.length - PROGRESS_BUFFER_MAX\n );\n }\n }\n if (state.progressSockets) {\n for (const socket of state.progressSockets) {\n try {\n if (socket.readyState === WebSocket.OPEN) {\n socket.send(JSON.stringify(errMsg));\n }\n } catch {\n /* best-effort */\n }\n }\n }\n });\n }\n\n return reply;\n } finally {\n // The success path keeps initInFlight=true to block double-submits while\n // the orchestrator boots; only an error in onInit (above) clears it. If\n // we never reached the onInit branch (e.g., 4xx validation), clear here.\n // We detect this by checking whether reply was already sent with 202.\n // Simpler: the outer success path sets it; validation failures must reset.\n const sent = reply.statusCode;\n if (sent !== 202) {\n state.initInFlight = false;\n }\n }\n });\n\n // WS /wizard/progress — only active in wizard mode (progress sockets are wizard-only).\n // CSWSH defense: enforce Origin header allowlist on upgrade.\n app.get('/wizard/progress', { websocket: true }, (socket, req) => {\n const origin = (req.raw as IncomingMessage).headers?.origin;\n if (!isAllowedWsOrigin(origin)) {\n try {\n socket.close(1008, 'origin_not_allowed');\n } catch {\n /* best-effort */\n }\n return;\n }\n\n const sockets = state.progressSockets;\n if (!sockets) {\n // Normal mode: close immediately (wizard is complete)\n socket.close(1001, 'wizard_complete');\n return;\n }\n\n sockets.add(socket);\n\n // Replay buffered messages for late-connecting clients\n if (state.progressBuffer) {\n for (const msg of state.progressBuffer) {\n try {\n socket.send(JSON.stringify(msg));\n } catch {\n /* best-effort */\n }\n }\n }\n\n socket.on('close', () => {\n sockets.delete(socket);\n });\n\n socket.on('error', () => {\n sockets.delete(socket);\n });\n });\n}\n\n/**\n * Build a TownhouseConfig from a WizardInitRequest by merging with defaults.\n * Uses path.dirname/join for cross-platform path handling.\n */\nexport function buildConfigFromRequest(\n request: WizardInitRequest,\n configPath: string\n): TownhouseConfig {\n const config = getDefaultConfig();\n\n // Point wallet path at the same directory as config — works on POSIX and Windows.\n const configDir = dirname(configPath);\n config.wallet.encrypted_path = join(configDir, 'wallet.enc');\n\n // Apply node selections and fees\n config.nodes.town.enabled = request.nodes.town.enabled;\n if (\n request.nodes.town.enabled &&\n request.nodes.town.feePerEvent !== undefined\n ) {\n config.nodes.town.feePerEvent = request.nodes.town.feePerEvent;\n }\n\n config.nodes.mill.enabled = request.nodes.mill.enabled;\n if (\n request.nodes.mill.enabled &&\n request.nodes.mill.feeBasisPoints !== undefined\n ) {\n config.nodes.mill.feeBasisPoints = request.nodes.mill.feeBasisPoints;\n }\n\n config.nodes.dvm.enabled = request.nodes.dvm.enabled;\n if (request.nodes.dvm.enabled && request.nodes.dvm.feePerJob !== undefined) {\n config.nodes.dvm.feePerJob = request.nodes.dvm.feePerJob;\n }\n\n // Apply transport\n config.transport.mode = request.transport.mode;\n\n return config;\n}\n","/**\n * Transport configuration routes.\n *\n * GET /api/transport — live transport status (mode, reachability, latency)\n * PATCH /api/transport — flip transport mode + trigger connector restart\n */\n\nimport type { FastifyInstance, FastifySchema } from 'fastify';\nimport type {\n ApiDeps,\n NodeType,\n TransportStatusPayload,\n TransportPatchRequest,\n TransportPatchResponse,\n} from '../types.js';\nimport { validateConfig } from '../../config/validator.js';\nimport { saveConfig } from '../../config/loader.js';\nimport { acquireConfigMutex, releaseConfigMutex } from '../config-mutex.js';\n\nconst DEFAULT_ATOR_PROXY = 'socks5h://proxy.ator.io:9050';\n\nexport interface RegisterTransportOptions {\n /**\n * 'wizard' — registers GET only (no PATCH at all). Caller must call\n * registerTransportPatchRoute() after wizard transition completes.\n * 'patch-only'— registers PATCH only (used by the wizard-to-normal transition).\n * 'normal' — registers both GET and PATCH (the standalone-server case).\n */\n mode?: 'normal' | 'wizard' | 'patch-only';\n}\n\n/** Normalize a SOCKS5 URL for byte-comparable equality (trailing slash, casing). */\nfunction normalizeProxyUrl(url: string | undefined): string | undefined {\n if (!url) return undefined;\n try {\n return new URL(url).toString();\n } catch {\n return url;\n }\n}\n\nconst patchBodySchema: FastifySchema = {\n body: {\n type: 'object',\n additionalProperties: false,\n required: ['mode'],\n properties: {\n mode: { type: 'string', enum: ['direct', 'ator'] },\n socksProxy: { type: 'string', minLength: 1, maxLength: 2048 },\n },\n },\n};\n\n/**\n * Register transport routes on the given Fastify instance.\n */\nexport function registerTransportRoutes(\n app: FastifyInstance,\n deps: ApiDeps,\n opts: RegisterTransportOptions = {}\n): void {\n const { mode = 'normal' } = opts;\n\n // ── GET /api/transport ────────────────────────────────────────────────────\n // Skipped for 'patch-only' mode (caller already registered GET earlier).\n if (mode !== 'patch-only') {\n app.get('/api/transport', async (_request, reply) => {\n // Read deps.transportProbe per request — the wizard server swaps the\n // probe instance on transition, so we cannot capture it at registration time.\n const probeStatus = deps.transportProbe.getStatus();\n const configTransport = deps.config.transport;\n\n const payload: TransportStatusPayload = {\n mode: configTransport.mode,\n reachable:\n configTransport.mode === 'direct' ? true : probeStatus.reachable,\n latencyProxyMs:\n configTransport.mode === 'direct' ? null : probeStatus.latencyProxyMs,\n latencyDirectMs:\n configTransport.mode === 'direct'\n ? null\n : probeStatus.latencyDirectMs,\n lastProbedAt: probeStatus.lastProbedAt,\n probeError:\n configTransport.mode === 'direct' ? null : probeStatus.probeError,\n ts: Date.now(),\n };\n\n if (configTransport.mode === 'ator') {\n payload.socksProxy = configTransport.socksProxy ?? DEFAULT_ATOR_PROXY;\n }\n\n return reply.status(200).send(payload);\n });\n }\n\n // ── PATCH /api/transport ──────────────────────────────────────────────────\n // Wizard mode: GET only — PATCH is added later via registerTransportRoutes\n // with mode 'patch-only' once the wizard transitions to normal.\n if (mode === 'wizard') {\n return;\n }\n\n // Probe handle for PATCH operations. Stable: PATCH is only registered for\n // the deps object the caller intends to mutate transport against.\n const probe = deps.transportProbe;\n\n app.patch<{ Body: TransportPatchRequest }>(\n '/api/transport',\n { schema: patchBodySchema },\n async (request, reply) => {\n const body = request.body;\n\n // Reject socksProxy when mode is direct — silent ignore is ambiguous to the caller\n if (body.mode === 'direct' && body.socksProxy !== undefined) {\n return reply.status(400).send({\n error: 'invalid_body',\n message: 'socksProxy is not allowed when mode is direct',\n });\n }\n\n // Validate socksProxy URL format if provided\n if (body.socksProxy !== undefined) {\n try {\n const u = new URL(body.socksProxy);\n if (u.protocol !== 'socks5:' && u.protocol !== 'socks5h:') {\n return reply.status(400).send({\n error: 'invalid_socksProxy',\n message: 'socksProxy must use socks5:// or socks5h:// scheme',\n });\n }\n if (!u.hostname) {\n return reply.status(400).send({\n error: 'invalid_socksProxy',\n message: 'socksProxy must have a hostname',\n });\n }\n if (u.username || u.password) {\n return reply.status(400).send({\n error: 'invalid_socksProxy',\n message: 'socksProxy must not include credentials in the URL',\n });\n }\n if (u.pathname && u.pathname !== '/') {\n return reply.status(400).send({\n error: 'invalid_socksProxy',\n message: 'socksProxy must not include a path',\n });\n }\n if (!u.port) {\n return reply.status(400).send({\n error: 'invalid_socksProxy',\n message: 'socksProxy must specify a port',\n });\n }\n const portNum = Number(u.port);\n if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) {\n return reply.status(400).send({\n error: 'invalid_socksProxy',\n message: 'socksProxy port must be in range 1-65535',\n });\n }\n } catch {\n return reply.status(400).send({\n error: 'invalid_socksProxy',\n message: 'socksProxy must be a valid URL',\n });\n }\n }\n\n const prevMode = deps.config.transport.mode;\n const prevSocksProxy = deps.config.transport.socksProxy;\n const newMode = body.mode;\n const newSocksProxy =\n newMode === 'ator'\n ? (body.socksProxy ?? prevSocksProxy ?? DEFAULT_ATOR_PROXY)\n : undefined;\n\n // No-op detection: same mode and (for ATOR) URL-normalized same proxy\n const noOp =\n prevMode === newMode &&\n (newMode === 'direct' ||\n normalizeProxyUrl(prevSocksProxy) ===\n normalizeProxyUrl(newSocksProxy));\n\n if (noOp) {\n const noOpResponse: TransportPatchResponse = {\n mode: newMode,\n ...(newMode === 'ator' ? { socksProxy: newSocksProxy } : {}),\n restartTriggered: false,\n };\n return reply.status(200).send(noOpResponse);\n }\n\n // Acquire shared config mutex\n if (!acquireConfigMutex()) {\n return reply.status(409).send({ error: 'config_mutation_in_flight' });\n }\n\n // Snapshot the prior probe URL so a failed flip can restore it.\n const priorProbeUrl =\n prevMode === 'ator' ? (prevSocksProxy ?? DEFAULT_ATOR_PROXY) : '';\n\n // Snapshot the full prior transport block so a failed flip can restore\n // exactly what the operator had — not just mode + socksProxy.\n // hiddenService / externalUrl / relayHiddenService are operator-managed\n // fields that the YAML may have set up independently (story 7e28ea9);\n // the PATCH must preserve them across mode flips, otherwise toggling\n // direct→ator→direct would silently strip the hidden-service setup.\n const priorTransport = { ...deps.config.transport };\n\n try {\n // Mutate in-memory config — carry forward all non-mode fields, then\n // override mode and socksProxy per the request.\n const {\n mode: _droppedMode,\n socksProxy: _droppedProxy,\n ...carryOver\n } = priorTransport;\n deps.config.transport = {\n ...carryOver,\n mode: newMode,\n ...(newMode === 'ator' ? { socksProxy: newSocksProxy } : {}),\n };\n\n // Defensive round-trip validation\n try {\n validateConfig(deps.config);\n } catch (validationError) {\n // Roll back in-memory edit (restore the FULL prior block — preserves\n // hiddenService/externalUrl/relayHiddenService).\n deps.config.transport = priorTransport;\n return reply.status(500).send({\n error: 'config_validation_error',\n message:\n validationError instanceof Error\n ? validationError.message\n : 'Invalid configuration',\n });\n }\n\n // Persist to disk — if this fails, restore in-memory state before bailing.\n try {\n await saveConfig(deps.configPath, deps.config);\n } catch (saveError) {\n deps.config.transport = priorTransport;\n return reply.status(500).send({\n error: 'config_save_failed',\n message:\n saveError instanceof Error\n ? saveError.message\n : 'Failed to persist config',\n });\n }\n\n // Compute active nodes\n const activeNodes = Object.entries(deps.config.nodes)\n .filter(([, cfg]) => cfg.enabled)\n .map(([t]) => t as NodeType);\n\n // Trigger connector restart\n try {\n await deps.orchestrator.regenerateConnectorConfig(activeNodes);\n } catch (restartError) {\n // Rollback: restore in-memory config and persist the restoration\n deps.config.transport = priorTransport;\n try {\n await saveConfig(deps.configPath, deps.config);\n } catch {\n // Best-effort rollback of disk write — if this fails, system is in\n // a bad state but we can't do anything further here.\n }\n // Restore probe to its prior target as well so the dashboard\n // doesn't keep reporting reachability for the failed-flip URL.\n try {\n probe.setProxyUrl(priorProbeUrl);\n if (prevMode === 'ator') {\n probe.start();\n } else {\n probe.stop();\n }\n } catch {\n /* best-effort */\n }\n return reply.status(500).send({\n error: 'connector_restart_failed',\n message:\n restartError instanceof Error\n ? restartError.message\n : 'Connector restart failed',\n });\n }\n\n // Update probe. ATOR→ATOR with a different proxy must restart the\n // probe loop so the new URL is adopted immediately rather than at\n // the next 30 s tick.\n try {\n if (newMode === 'ator') {\n const newProbeUrl = newSocksProxy ?? DEFAULT_ATOR_PROXY;\n if (prevMode === 'ator') {\n probe.stop();\n }\n probe.setProxyUrl(newProbeUrl);\n probe.start();\n } else {\n probe.stop();\n }\n } catch (probeError) {\n // The connector restart already succeeded — log and continue.\n const msg =\n probeError instanceof Error\n ? probeError.message\n : String(probeError);\n request.log.warn(`transport probe update after flip failed: ${msg}`);\n }\n\n const restartedAt = Date.now();\n const successResponse: TransportPatchResponse = {\n mode: newMode,\n ...(newMode === 'ator' ? { socksProxy: newSocksProxy } : {}),\n restartTriggered: true,\n restartedAt,\n };\n return reply.status(200).send(successResponse);\n } finally {\n releaseConfigMutex();\n }\n }\n );\n}\n","/**\n * API Server Factory.\n *\n * SECURITY: Only binds to loopback address by default (localhost-only for v1).\n * Set TOWNHOUSE_API_ALLOW_REMOTE=1 to override this security boundary.\n */\n\nimport { WebSocket } from 'ws';\nimport { buildFastifyApp } from './build-app.js';\nimport type { ApiServer, ApiDeps } from './types.js';\nimport { registerNodeRoutes } from './routes/nodes.js';\nimport { registerWalletRoutes } from './routes/wallet.js';\nimport { registerWalletBalancesRoutes } from './routes/wallet-balances.js';\nimport { registerWalletRevealRoutes } from './routes/wallet-reveal.js';\nimport { registerWalletWithdrawRoutes } from './routes/wallet-withdraw.js';\nimport { registerConfigPatchRoutes } from './routes/nodes-patch.js';\nimport {\n registerMetricsWsRoutes,\n getOpenWebSockets,\n} from './routes/metrics-ws.js';\nimport { registerWizardRoutes } from './routes/wizard.js';\nimport { registerTransportRoutes } from './routes/transport.js';\n\n/**\n * Create the Fastify API server. Caller MUST supply a `transportProbe` in\n * `deps` (constructed from the config and started if mode === 'ator').\n */\nexport async function createApiServer(deps: ApiDeps): Promise<ApiServer> {\n const { config, logger } = deps;\n\n const app = await buildFastifyApp({\n logger: logger ?? true,\n bindHost: config.api.host ?? '127.0.0.1',\n });\n\n // Register wizard state route in normal mode so the SPA can check state\n registerWizardRoutes(\n app,\n {\n configPath: deps.configPath,\n walletPath: config.wallet.encrypted_path,\n },\n { mode: 'normal' }\n );\n\n // Register transport routes (before nodes routes)\n registerTransportRoutes(app, deps);\n\n // Register all normal routes\n registerNodeRoutes(app, deps);\n registerWalletRoutes(app, deps);\n registerWalletBalancesRoutes(app, deps);\n registerWalletRevealRoutes(app, deps);\n registerWalletWithdrawRoutes(app, deps);\n registerConfigPatchRoutes(app, deps);\n registerMetricsWsRoutes(app, deps);\n\n const CLOSE_TIMEOUT_MS = 5000;\n async function close(): Promise<void> {\n try {\n deps.transportProbe.stop();\n } catch {\n /* best-effort — must not block shutdown */\n }\n\n const openSockets = getOpenWebSockets();\n for (const socket of openSockets) {\n try {\n if (socket.readyState === WebSocket.OPEN) {\n socket.close(1001, 'server_shutdown');\n }\n } catch {\n // Best-effort\n }\n }\n openSockets.clear();\n\n await Promise.race([\n app.close(),\n new Promise<void>((resolve) => setTimeout(resolve, CLOSE_TIMEOUT_MS)),\n ]);\n }\n\n return { app, close };\n}\n","/**\n * Wizard API Server Factory.\n *\n * Starts in wizard mode (only wizard routes), transitions to normal mode\n * after POST /wizard/init completes and containers are healthy.\n * SECURITY: Wizard mode hard-rejects non-loopback bind regardless of env var.\n */\n\nimport { WebSocket } from 'ws';\nimport type { FastifyBaseLogger, FastifyInstance } from 'fastify';\nimport type Docker from 'dockerode';\nimport { buildFastifyApp, LOOPBACK_HOSTS } from './build-app.js';\nimport { registerWizardRoutes, PROGRESS_BUFFER_MAX } from './routes/wizard.js';\nimport { registerNodeRoutes } from './routes/nodes.js';\nimport { registerWalletRoutes } from './routes/wallet.js';\nimport { registerWalletBalancesRoutes } from './routes/wallet-balances.js';\nimport { registerWalletRevealRoutes } from './routes/wallet-reveal.js';\nimport { registerWalletWithdrawRoutes } from './routes/wallet-withdraw.js';\nimport { registerConfigPatchRoutes } from './routes/nodes-patch.js';\nimport {\n registerMetricsWsRoutes,\n getOpenWebSockets,\n} from './routes/metrics-ws.js';\nimport { registerTransportRoutes } from './routes/transport.js';\nimport {\n ConnectorAdminClient,\n DEFAULT_ATOR_PROXY,\n TransportProbe,\n} from '../connector/index.js';\nimport { DockerOrchestrator } from '../docker/index.js';\nimport type { WalletManager } from '../wallet/index.js';\nimport type { TownhouseConfig } from '../config/schema.js';\nimport type { NodeType } from '../docker/types.js';\nimport type { WizardProgressMessage } from './types.js';\nimport type { ApiServer } from './types.js';\n\nexport interface WizardInitialDeps {\n /** Directory where ~/.townhouse/ (or override) lives */\n configDir: string;\n /** Full path to config.yaml */\n configPath: string;\n /** Full path to wallet.enc */\n walletPath: string;\n /** Port to bind the API */\n port: number;\n /** Bind host — must be a loopback address; defaults to 127.0.0.1 */\n bindHost?: string;\n docker: Docker;\n logger?: FastifyBaseLogger | boolean;\n}\n\nconst CLOSE_TIMEOUT_MS = 5000;\n\n/**\n * Create the wizard API server. Starts in wizard-only mode.\n * After POST /wizard/init + orchestrator launch, transitions to normal mode.\n */\nexport async function createWizardApiServer(\n initialDeps: WizardInitialDeps\n): Promise<ApiServer> {\n const bindHost = initialDeps.bindHost ?? '127.0.0.1';\n\n // SECURITY: Wizard mode hard-rejects non-loopback regardless of TOWNHOUSE_API_ALLOW_REMOTE.\n // This guard is stricter than buildFastifyApp's normal-mode check because the wizard\n // exposes unauthenticated mutating endpoints (POST /wizard/init).\n if (!LOOPBACK_HOSTS.includes(bindHost)) {\n throw new Error(\n 'The wizard refuses remote bind for security. Edit ~/.townhouse/config.yaml after setup if you need remote API access.'\n );\n }\n\n const state: {\n mode: 'wizard' | 'normal';\n progressBuffer: WizardProgressMessage[];\n progressSockets: Set<WebSocket>;\n transitioned: boolean;\n initInFlight: boolean;\n } = {\n mode: 'wizard',\n progressBuffer: [],\n progressSockets: new Set<WebSocket>(),\n transitioned: false,\n initInFlight: false,\n };\n\n const app = await buildFastifyApp({\n logger: initialDeps.logger ?? true,\n bindHost,\n requireLoopback: true,\n });\n\n // Handler that fires after POST /wizard/init: creates orchestrator, transitions mode.\n // NOTE: state.transitioned is flipped only AFTER orchestrator.up() resolves so that\n // a launch failure leaves the wizard recoverable (the route handler clears initInFlight\n // on rejection and rolls back wallet+config files).\n async function onInit(\n config: TownhouseConfig,\n walletManager: WalletManager,\n profiles: NodeType[]\n ): Promise<void> {\n if (state.transitioned) return;\n\n const orchestrator = new DockerOrchestrator(\n initialDeps.docker,\n config,\n walletManager\n );\n\n // Forward orchestrator events to WS buffer + connected sockets\n orchestrator.on(\n 'pullProgress',\n (event: { image: string; status: string; progress?: string }) => {\n const msg: WizardProgressMessage = {\n type: 'pull_progress',\n image: event.image,\n status: event.status,\n progress: event.progress,\n ts: Date.now(),\n };\n broadcastProgress(msg);\n }\n );\n\n orchestrator.on(\n 'containerState',\n (event: {\n name: string;\n state: string;\n detail?: string;\n error?: string;\n }) => {\n const ts = Date.now();\n let msg: WizardProgressMessage;\n if (event.state === 'running' || event.state === 'starting') {\n msg = { type: 'container_starting', name: event.name, ts };\n } else if (event.state === 'error') {\n // Surface the underlying detail/error if the orchestrator provides one;\n // fall back to the generic 'error' state string.\n const reason = event.detail ?? event.error ?? event.state;\n msg = { type: 'container_failed', name: event.name, reason, ts };\n } else if (event.state === 'stopping' || event.state === 'stopped') {\n // During launch, an unexpected stop means a partial failure — surface it.\n msg = {\n type: 'container_failed',\n name: event.name,\n reason: `container ${event.state} during launch`,\n ts,\n };\n } else {\n return;\n }\n broadcastProgress(msg);\n }\n );\n\n // The orchestrator emits 'healthy' via the `healthCheck` event, not `containerState`.\n // Forward that to container_healthy so the wire contract in AC-7 is actually populated.\n orchestrator.on(\n 'healthCheck',\n (event: { name: string; status: string }) => {\n if (event.status === 'healthy') {\n broadcastProgress({\n type: 'container_healthy',\n name: event.name,\n ts: Date.now(),\n });\n }\n }\n );\n\n // Start containers — if this rejects, the route's .catch will roll back files\n // and clear initInFlight so the operator can retry.\n await orchestrator.up(profiles);\n\n // Register all normal routes on the same Fastify instance\n const connectorAdmin = new ConnectorAdminClient(\n `http://127.0.0.1:${config.connector.adminPort}`\n );\n\n // Stop the wizard probe — the normal probe takes over.\n wizardProbe.stop();\n\n // Build probe for normal mode (after wizard completes)\n const normalProbe = new TransportProbe({\n proxyUrl:\n config.transport.mode === 'ator'\n ? (config.transport.socksProxy ?? DEFAULT_ATOR_PROXY)\n : '',\n });\n if (config.transport.mode === 'ator') {\n normalProbe.start();\n }\n // Swap the GET-route's view to the normal probe + real config. The GET\n // closure reads these per request, so subsequent calls reflect live state.\n wizardTransportDeps.config = config;\n wizardTransportDeps.transportProbe = normalProbe;\n activeProbe = normalProbe;\n\n const apiDeps = {\n configPath: initialDeps.configPath,\n config,\n orchestrator,\n wallet: walletManager,\n connectorAdmin,\n transportProbe: normalProbe,\n };\n\n registerNodeRoutes(app as FastifyInstance, apiDeps);\n registerWalletRoutes(app as FastifyInstance, apiDeps);\n registerWalletBalancesRoutes(app as FastifyInstance, apiDeps);\n registerWalletRevealRoutes(app as FastifyInstance, apiDeps);\n registerWalletWithdrawRoutes(app as FastifyInstance, apiDeps);\n registerConfigPatchRoutes(app as FastifyInstance, apiDeps);\n registerMetricsWsRoutes(app as FastifyInstance, apiDeps);\n // GET /api/transport is already registered (wizard mode). Add PATCH only to\n // avoid Fastify's FST_ERR_DUPLICATED_ROUTE on the wizard happy path.\n registerTransportRoutes(app as FastifyInstance, apiDeps, {\n mode: 'patch-only',\n });\n\n // Transition state — only after everything succeeded.\n state.transitioned = true;\n state.mode = 'normal';\n\n // Broadcast launch_complete\n broadcastProgress({ type: 'launch_complete', ts: Date.now() });\n }\n\n function broadcastProgress(msg: WizardProgressMessage): void {\n state.progressBuffer.push(msg);\n if (state.progressBuffer.length > PROGRESS_BUFFER_MAX) {\n state.progressBuffer.splice(\n 0,\n state.progressBuffer.length - PROGRESS_BUFFER_MAX\n );\n }\n for (const socket of state.progressSockets) {\n try {\n if (socket.readyState === WebSocket.OPEN) {\n socket.send(JSON.stringify(msg));\n }\n } catch {\n /* best-effort */\n }\n }\n }\n\n // Lazy ATOR probe for wizard step 3 preview.\n //\n // Privacy: do NOT start the probe at server boot — the wizard fires outbound\n // TCP+HTTPS only when the operator engages the ATOR radio (which calls\n // POST /api/transport/wizard-probe-start). Once started it runs until the\n // wizard transitions to normal mode (when the normal probe takes over) or\n // the server closes.\n const wizardProbe = new TransportProbe({ proxyUrl: DEFAULT_ATOR_PROXY });\n // `activeProbe` lets close() stop whichever probe is currently running.\n let activeProbe: TransportProbe = wizardProbe;\n\n // Wizard transport deps. The route closure reads `transportProbe` and `config`\n // per request, so swapping these on transition is observed by subsequent GETs.\n const wizardTransportConfig = {\n transport: { mode: 'ator' as const, socksProxy: DEFAULT_ATOR_PROXY },\n };\n const wizardTransportDeps = {\n config: wizardTransportConfig,\n transportProbe: wizardProbe,\n } as unknown as Parameters<typeof registerTransportRoutes>[1];\n registerTransportRoutes(app as FastifyInstance, wizardTransportDeps, {\n mode: 'wizard',\n });\n\n // Lazy probe-start endpoint (wizard-only). Idempotent.\n app.post('/api/transport/wizard-probe-start', async (_request, reply) => {\n if (state.mode !== 'wizard') {\n // After transition the normal probe runs based on saved config.\n return reply.status(409).send({ error: 'wizard_not_in_progress' });\n }\n wizardProbe.start();\n return reply.status(200).send({ started: true });\n });\n\n registerWizardRoutes(\n app as FastifyInstance,\n {\n configPath: initialDeps.configPath,\n walletPath: initialDeps.walletPath,\n },\n state,\n onInit\n );\n\n async function close(): Promise<void> {\n try {\n activeProbe.stop();\n } catch {\n /* best-effort */\n }\n // Defensive: stop wizardProbe in case activeProbe is the normal one.\n try {\n wizardProbe.stop();\n } catch {\n /* best-effort */\n }\n\n const openSockets = getOpenWebSockets();\n for (const socket of openSockets) {\n try {\n if (socket.readyState === WebSocket.OPEN) {\n socket.close(1001, 'server_shutdown');\n }\n } catch {\n /* best-effort */\n }\n }\n openSockets.clear();\n for (const socket of state.progressSockets) {\n try {\n socket.close(1001, 'server_shutdown');\n } catch {\n /* best-effort */\n }\n }\n state.progressSockets.clear();\n\n await Promise.race([\n app.close(),\n new Promise<void>((resolve) => setTimeout(resolve, CLOSE_TIMEOUT_MS)),\n ]);\n }\n\n return { app: app as FastifyInstance, close };\n}\n"],"mappings":"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","names":["dir","platform","arch","runtime","abi","require_node_gyp_build","mask","data","require_fallback","Receiver","Sender","parse","EventEmitter","https","http","net","randomBytes","URL","Receiver","Sender","parse","WebSocket","websocket","key","WebSocket","createWebSocketStream","err","parse","protocol","EventEmitter","http","WebSocket","WebSocketServer","writeFileSync","join","result","join","writeFileSync","prev","dirname","TIMEOUT_MS","TIMEOUT_MS","entry","after","http","type","WebSocket","sendReq","dirname","join","generateMnemonic","validateMnemonic","wordlist","generateMnemonic","wordlist","validateMnemonic","WebSocket","dirname","join","DEFAULT_ATOR_PROXY","patchBodySchema","CLOSE_TIMEOUT_MS","WebSocket","WebSocket"]}