@antseed/node 0.1.0 → 0.1.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.
Files changed (140) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +7 -5
  3. package/dist/discovery/http-metadata-resolver.d.ts +6 -0
  4. package/dist/discovery/http-metadata-resolver.d.ts.map +1 -1
  5. package/dist/discovery/http-metadata-resolver.js +32 -4
  6. package/dist/discovery/http-metadata-resolver.js.map +1 -1
  7. package/dist/discovery/peer-lookup.d.ts +1 -0
  8. package/dist/discovery/peer-lookup.d.ts.map +1 -1
  9. package/dist/discovery/peer-lookup.js +10 -25
  10. package/dist/discovery/peer-lookup.js.map +1 -1
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/interfaces/seller-provider.d.ts +13 -1
  16. package/dist/interfaces/seller-provider.d.ts.map +1 -1
  17. package/dist/node.d.ts +13 -3
  18. package/dist/node.d.ts.map +1 -1
  19. package/dist/node.js +146 -21
  20. package/dist/node.js.map +1 -1
  21. package/dist/proxy/proxy-mux.d.ts +3 -1
  22. package/dist/proxy/proxy-mux.d.ts.map +1 -1
  23. package/dist/proxy/proxy-mux.js +9 -5
  24. package/dist/proxy/proxy-mux.js.map +1 -1
  25. package/dist/types/http.d.ts +1 -0
  26. package/dist/types/http.d.ts.map +1 -1
  27. package/dist/types/http.js +1 -1
  28. package/dist/types/http.js.map +1 -1
  29. package/package.json +14 -10
  30. package/contracts/AntseedEscrow.sol +0 -310
  31. package/contracts/MockUSDC.sol +0 -64
  32. package/contracts/README.md +0 -102
  33. package/src/config/encryption.test.ts +0 -49
  34. package/src/config/encryption.ts +0 -53
  35. package/src/config/plugin-config-manager.test.ts +0 -92
  36. package/src/config/plugin-config-manager.ts +0 -153
  37. package/src/config/plugin-loader.ts +0 -90
  38. package/src/discovery/announcer.ts +0 -169
  39. package/src/discovery/bootstrap.ts +0 -57
  40. package/src/discovery/default-metadata-resolver.ts +0 -18
  41. package/src/discovery/dht-health.ts +0 -136
  42. package/src/discovery/dht-node.ts +0 -191
  43. package/src/discovery/http-metadata-resolver.ts +0 -47
  44. package/src/discovery/index.ts +0 -15
  45. package/src/discovery/metadata-codec.ts +0 -453
  46. package/src/discovery/metadata-resolver.ts +0 -7
  47. package/src/discovery/metadata-server.ts +0 -73
  48. package/src/discovery/metadata-validator.ts +0 -172
  49. package/src/discovery/peer-lookup.ts +0 -122
  50. package/src/discovery/peer-metadata.ts +0 -34
  51. package/src/discovery/peer-selector.ts +0 -134
  52. package/src/discovery/profile-manager.ts +0 -131
  53. package/src/discovery/profile-search.ts +0 -100
  54. package/src/discovery/reputation-verifier.ts +0 -54
  55. package/src/index.ts +0 -61
  56. package/src/interfaces/buyer-router.ts +0 -21
  57. package/src/interfaces/plugin.ts +0 -36
  58. package/src/interfaces/seller-provider.ts +0 -81
  59. package/src/metering/index.ts +0 -6
  60. package/src/metering/receipt-generator.ts +0 -105
  61. package/src/metering/receipt-verifier.ts +0 -102
  62. package/src/metering/session-tracker.ts +0 -145
  63. package/src/metering/storage.ts +0 -600
  64. package/src/metering/token-counter.ts +0 -127
  65. package/src/metering/usage-aggregator.ts +0 -236
  66. package/src/node.ts +0 -1698
  67. package/src/p2p/connection-auth.ts +0 -152
  68. package/src/p2p/connection-manager.ts +0 -916
  69. package/src/p2p/handshake.ts +0 -162
  70. package/src/p2p/ice-config.ts +0 -59
  71. package/src/p2p/identity.ts +0 -110
  72. package/src/p2p/index.ts +0 -11
  73. package/src/p2p/keepalive.ts +0 -118
  74. package/src/p2p/message-protocol.ts +0 -171
  75. package/src/p2p/nat-traversal.ts +0 -169
  76. package/src/p2p/payment-codec.ts +0 -165
  77. package/src/p2p/payment-mux.ts +0 -153
  78. package/src/p2p/reconnect.ts +0 -117
  79. package/src/payments/balance-manager.ts +0 -77
  80. package/src/payments/buyer-payment-manager.ts +0 -414
  81. package/src/payments/disputes.ts +0 -72
  82. package/src/payments/evm/escrow-client.ts +0 -263
  83. package/src/payments/evm/keypair.ts +0 -31
  84. package/src/payments/evm/signatures.ts +0 -103
  85. package/src/payments/evm/wallet.ts +0 -42
  86. package/src/payments/index.ts +0 -50
  87. package/src/payments/settlement.ts +0 -40
  88. package/src/payments/types.ts +0 -79
  89. package/src/proxy/index.ts +0 -3
  90. package/src/proxy/provider-detection.ts +0 -78
  91. package/src/proxy/proxy-mux.ts +0 -173
  92. package/src/proxy/request-codec.ts +0 -294
  93. package/src/reputation/index.ts +0 -6
  94. package/src/reputation/rating-manager.ts +0 -118
  95. package/src/reputation/report-manager.ts +0 -91
  96. package/src/reputation/trust-engine.ts +0 -120
  97. package/src/reputation/trust-score.ts +0 -74
  98. package/src/reputation/uptime-tracker.ts +0 -155
  99. package/src/routing/default-router.ts +0 -75
  100. package/src/types/bittorrent-dht.d.ts +0 -19
  101. package/src/types/buyer.ts +0 -37
  102. package/src/types/capability.ts +0 -34
  103. package/src/types/connection.ts +0 -29
  104. package/src/types/http.ts +0 -20
  105. package/src/types/index.ts +0 -14
  106. package/src/types/metering.ts +0 -175
  107. package/src/types/nat-api.d.ts +0 -29
  108. package/src/types/peer-profile.ts +0 -25
  109. package/src/types/peer.ts +0 -62
  110. package/src/types/plugin-config.ts +0 -31
  111. package/src/types/protocol.ts +0 -162
  112. package/src/types/provider.ts +0 -40
  113. package/src/types/rating.ts +0 -23
  114. package/src/types/report.ts +0 -30
  115. package/src/types/seller.ts +0 -38
  116. package/src/types/staking.ts +0 -23
  117. package/src/utils/debug.ts +0 -30
  118. package/src/utils/hex.ts +0 -14
  119. package/tests/balance-manager.test.ts +0 -156
  120. package/tests/bootstrap.test.ts +0 -108
  121. package/tests/buyer-payment-manager.test.ts +0 -358
  122. package/tests/connection-auth.test.ts +0 -87
  123. package/tests/default-router.test.ts +0 -148
  124. package/tests/evm-keypair.test.ts +0 -173
  125. package/tests/identity.test.ts +0 -133
  126. package/tests/message-protocol.test.ts +0 -212
  127. package/tests/metadata-codec.test.ts +0 -165
  128. package/tests/metadata-validator.test.ts +0 -261
  129. package/tests/metering-storage.test.ts +0 -244
  130. package/tests/payment-codec.test.ts +0 -95
  131. package/tests/payment-mux.test.ts +0 -191
  132. package/tests/peer-selector.test.ts +0 -184
  133. package/tests/provider-detection.test.ts +0 -107
  134. package/tests/proxy-mux-security.test.ts +0 -38
  135. package/tests/receipt.test.ts +0 -215
  136. package/tests/reputation-integration.test.ts +0 -195
  137. package/tests/request-codec.test.ts +0 -144
  138. package/tests/token-counter.test.ts +0 -122
  139. package/tsconfig.json +0 -9
  140. package/vitest.config.ts +0 -7
