@antseed/node 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +411 -0
- package/contracts/AntseedEscrow.sol +310 -0
- package/contracts/MockUSDC.sol +64 -0
- package/contracts/README.md +102 -0
- package/dist/config/encryption.d.ts +17 -0
- package/dist/config/encryption.d.ts.map +1 -0
- package/dist/config/encryption.js +49 -0
- package/dist/config/encryption.js.map +1 -0
- package/dist/config/plugin-config-manager.d.ts +31 -0
- package/dist/config/plugin-config-manager.d.ts.map +1 -0
- package/dist/config/plugin-config-manager.js +135 -0
- package/dist/config/plugin-config-manager.js.map +1 -0
- package/dist/config/plugin-loader.d.ts +25 -0
- package/dist/config/plugin-loader.d.ts.map +1 -0
- package/dist/config/plugin-loader.js +64 -0
- package/dist/config/plugin-loader.js.map +1 -0
- package/dist/discovery/announcer.d.ts +44 -0
- package/dist/discovery/announcer.d.ts.map +1 -0
- package/dist/discovery/announcer.js +129 -0
- package/dist/discovery/announcer.js.map +1 -0
- package/dist/discovery/bootstrap.d.ts +13 -0
- package/dist/discovery/bootstrap.d.ts.map +1 -0
- package/dist/discovery/bootstrap.js +39 -0
- package/dist/discovery/bootstrap.js.map +1 -0
- package/dist/discovery/default-metadata-resolver.d.ts +16 -0
- package/dist/discovery/default-metadata-resolver.d.ts.map +1 -0
- package/dist/discovery/default-metadata-resolver.js +16 -0
- package/dist/discovery/default-metadata-resolver.js.map +1 -0
- package/dist/discovery/dht-health.d.ts +38 -0
- package/dist/discovery/dht-health.d.ts.map +1 -0
- package/dist/discovery/dht-health.js +101 -0
- package/dist/discovery/dht-health.js.map +1 -0
- package/dist/discovery/dht-node.d.ts +34 -0
- package/dist/discovery/dht-node.d.ts.map +1 -0
- package/dist/discovery/dht-node.js +168 -0
- package/dist/discovery/dht-node.js.map +1 -0
- package/dist/discovery/http-metadata-resolver.d.ts +15 -0
- package/dist/discovery/http-metadata-resolver.d.ts.map +1 -0
- package/dist/discovery/http-metadata-resolver.js +33 -0
- package/dist/discovery/http-metadata-resolver.js.map +1 -0
- package/dist/discovery/index.d.ts +16 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +15 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/metadata-codec.d.ts +22 -0
- package/dist/discovery/metadata-codec.d.ts.map +1 -0
- package/dist/discovery/metadata-codec.js +390 -0
- package/dist/discovery/metadata-codec.js.map +1 -0
- package/dist/discovery/metadata-resolver.d.ts +9 -0
- package/dist/discovery/metadata-resolver.d.ts.map +1 -0
- package/dist/discovery/metadata-resolver.js +2 -0
- package/dist/discovery/metadata-resolver.js.map +1 -0
- package/dist/discovery/metadata-server.d.ts +16 -0
- package/dist/discovery/metadata-server.d.ts.map +1 -0
- package/dist/discovery/metadata-server.js +59 -0
- package/dist/discovery/metadata-server.js.map +1 -0
- package/dist/discovery/metadata-validator.d.ts +12 -0
- package/dist/discovery/metadata-validator.d.ts.map +1 -0
- package/dist/discovery/metadata-validator.js +153 -0
- package/dist/discovery/metadata-validator.js.map +1 -0
- package/dist/discovery/peer-lookup.d.ts +26 -0
- package/dist/discovery/peer-lookup.d.ts.map +1 -0
- package/dist/discovery/peer-lookup.js +86 -0
- package/dist/discovery/peer-lookup.js.map +1 -0
- package/dist/discovery/peer-metadata.d.ts +31 -0
- package/dist/discovery/peer-metadata.d.ts.map +1 -0
- package/dist/discovery/peer-metadata.js +2 -0
- package/dist/discovery/peer-metadata.js.map +1 -0
- package/dist/discovery/peer-selector.d.ts +33 -0
- package/dist/discovery/peer-selector.d.ts.map +1 -0
- package/dist/discovery/peer-selector.js +80 -0
- package/dist/discovery/peer-selector.js.map +1 -0
- package/dist/discovery/profile-manager.d.ts +50 -0
- package/dist/discovery/profile-manager.d.ts.map +1 -0
- package/dist/discovery/profile-manager.js +105 -0
- package/dist/discovery/profile-manager.js.map +1 -0
- package/dist/discovery/profile-search.d.ts +27 -0
- package/dist/discovery/profile-search.d.ts.map +1 -0
- package/dist/discovery/profile-search.js +75 -0
- package/dist/discovery/profile-search.js.map +1 -0
- package/dist/discovery/reputation-verifier.d.ts +25 -0
- package/dist/discovery/reputation-verifier.d.ts.map +1 -0
- package/dist/discovery/reputation-verifier.js +27 -0
- package/dist/discovery/reputation-verifier.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/buyer-router.d.ts +21 -0
- package/dist/interfaces/buyer-router.d.ts.map +1 -0
- package/dist/interfaces/buyer-router.js +2 -0
- package/dist/interfaces/buyer-router.js.map +1 -0
- package/dist/interfaces/plugin.d.ts +31 -0
- package/dist/interfaces/plugin.d.ts.map +1 -0
- package/dist/interfaces/plugin.js +2 -0
- package/dist/interfaces/plugin.js.map +1 -0
- package/dist/interfaces/seller-provider.d.ts +69 -0
- package/dist/interfaces/seller-provider.d.ts.map +1 -0
- package/dist/interfaces/seller-provider.js +2 -0
- package/dist/interfaces/seller-provider.js.map +1 -0
- package/dist/metering/index.d.ts +7 -0
- package/dist/metering/index.d.ts.map +1 -0
- package/dist/metering/index.js +7 -0
- package/dist/metering/index.js.map +1 -0
- package/dist/metering/receipt-generator.d.ts +49 -0
- package/dist/metering/receipt-generator.d.ts.map +1 -0
- package/dist/metering/receipt-generator.js +74 -0
- package/dist/metering/receipt-generator.js.map +1 -0
- package/dist/metering/receipt-verifier.d.ts +52 -0
- package/dist/metering/receipt-verifier.d.ts.map +1 -0
- package/dist/metering/receipt-verifier.js +63 -0
- package/dist/metering/receipt-verifier.js.map +1 -0
- package/dist/metering/session-tracker.d.ts +59 -0
- package/dist/metering/session-tracker.d.ts.map +1 -0
- package/dist/metering/session-tracker.js +119 -0
- package/dist/metering/session-tracker.js.map +1 -0
- package/dist/metering/storage.d.ts +72 -0
- package/dist/metering/storage.d.ts.map +1 -0
- package/dist/metering/storage.js +446 -0
- package/dist/metering/storage.js.map +1 -0
- package/dist/metering/token-counter.d.ts +50 -0
- package/dist/metering/token-counter.d.ts.map +1 -0
- package/dist/metering/token-counter.js +96 -0
- package/dist/metering/token-counter.js.map +1 -0
- package/dist/metering/usage-aggregator.d.ts +46 -0
- package/dist/metering/usage-aggregator.d.ts.map +1 -0
- package/dist/metering/usage-aggregator.js +170 -0
- package/dist/metering/usage-aggregator.js.map +1 -0
- package/dist/node.d.ts +179 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +1328 -0
- package/dist/node.js.map +1 -0
- package/dist/p2p/connection-auth.d.ts +35 -0
- package/dist/p2p/connection-auth.d.ts.map +1 -0
- package/dist/p2p/connection-auth.js +102 -0
- package/dist/p2p/connection-auth.js.map +1 -0
- package/dist/p2p/connection-manager.d.ts +101 -0
- package/dist/p2p/connection-manager.d.ts.map +1 -0
- package/dist/p2p/connection-manager.js +726 -0
- package/dist/p2p/connection-manager.js.map +1 -0
- package/dist/p2p/handshake.d.ts +47 -0
- package/dist/p2p/handshake.d.ts.map +1 -0
- package/dist/p2p/handshake.js +107 -0
- package/dist/p2p/handshake.js.map +1 -0
- package/dist/p2p/ice-config.d.ts +27 -0
- package/dist/p2p/ice-config.d.ts.map +1 -0
- package/dist/p2p/ice-config.js +43 -0
- package/dist/p2p/ice-config.js.map +1 -0
- package/dist/p2p/identity.d.ts +27 -0
- package/dist/p2p/identity.d.ts.map +1 -0
- package/dist/p2p/identity.js +76 -0
- package/dist/p2p/identity.js.map +1 -0
- package/dist/p2p/index.d.ts +12 -0
- package/dist/p2p/index.d.ts.map +1 -0
- package/dist/p2p/index.js +11 -0
- package/dist/p2p/index.js.map +1 -0
- package/dist/p2p/keepalive.d.ts +49 -0
- package/dist/p2p/keepalive.d.ts.map +1 -0
- package/dist/p2p/keepalive.js +93 -0
- package/dist/p2p/keepalive.js.map +1 -0
- package/dist/p2p/message-protocol.d.ts +50 -0
- package/dist/p2p/message-protocol.d.ts.map +1 -0
- package/dist/p2p/message-protocol.js +134 -0
- package/dist/p2p/message-protocol.js.map +1 -0
- package/dist/p2p/nat-traversal.d.ts +51 -0
- package/dist/p2p/nat-traversal.d.ts.map +1 -0
- package/dist/p2p/nat-traversal.js +135 -0
- package/dist/p2p/nat-traversal.js.map +1 -0
- package/dist/p2p/payment-codec.d.ts +20 -0
- package/dist/p2p/payment-codec.d.ts.map +1 -0
- package/dist/p2p/payment-codec.js +130 -0
- package/dist/p2p/payment-codec.js.map +1 -0
- package/dist/p2p/payment-mux.d.ts +49 -0
- package/dist/p2p/payment-mux.d.ts.map +1 -0
- package/dist/p2p/payment-mux.js +131 -0
- package/dist/p2p/payment-mux.js.map +1 -0
- package/dist/p2p/reconnect.d.ts +48 -0
- package/dist/p2p/reconnect.d.ts.map +1 -0
- package/dist/p2p/reconnect.js +89 -0
- package/dist/p2p/reconnect.js.map +1 -0
- package/dist/payments/balance-manager.d.ts +17 -0
- package/dist/payments/balance-manager.d.ts.map +1 -0
- package/dist/payments/balance-manager.js +54 -0
- package/dist/payments/balance-manager.js.map +1 -0
- package/dist/payments/buyer-payment-manager.d.ts +122 -0
- package/dist/payments/buyer-payment-manager.d.ts.map +1 -0
- package/dist/payments/buyer-payment-manager.js +280 -0
- package/dist/payments/buyer-payment-manager.js.map +1 -0
- package/dist/payments/disputes.d.ts +18 -0
- package/dist/payments/disputes.d.ts.map +1 -0
- package/dist/payments/disputes.js +47 -0
- package/dist/payments/disputes.js.map +1 -0
- package/dist/payments/evm/escrow-client.d.ts +61 -0
- package/dist/payments/evm/escrow-client.d.ts.map +1 -0
- package/dist/payments/evm/escrow-client.js +170 -0
- package/dist/payments/evm/escrow-client.js.map +1 -0
- package/dist/payments/evm/keypair.d.ts +21 -0
- package/dist/payments/evm/keypair.d.ts.map +1 -0
- package/dist/payments/evm/keypair.js +29 -0
- package/dist/payments/evm/keypair.js.map +1 -0
- package/dist/payments/evm/signatures.d.ts +11 -0
- package/dist/payments/evm/signatures.d.ts.map +1 -0
- package/dist/payments/evm/signatures.js +56 -0
- package/dist/payments/evm/signatures.js.map +1 -0
- package/dist/payments/evm/wallet.d.ts +5 -0
- package/dist/payments/evm/wallet.d.ts.map +1 -0
- package/dist/payments/evm/wallet.js +31 -0
- package/dist/payments/evm/wallet.js.map +1 -0
- package/dist/payments/index.d.ts +13 -0
- package/dist/payments/index.d.ts.map +1 -0
- package/dist/payments/index.js +14 -0
- package/dist/payments/index.js.map +1 -0
- package/dist/payments/settlement.d.ts +6 -0
- package/dist/payments/settlement.d.ts.map +1 -0
- package/dist/payments/settlement.js +25 -0
- package/dist/payments/settlement.js.map +1 -0
- package/dist/payments/types.d.ts +66 -0
- package/dist/payments/types.d.ts.map +1 -0
- package/dist/payments/types.js +2 -0
- package/dist/payments/types.js.map +1 -0
- package/dist/proxy/index.d.ts +4 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +4 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/provider-detection.d.ts +20 -0
- package/dist/proxy/provider-detection.d.ts.map +1 -0
- package/dist/proxy/provider-detection.js +61 -0
- package/dist/proxy/provider-detection.js.map +1 -0
- package/dist/proxy/proxy-mux.d.ts +35 -0
- package/dist/proxy/proxy-mux.d.ts.map +1 -0
- package/dist/proxy/proxy-mux.js +137 -0
- package/dist/proxy/proxy-mux.js.map +1 -0
- package/dist/proxy/request-codec.d.ts +33 -0
- package/dist/proxy/request-codec.d.ts.map +1 -0
- package/dist/proxy/request-codec.js +238 -0
- package/dist/proxy/request-codec.js.map +1 -0
- package/dist/reputation/index.d.ts +7 -0
- package/dist/reputation/index.d.ts.map +1 -0
- package/dist/reputation/index.js +6 -0
- package/dist/reputation/index.js.map +1 -0
- package/dist/reputation/rating-manager.d.ts +20 -0
- package/dist/reputation/rating-manager.d.ts.map +1 -0
- package/dist/reputation/rating-manager.js +91 -0
- package/dist/reputation/rating-manager.js.map +1 -0
- package/dist/reputation/report-manager.d.ts +21 -0
- package/dist/reputation/report-manager.d.ts.map +1 -0
- package/dist/reputation/report-manager.js +70 -0
- package/dist/reputation/report-manager.js.map +1 -0
- package/dist/reputation/trust-engine.d.ts +36 -0
- package/dist/reputation/trust-engine.d.ts.map +1 -0
- package/dist/reputation/trust-engine.js +95 -0
- package/dist/reputation/trust-engine.js.map +1 -0
- package/dist/reputation/trust-score.d.ts +43 -0
- package/dist/reputation/trust-score.d.ts.map +1 -0
- package/dist/reputation/trust-score.js +34 -0
- package/dist/reputation/trust-score.js.map +1 -0
- package/dist/reputation/uptime-tracker.d.ts +51 -0
- package/dist/reputation/uptime-tracker.d.ts.map +1 -0
- package/dist/reputation/uptime-tracker.js +123 -0
- package/dist/reputation/uptime-tracker.js.map +1 -0
- package/dist/routing/default-router.d.ts +21 -0
- package/dist/routing/default-router.d.ts.map +1 -0
- package/dist/routing/default-router.js +60 -0
- package/dist/routing/default-router.js.map +1 -0
- package/dist/types/buyer.d.ts +36 -0
- package/dist/types/buyer.d.ts.map +1 -0
- package/dist/types/buyer.js +2 -0
- package/dist/types/buyer.js.map +1 -0
- package/dist/types/capability.d.ts +25 -0
- package/dist/types/capability.d.ts.map +1 -0
- package/dist/types/capability.js +2 -0
- package/dist/types/capability.js.map +1 -0
- package/dist/types/connection.d.ts +27 -0
- package/dist/types/connection.d.ts.map +1 -0
- package/dist/types/connection.js +11 -0
- package/dist/types/connection.js.map +1 -0
- package/dist/types/http.d.ts +19 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/http.js +2 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +15 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/metering.d.ts +170 -0
- package/dist/types/metering.d.ts.map +1 -0
- package/dist/types/metering.js +2 -0
- package/dist/types/metering.js.map +1 -0
- package/dist/types/peer-profile.d.ts +24 -0
- package/dist/types/peer-profile.d.ts.map +1 -0
- package/dist/types/peer-profile.js +2 -0
- package/dist/types/peer-profile.js.map +1 -0
- package/dist/types/peer.d.ts +56 -0
- package/dist/types/peer.d.ts.map +1 -0
- package/dist/types/peer.js +11 -0
- package/dist/types/peer.js.map +1 -0
- package/dist/types/plugin-config.d.ts +31 -0
- package/dist/types/plugin-config.d.ts.map +1 -0
- package/dist/types/plugin-config.js +2 -0
- package/dist/types/plugin-config.js.map +1 -0
- package/dist/types/protocol.d.ts +141 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +42 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types/provider.d.ts +38 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/provider.js +11 -0
- package/dist/types/provider.js.map +1 -0
- package/dist/types/rating.d.ts +21 -0
- package/dist/types/rating.d.ts.map +1 -0
- package/dist/types/rating.js +2 -0
- package/dist/types/rating.js.map +1 -0
- package/dist/types/report.d.ts +20 -0
- package/dist/types/report.d.ts.map +1 -0
- package/dist/types/report.js +2 -0
- package/dist/types/report.js.map +1 -0
- package/dist/types/seller.d.ts +36 -0
- package/dist/types/seller.d.ts.map +1 -0
- package/dist/types/seller.js +2 -0
- package/dist/types/seller.js.map +1 -0
- package/dist/types/staking.d.ts +16 -0
- package/dist/types/staking.d.ts.map +1 -0
- package/dist/types/staking.js +6 -0
- package/dist/types/staking.js.map +1 -0
- package/dist/utils/debug.d.ts +4 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +25 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/hex.d.ts +3 -0
- package/dist/utils/hex.d.ts.map +1 -0
- package/dist/utils/hex.js +15 -0
- package/dist/utils/hex.js.map +1 -0
- package/package.json +62 -0
- package/scripts/ensure-node-native-modules.mjs +153 -0
- package/scripts/patch-ethers.js +44 -0
- package/src/config/encryption.test.ts +49 -0
- package/src/config/encryption.ts +53 -0
- package/src/config/plugin-config-manager.test.ts +92 -0
- package/src/config/plugin-config-manager.ts +153 -0
- package/src/config/plugin-loader.ts +90 -0
- package/src/discovery/announcer.ts +169 -0
- package/src/discovery/bootstrap.ts +57 -0
- package/src/discovery/default-metadata-resolver.ts +18 -0
- package/src/discovery/dht-health.ts +136 -0
- package/src/discovery/dht-node.ts +191 -0
- package/src/discovery/http-metadata-resolver.ts +47 -0
- package/src/discovery/index.ts +15 -0
- package/src/discovery/metadata-codec.ts +453 -0
- package/src/discovery/metadata-resolver.ts +7 -0
- package/src/discovery/metadata-server.ts +73 -0
- package/src/discovery/metadata-validator.ts +172 -0
- package/src/discovery/peer-lookup.ts +122 -0
- package/src/discovery/peer-metadata.ts +34 -0
- package/src/discovery/peer-selector.ts +134 -0
- package/src/discovery/profile-manager.ts +131 -0
- package/src/discovery/profile-search.ts +100 -0
- package/src/discovery/reputation-verifier.ts +54 -0
- package/src/index.ts +61 -0
- package/src/interfaces/buyer-router.ts +21 -0
- package/src/interfaces/plugin.ts +36 -0
- package/src/interfaces/seller-provider.ts +81 -0
- package/src/metering/index.ts +6 -0
- package/src/metering/receipt-generator.ts +105 -0
- package/src/metering/receipt-verifier.ts +102 -0
- package/src/metering/session-tracker.ts +145 -0
- package/src/metering/storage.ts +600 -0
- package/src/metering/token-counter.ts +127 -0
- package/src/metering/usage-aggregator.ts +236 -0
- package/src/node.ts +1698 -0
- package/src/p2p/connection-auth.ts +152 -0
- package/src/p2p/connection-manager.ts +916 -0
- package/src/p2p/handshake.ts +162 -0
- package/src/p2p/ice-config.ts +59 -0
- package/src/p2p/identity.ts +110 -0
- package/src/p2p/index.ts +11 -0
- package/src/p2p/keepalive.ts +118 -0
- package/src/p2p/message-protocol.ts +171 -0
- package/src/p2p/nat-traversal.ts +169 -0
- package/src/p2p/payment-codec.ts +165 -0
- package/src/p2p/payment-mux.ts +153 -0
- package/src/p2p/reconnect.ts +117 -0
- package/src/payments/balance-manager.ts +77 -0
- package/src/payments/buyer-payment-manager.ts +414 -0
- package/src/payments/disputes.ts +72 -0
- package/src/payments/evm/escrow-client.ts +263 -0
- package/src/payments/evm/keypair.ts +31 -0
- package/src/payments/evm/signatures.ts +103 -0
- package/src/payments/evm/wallet.ts +42 -0
- package/src/payments/index.ts +50 -0
- package/src/payments/settlement.ts +40 -0
- package/src/payments/types.ts +79 -0
- package/src/proxy/index.ts +3 -0
- package/src/proxy/provider-detection.ts +78 -0
- package/src/proxy/proxy-mux.ts +173 -0
- package/src/proxy/request-codec.ts +294 -0
- package/src/reputation/index.ts +6 -0
- package/src/reputation/rating-manager.ts +118 -0
- package/src/reputation/report-manager.ts +91 -0
- package/src/reputation/trust-engine.ts +120 -0
- package/src/reputation/trust-score.ts +74 -0
- package/src/reputation/uptime-tracker.ts +155 -0
- package/src/routing/default-router.ts +75 -0
- package/src/types/bittorrent-dht.d.ts +19 -0
- package/src/types/buyer.ts +37 -0
- package/src/types/capability.ts +34 -0
- package/src/types/connection.ts +29 -0
- package/src/types/http.ts +20 -0
- package/src/types/index.ts +14 -0
- package/src/types/metering.ts +175 -0
- package/src/types/nat-api.d.ts +29 -0
- package/src/types/peer-profile.ts +25 -0
- package/src/types/peer.ts +62 -0
- package/src/types/plugin-config.ts +31 -0
- package/src/types/protocol.ts +162 -0
- package/src/types/provider.ts +40 -0
- package/src/types/rating.ts +23 -0
- package/src/types/report.ts +30 -0
- package/src/types/seller.ts +38 -0
- package/src/types/staking.ts +23 -0
- package/src/utils/debug.ts +30 -0
- package/src/utils/hex.ts +14 -0
- package/tests/balance-manager.test.ts +156 -0
- package/tests/bootstrap.test.ts +108 -0
- package/tests/buyer-payment-manager.test.ts +358 -0
- package/tests/connection-auth.test.ts +87 -0
- package/tests/default-router.test.ts +148 -0
- package/tests/evm-keypair.test.ts +173 -0
- package/tests/identity.test.ts +133 -0
- package/tests/message-protocol.test.ts +212 -0
- package/tests/metadata-codec.test.ts +165 -0
- package/tests/metadata-validator.test.ts +261 -0
- package/tests/metering-storage.test.ts +244 -0
- package/tests/payment-codec.test.ts +95 -0
- package/tests/payment-mux.test.ts +191 -0
- package/tests/peer-selector.test.ts +184 -0
- package/tests/provider-detection.test.ts +107 -0
- package/tests/proxy-mux-security.test.ts +38 -0
- package/tests/receipt.test.ts +215 -0
- package/tests/reputation-integration.test.ts +195 -0
- package/tests/request-codec.test.ts +144 -0
- package/tests/token-counter.test.ts +122 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,173 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
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';
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
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
|
+
}
|