safehands-pharos 1.4.0 → 1.5.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.
Files changed (124) hide show
  1. package/README.md +174 -63
  2. package/dist/cli.d.ts +5 -5
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +126 -124
  5. package/dist/cli.js.map +1 -1
  6. package/dist/demo.d.ts +1 -1
  7. package/dist/demo.js +171 -171
  8. package/dist/index.d.ts +2 -2
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +73 -65
  11. package/dist/index.js.map +1 -1
  12. package/dist/init.d.ts +1 -1
  13. package/dist/init.js +65 -65
  14. package/dist/lib/constants.d.ts +303 -291
  15. package/dist/lib/constants.d.ts.map +1 -1
  16. package/dist/lib/constants.js +302 -292
  17. package/dist/lib/constants.js.map +1 -1
  18. package/dist/lib/dodoApi.d.ts +78 -78
  19. package/dist/lib/dodoApi.js +196 -196
  20. package/dist/lib/envLoader.d.ts +2 -0
  21. package/dist/lib/envLoader.d.ts.map +1 -0
  22. package/dist/lib/envLoader.js +44 -0
  23. package/dist/lib/envLoader.js.map +1 -0
  24. package/dist/lib/http.d.ts +14 -14
  25. package/dist/lib/http.js +118 -118
  26. package/dist/lib/pharosClient.d.ts +58 -58
  27. package/dist/lib/pharosClient.js +63 -63
  28. package/dist/lib/policy/actionPolicyEngine.d.ts +53 -53
  29. package/dist/lib/policy/actionPolicyEngine.js +212 -212
  30. package/dist/lib/riskEngine.d.ts +26 -26
  31. package/dist/lib/riskEngine.d.ts.map +1 -1
  32. package/dist/lib/riskEngine.js +288 -283
  33. package/dist/lib/riskEngine.js.map +1 -1
  34. package/dist/lib/signer/index.d.ts +24 -24
  35. package/dist/lib/signer/index.js +88 -88
  36. package/dist/lib/testDodoLive.d.ts +1 -1
  37. package/dist/lib/testDodoLive.js +104 -104
  38. package/dist/lib/testLiveSafehands.d.ts +1 -1
  39. package/dist/lib/testLiveSafehands.js +92 -92
  40. package/dist/lib/testRpcLive.d.ts +1 -1
  41. package/dist/lib/testRpcLive.js +88 -88
  42. package/dist/lib/testTools.js +397 -398
  43. package/dist/lib/testX402Live.d.ts +1 -1
  44. package/dist/lib/testX402Live.js +159 -159
  45. package/dist/lib/toolResponse.d.ts +25 -25
  46. package/dist/lib/toolResponse.js +53 -53
  47. package/dist/lib/wallet/index.d.ts +37 -37
  48. package/dist/lib/wallet/index.js +128 -128
  49. package/dist/scripts/checkDeploy.d.ts +1 -1
  50. package/dist/scripts/checkDeploy.js +24 -24
  51. package/dist/scripts/deployRegistry.d.ts +1 -1
  52. package/dist/scripts/deployRegistry.js +100 -100
  53. package/dist/scripts/testRegistry.d.ts +1 -1
  54. package/dist/scripts/testRegistry.js +43 -43
  55. package/dist/tools/approveToken.d.ts +45 -45
  56. package/dist/tools/approveToken.js +85 -85
  57. package/dist/tools/assessRisk.d.ts +79 -79
  58. package/dist/tools/assessRisk.js +104 -104
  59. package/dist/tools/checkAllowance.d.ts +43 -43
  60. package/dist/tools/checkAllowance.js +56 -56
  61. package/dist/tools/checkTokenSecurity.d.ts +46 -46
  62. package/dist/tools/checkTokenSecurity.js +95 -95
  63. package/dist/tools/createAgentWallet.d.ts +28 -26
  64. package/dist/tools/createAgentWallet.d.ts.map +1 -1
  65. package/dist/tools/createAgentWallet.js +82 -58
  66. package/dist/tools/createAgentWallet.js.map +1 -1
  67. package/dist/tools/estimateGas.d.ts +79 -79
  68. package/dist/tools/estimateGas.js +124 -124
  69. package/dist/tools/executeSwap.d.ts +61 -61
  70. package/dist/tools/executeSwap.js +141 -141
  71. package/dist/tools/explainRisk.d.ts +29 -29
  72. package/dist/tools/explainRisk.js +32 -32
  73. package/dist/tools/getAgentWallet.d.ts +21 -21
  74. package/dist/tools/getAgentWallet.js +27 -27
  75. package/dist/tools/getAgentWalletBalance.d.ts +11 -11
  76. package/dist/tools/getAgentWalletBalance.js +70 -70
  77. package/dist/tools/getExecutionHistory.d.ts +49 -49
  78. package/dist/tools/getExecutionHistory.js +154 -154
  79. package/dist/tools/getGasPrice.d.ts +43 -43
  80. package/dist/tools/getGasPrice.js +59 -59
  81. package/dist/tools/getPoolInfo.d.ts +75 -75
  82. package/dist/tools/getPoolInfo.js +137 -137
  83. package/dist/tools/getTokenPrice.d.ts +113 -113
  84. package/dist/tools/getTokenPrice.js +117 -117
  85. package/dist/tools/getTransactionStatus.d.ts +43 -43
  86. package/dist/tools/getTransactionStatus.js +59 -59
  87. package/dist/tools/getWalletBalance.d.ts +68 -68
  88. package/dist/tools/getWalletBalance.js +87 -87
  89. package/dist/tools/publishRiskScore.d.ts +63 -63
  90. package/dist/tools/publishRiskScore.js +88 -88
  91. package/dist/tools/queryRiskRegistry.d.ts +38 -38
  92. package/dist/tools/queryRiskRegistry.js +55 -55
  93. package/dist/tools/safehandsPreflightCheck.d.ts +77 -77
  94. package/dist/tools/safehandsPreflightCheck.js +47 -47
  95. package/dist/tools/safehandsRiskReport.d.ts +81 -81
  96. package/dist/tools/safehandsRiskReport.js +28 -28
  97. package/dist/tools/safehandsSafeExecute.d.ts +20 -20
  98. package/dist/tools/safehandsSafeExecute.js +81 -81
  99. package/dist/tools/safehandsWalletHealth.d.ts +14 -14
  100. package/dist/tools/safehandsWalletHealth.js +103 -103
  101. package/dist/tools/safehandsX402Preflight.d.ts +26 -26
  102. package/dist/tools/safehandsX402Preflight.js +65 -65
  103. package/dist/tools/sendPayment.d.ts +57 -57
  104. package/dist/tools/sendPayment.js +117 -117
  105. package/dist/tools/simulateTransaction.d.ts +60 -60
  106. package/dist/tools/simulateTransaction.js +83 -83
  107. package/dist/tools/tokenRegistryStatus.d.ts +26 -26
  108. package/dist/tools/tokenRegistryStatus.js +96 -96
  109. package/dist/tools/x402PayAndFetch.d.ts +81 -81
  110. package/dist/tools/x402PayAndFetch.js +152 -152
  111. package/dist/x402Server.d.ts +1 -1
  112. package/dist/x402Server.js +300 -252
  113. package/dist/x402Server.js.map +1 -1
  114. package/package.json +6 -16
  115. package/examples/dashboard/index.html +0 -337
  116. package/examples/pharos-skill-engine/SKILL.safehands.md +0 -85
  117. package/examples/pharos-skill-engine/assets/safehands/example-actions.json +0 -49
  118. package/examples/pharos-skill-engine/assets/safehands/policy-defaults.json +0 -11
  119. package/examples/pharos-skill-engine/references/safehands.md +0 -345
  120. package/examples/scenario-hack.ts +0 -38
  121. package/skill/SKILL.md +0 -133
  122. package/skill/assets/safehands/example-actions.json +0 -49
  123. package/skill/assets/safehands/policy-defaults.json +0 -11
  124. package/skill/references/safehands.md +0 -345
