@toon-protocol/connector 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +421 -0
- package/dist/btp/btp-claim-types.d.ts +30 -0
- package/dist/btp/btp-claim-types.d.ts.map +1 -0
- package/dist/btp/btp-claim-types.js +103 -0
- package/dist/btp/btp-claim-types.js.map +1 -0
- package/dist/btp/btp-client-manager.d.ts +27 -0
- package/dist/btp/btp-client-manager.d.ts.map +1 -0
- package/dist/btp/btp-client-manager.js +138 -0
- package/dist/btp/btp-client-manager.js.map +1 -0
- package/dist/btp/btp-client.d.ts +55 -0
- package/dist/btp/btp-client.d.ts.map +1 -0
- package/dist/btp/btp-client.js +474 -0
- package/dist/btp/btp-client.js.map +1 -0
- package/dist/btp/btp-message-parser.d.ts +4 -0
- package/dist/btp/btp-message-parser.d.ts.map +1 -0
- package/dist/btp/btp-message-parser.js +211 -0
- package/dist/btp/btp-message-parser.js.map +1 -0
- package/dist/btp/btp-server.d.ts +30 -0
- package/dist/btp/btp-server.d.ts.map +1 -0
- package/dist/btp/btp-server.js +458 -0
- package/dist/btp/btp-server.js.map +1 -0
- package/dist/btp/btp-types.d.ts +43 -0
- package/dist/btp/btp-types.d.ts.map +1 -0
- package/dist/btp/btp-types.js +44 -0
- package/dist/btp/btp-types.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +175 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/onboarding-wizard.d.ts +7 -0
- package/dist/cli/onboarding-wizard.d.ts.map +1 -0
- package/dist/cli/onboarding-wizard.js +257 -0
- package/dist/cli/onboarding-wizard.js.map +1 -0
- package/dist/cli/types.d.ts +38 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +3 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/config/aptos-env-validator.d.ts +8 -0
- package/dist/config/aptos-env-validator.d.ts.map +1 -0
- package/dist/config/aptos-env-validator.js +25 -0
- package/dist/config/aptos-env-validator.js.map +1 -0
- package/dist/config/config-loader.d.ts +20 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +269 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/environment-validator.d.ts +4 -0
- package/dist/config/environment-validator.d.ts.map +1 -0
- package/dist/config/environment-validator.js +239 -0
- package/dist/config/environment-validator.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/key-manager-config.d.ts +7 -0
- package/dist/config/key-manager-config.d.ts.map +1 -0
- package/dist/config/key-manager-config.js +209 -0
- package/dist/config/key-manager-config.js.map +1 -0
- package/dist/config/topology-validator.d.ts +14 -0
- package/dist/config/topology-validator.d.ts.map +1 -0
- package/dist/config/topology-validator.js +142 -0
- package/dist/config/topology-validator.js.map +1 -0
- package/dist/config/types.d.ts +210 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +10 -0
- package/dist/config/types.js.map +1 -0
- package/dist/core/connector-node.d.ts +79 -0
- package/dist/core/connector-node.d.ts.map +1 -0
- package/dist/core/connector-node.js +1036 -0
- package/dist/core/connector-node.js.map +1 -0
- package/dist/core/local-delivery-client.d.ts +16 -0
- package/dist/core/local-delivery-client.d.ts.map +1 -0
- package/dist/core/local-delivery-client.js +176 -0
- package/dist/core/local-delivery-client.js.map +1 -0
- package/dist/core/packet-handler.d.ts +45 -0
- package/dist/core/packet-handler.d.ts.map +1 -0
- package/dist/core/packet-handler.js +606 -0
- package/dist/core/packet-handler.js.map +1 -0
- package/dist/core/payment-handler.d.ts +27 -0
- package/dist/core/payment-handler.d.ts.map +1 -0
- package/dist/core/payment-handler.js +115 -0
- package/dist/core/payment-handler.js.map +1 -0
- package/dist/discovery/index.d.ts +3 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +6 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/peer-discovery-service.d.ts +29 -0
- package/dist/discovery/peer-discovery-service.d.ts.map +1 -0
- package/dist/discovery/peer-discovery-service.js +230 -0
- package/dist/discovery/peer-discovery-service.js.map +1 -0
- package/dist/discovery/types.d.ts +38 -0
- package/dist/discovery/types.d.ts.map +1 -0
- package/dist/discovery/types.js +3 -0
- package/dist/discovery/types.js.map +1 -0
- package/dist/encoding/oer-parser.d.ts +39 -0
- package/dist/encoding/oer-parser.d.ts.map +1 -0
- package/dist/encoding/oer-parser.js +154 -0
- package/dist/encoding/oer-parser.js.map +1 -0
- package/dist/explorer-ui/assets/EventDetailPanel-CnSaMk3V.js +6 -0
- package/dist/explorer-ui/assets/FilterBar-BEmAzBku.js +26 -0
- package/dist/explorer-ui/assets/chevron-right-BUT9VhYe.js +11 -0
- package/dist/explorer-ui/assets/index-BZ2INVgy.js +360 -0
- package/dist/explorer-ui/assets/index-Cemh6svI.css +1 -0
- package/dist/explorer-ui/index.html +14 -0
- package/dist/explorer-ui/vite.svg +1 -0
- package/dist/facilitator/index.d.ts +2 -0
- package/dist/facilitator/index.d.ts.map +1 -0
- package/dist/facilitator/index.js +7 -0
- package/dist/facilitator/index.js.map +1 -0
- package/dist/facilitator/spsp-client.d.ts +18 -0
- package/dist/facilitator/spsp-client.d.ts.map +1 -0
- package/dist/facilitator/spsp-client.js +95 -0
- package/dist/facilitator/spsp-client.js.map +1 -0
- package/dist/http/admin-api.d.ts +123 -0
- package/dist/http/admin-api.d.ts.map +1 -0
- package/dist/http/admin-api.js +1057 -0
- package/dist/http/admin-api.js.map +1 -0
- package/dist/http/admin-server.d.ts +41 -0
- package/dist/http/admin-server.d.ts.map +1 -0
- package/dist/http/admin-server.js +156 -0
- package/dist/http/admin-server.js.map +1 -0
- package/dist/http/health-server.d.ts +22 -0
- package/dist/http/health-server.d.ts.map +1 -0
- package/dist/http/health-server.js +192 -0
- package/dist/http/health-server.js.map +1 -0
- package/dist/http/ilp-send-handler.d.ts +19 -0
- package/dist/http/ilp-send-handler.d.ts.map +1 -0
- package/dist/http/ilp-send-handler.js +162 -0
- package/dist/http/ilp-send-handler.js.map +1 -0
- package/dist/http/types.d.ts +39 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +3 -0
- package/dist/http/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +22 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +41 -0
- package/dist/lib.js.map +1 -0
- package/dist/main.d.ts +4 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +79 -0
- package/dist/main.js.map +1 -0
- package/dist/routing/packet-processor.d.ts +36 -0
- package/dist/routing/packet-processor.d.ts.map +1 -0
- package/dist/routing/packet-processor.js +112 -0
- package/dist/routing/packet-processor.js.map +1 -0
- package/dist/routing/packet-worker.d.ts +10 -0
- package/dist/routing/packet-worker.d.ts.map +1 -0
- package/dist/routing/packet-worker.js +34 -0
- package/dist/routing/packet-worker.js.map +1 -0
- package/dist/routing/routing-table.d.ts +15 -0
- package/dist/routing/routing-table.d.ts.map +1 -0
- package/dist/routing/routing-table.js +63 -0
- package/dist/routing/routing-table.js.map +1 -0
- package/dist/routing/worker-pool.d.ts +43 -0
- package/dist/routing/worker-pool.d.ts.map +1 -0
- package/dist/routing/worker-pool.js +228 -0
- package/dist/routing/worker-pool.js.map +1 -0
- package/dist/security/alert-notifier.d.ts +34 -0
- package/dist/security/alert-notifier.d.ts.map +1 -0
- package/dist/security/alert-notifier.js +136 -0
- package/dist/security/alert-notifier.js.map +1 -0
- package/dist/security/audit-logger.d.ts +34 -0
- package/dist/security/audit-logger.d.ts.map +1 -0
- package/dist/security/audit-logger.js +132 -0
- package/dist/security/audit-logger.js.map +1 -0
- package/dist/security/backends/aws-kms-backend.d.ts +18 -0
- package/dist/security/backends/aws-kms-backend.d.ts.map +1 -0
- package/dist/security/backends/aws-kms-backend.js +130 -0
- package/dist/security/backends/aws-kms-backend.js.map +1 -0
- package/dist/security/backends/azure-kv-backend.d.ts +17 -0
- package/dist/security/backends/azure-kv-backend.d.ts.map +1 -0
- package/dist/security/backends/azure-kv-backend.js +121 -0
- package/dist/security/backends/azure-kv-backend.js.map +1 -0
- package/dist/security/backends/environment-backend.d.ts +15 -0
- package/dist/security/backends/environment-backend.d.ts.map +1 -0
- package/dist/security/backends/environment-backend.js +56 -0
- package/dist/security/backends/environment-backend.js.map +1 -0
- package/dist/security/backends/gcp-kms-backend.d.ts +17 -0
- package/dist/security/backends/gcp-kms-backend.d.ts.map +1 -0
- package/dist/security/backends/gcp-kms-backend.js +110 -0
- package/dist/security/backends/gcp-kms-backend.js.map +1 -0
- package/dist/security/backends/hsm-backend.d.ts +18 -0
- package/dist/security/backends/hsm-backend.d.ts.map +1 -0
- package/dist/security/backends/hsm-backend.js +187 -0
- package/dist/security/backends/hsm-backend.js.map +1 -0
- package/dist/security/fraud-detector.d.ts +79 -0
- package/dist/security/fraud-detector.d.ts.map +1 -0
- package/dist/security/fraud-detector.js +147 -0
- package/dist/security/fraud-detector.js.map +1 -0
- package/dist/security/key-manager-signer.d.ts +15 -0
- package/dist/security/key-manager-signer.d.ts.map +1 -0
- package/dist/security/key-manager-signer.js +91 -0
- package/dist/security/key-manager-signer.js.map +1 -0
- package/dist/security/key-manager.d.ts +69 -0
- package/dist/security/key-manager.d.ts.map +1 -0
- package/dist/security/key-manager.js +79 -0
- package/dist/security/key-manager.js.map +1 -0
- package/dist/security/key-rotation-manager.d.ts +27 -0
- package/dist/security/key-rotation-manager.d.ts.map +1 -0
- package/dist/security/key-rotation-manager.js +142 -0
- package/dist/security/key-rotation-manager.js.map +1 -0
- package/dist/security/rate-limit-config.d.ts +7 -0
- package/dist/security/rate-limit-config.d.ts.map +1 -0
- package/dist/security/rate-limit-config.js +57 -0
- package/dist/security/rate-limit-config.js.map +1 -0
- package/dist/security/rate-limiter.d.ts +46 -0
- package/dist/security/rate-limiter.d.ts.map +1 -0
- package/dist/security/rate-limiter.js +170 -0
- package/dist/security/rate-limiter.js.map +1 -0
- package/dist/security/reputation-tracker.d.ts +30 -0
- package/dist/security/reputation-tracker.d.ts.map +1 -0
- package/dist/security/reputation-tracker.js +111 -0
- package/dist/security/reputation-tracker.js.map +1 -0
- package/dist/security/rules/balance-manipulation-rule.d.ts +23 -0
- package/dist/security/rules/balance-manipulation-rule.d.ts.map +1 -0
- package/dist/security/rules/balance-manipulation-rule.js +70 -0
- package/dist/security/rules/balance-manipulation-rule.js.map +1 -0
- package/dist/security/rules/double-spend-detection-rule.d.ts +23 -0
- package/dist/security/rules/double-spend-detection-rule.d.ts.map +1 -0
- package/dist/security/rules/double-spend-detection-rule.js +61 -0
- package/dist/security/rules/double-spend-detection-rule.js.map +1 -0
- package/dist/security/rules/rapid-channel-closure-rule.d.ts +16 -0
- package/dist/security/rules/rapid-channel-closure-rule.d.ts.map +1 -0
- package/dist/security/rules/rapid-channel-closure-rule.js +57 -0
- package/dist/security/rules/rapid-channel-closure-rule.js.map +1 -0
- package/dist/security/rules/sudden-traffic-spike-rule.d.ts +18 -0
- package/dist/security/rules/sudden-traffic-spike-rule.d.ts.map +1 -0
- package/dist/security/rules/sudden-traffic-spike-rule.js +92 -0
- package/dist/security/rules/sudden-traffic-spike-rule.js.map +1 -0
- package/dist/security/rules/unusual-settlement-amount-rule.d.ts +12 -0
- package/dist/security/rules/unusual-settlement-amount-rule.d.ts.map +1 -0
- package/dist/security/rules/unusual-settlement-amount-rule.js +33 -0
- package/dist/security/rules/unusual-settlement-amount-rule.js.map +1 -0
- package/dist/security/token-bucket.d.ts +16 -0
- package/dist/security/token-bucket.d.ts.map +1 -0
- package/dist/security/token-bucket.js +49 -0
- package/dist/security/token-bucket.js.map +1 -0
- package/dist/security/violation-counter.d.ts +11 -0
- package/dist/security/violation-counter.d.ts.map +1 -0
- package/dist/security/violation-counter.js +61 -0
- package/dist/security/violation-counter.js.map +1 -0
- package/dist/settlement/account-id-generator.d.ts +4 -0
- package/dist/settlement/account-id-generator.d.ts.map +1 -0
- package/dist/settlement/account-id-generator.js +38 -0
- package/dist/settlement/account-id-generator.js.map +1 -0
- package/dist/settlement/account-manager.d.ts +47 -0
- package/dist/settlement/account-manager.d.ts.map +1 -0
- package/dist/settlement/account-manager.js +447 -0
- package/dist/settlement/account-manager.js.map +1 -0
- package/dist/settlement/account-metadata.d.ts +11 -0
- package/dist/settlement/account-metadata.d.ts.map +1 -0
- package/dist/settlement/account-metadata.js +40 -0
- package/dist/settlement/account-metadata.js.map +1 -0
- package/dist/settlement/aptos-channel-sdk.d.ts +66 -0
- package/dist/settlement/aptos-channel-sdk.d.ts.map +1 -0
- package/dist/settlement/aptos-channel-sdk.js +274 -0
- package/dist/settlement/aptos-channel-sdk.js.map +1 -0
- package/dist/settlement/aptos-claim-signer.d.ts +57 -0
- package/dist/settlement/aptos-claim-signer.d.ts.map +1 -0
- package/dist/settlement/aptos-claim-signer.js +200 -0
- package/dist/settlement/aptos-claim-signer.js.map +1 -0
- package/dist/settlement/aptos-client.d.ts +99 -0
- package/dist/settlement/aptos-client.d.ts.map +1 -0
- package/dist/settlement/aptos-client.js +474 -0
- package/dist/settlement/aptos-client.js.map +1 -0
- package/dist/settlement/channel-manager.d.ts +66 -0
- package/dist/settlement/channel-manager.d.ts.map +1 -0
- package/dist/settlement/channel-manager.js +214 -0
- package/dist/settlement/channel-manager.js.map +1 -0
- package/dist/settlement/claim-receiver-db-schema.d.ts +4 -0
- package/dist/settlement/claim-receiver-db-schema.d.ts.map +1 -0
- package/dist/settlement/claim-receiver-db-schema.js +25 -0
- package/dist/settlement/claim-receiver-db-schema.js.map +1 -0
- package/dist/settlement/claim-receiver.d.ts +31 -0
- package/dist/settlement/claim-receiver.d.ts.map +1 -0
- package/dist/settlement/claim-receiver.js +228 -0
- package/dist/settlement/claim-receiver.js.map +1 -0
- package/dist/settlement/claim-redemption-service.d.ts +39 -0
- package/dist/settlement/claim-redemption-service.d.ts.map +1 -0
- package/dist/settlement/claim-redemption-service.js +189 -0
- package/dist/settlement/claim-redemption-service.js.map +1 -0
- package/dist/settlement/claim-sender-db-schema.d.ts +3 -0
- package/dist/settlement/claim-sender-db-schema.d.ts.map +1 -0
- package/dist/settlement/claim-sender-db-schema.js +18 -0
- package/dist/settlement/claim-sender-db-schema.js.map +1 -0
- package/dist/settlement/claim-sender.d.ts +22 -0
- package/dist/settlement/claim-sender.d.ts.map +1 -0
- package/dist/settlement/claim-sender.js +108 -0
- package/dist/settlement/claim-sender.js.map +1 -0
- package/dist/settlement/eip712-helper.d.ts +13 -0
- package/dist/settlement/eip712-helper.d.ts.map +1 -0
- package/dist/settlement/eip712-helper.js +24 -0
- package/dist/settlement/eip712-helper.js.map +1 -0
- package/dist/settlement/in-memory-ledger-client.d.ts +40 -0
- package/dist/settlement/in-memory-ledger-client.d.ts.map +1 -0
- package/dist/settlement/in-memory-ledger-client.js +177 -0
- package/dist/settlement/in-memory-ledger-client.js.map +1 -0
- package/dist/settlement/ledger-client.d.ts +22 -0
- package/dist/settlement/ledger-client.d.ts.map +1 -0
- package/dist/settlement/ledger-client.js +3 -0
- package/dist/settlement/ledger-client.js.map +1 -0
- package/dist/settlement/metrics-collector.d.ts +29 -0
- package/dist/settlement/metrics-collector.d.ts.map +1 -0
- package/dist/settlement/metrics-collector.js +81 -0
- package/dist/settlement/metrics-collector.js.map +1 -0
- package/dist/settlement/payment-channel-sdk.d.ts +59 -0
- package/dist/settlement/payment-channel-sdk.d.ts.map +1 -0
- package/dist/settlement/payment-channel-sdk.js +677 -0
- package/dist/settlement/payment-channel-sdk.js.map +1 -0
- package/dist/settlement/per-packet-claim-service.d.ts +33 -0
- package/dist/settlement/per-packet-claim-service.d.ts.map +1 -0
- package/dist/settlement/per-packet-claim-service.js +177 -0
- package/dist/settlement/per-packet-claim-service.js.map +1 -0
- package/dist/settlement/settlement-api.d.ts +37 -0
- package/dist/settlement/settlement-api.d.ts.map +1 -0
- package/dist/settlement/settlement-api.js +172 -0
- package/dist/settlement/settlement-api.js.map +1 -0
- package/dist/settlement/settlement-coordinator.d.ts +47 -0
- package/dist/settlement/settlement-coordinator.d.ts.map +1 -0
- package/dist/settlement/settlement-coordinator.js +166 -0
- package/dist/settlement/settlement-coordinator.js.map +1 -0
- package/dist/settlement/settlement-executor.d.ts +44 -0
- package/dist/settlement/settlement-executor.d.ts.map +1 -0
- package/dist/settlement/settlement-executor.js +247 -0
- package/dist/settlement/settlement-executor.js.map +1 -0
- package/dist/settlement/settlement-monitor.d.ts +29 -0
- package/dist/settlement/settlement-monitor.d.ts.map +1 -0
- package/dist/settlement/settlement-monitor.js +172 -0
- package/dist/settlement/settlement-monitor.js.map +1 -0
- package/dist/settlement/tigerbeetle-batch-writer.d.ts +58 -0
- package/dist/settlement/tigerbeetle-batch-writer.d.ts.map +1 -0
- package/dist/settlement/tigerbeetle-batch-writer.js +162 -0
- package/dist/settlement/tigerbeetle-batch-writer.js.map +1 -0
- package/dist/settlement/tigerbeetle-client.d.ts +40 -0
- package/dist/settlement/tigerbeetle-client.d.ts.map +1 -0
- package/dist/settlement/tigerbeetle-client.js +279 -0
- package/dist/settlement/tigerbeetle-client.js.map +1 -0
- package/dist/settlement/tigerbeetle-errors.d.ts +23 -0
- package/dist/settlement/tigerbeetle-errors.d.ts.map +1 -0
- package/dist/settlement/tigerbeetle-errors.js +58 -0
- package/dist/settlement/tigerbeetle-errors.js.map +1 -0
- package/dist/settlement/types.d.ts +64 -0
- package/dist/settlement/types.d.ts.map +1 -0
- package/dist/settlement/types.js +42 -0
- package/dist/settlement/types.js.map +1 -0
- package/dist/settlement/unified-settlement-executor.d.ts +34 -0
- package/dist/settlement/unified-settlement-executor.d.ts.map +1 -0
- package/dist/settlement/unified-settlement-executor.js +145 -0
- package/dist/settlement/unified-settlement-executor.js.map +1 -0
- package/dist/settlement/xrp-channel-lifecycle.d.ts +41 -0
- package/dist/settlement/xrp-channel-lifecycle.d.ts.map +1 -0
- package/dist/settlement/xrp-channel-lifecycle.js +142 -0
- package/dist/settlement/xrp-channel-lifecycle.js.map +1 -0
- package/dist/settlement/xrp-channel-manager.d.ts +59 -0
- package/dist/settlement/xrp-channel-manager.d.ts.map +1 -0
- package/dist/settlement/xrp-channel-manager.js +160 -0
- package/dist/settlement/xrp-channel-manager.js.map +1 -0
- package/dist/settlement/xrp-channel-sdk.d.ts +30 -0
- package/dist/settlement/xrp-channel-sdk.d.ts.map +1 -0
- package/dist/settlement/xrp-channel-sdk.js +164 -0
- package/dist/settlement/xrp-channel-sdk.js.map +1 -0
- package/dist/settlement/xrp-claim-signer.d.ts +22 -0
- package/dist/settlement/xrp-claim-signer.d.ts.map +1 -0
- package/dist/settlement/xrp-claim-signer.js +122 -0
- package/dist/settlement/xrp-claim-signer.js.map +1 -0
- package/dist/settlement/xrpl-client.d.ts +104 -0
- package/dist/settlement/xrpl-client.d.ts.map +1 -0
- package/dist/settlement/xrpl-client.js +304 -0
- package/dist/settlement/xrpl-client.js.map +1 -0
- package/dist/test/testnet-config.d.ts +58 -0
- package/dist/test/testnet-config.d.ts.map +1 -0
- package/dist/test/testnet-config.js +89 -0
- package/dist/test/testnet-config.js.map +1 -0
- package/dist/test-utils/index.d.ts +3 -0
- package/dist/test-utils/index.d.ts.map +1 -0
- package/dist/test-utils/index.js +15 -0
- package/dist/test-utils/index.js.map +1 -0
- package/dist/test-utils/isolated-test-env.d.ts +31 -0
- package/dist/test-utils/isolated-test-env.d.ts.map +1 -0
- package/dist/test-utils/isolated-test-env.js +127 -0
- package/dist/test-utils/isolated-test-env.js.map +1 -0
- package/dist/test-utils/mock-factories-patch.d.ts +2 -0
- package/dist/test-utils/mock-factories-patch.d.ts.map +1 -0
- package/dist/test-utils/mock-factories-patch.js +3 -0
- package/dist/test-utils/mock-factories-patch.js.map +1 -0
- package/dist/test-utils/mock-factories.d.ts +22 -0
- package/dist/test-utils/mock-factories.d.ts.map +1 -0
- package/dist/test-utils/mock-factories.js +56 -0
- package/dist/test-utils/mock-factories.js.map +1 -0
- package/dist/utils/connection-pool.d.ts +42 -0
- package/dist/utils/connection-pool.d.ts.map +1 -0
- package/dist/utils/connection-pool.js +209 -0
- package/dist/utils/connection-pool.js.map +1 -0
- package/dist/utils/evm-rpc-connection-pool.d.ts +8 -0
- package/dist/utils/evm-rpc-connection-pool.d.ts.map +1 -0
- package/dist/utils/evm-rpc-connection-pool.js +40 -0
- package/dist/utils/evm-rpc-connection-pool.js.map +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +58 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/optional-require.d.ts +2 -0
- package/dist/utils/optional-require.d.ts.map +1 -0
- package/dist/utils/optional-require.js +54 -0
- package/dist/utils/optional-require.js.map +1 -0
- package/dist/utils/xrp-wss-connection-pool.d.ts +8 -0
- package/dist/utils/xrp-wss-connection-pool.d.ts.map +1 -0
- package/dist/utils/xrp-wss-connection-pool.js +42 -0
- package/dist/utils/xrp-wss-connection-pool.js.map +1 -0
- package/dist/wallet/audit-logger.d.ts +22 -0
- package/dist/wallet/audit-logger.d.ts.map +1 -0
- package/dist/wallet/audit-logger.js +120 -0
- package/dist/wallet/audit-logger.js.map +1 -0
- package/dist/wallet/fraud-detector-interface.d.ts +14 -0
- package/dist/wallet/fraud-detector-interface.d.ts.map +1 -0
- package/dist/wallet/fraud-detector-interface.js +3 -0
- package/dist/wallet/fraud-detector-interface.js.map +1 -0
- package/dist/wallet/key-manager.d.ts +6 -0
- package/dist/wallet/key-manager.d.ts.map +1 -0
- package/dist/wallet/key-manager.js +3 -0
- package/dist/wallet/key-manager.js.map +1 -0
- package/dist/wallet/placeholder-fraud-detector.d.ts +10 -0
- package/dist/wallet/placeholder-fraud-detector.d.ts.map +1 -0
- package/dist/wallet/placeholder-fraud-detector.js +10 -0
- package/dist/wallet/placeholder-fraud-detector.js.map +1 -0
- package/dist/wallet/rate-limiter.d.ts +26 -0
- package/dist/wallet/rate-limiter.d.ts.map +1 -0
- package/dist/wallet/rate-limiter.js +114 -0
- package/dist/wallet/rate-limiter.js.map +1 -0
- package/dist/wallet/suspicious-activity-detector.d.ts +25 -0
- package/dist/wallet/suspicious-activity-detector.d.ts.map +1 -0
- package/dist/wallet/suspicious-activity-detector.js +97 -0
- package/dist/wallet/suspicious-activity-detector.js.map +1 -0
- package/dist/wallet/treasury-wallet.d.ts +20 -0
- package/dist/wallet/treasury-wallet.d.ts.map +1 -0
- package/dist/wallet/treasury-wallet.js +151 -0
- package/dist/wallet/treasury-wallet.js.map +1 -0
- package/dist/wallet/wallet-authentication.d.ts +31 -0
- package/dist/wallet/wallet-authentication.d.ts.map +1 -0
- package/dist/wallet/wallet-authentication.js +102 -0
- package/dist/wallet/wallet-authentication.js.map +1 -0
- package/dist/wallet/wallet-db-schema.d.ts +11 -0
- package/dist/wallet/wallet-db-schema.d.ts.map +1 -0
- package/dist/wallet/wallet-db-schema.js +79 -0
- package/dist/wallet/wallet-db-schema.js.map +1 -0
- package/dist/wallet/wallet-security.d.ts +58 -0
- package/dist/wallet/wallet-security.d.ts.map +1 -0
- package/dist/wallet/wallet-security.js +148 -0
- package/dist/wallet/wallet-security.js.map +1 -0
- package/dist/wallet/wallet-seed-manager.d.ts +65 -0
- package/dist/wallet/wallet-seed-manager.d.ts.map +1 -0
- package/dist/wallet/wallet-seed-manager.js +418 -0
- package/dist/wallet/wallet-seed-manager.js.map +1 -0
- package/package.json +134 -0
|
@@ -0,0 +1,1057 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CHAIN_FORMAT_REGEX = void 0;
|
|
4
|
+
exports.createAdminRouter = createAdminRouter;
|
|
5
|
+
exports.validateDepositRequest = validateDepositRequest;
|
|
6
|
+
exports.validateSettlementConfig = validateSettlementConfig;
|
|
7
|
+
exports.validateOpenChannelRequest = validateOpenChannelRequest;
|
|
8
|
+
const node_crypto_1 = require("node:crypto");
|
|
9
|
+
const netmask_1 = require("netmask");
|
|
10
|
+
const optional_require_1 = require("../utils/optional-require");
|
|
11
|
+
const shared_1 = require("@toon-protocol/shared");
|
|
12
|
+
const types_1 = require("../settlement/types");
|
|
13
|
+
const ilp_send_handler_1 = require("./ilp-send-handler");
|
|
14
|
+
function normalizeIP(ip) {
|
|
15
|
+
if (ip.startsWith('::ffff:')) {
|
|
16
|
+
return ip.substring(7);
|
|
17
|
+
}
|
|
18
|
+
return ip;
|
|
19
|
+
}
|
|
20
|
+
function getClientIP(req, trustProxy) {
|
|
21
|
+
if (trustProxy) {
|
|
22
|
+
const forwardedFor = req.headers['x-forwarded-for'];
|
|
23
|
+
if (forwardedFor) {
|
|
24
|
+
const headerValue = typeof forwardedFor === 'string' ? forwardedFor : forwardedFor[0];
|
|
25
|
+
if (headerValue) {
|
|
26
|
+
const ips = headerValue.split(',');
|
|
27
|
+
const firstIP = ips[0];
|
|
28
|
+
if (firstIP) {
|
|
29
|
+
return normalizeIP(firstIP.trim());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const rawIP = req.ip || req.socket.remoteAddress || 'unknown';
|
|
35
|
+
return normalizeIP(rawIP);
|
|
36
|
+
}
|
|
37
|
+
function isIPAllowed(ip, allowedIPs) {
|
|
38
|
+
for (const allowed of allowedIPs) {
|
|
39
|
+
try {
|
|
40
|
+
if (allowed.includes('/')) {
|
|
41
|
+
const block = new netmask_1.Netmask(allowed);
|
|
42
|
+
if (block.contains(ip)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
if (ip === allowed) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
function createIPAllowlistMiddleware(allowedIPs, trustProxy, logger) {
|
|
59
|
+
const log = logger.child({ component: 'IPAllowlist' });
|
|
60
|
+
return (req, res, next) => {
|
|
61
|
+
const clientIP = getClientIP(req, trustProxy);
|
|
62
|
+
if (!isIPAllowed(clientIP, allowedIPs)) {
|
|
63
|
+
log.warn({
|
|
64
|
+
event: 'admin_api_ip_blocked',
|
|
65
|
+
ip: clientIP,
|
|
66
|
+
path: req.path,
|
|
67
|
+
allowedIPs,
|
|
68
|
+
trustProxy,
|
|
69
|
+
}, 'Admin API request blocked by IP allowlist');
|
|
70
|
+
res.status(403).json({
|
|
71
|
+
error: 'Forbidden',
|
|
72
|
+
message: 'IP address not allowed',
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
next();
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async function createAdminRouter(config) {
|
|
80
|
+
const { default: express } = await (0, optional_require_1.requireOptional)('express', 'HTTP admin/health APIs');
|
|
81
|
+
const router = express.Router();
|
|
82
|
+
const { routingTable, btpClientManager, logger, apiKey, allowedIPs, trustProxy = false, nodeId, settlementPeers, channelManager, paymentChannelSDK, accountManager, settlementMonitor, claimReceiver, packetSender, isReady, defaultSettlementTokenId, } = config;
|
|
83
|
+
const log = logger.child({ component: 'AdminAPI' });
|
|
84
|
+
router.use(express.json());
|
|
85
|
+
if (allowedIPs && allowedIPs.length > 0) {
|
|
86
|
+
router.use(createIPAllowlistMiddleware(allowedIPs, trustProxy, logger));
|
|
87
|
+
}
|
|
88
|
+
if (apiKey) {
|
|
89
|
+
const apiKeyBuffer = Buffer.from(apiKey);
|
|
90
|
+
router.use((req, res, next) => {
|
|
91
|
+
if (req.query.apiKey) {
|
|
92
|
+
log.warn({
|
|
93
|
+
event: 'admin_api_key_in_query',
|
|
94
|
+
ip: req.ip,
|
|
95
|
+
path: req.path,
|
|
96
|
+
}, 'API key supplied via query parameter (rejected — use X-Api-Key header)');
|
|
97
|
+
res.status(401).json({
|
|
98
|
+
error: 'Unauthorized',
|
|
99
|
+
message: 'API key must be provided via X-Api-Key header, not query parameter',
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const providedKey = req.headers['x-api-key'];
|
|
104
|
+
const providedBuffer = Buffer.from(typeof providedKey === 'string' ? providedKey : '');
|
|
105
|
+
const isLengthMatch = providedBuffer.length === apiKeyBuffer.length;
|
|
106
|
+
const comparand = isLengthMatch ? apiKeyBuffer : providedBuffer;
|
|
107
|
+
const isMatch = (0, node_crypto_1.timingSafeEqual)(providedBuffer, comparand) && isLengthMatch;
|
|
108
|
+
if (!isMatch) {
|
|
109
|
+
log.warn({
|
|
110
|
+
event: 'admin_api_auth_failed',
|
|
111
|
+
ip: req.ip,
|
|
112
|
+
path: req.path,
|
|
113
|
+
}, 'Admin API authentication failed');
|
|
114
|
+
res.status(401).json({
|
|
115
|
+
error: 'Unauthorized',
|
|
116
|
+
message: 'Invalid or missing API key',
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
next();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
router.use((req, _res, next) => {
|
|
124
|
+
log.info({
|
|
125
|
+
event: 'admin_api_request',
|
|
126
|
+
method: req.method,
|
|
127
|
+
path: req.path,
|
|
128
|
+
ip: req.ip,
|
|
129
|
+
}, `Admin API: ${req.method} ${req.path}`);
|
|
130
|
+
next();
|
|
131
|
+
});
|
|
132
|
+
router.get('/peers', (_req, res) => {
|
|
133
|
+
try {
|
|
134
|
+
const peerIds = btpClientManager.getPeerIds();
|
|
135
|
+
const peerStatus = btpClientManager.getPeerStatus();
|
|
136
|
+
const routes = routingTable.getAllRoutes();
|
|
137
|
+
const peers = peerIds.map((peerId) => {
|
|
138
|
+
const peerRoutes = routes.filter((r) => r.nextHop === peerId);
|
|
139
|
+
const ilpAddresses = peerRoutes.map((r) => r.prefix);
|
|
140
|
+
const peerResponse = {
|
|
141
|
+
id: peerId,
|
|
142
|
+
connected: peerStatus.get(peerId) ?? false,
|
|
143
|
+
ilpAddresses,
|
|
144
|
+
routeCount: peerRoutes.length,
|
|
145
|
+
};
|
|
146
|
+
if (settlementPeers) {
|
|
147
|
+
const peerConfig = settlementPeers.get(peerId);
|
|
148
|
+
if (peerConfig) {
|
|
149
|
+
peerResponse.settlement = {
|
|
150
|
+
preference: peerConfig.settlementPreference,
|
|
151
|
+
evmAddress: peerConfig.evmAddress,
|
|
152
|
+
tokenAddress: peerConfig.tokenAddress,
|
|
153
|
+
tokenNetworkAddress: peerConfig.tokenNetworkAddress,
|
|
154
|
+
chainId: peerConfig.chainId,
|
|
155
|
+
channelId: peerConfig.channelId,
|
|
156
|
+
initialDeposit: peerConfig.initialDeposit,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return peerResponse;
|
|
161
|
+
});
|
|
162
|
+
res.json({
|
|
163
|
+
nodeId,
|
|
164
|
+
peerCount: peers.length,
|
|
165
|
+
connectedCount: peers.filter((p) => p.connected).length,
|
|
166
|
+
peers,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
171
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to list peers');
|
|
172
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
router.post('/peers', async (req, res) => {
|
|
176
|
+
try {
|
|
177
|
+
const body = req.body;
|
|
178
|
+
if (!body.id || typeof body.id !== 'string') {
|
|
179
|
+
res.status(400).json({ error: 'Bad request', message: 'Missing or invalid peer id' });
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (!body.url || typeof body.url !== 'string') {
|
|
183
|
+
res.status(400).json({ error: 'Bad request', message: 'Missing or invalid peer url' });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (body.authToken === undefined ||
|
|
187
|
+
body.authToken === null ||
|
|
188
|
+
typeof body.authToken !== 'string') {
|
|
189
|
+
res.status(400).json({
|
|
190
|
+
error: 'Bad request',
|
|
191
|
+
message: 'authToken must be a string (can be empty for no auth)',
|
|
192
|
+
});
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (!body.url.startsWith('ws://') && !body.url.startsWith('wss://')) {
|
|
196
|
+
res.status(400).json({
|
|
197
|
+
error: 'Bad request',
|
|
198
|
+
message: 'URL must start with ws:// or wss://',
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const existingPeers = btpClientManager.getPeerIds();
|
|
203
|
+
const isUpdate = existingPeers.includes(body.id);
|
|
204
|
+
if (body.routes) {
|
|
205
|
+
for (const route of body.routes) {
|
|
206
|
+
if (!route.prefix || typeof route.prefix !== 'string') {
|
|
207
|
+
res.status(400).json({
|
|
208
|
+
error: 'Bad request',
|
|
209
|
+
message: 'Invalid route: missing prefix',
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (!(0, shared_1.isValidILPAddress)(route.prefix)) {
|
|
214
|
+
res.status(400).json({
|
|
215
|
+
error: 'Bad request',
|
|
216
|
+
message: `Invalid ILP address prefix: ${route.prefix}`,
|
|
217
|
+
});
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (body.settlement) {
|
|
223
|
+
const settlementError = validateSettlementConfig(body.settlement);
|
|
224
|
+
if (settlementError) {
|
|
225
|
+
res.status(400).json({ error: 'Bad request', message: settlementError });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (!isUpdate) {
|
|
230
|
+
const peer = {
|
|
231
|
+
id: body.id,
|
|
232
|
+
url: body.url,
|
|
233
|
+
authToken: body.authToken,
|
|
234
|
+
connected: false,
|
|
235
|
+
lastSeen: new Date(),
|
|
236
|
+
};
|
|
237
|
+
await btpClientManager.addPeer(peer);
|
|
238
|
+
log.info({ event: 'admin_peer_added', peerId: body.id, url: body.url }, `Added peer: ${body.id}`);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
log.info({ event: 'admin_peer_reregistered', peerId: body.id }, `Re-registering peer: ${body.id}`);
|
|
242
|
+
}
|
|
243
|
+
const addedRoutes = [];
|
|
244
|
+
if (body.routes) {
|
|
245
|
+
for (const route of body.routes) {
|
|
246
|
+
routingTable.addRoute(route.prefix, body.id, route.priority ?? 0);
|
|
247
|
+
addedRoutes.push(route.prefix);
|
|
248
|
+
log.info({ event: 'admin_route_added', prefix: route.prefix, nextHop: body.id }, `Added route: ${route.prefix} -> ${body.id}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (body.settlement && settlementPeers) {
|
|
252
|
+
const s = body.settlement;
|
|
253
|
+
const ilpAddress = body.routes && body.routes.length > 0 ? body.routes[0].prefix : '';
|
|
254
|
+
const settlementTokens = [];
|
|
255
|
+
if (s.tokenAddress) {
|
|
256
|
+
settlementTokens.push(s.tokenAddress);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
if (s.evmAddress)
|
|
260
|
+
settlementTokens.push('EVM');
|
|
261
|
+
}
|
|
262
|
+
const newConfig = {
|
|
263
|
+
peerId: body.id,
|
|
264
|
+
address: ilpAddress,
|
|
265
|
+
settlementPreference: s.preference,
|
|
266
|
+
settlementTokens,
|
|
267
|
+
evmAddress: s.evmAddress,
|
|
268
|
+
tokenAddress: s.tokenAddress,
|
|
269
|
+
tokenNetworkAddress: s.tokenNetworkAddress,
|
|
270
|
+
chainId: s.chainId,
|
|
271
|
+
channelId: s.channelId,
|
|
272
|
+
initialDeposit: s.initialDeposit,
|
|
273
|
+
};
|
|
274
|
+
if (isUpdate) {
|
|
275
|
+
const existingConfig = settlementPeers.get(body.id);
|
|
276
|
+
if (existingConfig) {
|
|
277
|
+
const mergedConfig = { ...existingConfig };
|
|
278
|
+
for (const [key, value] of Object.entries(newConfig)) {
|
|
279
|
+
if (value !== undefined) {
|
|
280
|
+
mergedConfig[key] = value;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
settlementPeers.set(body.id, mergedConfig);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
settlementPeers.set(body.id, newConfig);
|
|
287
|
+
}
|
|
288
|
+
log.info({
|
|
289
|
+
event: 'admin_settlement_config_merged',
|
|
290
|
+
peerId: body.id,
|
|
291
|
+
preference: s.preference,
|
|
292
|
+
}, `Merged settlement config for peer: ${body.id}`);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
settlementPeers.set(body.id, newConfig);
|
|
296
|
+
log.info({
|
|
297
|
+
event: 'admin_settlement_config_added',
|
|
298
|
+
peerId: body.id,
|
|
299
|
+
preference: s.preference,
|
|
300
|
+
}, `Added settlement config for peer: ${body.id}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (isUpdate) {
|
|
304
|
+
const connected = btpClientManager.isConnected(body.id);
|
|
305
|
+
res.status(200).json({
|
|
306
|
+
success: true,
|
|
307
|
+
peer: {
|
|
308
|
+
id: body.id,
|
|
309
|
+
url: body.url,
|
|
310
|
+
connected,
|
|
311
|
+
},
|
|
312
|
+
routes: addedRoutes,
|
|
313
|
+
updated: true,
|
|
314
|
+
message: `Peer '${body.id}' updated`,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
319
|
+
const connected = btpClientManager.isConnected(body.id);
|
|
320
|
+
res.status(201).json({
|
|
321
|
+
success: true,
|
|
322
|
+
peer: {
|
|
323
|
+
id: body.id,
|
|
324
|
+
url: body.url,
|
|
325
|
+
connected,
|
|
326
|
+
},
|
|
327
|
+
routes: addedRoutes,
|
|
328
|
+
created: true,
|
|
329
|
+
message: connected
|
|
330
|
+
? `Peer '${body.id}' added and connected`
|
|
331
|
+
: `Peer '${body.id}' added (connection pending)`,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
337
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to add peer');
|
|
338
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
router.delete('/peers/:peerId', async (req, res) => {
|
|
342
|
+
try {
|
|
343
|
+
const peerId = req.params.peerId;
|
|
344
|
+
if (!peerId) {
|
|
345
|
+
res.status(400).json({ error: 'Bad request', message: 'Missing peerId parameter' });
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const removeRoutes = req.query.removeRoutes !== 'false';
|
|
349
|
+
const existingPeers = btpClientManager.getPeerIds();
|
|
350
|
+
if (!existingPeers.includes(peerId)) {
|
|
351
|
+
res.status(404).json({
|
|
352
|
+
error: 'Not found',
|
|
353
|
+
message: `Peer '${peerId}' not found`,
|
|
354
|
+
});
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
await btpClientManager.removePeer(peerId);
|
|
358
|
+
log.info({ event: 'admin_peer_removed', peerId }, `Removed peer: ${peerId}`);
|
|
359
|
+
if (settlementPeers && settlementPeers.delete(peerId)) {
|
|
360
|
+
log.info({ event: 'admin_settlement_config_removed', peerId }, `Removed settlement config for peer: ${peerId}`);
|
|
361
|
+
}
|
|
362
|
+
const removedRoutes = [];
|
|
363
|
+
if (removeRoutes) {
|
|
364
|
+
const routes = routingTable.getAllRoutes();
|
|
365
|
+
for (const route of routes) {
|
|
366
|
+
if (route.nextHop === peerId) {
|
|
367
|
+
routingTable.removeRoute(route.prefix);
|
|
368
|
+
removedRoutes.push(route.prefix);
|
|
369
|
+
log.info({ event: 'admin_route_removed', prefix: route.prefix }, `Removed route: ${route.prefix}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
res.json({
|
|
374
|
+
success: true,
|
|
375
|
+
peerId,
|
|
376
|
+
removedRoutes,
|
|
377
|
+
message: `Peer '${peerId}' removed${removedRoutes.length > 0 ? ` with ${removedRoutes.length} routes` : ''}`,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
382
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to remove peer');
|
|
383
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
router.put('/peers/:peerId', (req, res) => {
|
|
387
|
+
try {
|
|
388
|
+
const peerId = req.params.peerId;
|
|
389
|
+
if (!peerId) {
|
|
390
|
+
res.status(400).json({ error: 'Bad request', message: 'Missing peerId parameter' });
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const existingPeers = btpClientManager.getPeerIds();
|
|
394
|
+
if (!existingPeers.includes(peerId)) {
|
|
395
|
+
res.status(404).json({
|
|
396
|
+
error: 'Not found',
|
|
397
|
+
message: 'Peer not found',
|
|
398
|
+
});
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const body = req.body;
|
|
402
|
+
if (body.settlement) {
|
|
403
|
+
const settlementError = validateSettlementConfig(body.settlement);
|
|
404
|
+
if (settlementError) {
|
|
405
|
+
res.status(400).json({ error: 'Bad request', message: settlementError });
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
if (body.routes) {
|
|
410
|
+
for (const route of body.routes) {
|
|
411
|
+
if (!route.prefix || typeof route.prefix !== 'string') {
|
|
412
|
+
res.status(400).json({
|
|
413
|
+
error: 'Bad request',
|
|
414
|
+
message: 'Invalid route: missing prefix',
|
|
415
|
+
});
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (!(0, shared_1.isValidILPAddress)(route.prefix)) {
|
|
419
|
+
res.status(400).json({
|
|
420
|
+
error: 'Bad request',
|
|
421
|
+
message: `Invalid ILP address prefix: ${route.prefix}`,
|
|
422
|
+
});
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (body.settlement && settlementPeers) {
|
|
428
|
+
const s = body.settlement;
|
|
429
|
+
const existingConfig = settlementPeers.get(peerId);
|
|
430
|
+
const settlementTokens = [];
|
|
431
|
+
if (s.tokenAddress) {
|
|
432
|
+
settlementTokens.push(s.tokenAddress);
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
if (s.evmAddress)
|
|
436
|
+
settlementTokens.push('EVM');
|
|
437
|
+
}
|
|
438
|
+
const newConfig = {
|
|
439
|
+
peerId,
|
|
440
|
+
address: existingConfig?.address ?? '',
|
|
441
|
+
settlementPreference: s.preference,
|
|
442
|
+
settlementTokens,
|
|
443
|
+
evmAddress: s.evmAddress,
|
|
444
|
+
tokenAddress: s.tokenAddress,
|
|
445
|
+
tokenNetworkAddress: s.tokenNetworkAddress,
|
|
446
|
+
chainId: s.chainId,
|
|
447
|
+
channelId: s.channelId,
|
|
448
|
+
initialDeposit: s.initialDeposit,
|
|
449
|
+
};
|
|
450
|
+
if (existingConfig) {
|
|
451
|
+
const mergedConfig = { ...existingConfig };
|
|
452
|
+
for (const [key, value] of Object.entries(newConfig)) {
|
|
453
|
+
if (value !== undefined) {
|
|
454
|
+
mergedConfig[key] = value;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
settlementPeers.set(peerId, mergedConfig);
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
settlementPeers.set(peerId, newConfig);
|
|
461
|
+
}
|
|
462
|
+
log.info({ event: 'admin_peer_settlement_updated', peerId, preference: s.preference }, `Updated settlement config for peer: ${peerId}`);
|
|
463
|
+
}
|
|
464
|
+
if (body.routes) {
|
|
465
|
+
for (const route of body.routes) {
|
|
466
|
+
routingTable.addRoute(route.prefix, peerId, route.priority ?? 0);
|
|
467
|
+
log.info({ event: 'admin_route_added', prefix: route.prefix, nextHop: peerId }, `Added route: ${route.prefix} -> ${peerId}`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
res.status(200).json({
|
|
471
|
+
success: true,
|
|
472
|
+
peerId,
|
|
473
|
+
updated: true,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
478
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to update peer');
|
|
479
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
router.get('/routes', (_req, res) => {
|
|
483
|
+
try {
|
|
484
|
+
const routes = routingTable.getAllRoutes();
|
|
485
|
+
res.json({
|
|
486
|
+
nodeId,
|
|
487
|
+
routeCount: routes.length,
|
|
488
|
+
routes: routes.map((r) => ({
|
|
489
|
+
prefix: r.prefix,
|
|
490
|
+
nextHop: r.nextHop,
|
|
491
|
+
priority: r.priority ?? 0,
|
|
492
|
+
})),
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
497
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to list routes');
|
|
498
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
router.post('/routes', (req, res) => {
|
|
502
|
+
try {
|
|
503
|
+
const body = req.body;
|
|
504
|
+
if (!body.prefix || typeof body.prefix !== 'string') {
|
|
505
|
+
res.status(400).json({ error: 'Bad request', message: 'Missing or invalid prefix' });
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (!body.nextHop || typeof body.nextHop !== 'string') {
|
|
509
|
+
res.status(400).json({ error: 'Bad request', message: 'Missing or invalid nextHop' });
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (!(0, shared_1.isValidILPAddress)(body.prefix)) {
|
|
513
|
+
res.status(400).json({
|
|
514
|
+
error: 'Bad request',
|
|
515
|
+
message: `Invalid ILP address prefix: ${body.prefix}`,
|
|
516
|
+
});
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
const existingPeers = btpClientManager.getPeerIds();
|
|
520
|
+
const peerExists = existingPeers.includes(body.nextHop);
|
|
521
|
+
const priority = body.priority ?? 0;
|
|
522
|
+
routingTable.addRoute(body.prefix, body.nextHop, priority);
|
|
523
|
+
log.info({ event: 'admin_route_added', prefix: body.prefix, nextHop: body.nextHop, priority }, `Added route: ${body.prefix} -> ${body.nextHop}`);
|
|
524
|
+
res.status(201).json({
|
|
525
|
+
success: true,
|
|
526
|
+
route: {
|
|
527
|
+
prefix: body.prefix,
|
|
528
|
+
nextHop: body.nextHop,
|
|
529
|
+
priority,
|
|
530
|
+
},
|
|
531
|
+
warning: peerExists ? undefined : `Peer '${body.nextHop}' does not exist yet`,
|
|
532
|
+
message: `Route '${body.prefix}' -> '${body.nextHop}' added`,
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
catch (error) {
|
|
536
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
537
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to add route');
|
|
538
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
router.delete('/routes/:prefix(*)', (req, res) => {
|
|
542
|
+
try {
|
|
543
|
+
const rawPrefix = req.params.prefix;
|
|
544
|
+
if (!rawPrefix) {
|
|
545
|
+
res.status(400).json({ error: 'Bad request', message: 'Missing prefix parameter' });
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
const prefix = decodeURIComponent(rawPrefix);
|
|
549
|
+
const routes = routingTable.getAllRoutes();
|
|
550
|
+
const existingRoute = routes.find((r) => r.prefix === prefix);
|
|
551
|
+
if (!existingRoute) {
|
|
552
|
+
res.status(404).json({
|
|
553
|
+
error: 'Not found',
|
|
554
|
+
message: `Route with prefix '${prefix}' not found`,
|
|
555
|
+
});
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
routingTable.removeRoute(prefix);
|
|
559
|
+
log.info({ event: 'admin_route_removed', prefix }, `Removed route: ${prefix}`);
|
|
560
|
+
res.json({
|
|
561
|
+
success: true,
|
|
562
|
+
prefix,
|
|
563
|
+
message: `Route '${prefix}' removed`,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
568
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to remove route');
|
|
569
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
router.post('/channels', async (req, res) => {
|
|
573
|
+
try {
|
|
574
|
+
if (!channelManager) {
|
|
575
|
+
res.status(503).json({
|
|
576
|
+
error: 'Service Unavailable',
|
|
577
|
+
message: 'Settlement infrastructure not enabled',
|
|
578
|
+
});
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
const validation = validateOpenChannelRequest(req.body);
|
|
582
|
+
if (!validation.valid) {
|
|
583
|
+
res.status(400).json({ error: 'Bad request', message: validation.error });
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const body = req.body;
|
|
587
|
+
const existingPeers = btpClientManager.getPeerIds();
|
|
588
|
+
if (!existingPeers.includes(body.peerId)) {
|
|
589
|
+
res.status(404).json({
|
|
590
|
+
error: 'Not found',
|
|
591
|
+
message: `Peer '${body.peerId}' must be registered before opening channels`,
|
|
592
|
+
});
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const chainPrefix = body.chain.split(':')[0];
|
|
596
|
+
if (chainPrefix === 'evm') {
|
|
597
|
+
const tokenId = body.token ?? 'AGENT';
|
|
598
|
+
const peerConfig = settlementPeers?.get(body.peerId);
|
|
599
|
+
const peerAddress = body.peerAddress || peerConfig?.evmAddress;
|
|
600
|
+
if (!peerAddress) {
|
|
601
|
+
res.status(400).json({
|
|
602
|
+
error: 'Bad request',
|
|
603
|
+
message: 'Peer EVM address must be provided in request or peer registration',
|
|
604
|
+
});
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (body.peerAddress && !/^0x[0-9a-fA-F]{40}$/.test(body.peerAddress)) {
|
|
608
|
+
res.status(400).json({
|
|
609
|
+
error: 'Bad request',
|
|
610
|
+
message: 'Invalid EVM address format: must be 0x-prefixed 42-char hex',
|
|
611
|
+
});
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
const addressSource = body.peerAddress ? 'request' : 'registration';
|
|
615
|
+
log.info({ peerId: body.peerId, peerAddress, source: addressSource }, `Resolved peer EVM address from ${addressSource}`);
|
|
616
|
+
const existing = channelManager.getChannelForPeer(body.peerId, tokenId);
|
|
617
|
+
if (existing && existing.status !== 'closed') {
|
|
618
|
+
res.status(409).json({
|
|
619
|
+
error: 'Conflict',
|
|
620
|
+
message: `Channel already exists for peer ${body.peerId} with token ${tokenId} on chain ${body.chain}`,
|
|
621
|
+
});
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
const channelId = await channelManager.ensureChannelExists(body.peerId, tokenId, {
|
|
625
|
+
initialDeposit: BigInt(body.initialDeposit),
|
|
626
|
+
settlementTimeout: body.settlementTimeout,
|
|
627
|
+
chain: body.chain,
|
|
628
|
+
peerAddress,
|
|
629
|
+
});
|
|
630
|
+
log.info({ peerId: body.peerId, chain: body.chain, channelId }, 'Channel opened via Admin API');
|
|
631
|
+
const metadata = channelManager.getChannelById(channelId);
|
|
632
|
+
if (!metadata) {
|
|
633
|
+
res.status(500).json({
|
|
634
|
+
error: 'Internal error',
|
|
635
|
+
message: 'Channel created but metadata unavailable',
|
|
636
|
+
});
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
res.status(201).json({
|
|
640
|
+
channelId,
|
|
641
|
+
chain: body.chain,
|
|
642
|
+
status: (0, types_1.normalizeChannelStatus)(metadata.status, log),
|
|
643
|
+
deposit: body.initialDeposit,
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
res.status(400).json({
|
|
648
|
+
error: 'Bad request',
|
|
649
|
+
message: `Unsupported blockchain: ${chainPrefix}`,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
catch (error) {
|
|
654
|
+
log.error({
|
|
655
|
+
err: error,
|
|
656
|
+
peerId: req.body.peerId,
|
|
657
|
+
chain: req.body.chain,
|
|
658
|
+
}, 'Channel open failed');
|
|
659
|
+
res.status(500).json({ error: 'Internal error', message: 'Channel open failed' });
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
router.get('/channels', async (_req, res) => {
|
|
663
|
+
try {
|
|
664
|
+
if (!channelManager) {
|
|
665
|
+
res.status(503).json({
|
|
666
|
+
error: 'Service Unavailable',
|
|
667
|
+
message: 'Settlement infrastructure not enabled',
|
|
668
|
+
});
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
let channels = channelManager.getAllChannels();
|
|
672
|
+
const filterPeerId = _req.query.peerId;
|
|
673
|
+
const filterChain = _req.query.chain;
|
|
674
|
+
const filterStatus = _req.query.status;
|
|
675
|
+
if (filterPeerId) {
|
|
676
|
+
channels = channels.filter((ch) => ch.peerId === filterPeerId);
|
|
677
|
+
}
|
|
678
|
+
if (filterChain) {
|
|
679
|
+
channels = channels.filter((ch) => ch.chain === filterChain);
|
|
680
|
+
}
|
|
681
|
+
if (filterStatus) {
|
|
682
|
+
const normalizedFilter = (0, types_1.normalizeChannelStatus)(filterStatus, log);
|
|
683
|
+
channels = channels.filter((ch) => (0, types_1.normalizeChannelStatus)(ch.status, log) === normalizedFilter);
|
|
684
|
+
}
|
|
685
|
+
const summaries = channels.map((ch) => ({
|
|
686
|
+
channelId: ch.channelId,
|
|
687
|
+
peerId: ch.peerId,
|
|
688
|
+
chain: ch.chain,
|
|
689
|
+
status: (0, types_1.normalizeChannelStatus)(ch.status, log),
|
|
690
|
+
deposit: 'unknown',
|
|
691
|
+
lastActivity: ch.lastActivityAt.toISOString(),
|
|
692
|
+
}));
|
|
693
|
+
if (paymentChannelSDK) {
|
|
694
|
+
await Promise.all(summaries.map(async (summary) => {
|
|
695
|
+
try {
|
|
696
|
+
const ch = channels.find((c) => c.channelId === summary.channelId);
|
|
697
|
+
if (ch) {
|
|
698
|
+
const state = await paymentChannelSDK.getChannelState(ch.channelId, ch.tokenAddress);
|
|
699
|
+
summary.deposit = state.myDeposit.toString();
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
catch {
|
|
703
|
+
}
|
|
704
|
+
}));
|
|
705
|
+
}
|
|
706
|
+
res.json(summaries);
|
|
707
|
+
}
|
|
708
|
+
catch (error) {
|
|
709
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
710
|
+
log.error({ event: 'admin_api_error', error: errorMessage }, 'Failed to list channels');
|
|
711
|
+
res.status(500).json({ error: 'Internal server error', message: errorMessage });
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
router.get('/channels/:channelId', async (req, res) => {
|
|
715
|
+
try {
|
|
716
|
+
if (!channelManager) {
|
|
717
|
+
res.status(503).json({
|
|
718
|
+
error: 'Service Unavailable',
|
|
719
|
+
message: 'Settlement infrastructure not enabled',
|
|
720
|
+
});
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
const reqChannelId = req.params.channelId;
|
|
724
|
+
const metadata = channelManager.getChannelById(reqChannelId);
|
|
725
|
+
if (!metadata) {
|
|
726
|
+
res.status(404).json({ error: 'Not found', message: 'Channel not found' });
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
if (paymentChannelSDK && metadata.chain.startsWith('evm')) {
|
|
730
|
+
const state = await paymentChannelSDK.getChannelState(metadata.channelId, metadata.tokenAddress);
|
|
731
|
+
res.json({
|
|
732
|
+
channelId: state.channelId,
|
|
733
|
+
participants: state.participants,
|
|
734
|
+
deposit: state.myDeposit.toString(),
|
|
735
|
+
theirDeposit: state.theirDeposit.toString(),
|
|
736
|
+
transferred: state.myTransferred.toString(),
|
|
737
|
+
theirTransferred: state.theirTransferred.toString(),
|
|
738
|
+
status: (0, types_1.normalizeChannelStatus)(state.status, log),
|
|
739
|
+
nonce: state.myNonce,
|
|
740
|
+
theirNonce: state.theirNonce,
|
|
741
|
+
settlementTimeout: state.settlementTimeout,
|
|
742
|
+
openedAt: state.openedAt,
|
|
743
|
+
closedAt: state.closedAt,
|
|
744
|
+
});
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
res.json({
|
|
748
|
+
channelId: metadata.channelId,
|
|
749
|
+
peerId: metadata.peerId,
|
|
750
|
+
chain: metadata.chain,
|
|
751
|
+
status: (0, types_1.normalizeChannelStatus)(metadata.status, log),
|
|
752
|
+
deposit: 'unknown',
|
|
753
|
+
tokenId: metadata.tokenId,
|
|
754
|
+
createdAt: metadata.createdAt.toISOString(),
|
|
755
|
+
lastActivity: metadata.lastActivityAt.toISOString(),
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
catch (error) {
|
|
759
|
+
log.error({ err: error, channelId: req.params.channelId }, 'Failed to query channel state');
|
|
760
|
+
res.status(500).json({ error: 'Internal error', message: 'Failed to query channel state' });
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
router.post('/channels/:channelId/deposit', async (req, res) => {
|
|
764
|
+
try {
|
|
765
|
+
if (!channelManager) {
|
|
766
|
+
res.status(503).json({
|
|
767
|
+
error: 'Service Unavailable',
|
|
768
|
+
message: 'Settlement infrastructure not enabled',
|
|
769
|
+
});
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const reqChannelId = req.params.channelId;
|
|
773
|
+
const metadata = channelManager.getChannelById(reqChannelId);
|
|
774
|
+
if (!metadata) {
|
|
775
|
+
res.status(404).json({ error: 'Not found', message: 'Channel not found' });
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
const validation = validateDepositRequest(req.body);
|
|
779
|
+
if (!validation.valid) {
|
|
780
|
+
res.status(400).json({ error: 'Bad request', message: validation.error });
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
if ((0, types_1.normalizeChannelStatus)(metadata.status, log) !== 'open') {
|
|
784
|
+
res.status(400).json({
|
|
785
|
+
error: 'Bad request',
|
|
786
|
+
message: 'Channel is not in open state',
|
|
787
|
+
});
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
const { amount } = req.body;
|
|
791
|
+
const chainPrefix = metadata.chain.split(':')[0];
|
|
792
|
+
if (chainPrefix === 'evm') {
|
|
793
|
+
if (!paymentChannelSDK) {
|
|
794
|
+
res.status(503).json({
|
|
795
|
+
error: 'Service Unavailable',
|
|
796
|
+
message: 'EVM settlement infrastructure not enabled',
|
|
797
|
+
});
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
await paymentChannelSDK.deposit(reqChannelId, metadata.tokenAddress, BigInt(amount));
|
|
801
|
+
const state = await paymentChannelSDK.getChannelState(reqChannelId, metadata.tokenAddress);
|
|
802
|
+
metadata.lastActivityAt = new Date();
|
|
803
|
+
log.info({ channelId: reqChannelId, chain: chainPrefix, amount }, 'Deposit completed via Admin API');
|
|
804
|
+
res.json({
|
|
805
|
+
channelId: reqChannelId,
|
|
806
|
+
newDeposit: state.myDeposit.toString(),
|
|
807
|
+
status: (0, types_1.normalizeChannelStatus)(metadata.status, log),
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
res.status(400).json({
|
|
812
|
+
error: 'Bad request',
|
|
813
|
+
message: `Unsupported blockchain: ${chainPrefix}`,
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
catch (error) {
|
|
818
|
+
log.error({ err: error, channelId: req.params.channelId }, 'Deposit failed');
|
|
819
|
+
res.status(500).json({ error: 'Internal error', message: 'Deposit failed' });
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
router.post('/channels/:channelId/close', async (req, res) => {
|
|
823
|
+
try {
|
|
824
|
+
if (!channelManager) {
|
|
825
|
+
res.status(503).json({
|
|
826
|
+
error: 'Service Unavailable',
|
|
827
|
+
message: 'Settlement infrastructure not enabled',
|
|
828
|
+
});
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
const reqChannelId = req.params.channelId;
|
|
832
|
+
const metadata = channelManager.getChannelById(reqChannelId);
|
|
833
|
+
if (!metadata) {
|
|
834
|
+
res.status(404).json({ error: 'Not found', message: 'Channel not found' });
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
const normalizedStatus = (0, types_1.normalizeChannelStatus)(metadata.status, log);
|
|
838
|
+
if (normalizedStatus !== 'open' && normalizedStatus !== 'opening') {
|
|
839
|
+
res.status(400).json({
|
|
840
|
+
error: 'Bad request',
|
|
841
|
+
message: 'Channel is not in a closeable state',
|
|
842
|
+
});
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const chainPrefix = metadata.chain.split(':')[0];
|
|
846
|
+
if (chainPrefix === 'evm') {
|
|
847
|
+
if (!paymentChannelSDK) {
|
|
848
|
+
res.status(503).json({
|
|
849
|
+
error: 'Service Unavailable',
|
|
850
|
+
message: 'EVM settlement infrastructure not enabled',
|
|
851
|
+
});
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
await paymentChannelSDK.closeChannel(reqChannelId, metadata.tokenAddress);
|
|
855
|
+
metadata.status = 'closing';
|
|
856
|
+
metadata.lastActivityAt = new Date();
|
|
857
|
+
log.info({ channelId: reqChannelId, chain: chainPrefix }, 'Channel close initiated via Admin API (grace period started)');
|
|
858
|
+
res.json({
|
|
859
|
+
channelId: reqChannelId,
|
|
860
|
+
status: 'closing',
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
res.status(400).json({
|
|
865
|
+
error: 'Bad request',
|
|
866
|
+
message: `Unsupported blockchain: ${chainPrefix}`,
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
catch (error) {
|
|
871
|
+
log.error({ err: error, channelId: req.params.channelId }, 'Channel close failed');
|
|
872
|
+
res.status(500).json({ error: 'Internal error', message: 'Channel close failed' });
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
router.get('/balances/:peerId', async (req, res) => {
|
|
876
|
+
try {
|
|
877
|
+
if (!accountManager) {
|
|
878
|
+
res.status(503).json({
|
|
879
|
+
error: 'Service Unavailable',
|
|
880
|
+
message: 'Account management not enabled',
|
|
881
|
+
});
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
const peerId = req.params.peerId;
|
|
885
|
+
const tokenId = req.query.tokenId || (defaultSettlementTokenId ?? 'M2M');
|
|
886
|
+
const balance = await accountManager.getAccountBalance(peerId, tokenId);
|
|
887
|
+
const response = {
|
|
888
|
+
peerId,
|
|
889
|
+
balances: [
|
|
890
|
+
{
|
|
891
|
+
tokenId,
|
|
892
|
+
debitBalance: balance.debitBalance.toString(),
|
|
893
|
+
creditBalance: balance.creditBalance.toString(),
|
|
894
|
+
netBalance: balance.netBalance.toString(),
|
|
895
|
+
},
|
|
896
|
+
],
|
|
897
|
+
};
|
|
898
|
+
log.info({ peerId, tokenId }, 'Balance queried via Admin API');
|
|
899
|
+
res.json(response);
|
|
900
|
+
}
|
|
901
|
+
catch (error) {
|
|
902
|
+
log.error({ err: error, peerId: req.params.peerId }, 'Balance query failed');
|
|
903
|
+
res.status(500).json({ error: 'Internal error', message: 'Balance query failed' });
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
router.get('/settlement/states', (_req, res) => {
|
|
907
|
+
try {
|
|
908
|
+
if (!settlementMonitor) {
|
|
909
|
+
res.status(503).json({
|
|
910
|
+
error: 'Service Unavailable',
|
|
911
|
+
message: 'Settlement monitoring not enabled',
|
|
912
|
+
});
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
const allStates = settlementMonitor.getAllSettlementStates();
|
|
916
|
+
const states = [];
|
|
917
|
+
for (const [key, state] of allStates.entries()) {
|
|
918
|
+
const separatorIndex = key.lastIndexOf(':');
|
|
919
|
+
const peerId = key.substring(0, separatorIndex);
|
|
920
|
+
const tokenId = key.substring(separatorIndex + 1);
|
|
921
|
+
states.push({ peerId, tokenId, state });
|
|
922
|
+
}
|
|
923
|
+
log.info({ stateCount: states.length }, 'Settlement states queried via Admin API');
|
|
924
|
+
res.json(states);
|
|
925
|
+
}
|
|
926
|
+
catch (error) {
|
|
927
|
+
log.error({ err: error }, 'Settlement state query failed');
|
|
928
|
+
res.status(500).json({ error: 'Internal error', message: 'Settlement state query failed' });
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
router.get('/channels/:channelId/claims', async (req, res) => {
|
|
932
|
+
try {
|
|
933
|
+
if (!channelManager) {
|
|
934
|
+
res.status(503).json({
|
|
935
|
+
error: 'Service Unavailable',
|
|
936
|
+
message: 'Settlement infrastructure not enabled',
|
|
937
|
+
});
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
if (!claimReceiver) {
|
|
941
|
+
res.status(503).json({
|
|
942
|
+
error: 'Service Unavailable',
|
|
943
|
+
message: 'Claim receiver not enabled',
|
|
944
|
+
});
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
const channelId = req.params.channelId;
|
|
948
|
+
const metadata = channelManager.getChannelById(channelId);
|
|
949
|
+
if (!metadata) {
|
|
950
|
+
res.status(404).json({ error: 'Not found', message: 'Channel not found' });
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
const chainPrefix = metadata.chain.split(':')[0];
|
|
954
|
+
const blockchain = chainPrefix;
|
|
955
|
+
const claim = await claimReceiver.getLatestVerifiedClaim(metadata.peerId, blockchain, channelId);
|
|
956
|
+
if (!claim) {
|
|
957
|
+
res.status(404).json({ error: 'Not found', message: 'No claims found for this channel' });
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
log.info({ channelId, blockchain }, 'Claim queried via Admin API');
|
|
961
|
+
res.json(claim);
|
|
962
|
+
}
|
|
963
|
+
catch (error) {
|
|
964
|
+
log.error({ err: error, channelId: req.params.channelId }, 'Claim query failed');
|
|
965
|
+
res.status(500).json({ error: 'Internal error', message: 'Claim query failed' });
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
const ilpSendHandler = new ilp_send_handler_1.IlpSendHandler(packetSender ?? null, isReady ?? null, log);
|
|
969
|
+
router.post('/ilp/send', ilpSendHandler.handle.bind(ilpSendHandler));
|
|
970
|
+
return router;
|
|
971
|
+
}
|
|
972
|
+
exports.CHAIN_FORMAT_REGEX = /^evm:[a-zA-Z0-9]+:\d+$/;
|
|
973
|
+
function validateDepositRequest(body) {
|
|
974
|
+
if (body.amount === undefined || body.amount === null) {
|
|
975
|
+
return { valid: false, error: 'Missing amount' };
|
|
976
|
+
}
|
|
977
|
+
if (typeof body.amount !== 'string') {
|
|
978
|
+
return { valid: false, error: 'amount must be a string' };
|
|
979
|
+
}
|
|
980
|
+
if (!(0, types_1.isValidNonNegativeIntegerString)(body.amount)) {
|
|
981
|
+
return { valid: false, error: 'amount must be a positive integer string' };
|
|
982
|
+
}
|
|
983
|
+
if (body.amount === '0') {
|
|
984
|
+
return { valid: false, error: 'amount must be greater than zero' };
|
|
985
|
+
}
|
|
986
|
+
return { valid: true };
|
|
987
|
+
}
|
|
988
|
+
function validateSettlementConfig(s) {
|
|
989
|
+
const VALID_PREFERENCES = ['evm', 'any'];
|
|
990
|
+
if (!s.preference || !VALID_PREFERENCES.includes(s.preference)) {
|
|
991
|
+
return 'settlement.preference must be one of: evm, any';
|
|
992
|
+
}
|
|
993
|
+
if (s.preference === 'evm' && !s.evmAddress) {
|
|
994
|
+
return 'settlement.evmAddress required when preference is evm';
|
|
995
|
+
}
|
|
996
|
+
if (s.preference === 'any' && !s.evmAddress) {
|
|
997
|
+
return 'settlement: evmAddress required when preference is any';
|
|
998
|
+
}
|
|
999
|
+
if (s.evmAddress && !(0, types_1.isValidEvmAddress)(s.evmAddress)) {
|
|
1000
|
+
return 'settlement.evmAddress must be a valid 0x-prefixed address (42 chars)';
|
|
1001
|
+
}
|
|
1002
|
+
if (s.tokenAddress && !(0, types_1.isValidEvmAddress)(s.tokenAddress)) {
|
|
1003
|
+
return 'settlement.tokenAddress must be a valid 0x-prefixed address (42 chars)';
|
|
1004
|
+
}
|
|
1005
|
+
if (s.tokenNetworkAddress && !(0, types_1.isValidEvmAddress)(s.tokenNetworkAddress)) {
|
|
1006
|
+
return 'settlement.tokenNetworkAddress must be a valid 0x-prefixed address (42 chars)';
|
|
1007
|
+
}
|
|
1008
|
+
if (s.chainId !== undefined && (!Number.isInteger(s.chainId) || s.chainId <= 0)) {
|
|
1009
|
+
return 'settlement.chainId must be a positive integer';
|
|
1010
|
+
}
|
|
1011
|
+
if (s.initialDeposit !== undefined && !(0, types_1.isValidNonNegativeIntegerString)(s.initialDeposit)) {
|
|
1012
|
+
return 'settlement.initialDeposit must be a non-negative integer string';
|
|
1013
|
+
}
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
function validateOpenChannelRequest(body) {
|
|
1017
|
+
if (!body.peerId || typeof body.peerId !== 'string') {
|
|
1018
|
+
return { valid: false, error: 'Missing or invalid peerId' };
|
|
1019
|
+
}
|
|
1020
|
+
if (!body.chain || typeof body.chain !== 'string') {
|
|
1021
|
+
return { valid: false, error: 'Missing or invalid chain' };
|
|
1022
|
+
}
|
|
1023
|
+
if (!exports.CHAIN_FORMAT_REGEX.test(body.chain)) {
|
|
1024
|
+
return {
|
|
1025
|
+
valid: false,
|
|
1026
|
+
error: `Invalid chain format: ${body.chain}. Expected {blockchain}:{network}:{chainId}`,
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
if (body.initialDeposit === undefined || body.initialDeposit === null) {
|
|
1030
|
+
return { valid: false, error: 'Missing initialDeposit' };
|
|
1031
|
+
}
|
|
1032
|
+
if (typeof body.initialDeposit !== 'string') {
|
|
1033
|
+
return { valid: false, error: 'initialDeposit must be a string' };
|
|
1034
|
+
}
|
|
1035
|
+
if (!(0, types_1.isValidNonNegativeIntegerString)(body.initialDeposit)) {
|
|
1036
|
+
return { valid: false, error: 'initialDeposit must be a non-negative integer string' };
|
|
1037
|
+
}
|
|
1038
|
+
if (body.token !== undefined &&
|
|
1039
|
+
typeof body.token === 'string' &&
|
|
1040
|
+
!(0, types_1.isValidEvmAddress)(body.token)) {
|
|
1041
|
+
return { valid: false, error: 'Invalid token address format' };
|
|
1042
|
+
}
|
|
1043
|
+
if (body.tokenNetwork !== undefined &&
|
|
1044
|
+
typeof body.tokenNetwork === 'string' &&
|
|
1045
|
+
!(0, types_1.isValidEvmAddress)(body.tokenNetwork)) {
|
|
1046
|
+
return { valid: false, error: 'Invalid tokenNetwork address format' };
|
|
1047
|
+
}
|
|
1048
|
+
if (body.settlementTimeout !== undefined) {
|
|
1049
|
+
if (typeof body.settlementTimeout !== 'number' ||
|
|
1050
|
+
!Number.isInteger(body.settlementTimeout) ||
|
|
1051
|
+
body.settlementTimeout <= 0) {
|
|
1052
|
+
return { valid: false, error: 'settlementTimeout must be a positive integer' };
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return { valid: true };
|
|
1056
|
+
}
|
|
1057
|
+
//# sourceMappingURL=admin-api.js.map
|