@antseed/node 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/interfaces/seller-provider.d.ts +13 -1
  6. package/dist/interfaces/seller-provider.d.ts.map +1 -1
  7. package/dist/node.d.ts +13 -3
  8. package/dist/node.d.ts.map +1 -1
  9. package/dist/node.js +123 -15
  10. package/dist/node.js.map +1 -1
  11. package/dist/proxy/proxy-mux.d.ts +3 -1
  12. package/dist/proxy/proxy-mux.d.ts.map +1 -1
  13. package/dist/proxy/proxy-mux.js +9 -5
  14. package/dist/proxy/proxy-mux.js.map +1 -1
  15. package/dist/types/http.d.ts +1 -0
  16. package/dist/types/http.d.ts.map +1 -1
  17. package/dist/types/http.js +1 -1
  18. package/dist/types/http.js.map +1 -1
  19. package/package.json +14 -10
  20. package/contracts/AntseedEscrow.sol +0 -310
  21. package/contracts/MockUSDC.sol +0 -64
  22. package/contracts/README.md +0 -102
  23. package/src/config/encryption.test.ts +0 -49
  24. package/src/config/encryption.ts +0 -53
  25. package/src/config/plugin-config-manager.test.ts +0 -92
  26. package/src/config/plugin-config-manager.ts +0 -153
  27. package/src/config/plugin-loader.ts +0 -90
  28. package/src/discovery/announcer.ts +0 -169
  29. package/src/discovery/bootstrap.ts +0 -57
  30. package/src/discovery/default-metadata-resolver.ts +0 -18
  31. package/src/discovery/dht-health.ts +0 -136
  32. package/src/discovery/dht-node.ts +0 -191
  33. package/src/discovery/http-metadata-resolver.ts +0 -47
  34. package/src/discovery/index.ts +0 -15
  35. package/src/discovery/metadata-codec.ts +0 -453
  36. package/src/discovery/metadata-resolver.ts +0 -7
  37. package/src/discovery/metadata-server.ts +0 -73
  38. package/src/discovery/metadata-validator.ts +0 -172
  39. package/src/discovery/peer-lookup.ts +0 -122
  40. package/src/discovery/peer-metadata.ts +0 -34
  41. package/src/discovery/peer-selector.ts +0 -134
  42. package/src/discovery/profile-manager.ts +0 -131
  43. package/src/discovery/profile-search.ts +0 -100
  44. package/src/discovery/reputation-verifier.ts +0 -54
  45. package/src/index.ts +0 -61
  46. package/src/interfaces/buyer-router.ts +0 -21
  47. package/src/interfaces/plugin.ts +0 -36
  48. package/src/interfaces/seller-provider.ts +0 -81
  49. package/src/metering/index.ts +0 -6
  50. package/src/metering/receipt-generator.ts +0 -105
  51. package/src/metering/receipt-verifier.ts +0 -102
  52. package/src/metering/session-tracker.ts +0 -145
  53. package/src/metering/storage.ts +0 -600
  54. package/src/metering/token-counter.ts +0 -127
  55. package/src/metering/usage-aggregator.ts +0 -236
  56. package/src/node.ts +0 -1698
  57. package/src/p2p/connection-auth.ts +0 -152
  58. package/src/p2p/connection-manager.ts +0 -916
  59. package/src/p2p/handshake.ts +0 -162
  60. package/src/p2p/ice-config.ts +0 -59
  61. package/src/p2p/identity.ts +0 -110
  62. package/src/p2p/index.ts +0 -11
  63. package/src/p2p/keepalive.ts +0 -118
  64. package/src/p2p/message-protocol.ts +0 -171
  65. package/src/p2p/nat-traversal.ts +0 -169
  66. package/src/p2p/payment-codec.ts +0 -165
  67. package/src/p2p/payment-mux.ts +0 -153
  68. package/src/p2p/reconnect.ts +0 -117
  69. package/src/payments/balance-manager.ts +0 -77
  70. package/src/payments/buyer-payment-manager.ts +0 -414
  71. package/src/payments/disputes.ts +0 -72
  72. package/src/payments/evm/escrow-client.ts +0 -263
  73. package/src/payments/evm/keypair.ts +0 -31
  74. package/src/payments/evm/signatures.ts +0 -103
  75. package/src/payments/evm/wallet.ts +0 -42
  76. package/src/payments/index.ts +0 -50
  77. package/src/payments/settlement.ts +0 -40
  78. package/src/payments/types.ts +0 -79
  79. package/src/proxy/index.ts +0 -3
  80. package/src/proxy/provider-detection.ts +0 -78
  81. package/src/proxy/proxy-mux.ts +0 -173
  82. package/src/proxy/request-codec.ts +0 -294
  83. package/src/reputation/index.ts +0 -6
  84. package/src/reputation/rating-manager.ts +0 -118
  85. package/src/reputation/report-manager.ts +0 -91
  86. package/src/reputation/trust-engine.ts +0 -120
  87. package/src/reputation/trust-score.ts +0 -74
  88. package/src/reputation/uptime-tracker.ts +0 -155
  89. package/src/routing/default-router.ts +0 -75
  90. package/src/types/bittorrent-dht.d.ts +0 -19
  91. package/src/types/buyer.ts +0 -37
  92. package/src/types/capability.ts +0 -34
  93. package/src/types/connection.ts +0 -29
  94. package/src/types/http.ts +0 -20
  95. package/src/types/index.ts +0 -14
  96. package/src/types/metering.ts +0 -175
  97. package/src/types/nat-api.d.ts +0 -29
  98. package/src/types/peer-profile.ts +0 -25
  99. package/src/types/peer.ts +0 -62
  100. package/src/types/plugin-config.ts +0 -31
  101. package/src/types/protocol.ts +0 -162
  102. package/src/types/provider.ts +0 -40
  103. package/src/types/rating.ts +0 -23
  104. package/src/types/report.ts +0 -30
  105. package/src/types/seller.ts +0 -38
  106. package/src/types/staking.ts +0 -23
  107. package/src/utils/debug.ts +0 -30
  108. package/src/utils/hex.ts +0 -14
  109. package/tests/balance-manager.test.ts +0 -156
  110. package/tests/bootstrap.test.ts +0 -108
  111. package/tests/buyer-payment-manager.test.ts +0 -358
  112. package/tests/connection-auth.test.ts +0 -87
  113. package/tests/default-router.test.ts +0 -148
  114. package/tests/evm-keypair.test.ts +0 -173
  115. package/tests/identity.test.ts +0 -133
  116. package/tests/message-protocol.test.ts +0 -212
  117. package/tests/metadata-codec.test.ts +0 -165
  118. package/tests/metadata-validator.test.ts +0 -261
  119. package/tests/metering-storage.test.ts +0 -244
  120. package/tests/payment-codec.test.ts +0 -95
  121. package/tests/payment-mux.test.ts +0 -191
  122. package/tests/peer-selector.test.ts +0 -184
  123. package/tests/provider-detection.test.ts +0 -107
  124. package/tests/proxy-mux-security.test.ts +0 -38
  125. package/tests/receipt.test.ts +0 -215
  126. package/tests/reputation-integration.test.ts +0 -195
  127. package/tests/request-codec.test.ts +0 -144
  128. package/tests/token-counter.test.ts +0 -122
  129. package/tsconfig.json +0 -9
  130. package/vitest.config.ts +0 -7
