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,118 +1,118 @@
1
- // ─── Tool: send_payment ────────────────────────────────────────────────
2
- import { z } from "zod";
3
- import { publicClient, createPharosWalletClientFromAccount, getExplorerUrl } from "../lib/pharosClient.js";
4
- import { isAddress, parseEther, formatEther } from "viem";
5
- import { assessRisk } from "../lib/riskEngine.js";
6
- import { fail, ok, classifyExternalError } from "../lib/toolResponse.js";
7
- import { MAX_BALANCE_USAGE_PCT, RISK_BLOCK_THRESHOLD, MAX_TX_AMOUNT_PHRS, CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
8
- import { getSigner, isSignerFailure } from "../lib/signer/index.js";
9
- import { evaluateActionPolicy } from "../lib/policy/actionPolicyEngine.js";
10
- import { checkDailyLimit, recordSpend, estimateUsd } from "../lib/spendAccumulator.js";
11
- export const sendPaymentSchema = z.object({
12
- toAddress: z.string(),
13
- amount: z.string(),
14
- memo: z.string().optional(),
15
- agentId: z.string().optional().describe("Managed testnet wallet agentId when WALLET_MODE=managed-testnet"),
16
- });
17
- export const sendPaymentTool = {
18
- name: "send_payment",
19
- description: "Send native PHRS with pre-flight validation. Checks address validity, balance sufficiency, and warns on high exposure.",
20
- inputSchema: sendPaymentSchema,
21
- };
22
- export async function handleSendPayment(raw) {
23
- if (process.env.WRITE_TOOLS_ENABLED !== "true") {
24
- return fail("WRITE_TOOLS_DISABLED", "send_payment is disabled by default. Set WRITE_TOOLS_ENABLED=true only for trusted testnet execution.", false, "send_payment");
25
- }
26
- const input = sendPaymentSchema.parse(raw);
27
- const signer = await getSigner(input.agentId);
28
- if (isSignerFailure(signer)) {
29
- return fail(signer.error.code, signer.error.message, false, "send_payment");
30
- }
31
- const walletAddress = signer.address;
32
- const policy = evaluateActionPolicy({
33
- actionType: "send_payment",
34
- amount: input.amount,
35
- amountUnit: "PHRS",
36
- recipient: input.toAddress,
37
- recipientVerified: false,
38
- chainId: CHAIN_ID,
39
- environment: PHAROS_ENVIRONMENT,
40
- isMainnet: false,
41
- signerAvailable: true,
42
- requiresSigner: true,
43
- });
44
- if (policy.decision === "BLOCK") {
45
- return fail("POLICY_BLOCKED", policy.reasons.join(" ") || "Payment blocked by SafeHands policy.", false, "send_payment");
46
- }
47
- if (Number(input.amount) > Number(MAX_TX_AMOUNT_PHRS)) {
48
- return fail("TX_LIMIT_EXCEEDED", `Payment amount exceeds configured testnet limit (${MAX_TX_AMOUNT_PHRS} PHRS).`, false, "send_payment");
49
- }
50
- const amountUsd = estimateUsd(input.amount, "PHRS");
51
- const dailyCheck = checkDailyLimit(walletAddress, amountUsd);
52
- if (!dailyCheck.allowed) {
53
- return fail("DAILY_SPEND_LIMIT_EXCEEDED", `Daily spend limit reached. Spent $${dailyCheck.currentUsd.toFixed(2)} of $${dailyCheck.limitUsd.toFixed(2)} USD today. Remaining: $${dailyCheck.remainingUsd.toFixed(2)}. Resets at UTC midnight.`, false, "send_payment");
54
- }
55
- const warnings = [];
56
- const validation = { addressValid: false, balanceSufficient: false, warnings };
57
- if (!isAddress(input.toAddress)) {
58
- return fail("INVALID_WALLET_ADDRESS", "Invalid recipient address", false, "send_payment");
59
- }
60
- validation.addressValid = true;
61
- if (input.toAddress === "0x0000000000000000000000000000000000000000") {
62
- return fail("ZERO_ADDRESS_BLOCKED", "Cannot send to zero address", false, "send_payment");
63
- }
64
- if (input.toAddress.toLowerCase() === walletAddress.toLowerCase()) {
65
- warnings.push("Sending to own address");
66
- }
67
- const amountWei = parseEther(input.amount);
68
- const balance = await publicClient.getBalance({ address: walletAddress });
69
- const gasEstimate = parseEther("0.01");
70
- if (balance < amountWei + gasEstimate) {
71
- return fail("INSUFFICIENT_TESTNET_BALANCE", `Insufficient balance: have ${formatEther(balance)} PHRS, need ${input.amount} + gas`, false, "send_payment");
72
- }
73
- validation.balanceSufficient = true;
74
- const usagePct = Number((amountWei * 100n) / balance);
75
- if (usagePct > MAX_BALANCE_USAGE_PCT) {
76
- warnings.push(`Using ${usagePct}% of wallet balance — high exposure`);
77
- }
78
- const risk = await assessRisk({
79
- action: "transfer",
80
- amount: input.amount,
81
- toAddress: input.toAddress,
82
- walletAddress,
83
- });
84
- if (risk.riskScore > RISK_BLOCK_THRESHOLD) {
85
- return fail("POLICY_BLOCKED", `Payment blocked — risk score ${risk.riskScore}/100: ${risk.suggestion}`, false, "send_payment");
86
- }
87
- try {
88
- const wallet = createPharosWalletClientFromAccount(signer.account);
89
- const txHash = await wallet.sendTransaction({
90
- to: input.toAddress,
91
- value: amountWei,
92
- });
93
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
94
- if (receipt.status !== "success") {
95
- return fail("TX_REVERTED", "send_payment transaction was mined but reverted on-chain.", false, "send_payment");
96
- }
97
- recordSpend(walletAddress, amountUsd);
98
- return ok({
99
- txHash,
100
- explorerUrl: getExplorerUrl(txHash),
101
- amountSent: input.amount,
102
- signerMode: signer.mode,
103
- walletAddress,
104
- gasUsed: receipt.gasUsed.toString(),
105
- validation,
106
- policy,
107
- riskAssessment: {
108
- riskScore: risk.riskScore,
109
- wasBlocked: false,
110
- },
111
- source: "send_payment",
112
- });
113
- }
114
- catch (err) {
115
- return classifyExternalError("pharos_rpc", err);
116
- }
117
- }
1
+ // ─── Tool: send_payment ────────────────────────────────────────────────
2
+ import { z } from "zod";
3
+ import { publicClient, createPharosWalletClientFromAccount, getExplorerUrl } from "../lib/pharosClient.js";
4
+ import { isAddress, parseEther, formatEther } from "viem";
5
+ import { assessRisk } from "../lib/riskEngine.js";
6
+ import { fail, ok, classifyExternalError } from "../lib/toolResponse.js";
7
+ import { MAX_BALANCE_USAGE_PCT, RISK_BLOCK_THRESHOLD, MAX_TX_AMOUNT_PHRS, CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
8
+ import { getSigner, isSignerFailure } from "../lib/signer/index.js";
9
+ import { evaluateActionPolicy } from "../lib/policy/actionPolicyEngine.js";
10
+ import { checkDailyLimit, recordSpend, estimateUsd } from "../lib/spendAccumulator.js";
11
+ export const sendPaymentSchema = z.object({
12
+ toAddress: z.string(),
13
+ amount: z.string(),
14
+ memo: z.string().optional(),
15
+ agentId: z.string().optional().describe("Managed testnet wallet agentId when WALLET_MODE=managed-testnet"),
16
+ });
17
+ export const sendPaymentTool = {
18
+ name: "send_payment",
19
+ description: "Send native PHRS with pre-flight validation. Checks address validity, balance sufficiency, and warns on high exposure.",
20
+ inputSchema: sendPaymentSchema,
21
+ };
22
+ export async function handleSendPayment(raw) {
23
+ if (process.env.WRITE_TOOLS_ENABLED !== "true") {
24
+ return fail("WRITE_TOOLS_DISABLED", "send_payment is disabled by default. Set WRITE_TOOLS_ENABLED=true only for trusted testnet execution.", false, "send_payment");
25
+ }
26
+ const input = sendPaymentSchema.parse(raw);
27
+ const signer = await getSigner(input.agentId);
28
+ if (isSignerFailure(signer)) {
29
+ return fail(signer.error.code, signer.error.message, false, "send_payment");
30
+ }
31
+ const walletAddress = signer.address;
32
+ const policy = evaluateActionPolicy({
33
+ actionType: "send_payment",
34
+ amount: input.amount,
35
+ amountUnit: "PHRS",
36
+ recipient: input.toAddress,
37
+ recipientVerified: false,
38
+ chainId: CHAIN_ID,
39
+ environment: PHAROS_ENVIRONMENT,
40
+ isMainnet: false,
41
+ signerAvailable: true,
42
+ requiresSigner: true,
43
+ });
44
+ if (policy.decision === "BLOCK") {
45
+ return fail("POLICY_BLOCKED", policy.reasons.join(" ") || "Payment blocked by SafeHands policy.", false, "send_payment");
46
+ }
47
+ if (Number(input.amount) > Number(MAX_TX_AMOUNT_PHRS)) {
48
+ return fail("TX_LIMIT_EXCEEDED", `Payment amount exceeds configured testnet limit (${MAX_TX_AMOUNT_PHRS} PHRS).`, false, "send_payment");
49
+ }
50
+ const amountUsd = estimateUsd(input.amount, "PHRS");
51
+ const dailyCheck = checkDailyLimit(walletAddress, amountUsd);
52
+ if (!dailyCheck.allowed) {
53
+ return fail("DAILY_SPEND_LIMIT_EXCEEDED", `Daily spend limit reached. Spent $${dailyCheck.currentUsd.toFixed(2)} of $${dailyCheck.limitUsd.toFixed(2)} USD today. Remaining: $${dailyCheck.remainingUsd.toFixed(2)}. Resets at UTC midnight.`, false, "send_payment");
54
+ }
55
+ const warnings = [];
56
+ const validation = { addressValid: false, balanceSufficient: false, warnings };
57
+ if (!isAddress(input.toAddress)) {
58
+ return fail("INVALID_WALLET_ADDRESS", "Invalid recipient address", false, "send_payment");
59
+ }
60
+ validation.addressValid = true;
61
+ if (input.toAddress === "0x0000000000000000000000000000000000000000") {
62
+ return fail("ZERO_ADDRESS_BLOCKED", "Cannot send to zero address", false, "send_payment");
63
+ }
64
+ if (input.toAddress.toLowerCase() === walletAddress.toLowerCase()) {
65
+ warnings.push("Sending to own address");
66
+ }
67
+ const amountWei = parseEther(input.amount);
68
+ const balance = await publicClient.getBalance({ address: walletAddress });
69
+ const gasEstimate = parseEther("0.01");
70
+ if (balance < amountWei + gasEstimate) {
71
+ return fail("INSUFFICIENT_TESTNET_BALANCE", `Insufficient balance: have ${formatEther(balance)} PHRS, need ${input.amount} + gas`, false, "send_payment");
72
+ }
73
+ validation.balanceSufficient = true;
74
+ const usagePct = Number((amountWei * 100n) / balance);
75
+ if (usagePct > MAX_BALANCE_USAGE_PCT) {
76
+ warnings.push(`Using ${usagePct}% of wallet balance — high exposure`);
77
+ }
78
+ const risk = await assessRisk({
79
+ action: "transfer",
80
+ amount: input.amount,
81
+ toAddress: input.toAddress,
82
+ walletAddress,
83
+ });
84
+ if (risk.riskScore > RISK_BLOCK_THRESHOLD) {
85
+ return fail("POLICY_BLOCKED", `Payment blocked — risk score ${risk.riskScore}/100: ${risk.suggestion}`, false, "send_payment");
86
+ }
87
+ try {
88
+ const wallet = createPharosWalletClientFromAccount(signer.account);
89
+ const txHash = await wallet.sendTransaction({
90
+ to: input.toAddress,
91
+ value: amountWei,
92
+ });
93
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
94
+ if (receipt.status !== "success") {
95
+ return fail("TX_REVERTED", "send_payment transaction was mined but reverted on-chain.", false, "send_payment");
96
+ }
97
+ recordSpend(walletAddress, amountUsd);
98
+ return ok({
99
+ txHash,
100
+ explorerUrl: getExplorerUrl(txHash),
101
+ amountSent: input.amount,
102
+ signerMode: signer.mode,
103
+ walletAddress,
104
+ gasUsed: receipt.gasUsed.toString(),
105
+ validation,
106
+ policy,
107
+ riskAssessment: {
108
+ riskScore: risk.riskScore,
109
+ wasBlocked: false,
110
+ },
111
+ source: "send_payment",
112
+ });
113
+ }
114
+ catch (err) {
115
+ return classifyExternalError("pharos_rpc", err);
116
+ }
117
+ }
118
118
  //# sourceMappingURL=sendPayment.js.map
@@ -1,61 +1,61 @@
1
- import { z } from "zod";
2
- export declare const simulateTransactionSchema: z.ZodObject<{
3
- action: z.ZodEnum<["swap", "transfer"]>;
4
- tokenIn: z.ZodOptional<z.ZodString>;
5
- tokenOut: z.ZodOptional<z.ZodString>;
6
- amount: z.ZodString;
7
- toAddress: z.ZodOptional<z.ZodString>;
8
- walletAddress: z.ZodString;
9
- }, "strip", z.ZodTypeAny, {
10
- amount: string;
11
- walletAddress: string;
12
- action: "transfer" | "swap";
13
- tokenIn?: string | undefined;
14
- tokenOut?: string | undefined;
15
- toAddress?: string | undefined;
16
- }, {
17
- amount: string;
18
- walletAddress: string;
19
- action: "transfer" | "swap";
20
- tokenIn?: string | undefined;
21
- tokenOut?: string | undefined;
22
- toAddress?: string | undefined;
23
- }>;
24
- export type SimulateTransactionInput = z.infer<typeof simulateTransactionSchema>;
25
- export declare const simulateTransactionTool: {
26
- name: string;
27
- description: string;
28
- inputSchema: z.ZodObject<{
29
- action: z.ZodEnum<["swap", "transfer"]>;
30
- tokenIn: z.ZodOptional<z.ZodString>;
31
- tokenOut: z.ZodOptional<z.ZodString>;
32
- amount: z.ZodString;
33
- toAddress: z.ZodOptional<z.ZodString>;
34
- walletAddress: z.ZodString;
35
- }, "strip", z.ZodTypeAny, {
36
- amount: string;
37
- walletAddress: string;
38
- action: "transfer" | "swap";
39
- tokenIn?: string | undefined;
40
- tokenOut?: string | undefined;
41
- toAddress?: string | undefined;
42
- }, {
43
- amount: string;
44
- walletAddress: string;
45
- action: "transfer" | "swap";
46
- tokenIn?: string | undefined;
47
- tokenOut?: string | undefined;
48
- toAddress?: string | undefined;
49
- }>;
50
- };
51
- export declare function handleSimulateTransaction(input: SimulateTransactionInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
52
- wouldSucceed: boolean;
53
- expectedOutput: string;
54
- gasEstimate: string;
55
- balanceChanges: {
56
- token: string;
57
- delta: string;
58
- }[];
59
- warnings: string[];
60
- }>>;
1
+ import { z } from "zod";
2
+ export declare const simulateTransactionSchema: z.ZodObject<{
3
+ action: z.ZodEnum<["swap", "transfer"]>;
4
+ tokenIn: z.ZodOptional<z.ZodString>;
5
+ tokenOut: z.ZodOptional<z.ZodString>;
6
+ amount: z.ZodString;
7
+ toAddress: z.ZodOptional<z.ZodString>;
8
+ walletAddress: z.ZodString;
9
+ }, "strip", z.ZodTypeAny, {
10
+ amount: string;
11
+ walletAddress: string;
12
+ action: "transfer" | "swap";
13
+ tokenIn?: string | undefined;
14
+ tokenOut?: string | undefined;
15
+ toAddress?: string | undefined;
16
+ }, {
17
+ amount: string;
18
+ walletAddress: string;
19
+ action: "transfer" | "swap";
20
+ tokenIn?: string | undefined;
21
+ tokenOut?: string | undefined;
22
+ toAddress?: string | undefined;
23
+ }>;
24
+ export type SimulateTransactionInput = z.infer<typeof simulateTransactionSchema>;
25
+ export declare const simulateTransactionTool: {
26
+ name: string;
27
+ description: string;
28
+ inputSchema: z.ZodObject<{
29
+ action: z.ZodEnum<["swap", "transfer"]>;
30
+ tokenIn: z.ZodOptional<z.ZodString>;
31
+ tokenOut: z.ZodOptional<z.ZodString>;
32
+ amount: z.ZodString;
33
+ toAddress: z.ZodOptional<z.ZodString>;
34
+ walletAddress: z.ZodString;
35
+ }, "strip", z.ZodTypeAny, {
36
+ amount: string;
37
+ walletAddress: string;
38
+ action: "transfer" | "swap";
39
+ tokenIn?: string | undefined;
40
+ tokenOut?: string | undefined;
41
+ toAddress?: string | undefined;
42
+ }, {
43
+ amount: string;
44
+ walletAddress: string;
45
+ action: "transfer" | "swap";
46
+ tokenIn?: string | undefined;
47
+ tokenOut?: string | undefined;
48
+ toAddress?: string | undefined;
49
+ }>;
50
+ };
51
+ export declare function handleSimulateTransaction(input: SimulateTransactionInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
52
+ wouldSucceed: boolean;
53
+ expectedOutput: string;
54
+ gasEstimate: string;
55
+ balanceChanges: {
56
+ token: string;
57
+ delta: string;
58
+ }[];
59
+ warnings: string[];
60
+ }>>;
61
61
  //# sourceMappingURL=simulateTransaction.d.ts.map
@@ -1,84 +1,84 @@
1
- // ─── Tool: simulate_transaction ────────────────────────────────────────
2
- import { z } from "zod";
3
- import { publicClient } from "../lib/pharosClient.js";
4
- import { getDodoRoute } from "../lib/dodoApi.js";
5
- import { parseEther, formatEther } from "viem";
6
- import { ok, fail } from "../lib/toolResponse.js";
7
- export const simulateTransactionSchema = z.object({
8
- action: z.enum(["swap", "transfer"]),
9
- tokenIn: z.string().optional(),
10
- tokenOut: z.string().optional(),
11
- amount: z.string(),
12
- toAddress: z.string().optional(),
13
- walletAddress: z.string(),
14
- });
15
- export const simulateTransactionTool = {
16
- name: "simulate_transaction",
17
- description: "Dry run a swap or transfer via eth_call — no gas spent. Returns expected output, gas estimate, and revert reasons.",
18
- inputSchema: simulateTransactionSchema,
19
- };
20
- export async function handleSimulateTransaction(input) {
21
- const warnings = [];
22
- const balanceChanges = [];
23
- try {
24
- if (input.action === "swap") {
25
- if (!input.tokenIn || !input.tokenOut) {
26
- return fail("INVALID_INPUT", "tokenIn and tokenOut required for swap simulation", false, "simulate_transaction");
27
- }
28
- const quote = await getDodoRoute({
29
- fromToken: input.tokenIn,
30
- toToken: input.tokenOut,
31
- amountHuman: input.amount,
32
- walletAddress: input.walletAddress,
33
- });
34
- if (!quote.routeAvailable) {
35
- return fail("NO_ROUTE_AVAILABLE", "No swap route available", true, "simulate_transaction");
36
- }
37
- // Simulate via eth_call
38
- try {
39
- await publicClient.call({
40
- to: quote.to,
41
- data: quote.calldata,
42
- value: BigInt(quote.value),
43
- account: input.walletAddress,
44
- });
45
- }
46
- catch (err) {
47
- const msg = err.message;
48
- if (msg.includes("revert")) {
49
- return fail("SIMULATION_REVERTED", msg, false, "simulate_transaction");
50
- }
51
- warnings.push(`Simulation warning: ${msg}`);
52
- }
53
- balanceChanges.push({ token: input.tokenIn, delta: `-${input.amount}` });
54
- balanceChanges.push({ token: input.tokenOut, delta: `+${quote.amountOut}` });
55
- return ok({ wouldSucceed: true, expectedOutput: quote.amountOut, gasEstimate: quote.gasLimit, balanceChanges, warnings });
56
- }
57
- // Transfer simulation
58
- if (!input.toAddress) {
59
- return fail("INVALID_INPUT", "toAddress required for transfer simulation", false, "simulate_transaction");
60
- }
61
- const amountWei = parseEther(input.amount);
62
- const balance = await publicClient.getBalance({ address: input.walletAddress });
63
- if (balance < amountWei) {
64
- return fail("INSUFFICIENT_TESTNET_BALANCE", `Insufficient balance: have ${formatEther(balance)}, need ${input.amount}`, false, "simulate_transaction");
65
- }
66
- const gasEstimate = await publicClient.estimateGas({
67
- to: input.toAddress,
68
- value: amountWei,
69
- account: input.walletAddress,
70
- });
71
- balanceChanges.push({ token: "PHRS", delta: `-${input.amount}` });
72
- return ok({
73
- wouldSucceed: true,
74
- expectedOutput: input.amount,
75
- gasEstimate: gasEstimate.toString(),
76
- balanceChanges,
77
- warnings,
78
- });
79
- }
80
- catch (err) {
81
- return fail("SIMULATION_FAILED", err.message, true, "simulate_transaction");
82
- }
83
- }
1
+ // ─── Tool: simulate_transaction ────────────────────────────────────────
2
+ import { z } from "zod";
3
+ import { publicClient } from "../lib/pharosClient.js";
4
+ import { getDodoRoute } from "../lib/dodoApi.js";
5
+ import { parseEther, formatEther } from "viem";
6
+ import { ok, fail } from "../lib/toolResponse.js";
7
+ export const simulateTransactionSchema = z.object({
8
+ action: z.enum(["swap", "transfer"]),
9
+ tokenIn: z.string().optional(),
10
+ tokenOut: z.string().optional(),
11
+ amount: z.string(),
12
+ toAddress: z.string().optional(),
13
+ walletAddress: z.string(),
14
+ });
15
+ export const simulateTransactionTool = {
16
+ name: "simulate_transaction",
17
+ description: "Dry run a swap or transfer via eth_call — no gas spent. Returns expected output, gas estimate, and revert reasons.",
18
+ inputSchema: simulateTransactionSchema,
19
+ };
20
+ export async function handleSimulateTransaction(input) {
21
+ const warnings = [];
22
+ const balanceChanges = [];
23
+ try {
24
+ if (input.action === "swap") {
25
+ if (!input.tokenIn || !input.tokenOut) {
26
+ return fail("INVALID_INPUT", "tokenIn and tokenOut required for swap simulation", false, "simulate_transaction");
27
+ }
28
+ const quote = await getDodoRoute({
29
+ fromToken: input.tokenIn,
30
+ toToken: input.tokenOut,
31
+ amountHuman: input.amount,
32
+ walletAddress: input.walletAddress,
33
+ });
34
+ if (!quote.routeAvailable) {
35
+ return fail("NO_ROUTE_AVAILABLE", "No swap route available", true, "simulate_transaction");
36
+ }
37
+ // Simulate via eth_call
38
+ try {
39
+ await publicClient.call({
40
+ to: quote.to,
41
+ data: quote.calldata,
42
+ value: BigInt(quote.value),
43
+ account: input.walletAddress,
44
+ });
45
+ }
46
+ catch (err) {
47
+ const msg = err.message;
48
+ if (msg.includes("revert")) {
49
+ return fail("SIMULATION_REVERTED", msg, false, "simulate_transaction");
50
+ }
51
+ warnings.push(`Simulation warning: ${msg}`);
52
+ }
53
+ balanceChanges.push({ token: input.tokenIn, delta: `-${input.amount}` });
54
+ balanceChanges.push({ token: input.tokenOut, delta: `+${quote.amountOut}` });
55
+ return ok({ wouldSucceed: true, expectedOutput: quote.amountOut, gasEstimate: quote.gasLimit, balanceChanges, warnings });
56
+ }
57
+ // Transfer simulation
58
+ if (!input.toAddress) {
59
+ return fail("INVALID_INPUT", "toAddress required for transfer simulation", false, "simulate_transaction");
60
+ }
61
+ const amountWei = parseEther(input.amount);
62
+ const balance = await publicClient.getBalance({ address: input.walletAddress });
63
+ if (balance < amountWei) {
64
+ return fail("INSUFFICIENT_TESTNET_BALANCE", `Insufficient balance: have ${formatEther(balance)}, need ${input.amount}`, false, "simulate_transaction");
65
+ }
66
+ const gasEstimate = await publicClient.estimateGas({
67
+ to: input.toAddress,
68
+ value: amountWei,
69
+ account: input.walletAddress,
70
+ });
71
+ balanceChanges.push({ token: "PHRS", delta: `-${input.amount}` });
72
+ return ok({
73
+ wouldSucceed: true,
74
+ expectedOutput: input.amount,
75
+ gasEstimate: gasEstimate.toString(),
76
+ balanceChanges,
77
+ warnings,
78
+ });
79
+ }
80
+ catch (err) {
81
+ return fail("SIMULATION_FAILED", err.message, true, "simulate_transaction");
82
+ }
83
+ }
84
84
  //# sourceMappingURL=simulateTransaction.js.map
@@ -1,27 +1,27 @@
1
- import { z } from "zod";
2
- import { type ToolResponse } from "../lib/toolResponse.js";
3
- export declare const tokenRegistryStatusSchema: z.ZodObject<{
4
- token: z.ZodOptional<z.ZodString>;
5
- tokenAddress: z.ZodOptional<z.ZodString>;
6
- }, "strip", z.ZodTypeAny, {
7
- token?: string | undefined;
8
- tokenAddress?: string | undefined;
9
- }, {
10
- token?: string | undefined;
11
- tokenAddress?: string | undefined;
12
- }>;
13
- export type TokenRegistryStatusInput = z.input<typeof tokenRegistryStatusSchema>;
14
- export type TokenRegistryStatusValue = "CANONICAL_TESTNET_TOKEN" | "SKILL_ENGINE_CANONICAL_TOKEN" | "ALTERNATE_SOURCE_TOKEN" | "CUSTOM_NON_REGISTRY" | "UNKNOWN" | "INVALID_ADDRESS";
15
- export declare function classifyTokenRegistryStatus(token: string): {
16
- input: string;
17
- normalizedAddress: any;
18
- symbol: any;
19
- status: TokenRegistryStatusValue;
20
- verificationStatus: any;
21
- docsSource: any;
22
- chainId: number;
23
- environment: string;
24
- isMainnet: boolean;
25
- };
26
- export declare function handleTokenRegistryStatus(raw: TokenRegistryStatusInput): Promise<ToolResponse<unknown>>;
1
+ import { z } from "zod";
2
+ import { type ToolResponse } from "../lib/toolResponse.js";
3
+ export declare const tokenRegistryStatusSchema: z.ZodObject<{
4
+ token: z.ZodOptional<z.ZodString>;
5
+ tokenAddress: z.ZodOptional<z.ZodString>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ token?: string | undefined;
8
+ tokenAddress?: string | undefined;
9
+ }, {
10
+ token?: string | undefined;
11
+ tokenAddress?: string | undefined;
12
+ }>;
13
+ export type TokenRegistryStatusInput = z.input<typeof tokenRegistryStatusSchema>;
14
+ export type TokenRegistryStatusValue = "CANONICAL_TESTNET_TOKEN" | "SKILL_ENGINE_CANONICAL_TOKEN" | "ALTERNATE_SOURCE_TOKEN" | "CUSTOM_NON_REGISTRY" | "UNKNOWN" | "INVALID_ADDRESS";
15
+ export declare function classifyTokenRegistryStatus(token: string): {
16
+ input: string;
17
+ normalizedAddress: any;
18
+ symbol: any;
19
+ status: TokenRegistryStatusValue;
20
+ verificationStatus: any;
21
+ docsSource: any;
22
+ chainId: number;
23
+ environment: string;
24
+ isMainnet: boolean;
25
+ };
26
+ export declare function handleTokenRegistryStatus(raw: TokenRegistryStatusInput): Promise<ToolResponse<unknown>>;
27
27
  //# sourceMappingURL=tokenRegistryStatus.d.ts.map