@@ -1,414 +0,0 @@
1
- import { randomBytes } from 'node:crypto';
2
- import { type AbstractSigner, Wallet } from 'ethers';
3
- import type { Identity } from '../p2p/identity.js';
4
- import type { PaymentMux } from '../p2p/payment-mux.js';
5
- import type {
6
- SessionLockConfirmPayload,
7
- SessionLockRejectPayload,
8
- SellerReceiptPayload,
9
- TopUpRequestPayload,
10
- } from '../types/protocol.js';
11
- import { BaseEscrowClient } from './evm/escrow-client.js';
12
- import { identityToEvmWallet, identityToEvmAddress } from './evm/keypair.js';
13
- import {
14
- buildLockMessageHash,
15
- buildSettlementMessageHash,
16
- buildExtendLockMessageHash,
17
- signMessageEcdsa,
18
- buildAckMessage,
19
- signMessageEd25519,
20
- } from './evm/signatures.js';
21
- import { bytesToHex, hexToBytes } from '../utils/hex.js';
22
- import { debugLog, debugWarn } from '../utils/debug.js';
23
-
24
- export interface BuyerPaymentConfig {
25
- /** Default lock amount in USDC base units (6 decimals). e.g. "1000000" = 1 USDC */
26
- defaultLockAmountUSDC: string;
27
- /** Base JSON-RPC endpoint */
28
- rpcUrl: string;
29
- /** Deployed AntseedEscrow contract address */
30
- contractAddress: string;
31
- /** USDC token contract address */
32
- usdcAddress: string;
33
- /** Auto-acknowledge seller receipts. Default: true */
34
- autoAck?: boolean;
35
- /** Auto-approve top-up requests. Default: true */
36
- autoTopUp?: boolean;
37
- /** Maximum total amount the buyer will commit per session (USDC base units). Default: "10000000" (10 USDC) */
38
- maxSessionBudgetUSDC?: string;
39
- }
40
-
41
- export type BuyerSessionStatus = 'pending' | 'confirmed' | 'active' | 'ending' | 'ended';
42
-
43
- export interface BuyerSessionState {
44
- sessionId: string;
45
- sellerPeerId: string;
46
- sellerEvmAddress: string;
47
- lockedAmount: bigint;
48
- status: BuyerSessionStatus;
49
- txSignature: string | null;
50
- lastRunningTotal: bigint;
51
- lastRequestCount: number;
52
- createdAt: number;
53
- updatedAt: number;
54
- }
55
-
56
- /**
57
- * Manages buyer-side bilateral payment sessions across seller connections.
58
- *
59
- * Handles the full lifecycle: lock initiation, receipt acknowledgement,
60
- * top-up approval, and session settlement.
61
- */
62
- export class BuyerPaymentManager {
63
- private readonly _identity: Identity;
64
- private _signer: AbstractSigner;
65
- private readonly _escrowClient: BaseEscrowClient;
66
- private readonly _config: BuyerPaymentConfig;
67
- private readonly _sessions = new Map<string, BuyerSessionState>();
68
-
69
- constructor(identity: Identity, config: BuyerPaymentConfig) {
70
- this._identity = identity;
71
- this._config = config;
72
- this._signer = identityToEvmWallet(identity);
73
- this._escrowClient = new BaseEscrowClient({
74
- rpcUrl: config.rpcUrl,
75
- contractAddress: config.contractAddress,
76
- usdcAddress: config.usdcAddress,
77
- });
78
- }
79
-
80
- get signer(): AbstractSigner {
81
- return this._signer;
82
- }
83
-
84
- /** @deprecated Use .signer instead */
85
- get wallet(): Wallet {
86
- return this._signer as Wallet;
87
- }
88
-
89
- /** Replace the signer at runtime (e.g. with a WalletConnect signer). */
90
- setSigner(signer: AbstractSigner): void {
91
- this._signer = signer;
92
- }
93
-
94
- get escrowClient(): BaseEscrowClient {
95
- return this._escrowClient;
96
- }
97
-
98
- /** Get a snapshot of all active sessions. */
99
- getActiveSessions(): BuyerSessionState[] {
100
- return [...this._sessions.values()].filter(
101
- (s) => s.status !== 'ended',
102
- );
103
- }
104
-
105
- /** Get the session for a given seller peer, if it exists. */
106
- getSession(sellerPeerId: string): BuyerSessionState | undefined {
107
- return this._sessions.get(sellerPeerId);
108
- }
109
-
110
- // ── Lock initiation ─────────────────────────────────────────────
111
-
112
- /**
113
- * Generate a session ID, sign a lock authorization, and send it
114
- * to the seller via PaymentMux.
115
- */
116
- async initiateLock(
117
- sellerPeerId: string,
118
- sellerEvmAddress: string,
119
- paymentMux: PaymentMux,
120
- lockAmount?: string,
121
- ): Promise<string> {
122
- const amount = lockAmount ?? this._config.defaultLockAmountUSDC;
123
- const amountBigInt = BigInt(amount);
124
-
125
- // Generate a 32-byte session ID as 0x-prefixed hex (bytes32)
126
- const sessionIdBytes = randomBytes(32);
127
- const sessionId = '0x' + sessionIdBytes.toString('hex');
128
-
129
- debugLog(`[BuyerPayment] Initiating lock: session=${sessionId.slice(0, 18)}... seller=${sellerPeerId.slice(0, 12)}... amount=${amount}`);
130
-
131
- // Sign the lock message with ECDSA (for on-chain verification)
132
- const messageHash = buildLockMessageHash(sessionId, sellerEvmAddress, amountBigInt);
133
- const buyerSig = await signMessageEcdsa(this._signer, messageHash);
134
-
135
- // Store session state
136
- const now = Date.now();
137
- const session: BuyerSessionState = {
138
- sessionId,
139
- sellerPeerId,
140
- sellerEvmAddress,
141
- lockedAmount: amountBigInt,
142
- status: 'pending',
143
- txSignature: null,
144
- lastRunningTotal: 0n,
145
- lastRequestCount: 0,
146
- createdAt: now,
147
- updatedAt: now,
148
- };
149
- this._sessions.set(sellerPeerId, session);
150
-
151
- // Send the lock auth message
152
- paymentMux.sendSessionLockAuth({
153
- sessionId,
154
- lockedAmount: amount,
155
- buyerSig,
156
- });
157
-
158
- return sessionId;
159
- }
160
-
161
- // ── Lock confirmation / rejection handlers ──────────────────────
162
-
163
- /**
164
- * Called when the seller confirms the lock was committed on-chain.
165
- */
166
- handleLockConfirm(sellerPeerId: string, payload: SessionLockConfirmPayload): void {
167
- const session = this._sessions.get(sellerPeerId);
168
- if (!session) {
169
- debugWarn(`[BuyerPayment] Lock confirm for unknown seller: ${sellerPeerId.slice(0, 12)}...`);
170
- return;
171
- }
172
- if (session.sessionId !== payload.sessionId) {
173
- debugWarn(`[BuyerPayment] Lock confirm session mismatch: expected=${session.sessionId.slice(0, 18)}... got=${payload.sessionId.slice(0, 18)}...`);
174
- return;
175
- }
176
-
177
- session.status = 'confirmed';
178
- session.txSignature = payload.txSignature;
179
- session.updatedAt = Date.now();
180
- debugLog(`[BuyerPayment] Lock confirmed: session=${session.sessionId.slice(0, 18)}... tx=${payload.txSignature.slice(0, 12)}...`);
181
- }
182
-
183
- /**
184
- * Called when the seller rejects the lock.
185
- */
186
- handleLockReject(sellerPeerId: string, payload: SessionLockRejectPayload): void {
187
- const session = this._sessions.get(sellerPeerId);
188
- if (!session) {
189
- debugWarn(`[BuyerPayment] Lock reject for unknown seller: ${sellerPeerId.slice(0, 12)}...`);
190
- return;
191
- }
192
-
193
- debugWarn(`[BuyerPayment] Lock rejected: session=${session.sessionId.slice(0, 18)}... reason=${payload.reason}`);
194
- this._sessions.delete(sellerPeerId);
195
- }
196
-
197
- // ── Receipt handling ────────────────────────────────────────────
198
-
199
- /**
200
- * Handle a running-total receipt from the seller.
201
- * If autoAck is enabled, automatically counter-sign and send BuyerAck.
202
- */
203
- async handleSellerReceipt(
204
- sellerPeerId: string,
205
- receipt: SellerReceiptPayload,
206
- paymentMux: PaymentMux,
207
- ): Promise<void> {
208
- const session = this._sessions.get(sellerPeerId);
209
- if (!session) {
210
- debugWarn(`[BuyerPayment] Receipt for unknown seller: ${sellerPeerId.slice(0, 12)}...`);
211
- return;
212
- }
213
-
214
- if (session.status === 'confirmed') {
215
- session.status = 'active';
216
- }
217
-
218
- // Update running total
219
- session.lastRunningTotal = BigInt(receipt.runningTotal);
220
- session.lastRequestCount = receipt.requestCount;
221
- session.updatedAt = Date.now();
222
-
223
- debugLog(`[BuyerPayment] Receipt: session=${session.sessionId.slice(0, 18)}... total=${receipt.runningTotal} count=${receipt.requestCount}`);
224
-
225
- const autoAck = this._config.autoAck ?? true;
226
- if (autoAck) {
227
- // Build ack message and sign with Ed25519
228
- const sessionIdBytes = hexToBytes(session.sessionId.startsWith('0x') ? session.sessionId.slice(2) : session.sessionId);
229
- const ackMsg = buildAckMessage(
230
- sessionIdBytes,
231
- BigInt(receipt.runningTotal),
232
- receipt.requestCount,
233
- );
234
- const sigBytes = await signMessageEd25519(this._identity, ackMsg);
235
- const buyerSig = bytesToHex(sigBytes);
236
-
237
- paymentMux.sendBuyerAck({
238
- sessionId: session.sessionId,
239
- runningTotal: receipt.runningTotal,
240
- requestCount: receipt.requestCount,
241
- buyerSig,
242
- });
243
-
244
- debugLog(`[BuyerPayment] Auto-ack sent for session=${session.sessionId.slice(0, 18)}...`);
245
- }
246
- }
247
-
248
- // ── Top-up handling ─────────────────────────────────────────────
249
-
250
- /**
251
- * Handle a top-up request from the seller.
252
- * If autoTopUp is enabled and budget allows, sign and send TopUpAuth.
253
- * Otherwise, end the session.
254
- */
255
- async handleTopUpRequest(
256
- sellerPeerId: string,
257
- request: TopUpRequestPayload,
258
- paymentMux: PaymentMux,
259
- ): Promise<void> {
260
- const session = this._sessions.get(sellerPeerId);
261
- if (!session) {
262
- debugWarn(`[BuyerPayment] Top-up for unknown seller: ${sellerPeerId.slice(0, 12)}...`);
263
- return;
264
- }
265
-
266
- const additionalAmount = BigInt(request.additionalAmount);
267
- const maxBudget = BigInt(this._config.maxSessionBudgetUSDC ?? '10000000');
268
- const newTotal = session.lockedAmount + additionalAmount;
269
- const autoTopUp = this._config.autoTopUp ?? true;
270
-
271
- debugLog(`[BuyerPayment] Top-up request: session=${session.sessionId.slice(0, 18)}... additional=${request.additionalAmount} newTotal=${newTotal}`);
272
-
273
- if (autoTopUp && newTotal <= maxBudget) {
274
- // Check on-chain balance
275
- const buyerAddr = identityToEvmAddress(this._identity);
276
- const account = await this._escrowClient.getBuyerAccount(buyerAddr);
277
- if (account.available >= additionalAmount) {
278
- // Sign extend-lock authorization
279
- const messageHash = buildExtendLockMessageHash(
280
- session.sessionId,
281
- session.sellerEvmAddress,
282
- additionalAmount,
283
- );
284
- const buyerSig = await signMessageEcdsa(this._signer, messageHash);
285
-
286
- session.lockedAmount = newTotal;
287
- session.updatedAt = Date.now();
288
-
289
- paymentMux.sendTopUpAuth({
290
- sessionId: session.sessionId,
291
- additionalAmount: request.additionalAmount,
292
- buyerSig,
293
- });
294
-
295
- debugLog(`[BuyerPayment] Top-up authorized: session=${session.sessionId.slice(0, 18)}...`);
296
- return;
297
- }
298
-
299
- debugWarn(`[BuyerPayment] Insufficient balance for top-up. Available=${account.available}, requested=${additionalAmount}`);
300
- }
301
-
302
- // Cannot or will not top up — end the session
303
- debugLog(`[BuyerPayment] Declining top-up, ending session=${session.sessionId.slice(0, 18)}...`);
304
- await this.endSession(sellerPeerId, paymentMux, 80);
305
- }
306
-
307
- // ── Session end ─────────────────────────────────────────────────
308
-
309
- /**
310
- * End a session with the given seller. Signs a settlement message
311
- * with ECDSA and sends SessionEnd.
312
- */
313
- async endSession(
314
- sellerPeerId: string,
315
- paymentMux: PaymentMux,
316
- score: number = 80,
317
- ): Promise<void> {
318
- const session = this._sessions.get(sellerPeerId);
319
- if (!session) {
320
- debugWarn(`[BuyerPayment] Cannot end session for unknown seller: ${sellerPeerId.slice(0, 12)}...`);
321
- return;
322
- }
323
-
324
- if (session.status === 'ending' || session.status === 'ended') {
325
- return;
326
- }
327
-
328
- session.status = 'ending';
329
- session.updatedAt = Date.now();
330
-
331
- debugLog(`[BuyerPayment] Ending session=${session.sessionId.slice(0, 18)}... total=${session.lastRunningTotal} score=${score}`);
332
-
333
- // Sign settlement message with ECDSA
334
- const messageHash = buildSettlementMessageHash(
335
- session.sessionId,
336
- session.lastRunningTotal,
337
- score,
338
- );
339
- const buyerSig = await signMessageEcdsa(this._signer, messageHash);
340
-
341
- paymentMux.sendSessionEnd({
342
- sessionId: session.sessionId,
343
- runningTotal: session.lastRunningTotal.toString(),
344
- requestCount: session.lastRequestCount,
345
- score,
346
- buyerSig,
347
- });
348
-
349
- session.status = 'ended';
350
- session.updatedAt = Date.now();
351
- debugLog(`[BuyerPayment] Session ended: ${session.sessionId.slice(0, 18)}...`);
352
- }
353
-
354
- // ── Escrow operations ───────────────────────────────────────────
355
-
356
- /**
357
- * Deposit USDC into the escrow contract.
358
- * @param amount Amount in USDC base units (6 decimals).
359
- */
360
- async deposit(amount: bigint): Promise<string> {
361
- debugLog(`[BuyerPayment] Depositing ${amount} to escrow`);
362
- return this._escrowClient.deposit(this._signer, amount);
363
- }
364
-
365
- /**
366
- * Withdraw USDC from the escrow contract.
367
- * @param amount Amount in USDC base units (6 decimals).
368
- */
369
- async withdraw(amount: bigint): Promise<string> {
370
- debugLog(`[BuyerPayment] Withdrawing ${amount} from escrow`);
371
- return this._escrowClient.withdraw(this._signer, amount);
372
- }
373
-
374
- /**
375
- * Get the buyer's on-chain escrow balance.
376
- */
377
- async getBalance(): Promise<{ deposited: bigint; committed: bigint; available: bigint }> {
378
- const buyerAddr = identityToEvmAddress(this._identity);
379
- return this._escrowClient.getBuyerAccount(buyerAddr);
380
- }
381
-
382
- // ── Dispute helpers ─────────────────────────────────────────────
383
-
384
- /**
385
- * Release an expired lock (buyer reclaims funds).
386
- */
387
- async releaseExpiredLock(sessionId: string): Promise<string> {
388
- debugLog(`[BuyerPayment] Releasing expired lock: session=${sessionId.slice(0, 18)}...`);
389
- return this._escrowClient.releaseExpiredLock(this._signer, sessionId);
390
- }
391
-
392
- /**
393
- * Respond to a dispute opened by the seller.
394
- */
395
- async respondToDispute(sessionId: string): Promise<string> {
396
- debugLog(`[BuyerPayment] Responding to dispute: session=${sessionId.slice(0, 18)}...`);
397
- return this._escrowClient.respondDispute(this._signer, sessionId);
398
- }
399
-
400
- /**
401
- * Check if a session lock has been confirmed (for polling).
402
- */
403
- isLockConfirmed(sellerPeerId: string): boolean {
404
- const session = this._sessions.get(sellerPeerId);
405
- return session?.status === 'confirmed' || session?.status === 'active';
406
- }
407
-
408
- /**
409
- * Check if a session lock has been rejected (for polling).
410
- */
411
- isLockRejected(sellerPeerId: string): boolean {
412
- return !this._sessions.has(sellerPeerId);
413
- }
414
- }
@@ -1,72 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import type { PeerId } from '../types/peer.js';
3
- import type { UsageReceipt } from '../types/metering.js';
4
- import type { PaymentDispute } from './types.js';
5
-
6
- export const DISPUTE_TIMEOUT_MS = 72 * 60 * 60 * 1000;
7
-
8
- export function createDispute(
9
- channel: { channelId: string; sessionId: string },
10
- initiatorPeerId: PeerId,
11
- reason: string,
12
- buyerReceipts: UsageReceipt[],
13
- sellerReceipts: UsageReceipt[],
14
- ): PaymentDispute {
15
- return {
16
- disputeId: randomUUID(),
17
- channelId: channel.channelId,
18
- sessionId: channel.sessionId,
19
- initiatorPeerId,
20
- reason,
21
- status: 'open',
22
- buyerReceipts,
23
- sellerReceipts,
24
- createdAt: Date.now(),
25
- resolvedAt: null,
26
- resolution: null,
27
- };
28
- }
29
-
30
- export function detectDiscrepancy(
31
- buyerReceipts: UsageReceipt[],
32
- sellerReceipts: UsageReceipt[],
33
- thresholdPercent: number,
34
- ): { discrepancyDetected: boolean; buyerTotal: number; sellerTotal: number; diffPercent: number } {
35
- const buyerTotal = buyerReceipts.reduce((sum, r) => sum + r.tokens.totalTokens, 0);
36
- const sellerTotal = sellerReceipts.reduce((sum, r) => sum + r.tokens.totalTokens, 0);
37
- const max = Math.max(buyerTotal, sellerTotal);
38
- const diffPercent = max === 0 ? 0 : (Math.abs(buyerTotal - sellerTotal) / max) * 100;
39
- const discrepancyDetected = diffPercent > thresholdPercent;
40
-
41
- return {
42
- discrepancyDetected,
43
- buyerTotal,
44
- sellerTotal,
45
- diffPercent,
46
- };
47
- }
48
-
49
- export function resolveDispute(
50
- dispute: PaymentDispute,
51
- resolution: string,
52
- ): PaymentDispute {
53
- return {
54
- ...dispute,
55
- status: 'resolved',
56
- resolvedAt: Date.now(),
57
- resolution,
58
- };
59
- }
60
-
61
- export function isDisputeExpired(dispute: PaymentDispute): boolean {
62
- return Date.now() - dispute.createdAt > DISPUTE_TIMEOUT_MS;
63
- }
64
-
65
- export function calculateDisputedAmount(
66
- buyerReceipts: UsageReceipt[],
67
- sellerReceipts: UsageReceipt[],
68
- ): number {
69
- const buyerTotalUsd = buyerReceipts.reduce((sum, r) => sum + r.costCents, 0) / 100;
70
- const sellerTotalUsd = sellerReceipts.reduce((sum, r) => sum + r.costCents, 0) / 100;
71
- return Math.abs(buyerTotalUsd - sellerTotalUsd);
72
- }