@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,414 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
}
|