@@ -1,173 +0,0 @@
1
- import { MessageType, type FramedMessage } from "../types/protocol.js";
2
- import type { PeerConnection } from "../p2p/connection-manager.js";
3
- import { encodeFrame } from "../p2p/message-protocol.js";
4
- import {
5
- encodeHttpRequest,
6
- decodeHttpRequest,
7
- encodeHttpResponse,
8
- decodeHttpResponse,
9
- encodeHttpResponseChunk,
10
- decodeHttpResponseChunk,
11
- } from "./request-codec.js";
12
- import type {
13
- SerializedHttpRequest,
14
- SerializedHttpResponse,
15
- SerializedHttpResponseChunk,
16
- } from "../types/http.js";
17
-
18
- type ResponseHandler = (response: SerializedHttpResponse) => void;
19
- type ChunkHandler = (chunk: SerializedHttpResponseChunk) => void;
20
- type RequestHandler = (request: SerializedHttpRequest) => void | Promise<void>;
21
-
22
- /**
23
- * Request/response multiplexer over DataChannel.
24
- * Handles both buyer-side and seller-side proxy communication.
25
- */
26
- export class ProxyMux {
27
- private readonly _connection: PeerConnection;
28
- private _messageIdCounter = 0;
29
-
30
- // Buyer side: pending requests awaiting responses
31
- private readonly _responseHandlers = new Map<string, ResponseHandler>();
32
- private readonly _chunkHandlers = new Map<string, ChunkHandler>();
33
-
34
- // Seller side: handler for incoming proxy requests
35
- private _requestHandler: RequestHandler | null = null;
36
-
37
- constructor(connection: PeerConnection) {
38
- this._connection = connection;
39
- }
40
-
41
- /** Buyer side: send a proxy request and register response/chunk handlers. */
42
- sendProxyRequest(
43
- request: SerializedHttpRequest,
44
- onResponse: ResponseHandler,
45
- onChunk: ChunkHandler
46
- ): void {
47
- this._responseHandlers.set(request.requestId, onResponse);
48
- this._chunkHandlers.set(request.requestId, onChunk);
49
-
50
- const payload = encodeHttpRequest(request);
51
- const frame = encodeFrame({
52
- type: MessageType.HttpRequest,
53
- messageId: this._nextMessageId(),
54
- payload,
55
- });
56
-
57
- this._connection.send(frame);
58
- }
59
-
60
- /** Buyer side: cancel handlers for an in-flight request. */
61
- cancelProxyRequest(requestId: string): void {
62
- this._responseHandlers.delete(requestId);
63
- this._chunkHandlers.delete(requestId);
64
- }
65
-
66
- /** Seller side: register a handler for incoming proxy requests. */
67
- onProxyRequest(handler: RequestHandler): void {
68
- this._requestHandler = handler;
69
- }
70
-
71
- /** Seller side: send a complete proxy response. */
72
- sendProxyResponse(response: SerializedHttpResponse): void {
73
- const payload = encodeHttpResponse(response);
74
- const frame = encodeFrame({
75
- type: MessageType.HttpResponse,
76
- messageId: this._nextMessageId(),
77
- payload,
78
- });
79
-
80
- this._connection.send(frame);
81
- }
82
-
83
- /** Seller side: send a proxy response chunk. */
84
- sendProxyChunk(chunk: SerializedHttpResponseChunk): void {
85
- const type = chunk.done
86
- ? MessageType.HttpResponseEnd
87
- : MessageType.HttpResponseChunk;
88
-
89
- const payload = encodeHttpResponseChunk(chunk);
90
- const frame = encodeFrame({
91
- type,
92
- messageId: this._nextMessageId(),
93
- payload,
94
- });
95
-
96
- this._connection.send(frame);
97
- }
98
-
99
- /** Route an incoming frame to the correct handler based on message type. */
100
- async handleFrame(frame: FramedMessage): Promise<void> {
101
- try {
102
- switch (frame.type) {
103
- case MessageType.HttpRequest: {
104
- // Seller side: incoming request from buyer
105
- if (this._requestHandler) {
106
- const request = decodeHttpRequest(frame.payload);
107
- await this._requestHandler(request);
108
- }
109
- break;
110
- }
111
- case MessageType.HttpResponse: {
112
- // Buyer side: complete response from seller
113
- const response = decodeHttpResponse(frame.payload);
114
- const handler = this._responseHandlers.get(response.requestId);
115
- if (handler) {
116
- this._responseHandlers.delete(response.requestId);
117
- this._chunkHandlers.delete(response.requestId);
118
- handler(response);
119
- }
120
- break;
121
- }
122
- case MessageType.HttpResponseChunk: {
123
- // Buyer side: streaming chunk from seller
124
- const chunk = decodeHttpResponseChunk(frame.payload);
125
- const chunkHandler = this._chunkHandlers.get(chunk.requestId);
126
- if (chunkHandler) {
127
- chunkHandler(chunk);
128
- }
129
- break;
130
- }
131
- case MessageType.HttpResponseEnd: {
132
- // Buyer side: final chunk (done=true) from seller
133
- const endChunk = decodeHttpResponseChunk(frame.payload);
134
- const endHandler = this._chunkHandlers.get(endChunk.requestId);
135
- if (endHandler) {
136
- endHandler(endChunk);
137
- this._responseHandlers.delete(endChunk.requestId);
138
- this._chunkHandlers.delete(endChunk.requestId);
139
- }
140
- break;
141
- }
142
- case MessageType.HttpResponseError: {
143
- // Buyer side: error response from seller
144
- const errorResponse = decodeHttpResponse(frame.payload);
145
- const errorHandler = this._responseHandlers.get(errorResponse.requestId);
146
- if (errorHandler) {
147
- this._responseHandlers.delete(errorResponse.requestId);
148
- this._chunkHandlers.delete(errorResponse.requestId);
149
- errorHandler(errorResponse);
150
- }
151
- break;
152
- }
153
- default:
154
- // Unknown message type — ignore
155
- break;
156
- }
157
- } catch (err) {
158
- const message = err instanceof Error ? err.message : String(err);
159
- throw new Error(`Failed to handle proxy frame type ${frame.type}: ${message}`);
160
- }
161
- }
162
-
163
- /** Number of in-flight requests (buyer side). */
164
- activeRequestCount(): number {
165
- return this._responseHandlers.size;
166
- }
167
-
168
- private _nextMessageId(): number {
169
- const id = this._messageIdCounter;
170
- this._messageIdCounter = (this._messageIdCounter + 1) & 0xFFFFFFFF;
171
- return id;
172
- }
173
- }
@@ -1,294 +0,0 @@
1
- import type {
2
- SerializedHttpRequest,
3
- SerializedHttpResponse,
4
- SerializedHttpResponseChunk,
5
- } from "../types/http.js";
6
-
7
- const encoder = new TextEncoder();
8
- const decoder = new TextDecoder();
9
-
10
- /**
11
- * Encode an HTTP request into binary format:
12
- * [requestIdLen:2][requestId:N][methodLen:1][method:N][pathLen:2][path:N]
13
- * [headerCount:2][for each header: keyLen:2, key:N, valLen:2, val:N]
14
- * [bodyLen:4][body:N]
15
- */
16
- export function encodeHttpRequest(req: SerializedHttpRequest): Uint8Array {
17
- const requestIdBytes = encoder.encode(req.requestId);
18
- const methodBytes = encoder.encode(req.method);
19
- const pathBytes = encoder.encode(req.path);
20
-
21
- const headerEntries = Object.entries(req.headers);
22
- const encodedHeaders: Array<{ key: Uint8Array; val: Uint8Array }> = [];
23
- let headersSize = 0;
24
- for (const [key, val] of headerEntries) {
25
- const keyBytes = encoder.encode(key);
26
- const valBytes = encoder.encode(val);
27
- encodedHeaders.push({ key: keyBytes, val: valBytes });
28
- headersSize += 2 + keyBytes.length + 2 + valBytes.length;
29
- }
30
-
31
- const totalSize =
32
- 2 + requestIdBytes.length +
33
- 1 + methodBytes.length +
34
- 2 + pathBytes.length +
35
- 2 + headersSize +
36
- 4 + req.body.length;
37
-
38
- const buf = new Uint8Array(totalSize);
39
- const view = new DataView(buf.buffer);
40
- let offset = 0;
41
-
42
- // requestId
43
- view.setUint16(offset, requestIdBytes.length);
44
- offset += 2;
45
- buf.set(requestIdBytes, offset);
46
- offset += requestIdBytes.length;
47
-
48
- // method
49
- view.setUint8(offset, methodBytes.length);
50
- offset += 1;
51
- buf.set(methodBytes, offset);
52
- offset += methodBytes.length;
53
-
54
- // path
55
- view.setUint16(offset, pathBytes.length);
56
- offset += 2;
57
- buf.set(pathBytes, offset);
58
- offset += pathBytes.length;
59
-
60
- // headers
61
- view.setUint16(offset, headerEntries.length);
62
- offset += 2;
63
- for (const { key, val } of encodedHeaders) {
64
- view.setUint16(offset, key.length);
65
- offset += 2;
66
- buf.set(key, offset);
67
- offset += key.length;
68
- view.setUint16(offset, val.length);
69
- offset += 2;
70
- buf.set(val, offset);
71
- offset += val.length;
72
- }
73
-
74
- // body
75
- view.setUint32(offset, req.body.length);
76
- offset += 4;
77
- buf.set(req.body, offset);
78
-
79
- return buf;
80
- }
81
-
82
- /**
83
- * Decode binary data into a SerializedHttpRequest.
84
- */
85
- export function decodeHttpRequest(data: Uint8Array): SerializedHttpRequest {
86
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
87
- let offset = 0;
88
-
89
- // requestId
90
- const requestIdLen = view.getUint16(offset);
91
- offset += 2;
92
- const requestId = decoder.decode(data.slice(offset, offset + requestIdLen));
93
- offset += requestIdLen;
94
-
95
- // method
96
- const methodLen = view.getUint8(offset);
97
- offset += 1;
98
- const method = decoder.decode(data.slice(offset, offset + methodLen));
99
- offset += methodLen;
100
-
101
- // path
102
- const pathLen = view.getUint16(offset);
103
- offset += 2;
104
- const path = decoder.decode(data.slice(offset, offset + pathLen));
105
- offset += pathLen;
106
-
107
- // headers
108
- const headerCount = view.getUint16(offset);
109
- offset += 2;
110
- const headers: Record<string, string> = {};
111
- for (let i = 0; i < headerCount; i++) {
112
- const keyLen = view.getUint16(offset);
113
- offset += 2;
114
- const key = decoder.decode(data.slice(offset, offset + keyLen));
115
- offset += keyLen;
116
- const valLen = view.getUint16(offset);
117
- offset += 2;
118
- const val = decoder.decode(data.slice(offset, offset + valLen));
119
- offset += valLen;
120
- headers[key] = val;
121
- }
122
-
123
- // body
124
- const bodyLen = view.getUint32(offset);
125
- offset += 4;
126
- const body = data.slice(offset, offset + bodyLen);
127
-
128
- return { requestId, method, path, headers, body };
129
- }
130
-
131
- /**
132
- * Encode an HTTP response into binary format:
133
- * [requestIdLen:2][requestId:N][statusCode:2]
134
- * [headerCount:2][for each header: keyLen:2, key:N, valLen:2, val:N]
135
- * [bodyLen:4][body:N]
136
- */
137
- export function encodeHttpResponse(resp: SerializedHttpResponse): Uint8Array {
138
- const requestIdBytes = encoder.encode(resp.requestId);
139
-
140
- const headerEntries = Object.entries(resp.headers);
141
- const encodedHeaders: Array<{ key: Uint8Array; val: Uint8Array }> = [];
142
- let headersSize = 0;
143
- for (const [key, val] of headerEntries) {
144
- const keyBytes = encoder.encode(key);
145
- const valBytes = encoder.encode(val);
146
- encodedHeaders.push({ key: keyBytes, val: valBytes });
147
- headersSize += 2 + keyBytes.length + 2 + valBytes.length;
148
- }
149
-
150
- const totalSize =
151
- 2 + requestIdBytes.length +
152
- 2 +
153
- 2 + headersSize +
154
- 4 + resp.body.length;
155
-
156
- const buf = new Uint8Array(totalSize);
157
- const view = new DataView(buf.buffer);
158
- let offset = 0;
159
-
160
- // requestId
161
- view.setUint16(offset, requestIdBytes.length);
162
- offset += 2;
163
- buf.set(requestIdBytes, offset);
164
- offset += requestIdBytes.length;
165
-
166
- // statusCode
167
- view.setUint16(offset, resp.statusCode);
168
- offset += 2;
169
-
170
- // headers
171
- view.setUint16(offset, headerEntries.length);
172
- offset += 2;
173
- for (const { key, val } of encodedHeaders) {
174
- view.setUint16(offset, key.length);
175
- offset += 2;
176
- buf.set(key, offset);
177
- offset += key.length;
178
- view.setUint16(offset, val.length);
179
- offset += 2;
180
- buf.set(val, offset);
181
- offset += val.length;
182
- }
183
-
184
- // body
185
- view.setUint32(offset, resp.body.length);
186
- offset += 4;
187
- buf.set(resp.body, offset);
188
-
189
- return buf;
190
- }
191
-
192
- /**
193
- * Decode binary data into a SerializedHttpResponse.
194
- */
195
- export function decodeHttpResponse(data: Uint8Array): SerializedHttpResponse {
196
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
197
- let offset = 0;
198
-
199
- // requestId
200
- const requestIdLen = view.getUint16(offset);
201
- offset += 2;
202
- const requestId = decoder.decode(data.slice(offset, offset + requestIdLen));
203
- offset += requestIdLen;
204
-
205
- // statusCode
206
- const statusCode = view.getUint16(offset);
207
- offset += 2;
208
-
209
- // headers
210
- const headerCount = view.getUint16(offset);
211
- offset += 2;
212
- const headers: Record<string, string> = {};
213
- for (let i = 0; i < headerCount; i++) {
214
- const keyLen = view.getUint16(offset);
215
- offset += 2;
216
- const key = decoder.decode(data.slice(offset, offset + keyLen));
217
- offset += keyLen;
218
- const valLen = view.getUint16(offset);
219
- offset += 2;
220
- const val = decoder.decode(data.slice(offset, offset + valLen));
221
- offset += valLen;
222
- headers[key] = val;
223
- }
224
-
225
- // body
226
- const bodyLen = view.getUint32(offset);
227
- offset += 4;
228
- const body = data.slice(offset, offset + bodyLen);
229
-
230
- return { requestId, statusCode, headers, body };
231
- }
232
-
233
- /**
234
- * Encode an HTTP response chunk into binary format:
235
- * [requestIdLen:2][requestId:N][done:1][dataLen:4][data:N]
236
- */
237
- export function encodeHttpResponseChunk(
238
- chunk: SerializedHttpResponseChunk
239
- ): Uint8Array {
240
- const requestIdBytes = encoder.encode(chunk.requestId);
241
-
242
- const totalSize =
243
- 2 + requestIdBytes.length +
244
- 1 +
245
- 4 + chunk.data.length;
246
-
247
- const buf = new Uint8Array(totalSize);
248
- const view = new DataView(buf.buffer);
249
- let offset = 0;
250
-
251
- // requestId
252
- view.setUint16(offset, requestIdBytes.length);
253
- offset += 2;
254
- buf.set(requestIdBytes, offset);
255
- offset += requestIdBytes.length;
256
-
257
- // done
258
- view.setUint8(offset, chunk.done ? 1 : 0);
259
- offset += 1;
260
-
261
- // data
262
- view.setUint32(offset, chunk.data.length);
263
- offset += 4;
264
- buf.set(chunk.data, offset);
265
-
266
- return buf;
267
- }
268
-
269
- /**
270
- * Decode binary data into a SerializedHttpResponseChunk.
271
- */
272
- export function decodeHttpResponseChunk(
273
- data: Uint8Array
274
- ): SerializedHttpResponseChunk {
275
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
276
- let offset = 0;
277
-
278
- // requestId
279
- const requestIdLen = view.getUint16(offset);
280
- offset += 2;
281
- const requestId = decoder.decode(data.slice(offset, offset + requestIdLen));
282
- offset += requestIdLen;
283
-
284
- // done
285
- const done = view.getUint8(offset) === 1;
286
- offset += 1;
287
-
288
- // data
289
- const dataLen = view.getUint32(offset);
290
- offset += 4;
291
- const chunkData = data.slice(offset, offset + dataLen);
292
-
293
- return { requestId, data: chunkData, done };
294
- }
@@ -1,6 +0,0 @@
1
- export { computeTrustScore, DEFAULT_TRUST_WEIGHTS, DEFAULT_COMPONENTS } from './trust-score.js';
2
- export type { TrustScore, TrustComponents } from './trust-score.js';
3
- export { TrustScoreEngine, type TrustEngineConfig } from './trust-engine.js';
4
- export { UptimeTracker, type UptimeTrackerConfig, type UptimeWindow, type PeerUptimeRecord } from './uptime-tracker.js';
5
- export { ReportManager, type ReportManagerConfig } from './report-manager.js';
6
- export { RatingManager, type RatingManagerConfig } from './rating-manager.js';
@@ -1,118 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import type { PeerId } from '../types/peer.js';
5
- import type { PeerRating, RatingDimension, AggregateRating } from '../types/rating.js';
6
- import type { Identity } from '../p2p/identity.js';
7
- import { signData } from '../p2p/identity.js';
8
- import { bytesToHex } from '../utils/hex.js';
9
-
10
- const HALF_LIFE_MS = 90 * 24 * 60 * 60 * 1000; // 90 days
11
- const DIMENSIONS: RatingDimension[] = ['quality', 'speed', 'reliability', 'value', 'overall'];
12
-
13
- export interface RatingManagerConfig {
14
- configDir: string;
15
- identity?: Identity;
16
- }
17
-
18
- export class RatingManager {
19
- private readonly configDir: string;
20
- private readonly identity: Identity | undefined;
21
- private ratings: PeerRating[] = [];
22
-
23
- constructor(config: RatingManagerConfig) {
24
- this.configDir = config.configDir;
25
- this.identity = config.identity;
26
- }
27
-
28
- async submitRating(
29
- targetPeerId: PeerId,
30
- sessionId: string,
31
- dimensions: Record<RatingDimension, 1 | 2 | 3 | 4 | 5>,
32
- comment?: string,
33
- ): Promise<PeerRating> {
34
- if (!this.identity) throw new Error('Identity required to submit ratings');
35
-
36
- const rating: PeerRating = {
37
- ratingId: randomUUID(),
38
- raterPeerId: this.identity.peerId as PeerId,
39
- targetPeerId,
40
- sessionId,
41
- dimensions,
42
- comment,
43
- timestamp: Date.now(),
44
- signature: '',
45
- };
46
-
47
- const dataToSign = `${rating.ratingId}:${rating.raterPeerId}:${rating.targetPeerId}:${rating.sessionId}:${rating.timestamp}`;
48
- const sig = await signData(this.identity.privateKey, new TextEncoder().encode(dataToSign));
49
- rating.signature = bytesToHex(sig);
50
-
51
- this.ratings.push(rating);
52
- await this.save();
53
- return rating;
54
- }
55
-
56
- getAggregateRating(peerId: PeerId): AggregateRating {
57
- const peerRatings = this.ratings.filter(r => r.targetPeerId === peerId);
58
- const now = Date.now();
59
-
60
- const weightedSums: Record<string, number> = Object.fromEntries(DIMENSIONS.map(d => [d, 0]));
61
- let totalWeight = 0;
62
-
63
- for (const rating of peerRatings) {
64
- // Exponential decay weight
65
- const age = now - rating.timestamp;
66
- const weight = Math.pow(0.5, age / HALF_LIFE_MS);
67
- totalWeight += weight;
68
-
69
- for (const dim of DIMENSIONS) {
70
- weightedSums[dim]! += rating.dimensions[dim] * weight;
71
- }
72
- }
73
-
74
- const averageByDimension = {} as Record<RatingDimension, number>;
75
- for (const dim of DIMENSIONS) {
76
- averageByDimension[dim] = totalWeight > 0
77
- ? Math.round((weightedSums[dim]! / totalWeight) * 100) / 100
78
- : 0;
79
- }
80
-
81
- const overallAverage = totalWeight > 0
82
- ? Math.round((DIMENSIONS.reduce((sum, dim) => sum + averageByDimension[dim], 0) / DIMENSIONS.length) * 100) / 100
83
- : 0;
84
-
85
- return {
86
- peerId,
87
- averageByDimension,
88
- overallAverage,
89
- totalRatings: peerRatings.length,
90
- lastUpdated: now,
91
- };
92
- }
93
-
94
- getRatingsFor(peerId: PeerId): PeerRating[] {
95
- return this.ratings.filter(r => r.targetPeerId === peerId);
96
- }
97
-
98
- getMyRatings(): PeerRating[] {
99
- if (!this.identity) return [];
100
- return this.ratings.filter(r => r.raterPeerId === this.identity!.peerId);
101
- }
102
-
103
- async save(): Promise<void> {
104
- await mkdir(this.configDir, { recursive: true });
105
- const filePath = join(this.configDir, 'ratings.json');
106
- await writeFile(filePath, JSON.stringify(this.ratings, null, 2), 'utf-8');
107
- }
108
-
109
- async load(): Promise<void> {
110
- const filePath = join(this.configDir, 'ratings.json');
111
- try {
112
- const raw = await readFile(filePath, 'utf-8');
113
- this.ratings = JSON.parse(raw) as PeerRating[];
114
- } catch {
115
- this.ratings = [];
116
- }
117
- }
118
- }
@@ -1,91 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import type { PeerId } from '../types/peer.js';
5
- import type { PeerReport, ReportReason, ReportEvidence } from '../types/report.js';
6
- import type { Identity } from '../p2p/identity.js';
7
- import { signData } from '../p2p/identity.js';
8
- import { bytesToHex } from '../utils/hex.js';
9
-
10
- export interface ReportManagerConfig {
11
- configDir: string;
12
- identity?: Identity;
13
- }
14
-
15
- export class ReportManager {
16
- private readonly configDir: string;
17
- private readonly identity: Identity | undefined;
18
- private reports: PeerReport[] = [];
19
-
20
- constructor(config: ReportManagerConfig) {
21
- this.configDir = config.configDir;
22
- this.identity = config.identity;
23
- }
24
-
25
- async submitReport(
26
- targetPeerId: PeerId,
27
- reason: ReportReason,
28
- evidence: ReportEvidence[],
29
- sessionId?: string,
30
- ): Promise<PeerReport> {
31
- if (!this.identity) throw new Error('Identity required to submit reports');
32
-
33
- const report: PeerReport = {
34
- reportId: randomUUID(),
35
- reporterPeerId: this.identity.peerId as PeerId,
36
- targetPeerId,
37
- reason,
38
- evidence,
39
- sessionId,
40
- timestamp: Date.now(),
41
- status: 'pending',
42
- signature: '',
43
- };
44
-
45
- // Sign the report
46
- const dataToSign = `${report.reportId}:${report.reporterPeerId}:${report.targetPeerId}:${report.reason}:${report.timestamp}`;
47
- const sig = await signData(this.identity.privateKey, new TextEncoder().encode(dataToSign));
48
- report.signature = bytesToHex(sig);
49
-
50
- this.reports.push(report);
51
- await this.save();
52
- return report;
53
- }
54
-
55
- getReportsAgainst(peerId: PeerId): PeerReport[] {
56
- return this.reports.filter(r => r.targetPeerId === peerId);
57
- }
58
-
59
- getMyReports(): PeerReport[] {
60
- if (!this.identity) return [];
61
- return this.reports.filter(r => r.reporterPeerId === this.identity!.peerId);
62
- }
63
-
64
- getReport(reportId: string): PeerReport | null {
65
- return this.reports.find(r => r.reportId === reportId) ?? null;
66
- }
67
-
68
- updateReportStatus(reportId: string, status: PeerReport['status']): void {
69
- const report = this.reports.find(r => r.reportId === reportId);
70
- if (report) {
71
- report.status = status;
72
- }
73
- }
74
-
75
- async save(): Promise<void> {
76
- const dir = join(this.configDir, 'reports');
77
- await mkdir(dir, { recursive: true });
78
- const filePath = join(dir, 'reports.json');
79
- await writeFile(filePath, JSON.stringify(this.reports, null, 2), 'utf-8');
80
- }
81
-
82
- async load(): Promise<void> {
83
- const filePath = join(this.configDir, 'reports', 'reports.json');
84
- try {
85
- const raw = await readFile(filePath, 'utf-8');
86
- this.reports = JSON.parse(raw) as PeerReport[];
87
- } catch {
88
- this.reports = [];
89
- }
90
- }
91
- }