@@ -1,153 +1,153 @@
1
- // ─── Tool: x402_pay_and_fetch ─────────────────────────────────────────────
2
- // Enables an agent to fetch protected resources from an x402 server.
3
- // Automatically executes the payment challenge only after HTTP 402 is returned.
4
- // ─────────────────────────────────────────────────────────────────────────
5
- import { z } from "zod";
6
- import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
7
- import { registerExactEvmScheme } from "@x402/evm/exact/client";
8
- import { CHAIN_ID, PHAROS_ENVIRONMENT, RPC_URL, MAX_X402_PAYMENT_USDC, X402_PAYMENT_TOKEN_ADDRESS } from "../lib/constants.js";
9
- import { assertSafeFetchUrl, fetchWithTimeoutAndRetry } from "../lib/http.js";
10
- import { fail, ok, requireWriteToolsEnabled } from "../lib/toolResponse.js";
11
- import { getSigner, isSignerFailure } from "../lib/signer/index.js";
12
- import { evaluateActionPolicy } from "../lib/policy/actionPolicyEngine.js";
13
- export const x402PayAndFetchSchema = z.object({
14
- url: z.string().describe("Target URL of the protected resource requiring x402 payment"),
15
- method: z.enum(["GET", "POST", "PUT", "DELETE"]).optional().default("GET").describe("HTTP method to use"),
16
- body: z.string().optional().describe("Optional stringified JSON request body"),
17
- rpcUrl: z.string().optional().describe("Custom RPC URL for payment verification (defaults to Atlantic Testnet RPC)"),
18
- agentId: z.string().optional().describe("Managed testnet wallet agentId when WALLET_MODE=managed-testnet"),
19
- maxPaymentUsdc: z.string().optional().default(MAX_X402_PAYMENT_USDC),
20
- });
21
- export const x402PayAndFetchTool = {
22
- name: "x402_pay_and_fetch",
23
- description: "Fetch resources from an HTTP x402 payment-gated server. " +
24
- "If the server challenges with HTTP 402, this tool signs the required testnet payment payload and completes the fetch.",
25
- inputSchema: x402PayAndFetchSchema,
26
- };
27
- async function readResponseBody(res) {
28
- const contentType = res.headers.get("content-type") || "";
29
- if (contentType.includes("application/json")) {
30
- try {
31
- return await res.json();
32
- }
33
- catch {
34
- return null;
35
- }
36
- }
37
- return await res.text();
38
- }
39
- function buildFetchOptions(input) {
40
- const fetchOptions = {
41
- method: input.method,
42
- headers: {
43
- "Content-Type": "application/json",
44
- },
45
- };
46
- if (input.body)
47
- fetchOptions.body = input.body;
48
- return fetchOptions;
49
- }
50
- export async function handleX402PayAndFetch(raw) {
51
- const input = x402PayAndFetchSchema.parse(raw);
52
- try {
53
- await assertSafeFetchUrl(input.url);
54
- }
55
- catch (err) {
56
- return fail("SSRF_BLOCKED", err instanceof Error ? err.message.replace(/^SSRF_BLOCKED:\s*/, "") : String(err), false, "x402_pay_and_fetch");
57
- }
58
- const staticPolicy = evaluateActionPolicy({
59
- actionType: "x402_pay_and_fetch",
60
- url: input.url,
61
- paymentAmountUsdc: input.maxPaymentUsdc,
62
- paymentTokenAddress: X402_PAYMENT_TOKEN_ADDRESS,
63
- chainId: CHAIN_ID,
64
- environment: PHAROS_ENVIRONMENT,
65
- isMainnet: false,
66
- });
67
- if (staticPolicy.decision === "BLOCK") {
68
- return fail("POLICY_BLOCKED", staticPolicy.reasons.join(" ") || "x402 request blocked by SafeHands policy.", false, "x402_pay_and_fetch");
69
- }
70
- const fetchOptions = buildFetchOptions(input);
71
- try {
72
- const initial = await fetchWithTimeoutAndRetry(input.url, {
73
- ...fetchOptions,
74
- timeoutMs: 10_000,
75
- retries: 1,
76
- retryDelayMs: 250,
77
- });
78
- if (initial.status !== 402) {
79
- const data = await readResponseBody(initial);
80
- return ok({
81
- status: initial.status,
82
- statusText: initial.statusText,
83
- data,
84
- paymentExecuted: false,
85
- paymentDetails: null,
86
- chainId: CHAIN_ID,
87
- environment: PHAROS_ENVIRONMENT,
88
- isMainnet: false,
89
- policy: staticPolicy,
90
- source: "x402_fetch",
91
- });
92
- }
93
- const writeGuard = requireWriteToolsEnabled("x402_pay_and_fetch");
94
- if (writeGuard)
95
- return writeGuard;
96
- const signer = await getSigner(input.agentId, { purpose: "x402" });
97
- if (isSignerFailure(signer)) {
98
- return fail("X402_PAYMENT_REQUIRED", `The resource returned HTTP 402, but no safe x402 signer is available: ${signer.error.message}`, false, "x402_pay_and_fetch");
99
- }
100
- const paymentPolicy = evaluateActionPolicy({
101
- actionType: "x402_pay_and_fetch",
102
- url: input.url,
103
- paymentAmountUsdc: input.maxPaymentUsdc,
104
- paymentTokenAddress: X402_PAYMENT_TOKEN_ADDRESS,
105
- chainId: CHAIN_ID,
106
- environment: PHAROS_ENVIRONMENT,
107
- isMainnet: false,
108
- signerAvailable: true,
109
- requiresSigner: true,
110
- });
111
- if (paymentPolicy.decision === "BLOCK") {
112
- return fail("POLICY_BLOCKED", paymentPolicy.reasons.join(" ") || "x402 payment blocked by SafeHands policy.", false, "x402_pay_and_fetch");
113
- }
114
- const rpc = input.rpcUrl || process.env.PHAROS_RPC_URL || RPC_URL;
115
- const client = new x402Client();
116
- registerExactEvmScheme(client, {
117
- signer: signer.account,
118
- schemeOptions: {
119
- [CHAIN_ID]: { rpcUrl: rpc },
120
- },
121
- });
122
- const fetchWithPayment = wrapFetchWithPayment(fetch, client);
123
- const paidResponse = await fetchWithPayment(input.url, fetchOptions);
124
- const data = await readResponseBody(paidResponse);
125
- const paymentResponseHeader = paidResponse.headers.get("PAYMENT-RESPONSE");
126
- return ok({
127
- status: paidResponse.status,
128
- statusText: paidResponse.statusText,
129
- data,
130
- paymentExecuted: !!paymentResponseHeader,
131
- paymentDetails: paymentResponseHeader
132
- ? {
133
- headerRedacted: true,
134
- note: "PAYMENT-RESPONSE header was present but intentionally not exposed to avoid leaking signed payment data.",
135
- }
136
- : null,
137
- signerMode: signer.mode,
138
- walletAddress: signer.address,
139
- paymentToken: X402_PAYMENT_TOKEN_ADDRESS,
140
- maxPaymentUsdc: input.maxPaymentUsdc,
141
- chainId: CHAIN_ID,
142
- environment: PHAROS_ENVIRONMENT,
143
- isMainnet: false,
144
- policy: paymentPolicy,
145
- testnetPayment: true,
146
- source: "x402_fetch",
147
- });
148
- }
149
- catch (err) {
150
- return fail("X402_PAYMENT_FAILED", err instanceof Error ? err.message : String(err), true, "x402_pay_and_fetch");
151
- }
152
- }
1
+ // ─── Tool: x402_pay_and_fetch ─────────────────────────────────────────────
2
+ // Enables an agent to fetch protected resources from an x402 server.
3
+ // Automatically executes the payment challenge only after HTTP 402 is returned.
4
+ // ─────────────────────────────────────────────────────────────────────────
5
+ import { z } from "zod";
6
+ import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
7
+ import { registerExactEvmScheme } from "@x402/evm/exact/client";
8
+ import { CHAIN_ID, PHAROS_ENVIRONMENT, RPC_URL, MAX_X402_PAYMENT_USDC, X402_PAYMENT_TOKEN_ADDRESS } from "../lib/constants.js";
9
+ import { assertSafeFetchUrl, fetchWithTimeoutAndRetry } from "../lib/http.js";
10
+ import { fail, ok, requireWriteToolsEnabled } from "../lib/toolResponse.js";
11
+ import { getSigner, isSignerFailure } from "../lib/signer/index.js";
12
+ import { evaluateActionPolicy } from "../lib/policy/actionPolicyEngine.js";
13
+ export const x402PayAndFetchSchema = z.object({
14
+ url: z.string().describe("Target URL of the protected resource requiring x402 payment"),
15
+ method: z.enum(["GET", "POST", "PUT", "DELETE"]).optional().default("GET").describe("HTTP method to use"),
16
+ body: z.string().optional().describe("Optional stringified JSON request body"),
17
+ rpcUrl: z.string().optional().describe("Custom RPC URL for payment verification (defaults to Atlantic Testnet RPC)"),
18
+ agentId: z.string().optional().describe("Managed testnet wallet agentId when WALLET_MODE=managed-testnet"),
19
+ maxPaymentUsdc: z.string().optional().default(MAX_X402_PAYMENT_USDC),
20
+ });
21
+ export const x402PayAndFetchTool = {
22
+ name: "x402_pay_and_fetch",
23
+ description: "Fetch resources from an HTTP x402 payment-gated server. " +
24
+ "If the server challenges with HTTP 402, this tool signs the required testnet payment payload and completes the fetch.",
25
+ inputSchema: x402PayAndFetchSchema,
26
+ };
27
+ async function readResponseBody(res) {
28
+ const contentType = res.headers.get("content-type") || "";
29
+ if (contentType.includes("application/json")) {
30
+ try {
31
+ return await res.json();
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ return await res.text();
38
+ }
39
+ function buildFetchOptions(input) {
40
+ const fetchOptions = {
41
+ method: input.method,
42
+ headers: {
43
+ "Content-Type": "application/json",
44
+ },
45
+ };
46
+ if (input.body)
47
+ fetchOptions.body = input.body;
48
+ return fetchOptions;
49
+ }
50
+ export async function handleX402PayAndFetch(raw) {
51
+ const input = x402PayAndFetchSchema.parse(raw);
52
+ try {
53
+ await assertSafeFetchUrl(input.url);
54
+ }
55
+ catch (err) {
56
+ return fail("SSRF_BLOCKED", err instanceof Error ? err.message.replace(/^SSRF_BLOCKED:\s*/, "") : String(err), false, "x402_pay_and_fetch");
57
+ }
58
+ const staticPolicy = evaluateActionPolicy({
59
+ actionType: "x402_pay_and_fetch",
60
+ url: input.url,
61
+ paymentAmountUsdc: input.maxPaymentUsdc,
62
+ paymentTokenAddress: X402_PAYMENT_TOKEN_ADDRESS,
63
+ chainId: CHAIN_ID,
64
+ environment: PHAROS_ENVIRONMENT,
65
+ isMainnet: false,
66
+ });
67
+ if (staticPolicy.decision === "BLOCK") {
68
+ return fail("POLICY_BLOCKED", staticPolicy.reasons.join(" ") || "x402 request blocked by SafeHands policy.", false, "x402_pay_and_fetch");
69
+ }
70
+ const fetchOptions = buildFetchOptions(input);
71
+ try {
72
+ const initial = await fetchWithTimeoutAndRetry(input.url, {
73
+ ...fetchOptions,
74
+ timeoutMs: 10_000,
75
+ retries: 1,
76
+ retryDelayMs: 250,
77
+ });
78
+ if (initial.status !== 402) {
79
+ const data = await readResponseBody(initial);
80
+ return ok({
81
+ status: initial.status,
82
+ statusText: initial.statusText,
83
+ data,
84
+ paymentExecuted: false,
85
+ paymentDetails: null,
86
+ chainId: CHAIN_ID,
87
+ environment: PHAROS_ENVIRONMENT,
88
+ isMainnet: false,
89
+ policy: staticPolicy,
90
+ source: "x402_fetch",
91
+ });
92
+ }
93
+ const writeGuard = requireWriteToolsEnabled("x402_pay_and_fetch");
94
+ if (writeGuard)
95
+ return writeGuard;
96
+ const signer = await getSigner(input.agentId, { purpose: "x402" });
97
+ if (isSignerFailure(signer)) {
98
+ return fail("X402_PAYMENT_REQUIRED", `The resource returned HTTP 402, but no safe x402 signer is available: ${signer.error.message}`, false, "x402_pay_and_fetch");
99
+ }
100
+ const paymentPolicy = evaluateActionPolicy({
101
+ actionType: "x402_pay_and_fetch",
102
+ url: input.url,
103
+ paymentAmountUsdc: input.maxPaymentUsdc,
104
+ paymentTokenAddress: X402_PAYMENT_TOKEN_ADDRESS,
105
+ chainId: CHAIN_ID,
106
+ environment: PHAROS_ENVIRONMENT,
107
+ isMainnet: false,
108
+ signerAvailable: true,
109
+ requiresSigner: true,
110
+ });
111
+ if (paymentPolicy.decision === "BLOCK") {
112
+ return fail("POLICY_BLOCKED", paymentPolicy.reasons.join(" ") || "x402 payment blocked by SafeHands policy.", false, "x402_pay_and_fetch");
113
+ }
114
+ const rpc = input.rpcUrl || process.env.PHAROS_RPC_URL || RPC_URL;
115
+ const client = new x402Client();
116
+ registerExactEvmScheme(client, {
117
+ signer: signer.account,
118
+ schemeOptions: {
119
+ [CHAIN_ID]: { rpcUrl: rpc },
120
+ },
121
+ });
122
+ const fetchWithPayment = wrapFetchWithPayment(fetch, client);
123
+ const paidResponse = await fetchWithPayment(input.url, fetchOptions);
124
+ const data = await readResponseBody(paidResponse);
125
+ const paymentResponseHeader = paidResponse.headers.get("PAYMENT-RESPONSE");
126
+ return ok({
127
+ status: paidResponse.status,
128
+ statusText: paidResponse.statusText,
129
+ data,
130
+ paymentExecuted: !!paymentResponseHeader,
131
+ paymentDetails: paymentResponseHeader
132
+ ? {
133
+ headerRedacted: true,
134
+ note: "PAYMENT-RESPONSE header was present but intentionally not exposed to avoid leaking signed payment data.",
135
+ }
136
+ : null,
137
+ signerMode: signer.mode,
138
+ walletAddress: signer.address,
139
+ paymentToken: X402_PAYMENT_TOKEN_ADDRESS,
140
+ maxPaymentUsdc: input.maxPaymentUsdc,
141
+ chainId: CHAIN_ID,
142
+ environment: PHAROS_ENVIRONMENT,
143
+ isMainnet: false,
144
+ policy: paymentPolicy,
145
+ testnetPayment: true,
146
+ source: "x402_fetch",
147
+ });
148
+ }
149
+ catch (err) {
150
+ return fail("X402_PAYMENT_FAILED", err instanceof Error ? err.message : String(err), true, "x402_pay_and_fetch");
151
+ }
152
+ }
153
153
  //# sourceMappingURL=x402PayAndFetch.js.map
@@ -1,2 +1,2 @@
1
- export {};
1
+ export {};
2
2
  //# sourceMappingURL=x402Server.d.ts.map