@shroud-fi/scanning 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/cjs/backend.d.ts +2 -0
- package/dist/cjs/backend.d.ts.map +1 -0
- package/dist/cjs/backend.js +6 -0
- package/dist/cjs/backend.js.map +1 -0
- package/dist/cjs/constants.d.ts +14 -0
- package/dist/cjs/constants.d.ts.map +1 -0
- package/dist/cjs/constants.js +17 -0
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/cursor.d.ts +8 -0
- package/dist/cjs/cursor.d.ts.map +1 -0
- package/dist/cjs/cursor.js +28 -0
- package/dist/cjs/cursor.js.map +1 -0
- package/dist/cjs/dedup.d.ts +10 -0
- package/dist/cjs/dedup.d.ts.map +1 -0
- package/dist/cjs/dedup.js +48 -0
- package/dist/cjs/dedup.js.map +1 -0
- package/dist/cjs/detector.d.ts +9 -0
- package/dist/cjs/detector.d.ts.map +1 -0
- package/dist/cjs/detector.js +425 -0
- package/dist/cjs/detector.js.map +1 -0
- package/dist/cjs/errors.d.ts +21 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +49 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.d.ts +9 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +33 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/types.d.ts +90 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +17 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/viem-backend.d.ts +14 -0
- package/dist/cjs/viem-backend.d.ts.map +1 -0
- package/dist/cjs/viem-backend.js +166 -0
- package/dist/cjs/viem-backend.js.map +1 -0
- package/dist/esm/backend.d.ts +2 -0
- package/dist/esm/backend.d.ts.map +1 -0
- package/dist/esm/backend.js +5 -0
- package/dist/esm/backend.js.map +1 -0
- package/dist/esm/constants.d.ts +14 -0
- package/dist/esm/constants.d.ts.map +1 -0
- package/dist/esm/constants.js +14 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/cursor.d.ts +8 -0
- package/dist/esm/cursor.d.ts.map +1 -0
- package/dist/esm/cursor.js +24 -0
- package/dist/esm/cursor.js.map +1 -0
- package/dist/esm/dedup.d.ts +10 -0
- package/dist/esm/dedup.d.ts.map +1 -0
- package/dist/esm/dedup.js +44 -0
- package/dist/esm/dedup.js.map +1 -0
- package/dist/esm/detector.d.ts +9 -0
- package/dist/esm/detector.d.ts.map +1 -0
- package/dist/esm/detector.js +422 -0
- package/dist/esm/detector.js.map +1 -0
- package/dist/esm/errors.d.ts +21 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +41 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types.d.ts +90 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +16 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/viem-backend.d.ts +14 -0
- package/dist/esm/viem-backend.d.ts.map +1 -0
- package/dist/esm/viem-backend.js +162 -0
- package/dist/esm/viem-backend.js.map +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ShroudFi contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @shroud-fi/scanning
|
|
2
|
+
|
|
3
|
+
> Receiver-side stealth payment detection for ShroudFi.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@shroud-fi/scanning)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm i @shroud-fi/scanning viem
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
`@shroud-fi/scanning` is the receiver side of a ShroudFi payment. It:
|
|
15
|
+
|
|
16
|
+
1. Scans a block range on Base for EIP-5564 `Announcement` events.
|
|
17
|
+
2. Filters by **one-byte view tag** — eliminates ~99.6% of irrelevant announcements without doing the heavy elliptic-curve math.
|
|
18
|
+
3. For each surviving candidate, performs an ECDH-style derivation to check whether the payment is for you, and if so, derives the stealth private key needed to spend it.
|
|
19
|
+
|
|
20
|
+
The scan key is **separable** — you can delegate scanning to a service while keeping the spending key in agent runtime.
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { createScanner } from '@shroud-fi/scanning';
|
|
26
|
+
import { deriveAgentIdentity } from '@shroud-fi/core';
|
|
27
|
+
import { createTransport } from '@shroud-fi/transport';
|
|
28
|
+
|
|
29
|
+
const transport = createTransport({ chain: 'base', rpcUrl });
|
|
30
|
+
const identity = deriveAgentIdentity(masterSeed);
|
|
31
|
+
const scanner = createScanner(transport, identity);
|
|
32
|
+
|
|
33
|
+
const payments = await scanner.scan({ fromBlock: 46_800_000n, toBlock: 'latest' });
|
|
34
|
+
// → [{ stealthAddress, stealthPrivateKey, ephemeralPubKey, viewTag, blockNumber, logIndex }, ...]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Exports
|
|
38
|
+
|
|
39
|
+
| Symbol | Purpose |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `createScanner(transport, identity)` | Scanner bound to an agent identity + transport. |
|
|
42
|
+
| `scanner.scan(range)` | Detect inbound payments in a block range; returns the stealth private key per hit. |
|
|
43
|
+
| `DetectedPayment` | `{ stealthAddress, stealthPrivateKey, ephemeralPubKey, viewTag, blockNumber, logIndex }` |
|
|
44
|
+
|
|
45
|
+
Full API reference: [shroudfi.live/sdk#scanning](https://shroudfi.live/sdk#scanning)
|
|
46
|
+
|
|
47
|
+
## Operational notes
|
|
48
|
+
|
|
49
|
+
- **Long ranges:** the scanner batches log requests. For an agent that's been offline > 24h, scanning is bounded by RPC log-query limits — chunk the range.
|
|
50
|
+
- **Real-time:** for low-latency detection, run `scanner.scan` from `latestBlock - confirmationDepth` on a tight cron, or use a webhook delivery primitive (planned for a future release).
|
|
51
|
+
- **Privacy invariant:** the scanner never logs the spending key it derives. Caller is responsible for handling `stealthPrivateKey` securely.
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT — see [LICENSE](./LICENSE).
|
|
56
|
+
|
|
57
|
+
Part of the [ShroudFi](https://shroudfi.live) privacy SDK for AI agents on Base.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/backend.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,aAAa,GACd,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Thin re-export module that exposes the ScannerBackend interface without
|
|
3
|
+
// pulling the whole index.ts barrel. Lets backend implementations import the
|
|
4
|
+
// minimum surface they need.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/backend.ts"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,6EAA6E;AAC7E,6BAA6B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FinalityLevel } from './types.js';
|
|
2
|
+
/** Default ERC-5564 SCHEME_ID — secp256k1 with view tags. */
|
|
3
|
+
export declare const DEFAULT_SCHEME_ID = 1n;
|
|
4
|
+
/** Reconciliation tick interval — 5 minutes. */
|
|
5
|
+
export declare const DEFAULT_RECONCILE_INTERVAL_MS = 300000;
|
|
6
|
+
/** LRU dedup capacity — chosen to fit ~30 minutes of Base block production. */
|
|
7
|
+
export declare const DEFAULT_DEDUP_CAPACITY = 10000;
|
|
8
|
+
/** Max blocks per getLogs call — Alchemy/QuickNode default-safe. */
|
|
9
|
+
export declare const DEFAULT_GETLOGS_CHUNK_SIZE = 10000n;
|
|
10
|
+
/** Default finality threshold an event must satisfy before yielding. */
|
|
11
|
+
export declare const DEFAULT_FINALITY: FinalityLevel;
|
|
12
|
+
/** Minimum metadata length before a view tag can even be read (byte 0). */
|
|
13
|
+
export declare const MIN_METADATA_LENGTH = 1;
|
|
14
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,6DAA6D;AAC7D,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,gDAAgD;AAChD,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAErD,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,oEAAoE;AACpE,eAAO,MAAM,0BAA0B,SAAU,CAAC;AAElD,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,aAAsB,CAAC;AAEtD,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB,IAAI,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Defaults for @shroud-fi/scanning. All values are tunable via ScannerConfig.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.MIN_METADATA_LENGTH = exports.DEFAULT_FINALITY = exports.DEFAULT_GETLOGS_CHUNK_SIZE = exports.DEFAULT_DEDUP_CAPACITY = exports.DEFAULT_RECONCILE_INTERVAL_MS = exports.DEFAULT_SCHEME_ID = void 0;
|
|
5
|
+
/** Default ERC-5564 SCHEME_ID — secp256k1 with view tags. */
|
|
6
|
+
exports.DEFAULT_SCHEME_ID = 1n;
|
|
7
|
+
/** Reconciliation tick interval — 5 minutes. */
|
|
8
|
+
exports.DEFAULT_RECONCILE_INTERVAL_MS = 300_000;
|
|
9
|
+
/** LRU dedup capacity — chosen to fit ~30 minutes of Base block production. */
|
|
10
|
+
exports.DEFAULT_DEDUP_CAPACITY = 10_000;
|
|
11
|
+
/** Max blocks per getLogs call — Alchemy/QuickNode default-safe. */
|
|
12
|
+
exports.DEFAULT_GETLOGS_CHUNK_SIZE = 10000n;
|
|
13
|
+
/** Default finality threshold an event must satisfy before yielding. */
|
|
14
|
+
exports.DEFAULT_FINALITY = 'safe';
|
|
15
|
+
/** Minimum metadata length before a view tag can even be read (byte 0). */
|
|
16
|
+
exports.MIN_METADATA_LENGTH = 1;
|
|
17
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";AAAA,8EAA8E;;;AAI9E,6DAA6D;AAChD,QAAA,iBAAiB,GAAG,EAAE,CAAC;AAEpC,gDAAgD;AACnC,QAAA,6BAA6B,GAAG,OAAO,CAAC;AAErD,+EAA+E;AAClE,QAAA,sBAAsB,GAAG,MAAM,CAAC;AAE7C,oEAAoE;AACvD,QAAA,0BAA0B,GAAG,MAAO,CAAC;AAElD,wEAAwE;AAC3D,QAAA,gBAAgB,GAAkB,MAAM,CAAC;AAEtD,2EAA2E;AAC9D,QAAA,mBAAmB,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/cursor.ts"],"names":[],"mappings":"AAOA,qBAAa,MAAM;;gBAGL,UAAU,EAAE,MAAM;IAO9B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,0EAA0E;IAC1E,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAK/B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Monotonic block cursor used by the detector's reconciliation loop.
|
|
3
|
+
//
|
|
4
|
+
// In-memory only — by design (per types.ts contract). On restart the scanner
|
|
5
|
+
// resets to `startBlock`. Dedup + ECDH verification prevent double-yield.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.Cursor = void 0;
|
|
8
|
+
const errors_js_1 = require("./errors.js");
|
|
9
|
+
class Cursor {
|
|
10
|
+
#last;
|
|
11
|
+
constructor(startBlock) {
|
|
12
|
+
if (startBlock < 0n) {
|
|
13
|
+
throw new errors_js_1.ScanningError('startBlock must be non-negative');
|
|
14
|
+
}
|
|
15
|
+
this.#last = startBlock;
|
|
16
|
+
}
|
|
17
|
+
get last() {
|
|
18
|
+
return this.#last;
|
|
19
|
+
}
|
|
20
|
+
/** Advance to `block` if it is strictly greater than the current last. */
|
|
21
|
+
advanceTo(block) {
|
|
22
|
+
if (block > this.#last) {
|
|
23
|
+
this.#last = block;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.Cursor = Cursor;
|
|
28
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/cursor.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,EAAE;AACF,6EAA6E;AAC7E,0EAA0E;;;AAE1E,2CAA4C;AAE5C,MAAa,MAAM;IACjB,KAAK,CAAS;IAEd,YAAY,UAAkB;QAC5B,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,yBAAa,CAAC,iCAAiC,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;IAC1B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,0EAA0E;IAC1E,SAAS,CAAC,KAAa;QACrB,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AApBD,wBAoBC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class LRUDeduper {
|
|
2
|
+
#private;
|
|
3
|
+
constructor(capacity: number);
|
|
4
|
+
has(key: string): boolean;
|
|
5
|
+
/** Add a key. Returns true if newly added, false if already present. */
|
|
6
|
+
add(key: string): boolean;
|
|
7
|
+
clear(): void;
|
|
8
|
+
get size(): number;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=dedup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../../src/dedup.ts"],"names":[],"mappings":"AAWA,qBAAa,UAAU;;gBAIT,QAAQ,EAAE,MAAM;IAQ5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,wEAAwE;IACxE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAazB,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// FIFO LRU deduper for announcement keys (`${txHash}:${logIndex}`).
|
|
3
|
+
//
|
|
4
|
+
// Privacy contract:
|
|
5
|
+
// - Keys passed in are public on-chain identifiers (txHash + logIndex). The
|
|
6
|
+
// deduper never sees private key material; nothing here is sensitive on its
|
|
7
|
+
// own. Still, no console.* logging by policy.
|
|
8
|
+
// - JS Map iteration order is insertion order, which gives us FIFO eviction
|
|
9
|
+
// for free without an explicit doubly-linked list.
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.LRUDeduper = void 0;
|
|
12
|
+
const errors_js_1 = require("./errors.js");
|
|
13
|
+
class LRUDeduper {
|
|
14
|
+
#capacity;
|
|
15
|
+
#map;
|
|
16
|
+
constructor(capacity) {
|
|
17
|
+
if (!Number.isInteger(capacity) || capacity < 1) {
|
|
18
|
+
throw new errors_js_1.ScanningError('LRU capacity must be a positive integer');
|
|
19
|
+
}
|
|
20
|
+
this.#capacity = capacity;
|
|
21
|
+
this.#map = new Map();
|
|
22
|
+
}
|
|
23
|
+
has(key) {
|
|
24
|
+
return this.#map.has(key);
|
|
25
|
+
}
|
|
26
|
+
/** Add a key. Returns true if newly added, false if already present. */
|
|
27
|
+
add(key) {
|
|
28
|
+
if (this.#map.has(key))
|
|
29
|
+
return false;
|
|
30
|
+
this.#map.set(key, true);
|
|
31
|
+
if (this.#map.size > this.#capacity) {
|
|
32
|
+
// FIFO eviction: drop the oldest entry (first in insertion order).
|
|
33
|
+
for (const oldest of this.#map.keys()) {
|
|
34
|
+
this.#map.delete(oldest);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
clear() {
|
|
41
|
+
this.#map.clear();
|
|
42
|
+
}
|
|
43
|
+
get size() {
|
|
44
|
+
return this.#map.size;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.LRUDeduper = LRUDeduper;
|
|
48
|
+
//# sourceMappingURL=dedup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup.js","sourceRoot":"","sources":["../../src/dedup.ts"],"names":[],"mappings":";AAAA,oEAAoE;AACpE,EAAE;AACF,oBAAoB;AACpB,8EAA8E;AAC9E,gFAAgF;AAChF,kDAAkD;AAClD,8EAA8E;AAC9E,uDAAuD;;;AAEvD,2CAA4C;AAE5C,MAAa,UAAU;IACZ,SAAS,CAAS;IAClB,IAAI,CAAoB;IAEjC,YAAY,QAAgB;QAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,yBAAa,CAAC,yCAAyC,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAgB,CAAC;IACtC,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,wEAAwE;IACxE,GAAG,CAAC,GAAW;QACb,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YACpC,mEAAmE;YACnE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACtC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzB,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;CACF;AArCD,gCAqCC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Scanner, ScannerConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build a Scanner instance.
|
|
4
|
+
*
|
|
5
|
+
* Construction validates config + resolves defaults. The Scanner is inert until
|
|
6
|
+
* the caller starts iterating watch() or scanRange(). close() is idempotent.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createScanner(config: ScannerConfig): Scanner;
|
|
9
|
+
//# sourceMappingURL=detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/detector.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAGV,OAAO,EAEP,aAAa,EAEd,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CA0b5D"}
|