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,44 +1,44 @@
1
- import { z } from "zod";
2
- export declare const getGasPriceSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
- export type GetGasPriceInput = z.input<typeof getGasPriceSchema>;
4
- export declare const getGasPriceTool: {
5
- name: string;
6
- description: string;
7
- inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
8
- };
9
- export declare function handleGetGasPrice(_raw: GetGasPriceInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
10
- gasPrice: {
11
- value: string;
12
- unit: string;
13
- };
14
- gasPriceWei: string;
15
- trend: "low" | "high" | "normal";
16
- recommendation: string;
17
- estimates: {
18
- nativeTransfer: {
19
- gas: {
20
- value: string;
21
- unit: string;
22
- };
23
- costPHRS: {
24
- value: string;
25
- unit: string;
26
- };
27
- };
28
- tokenSwap: {
29
- gas: {
30
- value: string;
31
- unit: string;
32
- };
33
- costPHRS: {
34
- value: string;
35
- unit: string;
36
- };
37
- };
38
- };
39
- chainId: number;
40
- environment: string;
41
- isMainnet: boolean;
42
- source: string;
43
- }>>;
1
+ import { z } from "zod";
2
+ export declare const getGasPriceSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
+ export type GetGasPriceInput = z.input<typeof getGasPriceSchema>;
4
+ export declare const getGasPriceTool: {
5
+ name: string;
6
+ description: string;
7
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
8
+ };
9
+ export declare function handleGetGasPrice(_raw: GetGasPriceInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
10
+ gasPrice: {
11
+ value: string;
12
+ unit: string;
13
+ };
14
+ gasPriceWei: string;
15
+ trend: "low" | "high" | "normal";
16
+ recommendation: string;
17
+ estimates: {
18
+ nativeTransfer: {
19
+ gas: {
20
+ value: string;
21
+ unit: string;
22
+ };
23
+ costPHRS: {
24
+ value: string;
25
+ unit: string;
26
+ };
27
+ };
28
+ tokenSwap: {
29
+ gas: {
30
+ value: string;
31
+ unit: string;
32
+ };
33
+ costPHRS: {
34
+ value: string;
35
+ unit: string;
36
+ };
37
+ };
38
+ };
39
+ chainId: number;
40
+ environment: string;
41
+ isMainnet: boolean;
42
+ source: string;
43
+ }>>;
44
44
  //# sourceMappingURL=getGasPrice.d.ts.map
