@toon-protocol/connector 3.3.1 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/btp/btp-claim-types.d.ts +52 -0
- package/dist/btp/btp-claim-types.d.ts.map +1 -0
- package/dist/btp/btp-claim-types.js +209 -0
- package/dist/btp/btp-claim-types.js.map +1 -0
- package/dist/btp/btp-client-manager.d.ts +30 -0
- package/dist/btp/btp-client-manager.d.ts.map +1 -0
- package/dist/btp/btp-client-manager.js +153 -0
- package/dist/btp/btp-client-manager.js.map +1 -0
- package/dist/btp/btp-client.d.ts +58 -0
- package/dist/btp/btp-client.d.ts.map +1 -0
- package/dist/btp/btp-client.js +485 -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 +33 -0
- package/dist/btp/btp-server.d.ts.map +1 -0
- package/dist/btp/btp-server.js +485 -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/btp/inbound-claim-validator.d.ts +20 -0
- package/dist/btp/inbound-claim-validator.d.ts.map +1 -0
- package/dist/btp/inbound-claim-validator.js +150 -0
- package/dist/btp/inbound-claim-validator.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/config-loader.d.ts +24 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +436 -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 +3 -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 +226 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +52 -0
- package/dist/config/types.js.map +1 -0
- package/dist/core/connector-node.d.ts +91 -0
- package/dist/core/connector-node.d.ts.map +1 -0
- package/dist/core/connector-node.js +1322 -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 +160 -0
- package/dist/core/local-delivery-client.js.map +1 -0
- package/dist/core/packet-handler.d.ts +57 -0
- package/dist/core/packet-handler.d.ts.map +1 -0
- package/dist/core/packet-handler.js +655 -0
- package/dist/core/packet-handler.js.map +1 -0
- package/dist/core/payment-handler.d.ts +25 -0
- package/dist/core/payment-handler.d.ts.map +1 -0
- package/dist/core/payment-handler.js +104 -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/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-inventory.d.ts +29 -0
- package/dist/http/admin-api-inventory.d.ts.map +1 -0
- package/dist/http/admin-api-inventory.js +480 -0
- package/dist/http/admin-api-inventory.js.map +1 -0
- package/dist/http/admin-api.d.ts +182 -0
- package/dist/http/admin-api.d.ts.map +1 -0
- package/dist/http/admin-api.js +1324 -0
- package/dist/http/admin-api.js.map +1 -0
- package/dist/http/admin-server.d.ts +49 -0
- package/dist/http/admin-server.d.ts.map +1 -0
- package/dist/http/admin-server.js +160 -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 +15 -0
- package/dist/http/ilp-send-handler.d.ts.map +1 -0
- package/dist/http/ilp-send-handler.js +167 -0
- package/dist/http/ilp-send-handler.js.map +1 -0
- package/dist/http/types.d.ts +43 -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 +39 -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/observability/metrics-registry.d.ts +39 -0
- package/dist/observability/metrics-registry.d.ts.map +1 -0
- package/dist/observability/metrics-registry.js +151 -0
- package/dist/observability/metrics-registry.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/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/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 +51 -0
- package/dist/settlement/account-manager.d.ts.map +1 -0
- package/dist/settlement/account-manager.js +459 -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/channel-manager.d.ts +67 -0
- package/dist/settlement/channel-manager.d.ts.map +1 -0
- package/dist/settlement/channel-manager.js +226 -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 +67 -0
- package/dist/settlement/claim-receiver.d.ts.map +1 -0
- package/dist/settlement/claim-receiver.js +707 -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 +24 -0
- package/dist/settlement/claim-sender.d.ts.map +1 -0
- package/dist/settlement/claim-sender.js +146 -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/mina-payment-channel-sdk.d.ts +73 -0
- package/dist/settlement/mina-payment-channel-sdk.d.ts.map +1 -0
- package/dist/settlement/mina-payment-channel-sdk.js +538 -0
- package/dist/settlement/mina-payment-channel-sdk.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 +39 -0
- package/dist/settlement/per-packet-claim-service.d.ts.map +1 -0
- package/dist/settlement/per-packet-claim-service.js +342 -0
- package/dist/settlement/per-packet-claim-service.js.map +1 -0
- package/dist/settlement/privacy/index.d.ts +3 -0
- package/dist/settlement/privacy/index.d.ts.map +1 -0
- package/dist/settlement/privacy/index.js +11 -0
- package/dist/settlement/privacy/index.js.map +1 -0
- package/dist/settlement/privacy/nip59-claim-wrapper.d.ts +60 -0
- package/dist/settlement/privacy/nip59-claim-wrapper.d.ts.map +1 -0
- package/dist/settlement/privacy/nip59-claim-wrapper.js +361 -0
- package/dist/settlement/privacy/nip59-claim-wrapper.js.map +1 -0
- package/dist/settlement/provider/chain-provider-registry.d.ts +20 -0
- package/dist/settlement/provider/chain-provider-registry.d.ts.map +1 -0
- package/dist/settlement/provider/chain-provider-registry.js +53 -0
- package/dist/settlement/provider/chain-provider-registry.js.map +1 -0
- package/dist/settlement/provider/evm-payment-channel-provider.d.ts +31 -0
- package/dist/settlement/provider/evm-payment-channel-provider.d.ts.map +1 -0
- package/dist/settlement/provider/evm-payment-channel-provider.js +207 -0
- package/dist/settlement/provider/evm-payment-channel-provider.js.map +1 -0
- package/dist/settlement/provider/index.d.ts +6 -0
- package/dist/settlement/provider/index.d.ts.map +1 -0
- package/dist/settlement/provider/index.js +16 -0
- package/dist/settlement/provider/index.js.map +1 -0
- package/dist/settlement/provider/mina-payment-channel-provider.d.ts +43 -0
- package/dist/settlement/provider/mina-payment-channel-provider.d.ts.map +1 -0
- package/dist/settlement/provider/mina-payment-channel-provider.js +330 -0
- package/dist/settlement/provider/mina-payment-channel-provider.js.map +1 -0
- package/dist/settlement/provider/payment-channel-provider.d.ts +88 -0
- package/dist/settlement/provider/payment-channel-provider.d.ts.map +1 -0
- package/dist/settlement/provider/payment-channel-provider.js +3 -0
- package/dist/settlement/provider/payment-channel-provider.js.map +1 -0
- package/dist/settlement/provider/solana-payment-channel-provider.d.ts +38 -0
- package/dist/settlement/provider/solana-payment-channel-provider.d.ts.map +1 -0
- package/dist/settlement/provider/solana-payment-channel-provider.js +262 -0
- package/dist/settlement/provider/solana-payment-channel-provider.js.map +1 -0
- package/dist/settlement/sent-claims-queries.d.ts +23 -0
- package/dist/settlement/sent-claims-queries.d.ts.map +1 -0
- package/dist/settlement/sent-claims-queries.js +134 -0
- package/dist/settlement/sent-claims-queries.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 +51 -0
- package/dist/settlement/settlement-executor.d.ts.map +1 -0
- package/dist/settlement/settlement-executor.js +265 -0
- package/dist/settlement/settlement-executor.js.map +1 -0
- package/dist/settlement/settlement-monitor.d.ts +30 -0
- package/dist/settlement/settlement-monitor.d.ts.map +1 -0
- package/dist/settlement/settlement-monitor.js +141 -0
- package/dist/settlement/settlement-monitor.js.map +1 -0
- package/dist/settlement/solana-payment-channel-sdk.d.ts +79 -0
- package/dist/settlement/solana-payment-channel-sdk.d.ts.map +1 -0
- package/dist/settlement/solana-payment-channel-sdk.js +636 -0
- package/dist/settlement/solana-payment-channel-sdk.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/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/transport/direct-transport-provider.d.ts +12 -0
- package/dist/transport/direct-transport-provider.d.ts.map +1 -0
- package/dist/transport/direct-transport-provider.js +27 -0
- package/dist/transport/direct-transport-provider.js.map +1 -0
- package/dist/transport/index.d.ts +7 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +16 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/managed-anon-client.d.ts +47 -0
- package/dist/transport/managed-anon-client.d.ts.map +1 -0
- package/dist/transport/managed-anon-client.js +265 -0
- package/dist/transport/managed-anon-client.js.map +1 -0
- package/dist/transport/probe-tcp-port.d.ts +3 -0
- package/dist/transport/probe-tcp-port.d.ts.map +1 -0
- package/dist/transport/probe-tcp-port.js +59 -0
- package/dist/transport/probe-tcp-port.js.map +1 -0
- package/dist/transport/socks-transport-provider.d.ts +29 -0
- package/dist/transport/socks-transport-provider.d.ts.map +1 -0
- package/dist/transport/socks-transport-provider.js +136 -0
- package/dist/transport/socks-transport-provider.js.map +1 -0
- package/dist/transport/socks-url.d.ts +6 -0
- package/dist/transport/socks-url.d.ts.map +1 -0
- package/dist/transport/socks-url.js +29 -0
- package/dist/transport/socks-url.js.map +1 -0
- package/dist/transport/transport-provider.d.ts +9 -0
- package/dist/transport/transport-provider.d.ts.map +1 -0
- package/dist/transport/transport-provider.js +3 -0
- package/dist/transport/transport-provider.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/redact.d.ts +3 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +21 -0
- package/dist/utils/redact.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/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 +1 -1
|
@@ -0,0 +1,1324 @@
|
|
|
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, sentClaimsQueries, packetSender, isReady, defaultSettlementTokenId, metricsRegistry, resolveTokenMetadata, connectorFeePercentage, } = 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 registeredPeers = btpClientManager.getPeerIds();
|
|
887
|
+
if (!registeredPeers.includes(peerId)) {
|
|
888
|
+
res.status(404).json({
|
|
889
|
+
error: 'Not found',
|
|
890
|
+
peerId,
|
|
891
|
+
message: `Peer '${peerId}' not found`,
|
|
892
|
+
});
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const balance = await accountManager.getAccountBalance(peerId, tokenId);
|
|
896
|
+
const response = {
|
|
897
|
+
peerId,
|
|
898
|
+
balances: [
|
|
899
|
+
{
|
|
900
|
+
tokenId,
|
|
901
|
+
debitBalance: balance.debitBalance.toString(),
|
|
902
|
+
creditBalance: balance.creditBalance.toString(),
|
|
903
|
+
netBalance: balance.netBalance.toString(),
|
|
904
|
+
},
|
|
905
|
+
],
|
|
906
|
+
};
|
|
907
|
+
log.info({ peerId, tokenId }, 'Balance queried via Admin API');
|
|
908
|
+
res.json(response);
|
|
909
|
+
}
|
|
910
|
+
catch (error) {
|
|
911
|
+
log.error({ err: error, peerId: req.params.peerId }, 'Balance query failed');
|
|
912
|
+
res.status(500).json({ error: 'Internal error', message: 'Balance query failed' });
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
router.get('/settlement/states', (_req, res) => {
|
|
916
|
+
try {
|
|
917
|
+
if (!settlementMonitor) {
|
|
918
|
+
res.status(503).json({
|
|
919
|
+
error: 'Service Unavailable',
|
|
920
|
+
message: 'Settlement monitoring not enabled',
|
|
921
|
+
});
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
const allStates = settlementMonitor.getAllSettlementStates();
|
|
925
|
+
const states = [];
|
|
926
|
+
for (const [key, state] of allStates.entries()) {
|
|
927
|
+
const separatorIndex = key.lastIndexOf(':');
|
|
928
|
+
const peerId = key.substring(0, separatorIndex);
|
|
929
|
+
const tokenId = key.substring(separatorIndex + 1);
|
|
930
|
+
states.push({ peerId, tokenId, state });
|
|
931
|
+
}
|
|
932
|
+
log.info({ stateCount: states.length }, 'Settlement states queried via Admin API');
|
|
933
|
+
res.json(states);
|
|
934
|
+
}
|
|
935
|
+
catch (error) {
|
|
936
|
+
log.error({ err: error }, 'Settlement state query failed');
|
|
937
|
+
res.status(500).json({ error: 'Internal error', message: 'Settlement state query failed' });
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
router.get('/channels/:channelId/claims', async (req, res) => {
|
|
941
|
+
try {
|
|
942
|
+
if (!channelManager) {
|
|
943
|
+
res.status(503).json({
|
|
944
|
+
error: 'Service Unavailable',
|
|
945
|
+
message: 'Settlement infrastructure not enabled',
|
|
946
|
+
});
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
if (!claimReceiver) {
|
|
950
|
+
res.status(503).json({
|
|
951
|
+
error: 'Service Unavailable',
|
|
952
|
+
message: 'Claim receiver not enabled',
|
|
953
|
+
});
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const channelId = req.params.channelId;
|
|
957
|
+
const metadata = channelManager.getChannelById(channelId);
|
|
958
|
+
if (!metadata) {
|
|
959
|
+
res.status(404).json({ error: 'Not found', message: 'Channel not found' });
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
const chainPrefix = metadata.chain.split(':')[0];
|
|
963
|
+
const blockchain = chainPrefix;
|
|
964
|
+
const claim = await claimReceiver.getLatestVerifiedClaim(metadata.peerId, blockchain, channelId);
|
|
965
|
+
if (!claim) {
|
|
966
|
+
res.status(404).json({ error: 'Not found', message: 'No claims found for this channel' });
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
log.info({ channelId, blockchain }, 'Claim queried via Admin API');
|
|
970
|
+
res.json(claim);
|
|
971
|
+
}
|
|
972
|
+
catch (error) {
|
|
973
|
+
log.error({ err: error, channelId: req.params.channelId }, 'Claim query failed');
|
|
974
|
+
res.status(500).json({ error: 'Internal error', message: 'Claim query failed' });
|
|
975
|
+
}
|
|
976
|
+
});
|
|
977
|
+
const ilpSendHandler = new ilp_send_handler_1.IlpSendHandler(packetSender ?? null, isReady ?? null, log);
|
|
978
|
+
router.post('/ilp/send', ilpSendHandler.handle.bind(ilpSendHandler));
|
|
979
|
+
router.get('/metrics.json', async (_req, res) => {
|
|
980
|
+
try {
|
|
981
|
+
if (!metricsRegistry) {
|
|
982
|
+
res.status(503).json({
|
|
983
|
+
error: 'Service Unavailable',
|
|
984
|
+
message: 'Metrics not enabled',
|
|
985
|
+
});
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
const livePeerIds = btpClientManager.getPeerIds();
|
|
989
|
+
const peerSnapshots = await metricsRegistry.snapshotPeers();
|
|
990
|
+
const snapshotByPeer = new Map(peerSnapshots.map((s) => [s.peerId, s]));
|
|
991
|
+
const peerStatus = btpClientManager.getPeerStatus();
|
|
992
|
+
const peers = [...livePeerIds].sort().map((peerId) => {
|
|
993
|
+
const snap = snapshotByPeer.get(peerId);
|
|
994
|
+
const lastPacketAt = snap && snap.lastPacketAtUnixSeconds > 0
|
|
995
|
+
? new Date(snap.lastPacketAtUnixSeconds * 1000).toISOString()
|
|
996
|
+
: null;
|
|
997
|
+
return {
|
|
998
|
+
peerId,
|
|
999
|
+
connected: peerStatus.get(peerId) ?? false,
|
|
1000
|
+
packetsForwarded: snap?.packetsForwarded ?? 0,
|
|
1001
|
+
packetsRejected: snap?.packetsRejected ?? 0,
|
|
1002
|
+
bytesSent: snap?.bytesSent ?? 0,
|
|
1003
|
+
lastPacketAt,
|
|
1004
|
+
};
|
|
1005
|
+
});
|
|
1006
|
+
const aggregate = peers.reduce((acc, p) => ({
|
|
1007
|
+
packetsForwarded: acc.packetsForwarded + p.packetsForwarded,
|
|
1008
|
+
packetsRejected: acc.packetsRejected + p.packetsRejected,
|
|
1009
|
+
bytesSent: acc.bytesSent + p.bytesSent,
|
|
1010
|
+
}), { packetsForwarded: 0, packetsRejected: 0, bytesSent: 0 });
|
|
1011
|
+
res.set('Cache-Control', 'no-store');
|
|
1012
|
+
res.json({
|
|
1013
|
+
uptimeSeconds: Math.floor(process.uptime()),
|
|
1014
|
+
aggregate,
|
|
1015
|
+
peers,
|
|
1016
|
+
timestamp: new Date().toISOString(),
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
catch (error) {
|
|
1020
|
+
log.error({
|
|
1021
|
+
event: 'admin_api_metrics_error',
|
|
1022
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1023
|
+
}, 'Failed to generate metrics.json');
|
|
1024
|
+
res.status(500).json({
|
|
1025
|
+
error: 'Internal server error',
|
|
1026
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
router.get('/earnings.json', async (_req, res) => {
|
|
1031
|
+
try {
|
|
1032
|
+
if (!accountManager || !claimReceiver) {
|
|
1033
|
+
res.status(503).json({
|
|
1034
|
+
error: 'Service Unavailable',
|
|
1035
|
+
message: 'Earnings subsystem not enabled (accountManager or claimReceiver missing)',
|
|
1036
|
+
});
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
const metadataFallback = async (_chain, tokenAddress) => ({
|
|
1040
|
+
assetCode: tokenAddress || 'UNKNOWN',
|
|
1041
|
+
assetScale: 0,
|
|
1042
|
+
});
|
|
1043
|
+
const resolve = resolveTokenMetadata ?? metadataFallback;
|
|
1044
|
+
const metaCache = new Map();
|
|
1045
|
+
const resolveCached = async (blockchain, tokenAddress) => {
|
|
1046
|
+
const key = `${blockchain}:${tokenAddress}`;
|
|
1047
|
+
const hit = metaCache.get(key);
|
|
1048
|
+
if (hit)
|
|
1049
|
+
return hit;
|
|
1050
|
+
let meta;
|
|
1051
|
+
try {
|
|
1052
|
+
meta = await resolve(blockchain, tokenAddress);
|
|
1053
|
+
}
|
|
1054
|
+
catch (err) {
|
|
1055
|
+
log.warn({
|
|
1056
|
+
event: 'admin_api_earnings_metadata_failed',
|
|
1057
|
+
blockchain,
|
|
1058
|
+
tokenAddress,
|
|
1059
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1060
|
+
}, 'Token metadata lookup failed; using raw-address fallback');
|
|
1061
|
+
meta = await metadataFallback(blockchain, tokenAddress);
|
|
1062
|
+
}
|
|
1063
|
+
metaCache.set(key, meta);
|
|
1064
|
+
return meta;
|
|
1065
|
+
};
|
|
1066
|
+
const livePeerIds = [...btpClientManager.getPeerIds()].sort();
|
|
1067
|
+
const peersOut = [];
|
|
1068
|
+
const incomingTotalByAsset = new Map();
|
|
1069
|
+
void accountManager;
|
|
1070
|
+
for (const peerId of livePeerIds) {
|
|
1071
|
+
const inboundByAsset = await claimReceiver.getCumulativeInboundByAsset(peerId);
|
|
1072
|
+
const outboundByAsset = sentClaimsQueries
|
|
1073
|
+
? await sentClaimsQueries.getCumulativeOutboundByAsset(peerId)
|
|
1074
|
+
: new Map();
|
|
1075
|
+
const peerConfig = settlementPeers?.get(peerId);
|
|
1076
|
+
const configuredTokens = new Set();
|
|
1077
|
+
if (peerConfig?.tokenAddress)
|
|
1078
|
+
configuredTokens.add(peerConfig.tokenAddress);
|
|
1079
|
+
for (const t of peerConfig?.settlementTokens ?? [])
|
|
1080
|
+
configuredTokens.add(t);
|
|
1081
|
+
const assetKeys = new Set([...inboundByAsset.keys(), ...outboundByAsset.keys()]);
|
|
1082
|
+
const configuredBlockchain = peerConfig?.settlementPreference === 'solana'
|
|
1083
|
+
? 'solana'
|
|
1084
|
+
: peerConfig?.settlementPreference === 'mina'
|
|
1085
|
+
? 'mina'
|
|
1086
|
+
: 'evm';
|
|
1087
|
+
for (const t of configuredTokens)
|
|
1088
|
+
assetKeys.add(`${configuredBlockchain}:${t}`);
|
|
1089
|
+
const byAsset = [];
|
|
1090
|
+
for (const key of assetKeys) {
|
|
1091
|
+
const sepIdx = key.indexOf(':');
|
|
1092
|
+
const blockchain = key.substring(0, sepIdx);
|
|
1093
|
+
const tokenAddress = key.substring(sepIdx + 1);
|
|
1094
|
+
const meta = await resolveCached(blockchain, tokenAddress);
|
|
1095
|
+
const inbound = inboundByAsset.get(key);
|
|
1096
|
+
const outbound = outboundByAsset.get(key);
|
|
1097
|
+
const received = inbound?.total ?? 0n;
|
|
1098
|
+
const sent = outbound?.total ?? 0n;
|
|
1099
|
+
const lastInbound = inbound?.lastAt ?? 0;
|
|
1100
|
+
const lastOutbound = outbound?.lastAt ?? 0;
|
|
1101
|
+
const lastAtMax = Math.max(lastInbound, lastOutbound);
|
|
1102
|
+
const lastAt = lastAtMax > 0 ? lastAtMax : null;
|
|
1103
|
+
byAsset.push({
|
|
1104
|
+
assetCode: meta.assetCode,
|
|
1105
|
+
assetScale: meta.assetScale,
|
|
1106
|
+
claimsReceivedTotal: received.toString(),
|
|
1107
|
+
claimsSentTotal: sent.toString(),
|
|
1108
|
+
netBalance: (sent - received).toString(),
|
|
1109
|
+
lastClaimAt: lastAt ? new Date(lastAt).toISOString() : null,
|
|
1110
|
+
});
|
|
1111
|
+
const feeKey = `${meta.assetCode}|${meta.assetScale}`;
|
|
1112
|
+
incomingTotalByAsset.set(feeKey, (incomingTotalByAsset.get(feeKey) ?? 0n) + received);
|
|
1113
|
+
}
|
|
1114
|
+
peersOut.push({ peerId, byAsset });
|
|
1115
|
+
}
|
|
1116
|
+
const connectorFees = [];
|
|
1117
|
+
const feePct = connectorFeePercentage ?? 0;
|
|
1118
|
+
if (feePct > 0) {
|
|
1119
|
+
const basisPoints = BigInt(Math.round(feePct * 100));
|
|
1120
|
+
for (const [key, incomingSum] of incomingTotalByAsset) {
|
|
1121
|
+
if (incomingSum === 0n)
|
|
1122
|
+
continue;
|
|
1123
|
+
const sepIdx = key.lastIndexOf('|');
|
|
1124
|
+
const assetCode = key.substring(0, sepIdx);
|
|
1125
|
+
const assetScale = parseInt(key.substring(sepIdx + 1), 10);
|
|
1126
|
+
const total = (incomingSum * basisPoints) / 10000n;
|
|
1127
|
+
connectorFees.push({ assetCode, assetScale, total: total.toString() });
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
const inboundRaw = await claimReceiver.getRecentClaims(50);
|
|
1131
|
+
const outboundRaw = sentClaimsQueries ? await sentClaimsQueries.getRecentSentClaims(50) : [];
|
|
1132
|
+
const extractClaim = (blockchain, c) => {
|
|
1133
|
+
if (blockchain === 'evm') {
|
|
1134
|
+
let cum = 0n;
|
|
1135
|
+
try {
|
|
1136
|
+
cum = BigInt(c.transferredAmount ?? '0');
|
|
1137
|
+
}
|
|
1138
|
+
catch {
|
|
1139
|
+
cum = 0n;
|
|
1140
|
+
}
|
|
1141
|
+
return { tokenAddress: c.tokenAddress ?? '', cumulative: cum };
|
|
1142
|
+
}
|
|
1143
|
+
if (blockchain === 'solana') {
|
|
1144
|
+
let cum = 0n;
|
|
1145
|
+
try {
|
|
1146
|
+
cum = BigInt(c.transferredAmount ?? '0');
|
|
1147
|
+
}
|
|
1148
|
+
catch {
|
|
1149
|
+
cum = 0n;
|
|
1150
|
+
}
|
|
1151
|
+
return { tokenAddress: c.programId ?? '', cumulative: cum };
|
|
1152
|
+
}
|
|
1153
|
+
return { tokenAddress: c.tokenId ?? '', cumulative: 0n };
|
|
1154
|
+
};
|
|
1155
|
+
const parsed = [];
|
|
1156
|
+
for (const row of inboundRaw) {
|
|
1157
|
+
const blockchain = row.blockchain;
|
|
1158
|
+
const { tokenAddress, cumulative } = extractClaim(blockchain, row.claimData);
|
|
1159
|
+
const meta = tokenAddress
|
|
1160
|
+
? await resolveCached(blockchain, tokenAddress)
|
|
1161
|
+
: { assetCode: 'UNKNOWN', assetScale: 0 };
|
|
1162
|
+
parsed.push({
|
|
1163
|
+
peerId: row.peerId,
|
|
1164
|
+
blockchain,
|
|
1165
|
+
channelId: row.channelId,
|
|
1166
|
+
tokenAddress,
|
|
1167
|
+
cumulative,
|
|
1168
|
+
direction: 'inbound',
|
|
1169
|
+
at: row.receivedAt,
|
|
1170
|
+
meta,
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
for (const row of outboundRaw) {
|
|
1174
|
+
const blockchain = row.blockchain;
|
|
1175
|
+
const { tokenAddress, cumulative } = extractClaim(blockchain, row.claimData);
|
|
1176
|
+
const meta = tokenAddress
|
|
1177
|
+
? await resolveCached(blockchain, tokenAddress)
|
|
1178
|
+
: { assetCode: 'UNKNOWN', assetScale: 0 };
|
|
1179
|
+
parsed.push({
|
|
1180
|
+
peerId: row.peerId,
|
|
1181
|
+
blockchain,
|
|
1182
|
+
channelId: row.channelId,
|
|
1183
|
+
tokenAddress,
|
|
1184
|
+
cumulative,
|
|
1185
|
+
direction: 'outbound',
|
|
1186
|
+
at: row.sentAt,
|
|
1187
|
+
meta,
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
parsed.sort((a, b) => b.at - a.at);
|
|
1191
|
+
const topN = parsed.slice(0, 50);
|
|
1192
|
+
const priorByChannel = new Map();
|
|
1193
|
+
const withDeltas = [];
|
|
1194
|
+
for (let i = topN.length - 1; i >= 0; i--) {
|
|
1195
|
+
const p = topN[i];
|
|
1196
|
+
if (!p)
|
|
1197
|
+
continue;
|
|
1198
|
+
const chanKey = `${p.blockchain}:${p.channelId}:${p.direction}`;
|
|
1199
|
+
const prior = priorByChannel.get(chanKey) ?? 0n;
|
|
1200
|
+
const delta = p.cumulative - prior;
|
|
1201
|
+
priorByChannel.set(chanKey, p.cumulative);
|
|
1202
|
+
withDeltas.push({
|
|
1203
|
+
peerId: p.peerId,
|
|
1204
|
+
assetCode: p.meta.assetCode,
|
|
1205
|
+
assetScale: p.meta.assetScale,
|
|
1206
|
+
amount: delta.toString(),
|
|
1207
|
+
direction: p.direction,
|
|
1208
|
+
at: new Date(p.at).toISOString(),
|
|
1209
|
+
_sortKey: p.at,
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
withDeltas.sort((a, b) => b._sortKey - a._sortKey);
|
|
1213
|
+
const recentClaims = withDeltas.map(({ _sortKey, ...rest }) => {
|
|
1214
|
+
void _sortKey;
|
|
1215
|
+
return rest;
|
|
1216
|
+
});
|
|
1217
|
+
res.set('Cache-Control', 'no-store');
|
|
1218
|
+
res.json({
|
|
1219
|
+
uptimeSeconds: Math.floor(process.uptime()),
|
|
1220
|
+
peers: peersOut,
|
|
1221
|
+
connectorFees,
|
|
1222
|
+
recentClaims,
|
|
1223
|
+
timestamp: new Date().toISOString(),
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
catch (error) {
|
|
1227
|
+
log.error({
|
|
1228
|
+
event: 'admin_api_earnings_error',
|
|
1229
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1230
|
+
}, 'Failed to generate earnings.json');
|
|
1231
|
+
res.status(500).json({
|
|
1232
|
+
error: 'Internal server error',
|
|
1233
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
return router;
|
|
1238
|
+
}
|
|
1239
|
+
exports.CHAIN_FORMAT_REGEX = /^evm:[a-zA-Z0-9]+:\d+$/;
|
|
1240
|
+
function validateDepositRequest(body) {
|
|
1241
|
+
if (body.amount === undefined || body.amount === null) {
|
|
1242
|
+
return { valid: false, error: 'Missing amount' };
|
|
1243
|
+
}
|
|
1244
|
+
if (typeof body.amount !== 'string') {
|
|
1245
|
+
return { valid: false, error: 'amount must be a string' };
|
|
1246
|
+
}
|
|
1247
|
+
if (!(0, types_1.isValidNonNegativeIntegerString)(body.amount)) {
|
|
1248
|
+
return { valid: false, error: 'amount must be a positive integer string' };
|
|
1249
|
+
}
|
|
1250
|
+
if (body.amount === '0') {
|
|
1251
|
+
return { valid: false, error: 'amount must be greater than zero' };
|
|
1252
|
+
}
|
|
1253
|
+
return { valid: true };
|
|
1254
|
+
}
|
|
1255
|
+
function validateSettlementConfig(s) {
|
|
1256
|
+
const VALID_PREFERENCES = ['evm', 'any'];
|
|
1257
|
+
if (!s.preference || !VALID_PREFERENCES.includes(s.preference)) {
|
|
1258
|
+
return 'settlement.preference must be one of: evm, any';
|
|
1259
|
+
}
|
|
1260
|
+
if (s.preference === 'evm' && !s.evmAddress) {
|
|
1261
|
+
return 'settlement.evmAddress required when preference is evm';
|
|
1262
|
+
}
|
|
1263
|
+
if (s.preference === 'any' && !s.evmAddress) {
|
|
1264
|
+
return 'settlement: evmAddress required when preference is any';
|
|
1265
|
+
}
|
|
1266
|
+
if (s.evmAddress && !(0, types_1.isValidEvmAddress)(s.evmAddress)) {
|
|
1267
|
+
return 'settlement.evmAddress must be a valid 0x-prefixed address (42 chars)';
|
|
1268
|
+
}
|
|
1269
|
+
if (s.tokenAddress && !(0, types_1.isValidEvmAddress)(s.tokenAddress)) {
|
|
1270
|
+
return 'settlement.tokenAddress must be a valid 0x-prefixed address (42 chars)';
|
|
1271
|
+
}
|
|
1272
|
+
if (s.tokenNetworkAddress && !(0, types_1.isValidEvmAddress)(s.tokenNetworkAddress)) {
|
|
1273
|
+
return 'settlement.tokenNetworkAddress must be a valid 0x-prefixed address (42 chars)';
|
|
1274
|
+
}
|
|
1275
|
+
if (s.chainId !== undefined && (!Number.isInteger(s.chainId) || s.chainId <= 0)) {
|
|
1276
|
+
return 'settlement.chainId must be a positive integer';
|
|
1277
|
+
}
|
|
1278
|
+
if (s.initialDeposit !== undefined && !(0, types_1.isValidNonNegativeIntegerString)(s.initialDeposit)) {
|
|
1279
|
+
return 'settlement.initialDeposit must be a non-negative integer string';
|
|
1280
|
+
}
|
|
1281
|
+
return null;
|
|
1282
|
+
}
|
|
1283
|
+
function validateOpenChannelRequest(body) {
|
|
1284
|
+
if (!body.peerId || typeof body.peerId !== 'string') {
|
|
1285
|
+
return { valid: false, error: 'Missing or invalid peerId' };
|
|
1286
|
+
}
|
|
1287
|
+
if (!body.chain || typeof body.chain !== 'string') {
|
|
1288
|
+
return { valid: false, error: 'Missing or invalid chain' };
|
|
1289
|
+
}
|
|
1290
|
+
if (!exports.CHAIN_FORMAT_REGEX.test(body.chain)) {
|
|
1291
|
+
return {
|
|
1292
|
+
valid: false,
|
|
1293
|
+
error: `Invalid chain format: ${body.chain}. Expected {blockchain}:{network}:{chainId}`,
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
if (body.initialDeposit === undefined || body.initialDeposit === null) {
|
|
1297
|
+
return { valid: false, error: 'Missing initialDeposit' };
|
|
1298
|
+
}
|
|
1299
|
+
if (typeof body.initialDeposit !== 'string') {
|
|
1300
|
+
return { valid: false, error: 'initialDeposit must be a string' };
|
|
1301
|
+
}
|
|
1302
|
+
if (!(0, types_1.isValidNonNegativeIntegerString)(body.initialDeposit)) {
|
|
1303
|
+
return { valid: false, error: 'initialDeposit must be a non-negative integer string' };
|
|
1304
|
+
}
|
|
1305
|
+
if (body.token !== undefined &&
|
|
1306
|
+
typeof body.token === 'string' &&
|
|
1307
|
+
!(0, types_1.isValidEvmAddress)(body.token)) {
|
|
1308
|
+
return { valid: false, error: 'Invalid token address format' };
|
|
1309
|
+
}
|
|
1310
|
+
if (body.tokenNetwork !== undefined &&
|
|
1311
|
+
typeof body.tokenNetwork === 'string' &&
|
|
1312
|
+
!(0, types_1.isValidEvmAddress)(body.tokenNetwork)) {
|
|
1313
|
+
return { valid: false, error: 'Invalid tokenNetwork address format' };
|
|
1314
|
+
}
|
|
1315
|
+
if (body.settlementTimeout !== undefined) {
|
|
1316
|
+
if (typeof body.settlementTimeout !== 'number' ||
|
|
1317
|
+
!Number.isInteger(body.settlementTimeout) ||
|
|
1318
|
+
body.settlementTimeout <= 0) {
|
|
1319
|
+
return { valid: false, error: 'settlementTimeout must be a positive integer' };
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
return { valid: true };
|
|
1323
|
+
}
|
|
1324
|
+
//# sourceMappingURL=admin-api.js.map
|