nostr-wot-sdk 0.3.1 → 0.3.2
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/CHANGELOG.md +135 -0
- package/README.md +7 -5
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/local/index.cjs +1 -1
- package/dist/local/index.cjs.map +1 -1
- package/dist/local/index.js +1 -1
- package/dist/local/index.js.map +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.3.2] - 2025-02-05
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Scoring formula changed from multiplicative to additive** to match extension
|
|
13
|
+
- Old: `score = baseScore × distanceWeight × (1 + bonuses)`
|
|
14
|
+
- New: `score = (baseScore × distanceWeight) + bonuses`
|
|
15
|
+
- Example: 2 hops + 30% path bonus = 0.5 + 0.3 = 0.80 (was 0.65)
|
|
16
|
+
- This produces higher scores for pubkeys with multiple paths
|
|
17
|
+
|
|
18
|
+
## [0.3.1] - 2025-02-05
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- `getDistanceBatch(targets, includePaths?)` now accepts an optional `includePaths` parameter
|
|
23
|
+
- When `false` (default): returns `{ pubkey: hops }` - backwards compatible
|
|
24
|
+
- When `true`: returns `{ pubkey: { hops, paths } }` - includes path count for scoring
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- `getTrustScoreBatch` now uses path counts internally for accurate trust score calculation with path bonuses
|
|
29
|
+
|
|
30
|
+
## [0.3.0] - 2025-02-05
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **Automatic Extension Connection for React** - Zero-config React integration
|
|
35
|
+
- `WoTProvider` now auto-connects to the extension by default (`useExtension: true`)
|
|
36
|
+
- New `useExtension()` hook for accessing extension connection state
|
|
37
|
+
- Extension state includes: `isConnected`, `isConnecting`, `isInstalled`, `isChecked`, `error`, `connect()`
|
|
38
|
+
|
|
39
|
+
- **Event-based Extension Connection Flow**
|
|
40
|
+
- New `src/extension.ts` module with reliable extension detection
|
|
41
|
+
- `checkExtension(timeout?)` - Check if extension is installed using `nostr-wot-check` → `nostr-wot-present` handshake
|
|
42
|
+
- `connectExtension(timeout?)` - Connect to extension using `nostr-wot-connect` → `nostr-wot-ready` handshake
|
|
43
|
+
- `checkAndConnect(options?)` - Combined check and connect in one call
|
|
44
|
+
- `ExtensionConnector` class - Stateful connector with subscription support for state changes
|
|
45
|
+
- `getDefaultConnector()` / `resetDefaultConnector()` - Singleton pattern for shared connector
|
|
46
|
+
|
|
47
|
+
- **New Extension Events Protocol**
|
|
48
|
+
| Event | Direction | Purpose |
|
|
49
|
+
|-------|-----------|---------|
|
|
50
|
+
| `nostr-wot-check` | Page → Extension | Check if extension installed |
|
|
51
|
+
| `nostr-wot-present` | Extension → Page | Response confirming presence |
|
|
52
|
+
| `nostr-wot-connect` | Page → Extension | Request API injection |
|
|
53
|
+
| `nostr-wot-ready` | Extension → Page | API is ready at `window.nostr.wot` |
|
|
54
|
+
| `nostr-wot-error` | Extension → Page | Injection failed with error |
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- `WoTProvider` props are now optional - just `<WoTProvider>` works out of the box
|
|
59
|
+
- `WoT` class `getExtension()` now uses event-based connection flow for reliable detection
|
|
60
|
+
|
|
61
|
+
### Usage
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { WoTProvider, useWoT, useExtension } from 'nostr-wot-sdk/react';
|
|
65
|
+
|
|
66
|
+
// Just wrap your app - no config needed
|
|
67
|
+
function App() {
|
|
68
|
+
return (
|
|
69
|
+
<WoTProvider>
|
|
70
|
+
<YourApp />
|
|
71
|
+
</WoTProvider>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check extension status
|
|
76
|
+
function Status() {
|
|
77
|
+
const { isConnected, isConnecting } = useExtension();
|
|
78
|
+
if (isConnecting) return <span>Connecting...</span>;
|
|
79
|
+
return <span>{isConnected ? 'Connected' : 'Not connected'}</span>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Use WoT data
|
|
83
|
+
function Profile({ pubkey }) {
|
|
84
|
+
const { distance, score, loading } = useWoT(pubkey);
|
|
85
|
+
// ...
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## [0.2.0] - 2025-02-04
|
|
90
|
+
|
|
91
|
+
### Added
|
|
92
|
+
|
|
93
|
+
- Full extension API support matching [nostr-wot-extension](https://github.com/nostr-wot/nostr-wot-extension)
|
|
94
|
+
- Extension-first architecture: extension always takes priority when available
|
|
95
|
+
- New extension-only methods:
|
|
96
|
+
- `getFollows(pubkey?)` - Get follow list
|
|
97
|
+
- `getCommonFollows(pubkey)` - Get mutual follows
|
|
98
|
+
- `getPath(target)` - Get actual path to target
|
|
99
|
+
- `getStats()` - Get graph statistics
|
|
100
|
+
- `isConfigured()` - Check extension configuration status
|
|
101
|
+
- `getExtensionConfig()` - Get extension configuration
|
|
102
|
+
- Batch operations:
|
|
103
|
+
- `getDistanceBatch(targets)` - Batch distance queries
|
|
104
|
+
- `getTrustScoreBatch(targets)` - Batch trust score queries
|
|
105
|
+
- `filterByWoT(pubkeys, options?)` - Filter pubkeys by WoT membership
|
|
106
|
+
- React integration (`nostr-wot-sdk/react`):
|
|
107
|
+
- `WoTProvider` - Context provider
|
|
108
|
+
- `useWoT(pubkey)` - Full WoT data hook
|
|
109
|
+
- `useIsInWoT(pubkey)` - Boolean WoT check
|
|
110
|
+
- `useTrustScore(pubkey)` - Trust score hook
|
|
111
|
+
- `useBatchWoT(pubkeys)` - Batch queries hook
|
|
112
|
+
- Local mode (`nostr-wot-sdk/local`) for server-side usage
|
|
113
|
+
- GitHub Actions workflows for CI and npm publishing
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- `WoTOptions.useExtension` controls extension usage (default: `false`)
|
|
118
|
+
- Fallback configuration via `WoTOptions.fallback` for oracle mode when extension unavailable
|
|
119
|
+
|
|
120
|
+
## [0.1.0] - 2025-02-03
|
|
121
|
+
|
|
122
|
+
### Added
|
|
123
|
+
|
|
124
|
+
- Initial release
|
|
125
|
+
- Core `WoT` class with oracle-based queries
|
|
126
|
+
- Methods: `getDistance`, `isInMyWoT`, `getTrustScore`, `getDistanceBetween`, `batchCheck`, `getDetails`
|
|
127
|
+
- Custom scoring configuration
|
|
128
|
+
- TypeScript support with full type definitions
|
|
129
|
+
- Error classes: `WoTError`, `NetworkError`, `NotFoundError`, `TimeoutError`, `ValidationError`
|
|
130
|
+
|
|
131
|
+
[0.3.2]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.3.1...v0.3.2
|
|
132
|
+
[0.3.1]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.3.0...v0.3.1
|
|
133
|
+
[0.3.0]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.2.0...v0.3.0
|
|
134
|
+
[0.2.0]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.1.0...v0.2.0
|
|
135
|
+
[0.1.0]: https://github.com/nostr-wot/nostr-wot-sdk/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -321,21 +321,23 @@ const wot = new WoT({
|
|
|
321
321
|
3: 0.25, // 3 hops
|
|
322
322
|
4: 0.1, // 4+ hops
|
|
323
323
|
},
|
|
324
|
-
// Bonus
|
|
325
|
-
mutualBonus: 0.5, // +
|
|
326
|
-
pathBonus: 0.1, // +
|
|
327
|
-
maxPathBonus: 0.5, // Cap path bonus at +
|
|
324
|
+
// Bonus values (additive)
|
|
325
|
+
mutualBonus: 0.5, // +0.5 for mutual follows
|
|
326
|
+
pathBonus: 0.1, // +0.1 per additional path
|
|
327
|
+
maxPathBonus: 0.5, // Cap path bonus at +0.5
|
|
328
328
|
}
|
|
329
329
|
});
|
|
330
330
|
```
|
|
331
331
|
|
|
332
332
|
### Scoring Formula
|
|
333
333
|
```
|
|
334
|
-
score = baseScore × distanceWeight
|
|
334
|
+
score = (baseScore × distanceWeight) + bonuses
|
|
335
335
|
|
|
336
336
|
where:
|
|
337
337
|
baseScore = 1 / (hops + 1)
|
|
338
338
|
bonuses = mutualBonus (if mutual) + min(pathBonus × (paths - 1), maxPathBonus)
|
|
339
|
+
|
|
340
|
+
Example: 2 hops + 30% path bonus = 0.5 + 0.3 = 0.80
|
|
339
341
|
```
|
|
340
342
|
|
|
341
343
|
## Server-Side Local Mode
|
package/dist/index.cjs
CHANGED
|
@@ -127,7 +127,7 @@ function calculateTrustScore(result, scoring) {
|
|
|
127
127
|
const pathCountBonus = Math.min(pathBonus * (paths - 1), maxPathBonus);
|
|
128
128
|
bonuses += pathCountBonus;
|
|
129
129
|
}
|
|
130
|
-
const score = baseScore * distanceWeight
|
|
130
|
+
const score = baseScore * distanceWeight + bonuses;
|
|
131
131
|
return Math.min(1, Math.max(0, score));
|
|
132
132
|
}
|
|
133
133
|
async function fetchWithTimeout(url, options = {}) {
|
package/dist/index.d.cts
CHANGED
|
@@ -761,12 +761,14 @@ declare function normalizePubkey(pubkey: string): string;
|
|
|
761
761
|
* Calculates trust score based on distance result and scoring config
|
|
762
762
|
*
|
|
763
763
|
* Formula:
|
|
764
|
-
* score = baseScore × distanceWeight
|
|
764
|
+
* score = (baseScore × distanceWeight) + bonuses
|
|
765
765
|
*
|
|
766
766
|
* where:
|
|
767
767
|
* baseScore = 1 / (hops + 1)
|
|
768
768
|
* bonuses = mutualBonus (if mutual) + min(pathBonus × (paths - 1), maxPathBonus)
|
|
769
769
|
*
|
|
770
|
+
* Example: 2 hops + 30% path bonus = 0.5 + 0.3 = 0.80
|
|
771
|
+
*
|
|
770
772
|
* Note: `mutual` is optional (only available from oracle, not extension)
|
|
771
773
|
*/
|
|
772
774
|
declare function calculateTrustScore(result: DistanceResult, scoring: ScoringConfig): number;
|
package/dist/index.d.ts
CHANGED
|
@@ -761,12 +761,14 @@ declare function normalizePubkey(pubkey: string): string;
|
|
|
761
761
|
* Calculates trust score based on distance result and scoring config
|
|
762
762
|
*
|
|
763
763
|
* Formula:
|
|
764
|
-
* score = baseScore × distanceWeight
|
|
764
|
+
* score = (baseScore × distanceWeight) + bonuses
|
|
765
765
|
*
|
|
766
766
|
* where:
|
|
767
767
|
* baseScore = 1 / (hops + 1)
|
|
768
768
|
* bonuses = mutualBonus (if mutual) + min(pathBonus × (paths - 1), maxPathBonus)
|
|
769
769
|
*
|
|
770
|
+
* Example: 2 hops + 30% path bonus = 0.5 + 0.3 = 0.80
|
|
771
|
+
*
|
|
770
772
|
* Note: `mutual` is optional (only available from oracle, not extension)
|
|
771
773
|
*/
|
|
772
774
|
declare function calculateTrustScore(result: DistanceResult, scoring: ScoringConfig): number;
|
package/dist/index.js
CHANGED
|
@@ -125,7 +125,7 @@ function calculateTrustScore(result, scoring) {
|
|
|
125
125
|
const pathCountBonus = Math.min(pathBonus * (paths - 1), maxPathBonus);
|
|
126
126
|
bonuses += pathCountBonus;
|
|
127
127
|
}
|
|
128
|
-
const score = baseScore * distanceWeight
|
|
128
|
+
const score = baseScore * distanceWeight + bonuses;
|
|
129
129
|
return Math.min(1, Math.max(0, score));
|
|
130
130
|
}
|
|
131
131
|
async function fetchWithTimeout(url, options = {}) {
|
package/dist/local/index.cjs
CHANGED
|
@@ -92,7 +92,7 @@ function calculateTrustScore(result, scoring) {
|
|
|
92
92
|
const pathCountBonus = Math.min(pathBonus * (paths - 1), maxPathBonus);
|
|
93
93
|
bonuses += pathCountBonus;
|
|
94
94
|
}
|
|
95
|
-
const score = baseScore * distanceWeight
|
|
95
|
+
const score = baseScore * distanceWeight + bonuses;
|
|
96
96
|
return Math.min(1, Math.max(0, score));
|
|
97
97
|
}
|
|
98
98
|
function chunk(array, size) {
|
package/dist/local/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/errors.ts","../../src/utils.ts","../../src/local/storage.ts","../../src/local/relay.ts","../../src/local/local-wot.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base error class for WoT SDK errors\n */\nexport class WoTError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WoTError';\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n // Fix prototype chain for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when a network request fails\n */\nexport class NetworkError extends WoTError {\n public readonly statusCode?: number;\n public readonly url?: string;\n\n constructor(message: string, statusCode?: number, url?: string) {\n super(message);\n this.name = 'NetworkError';\n this.statusCode = statusCode;\n this.url = url;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when a pubkey is not found in the graph\n */\nexport class NotFoundError extends WoTError {\n public readonly pubkey: string;\n\n constructor(pubkey: string, message?: string) {\n super(message || `Pubkey not found in graph: ${pubkey}`);\n this.name = 'NotFoundError';\n this.pubkey = pubkey;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when a request times out\n */\nexport class TimeoutError extends WoTError {\n public readonly timeout: number;\n\n constructor(timeout: number, message?: string) {\n super(message || `Request timed out after ${timeout}ms`);\n this.name = 'TimeoutError';\n this.timeout = timeout;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when validation fails\n */\nexport class ValidationError extends WoTError {\n public readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message);\n this.name = 'ValidationError';\n this.field = field;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when local storage operations fail\n */\nexport class StorageError extends WoTError {\n public readonly operation: string;\n\n constructor(operation: string, message?: string) {\n super(message || `Storage operation failed: ${operation}`);\n this.name = 'StorageError';\n this.operation = operation;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when relay connection fails\n */\nexport class RelayError extends WoTError {\n public readonly relay: string;\n\n constructor(relay: string, message?: string) {\n super(message || `Relay connection failed: ${relay}`);\n this.name = 'RelayError';\n this.relay = relay;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import type { ScoringConfig, DistanceResult } from './types';\n\n/**\n * Default scoring configuration\n */\nexport const DEFAULT_SCORING: ScoringConfig = {\n distanceWeights: {\n 1: 1.0,\n 2: 0.5,\n 3: 0.25,\n 4: 0.1,\n },\n mutualBonus: 0.5,\n pathBonus: 0.1,\n maxPathBonus: 0.5,\n};\n\n/**\n * Default oracle URL\n */\nexport const DEFAULT_ORACLE = 'https://nostr-wot.com';\n\n/**\n * Default max hops for WoT queries\n */\nexport const DEFAULT_MAX_HOPS = 3;\n\n/**\n * Default timeout in milliseconds\n */\nexport const DEFAULT_TIMEOUT = 5000;\n\n/**\n * Validates a hex pubkey\n */\nexport function isValidPubkey(pubkey: string): boolean {\n return /^[0-9a-f]{64}$/i.test(pubkey);\n}\n\n/**\n * Validates an oracle URL (must be HTTPS)\n */\nexport function isValidOracleUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a relay URL (must be WSS or WS)\n */\nexport function isValidRelayUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'wss:' || parsed.protocol === 'ws:';\n } catch {\n return false;\n }\n}\n\n/**\n * Maximum allowed batch size for array inputs\n */\nexport const MAX_BATCH_SIZE = 10000;\n\n/**\n * Normalizes a pubkey to lowercase hex\n */\nexport function normalizePubkey(pubkey: string): string {\n return pubkey.toLowerCase();\n}\n\n/**\n * Merges scoring configuration with defaults\n */\nexport function mergeScoringConfig(\n partial?: Partial<ScoringConfig>\n): ScoringConfig {\n if (!partial) return { ...DEFAULT_SCORING };\n\n return {\n distanceWeights: {\n ...DEFAULT_SCORING.distanceWeights,\n ...partial.distanceWeights,\n },\n mutualBonus: partial.mutualBonus ?? DEFAULT_SCORING.mutualBonus,\n pathBonus: partial.pathBonus ?? DEFAULT_SCORING.pathBonus,\n maxPathBonus: partial.maxPathBonus ?? DEFAULT_SCORING.maxPathBonus,\n };\n}\n\n/**\n * Calculates trust score based on distance result and scoring config\n *\n * Formula:\n * score = baseScore × distanceWeight × (1 + bonuses)\n *\n * where:\n * baseScore = 1 / (hops + 1)\n * bonuses = mutualBonus (if mutual) + min(pathBonus × (paths - 1), maxPathBonus)\n *\n * Note: `mutual` is optional (only available from oracle, not extension)\n */\nexport function calculateTrustScore(\n result: DistanceResult,\n scoring: ScoringConfig\n): number {\n const { hops, paths, mutual } = result;\n const { distanceWeights, mutualBonus, pathBonus, maxPathBonus } = scoring;\n\n // Base score decreases with distance\n const baseScore = 1 / (hops + 1);\n\n // Get distance weight (default to lowest defined weight for distant hops)\n const maxDefinedHop = Math.max(...Object.keys(distanceWeights).map(Number));\n const distanceWeight =\n distanceWeights[hops] ?? distanceWeights[maxDefinedHop] ?? 0.1;\n\n // Calculate bonuses\n let bonuses = 0;\n\n // Mutual follow bonus (only if mutual info is available)\n if (mutual === true) {\n bonuses += mutualBonus;\n }\n\n // Path count bonus (more paths = more trust)\n if (paths > 1) {\n const pathCountBonus = Math.min(pathBonus * (paths - 1), maxPathBonus);\n bonuses += pathCountBonus;\n }\n\n // Final score (clamped to 0-1)\n const score = baseScore * distanceWeight * (1 + bonuses);\n return Math.min(1, Math.max(0, score));\n}\n\n/**\n * Creates a fetch request with timeout\n */\nexport async function fetchWithTimeout(\n url: string,\n options: RequestInit & { timeout?: number } = {}\n): Promise<Response> {\n const { timeout = DEFAULT_TIMEOUT, ...fetchOptions } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n return await fetch(url, {\n ...fetchOptions,\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Delays execution for specified milliseconds\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Chunks an array into smaller arrays\n */\nexport function chunk<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Creates a deferred promise\n */\nexport interface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: unknown) => void;\n}\n\nexport function createDeferred<T>(): Deferred<T> {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason?: unknown) => void;\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { promise, resolve, reject };\n}\n","import type { StorageAdapter } from '../types';\nimport { StorageError } from '../errors';\n\n/**\n * In-memory storage adapter\n */\nexport class MemoryStorage implements StorageAdapter {\n private data = new Map<string, string>();\n\n async get(key: string): Promise<string | null> {\n return this.data.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.data.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.data.delete(key);\n }\n\n async clear(): Promise<void> {\n this.data.clear();\n }\n\n async keys(): Promise<string[]> {\n return Array.from(this.data.keys());\n }\n}\n\n/**\n * IndexedDB storage adapter\n */\nexport class IndexedDBStorage implements StorageAdapter {\n private dbName: string;\n private storeName = 'wot-data';\n private db: IDBDatabase | null = null;\n private dbPromise: Promise<IDBDatabase> | null = null;\n\n constructor(dbName = 'nostr-wot-sdk') {\n this.dbName = dbName;\n }\n\n private async getDB(): Promise<IDBDatabase> {\n if (this.db) return this.db;\n if (this.dbPromise) return this.dbPromise;\n\n this.dbPromise = new Promise((resolve, reject) => {\n if (typeof indexedDB === 'undefined') {\n reject(new StorageError('open', 'IndexedDB is not available'));\n return;\n }\n\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => {\n reject(new StorageError('open', request.error?.message));\n };\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve(request.result);\n };\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n });\n\n return this.dbPromise;\n }\n\n async get(key: string): Promise<string | null> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readonly');\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n\n request.onerror = () => {\n reject(new StorageError('get', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve(request.result ?? null);\n };\n });\n }\n\n async set(key: string, value: string): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n\n request.onerror = () => {\n reject(new StorageError('set', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve();\n };\n });\n }\n\n async delete(key: string): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.delete(key);\n\n request.onerror = () => {\n reject(new StorageError('delete', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve();\n };\n });\n }\n\n async clear(): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.clear();\n\n request.onerror = () => {\n reject(new StorageError('clear', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve();\n };\n });\n }\n\n async keys(): Promise<string[]> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readonly');\n const store = transaction.objectStore(this.storeName);\n const request = store.getAllKeys();\n\n request.onerror = () => {\n reject(new StorageError('keys', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve(request.result.map(String));\n };\n });\n }\n\n close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n this.dbPromise = null;\n }\n }\n}\n\n/**\n * Creates a storage adapter based on type\n */\nexport function createStorage(\n type: 'memory' | 'indexeddb' | StorageAdapter\n): StorageAdapter {\n if (typeof type === 'object') {\n return type;\n }\n\n switch (type) {\n case 'indexeddb':\n return new IndexedDBStorage();\n case 'memory':\n default:\n return new MemoryStorage();\n }\n}\n","import type { NostrContactEvent } from '../types';\nimport { RelayError } from '../errors';\nimport { createDeferred, type Deferred } from '../utils';\n\n/**\n * Nostr relay subscription filter\n */\ninterface NostrFilter {\n kinds?: number[];\n authors?: string[];\n '#p'?: string[];\n since?: number;\n until?: number;\n limit?: number;\n}\n\n/**\n * Nostr relay message types\n */\ntype NostrMessage =\n | ['EVENT', string, NostrContactEvent]\n | ['EOSE', string]\n | ['NOTICE', string]\n | ['OK', string, boolean, string];\n\n/**\n * Simple Nostr relay connection for fetching contact lists (kind 3)\n */\nexport class RelayConnection {\n private url: string;\n private ws: WebSocket | null = null;\n private subscriptions = new Map<\n string,\n {\n filter: NostrFilter;\n events: NostrContactEvent[];\n deferred: Deferred<NostrContactEvent[]>;\n }\n >();\n private connectPromise: Promise<void> | null = null;\n private subIdCounter = 0;\n\n constructor(url: string) {\n this.url = url;\n }\n\n /**\n * Connect to the relay\n */\n async connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.connectPromise = new Promise((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => {\n this.connectPromise = null;\n resolve();\n };\n\n this.ws.onerror = (event) => {\n this.connectPromise = null;\n reject(new RelayError(this.url, `Connection error: ${event}`));\n };\n\n this.ws.onclose = () => {\n this.ws = null;\n this.connectPromise = null;\n };\n\n this.ws.onmessage = (event) => {\n try {\n const message = JSON.parse(event.data) as NostrMessage;\n this.handleMessage(message);\n } catch {\n // Ignore malformed messages\n }\n };\n } catch (error) {\n this.connectPromise = null;\n reject(\n new RelayError(\n this.url,\n error instanceof Error ? error.message : 'Connection failed'\n )\n );\n }\n });\n\n return this.connectPromise;\n }\n\n /**\n * Handle incoming relay message\n */\n private handleMessage(message: NostrMessage): void {\n const [type, subId] = message;\n\n if (type === 'EVENT') {\n const event = message[2];\n const sub = this.subscriptions.get(subId);\n if (sub && event.kind === 3) {\n sub.events.push(event);\n }\n } else if (type === 'EOSE') {\n const sub = this.subscriptions.get(subId);\n if (sub) {\n sub.deferred.resolve(sub.events);\n this.subscriptions.delete(subId);\n this.send(['CLOSE', subId]);\n }\n }\n }\n\n /**\n * Send a message to the relay\n */\n private send(message: unknown[]): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(message));\n }\n }\n\n /**\n * Fetch contact lists for given pubkeys\n */\n async fetchContactLists(\n pubkeys: string[],\n timeout = 10000\n ): Promise<NostrContactEvent[]> {\n await this.connect();\n\n const subId = `wot-${++this.subIdCounter}`;\n const filter: NostrFilter = {\n kinds: [3],\n authors: pubkeys,\n };\n\n const deferred = createDeferred<NostrContactEvent[]>();\n\n this.subscriptions.set(subId, {\n filter,\n events: [],\n deferred,\n });\n\n // Send subscription request\n this.send(['REQ', subId, filter]);\n\n // Set timeout\n const timeoutId = setTimeout(() => {\n const sub = this.subscriptions.get(subId);\n if (sub) {\n sub.deferred.resolve(sub.events);\n this.subscriptions.delete(subId);\n this.send(['CLOSE', subId]);\n }\n }, timeout);\n\n try {\n return await deferred.promise;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Close the relay connection\n */\n close(): void {\n // Close all pending subscriptions\n for (const [subId, sub] of this.subscriptions) {\n sub.deferred.resolve(sub.events);\n this.send(['CLOSE', subId]);\n }\n this.subscriptions.clear();\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n /**\n * Get relay URL\n */\n getUrl(): string {\n return this.url;\n }\n}\n\n/**\n * Pool of relay connections\n */\nexport class RelayPool {\n private relays: RelayConnection[] = [];\n private connected = false;\n\n constructor(urls: string[]) {\n this.relays = urls.map((url) => new RelayConnection(url));\n }\n\n /**\n * Connect to all relays\n */\n async connect(): Promise<void> {\n if (this.connected) return;\n\n const results = await Promise.allSettled(\n this.relays.map((relay) => relay.connect())\n );\n\n // At least one relay must connect\n const connected = results.filter((r) => r.status === 'fulfilled');\n if (connected.length === 0) {\n throw new RelayError('all', 'Failed to connect to any relay');\n }\n\n this.connected = true;\n }\n\n /**\n * Fetch contact lists from all connected relays\n */\n async fetchContactLists(\n pubkeys: string[],\n timeout = 10000\n ): Promise<Map<string, NostrContactEvent>> {\n await this.connect();\n\n const results = new Map<string, NostrContactEvent>();\n\n // Fetch from all relays in parallel\n const allEvents = await Promise.all(\n this.relays.map((relay) =>\n relay.fetchContactLists(pubkeys, timeout).catch(() => [])\n )\n );\n\n // Merge results, keeping the most recent event for each pubkey\n for (const events of allEvents) {\n for (const event of events) {\n const existing = results.get(event.pubkey);\n if (!existing || event.created_at > existing.created_at) {\n results.set(event.pubkey, event);\n }\n }\n }\n\n return results;\n }\n\n /**\n * Close all relay connections\n */\n close(): void {\n for (const relay of this.relays) {\n relay.close();\n }\n this.relays = [];\n this.connected = false;\n }\n}\n\n/**\n * Extract followed pubkeys from a contact list event\n */\nexport function extractFollows(event: NostrContactEvent): string[] {\n const follows: string[] = [];\n\n for (const tag of event.tags) {\n if (tag[0] === 'p' && tag[1]) {\n // Validate pubkey format (64 hex chars)\n if (/^[0-9a-f]{64}$/i.test(tag[1])) {\n follows.push(tag[1].toLowerCase());\n }\n }\n }\n\n return follows;\n}\n","import type {\n LocalWoTOptions,\n ScoringConfig,\n QueryOptions,\n DistanceResult,\n BatchResult,\n SyncOptions,\n StorageAdapter,\n} from '../types';\nimport { ValidationError } from '../errors';\nimport {\n DEFAULT_MAX_HOPS,\n MAX_BATCH_SIZE,\n mergeScoringConfig,\n calculateTrustScore,\n isValidPubkey,\n isValidRelayUrl,\n normalizePubkey,\n chunk,\n} from '../utils';\nimport { createStorage } from './storage';\nimport { RelayPool, extractFollows } from './relay';\n\n/**\n * Storage keys\n */\nconst KEYS = {\n FOLLOWS_PREFIX: 'follows:',\n META_PREFIX: 'meta:',\n SYNC_DEPTH: 'sync:depth',\n SYNC_TIME: 'sync:time',\n};\n\n/**\n * LocalWoT - Compute Web of Trust locally without oracle\n */\nexport class LocalWoT {\n private readonly myPubkey: string;\n private readonly relayUrls: string[];\n private readonly maxHops: number;\n private readonly scoring: ScoringConfig;\n private storage: StorageAdapter;\n private pool: RelayPool | null = null;\n\n constructor(options: LocalWoTOptions) {\n if (!options.myPubkey) {\n throw new ValidationError('myPubkey is required', 'myPubkey');\n }\n if (!isValidPubkey(options.myPubkey)) {\n throw new ValidationError(\n 'myPubkey must be a valid 64-character hex string',\n 'myPubkey'\n );\n }\n if (!options.relays || options.relays.length === 0) {\n throw new ValidationError('At least one relay URL is required', 'relays');\n }\n for (const relay of options.relays) {\n if (!isValidRelayUrl(relay)) {\n throw new ValidationError(\n `Invalid relay URL: ${relay}. Must be wss:// or ws://`,\n 'relays'\n );\n }\n }\n\n this.myPubkey = normalizePubkey(options.myPubkey);\n this.relayUrls = options.relays;\n this.maxHops = options.maxHops ?? DEFAULT_MAX_HOPS;\n this.scoring = mergeScoringConfig(options.scoring);\n this.storage = createStorage(options.storage ?? 'memory');\n }\n\n /**\n * Get or create relay pool\n */\n private getPool(): RelayPool {\n if (!this.pool) {\n this.pool = new RelayPool(this.relayUrls);\n }\n return this.pool;\n }\n\n /**\n * Get follows for a pubkey from storage\n */\n private async getFollows(pubkey: string): Promise<string[] | null> {\n const data = await this.storage.get(KEYS.FOLLOWS_PREFIX + pubkey);\n if (!data) return null;\n try {\n return JSON.parse(data) as string[];\n } catch {\n return null;\n }\n }\n\n /**\n * Set follows for a pubkey in storage\n */\n private async setFollows(pubkey: string, follows: string[]): Promise<void> {\n await this.storage.set(KEYS.FOLLOWS_PREFIX + pubkey, JSON.stringify(follows));\n }\n\n /**\n * Check if a pubkey follows another\n */\n private async doesFollow(from: string, to: string): Promise<boolean> {\n const follows = await this.getFollows(from);\n return follows?.includes(to) ?? false;\n }\n\n /**\n * Sync follow graph from relays\n * @param options - Sync options\n */\n async sync(options: SyncOptions = {}): Promise<void> {\n const depth = options.depth ?? 2;\n const onProgress = options.onProgress;\n\n const pool = this.getPool();\n const visited = new Set<string>();\n let currentLayer = new Set([this.myPubkey]);\n\n for (let d = 0; d < depth; d++) {\n const toFetch = Array.from(currentLayer).filter((pk) => !visited.has(pk));\n\n if (toFetch.length === 0) break;\n\n // Report progress\n if (onProgress) {\n onProgress({\n currentDepth: d + 1,\n totalDepth: depth,\n processed: 0,\n total: toFetch.length,\n });\n }\n\n // Fetch in batches\n const nextLayer = new Set<string>();\n const batches = chunk(toFetch, 100);\n let processed = 0;\n\n for (const batch of batches) {\n const events = await pool.fetchContactLists(batch);\n\n for (const [pubkey, event] of events) {\n visited.add(pubkey);\n const follows = extractFollows(event);\n await this.setFollows(pubkey, follows);\n\n // Add follows to next layer\n if (d < depth - 1) {\n for (const follow of follows) {\n if (!visited.has(follow)) {\n nextLayer.add(follow);\n }\n }\n }\n }\n\n // Mark pubkeys without events as having no follows\n for (const pubkey of batch) {\n if (!events.has(pubkey)) {\n visited.add(pubkey);\n await this.setFollows(pubkey, []);\n }\n }\n\n processed += batch.length;\n\n if (onProgress) {\n onProgress({\n currentDepth: d + 1,\n totalDepth: depth,\n processed,\n total: toFetch.length,\n });\n }\n }\n\n currentLayer = nextLayer;\n }\n\n // Save sync metadata\n await this.storage.set(KEYS.SYNC_DEPTH, String(depth));\n await this.storage.set(KEYS.SYNC_TIME, String(Date.now()));\n }\n\n /**\n * BFS to find shortest path between two pubkeys\n */\n private async findShortestPath(\n from: string,\n to: string,\n maxHops: number\n ): Promise<{ distance: number; paths: number; bridges: string[] } | null> {\n if (from === to) {\n return { distance: 0, paths: 1, bridges: [] };\n }\n\n const visited = new Set<string>([from]);\n let currentLayer = [from];\n let distance = 0;\n const bridges: string[] = [];\n let pathCount = 0;\n\n while (currentLayer.length > 0 && distance < maxHops) {\n distance++;\n const nextLayer: string[] = [];\n let foundInLayer = false;\n\n for (const pubkey of currentLayer) {\n const follows = await this.getFollows(pubkey);\n if (!follows) continue;\n\n for (const follow of follows) {\n if (follow === to) {\n foundInLayer = true;\n pathCount++;\n // Track first-hop bridges\n if (distance === 1) {\n bridges.push(pubkey);\n } else if (!bridges.includes(pubkey)) {\n // Track bridges (pubkeys that lead to target)\n const firstHop = currentLayer.find((pk) =>\n this.getFollows(pk).then((f) => f?.includes(pubkey))\n );\n if (firstHop && !bridges.includes(firstHop)) {\n bridges.push(firstHop);\n }\n }\n } else if (!visited.has(follow)) {\n visited.add(follow);\n nextLayer.push(follow);\n }\n }\n }\n\n if (foundInLayer) {\n return { distance, paths: pathCount, bridges };\n }\n\n currentLayer = nextLayer;\n }\n\n return null;\n }\n\n /**\n * Validates a pubkey parameter\n */\n private validatePubkey(pubkey: string, paramName: string): string {\n if (!pubkey) {\n throw new ValidationError(`${paramName} is required`, paramName);\n }\n if (!isValidPubkey(pubkey)) {\n throw new ValidationError(\n `${paramName} must be a valid 64-character hex string`,\n paramName\n );\n }\n return normalizePubkey(pubkey);\n }\n\n /**\n * Get shortest path length to target pubkey\n */\n async getDistance(\n target: string,\n options?: QueryOptions\n ): Promise<number | null> {\n const normalizedTarget = this.validatePubkey(target, 'target');\n const maxHops = options?.maxHops ?? this.maxHops;\n\n const result = await this.findShortestPath(\n this.myPubkey,\n normalizedTarget,\n maxHops\n );\n return result?.distance ?? null;\n }\n\n /**\n * Check if target is within your Web of Trust\n */\n async isInMyWoT(target: string, options?: QueryOptions): Promise<boolean> {\n const distance = await this.getDistance(target, options);\n const maxHops = options?.maxHops ?? this.maxHops;\n return distance !== null && distance <= maxHops;\n }\n\n /**\n * Get computed trust score based on distance and weights\n */\n async getTrustScore(target: string, options?: QueryOptions): Promise<number> {\n const details = await this.getDetails(target, options);\n if (!details) return 0;\n return calculateTrustScore(details, this.scoring);\n }\n\n /**\n * Get distance between any two pubkeys\n */\n async getDistanceBetween(\n from: string,\n to: string,\n options?: QueryOptions\n ): Promise<number | null> {\n const normalizedFrom = this.validatePubkey(from, 'from');\n const normalizedTo = this.validatePubkey(to, 'to');\n const maxHops = options?.maxHops ?? this.maxHops;\n\n const result = await this.findShortestPath(normalizedFrom, normalizedTo, maxHops);\n return result?.distance ?? null;\n }\n\n /**\n * Check multiple pubkeys efficiently\n */\n async batchCheck(\n targets: string[],\n options?: QueryOptions\n ): Promise<Map<string, BatchResult>> {\n if (!Array.isArray(targets) || targets.length === 0) {\n throw new ValidationError('targets must be a non-empty array', 'targets');\n }\n if (targets.length > MAX_BATCH_SIZE) {\n throw new ValidationError(\n `targets array exceeds maximum size of ${MAX_BATCH_SIZE}`,\n 'targets'\n );\n }\n\n const results = new Map<string, BatchResult>();\n const maxHops = options?.maxHops ?? this.maxHops;\n\n for (const target of targets) {\n const normalizedTarget = this.validatePubkey(target, 'target');\n const details = await this.getDetails(normalizedTarget, options);\n\n results.set(normalizedTarget, {\n pubkey: normalizedTarget,\n distance: details?.hops ?? null,\n score: details ? calculateTrustScore(details, this.scoring) : 0,\n inWoT: details !== null && details.hops <= maxHops,\n });\n }\n\n return results;\n }\n\n /**\n * Get full distance result with bridges and path count\n */\n async getDetails(\n target: string,\n options?: QueryOptions\n ): Promise<DistanceResult | null> {\n const normalizedTarget = this.validatePubkey(target, 'target');\n const maxHops = options?.maxHops ?? this.maxHops;\n\n const result = await this.findShortestPath(\n this.myPubkey,\n normalizedTarget,\n maxHops\n );\n\n if (!result) return null;\n\n // Check for mutual follow\n const mutual = await this.doesFollow(normalizedTarget, this.myPubkey);\n\n return {\n hops: result.distance,\n paths: result.paths,\n bridges: result.bridges,\n mutual,\n };\n }\n\n /**\n * Clear all stored data\n */\n async clear(): Promise<void> {\n await this.storage.clear();\n }\n\n /**\n * Close relay connections\n */\n close(): void {\n if (this.pool) {\n this.pool.close();\n this.pool = null;\n }\n }\n\n /**\n * Get the current pubkey\n */\n getMyPubkey(): string {\n return this.myPubkey;\n }\n\n /**\n * Get sync status\n */\n async getSyncStatus(): Promise<{ depth: number; time: number } | null> {\n const depth = await this.storage.get(KEYS.SYNC_DEPTH);\n const time = await this.storage.get(KEYS.SYNC_TIME);\n\n if (!depth || !time) return null;\n\n return {\n depth: parseInt(depth, 10),\n time: parseInt(time, 10),\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/errors.ts","../../src/utils.ts","../../src/local/storage.ts","../../src/local/relay.ts","../../src/local/local-wot.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base error class for WoT SDK errors\n */\nexport class WoTError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WoTError';\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n // Fix prototype chain for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when a network request fails\n */\nexport class NetworkError extends WoTError {\n public readonly statusCode?: number;\n public readonly url?: string;\n\n constructor(message: string, statusCode?: number, url?: string) {\n super(message);\n this.name = 'NetworkError';\n this.statusCode = statusCode;\n this.url = url;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when a pubkey is not found in the graph\n */\nexport class NotFoundError extends WoTError {\n public readonly pubkey: string;\n\n constructor(pubkey: string, message?: string) {\n super(message || `Pubkey not found in graph: ${pubkey}`);\n this.name = 'NotFoundError';\n this.pubkey = pubkey;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when a request times out\n */\nexport class TimeoutError extends WoTError {\n public readonly timeout: number;\n\n constructor(timeout: number, message?: string) {\n super(message || `Request timed out after ${timeout}ms`);\n this.name = 'TimeoutError';\n this.timeout = timeout;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when validation fails\n */\nexport class ValidationError extends WoTError {\n public readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message);\n this.name = 'ValidationError';\n this.field = field;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when local storage operations fail\n */\nexport class StorageError extends WoTError {\n public readonly operation: string;\n\n constructor(operation: string, message?: string) {\n super(message || `Storage operation failed: ${operation}`);\n this.name = 'StorageError';\n this.operation = operation;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when relay connection fails\n */\nexport class RelayError extends WoTError {\n public readonly relay: string;\n\n constructor(relay: string, message?: string) {\n super(message || `Relay connection failed: ${relay}`);\n this.name = 'RelayError';\n this.relay = relay;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import type { ScoringConfig, DistanceResult } from './types';\n\n/**\n * Default scoring configuration\n */\nexport const DEFAULT_SCORING: ScoringConfig = {\n distanceWeights: {\n 1: 1.0,\n 2: 0.5,\n 3: 0.25,\n 4: 0.1,\n },\n mutualBonus: 0.5,\n pathBonus: 0.1,\n maxPathBonus: 0.5,\n};\n\n/**\n * Default oracle URL\n */\nexport const DEFAULT_ORACLE = 'https://nostr-wot.com';\n\n/**\n * Default max hops for WoT queries\n */\nexport const DEFAULT_MAX_HOPS = 3;\n\n/**\n * Default timeout in milliseconds\n */\nexport const DEFAULT_TIMEOUT = 5000;\n\n/**\n * Validates a hex pubkey\n */\nexport function isValidPubkey(pubkey: string): boolean {\n return /^[0-9a-f]{64}$/i.test(pubkey);\n}\n\n/**\n * Validates an oracle URL (must be HTTPS)\n */\nexport function isValidOracleUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a relay URL (must be WSS or WS)\n */\nexport function isValidRelayUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'wss:' || parsed.protocol === 'ws:';\n } catch {\n return false;\n }\n}\n\n/**\n * Maximum allowed batch size for array inputs\n */\nexport const MAX_BATCH_SIZE = 10000;\n\n/**\n * Normalizes a pubkey to lowercase hex\n */\nexport function normalizePubkey(pubkey: string): string {\n return pubkey.toLowerCase();\n}\n\n/**\n * Merges scoring configuration with defaults\n */\nexport function mergeScoringConfig(\n partial?: Partial<ScoringConfig>\n): ScoringConfig {\n if (!partial) return { ...DEFAULT_SCORING };\n\n return {\n distanceWeights: {\n ...DEFAULT_SCORING.distanceWeights,\n ...partial.distanceWeights,\n },\n mutualBonus: partial.mutualBonus ?? DEFAULT_SCORING.mutualBonus,\n pathBonus: partial.pathBonus ?? DEFAULT_SCORING.pathBonus,\n maxPathBonus: partial.maxPathBonus ?? DEFAULT_SCORING.maxPathBonus,\n };\n}\n\n/**\n * Calculates trust score based on distance result and scoring config\n *\n * Formula:\n * score = (baseScore × distanceWeight) + bonuses\n *\n * where:\n * baseScore = 1 / (hops + 1)\n * bonuses = mutualBonus (if mutual) + min(pathBonus × (paths - 1), maxPathBonus)\n *\n * Example: 2 hops + 30% path bonus = 0.5 + 0.3 = 0.80\n *\n * Note: `mutual` is optional (only available from oracle, not extension)\n */\nexport function calculateTrustScore(\n result: DistanceResult,\n scoring: ScoringConfig\n): number {\n const { hops, paths, mutual } = result;\n const { distanceWeights, mutualBonus, pathBonus, maxPathBonus } = scoring;\n\n // Base score decreases with distance\n const baseScore = 1 / (hops + 1);\n\n // Get distance weight (default to lowest defined weight for distant hops)\n const maxDefinedHop = Math.max(...Object.keys(distanceWeights).map(Number));\n const distanceWeight =\n distanceWeights[hops] ?? distanceWeights[maxDefinedHop] ?? 0.1;\n\n // Calculate bonuses\n let bonuses = 0;\n\n // Mutual follow bonus (only if mutual info is available)\n if (mutual === true) {\n bonuses += mutualBonus;\n }\n\n // Path count bonus (more paths = more trust)\n if (paths > 1) {\n const pathCountBonus = Math.min(pathBonus * (paths - 1), maxPathBonus);\n bonuses += pathCountBonus;\n }\n\n // Final score using additive formula (clamped to 0-1)\n const score = (baseScore * distanceWeight) + bonuses;\n return Math.min(1, Math.max(0, score));\n}\n\n/**\n * Creates a fetch request with timeout\n */\nexport async function fetchWithTimeout(\n url: string,\n options: RequestInit & { timeout?: number } = {}\n): Promise<Response> {\n const { timeout = DEFAULT_TIMEOUT, ...fetchOptions } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n return await fetch(url, {\n ...fetchOptions,\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Delays execution for specified milliseconds\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Chunks an array into smaller arrays\n */\nexport function chunk<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Creates a deferred promise\n */\nexport interface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: unknown) => void;\n}\n\nexport function createDeferred<T>(): Deferred<T> {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason?: unknown) => void;\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { promise, resolve, reject };\n}\n","import type { StorageAdapter } from '../types';\nimport { StorageError } from '../errors';\n\n/**\n * In-memory storage adapter\n */\nexport class MemoryStorage implements StorageAdapter {\n private data = new Map<string, string>();\n\n async get(key: string): Promise<string | null> {\n return this.data.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.data.set(key, value);\n }\n\n async delete(key: string): Promise<void> {\n this.data.delete(key);\n }\n\n async clear(): Promise<void> {\n this.data.clear();\n }\n\n async keys(): Promise<string[]> {\n return Array.from(this.data.keys());\n }\n}\n\n/**\n * IndexedDB storage adapter\n */\nexport class IndexedDBStorage implements StorageAdapter {\n private dbName: string;\n private storeName = 'wot-data';\n private db: IDBDatabase | null = null;\n private dbPromise: Promise<IDBDatabase> | null = null;\n\n constructor(dbName = 'nostr-wot-sdk') {\n this.dbName = dbName;\n }\n\n private async getDB(): Promise<IDBDatabase> {\n if (this.db) return this.db;\n if (this.dbPromise) return this.dbPromise;\n\n this.dbPromise = new Promise((resolve, reject) => {\n if (typeof indexedDB === 'undefined') {\n reject(new StorageError('open', 'IndexedDB is not available'));\n return;\n }\n\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => {\n reject(new StorageError('open', request.error?.message));\n };\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve(request.result);\n };\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n });\n\n return this.dbPromise;\n }\n\n async get(key: string): Promise<string | null> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readonly');\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n\n request.onerror = () => {\n reject(new StorageError('get', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve(request.result ?? null);\n };\n });\n }\n\n async set(key: string, value: string): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n\n request.onerror = () => {\n reject(new StorageError('set', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve();\n };\n });\n }\n\n async delete(key: string): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.delete(key);\n\n request.onerror = () => {\n reject(new StorageError('delete', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve();\n };\n });\n }\n\n async clear(): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.clear();\n\n request.onerror = () => {\n reject(new StorageError('clear', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve();\n };\n });\n }\n\n async keys(): Promise<string[]> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readonly');\n const store = transaction.objectStore(this.storeName);\n const request = store.getAllKeys();\n\n request.onerror = () => {\n reject(new StorageError('keys', request.error?.message));\n };\n\n request.onsuccess = () => {\n resolve(request.result.map(String));\n };\n });\n }\n\n close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n this.dbPromise = null;\n }\n }\n}\n\n/**\n * Creates a storage adapter based on type\n */\nexport function createStorage(\n type: 'memory' | 'indexeddb' | StorageAdapter\n): StorageAdapter {\n if (typeof type === 'object') {\n return type;\n }\n\n switch (type) {\n case 'indexeddb':\n return new IndexedDBStorage();\n case 'memory':\n default:\n return new MemoryStorage();\n }\n}\n","import type { NostrContactEvent } from '../types';\nimport { RelayError } from '../errors';\nimport { createDeferred, type Deferred } from '../utils';\n\n/**\n * Nostr relay subscription filter\n */\ninterface NostrFilter {\n kinds?: number[];\n authors?: string[];\n '#p'?: string[];\n since?: number;\n until?: number;\n limit?: number;\n}\n\n/**\n * Nostr relay message types\n */\ntype NostrMessage =\n | ['EVENT', string, NostrContactEvent]\n | ['EOSE', string]\n | ['NOTICE', string]\n | ['OK', string, boolean, string];\n\n/**\n * Simple Nostr relay connection for fetching contact lists (kind 3)\n */\nexport class RelayConnection {\n private url: string;\n private ws: WebSocket | null = null;\n private subscriptions = new Map<\n string,\n {\n filter: NostrFilter;\n events: NostrContactEvent[];\n deferred: Deferred<NostrContactEvent[]>;\n }\n >();\n private connectPromise: Promise<void> | null = null;\n private subIdCounter = 0;\n\n constructor(url: string) {\n this.url = url;\n }\n\n /**\n * Connect to the relay\n */\n async connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.connectPromise = new Promise((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => {\n this.connectPromise = null;\n resolve();\n };\n\n this.ws.onerror = (event) => {\n this.connectPromise = null;\n reject(new RelayError(this.url, `Connection error: ${event}`));\n };\n\n this.ws.onclose = () => {\n this.ws = null;\n this.connectPromise = null;\n };\n\n this.ws.onmessage = (event) => {\n try {\n const message = JSON.parse(event.data) as NostrMessage;\n this.handleMessage(message);\n } catch {\n // Ignore malformed messages\n }\n };\n } catch (error) {\n this.connectPromise = null;\n reject(\n new RelayError(\n this.url,\n error instanceof Error ? error.message : 'Connection failed'\n )\n );\n }\n });\n\n return this.connectPromise;\n }\n\n /**\n * Handle incoming relay message\n */\n private handleMessage(message: NostrMessage): void {\n const [type, subId] = message;\n\n if (type === 'EVENT') {\n const event = message[2];\n const sub = this.subscriptions.get(subId);\n if (sub && event.kind === 3) {\n sub.events.push(event);\n }\n } else if (type === 'EOSE') {\n const sub = this.subscriptions.get(subId);\n if (sub) {\n sub.deferred.resolve(sub.events);\n this.subscriptions.delete(subId);\n this.send(['CLOSE', subId]);\n }\n }\n }\n\n /**\n * Send a message to the relay\n */\n private send(message: unknown[]): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(message));\n }\n }\n\n /**\n * Fetch contact lists for given pubkeys\n */\n async fetchContactLists(\n pubkeys: string[],\n timeout = 10000\n ): Promise<NostrContactEvent[]> {\n await this.connect();\n\n const subId = `wot-${++this.subIdCounter}`;\n const filter: NostrFilter = {\n kinds: [3],\n authors: pubkeys,\n };\n\n const deferred = createDeferred<NostrContactEvent[]>();\n\n this.subscriptions.set(subId, {\n filter,\n events: [],\n deferred,\n });\n\n // Send subscription request\n this.send(['REQ', subId, filter]);\n\n // Set timeout\n const timeoutId = setTimeout(() => {\n const sub = this.subscriptions.get(subId);\n if (sub) {\n sub.deferred.resolve(sub.events);\n this.subscriptions.delete(subId);\n this.send(['CLOSE', subId]);\n }\n }, timeout);\n\n try {\n return await deferred.promise;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Close the relay connection\n */\n close(): void {\n // Close all pending subscriptions\n for (const [subId, sub] of this.subscriptions) {\n sub.deferred.resolve(sub.events);\n this.send(['CLOSE', subId]);\n }\n this.subscriptions.clear();\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n /**\n * Get relay URL\n */\n getUrl(): string {\n return this.url;\n }\n}\n\n/**\n * Pool of relay connections\n */\nexport class RelayPool {\n private relays: RelayConnection[] = [];\n private connected = false;\n\n constructor(urls: string[]) {\n this.relays = urls.map((url) => new RelayConnection(url));\n }\n\n /**\n * Connect to all relays\n */\n async connect(): Promise<void> {\n if (this.connected) return;\n\n const results = await Promise.allSettled(\n this.relays.map((relay) => relay.connect())\n );\n\n // At least one relay must connect\n const connected = results.filter((r) => r.status === 'fulfilled');\n if (connected.length === 0) {\n throw new RelayError('all', 'Failed to connect to any relay');\n }\n\n this.connected = true;\n }\n\n /**\n * Fetch contact lists from all connected relays\n */\n async fetchContactLists(\n pubkeys: string[],\n timeout = 10000\n ): Promise<Map<string, NostrContactEvent>> {\n await this.connect();\n\n const results = new Map<string, NostrContactEvent>();\n\n // Fetch from all relays in parallel\n const allEvents = await Promise.all(\n this.relays.map((relay) =>\n relay.fetchContactLists(pubkeys, timeout).catch(() => [])\n )\n );\n\n // Merge results, keeping the most recent event for each pubkey\n for (const events of allEvents) {\n for (const event of events) {\n const existing = results.get(event.pubkey);\n if (!existing || event.created_at > existing.created_at) {\n results.set(event.pubkey, event);\n }\n }\n }\n\n return results;\n }\n\n /**\n * Close all relay connections\n */\n close(): void {\n for (const relay of this.relays) {\n relay.close();\n }\n this.relays = [];\n this.connected = false;\n }\n}\n\n/**\n * Extract followed pubkeys from a contact list event\n */\nexport function extractFollows(event: NostrContactEvent): string[] {\n const follows: string[] = [];\n\n for (const tag of event.tags) {\n if (tag[0] === 'p' && tag[1]) {\n // Validate pubkey format (64 hex chars)\n if (/^[0-9a-f]{64}$/i.test(tag[1])) {\n follows.push(tag[1].toLowerCase());\n }\n }\n }\n\n return follows;\n}\n","import type {\n LocalWoTOptions,\n ScoringConfig,\n QueryOptions,\n DistanceResult,\n BatchResult,\n SyncOptions,\n StorageAdapter,\n} from '../types';\nimport { ValidationError } from '../errors';\nimport {\n DEFAULT_MAX_HOPS,\n MAX_BATCH_SIZE,\n mergeScoringConfig,\n calculateTrustScore,\n isValidPubkey,\n isValidRelayUrl,\n normalizePubkey,\n chunk,\n} from '../utils';\nimport { createStorage } from './storage';\nimport { RelayPool, extractFollows } from './relay';\n\n/**\n * Storage keys\n */\nconst KEYS = {\n FOLLOWS_PREFIX: 'follows:',\n META_PREFIX: 'meta:',\n SYNC_DEPTH: 'sync:depth',\n SYNC_TIME: 'sync:time',\n};\n\n/**\n * LocalWoT - Compute Web of Trust locally without oracle\n */\nexport class LocalWoT {\n private readonly myPubkey: string;\n private readonly relayUrls: string[];\n private readonly maxHops: number;\n private readonly scoring: ScoringConfig;\n private storage: StorageAdapter;\n private pool: RelayPool | null = null;\n\n constructor(options: LocalWoTOptions) {\n if (!options.myPubkey) {\n throw new ValidationError('myPubkey is required', 'myPubkey');\n }\n if (!isValidPubkey(options.myPubkey)) {\n throw new ValidationError(\n 'myPubkey must be a valid 64-character hex string',\n 'myPubkey'\n );\n }\n if (!options.relays || options.relays.length === 0) {\n throw new ValidationError('At least one relay URL is required', 'relays');\n }\n for (const relay of options.relays) {\n if (!isValidRelayUrl(relay)) {\n throw new ValidationError(\n `Invalid relay URL: ${relay}. Must be wss:// or ws://`,\n 'relays'\n );\n }\n }\n\n this.myPubkey = normalizePubkey(options.myPubkey);\n this.relayUrls = options.relays;\n this.maxHops = options.maxHops ?? DEFAULT_MAX_HOPS;\n this.scoring = mergeScoringConfig(options.scoring);\n this.storage = createStorage(options.storage ?? 'memory');\n }\n\n /**\n * Get or create relay pool\n */\n private getPool(): RelayPool {\n if (!this.pool) {\n this.pool = new RelayPool(this.relayUrls);\n }\n return this.pool;\n }\n\n /**\n * Get follows for a pubkey from storage\n */\n private async getFollows(pubkey: string): Promise<string[] | null> {\n const data = await this.storage.get(KEYS.FOLLOWS_PREFIX + pubkey);\n if (!data) return null;\n try {\n return JSON.parse(data) as string[];\n } catch {\n return null;\n }\n }\n\n /**\n * Set follows for a pubkey in storage\n */\n private async setFollows(pubkey: string, follows: string[]): Promise<void> {\n await this.storage.set(KEYS.FOLLOWS_PREFIX + pubkey, JSON.stringify(follows));\n }\n\n /**\n * Check if a pubkey follows another\n */\n private async doesFollow(from: string, to: string): Promise<boolean> {\n const follows = await this.getFollows(from);\n return follows?.includes(to) ?? false;\n }\n\n /**\n * Sync follow graph from relays\n * @param options - Sync options\n */\n async sync(options: SyncOptions = {}): Promise<void> {\n const depth = options.depth ?? 2;\n const onProgress = options.onProgress;\n\n const pool = this.getPool();\n const visited = new Set<string>();\n let currentLayer = new Set([this.myPubkey]);\n\n for (let d = 0; d < depth; d++) {\n const toFetch = Array.from(currentLayer).filter((pk) => !visited.has(pk));\n\n if (toFetch.length === 0) break;\n\n // Report progress\n if (onProgress) {\n onProgress({\n currentDepth: d + 1,\n totalDepth: depth,\n processed: 0,\n total: toFetch.length,\n });\n }\n\n // Fetch in batches\n const nextLayer = new Set<string>();\n const batches = chunk(toFetch, 100);\n let processed = 0;\n\n for (const batch of batches) {\n const events = await pool.fetchContactLists(batch);\n\n for (const [pubkey, event] of events) {\n visited.add(pubkey);\n const follows = extractFollows(event);\n await this.setFollows(pubkey, follows);\n\n // Add follows to next layer\n if (d < depth - 1) {\n for (const follow of follows) {\n if (!visited.has(follow)) {\n nextLayer.add(follow);\n }\n }\n }\n }\n\n // Mark pubkeys without events as having no follows\n for (const pubkey of batch) {\n if (!events.has(pubkey)) {\n visited.add(pubkey);\n await this.setFollows(pubkey, []);\n }\n }\n\n processed += batch.length;\n\n if (onProgress) {\n onProgress({\n currentDepth: d + 1,\n totalDepth: depth,\n processed,\n total: toFetch.length,\n });\n }\n }\n\n currentLayer = nextLayer;\n }\n\n // Save sync metadata\n await this.storage.set(KEYS.SYNC_DEPTH, String(depth));\n await this.storage.set(KEYS.SYNC_TIME, String(Date.now()));\n }\n\n /**\n * BFS to find shortest path between two pubkeys\n */\n private async findShortestPath(\n from: string,\n to: string,\n maxHops: number\n ): Promise<{ distance: number; paths: number; bridges: string[] } | null> {\n if (from === to) {\n return { distance: 0, paths: 1, bridges: [] };\n }\n\n const visited = new Set<string>([from]);\n let currentLayer = [from];\n let distance = 0;\n const bridges: string[] = [];\n let pathCount = 0;\n\n while (currentLayer.length > 0 && distance < maxHops) {\n distance++;\n const nextLayer: string[] = [];\n let foundInLayer = false;\n\n for (const pubkey of currentLayer) {\n const follows = await this.getFollows(pubkey);\n if (!follows) continue;\n\n for (const follow of follows) {\n if (follow === to) {\n foundInLayer = true;\n pathCount++;\n // Track first-hop bridges\n if (distance === 1) {\n bridges.push(pubkey);\n } else if (!bridges.includes(pubkey)) {\n // Track bridges (pubkeys that lead to target)\n const firstHop = currentLayer.find((pk) =>\n this.getFollows(pk).then((f) => f?.includes(pubkey))\n );\n if (firstHop && !bridges.includes(firstHop)) {\n bridges.push(firstHop);\n }\n }\n } else if (!visited.has(follow)) {\n visited.add(follow);\n nextLayer.push(follow);\n }\n }\n }\n\n if (foundInLayer) {\n return { distance, paths: pathCount, bridges };\n }\n\n currentLayer = nextLayer;\n }\n\n return null;\n }\n\n /**\n * Validates a pubkey parameter\n */\n private validatePubkey(pubkey: string, paramName: string): string {\n if (!pubkey) {\n throw new ValidationError(`${paramName} is required`, paramName);\n }\n if (!isValidPubkey(pubkey)) {\n throw new ValidationError(\n `${paramName} must be a valid 64-character hex string`,\n paramName\n );\n }\n return normalizePubkey(pubkey);\n }\n\n /**\n * Get shortest path length to target pubkey\n */\n async getDistance(\n target: string,\n options?: QueryOptions\n ): Promise<number | null> {\n const normalizedTarget = this.validatePubkey(target, 'target');\n const maxHops = options?.maxHops ?? this.maxHops;\n\n const result = await this.findShortestPath(\n this.myPubkey,\n normalizedTarget,\n maxHops\n );\n return result?.distance ?? null;\n }\n\n /**\n * Check if target is within your Web of Trust\n */\n async isInMyWoT(target: string, options?: QueryOptions): Promise<boolean> {\n const distance = await this.getDistance(target, options);\n const maxHops = options?.maxHops ?? this.maxHops;\n return distance !== null && distance <= maxHops;\n }\n\n /**\n * Get computed trust score based on distance and weights\n */\n async getTrustScore(target: string, options?: QueryOptions): Promise<number> {\n const details = await this.getDetails(target, options);\n if (!details) return 0;\n return calculateTrustScore(details, this.scoring);\n }\n\n /**\n * Get distance between any two pubkeys\n */\n async getDistanceBetween(\n from: string,\n to: string,\n options?: QueryOptions\n ): Promise<number | null> {\n const normalizedFrom = this.validatePubkey(from, 'from');\n const normalizedTo = this.validatePubkey(to, 'to');\n const maxHops = options?.maxHops ?? this.maxHops;\n\n const result = await this.findShortestPath(normalizedFrom, normalizedTo, maxHops);\n return result?.distance ?? null;\n }\n\n /**\n * Check multiple pubkeys efficiently\n */\n async batchCheck(\n targets: string[],\n options?: QueryOptions\n ): Promise<Map<string, BatchResult>> {\n if (!Array.isArray(targets) || targets.length === 0) {\n throw new ValidationError('targets must be a non-empty array', 'targets');\n }\n if (targets.length > MAX_BATCH_SIZE) {\n throw new ValidationError(\n `targets array exceeds maximum size of ${MAX_BATCH_SIZE}`,\n 'targets'\n );\n }\n\n const results = new Map<string, BatchResult>();\n const maxHops = options?.maxHops ?? this.maxHops;\n\n for (const target of targets) {\n const normalizedTarget = this.validatePubkey(target, 'target');\n const details = await this.getDetails(normalizedTarget, options);\n\n results.set(normalizedTarget, {\n pubkey: normalizedTarget,\n distance: details?.hops ?? null,\n score: details ? calculateTrustScore(details, this.scoring) : 0,\n inWoT: details !== null && details.hops <= maxHops,\n });\n }\n\n return results;\n }\n\n /**\n * Get full distance result with bridges and path count\n */\n async getDetails(\n target: string,\n options?: QueryOptions\n ): Promise<DistanceResult | null> {\n const normalizedTarget = this.validatePubkey(target, 'target');\n const maxHops = options?.maxHops ?? this.maxHops;\n\n const result = await this.findShortestPath(\n this.myPubkey,\n normalizedTarget,\n maxHops\n );\n\n if (!result) return null;\n\n // Check for mutual follow\n const mutual = await this.doesFollow(normalizedTarget, this.myPubkey);\n\n return {\n hops: result.distance,\n paths: result.paths,\n bridges: result.bridges,\n mutual,\n };\n }\n\n /**\n * Clear all stored data\n */\n async clear(): Promise<void> {\n await this.storage.clear();\n }\n\n /**\n * Close relay connections\n */\n close(): void {\n if (this.pool) {\n this.pool.close();\n this.pool = null;\n }\n }\n\n /**\n * Get the current pubkey\n */\n getMyPubkey(): string {\n return this.myPubkey;\n }\n\n /**\n * Get sync status\n */\n async getSyncStatus(): Promise<{ depth: number; time: number } | null> {\n const depth = await this.storage.get(KEYS.SYNC_DEPTH);\n const time = await this.storage.get(KEYS.SYNC_TIME);\n\n if (!depth || !time) return null;\n\n return {\n depth: parseInt(depth, 10),\n time: parseInt(time, 10),\n };\n }\n}\n"]}
|
package/dist/local/index.js
CHANGED
|
@@ -90,7 +90,7 @@ function calculateTrustScore(result, scoring) {
|
|
|
90
90
|
const pathCountBonus = Math.min(pathBonus * (paths - 1), maxPathBonus);
|
|
91
91
|
bonuses += pathCountBonus;
|
|
92
92
|
}
|
|
93
|
-
const score = baseScore * distanceWeight
|
|
93
|
+
const score = baseScore * distanceWeight + bonuses;
|
|
94
94
|
return Math.min(1, Math.max(0, score));
|
|
95
95
|
}
|
|
96
96
|
function chunk(array, size) {
|