safehands-pharos 1.5.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/policies/default.json +15 -0
- package/.env.example +81 -64
- package/README.md +301 -444
- package/SECURITY.md +112 -0
- package/SKILL.md +59 -0
- package/contracts/SafeHandsAttestation.sol +182 -0
- package/contracts/SafeHandsRegistry.sol +149 -0
- package/dist/agent/SafeHandsGuardianAgent.d.ts +39 -0
- package/dist/agent/SafeHandsGuardianAgent.d.ts.map +1 -0
- package/dist/agent/SafeHandsGuardianAgent.js +98 -0
- package/dist/agent/SafeHandsGuardianAgent.js.map +1 -0
- package/dist/agent/agentDecisionFormatter.d.ts +43 -0
- package/dist/agent/agentDecisionFormatter.d.ts.map +1 -0
- package/dist/agent/agentDecisionFormatter.js +96 -0
- package/dist/agent/agentDecisionFormatter.js.map +1 -0
- package/dist/agent/agentEnrich.d.ts +28 -0
- package/dist/agent/agentEnrich.d.ts.map +1 -0
- package/dist/agent/agentEnrich.js +99 -0
- package/dist/agent/agentEnrich.js.map +1 -0
- package/dist/agent/agentIntentClassifier.d.ts +44 -0
- package/dist/agent/agentIntentClassifier.d.ts.map +1 -0
- package/dist/agent/agentIntentClassifier.js +77 -0
- package/dist/agent/agentIntentClassifier.js.map +1 -0
- package/dist/agent/agentPolicyResolver.d.ts +44 -0
- package/dist/agent/agentPolicyResolver.d.ts.map +1 -0
- package/dist/agent/agentPolicyResolver.js +94 -0
- package/dist/agent/agentPolicyResolver.js.map +1 -0
- package/dist/agent/agentRuntime.d.ts +12 -0
- package/dist/agent/agentRuntime.d.ts.map +1 -0
- package/dist/agent/agentRuntime.js +31 -0
- package/dist/agent/agentRuntime.js.map +1 -0
- package/dist/agent/agentToolRouter.d.ts +24 -0
- package/dist/agent/agentToolRouter.d.ts.map +1 -0
- package/dist/agent/agentToolRouter.js +89 -0
- package/dist/agent/agentToolRouter.js.map +1 -0
- package/dist/agent/guardianOperator.d.ts +35 -0
- package/dist/agent/guardianOperator.d.ts.map +1 -0
- package/dist/agent/guardianOperator.js +65 -0
- package/dist/agent/guardianOperator.js.map +1 -0
- package/dist/agent/index.d.ts +8 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +14 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/api/activityRoutes.d.ts +70 -0
- package/dist/api/activityRoutes.d.ts.map +1 -0
- package/dist/api/activityRoutes.js +100 -0
- package/dist/api/activityRoutes.js.map +1 -0
- package/dist/api/agentRoutes.d.ts +16 -0
- package/dist/api/agentRoutes.d.ts.map +1 -0
- package/dist/api/agentRoutes.js +37 -0
- package/dist/api/agentRoutes.js.map +1 -0
- package/dist/api/broadcastRoutes.d.ts +34 -0
- package/dist/api/broadcastRoutes.d.ts.map +1 -0
- package/dist/api/broadcastRoutes.js +147 -0
- package/dist/api/broadcastRoutes.js.map +1 -0
- package/dist/api/consolePage.d.ts +2 -0
- package/dist/api/consolePage.d.ts.map +1 -0
- package/dist/api/consolePage.js +206 -0
- package/dist/api/consolePage.js.map +1 -0
- package/dist/api/httpHardening.d.ts +75 -0
- package/dist/api/httpHardening.d.ts.map +1 -0
- package/dist/api/httpHardening.js +122 -0
- package/dist/api/httpHardening.js.map +1 -0
- package/dist/api/indexerRoutes.d.ts +46 -0
- package/dist/api/indexerRoutes.d.ts.map +1 -0
- package/dist/api/indexerRoutes.js +75 -0
- package/dist/api/indexerRoutes.js.map +1 -0
- package/dist/api/paidRoutes.d.ts +8 -0
- package/dist/api/paidRoutes.d.ts.map +1 -0
- package/dist/api/paidRoutes.js +175 -0
- package/dist/api/paidRoutes.js.map +1 -0
- package/dist/api/prepareRoutes.d.ts +58 -0
- package/dist/api/prepareRoutes.d.ts.map +1 -0
- package/dist/api/prepareRoutes.js +90 -0
- package/dist/api/prepareRoutes.js.map +1 -0
- package/dist/api/response.d.ts +39 -0
- package/dist/api/response.d.ts.map +1 -0
- package/dist/api/response.js +53 -0
- package/dist/api/response.js.map +1 -0
- package/dist/api/routes.d.ts +175 -0
- package/dist/api/routes.d.ts.map +1 -0
- package/dist/api/routes.js +276 -0
- package/dist/api/routes.js.map +1 -0
- package/dist/api/schemas.d.ts +147 -0
- package/dist/api/schemas.d.ts.map +1 -0
- package/dist/api/schemas.js +81 -0
- package/dist/api/schemas.js.map +1 -0
- package/dist/api/server.d.ts +11 -0
- package/dist/api/server.d.ts.map +1 -0
- package/dist/api/server.js +505 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/toolRoutes.d.ts +14 -0
- package/dist/api/toolRoutes.d.ts.map +1 -0
- package/dist/api/toolRoutes.js +138 -0
- package/dist/api/toolRoutes.js.map +1 -0
- package/dist/api/walletPrepareRoutes.d.ts +74 -0
- package/dist/api/walletPrepareRoutes.d.ts.map +1 -0
- package/dist/api/walletPrepareRoutes.js +127 -0
- package/dist/api/walletPrepareRoutes.js.map +1 -0
- package/dist/api/x402Gate.d.ts +51 -0
- package/dist/api/x402Gate.d.ts.map +1 -0
- package/dist/api/x402Gate.js +184 -0
- package/dist/api/x402Gate.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +29 -1
- package/dist/cli.js.map +1 -1
- package/dist/data/ecosystemRegistry.data.d.ts +3 -0
- package/dist/data/ecosystemRegistry.data.d.ts.map +1 -0
- package/dist/data/ecosystemRegistry.data.js +582 -0
- package/dist/data/ecosystemRegistry.data.js.map +1 -0
- package/dist/demo.d.ts +0 -0
- package/dist/demo.d.ts.map +1 -1
- package/dist/demo.js +43 -8
- package/dist/demo.js.map +1 -1
- package/dist/handsafe.zip +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.d.ts.map +0 -0
- package/dist/index.js +212 -135
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +0 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +72 -10
- package/dist/init.js.map +1 -1
- package/dist/lib/analysis/abiWords.d.ts +17 -0
- package/dist/lib/analysis/abiWords.d.ts.map +1 -0
- package/dist/lib/analysis/abiWords.js +48 -0
- package/dist/lib/analysis/abiWords.js.map +1 -0
- package/dist/lib/analysis/approval.d.ts +29 -0
- package/dist/lib/analysis/approval.d.ts.map +1 -0
- package/dist/lib/analysis/approval.js +189 -0
- package/dist/lib/analysis/approval.js.map +1 -0
- package/dist/lib/analysis/calldata.d.ts +60 -0
- package/dist/lib/analysis/calldata.d.ts.map +1 -0
- package/dist/lib/analysis/calldata.js +464 -0
- package/dist/lib/analysis/calldata.js.map +1 -0
- package/dist/lib/analysis/contractIntel.d.ts +65 -0
- package/dist/lib/analysis/contractIntel.d.ts.map +1 -0
- package/dist/lib/analysis/contractIntel.js +320 -0
- package/dist/lib/analysis/contractIntel.js.map +1 -0
- package/dist/lib/analysis/evm.d.ts +42 -0
- package/dist/lib/analysis/evm.d.ts.map +1 -0
- package/dist/lib/analysis/evm.js +185 -0
- package/dist/lib/analysis/evm.js.map +1 -0
- package/dist/lib/analysis/gas.d.ts +4 -0
- package/dist/lib/analysis/gas.d.ts.map +1 -0
- package/dist/lib/analysis/gas.js +13 -0
- package/dist/lib/analysis/gas.js.map +1 -0
- package/dist/lib/analysis/index.d.ts +11 -0
- package/dist/lib/analysis/index.d.ts.map +1 -0
- package/dist/lib/analysis/index.js +16 -0
- package/dist/lib/analysis/index.js.map +1 -0
- package/dist/lib/analysis/pharosTokens.d.ts +31 -0
- package/dist/lib/analysis/pharosTokens.d.ts.map +1 -0
- package/dist/lib/analysis/pharosTokens.js +78 -0
- package/dist/lib/analysis/pharosTokens.js.map +1 -0
- package/dist/lib/analysis/safeTx.d.ts +27 -0
- package/dist/lib/analysis/safeTx.d.ts.map +1 -0
- package/dist/lib/analysis/safeTx.js +118 -0
- package/dist/lib/analysis/safeTx.js.map +1 -0
- package/dist/lib/analysis/token.d.ts +21 -0
- package/dist/lib/analysis/token.d.ts.map +1 -0
- package/dist/lib/analysis/token.js +151 -0
- package/dist/lib/analysis/token.js.map +1 -0
- package/dist/lib/analysis/types.d.ts +49 -0
- package/dist/lib/analysis/types.d.ts.map +1 -0
- package/dist/lib/analysis/types.js +10 -0
- package/dist/lib/analysis/types.js.map +1 -0
- package/dist/lib/analysis/x402.d.ts +24 -0
- package/dist/lib/analysis/x402.d.ts.map +1 -0
- package/dist/lib/analysis/x402.js +60 -0
- package/dist/lib/analysis/x402.js.map +1 -0
- package/dist/lib/auditLog.d.ts +1 -0
- package/dist/lib/auditLog.d.ts.map +1 -1
- package/dist/lib/auditLog.js +0 -0
- package/dist/lib/auditLog.js.map +1 -1
- package/dist/lib/config.d.ts +77 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +120 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +246 -97
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +334 -127
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/dodoApi.d.ts +26 -3
- package/dist/lib/dodoApi.d.ts.map +1 -1
- package/dist/lib/dodoApi.js +80 -17
- package/dist/lib/dodoApi.js.map +1 -1
- package/dist/lib/ecosystemRegistry.d.ts +126 -0
- package/dist/lib/ecosystemRegistry.d.ts.map +1 -0
- package/dist/lib/ecosystemRegistry.js +178 -0
- package/dist/lib/ecosystemRegistry.js.map +1 -0
- package/dist/lib/envLoader.d.ts +0 -0
- package/dist/lib/envLoader.d.ts.map +0 -0
- package/dist/lib/envLoader.js +39 -18
- package/dist/lib/envLoader.js.map +1 -1
- package/dist/lib/goldsky.d.ts +58 -0
- package/dist/lib/goldsky.d.ts.map +1 -0
- package/dist/lib/goldsky.js +275 -0
- package/dist/lib/goldsky.js.map +1 -0
- package/dist/lib/guardian/decision.d.ts +23 -0
- package/dist/lib/guardian/decision.d.ts.map +1 -0
- package/dist/lib/guardian/decision.js +40 -0
- package/dist/lib/guardian/decision.js.map +1 -0
- package/dist/lib/http.d.ts +0 -1
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js +297 -32
- package/dist/lib/http.js.map +1 -1
- package/dist/lib/managedExecution.d.ts +19 -0
- package/dist/lib/managedExecution.d.ts.map +1 -0
- package/dist/lib/managedExecution.js +64 -0
- package/dist/lib/managedExecution.js.map +1 -0
- package/dist/lib/merkleBatcher.d.ts +23 -0
- package/dist/lib/merkleBatcher.d.ts.map +1 -0
- package/dist/lib/merkleBatcher.js +62 -0
- package/dist/lib/merkleBatcher.js.map +1 -0
- package/dist/lib/networks.d.ts +48 -0
- package/dist/lib/networks.d.ts.map +1 -0
- package/dist/lib/networks.js +103 -0
- package/dist/lib/networks.js.map +1 -0
- package/dist/lib/observability/accessContext.d.ts +29 -0
- package/dist/lib/observability/accessContext.d.ts.map +1 -0
- package/dist/lib/observability/accessContext.js +50 -0
- package/dist/lib/observability/accessContext.js.map +1 -0
- package/dist/lib/observability/activityStore.d.ts +70 -0
- package/dist/lib/observability/activityStore.d.ts.map +1 -0
- package/dist/lib/observability/activityStore.js +149 -0
- package/dist/lib/observability/activityStore.js.map +1 -0
- package/dist/lib/observability/apiKey.d.ts +55 -0
- package/dist/lib/observability/apiKey.d.ts.map +1 -0
- package/dist/lib/observability/apiKey.js +141 -0
- package/dist/lib/observability/apiKey.js.map +1 -0
- package/dist/lib/observability/logger.d.ts +30 -0
- package/dist/lib/observability/logger.d.ts.map +1 -0
- package/dist/lib/observability/logger.js +30 -0
- package/dist/lib/observability/logger.js.map +1 -0
- package/dist/lib/observability/quota.d.ts +33 -0
- package/dist/lib/observability/quota.d.ts.map +1 -0
- package/dist/lib/observability/quota.js +49 -0
- package/dist/lib/observability/quota.js.map +1 -0
- package/dist/lib/observability/requestId.d.ts +8 -0
- package/dist/lib/observability/requestId.d.ts.map +1 -0
- package/dist/lib/observability/requestId.js +24 -0
- package/dist/lib/observability/requestId.js.map +1 -0
- package/dist/lib/observability/sanitize.d.ts +77 -0
- package/dist/lib/observability/sanitize.d.ts.map +1 -0
- package/dist/lib/observability/sanitize.js +228 -0
- package/dist/lib/observability/sanitize.js.map +1 -0
- package/dist/lib/observability/scopes.d.ts +20 -0
- package/dist/lib/observability/scopes.d.ts.map +1 -0
- package/dist/lib/observability/scopes.js +77 -0
- package/dist/lib/observability/scopes.js.map +1 -0
- package/dist/lib/okxDexApi.d.ts +106 -0
- package/dist/lib/okxDexApi.d.ts.map +1 -0
- package/dist/lib/okxDexApi.js +221 -0
- package/dist/lib/okxDexApi.js.map +1 -0
- package/dist/lib/persistentJsonStore.d.ts +5 -0
- package/dist/lib/persistentJsonStore.d.ts.map +1 -0
- package/dist/lib/persistentJsonStore.js +39 -0
- package/dist/lib/persistentJsonStore.js.map +1 -0
- package/dist/lib/pharos/attestationPublisher.d.ts +50 -0
- package/dist/lib/pharos/attestationPublisher.d.ts.map +1 -0
- package/dist/lib/pharos/attestationPublisher.js +262 -0
- package/dist/lib/pharos/attestationPublisher.js.map +1 -0
- package/dist/lib/pharos/ecosystem.d.ts +52 -0
- package/dist/lib/pharos/ecosystem.d.ts.map +1 -0
- package/dist/lib/pharos/ecosystem.js +431 -0
- package/dist/lib/pharos/ecosystem.js.map +1 -0
- package/dist/lib/pharos/ecosystemEvidence.d.ts +53 -0
- package/dist/lib/pharos/ecosystemEvidence.d.ts.map +1 -0
- package/dist/lib/pharos/ecosystemEvidence.js +133 -0
- package/dist/lib/pharos/ecosystemEvidence.js.map +1 -0
- package/dist/lib/pharos/rpc.d.ts +44 -0
- package/dist/lib/pharos/rpc.d.ts.map +1 -0
- package/dist/lib/pharos/rpc.js +90 -0
- package/dist/lib/pharos/rpc.js.map +1 -0
- package/dist/lib/pharos/rpcEvidence.d.ts +49 -0
- package/dist/lib/pharos/rpcEvidence.d.ts.map +1 -0
- package/dist/lib/pharos/rpcEvidence.js +46 -0
- package/dist/lib/pharos/rpcEvidence.js.map +1 -0
- package/dist/lib/pharos/rpcMethods.d.ts +46 -0
- package/dist/lib/pharos/rpcMethods.d.ts.map +1 -0
- package/dist/lib/pharos/rpcMethods.js +176 -0
- package/dist/lib/pharos/rpcMethods.js.map +1 -0
- package/dist/lib/pharos/spvVerifier.d.ts +47 -0
- package/dist/lib/pharos/spvVerifier.d.ts.map +1 -0
- package/dist/lib/pharos/spvVerifier.js +105 -0
- package/dist/lib/pharos/spvVerifier.js.map +1 -0
- package/dist/lib/pharos/userSignedBroadcaster.d.ts +10 -0
- package/dist/lib/pharos/userSignedBroadcaster.d.ts.map +1 -0
- package/dist/lib/pharos/userSignedBroadcaster.js +50 -0
- package/dist/lib/pharos/userSignedBroadcaster.js.map +1 -0
- package/dist/lib/pharosClient.d.ts +5 -10
- package/dist/lib/pharosClient.d.ts.map +1 -1
- package/dist/lib/pharosClient.js +9 -16
- package/dist/lib/pharosClient.js.map +1 -1
- package/dist/lib/policy/actionPolicyEngine.d.ts +37 -1
- package/dist/lib/policy/actionPolicyEngine.d.ts.map +1 -1
- package/dist/lib/policy/actionPolicyEngine.js +213 -52
- package/dist/lib/policy/actionPolicyEngine.js.map +1 -1
- package/dist/lib/policy/agentPolicy.d.ts +29 -0
- package/dist/lib/policy/agentPolicy.d.ts.map +1 -0
- package/dist/lib/policy/agentPolicy.js +154 -0
- package/dist/lib/policy/agentPolicy.js.map +1 -0
- package/dist/lib/policy/policyPresets.d.ts +30 -0
- package/dist/lib/policy/policyPresets.d.ts.map +1 -0
- package/dist/lib/policy/policyPresets.js +124 -0
- package/dist/lib/policy/policyPresets.js.map +1 -0
- package/dist/lib/policy/writeExecutionGate.d.ts +23 -0
- package/dist/lib/policy/writeExecutionGate.d.ts.map +1 -0
- package/dist/lib/policy/writeExecutionGate.js +65 -0
- package/dist/lib/policy/writeExecutionGate.js.map +1 -0
- package/dist/lib/preparedTxStore.d.ts +21 -0
- package/dist/lib/preparedTxStore.d.ts.map +1 -0
- package/dist/lib/preparedTxStore.js +90 -0
- package/dist/lib/preparedTxStore.js.map +1 -0
- package/dist/lib/price/chainlinkPushProvider.d.ts +34 -0
- package/dist/lib/price/chainlinkPushProvider.d.ts.map +1 -0
- package/dist/lib/price/chainlinkPushProvider.js +36 -0
- package/dist/lib/price/chainlinkPushProvider.js.map +1 -0
- package/dist/lib/price/feedRegistry.d.ts +26 -0
- package/dist/lib/price/feedRegistry.d.ts.map +1 -0
- package/dist/lib/price/feedRegistry.js +67 -0
- package/dist/lib/price/feedRegistry.js.map +1 -0
- package/dist/lib/price/priceResolver.d.ts +35 -0
- package/dist/lib/price/priceResolver.d.ts.map +1 -0
- package/dist/lib/price/priceResolver.js +246 -0
- package/dist/lib/price/priceResolver.js.map +1 -0
- package/dist/lib/price/supraProvider.d.ts +9 -0
- package/dist/lib/price/supraProvider.d.ts.map +1 -0
- package/dist/lib/price/supraProvider.js +17 -0
- package/dist/lib/price/supraProvider.js.map +1 -0
- package/dist/lib/price/types.d.ts +67 -0
- package/dist/lib/price/types.d.ts.map +1 -0
- package/dist/lib/price/types.js +7 -0
- package/dist/lib/price/types.js.map +1 -0
- package/dist/lib/productionGuards.d.ts +16 -0
- package/dist/lib/productionGuards.d.ts.map +1 -0
- package/dist/lib/productionGuards.js +93 -0
- package/dist/lib/productionGuards.js.map +1 -0
- package/dist/lib/recipientSafety.d.ts +5 -0
- package/dist/lib/recipientSafety.d.ts.map +1 -0
- package/dist/lib/recipientSafety.js +28 -0
- package/dist/lib/recipientSafety.js.map +1 -0
- package/dist/lib/riskEngine.d.ts +19 -0
- package/dist/lib/riskEngine.d.ts.map +1 -1
- package/dist/lib/riskEngine.js +107 -38
- package/dist/lib/riskEngine.js.map +1 -1
- package/dist/lib/riskInclusion.d.ts +72 -0
- package/dist/lib/riskInclusion.d.ts.map +1 -0
- package/dist/lib/riskInclusion.js +252 -0
- package/dist/lib/riskInclusion.js.map +1 -0
- package/dist/lib/safeHandsRegistry.d.ts +32 -0
- package/dist/lib/safeHandsRegistry.d.ts.map +1 -0
- package/dist/lib/safeHandsRegistry.js +151 -0
- package/dist/lib/safeHandsRegistry.js.map +1 -0
- package/dist/lib/signer/index.d.ts +3 -3
- package/dist/lib/signer/index.d.ts.map +1 -1
- package/dist/lib/signer/index.js +33 -11
- package/dist/lib/signer/index.js.map +1 -1
- package/dist/lib/spendAccumulator.d.ts +24 -1
- package/dist/lib/spendAccumulator.d.ts.map +1 -1
- package/dist/lib/spendAccumulator.js +76 -6
- package/dist/lib/spendAccumulator.js.map +1 -1
- package/dist/lib/toolResponse.d.ts +6 -1
- package/dist/lib/toolResponse.d.ts.map +1 -1
- package/dist/lib/toolResponse.js +13 -9
- package/dist/lib/toolResponse.js.map +1 -1
- package/dist/lib/validation.d.ts +7 -0
- package/dist/lib/validation.d.ts.map +1 -0
- package/dist/lib/validation.js +62 -0
- package/dist/lib/validation.js.map +1 -0
- package/dist/lib/wallet/index.d.ts +8 -12
- package/dist/lib/wallet/index.d.ts.map +1 -1
- package/dist/lib/wallet/index.js +48 -35
- package/dist/lib/wallet/index.js.map +1 -1
- package/dist/lib/x402ReplayStore.d.ts +6 -0
- package/dist/lib/x402ReplayStore.d.ts.map +1 -0
- package/dist/lib/x402ReplayStore.js +79 -0
- package/dist/lib/x402ReplayStore.js.map +1 -0
- package/dist/safehands.zip +0 -0
- package/dist/sdk.d.ts +14 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +25 -0
- package/dist/sdk.js.map +1 -0
- package/dist/tools/approveToken.d.ts +31 -10
- package/dist/tools/approveToken.d.ts.map +1 -1
- package/dist/tools/approveToken.js +91 -24
- package/dist/tools/approveToken.js.map +1 -1
- package/dist/tools/assessRisk.d.ts +13 -26
- package/dist/tools/assessRisk.d.ts.map +1 -1
- package/dist/tools/assessRisk.js +34 -75
- package/dist/tools/assessRisk.js.map +1 -1
- package/dist/tools/checkAllowance.d.ts +9 -3
- package/dist/tools/checkAllowance.d.ts.map +1 -1
- package/dist/tools/checkAllowance.js +27 -5
- package/dist/tools/checkAllowance.js.map +1 -1
- package/dist/tools/checkTokenSecurity.d.ts +62 -5
- package/dist/tools/checkTokenSecurity.d.ts.map +1 -1
- package/dist/tools/checkTokenSecurity.js +166 -21
- package/dist/tools/checkTokenSecurity.js.map +1 -1
- package/dist/tools/createAgentWallet.d.ts +4 -2
- package/dist/tools/createAgentWallet.d.ts.map +1 -1
- package/dist/tools/createAgentWallet.js +36 -31
- package/dist/tools/createAgentWallet.js.map +1 -1
- package/dist/tools/estimateGas.d.ts +7 -2
- package/dist/tools/estimateGas.d.ts.map +1 -1
- package/dist/tools/estimateGas.js +16 -10
- package/dist/tools/estimateGas.js.map +1 -1
- package/dist/tools/executeSwap.d.ts +56 -8
- package/dist/tools/executeSwap.d.ts.map +1 -1
- package/dist/tools/executeSwap.js +194 -46
- package/dist/tools/executeSwap.js.map +1 -1
- package/dist/tools/explainRisk.d.ts +9 -9
- package/dist/tools/explainRisk.d.ts.map +1 -1
- package/dist/tools/explainRisk.js +5 -4
- package/dist/tools/explainRisk.js.map +1 -1
- package/dist/tools/getAgentPolicy.d.ts +15 -0
- package/dist/tools/getAgentPolicy.d.ts.map +1 -0
- package/dist/tools/getAgentPolicy.js +16 -0
- package/dist/tools/getAgentPolicy.js.map +1 -0
- package/dist/tools/getAgentReputation.d.ts +31 -0
- package/dist/tools/getAgentReputation.d.ts.map +1 -0
- package/dist/tools/getAgentReputation.js +44 -0
- package/dist/tools/getAgentReputation.js.map +1 -0
- package/dist/tools/getAgentWallet.d.ts +1 -1
- package/dist/tools/getAgentWallet.d.ts.map +1 -1
- package/dist/tools/getAgentWallet.js +11 -1
- package/dist/tools/getAgentWallet.js.map +1 -1
- package/dist/tools/getAgentWalletBalance.d.ts +1 -1
- package/dist/tools/getAgentWalletBalance.d.ts.map +1 -1
- package/dist/tools/getAgentWalletBalance.js +58 -26
- package/dist/tools/getAgentWalletBalance.js.map +1 -1
- package/dist/tools/getExecutionHistory.d.ts +1 -1
- package/dist/tools/getExecutionHistory.d.ts.map +1 -1
- package/dist/tools/getExecutionHistory.js +13 -19
- package/dist/tools/getExecutionHistory.js.map +1 -1
- package/dist/tools/getGasPrice.d.ts +3 -3
- package/dist/tools/getGasPrice.d.ts.map +0 -0
- package/dist/tools/getGasPrice.js +7 -7
- package/dist/tools/getGasPrice.js.map +1 -1
- package/dist/tools/getPoolInfo.d.ts +17 -17
- package/dist/tools/getPoolInfo.d.ts.map +1 -1
- package/dist/tools/getPoolInfo.js +14 -9
- package/dist/tools/getPoolInfo.js.map +1 -1
- package/dist/tools/getSpvProof.d.ts +24 -0
- package/dist/tools/getSpvProof.d.ts.map +1 -0
- package/dist/tools/getSpvProof.js +64 -0
- package/dist/tools/getSpvProof.js.map +1 -0
- package/dist/tools/getTokenPrice.d.ts +28 -85
- package/dist/tools/getTokenPrice.d.ts.map +1 -1
- package/dist/tools/getTokenPrice.js +87 -94
- package/dist/tools/getTokenPrice.js.map +1 -1
- package/dist/tools/getTransactionStatus.d.ts +2 -2
- package/dist/tools/getTransactionStatus.d.ts.map +0 -0
- package/dist/tools/getTransactionStatus.js +0 -0
- package/dist/tools/getTransactionStatus.js.map +0 -0
- package/dist/tools/getWalletBalance.d.ts +38 -3
- package/dist/tools/getWalletBalance.d.ts.map +1 -1
- package/dist/tools/getWalletBalance.js +92 -52
- package/dist/tools/getWalletBalance.js.map +1 -1
- package/dist/tools/publishRiskScore.d.ts +36 -14
- package/dist/tools/publishRiskScore.d.ts.map +1 -1
- package/dist/tools/publishRiskScore.js +80 -32
- package/dist/tools/publishRiskScore.js.map +1 -1
- package/dist/tools/queryGoldsky.d.ts +20 -0
- package/dist/tools/queryGoldsky.d.ts.map +1 -0
- package/dist/tools/queryGoldsky.js +29 -0
- package/dist/tools/queryGoldsky.js.map +1 -0
- package/dist/tools/queryRiskRegistry.d.ts +14 -14
- package/dist/tools/queryRiskRegistry.d.ts.map +1 -1
- package/dist/tools/queryRiskRegistry.js +34 -30
- package/dist/tools/queryRiskRegistry.js.map +1 -1
- package/dist/tools/safehandsPreflightCheck.d.ts +29 -14
- package/dist/tools/safehandsPreflightCheck.d.ts.map +1 -1
- package/dist/tools/safehandsPreflightCheck.js +133 -6
- package/dist/tools/safehandsPreflightCheck.js.map +1 -1
- package/dist/tools/safehandsRiskReport.d.ts +29 -14
- package/dist/tools/safehandsRiskReport.d.ts.map +1 -1
- package/dist/tools/safehandsRiskReport.js +23 -3
- package/dist/tools/safehandsRiskReport.js.map +1 -1
- package/dist/tools/safehandsSafeExecute.d.ts +1 -1
- package/dist/tools/safehandsSafeExecute.d.ts.map +1 -1
- package/dist/tools/safehandsSafeExecute.js +100 -17
- package/dist/tools/safehandsSafeExecute.js.map +1 -1
- package/dist/tools/safehandsWalletHealth.d.ts +15 -1
- package/dist/tools/safehandsWalletHealth.d.ts.map +1 -1
- package/dist/tools/safehandsWalletHealth.js +67 -25
- package/dist/tools/safehandsWalletHealth.js.map +1 -1
- package/dist/tools/safehandsX402Preflight.d.ts +3 -3
- package/dist/tools/safehandsX402Preflight.d.ts.map +1 -1
- package/dist/tools/safehandsX402Preflight.js +24 -3
- package/dist/tools/safehandsX402Preflight.js.map +1 -1
- package/dist/tools/sendPayment.d.ts +10 -4
- package/dist/tools/sendPayment.d.ts.map +1 -1
- package/dist/tools/sendPayment.js +63 -36
- package/dist/tools/sendPayment.js.map +1 -1
- package/dist/tools/setAgentPolicy.d.ts +75 -0
- package/dist/tools/setAgentPolicy.d.ts.map +1 -0
- package/dist/tools/setAgentPolicy.js +80 -0
- package/dist/tools/setAgentPolicy.js.map +1 -0
- package/dist/tools/simulateTransaction.d.ts +7 -3
- package/dist/tools/simulateTransaction.d.ts.map +1 -1
- package/dist/tools/simulateTransaction.js +42 -9
- package/dist/tools/simulateTransaction.js.map +1 -1
- package/dist/tools/tokenRegistryStatus.d.ts +25 -5
- package/dist/tools/tokenRegistryStatus.d.ts.map +1 -1
- package/dist/tools/tokenRegistryStatus.js +61 -31
- package/dist/tools/tokenRegistryStatus.js.map +1 -1
- package/dist/tools/verifyRiskInclusion.d.ts +59 -0
- package/dist/tools/verifyRiskInclusion.d.ts.map +1 -0
- package/dist/tools/verifyRiskInclusion.js +40 -0
- package/dist/tools/verifyRiskInclusion.js.map +1 -0
- package/dist/tools/x402PayAndFetch.d.ts +15 -9
- package/dist/tools/x402PayAndFetch.d.ts.map +1 -1
- package/dist/tools/x402PayAndFetch.js +163 -20
- package/dist/tools/x402PayAndFetch.js.map +1 -1
- package/dist/worker.d.ts +3 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +39 -0
- package/dist/worker.js.map +1 -0
- package/dist/x402Server.d.ts +1 -1
- package/dist/x402Server.d.ts.map +1 -1
- package/dist/x402Server.js +144 -35
- package/dist/x402Server.js.map +1 -1
- package/docs/REVIEWER_QUICKSTART.md +113 -0
- package/docs/SAFEHANDS_REVIEWER_DEMO_SCRIPT.md +228 -0
- package/package.json +131 -73
- package/contracts/RiskRegistry.json +0 -223
- package/contracts/RiskRegistry.sol +0 -58
- package/dist/lib/testDodoLive.d.ts +0 -2
- package/dist/lib/testDodoLive.d.ts.map +0 -1
- package/dist/lib/testDodoLive.js +0 -105
- package/dist/lib/testDodoLive.js.map +0 -1
- package/dist/lib/testLiveSafehands.d.ts +0 -2
- package/dist/lib/testLiveSafehands.d.ts.map +0 -1
- package/dist/lib/testLiveSafehands.js +0 -93
- package/dist/lib/testLiveSafehands.js.map +0 -1
- package/dist/lib/testRpc.d.ts +0 -2
- package/dist/lib/testRpc.d.ts.map +0 -1
- package/dist/lib/testRpc.js +0 -30
- package/dist/lib/testRpc.js.map +0 -1
- package/dist/lib/testRpcLive.d.ts +0 -2
- package/dist/lib/testRpcLive.d.ts.map +0 -1
- package/dist/lib/testRpcLive.js +0 -89
- package/dist/lib/testRpcLive.js.map +0 -1
- package/dist/lib/testTools.d.ts +0 -2
- package/dist/lib/testTools.d.ts.map +0 -1
- package/dist/lib/testTools.js +0 -397
- package/dist/lib/testTools.js.map +0 -1
- package/dist/lib/testX402Live.d.ts +0 -2
- package/dist/lib/testX402Live.d.ts.map +0 -1
- package/dist/lib/testX402Live.js +0 -160
- package/dist/lib/testX402Live.js.map +0 -1
- package/dist/scripts/checkDeploy.d.ts +0 -2
- package/dist/scripts/checkDeploy.d.ts.map +0 -1
- package/dist/scripts/checkDeploy.js +0 -25
- package/dist/scripts/checkDeploy.js.map +0 -1
- package/dist/scripts/deployRegistry.d.ts +0 -2
- package/dist/scripts/deployRegistry.d.ts.map +0 -1
- package/dist/scripts/deployRegistry.js +0 -101
- package/dist/scripts/deployRegistry.js.map +0 -1
- package/dist/scripts/testRegistry.d.ts +0 -2
- package/dist/scripts/testRegistry.d.ts.map +0 -1
- package/dist/scripts/testRegistry.js +0 -44
- package/dist/scripts/testRegistry.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/analysis/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAC9E,2EAA2E;AAE3E,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type NetworkName, type PharosNetwork } from "../networks.js";
|
|
2
|
+
import type { EvidenceSource, EvidenceStatus } from "./types.js";
|
|
3
|
+
export interface TokenRegistryEvidence {
|
|
4
|
+
symbol: string | null;
|
|
5
|
+
name: string | null;
|
|
6
|
+
network: NetworkName;
|
|
7
|
+
chainId: number;
|
|
8
|
+
address: string | null;
|
|
9
|
+
decimals: number | null;
|
|
10
|
+
source: EvidenceSource;
|
|
11
|
+
status: EvidenceStatus;
|
|
12
|
+
riskRelevance: string;
|
|
13
|
+
}
|
|
14
|
+
interface ResolvedToken {
|
|
15
|
+
symbol: string;
|
|
16
|
+
name: string | null;
|
|
17
|
+
address: string;
|
|
18
|
+
decimals: number | null;
|
|
19
|
+
source: EvidenceSource;
|
|
20
|
+
}
|
|
21
|
+
/** Resolve a token (symbol or address) within a network's official registry. */
|
|
22
|
+
export declare function lookupPharosToken(input: string, network: NetworkName): ResolvedToken | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Build read-only token-registry evidence for a token on a network.
|
|
25
|
+
* - recognized official token → status `implemented`
|
|
26
|
+
* - valid but unknown address → status `to_verify` (never silently trusted)
|
|
27
|
+
* - invalid / unknown symbol → `null`
|
|
28
|
+
*/
|
|
29
|
+
export declare function tokenRegistryEvidence(input: string, network?: PharosNetwork): TokenRegistryEvidence | null;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=pharosTokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pharosTokens.d.ts","sourceRoot":"","sources":["../../../src/lib/analysis/pharosTokens.ts"],"names":[],"mappings":"AAUA,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAExF,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAKD,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,CA2BhG;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkC,GAAG,qBAAqB,GAAG,IAAI,CA8B9H"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// ─── Network-aware Pharos Token Registry (read-only) ───────────────────
|
|
2
|
+
// Single source of truth for token-registry *evidence*. Pacific Mainnet uses the
|
|
3
|
+
// official Pharos token list (constants.PACIFIC_MAINNET_TOKEN_REGISTRY); Atlantic
|
|
4
|
+
// Testnet delegates to the existing testnet classifier (unchanged). Recognition is
|
|
5
|
+
// by registry address only — it is NOT a safety guarantee for an action. Pure: no
|
|
6
|
+
// RPC, no keys, no writes.
|
|
7
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
8
|
+
import { getAddress, isAddress } from "viem";
|
|
9
|
+
import { PACIFIC_MAINNET_TOKEN_REGISTRY } from "../constants.js";
|
|
10
|
+
import { getActiveNetwork } from "../networks.js";
|
|
11
|
+
import { classifyTokenRegistryStatus } from "../../tools/tokenRegistryStatus.js";
|
|
12
|
+
const RISK_RELEVANCE = "Recognized via the network token registry by address; recognition is metadata, not a safety guarantee; a known token does not make a risky action safe.";
|
|
13
|
+
/** Resolve a token (symbol or address) within a network's official registry. */
|
|
14
|
+
export function lookupPharosToken(input, network) {
|
|
15
|
+
const raw = (input ?? "").trim();
|
|
16
|
+
if (!raw)
|
|
17
|
+
return undefined;
|
|
18
|
+
if (network === "pacific-mainnet") {
|
|
19
|
+
const upper = raw.toUpperCase();
|
|
20
|
+
const entries = Object.values(PACIFIC_MAINNET_TOKEN_REGISTRY);
|
|
21
|
+
const bySymbol = entries.find((t) => t.symbol === upper);
|
|
22
|
+
if (bySymbol) {
|
|
23
|
+
return { symbol: bySymbol.symbol, name: bySymbol.name, address: bySymbol.address, decimals: bySymbol.decimals, source: "official_docs" };
|
|
24
|
+
}
|
|
25
|
+
if (isAddress(raw)) {
|
|
26
|
+
const lower = raw.toLowerCase();
|
|
27
|
+
const byAddr = entries.find((t) => t.address.toLowerCase() === lower);
|
|
28
|
+
if (byAddr) {
|
|
29
|
+
return { symbol: byAddr.symbol, name: byAddr.name, address: byAddr.address, decimals: byAddr.decimals, source: "official_docs" };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
// Atlantic Testnet — delegate to the existing classifier (behavior preserved).
|
|
35
|
+
const cls = classifyTokenRegistryStatus(raw);
|
|
36
|
+
if (cls.symbol && cls.normalizedAddress && (cls.status === "CANONICAL_MAINNET_TOKEN" || cls.status === "SKILL_ENGINE_CANONICAL_TOKEN")) {
|
|
37
|
+
return { symbol: cls.symbol, name: null, address: cls.normalizedAddress, decimals: null, source: "existing_registry" };
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Build read-only token-registry evidence for a token on a network.
|
|
43
|
+
* - recognized official token → status `implemented`
|
|
44
|
+
* - valid but unknown address → status `to_verify` (never silently trusted)
|
|
45
|
+
* - invalid / unknown symbol → `null`
|
|
46
|
+
*/
|
|
47
|
+
export function tokenRegistryEvidence(input, network = getActiveNetwork()) {
|
|
48
|
+
const raw = (input ?? "").trim();
|
|
49
|
+
const tok = lookupPharosToken(raw, network.name);
|
|
50
|
+
if (tok) {
|
|
51
|
+
return {
|
|
52
|
+
symbol: tok.symbol,
|
|
53
|
+
name: tok.name,
|
|
54
|
+
network: network.name,
|
|
55
|
+
chainId: network.chainId,
|
|
56
|
+
address: tok.address,
|
|
57
|
+
decimals: tok.decimals,
|
|
58
|
+
source: tok.source,
|
|
59
|
+
status: "implemented",
|
|
60
|
+
riskRelevance: RISK_RELEVANCE,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (isAddress(raw)) {
|
|
64
|
+
return {
|
|
65
|
+
symbol: null,
|
|
66
|
+
name: null,
|
|
67
|
+
network: network.name,
|
|
68
|
+
chainId: network.chainId,
|
|
69
|
+
address: getAddress(raw),
|
|
70
|
+
decimals: null,
|
|
71
|
+
source: "to_verify",
|
|
72
|
+
status: "to_verify",
|
|
73
|
+
riskRelevance: "Token is a valid address but not in the official network registry; treat as unverified/custom (TO_VERIFY).",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=pharosTokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pharosTokens.js","sourceRoot":"","sources":["../../../src/lib/analysis/pharosTokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type CanonicalContractEvidence } from "./contractIntel.js";
|
|
2
|
+
import { type AnalyzerResult } from "./types.js";
|
|
3
|
+
import type { GuardianDecision } from "../guardian/decision.js";
|
|
4
|
+
export declare const MULTISEND_SELECTOR = "0x8d80ff0a";
|
|
5
|
+
export declare const SAFE_EXEC_SELECTOR = "0x6a761202";
|
|
6
|
+
export interface SafeInnerCall {
|
|
7
|
+
index: number;
|
|
8
|
+
operation: number;
|
|
9
|
+
to: string;
|
|
10
|
+
value: string;
|
|
11
|
+
dataLength: number;
|
|
12
|
+
selector: string | null;
|
|
13
|
+
decision: GuardianDecision;
|
|
14
|
+
summary: string;
|
|
15
|
+
/** Per-network canonical recognition of this inner call's target (null when unknown). */
|
|
16
|
+
canonicalContractEvidence: CanonicalContractEvidence | null;
|
|
17
|
+
}
|
|
18
|
+
export interface SafeTxAnalysisDetails {
|
|
19
|
+
kind: "multisend" | "safe_exec" | "unknown";
|
|
20
|
+
selector: string | null;
|
|
21
|
+
innerCallCount: number | null;
|
|
22
|
+
innerCalls: SafeInnerCall[];
|
|
23
|
+
hasDelegateCall: boolean;
|
|
24
|
+
fullyDecoded: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function analyzeSafeTx(data: string): Promise<AnalyzerResult<SafeTxAnalysisDetails>>;
|
|
27
|
+
//# sourceMappingURL=safeTx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safeTx.d.ts","sourceRoot":"","sources":["../../../src/lib/analysis/safeTx.ts"],"names":[],"mappings":"AASA,OAAO,EAA6B,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/F,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAC/C,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAM/C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,yFAAyF;IACzF,yBAAyB,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC;IAC5C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;CACvB;AA+BD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC,CAiFhG"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// ─── Safe / MultiSend Analyzer (read-only, Experimental) ───────────────
|
|
2
|
+
// Recognizes Safe transactions and decodes MultiSend batches on a best-effort
|
|
3
|
+
// basis. The highest-risk inner call drives the aggregate decision. Deep decode
|
|
4
|
+
// is Experimental — partial/unparsable input is reported clearly. Never submits
|
|
5
|
+
// a Safe transaction and never co-signs.
|
|
6
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
7
|
+
import { bytesToBigInt, bytesToHex, decodeFunctionData, hexToBytes } from "viem";
|
|
8
|
+
import { analyzeApproval, APPROVE_SELECTOR } from "./approval.js";
|
|
9
|
+
import { canonicalContractEvidence } from "./contractIntel.js";
|
|
10
|
+
import { analyzeEvmCall } from "./evm.js";
|
|
11
|
+
import { makeResult } from "./types.js";
|
|
12
|
+
export const MULTISEND_SELECTOR = "0x8d80ff0a";
|
|
13
|
+
export const SAFE_EXEC_SELECTOR = "0x6a761202"; // execTransaction(...)
|
|
14
|
+
const MULTISEND_ABI = [
|
|
15
|
+
{ name: "multiSend", type: "function", stateMutability: "payable", inputs: [{ name: "transactions", type: "bytes" }], outputs: [] },
|
|
16
|
+
];
|
|
17
|
+
const SEVERITY = { ALLOW: 0, PREPARE_ONLY: 1, REQUIRE_CONFIRMATION: 2, BLOCK: 3 };
|
|
18
|
+
function worst(a, b) {
|
|
19
|
+
return SEVERITY[a] >= SEVERITY[b] ? a : b;
|
|
20
|
+
}
|
|
21
|
+
function decodeMultiSendBatch(transactions) {
|
|
22
|
+
const buf = hexToBytes(transactions);
|
|
23
|
+
const calls = [];
|
|
24
|
+
let i = 0;
|
|
25
|
+
while (i < buf.length) {
|
|
26
|
+
const operation = buf[i];
|
|
27
|
+
i += 1;
|
|
28
|
+
const to = bytesToHex(buf.slice(i, i + 20));
|
|
29
|
+
i += 20;
|
|
30
|
+
const value = bytesToBigInt(buf.slice(i, i + 32));
|
|
31
|
+
i += 32;
|
|
32
|
+
const dataLen = Number(bytesToBigInt(buf.slice(i, i + 32)));
|
|
33
|
+
i += 32;
|
|
34
|
+
const data = bytesToHex(buf.slice(i, i + dataLen));
|
|
35
|
+
i += dataLen;
|
|
36
|
+
calls.push({ index: calls.length, operation, to, value: value.toString(), dataLength: dataLen, data });
|
|
37
|
+
}
|
|
38
|
+
return calls;
|
|
39
|
+
}
|
|
40
|
+
export async function analyzeSafeTx(data) {
|
|
41
|
+
const reasons = [];
|
|
42
|
+
const warnings = ["Safe/MultiSend decoding is Experimental; verify the full batch independently before signing."];
|
|
43
|
+
const hex = (data?.startsWith("0x") ? data : `0x${data ?? ""}`).toLowerCase();
|
|
44
|
+
const selector = hex.length >= 10 ? hex.slice(0, 10) : null;
|
|
45
|
+
const partial = (kind, msg) => makeResult({
|
|
46
|
+
analyzer: "safe_tx",
|
|
47
|
+
decision: "REQUIRE_CONFIRMATION",
|
|
48
|
+
internalDecision: "REQUIRE_CONFIRMATION",
|
|
49
|
+
riskLevel: "UNKNOWN",
|
|
50
|
+
reasons: [msg],
|
|
51
|
+
warnings,
|
|
52
|
+
analyzerStatus: "partial",
|
|
53
|
+
experimental: true,
|
|
54
|
+
details: { kind, selector, innerCallCount: null, innerCalls: [], hasDelegateCall: false, fullyDecoded: false },
|
|
55
|
+
});
|
|
56
|
+
if (selector === SAFE_EXEC_SELECTOR) {
|
|
57
|
+
return partial("safe_exec", "Recognized a Safe execTransaction call; nested call decode is not performed (Experimental).");
|
|
58
|
+
}
|
|
59
|
+
if (selector !== MULTISEND_SELECTOR) {
|
|
60
|
+
return partial("unknown", `Not a recognized Safe/MultiSend selector (${selector ?? "n/a"}).`);
|
|
61
|
+
}
|
|
62
|
+
let transactions;
|
|
63
|
+
try {
|
|
64
|
+
const decoded = decodeFunctionData({ abi: MULTISEND_ABI, data: hex });
|
|
65
|
+
transactions = decoded.args[0];
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return partial("multisend", "MultiSend payload could not be ABI-decoded (Experimental, partial).");
|
|
69
|
+
}
|
|
70
|
+
let rawCalls;
|
|
71
|
+
try {
|
|
72
|
+
rawCalls = decodeMultiSendBatch(transactions);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return partial("multisend", "MultiSend batch bytes could not be parsed (Experimental, partial).");
|
|
76
|
+
}
|
|
77
|
+
let aggregate = "ALLOW";
|
|
78
|
+
let hasDelegateCall = false;
|
|
79
|
+
const innerCalls = [];
|
|
80
|
+
for (const c of rawCalls) {
|
|
81
|
+
const sel = c.data && c.data.length >= 10 ? c.data.slice(0, 10).toLowerCase() : null;
|
|
82
|
+
if (c.operation === 1)
|
|
83
|
+
hasDelegateCall = true;
|
|
84
|
+
let decision;
|
|
85
|
+
let summary;
|
|
86
|
+
if (sel === APPROVE_SELECTOR) {
|
|
87
|
+
const a = analyzeApproval(c.data, c.to);
|
|
88
|
+
decision = a.decision;
|
|
89
|
+
summary = a.reasons[0] ?? "approval";
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const e = await analyzeEvmCall({ to: c.to, data: c.data, value: c.value });
|
|
93
|
+
decision = e.decision;
|
|
94
|
+
summary = e.reasons[0] ?? e.details.callClass;
|
|
95
|
+
}
|
|
96
|
+
// A delegatecall in a batch is inherently higher-risk.
|
|
97
|
+
if (c.operation === 1)
|
|
98
|
+
decision = worst(decision, "REQUIRE_CONFIRMATION");
|
|
99
|
+
aggregate = worst(aggregate, decision);
|
|
100
|
+
innerCalls.push({ index: c.index, operation: c.operation, to: c.to, value: c.value, dataLength: c.dataLength, selector: sel, decision, summary, canonicalContractEvidence: canonicalContractEvidence(c.to) });
|
|
101
|
+
}
|
|
102
|
+
if (hasDelegateCall)
|
|
103
|
+
warnings.push("Batch contains a delegatecall (operation=1); elevated risk.");
|
|
104
|
+
reasons.push(`Decoded MultiSend batch with ${innerCalls.length} inner call(s); aggregate decision follows the highest-risk inner call.`);
|
|
105
|
+
const riskLevel = aggregate === "BLOCK" ? "CRITICAL" : aggregate === "REQUIRE_CONFIRMATION" ? "MEDIUM" : "LOW";
|
|
106
|
+
return makeResult({
|
|
107
|
+
analyzer: "safe_tx",
|
|
108
|
+
decision: aggregate,
|
|
109
|
+
internalDecision: aggregate,
|
|
110
|
+
riskLevel,
|
|
111
|
+
reasons,
|
|
112
|
+
warnings,
|
|
113
|
+
analyzerStatus: "ok",
|
|
114
|
+
experimental: true,
|
|
115
|
+
details: { kind: "multisend", selector, innerCallCount: innerCalls.length, innerCalls, hasDelegateCall, fullyDecoded: true },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=safeTx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safeTx.js","sourceRoot":"","sources":["../../../src/lib/analysis/safeTx.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type TokenRegistryStatusValue } from "../../tools/tokenRegistryStatus.js";
|
|
2
|
+
import { type NetworkName } from "../networks.js";
|
|
3
|
+
import { type TokenRegistryEvidence } from "./pharosTokens.js";
|
|
4
|
+
import { type AnalyzerResult } from "./types.js";
|
|
5
|
+
export interface TokenAnalysisDetails {
|
|
6
|
+
input: string;
|
|
7
|
+
resolvedFrom: "symbol" | "address" | "invalid";
|
|
8
|
+
normalizedAddress: string | null;
|
|
9
|
+
symbol: string | null;
|
|
10
|
+
status: TokenRegistryStatusValue;
|
|
11
|
+
verificationStatus: string;
|
|
12
|
+
/** Which network's registry produced this verdict. */
|
|
13
|
+
registryScope: NetworkName;
|
|
14
|
+
/** True — SafeHands now ships a Pacific Mainnet token registry (Phase 5B). */
|
|
15
|
+
mainnetRegistryImplemented: boolean;
|
|
16
|
+
/** Per-network token-registry evidence (null when not a valid token). */
|
|
17
|
+
tokenRegistryEvidence: TokenRegistryEvidence | null;
|
|
18
|
+
activeNetwork: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function analyzeToken(token: string): AnalyzerResult<TokenAnalysisDetails>;
|
|
21
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/lib/analysis/token.ts"],"names":[],"mappings":"AASA,OAAO,EAA+B,KAAK,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAChH,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAA4C,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACzG,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC/C,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,wBAAwB,CAAC;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,aAAa,EAAE,WAAW,CAAC;IAC3B,8EAA8E;IAC9E,0BAA0B,EAAE,OAAO,CAAC;IACpC,yEAAyE;IACzE,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACpD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAMhF"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// ─── Token Analyzer (read-only) ────────────────────────────────────────
|
|
2
|
+
// Maps a token (symbol or address) to a public SafeHands decision, PER-NETWORK.
|
|
3
|
+
// On Pacific Mainnet it uses the official Pharos token registry
|
|
4
|
+
// (constants.PACIFIC_MAINNET_TOKEN_REGISTRY, Phase 5A audit); on Atlantic Testnet
|
|
5
|
+
// it uses the existing testnet classifier (unchanged). Tokens are never trusted
|
|
6
|
+
// by symbol alone, and a known token NEVER makes a risky action safe.
|
|
7
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
8
|
+
import { getAddress, isAddress } from "viem";
|
|
9
|
+
import { classifyTokenRegistryStatus } from "../../tools/tokenRegistryStatus.js";
|
|
10
|
+
import { getActiveNetwork } from "../networks.js";
|
|
11
|
+
import { lookupPharosToken, tokenRegistryEvidence } from "./pharosTokens.js";
|
|
12
|
+
import { makeResult } from "./types.js";
|
|
13
|
+
export function analyzeToken(token) {
|
|
14
|
+
const raw = (token ?? "").trim();
|
|
15
|
+
const active = getActiveNetwork();
|
|
16
|
+
const evidence = tokenRegistryEvidence(raw, active);
|
|
17
|
+
return active.isMainnet ? analyzePacificToken(raw, active.name, evidence) : analyzeAtlanticToken(raw, active.name, evidence);
|
|
18
|
+
}
|
|
19
|
+
/** Pacific Mainnet: recognize against the official Pharos token registry. */
|
|
20
|
+
function analyzePacificToken(raw, registryScope, evidence) {
|
|
21
|
+
const reasons = [];
|
|
22
|
+
const warnings = [];
|
|
23
|
+
const tok = lookupPharosToken(raw, "pacific-mainnet");
|
|
24
|
+
let normalizedAddress;
|
|
25
|
+
let symbol;
|
|
26
|
+
let status;
|
|
27
|
+
let verificationStatus;
|
|
28
|
+
let resolvedFrom;
|
|
29
|
+
let internalDecision;
|
|
30
|
+
let riskLevel;
|
|
31
|
+
if (tok) {
|
|
32
|
+
normalizedAddress = getAddress(tok.address);
|
|
33
|
+
symbol = tok.symbol;
|
|
34
|
+
status = "CANONICAL_MAINNET_TOKEN";
|
|
35
|
+
verificationStatus = "DOCS_VERIFIED";
|
|
36
|
+
resolvedFrom = isAddress(raw) ? "address" : "symbol";
|
|
37
|
+
if (resolvedFrom === "address") {
|
|
38
|
+
// ALLOW requires an address match against the official registry — the caller
|
|
39
|
+
// named the exact canonical contract.
|
|
40
|
+
internalDecision = "ALLOW";
|
|
41
|
+
riskLevel = "LOW";
|
|
42
|
+
reasons.push(`Token is a canonical Pharos Pacific Mainnet token (${symbol}).`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Fail-closed (truth-model rule 1): a known NAME alone never produces ALLOW.
|
|
46
|
+
// The symbol resolves to the canonical registry address, but the caller did
|
|
47
|
+
// not identify a contract — confirm the resolved address before acting.
|
|
48
|
+
internalDecision = "REQUIRE_CONFIRMATION";
|
|
49
|
+
riskLevel = "MEDIUM";
|
|
50
|
+
reasons.push(`Symbol "${raw}" resolves to the canonical Pharos Pacific Mainnet token ${symbol} at ${normalizedAddress}, but a symbol alone is not an on-chain guarantee; confirm the resolved address before acting on it.`);
|
|
51
|
+
warnings.push(`Symbol "${raw}" was resolved to the official Pacific Mainnet registry address ${normalizedAddress}; a symbol alone is not an on-chain guarantee.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (isAddress(raw)) {
|
|
55
|
+
normalizedAddress = getAddress(raw);
|
|
56
|
+
symbol = null;
|
|
57
|
+
status = "CUSTOM_NON_REGISTRY";
|
|
58
|
+
verificationStatus = "UNVERIFIED_CUSTOM_TOKEN";
|
|
59
|
+
resolvedFrom = "address";
|
|
60
|
+
internalDecision = "REQUIRE_CONFIRMATION";
|
|
61
|
+
riskLevel = "MEDIUM";
|
|
62
|
+
reasons.push("Token is not in the Pacific Mainnet registry; unknown/custom token requires review.");
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
normalizedAddress = null;
|
|
66
|
+
symbol = null;
|
|
67
|
+
status = "INVALID_ADDRESS";
|
|
68
|
+
verificationStatus = "INVALID_ADDRESS";
|
|
69
|
+
resolvedFrom = "invalid";
|
|
70
|
+
internalDecision = "BLOCK";
|
|
71
|
+
riskLevel = "CRITICAL";
|
|
72
|
+
reasons.push("Token is not a valid EVM address or known Pacific Mainnet symbol.");
|
|
73
|
+
}
|
|
74
|
+
return makeResult({
|
|
75
|
+
analyzer: "token",
|
|
76
|
+
decision: internalDecision,
|
|
77
|
+
internalDecision,
|
|
78
|
+
riskLevel,
|
|
79
|
+
reasons,
|
|
80
|
+
warnings,
|
|
81
|
+
analyzerStatus: "ok",
|
|
82
|
+
details: { input: raw, resolvedFrom, normalizedAddress, symbol, status, verificationStatus, registryScope, mainnetRegistryImplemented: true, tokenRegistryEvidence: evidence, activeNetwork: registryScope },
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/** Atlantic Testnet: existing testnet classifier (behavior preserved). */
|
|
86
|
+
function analyzeAtlanticToken(raw, registryScope, evidence) {
|
|
87
|
+
const cls = classifyTokenRegistryStatus(raw);
|
|
88
|
+
const reasons = [];
|
|
89
|
+
const warnings = [];
|
|
90
|
+
const resolvedFrom = cls.status === "INVALID_ADDRESS" ? "invalid" : isAddress(raw) ? "address" : "symbol";
|
|
91
|
+
if (resolvedFrom === "symbol" && cls.normalizedAddress) {
|
|
92
|
+
warnings.push(`Symbol "${raw}" was resolved to the project's testnet registry address ${cls.normalizedAddress}; a symbol alone is not an on-chain guarantee.`);
|
|
93
|
+
}
|
|
94
|
+
let internalDecision;
|
|
95
|
+
let riskLevel;
|
|
96
|
+
switch (cls.status) {
|
|
97
|
+
case "INVALID_ADDRESS":
|
|
98
|
+
internalDecision = "BLOCK";
|
|
99
|
+
riskLevel = "CRITICAL";
|
|
100
|
+
reasons.push("Token is not a valid EVM address or known symbol.");
|
|
101
|
+
break;
|
|
102
|
+
case "SKILL_ENGINE_CANONICAL_TOKEN":
|
|
103
|
+
case "CANONICAL_MAINNET_TOKEN":
|
|
104
|
+
if (resolvedFrom === "symbol") {
|
|
105
|
+
// Fail-closed (truth-model rule 1): a known NAME alone never produces ALLOW.
|
|
106
|
+
internalDecision = "REQUIRE_CONFIRMATION";
|
|
107
|
+
riskLevel = "MEDIUM";
|
|
108
|
+
reasons.push(`Symbol "${raw}" resolves to the registry token ${cls.symbol ?? "?"} at ${cls.normalizedAddress ?? "?"}, but a symbol alone is not an on-chain guarantee; confirm the resolved address before acting on it.`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
internalDecision = "ALLOW";
|
|
112
|
+
riskLevel = "LOW";
|
|
113
|
+
reasons.push(`Token is a canonical Atlantic-mainnet token (${cls.symbol ?? "?"}).`);
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
case "ALTERNATE_SOURCE_TOKEN":
|
|
117
|
+
internalDecision = "REQUIRE_CONFIRMATION";
|
|
118
|
+
riskLevel = "MEDIUM";
|
|
119
|
+
reasons.push("Token is an alternate-source token (not the primary registry entry); confirm before use.");
|
|
120
|
+
break;
|
|
121
|
+
case "CUSTOM_NON_REGISTRY":
|
|
122
|
+
case "UNKNOWN":
|
|
123
|
+
default:
|
|
124
|
+
internalDecision = "REQUIRE_CONFIRMATION";
|
|
125
|
+
riskLevel = "MEDIUM";
|
|
126
|
+
reasons.push("Token is not in the SafeHands registry; unknown/custom token requires review.");
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
return makeResult({
|
|
130
|
+
analyzer: "token",
|
|
131
|
+
decision: internalDecision,
|
|
132
|
+
internalDecision,
|
|
133
|
+
riskLevel,
|
|
134
|
+
reasons,
|
|
135
|
+
warnings,
|
|
136
|
+
analyzerStatus: "ok",
|
|
137
|
+
details: {
|
|
138
|
+
input: raw,
|
|
139
|
+
resolvedFrom,
|
|
140
|
+
normalizedAddress: cls.normalizedAddress,
|
|
141
|
+
symbol: cls.symbol,
|
|
142
|
+
status: cls.status,
|
|
143
|
+
verificationStatus: cls.verificationStatus,
|
|
144
|
+
registryScope,
|
|
145
|
+
mainnetRegistryImplemented: true,
|
|
146
|
+
tokenRegistryEvidence: evidence,
|
|
147
|
+
activeNetwork: registryScope,
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/lib/analysis/token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { GuardianDecision } from "../guardian/decision.js";
|
|
2
|
+
export type AnalyzerRiskLevel = "LOW" | "MEDIUM" | "HIGH" | "CRITICAL" | "UNKNOWN";
|
|
3
|
+
/** ok = fully analyzed; partial = recognized but not fully decoded; unavailable = could not analyze. */
|
|
4
|
+
export type AnalyzerStatus = "ok" | "partial" | "unavailable";
|
|
5
|
+
/**
|
|
6
|
+
* Shared provenance/maturity labels for read-only recognition evidence
|
|
7
|
+
* (canonical contracts, token registry). Recognition is metadata — it is never a
|
|
8
|
+
* safety guarantee for an action.
|
|
9
|
+
* official_docs — taken from official Pharos docs (Phase 5A audit).
|
|
10
|
+
* existing_registry — from the project's existing testnet registry/config.
|
|
11
|
+
* to_verify — a valid target that is NOT in any official registry.
|
|
12
|
+
*/
|
|
13
|
+
export type EvidenceSource = "official_docs" | "existing_registry" | "to_verify";
|
|
14
|
+
/** implemented = backed by code + tests; experimental = partial; to_verify = unconfirmed. */
|
|
15
|
+
export type EvidenceStatus = "implemented" | "experimental" | "to_verify";
|
|
16
|
+
export interface AnalyzerResult<TDetails = Record<string, unknown>> {
|
|
17
|
+
analyzer: string;
|
|
18
|
+
/** Public four-value SafeHands decision. */
|
|
19
|
+
decision: GuardianDecision;
|
|
20
|
+
/** Internal engine-style label kept for explanation only. */
|
|
21
|
+
internalDecision?: string;
|
|
22
|
+
riskLevel: AnalyzerRiskLevel;
|
|
23
|
+
reasons: string[];
|
|
24
|
+
warnings: string[];
|
|
25
|
+
analyzerStatus: AnalyzerStatus;
|
|
26
|
+
/** True when the analyzer is a partial/demo decoder (e.g. deep Safe/Permit2 decode). */
|
|
27
|
+
experimental?: boolean;
|
|
28
|
+
/** Always true — analyzers never write. Lets callers/tests assert read-only. */
|
|
29
|
+
readOnly: true;
|
|
30
|
+
details: TDetails;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Optional read-only chain access. Pass concrete implementations from
|
|
34
|
+
* pharosClient in tool wiring; omit for offline/pure analysis and smoke tests.
|
|
35
|
+
* None of these may mutate chain state.
|
|
36
|
+
*/
|
|
37
|
+
export interface ReadOnlyChainAccess {
|
|
38
|
+
getCode?: (address: `0x${string}`) => Promise<string | undefined>;
|
|
39
|
+
estimateGas?: (args: {
|
|
40
|
+
to?: `0x${string}`;
|
|
41
|
+
data?: `0x${string}`;
|
|
42
|
+
value?: bigint;
|
|
43
|
+
account?: `0x${string}`;
|
|
44
|
+
}) => Promise<bigint>;
|
|
45
|
+
getGasPrice?: () => Promise<bigint>;
|
|
46
|
+
getTransactionReceipt?: (hash: `0x${string}`) => Promise<unknown>;
|
|
47
|
+
}
|
|
48
|
+
export declare function makeResult<T>(partial: Omit<AnalyzerResult<T>, "readOnly">): AnalyzerResult<T>;
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/analysis/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAEnF,wGAAwG;AACxG,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,mBAAmB,GAAG,WAAW,CAAC;AACjF,6FAA6F;AAC7F,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,cAAc,GAAG,WAAW,CAAC;AAE1E,MAAM,WAAW,cAAc,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,wFAAwF;IACxF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gFAAgF;IAChF,QAAQ,EAAE,IAAI,CAAC;IACf,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAClE,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,EAAE,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;KACzB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAE7F"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// ─── SafeHands Read-Only Analyzers — Shared Types ──────────────────────
|
|
2
|
+
// Every analyzer is READ-ONLY. No analyzer signs, sends, approves, swaps,
|
|
3
|
+
// publishes, or writes on-chain. Optional chain access is read-only (eth_getCode,
|
|
4
|
+
// eth_estimateGas, eth_getGasPrice, eth_getTransactionReceipt) and is omitted in
|
|
5
|
+
// offline/pure analysis and tests.
|
|
6
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
7
|
+
export function makeResult(partial) {
|
|
8
|
+
return { readOnly: true, ...partial };
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/analysis/types.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,0EAA0E;AAC1E,kFAAkF;AAClF,iFAAiF;AACjF,mCAAmC;AACnC,2EAA2E;AAuD3E,MAAM,UAAU,UAAU,CAAI,OAA4C;IACxE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type AnalyzerResult } from "./types.js";
|
|
2
|
+
export interface X402AnalysisInput {
|
|
3
|
+
url: string;
|
|
4
|
+
paymentAmountUsdc?: string;
|
|
5
|
+
paymentTokenAddress?: string;
|
|
6
|
+
payTo?: string;
|
|
7
|
+
agentId?: string;
|
|
8
|
+
chainId?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface X402AnalysisDetails {
|
|
11
|
+
url: string;
|
|
12
|
+
paymentAmountUsdc: string;
|
|
13
|
+
maxPaymentUsdc: string;
|
|
14
|
+
paymentTokenAddress: string;
|
|
15
|
+
payTo: string | null;
|
|
16
|
+
payToValid: boolean | null;
|
|
17
|
+
urlSafe: boolean;
|
|
18
|
+
amountWithinLimit: boolean;
|
|
19
|
+
tokenAllowlisted: boolean;
|
|
20
|
+
mainnetPaymentOnly: true;
|
|
21
|
+
mainnetPaymentSupported: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function analyzeX402(input: X402AnalysisInput): AnalyzerResult<X402AnalysisDetails>;
|
|
24
|
+
//# sourceMappingURL=x402.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../../../src/lib/analysis/x402.ts"],"names":[],"mappings":"AAaA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,IAAI,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,iBAAiB,GAAG,cAAc,CAAC,mBAAmB,CAAC,CAkDzF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// ─── x402 Analyzer (read-only) ─────────────────────────────────────────
|
|
2
|
+
// Wraps the existing deterministic x402 policy checks: URL SSRF guard, payment
|
|
3
|
+
// amount vs policy limit, and payment-token allowlist. Pure and offline-safe
|
|
4
|
+
// (static SSRF check, no DNS, no network). Requires NO payment keys.
|
|
5
|
+
//
|
|
6
|
+
// SafeHands supports x402 preflight by default. Actual settlement remains gated
|
|
7
|
+
// behind signer availability, WRITE_TOOLS_ENABLED, policy checks, and authorization.
|
|
8
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
9
|
+
import { isAddress } from "viem";
|
|
10
|
+
import { evaluateActionPolicy } from "../policy/actionPolicyEngine.js";
|
|
11
|
+
import { mapEngineDecision } from "../guardian/decision.js";
|
|
12
|
+
import { MAX_X402_PAYMENT_USDC, X402_PAYMENT_TOKEN_ADDRESS } from "../constants.js";
|
|
13
|
+
import { makeResult } from "./types.js";
|
|
14
|
+
export function analyzeX402(input) {
|
|
15
|
+
const paymentAmountUsdc = input.paymentAmountUsdc ?? "0.001";
|
|
16
|
+
const paymentTokenAddress = input.paymentTokenAddress ?? X402_PAYMENT_TOKEN_ADDRESS;
|
|
17
|
+
const policy = evaluateActionPolicy({
|
|
18
|
+
actionType: "x402_pay_and_fetch",
|
|
19
|
+
agentId: input.agentId,
|
|
20
|
+
url: input.url,
|
|
21
|
+
paymentAmountUsdc,
|
|
22
|
+
paymentTokenAddress,
|
|
23
|
+
chainId: input.chainId,
|
|
24
|
+
});
|
|
25
|
+
const urlCheck = policy.checks.find((c) => c.name === "x402_url");
|
|
26
|
+
const amountCheck = policy.checks.find((c) => c.name === "x402_payment_limit");
|
|
27
|
+
const tokenCheck = policy.checks.find((c) => c.name === "x402_payment_token");
|
|
28
|
+
const urlSafe = urlCheck ? urlCheck.status === "pass" : false;
|
|
29
|
+
const amountWithinLimit = amountCheck ? amountCheck.status === "pass" : true;
|
|
30
|
+
const tokenAllowlisted = !tokenCheck || tokenCheck.status === "pass";
|
|
31
|
+
const payToValid = input.payTo !== undefined ? isAddress(input.payTo) : null;
|
|
32
|
+
const warnings = [...policy.requiredActions];
|
|
33
|
+
if (payToValid === false)
|
|
34
|
+
warnings.push("payTo recipient is not a valid EVM address.");
|
|
35
|
+
// payment keys are never required for analysis; settlement is gated at the tool layer
|
|
36
|
+
const decision = payToValid === false ? "BLOCK" : mapEngineDecision(policy.decision);
|
|
37
|
+
return makeResult({
|
|
38
|
+
analyzer: "x402",
|
|
39
|
+
decision,
|
|
40
|
+
internalDecision: policy.decision,
|
|
41
|
+
riskLevel: policy.riskLevel,
|
|
42
|
+
reasons: policy.reasons.length ? policy.reasons : [urlSafe ? "x402 request passed static safety checks." : "x402 request failed a safety check."],
|
|
43
|
+
warnings,
|
|
44
|
+
analyzerStatus: "ok",
|
|
45
|
+
details: {
|
|
46
|
+
url: input.url,
|
|
47
|
+
paymentAmountUsdc,
|
|
48
|
+
maxPaymentUsdc: MAX_X402_PAYMENT_USDC,
|
|
49
|
+
paymentTokenAddress,
|
|
50
|
+
payTo: input.payTo ?? null,
|
|
51
|
+
payToValid,
|
|
52
|
+
urlSafe,
|
|
53
|
+
amountWithinLimit,
|
|
54
|
+
tokenAllowlisted,
|
|
55
|
+
mainnetPaymentOnly: true,
|
|
56
|
+
mainnetPaymentSupported: true,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=x402.js.map
|