@@ -1,60 +1,60 @@
1
- // ─── Tool: get_gas_price ───────────────────────────────────────────────
2
- // Fetches current gas price from Pharos RPC with trend analysis.
3
- // ────────────────────────────────────────────────────────────────────────
4
- import { z } from "zod";
5
- import { publicClient } from "../lib/pharosClient.js";
6
- import { formatGwei } from "viem";
7
- import { CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
8
- import { classifyExternalError, ok } from "../lib/toolResponse.js";
9
- export const getGasPriceSchema = z.object({});
10
- export const getGasPriceTool = {
11
- name: "get_gas_price",
12
- description: "Get the current gas price on Pharos Atlantic Testnet with trend classification (low/normal/high) and cost estimates.",
13
- inputSchema: getGasPriceSchema,
14
- };
15
- export async function handleGetGasPrice(_raw) {
16
- try {
17
- const gasPrice = await publicClient.getGasPrice();
18
- const gasPriceGwei = parseFloat(formatGwei(gasPrice));
19
- let trend;
20
- let recommendation;
21
- if (gasPriceGwei <= 5) {
22
- trend = "low";
23
- recommendation = "Gas is cheap. Good time to execute testnet transactions.";
24
- }
25
- else if (gasPriceGwei <= 50) {
26
- trend = "normal";
27
- recommendation = "Gas is at normal testnet levels. Proceed with standard transactions.";
28
- }
29
- else {
30
- trend = "high";
31
- recommendation = "Gas is elevated. Consider waiting or reducing transaction complexity.";
32
- }
33
- const transferCostWei = gasPrice * 21000n;
34
- const swapCostWei = gasPrice * 250000n;
35
- return ok({
36
- gasPrice: { value: gasPriceGwei.toFixed(4), unit: "gwei" },
37
- gasPriceWei: gasPrice.toString(),
38
- trend,
39
- recommendation,
40
- estimates: {
41
- nativeTransfer: {
42
- gas: { value: "21000", unit: "gas" },
43
- costPHRS: { value: (Number(transferCostWei) / 1e18).toFixed(8), unit: "PHRS" },
44
- },
45
- tokenSwap: {
46
- gas: { value: "250000", unit: "gas" },
47
- costPHRS: { value: (Number(swapCostWei) / 1e18).toFixed(8), unit: "PHRS" },
48
- },
49
- },
50
- chainId: CHAIN_ID,
51
- environment: PHAROS_ENVIRONMENT,
52
- isMainnet: false,
53
- source: "pharos_rpc",
54
- });
55
- }
56
- catch (err) {
57
- return classifyExternalError("pharos_rpc", err);
58
- }
59
- }
1
+ // ─── Tool: get_gas_price ───────────────────────────────────────────────
2
+ // Fetches current gas price from Pharos RPC with trend analysis.
3
+ // ────────────────────────────────────────────────────────────────────────
4
+ import { z } from "zod";
5
+ import { publicClient } from "../lib/pharosClient.js";
6
+ import { formatGwei } from "viem";
7
+ import { CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
8
+ import { classifyExternalError, ok } from "../lib/toolResponse.js";
9
+ export const getGasPriceSchema = z.object({});
10
+ export const getGasPriceTool = {
11
+ name: "get_gas_price",
12
+ description: "Get the current gas price on Pharos Atlantic Testnet with trend classification (low/normal/high) and cost estimates.",
13
+ inputSchema: getGasPriceSchema,
14
+ };
15
+ export async function handleGetGasPrice(_raw) {
16
+ try {
17
+ const gasPrice = await publicClient.getGasPrice();
18
+ const gasPriceGwei = parseFloat(formatGwei(gasPrice));
19
+ let trend;
20
+ let recommendation;
21
+ if (gasPriceGwei <= 5) {
22
+ trend = "low";
23
+ recommendation = "Gas is cheap. Good time to execute testnet transactions.";
24
+ }
25
+ else if (gasPriceGwei <= 50) {
26
+ trend = "normal";
27
+ recommendation = "Gas is at normal testnet levels. Proceed with standard transactions.";
28
+ }
29
+ else {
30
+ trend = "high";
31
+ recommendation = "Gas is elevated. Consider waiting or reducing transaction complexity.";
32
+ }
33
+ const transferCostWei = gasPrice * 21000n;
34
+ const swapCostWei = gasPrice * 250000n;
35
+ return ok({
36
+ gasPrice: { value: gasPriceGwei.toFixed(4), unit: "gwei" },
37
+ gasPriceWei: gasPrice.toString(),
38
+ trend,
39
+ recommendation,
40
+ estimates: {
41
+ nativeTransfer: {
42
+ gas: { value: "21000", unit: "gas" },
43
+ costPHRS: { value: (Number(transferCostWei) / 1e18).toFixed(8), unit: "PHRS" },
44
+ },
45
+ tokenSwap: {
46
+ gas: { value: "250000", unit: "gas" },
47
+ costPHRS: { value: (Number(swapCostWei) / 1e18).toFixed(8), unit: "PHRS" },
48
+ },
49
+ },
50
+ chainId: CHAIN_ID,
51
+ environment: PHAROS_ENVIRONMENT,
52
+ isMainnet: false,
53
+ source: "pharos_rpc",
54
+ });
55
+ }
56
+ catch (err) {
57
+ return classifyExternalError("pharos_rpc", err);
58
+ }
59
+ }
60
60
  //# sourceMappingURL=getGasPrice.js.map
@@ -1,76 +1,76 @@
1
- import { z } from "zod";
2
- export declare const getPoolInfoSchema: z.ZodObject<{
3
- tokenA: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
4
- tokenB: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
5
- }, "strip", z.ZodTypeAny, {
6
- tokenA: "PHRS" | "USDC" | "USDT";
7
- tokenB: "PHRS" | "USDC" | "USDT";
8
- }, {
9
- tokenA: "PHRS" | "USDC" | "USDT";
10
- tokenB: "PHRS" | "USDC" | "USDT";
11
- }>;
12
- export type GetPoolInfoInput = z.input<typeof getPoolInfoSchema>;
13
- export declare const getPoolInfoTool: {
14
- name: string;
15
- description: string;
16
- inputSchema: z.ZodObject<{
17
- tokenA: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
18
- tokenB: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
19
- }, "strip", z.ZodTypeAny, {
20
- tokenA: "PHRS" | "USDC" | "USDT";
21
- tokenB: "PHRS" | "USDC" | "USDT";
22
- }, {
23
- tokenA: "PHRS" | "USDC" | "USDT";
24
- tokenB: "PHRS" | "USDC" | "USDT";
25
- }>;
26
- };
27
- export declare function handleGetPoolInfo(raw: GetPoolInfoInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
28
- pair: string;
29
- available: boolean;
30
- message: string;
31
- source: string;
32
- sourceStatus: string;
33
- publicMode: boolean;
34
- chainId: number;
35
- environment: string;
36
- isMainnet: boolean;
37
- }> | import("../lib/toolResponse.js").ToolSuccess<{
38
- pair: string;
39
- available: boolean;
40
- priceRatio: {
41
- value: string;
42
- unit: "PHRS" | "USDC" | "USDT";
43
- per: string;
44
- } | null;
45
- priceImpact: {
46
- value: string;
47
- unit: string;
48
- };
49
- pricePerFromToken: {
50
- value: string;
51
- unit: "PHRS" | "USDC" | "USDT";
52
- } | null;
53
- pricePerToToken: {
54
- value: string;
55
- unit: "PHRS" | "USDC" | "USDT";
56
- } | null;
57
- fee: {
58
- value: string;
59
- unit: string;
60
- } | null;
61
- liquidity: {
62
- baseLiquidity: string;
63
- quoteLiquidity: string;
64
- poolType: string;
65
- } | null;
66
- poolListStatus: string;
67
- source: string;
68
- sourceStatus: string;
69
- publicMode: boolean;
70
- routeAvailable: boolean;
71
- confidence: string;
72
- chainId: number;
73
- environment: string;
74
- isMainnet: boolean;
75
- }>>;
1
+ import { z } from "zod";
2
+ export declare const getPoolInfoSchema: z.ZodObject<{
3
+ tokenA: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
4
+ tokenB: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ tokenA: "PHRS" | "USDC" | "USDT";
7
+ tokenB: "PHRS" | "USDC" | "USDT";
8
+ }, {
9
+ tokenA: "PHRS" | "USDC" | "USDT";
10
+ tokenB: "PHRS" | "USDC" | "USDT";
11
+ }>;
12
+ export type GetPoolInfoInput = z.input<typeof getPoolInfoSchema>;
13
+ export declare const getPoolInfoTool: {
14
+ name: string;
15
+ description: string;
16
+ inputSchema: z.ZodObject<{
17
+ tokenA: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
18
+ tokenB: z.ZodEnum<["PHRS", "USDC", "USDT"]>;
19
+ }, "strip", z.ZodTypeAny, {
20
+ tokenA: "PHRS" | "USDC" | "USDT";
21
+ tokenB: "PHRS" | "USDC" | "USDT";
22
+ }, {
23
+ tokenA: "PHRS" | "USDC" | "USDT";
24
+ tokenB: "PHRS" | "USDC" | "USDT";
25
+ }>;
26
+ };
27
+ export declare function handleGetPoolInfo(raw: GetPoolInfoInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
28
+ pair: string;
29
+ available: boolean;
30
+ message: string;
31
+ source: string;
32
+ sourceStatus: string;
33
+ publicMode: boolean;
34
+ chainId: number;
35
+ environment: string;
36
+ isMainnet: boolean;
37
+ }> | import("../lib/toolResponse.js").ToolSuccess<{
38
+ pair: string;
39
+ available: boolean;
40
+ priceRatio: {
41
+ value: string;
42
+ unit: "PHRS" | "USDC" | "USDT";
43
+ per: string;
44
+ } | null;
45
+ priceImpact: {
46
+ value: string;
47
+ unit: string;
48
+ };
49
+ pricePerFromToken: {
50
+ value: string;
51
+ unit: "PHRS" | "USDC" | "USDT";
52
+ } | null;
53
+ pricePerToToken: {
54
+ value: string;
55
+ unit: "PHRS" | "USDC" | "USDT";
56
+ } | null;
57
+ fee: {
58
+ value: string;
59
+ unit: string;
60
+ } | null;
61
+ liquidity: {
62
+ baseLiquidity: string;
63
+ quoteLiquidity: string;
64
+ poolType: string;
65
+ } | null;
66
+ poolListStatus: string;
67
+ source: string;
68
+ sourceStatus: string;
69
+ publicMode: boolean;
70
+ routeAvailable: boolean;
71
+ confidence: string;
72
+ chainId: number;
73
+ environment: string;
74
+ isMainnet: boolean;
75
+ }>>;
76
76
  //# sourceMappingURL=getPoolInfo.d.ts.map
@@ -1,138 +1,138 @@
1
- // ─── Tool: get_pool_info ───────────────────────────────────────────────
2
- // Fetches DODO/FaroSwap route-derived liquidity info for a token pair on
3
- // Pharos Atlantic Testnet. API key is optional: public mode is tried first
4
- // when DODO_API_KEY is not configured.
5
- // ────────────────────────────────────────────────────────────────────────
6
- import { z } from "zod";
7
- import { resolveTokenAddress } from "../lib/dodoApi.js";
8
- import { DODO_API_BASE, DODO_API_KEY, CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
9
- import { fetchWithTimeoutAndRetry } from "../lib/http.js";
10
- import { classifyExternalError, fail, ok } from "../lib/toolResponse.js";
11
- export const getPoolInfoSchema = z.object({
12
- tokenA: z.enum(["PHRS", "USDC", "USDT"]).describe("First token in the pair"),
13
- tokenB: z.enum(["PHRS", "USDC", "USDT"]).describe("Second token in the pair"),
14
- });
15
- export const getPoolInfoTool = {
16
- name: "get_pool_info",
17
- description: "Fetch DODO/FaroSwap route-derived liquidity info for a token pair on Pharos testnet. API key is optional; public mode is attempted first.",
18
- inputSchema: getPoolInfoSchema,
19
- };
20
- function addOptionalApiKey(url) {
21
- const key = DODO_API_KEY?.trim();
22
- if (!key)
23
- return false;
24
- url.searchParams.set("apikey", key);
25
- return true;
26
- }
27
- function isAuthErrorStatus(status) {
28
- return status === 401 || status === 403;
29
- }
30
- export async function handleGetPoolInfo(raw) {
31
- const input = getPoolInfoSchema.parse(raw);
32
- if (input.tokenA === input.tokenB) {
33
- return fail("INVALID_PAIR", "Cannot query pool for identical tokens.", false, "get_pool_info");
34
- }
35
- try {
36
- const addrA = resolveTokenAddress(input.tokenA);
37
- const addrB = resolveTokenAddress(input.tokenB);
38
- const routeUrl = new URL(`${DODO_API_BASE}/route-service/v2/widget/getdodoroute`);
39
- routeUrl.searchParams.set("chainId", String(CHAIN_ID));
40
- routeUrl.searchParams.set("fromTokenAddress", addrA);
41
- routeUrl.searchParams.set("toTokenAddress", addrB);
42
- routeUrl.searchParams.set("fromAmount", "1000000000000000000");
43
- routeUrl.searchParams.set("userAddr", "0x0000000000000000000000000000000000000001");
44
- routeUrl.searchParams.set("slippage", "3");
45
- routeUrl.searchParams.set("source", "dodoV2AndMixWasm");
46
- routeUrl.searchParams.set("estimateGas", "true");
47
- const routeUsedApiKey = addOptionalApiKey(routeUrl);
48
- const routeResponse = await fetchWithTimeoutAndRetry(routeUrl, { timeoutMs: 10_000, retries: 2, retryDelayMs: 300 });
49
- if (isAuthErrorStatus(routeResponse.status)) {
50
- return fail("DODO_API_AUTH_REQUIRED", "DODO/FaroSwap route API rejected public mode. Configure DODO_API_KEY only if this endpoint requires authenticated access.", false, "dodo_api");
51
- }
52
- if (!routeResponse.ok) {
53
- return fail("DODO_API_UNAVAILABLE", `DODO route API returned ${routeResponse.status} ${routeResponse.statusText}.`, true, "dodo_api");
54
- }
55
- const routeJson = (await routeResponse.json());
56
- if (!routeJson.data || routeJson.status !== 200) {
57
- const msg = (routeJson.message || "").toLowerCase();
58
- if (msg.includes("api key") || msg.includes("apikey") || msg.includes("unauthorized") || msg.includes("forbidden")) {
59
- return fail("DODO_API_AUTH_REQUIRED", "DODO/FaroSwap route API rejected public mode. Configure DODO_API_KEY only if this endpoint requires authenticated access.", false, "dodo_api");
60
- }
61
- return ok({
62
- pair: `${input.tokenA}/${input.tokenB}`,
63
- available: false,
64
- message: "No active DODO/FaroSwap route found for this pair on Pharos testnet.",
65
- source: "DODO/FaroSwap public route API",
66
- sourceStatus: "no_route_available",
67
- publicMode: !routeUsedApiKey,
68
- chainId: CHAIN_ID,
69
- environment: PHAROS_ENVIRONMENT,
70
- isMainnet: false,
71
- });
72
- }
73
- const d = routeJson.data;
74
- const resAmount = parseFloat(String(d.resAmount || "0"));
75
- const priceImpact = parseFloat(String(d.priceImpact || "0"));
76
- const fee = parseFloat(String(d.baseFeeAmount || "0"));
77
- const pricePerFrom = parseFloat(String(d.resPricePerFromToken || "0"));
78
- const pricePerTo = parseFloat(String(d.resPricePerToToken || "0"));
79
- let liquidityInfo = null;
80
- let poolListStatus = "unavailable";
81
- try {
82
- const poolsUrl = new URL(`${DODO_API_BASE}/dodo-pair/list`);
83
- poolsUrl.searchParams.set("chainId", String(CHAIN_ID));
84
- poolsUrl.searchParams.set("baseToken", addrA);
85
- poolsUrl.searchParams.set("quoteToken", addrB);
86
- addOptionalApiKey(poolsUrl);
87
- const poolsResp = await fetchWithTimeoutAndRetry(poolsUrl, { timeoutMs: 10_000, retries: 1, retryDelayMs: 300 });
88
- if (poolsResp.ok) {
89
- const poolsJson = (await poolsResp.json());
90
- if (poolsJson.data?.list && poolsJson.data.list.length > 0) {
91
- const pool = poolsJson.data.list[0];
92
- liquidityInfo = {
93
- baseLiquidity: pool.baseLiquidity || "unknown",
94
- quoteLiquidity: pool.quoteLiquidity || "unknown",
95
- poolType: pool.type || "unknown",
96
- };
97
- poolListStatus = "ok";
98
- }
99
- else {
100
- poolListStatus = "empty";
101
- }
102
- }
103
- else if (isAuthErrorStatus(poolsResp.status)) {
104
- poolListStatus = "auth_required";
105
- }
106
- }
107
- catch {
108
- poolListStatus = "unavailable";
109
- }
110
- return ok({
111
- pair: `${input.tokenA}/${input.tokenB}`,
112
- available: true,
113
- priceRatio: resAmount > 0 ? { value: resAmount.toString(), unit: input.tokenB, per: `1 ${input.tokenA}` } : null,
114
- priceImpact: { value: priceImpact.toFixed(4), unit: "percent" },
115
- pricePerFromToken: pricePerFrom > 0 ? { value: pricePerFrom.toFixed(6), unit: input.tokenB } : null,
116
- pricePerToToken: pricePerTo > 0 ? { value: pricePerTo.toFixed(6), unit: input.tokenA } : null,
117
- fee: fee > 0 ? { value: fee.toString(), unit: "raw" } : null,
118
- liquidity: liquidityInfo,
119
- poolListStatus,
120
- source: "DODO/FaroSwap public route API",
121
- sourceStatus: "ok",
122
- publicMode: !routeUsedApiKey,
123
- routeAvailable: true,
124
- confidence: liquidityInfo ? "medium" : "low",
125
- chainId: CHAIN_ID,
126
- environment: PHAROS_ENVIRONMENT,
127
- isMainnet: false,
128
- });
129
- }
130
- catch (err) {
131
- const message = err instanceof Error ? err.message : String(err);
132
- if (message.includes("INVALID_TOKEN_ADDRESS")) {
133
- return fail("INVALID_TOKEN_ADDRESS", message, false, "get_pool_info");
134
- }
135
- return classifyExternalError("dodo_api", err);
136
- }
137
- }
1
+ // ─── Tool: get_pool_info ───────────────────────────────────────────────
2
+ // Fetches DODO/FaroSwap route-derived liquidity info for a token pair on
3
+ // Pharos Atlantic Testnet. API key is optional: public mode is tried first
4
+ // when DODO_API_KEY is not configured.
5
+ // ────────────────────────────────────────────────────────────────────────
6
+ import { z } from "zod";
7
+ import { resolveTokenAddress } from "../lib/dodoApi.js";
8
+ import { DODO_API_BASE, DODO_API_KEY, CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
9
+ import { fetchWithTimeoutAndRetry } from "../lib/http.js";
10
+ import { classifyExternalError, fail, ok } from "../lib/toolResponse.js";
11
+ export const getPoolInfoSchema = z.object({
12
+ tokenA: z.enum(["PHRS", "USDC", "USDT"]).describe("First token in the pair"),
13
+ tokenB: z.enum(["PHRS", "USDC", "USDT"]).describe("Second token in the pair"),
14
+ });
15
+ export const getPoolInfoTool = {
16
+ name: "get_pool_info",
17
+ description: "Fetch DODO/FaroSwap route-derived liquidity info for a token pair on Pharos testnet. API key is optional; public mode is attempted first.",
18
+ inputSchema: getPoolInfoSchema,
19
+ };
20
+ function addOptionalApiKey(url) {
21
+ const key = DODO_API_KEY?.trim();
22
+ if (!key)
23
+ return false;
24
+ url.searchParams.set("apikey", key);
25
+ return true;
26
+ }
27
+ function isAuthErrorStatus(status) {
28
+ return status === 401 || status === 403;
29
+ }
30
+ export async function handleGetPoolInfo(raw) {
31
+ const input = getPoolInfoSchema.parse(raw);
32
+ if (input.tokenA === input.tokenB) {
33
+ return fail("INVALID_PAIR", "Cannot query pool for identical tokens.", false, "get_pool_info");
34
+ }
35
+ try {
36
+ const addrA = resolveTokenAddress(input.tokenA);
37
+ const addrB = resolveTokenAddress(input.tokenB);
38
+ const routeUrl = new URL(`${DODO_API_BASE}/route-service/v2/widget/getdodoroute`);
39
+ routeUrl.searchParams.set("chainId", String(CHAIN_ID));
40
+ routeUrl.searchParams.set("fromTokenAddress", addrA);
41
+ routeUrl.searchParams.set("toTokenAddress", addrB);
42
+ routeUrl.searchParams.set("fromAmount", "1000000000000000000");
43
+ routeUrl.searchParams.set("userAddr", "0x0000000000000000000000000000000000000001");
44
+ routeUrl.searchParams.set("slippage", "3");
45
+ routeUrl.searchParams.set("source", "dodoV2AndMixWasm");
46
+ routeUrl.searchParams.set("estimateGas", "true");
47
+ const routeUsedApiKey = addOptionalApiKey(routeUrl);
48
+ const routeResponse = await fetchWithTimeoutAndRetry(routeUrl, { timeoutMs: 10_000, retries: 2, retryDelayMs: 300 });
49
+ if (isAuthErrorStatus(routeResponse.status)) {
50
+ return fail("DODO_API_AUTH_REQUIRED", "DODO/FaroSwap route API rejected public mode. Configure DODO_API_KEY only if this endpoint requires authenticated access.", false, "dodo_api");
51
+ }
52
+ if (!routeResponse.ok) {
53
+ return fail("DODO_API_UNAVAILABLE", `DODO route API returned ${routeResponse.status} ${routeResponse.statusText}.`, true, "dodo_api");
54
+ }
55
+ const routeJson = (await routeResponse.json());
56
+ if (!routeJson.data || routeJson.status !== 200) {
57
+ const msg = (routeJson.message || "").toLowerCase();
58
+ if (msg.includes("api key") || msg.includes("apikey") || msg.includes("unauthorized") || msg.includes("forbidden")) {
59
+ return fail("DODO_API_AUTH_REQUIRED", "DODO/FaroSwap route API rejected public mode. Configure DODO_API_KEY only if this endpoint requires authenticated access.", false, "dodo_api");
60
+ }
61
+ return ok({
62
+ pair: `${input.tokenA}/${input.tokenB}`,
63
+ available: false,
64
+ message: "No active DODO/FaroSwap route found for this pair on Pharos testnet.",
65
+ source: "DODO/FaroSwap public route API",
66
+ sourceStatus: "no_route_available",
67
+ publicMode: !routeUsedApiKey,
68
+ chainId: CHAIN_ID,
69
+ environment: PHAROS_ENVIRONMENT,
70
+ isMainnet: false,
71
+ });
72
+ }
73
+ const d = routeJson.data;
74
+ const resAmount = parseFloat(String(d.resAmount || "0"));
75
+ const priceImpact = parseFloat(String(d.priceImpact || "0"));
76
+ const fee = parseFloat(String(d.baseFeeAmount || "0"));
77
+ const pricePerFrom = parseFloat(String(d.resPricePerFromToken || "0"));
78
+ const pricePerTo = parseFloat(String(d.resPricePerToToken || "0"));
79
+ let liquidityInfo = null;
80
+ let poolListStatus = "unavailable";
81
+ try {
82
+ const poolsUrl = new URL(`${DODO_API_BASE}/dodo-pair/list`);
83
+ poolsUrl.searchParams.set("chainId", String(CHAIN_ID));
84
+ poolsUrl.searchParams.set("baseToken", addrA);
85
+ poolsUrl.searchParams.set("quoteToken", addrB);
86
+ addOptionalApiKey(poolsUrl);
87
+ const poolsResp = await fetchWithTimeoutAndRetry(poolsUrl, { timeoutMs: 10_000, retries: 1, retryDelayMs: 300 });
88
+ if (poolsResp.ok) {
89
+ const poolsJson = (await poolsResp.json());
90
+ if (poolsJson.data?.list && poolsJson.data.list.length > 0) {
91
+ const pool = poolsJson.data.list[0];
92
+ liquidityInfo = {
93
+ baseLiquidity: pool.baseLiquidity || "unknown",
94
+ quoteLiquidity: pool.quoteLiquidity || "unknown",
95
+ poolType: pool.type || "unknown",
96
+ };
97
+ poolListStatus = "ok";
98
+ }
99
+ else {
100
+ poolListStatus = "empty";
101
+ }
102
+ }
103
+ else if (isAuthErrorStatus(poolsResp.status)) {
104
+ poolListStatus = "auth_required";
105
+ }
106
+ }
107
+ catch {
108
+ poolListStatus = "unavailable";
109
+ }
110
+ return ok({
111
+ pair: `${input.tokenA}/${input.tokenB}`,
112
+ available: true,
113
+ priceRatio: resAmount > 0 ? { value: resAmount.toString(), unit: input.tokenB, per: `1 ${input.tokenA}` } : null,
114
+ priceImpact: { value: priceImpact.toFixed(4), unit: "percent" },
115
+ pricePerFromToken: pricePerFrom > 0 ? { value: pricePerFrom.toFixed(6), unit: input.tokenB } : null,
116
+ pricePerToToken: pricePerTo > 0 ? { value: pricePerTo.toFixed(6), unit: input.tokenA } : null,
117
+ fee: fee > 0 ? { value: fee.toString(), unit: "raw" } : null,
118
+ liquidity: liquidityInfo,
119
+ poolListStatus,
120
+ source: "DODO/FaroSwap public route API",
121
+ sourceStatus: "ok",
122
+ publicMode: !routeUsedApiKey,
123
+ routeAvailable: true,
124
+ confidence: liquidityInfo ? "medium" : "low",
125
+ chainId: CHAIN_ID,
126
+ environment: PHAROS_ENVIRONMENT,
127
+ isMainnet: false,
128
+ });
129
+ }
130
+ catch (err) {
131
+ const message = err instanceof Error ? err.message : String(err);
132
+ if (message.includes("INVALID_TOKEN_ADDRESS")) {
133
+ return fail("INVALID_TOKEN_ADDRESS", message, false, "get_pool_info");
134
+ }
135
+ return classifyExternalError("dodo_api", err);
136
+ }
137
+ }
138
138
  //# sourceMappingURL=getPoolInfo.js.map