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.
- package/README.md +174 -63
- package/dist/cli.d.ts +5 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -124
- package/dist/cli.js.map +1 -1
- package/dist/demo.d.ts +1 -1
- package/dist/demo.js +171 -171
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -65
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +65 -65
- package/dist/lib/constants.d.ts +303 -291
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +302 -292
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/dodoApi.d.ts +78 -78
- package/dist/lib/dodoApi.js +196 -196
- package/dist/lib/envLoader.d.ts +2 -0
- package/dist/lib/envLoader.d.ts.map +1 -0
- package/dist/lib/envLoader.js +44 -0
- package/dist/lib/envLoader.js.map +1 -0
- package/dist/lib/http.d.ts +14 -14
- package/dist/lib/http.js +118 -118
- package/dist/lib/pharosClient.d.ts +58 -58
- package/dist/lib/pharosClient.js +63 -63
- package/dist/lib/policy/actionPolicyEngine.d.ts +53 -53
- package/dist/lib/policy/actionPolicyEngine.js +212 -212
- package/dist/lib/riskEngine.d.ts +26 -26
- package/dist/lib/riskEngine.d.ts.map +1 -1
- package/dist/lib/riskEngine.js +288 -283
- package/dist/lib/riskEngine.js.map +1 -1
- package/dist/lib/signer/index.d.ts +24 -24
- package/dist/lib/signer/index.js +88 -88
- package/dist/lib/testDodoLive.d.ts +1 -1
- package/dist/lib/testDodoLive.js +104 -104
- package/dist/lib/testLiveSafehands.d.ts +1 -1
- package/dist/lib/testLiveSafehands.js +92 -92
- package/dist/lib/testRpcLive.d.ts +1 -1
- package/dist/lib/testRpcLive.js +88 -88
- package/dist/lib/testTools.js +397 -398
- package/dist/lib/testX402Live.d.ts +1 -1
- package/dist/lib/testX402Live.js +159 -159
- package/dist/lib/toolResponse.d.ts +25 -25
- package/dist/lib/toolResponse.js +53 -53
- package/dist/lib/wallet/index.d.ts +37 -37
- package/dist/lib/wallet/index.js +128 -128
- package/dist/scripts/checkDeploy.d.ts +1 -1
- package/dist/scripts/checkDeploy.js +24 -24
- package/dist/scripts/deployRegistry.d.ts +1 -1
- package/dist/scripts/deployRegistry.js +100 -100
- package/dist/scripts/testRegistry.d.ts +1 -1
- package/dist/scripts/testRegistry.js +43 -43
- package/dist/tools/approveToken.d.ts +45 -45
- package/dist/tools/approveToken.js +85 -85
- package/dist/tools/assessRisk.d.ts +79 -79
- package/dist/tools/assessRisk.js +104 -104
- package/dist/tools/checkAllowance.d.ts +43 -43
- package/dist/tools/checkAllowance.js +56 -56
- package/dist/tools/checkTokenSecurity.d.ts +46 -46
- package/dist/tools/checkTokenSecurity.js +95 -95
- package/dist/tools/createAgentWallet.d.ts +28 -26
- package/dist/tools/createAgentWallet.d.ts.map +1 -1
- package/dist/tools/createAgentWallet.js +82 -58
- package/dist/tools/createAgentWallet.js.map +1 -1
- package/dist/tools/estimateGas.d.ts +79 -79
- package/dist/tools/estimateGas.js +124 -124
- package/dist/tools/executeSwap.d.ts +61 -61
- package/dist/tools/executeSwap.js +141 -141
- package/dist/tools/explainRisk.d.ts +29 -29
- package/dist/tools/explainRisk.js +32 -32
- package/dist/tools/getAgentWallet.d.ts +21 -21
- package/dist/tools/getAgentWallet.js +27 -27
- package/dist/tools/getAgentWalletBalance.d.ts +11 -11
- package/dist/tools/getAgentWalletBalance.js +70 -70
- package/dist/tools/getExecutionHistory.d.ts +49 -49
- package/dist/tools/getExecutionHistory.js +154 -154
- package/dist/tools/getGasPrice.d.ts +43 -43
- package/dist/tools/getGasPrice.js +59 -59
- package/dist/tools/getPoolInfo.d.ts +75 -75
- package/dist/tools/getPoolInfo.js +137 -137
- package/dist/tools/getTokenPrice.d.ts +113 -113
- package/dist/tools/getTokenPrice.js +117 -117
- package/dist/tools/getTransactionStatus.d.ts +43 -43
- package/dist/tools/getTransactionStatus.js +59 -59
- package/dist/tools/getWalletBalance.d.ts +68 -68
- package/dist/tools/getWalletBalance.js +87 -87
- package/dist/tools/publishRiskScore.d.ts +63 -63
- package/dist/tools/publishRiskScore.js +88 -88
- package/dist/tools/queryRiskRegistry.d.ts +38 -38
- package/dist/tools/queryRiskRegistry.js +55 -55
- package/dist/tools/safehandsPreflightCheck.d.ts +77 -77
- package/dist/tools/safehandsPreflightCheck.js +47 -47
- package/dist/tools/safehandsRiskReport.d.ts +81 -81
- package/dist/tools/safehandsRiskReport.js +28 -28
- package/dist/tools/safehandsSafeExecute.d.ts +20 -20
- package/dist/tools/safehandsSafeExecute.js +81 -81
- package/dist/tools/safehandsWalletHealth.d.ts +14 -14
- package/dist/tools/safehandsWalletHealth.js +103 -103
- package/dist/tools/safehandsX402Preflight.d.ts +26 -26
- package/dist/tools/safehandsX402Preflight.js +65 -65
- package/dist/tools/sendPayment.d.ts +57 -57
- package/dist/tools/sendPayment.js +117 -117
- package/dist/tools/simulateTransaction.d.ts +60 -60
- package/dist/tools/simulateTransaction.js +83 -83
- package/dist/tools/tokenRegistryStatus.d.ts +26 -26
- package/dist/tools/tokenRegistryStatus.js +96 -96
- package/dist/tools/x402PayAndFetch.d.ts +81 -81
- package/dist/tools/x402PayAndFetch.js +152 -152
- package/dist/x402Server.d.ts +1 -1
- package/dist/x402Server.js +300 -252
- package/dist/x402Server.js.map +1 -1
- package/package.json +6 -16
- package/examples/dashboard/index.html +0 -337
- package/examples/pharos-skill-engine/SKILL.safehands.md +0 -85
- package/examples/pharos-skill-engine/assets/safehands/example-actions.json +0 -49
- package/examples/pharos-skill-engine/assets/safehands/policy-defaults.json +0 -11
- package/examples/pharos-skill-engine/references/safehands.md +0 -345
- package/examples/scenario-hack.ts +0 -38
- package/skill/SKILL.md +0 -133
- package/skill/assets/safehands/example-actions.json +0 -49
- package/skill/assets/safehands/policy-defaults.json +0 -11
- package/skill/references/safehands.md +0 -345
|
@@ -1,59 +1,83 @@
|
|
|
1
|
-
// ─── create_agent_wallet ────────────────────────────────────────────────
|
|
2
|
-
// Creates a new managed testnet agent wallet.
|
|
3
|
-
// Private key is AES-256-GCM encrypted before storage, never returned in response.
|
|
4
|
-
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
|
|
7
|
-
import { ok, fail } from "../lib/toolResponse.js";
|
|
8
|
-
import { walletStore, encryptKey, usesPersistentWalletStore, getEffectiveEncryptionKey } from "../lib/wallet/index.js";
|
|
9
|
-
import { CHAIN_ID, PHAROS_ENVIRONMENT, IS_MAINNET } from "../lib/constants.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.
|
|
14
|
-
.
|
|
15
|
-
.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.
|
|
19
|
-
.
|
|
20
|
-
.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
1
|
+
// ─── create_agent_wallet ────────────────────────────────────────────────
|
|
2
|
+
// Creates a new managed testnet agent wallet.
|
|
3
|
+
// Private key is AES-256-GCM encrypted before storage, never returned in response.
|
|
4
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
|
|
7
|
+
import { ok, fail } from "../lib/toolResponse.js";
|
|
8
|
+
import { walletStore, encryptKey, usesPersistentWalletStore, getEffectiveEncryptionKey } from "../lib/wallet/index.js";
|
|
9
|
+
import { CHAIN_ID, PHAROS_ENVIRONMENT, IS_MAINNET, RISK_REGISTRY_ADDRESS, RISK_REGISTRY_ABI } from "../lib/constants.js";
|
|
10
|
+
import { createPharosWalletClientFromAccount } from "../lib/pharosClient.js";
|
|
11
|
+
export const createAgentWalletSchema = z.object({
|
|
12
|
+
agentId: z
|
|
13
|
+
.string()
|
|
14
|
+
.min(1)
|
|
15
|
+
.max(64)
|
|
16
|
+
.describe("Unique identifier for this agent wallet (e.g. 'trading-agent-1')"),
|
|
17
|
+
overwrite: z
|
|
18
|
+
.boolean()
|
|
19
|
+
.optional()
|
|
20
|
+
.default(false)
|
|
21
|
+
.describe("If true, overwrite existing wallet for this agentId"),
|
|
22
|
+
});
|
|
23
|
+
export async function handleCreateAgentWallet(params) {
|
|
24
|
+
const { agentId, overwrite } = params;
|
|
25
|
+
// Check if wallet already exists
|
|
26
|
+
const existing = await walletStore.get(agentId);
|
|
27
|
+
if (existing && !overwrite) {
|
|
28
|
+
return fail("WALLET_ALREADY_EXISTS", `A wallet for agentId '${agentId}' already exists. Use overwrite:true to replace it, or use get_agent_wallet to retrieve it.`, false, "wallet_store");
|
|
29
|
+
}
|
|
30
|
+
if (usesPersistentWalletStore() && !process.env.WALLET_ENCRYPTION_KEY) {
|
|
31
|
+
return fail("WALLET_ENCRYPTION_KEY_REQUIRED", "WALLET_ENCRYPTION_KEY is required when WALLET_STORE_PATH is used. Use in-memory store for local tests or provide a testnet-only encryption key.", false, "wallet_store");
|
|
32
|
+
}
|
|
33
|
+
// Generate new wallet
|
|
34
|
+
const privateKey = generatePrivateKey();
|
|
35
|
+
const account = privateKeyToAccount(privateKey);
|
|
36
|
+
// Encrypt key before storage (AES-256-GCM)
|
|
37
|
+
const encryptedKey = encryptKey(privateKey, getEffectiveEncryptionKey());
|
|
38
|
+
// Store wallet
|
|
39
|
+
await walletStore.set(agentId, {
|
|
40
|
+
agentId,
|
|
41
|
+
address: account.address,
|
|
42
|
+
encryptedKey,
|
|
43
|
+
environment: "atlantic-testnet",
|
|
44
|
+
chainId: 688689,
|
|
45
|
+
isMainnet: false,
|
|
46
|
+
createdAt: new Date().toISOString(),
|
|
47
|
+
});
|
|
48
|
+
// Auto-authorize new wallet in RiskRegistry if deployer key is available
|
|
49
|
+
let riskRegistryAuthorized = false;
|
|
50
|
+
let riskRegistryAuthTxHash = null;
|
|
51
|
+
const deployerKey = process.env.PRIVATE_KEY;
|
|
52
|
+
if (deployerKey && process.env.WRITE_TOOLS_ENABLED === "true") {
|
|
53
|
+
try {
|
|
54
|
+
const deployerAccount = privateKeyToAccount(deployerKey);
|
|
55
|
+
const deployerWallet = createPharosWalletClientFromAccount(deployerAccount);
|
|
56
|
+
const txHash = await deployerWallet.writeContract({
|
|
57
|
+
address: RISK_REGISTRY_ADDRESS,
|
|
58
|
+
abi: RISK_REGISTRY_ABI,
|
|
59
|
+
functionName: "setAuthorizedAgent",
|
|
60
|
+
args: [account.address, true],
|
|
61
|
+
});
|
|
62
|
+
riskRegistryAuthorized = true;
|
|
63
|
+
riskRegistryAuthTxHash = txHash;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Authorization failed — wallet still created, just not authorized for publish
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return ok({
|
|
70
|
+
agentId,
|
|
71
|
+
address: account.address,
|
|
72
|
+
environment: PHAROS_ENVIRONMENT,
|
|
73
|
+
chainId: CHAIN_ID,
|
|
74
|
+
isMainnet: IS_MAINNET,
|
|
75
|
+
isTestnet: true,
|
|
76
|
+
createdAt: new Date().toISOString(),
|
|
77
|
+
warning: "This is a TESTNET wallet only. Never use for mainnet funds. Private key is AES-256-GCM encrypted locally — testnet-grade, not KMS/Vault.",
|
|
78
|
+
instructions: `Fund this wallet with testnet PHRS from https://testnet.pharosnetwork.xyz/ before executing write operations. Set WRITE_TOOLS_ENABLED=true to enable transactions.`,
|
|
79
|
+
riskRegistryAuthorized,
|
|
80
|
+
riskRegistryAuthTxHash,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
59
83
|
//# sourceMappingURL=createAgentWallet.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAgentWallet.js","sourceRoot":"","sources":["../../src/tools/createAgentWallet.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,8CAA8C;AAC9C,mFAAmF;AACnF,2EAA2E;AAE3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAqB,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACvH,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"createAgentWallet.js","sourceRoot":"","sources":["../../src/tools/createAgentWallet.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export declare const estimateGasSchema: 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
|
-
walletAddress: z.ZodString;
|
|
8
|
-
toAddress: z.ZodOptional<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 EstimateGasInput = z.input<typeof estimateGasSchema>;
|
|
25
|
-
export declare const estimateGasTool: {
|
|
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
|
-
walletAddress: z.ZodString;
|
|
34
|
-
toAddress: z.ZodOptional<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 handleEstimateGas(raw: EstimateGasInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
|
|
52
|
-
action: "transfer" | "swap";
|
|
53
|
-
gasEstimate: {
|
|
54
|
-
value: string;
|
|
55
|
-
unit: string;
|
|
56
|
-
};
|
|
57
|
-
gasPrice: {
|
|
58
|
-
value: string;
|
|
59
|
-
unit: string;
|
|
60
|
-
};
|
|
61
|
-
gasCostPHRS: {
|
|
62
|
-
value: string;
|
|
63
|
-
unit: string;
|
|
64
|
-
};
|
|
65
|
-
gasCostUsd: {
|
|
66
|
-
value: string;
|
|
67
|
-
unit: string;
|
|
68
|
-
} | null;
|
|
69
|
-
walletBalance: {
|
|
70
|
-
value: string;
|
|
71
|
-
unit: string;
|
|
72
|
-
};
|
|
73
|
-
isSufficient: boolean;
|
|
74
|
-
priceSourceStatus: string;
|
|
75
|
-
chainId: number;
|
|
76
|
-
environment: string;
|
|
77
|
-
isMainnet: boolean;
|
|
78
|
-
source: string;
|
|
79
|
-
}>>;
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const estimateGasSchema: 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
|
+
walletAddress: z.ZodString;
|
|
8
|
+
toAddress: z.ZodOptional<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 EstimateGasInput = z.input<typeof estimateGasSchema>;
|
|
25
|
+
export declare const estimateGasTool: {
|
|
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
|
+
walletAddress: z.ZodString;
|
|
34
|
+
toAddress: z.ZodOptional<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 handleEstimateGas(raw: EstimateGasInput): Promise<import("../lib/toolResponse.js").ToolFailure | import("../lib/toolResponse.js").ToolSuccess<{
|
|
52
|
+
action: "transfer" | "swap";
|
|
53
|
+
gasEstimate: {
|
|
54
|
+
value: string;
|
|
55
|
+
unit: string;
|
|
56
|
+
};
|
|
57
|
+
gasPrice: {
|
|
58
|
+
value: string;
|
|
59
|
+
unit: string;
|
|
60
|
+
};
|
|
61
|
+
gasCostPHRS: {
|
|
62
|
+
value: string;
|
|
63
|
+
unit: string;
|
|
64
|
+
};
|
|
65
|
+
gasCostUsd: {
|
|
66
|
+
value: string;
|
|
67
|
+
unit: string;
|
|
68
|
+
} | null;
|
|
69
|
+
walletBalance: {
|
|
70
|
+
value: string;
|
|
71
|
+
unit: string;
|
|
72
|
+
};
|
|
73
|
+
isSufficient: boolean;
|
|
74
|
+
priceSourceStatus: string;
|
|
75
|
+
chainId: number;
|
|
76
|
+
environment: string;
|
|
77
|
+
isMainnet: boolean;
|
|
78
|
+
source: string;
|
|
79
|
+
}>>;
|
|
80
80
|
//# sourceMappingURL=estimateGas.d.ts.map
|
|
@@ -1,125 +1,125 @@
|
|
|
1
|
-
// ─── Tool: estimate_gas ────────────────────────────────────────────────
|
|
2
|
-
// Estimates gas cost for a swap or transfer before executing.
|
|
3
|
-
// ────────────────────────────────────────────────────────────────────────
|
|
4
|
-
import { z } from "zod";
|
|
5
|
-
import { publicClient } from "../lib/pharosClient.js";
|
|
6
|
-
import { getDodoRoute, isNativeToken } from "../lib/dodoApi.js";
|
|
7
|
-
import { formatEther, formatGwei, isAddress, parseEther } from "viem";
|
|
8
|
-
import { CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
|
|
9
|
-
import { classifyExternalError, fail, ok } from "../lib/toolResponse.js";
|
|
10
|
-
export const estimateGasSchema = z.object({
|
|
11
|
-
action: z.enum(["swap", "transfer"]).describe("Type of action to estimate gas for"),
|
|
12
|
-
tokenIn: z.string().optional().describe("Token to swap from (for swaps)"),
|
|
13
|
-
tokenOut: z.string().optional().describe("Token to swap to (for swaps)"),
|
|
14
|
-
amount: z.string().describe("Human-readable amount"),
|
|
15
|
-
walletAddress: z.string().describe("Sender wallet address"),
|
|
16
|
-
toAddress: z.string().optional().describe("Recipient address (for transfers)"),
|
|
17
|
-
});
|
|
18
|
-
export const estimateGasTool = {
|
|
19
|
-
name: "estimate_gas",
|
|
20
|
-
description: "Estimate gas cost for a swap or transfer before executing. Returns gas units, cost in PHRS/USD, and whether the wallet has sufficient gas.",
|
|
21
|
-
inputSchema: estimateGasSchema,
|
|
22
|
-
};
|
|
23
|
-
const QUOTE_WALLET = "0x0000000000000000000000000000000000000001";
|
|
24
|
-
export async function handleEstimateGas(raw) {
|
|
25
|
-
const input = estimateGasSchema.parse(raw);
|
|
26
|
-
if (!isAddress(input.walletAddress)) {
|
|
27
|
-
return fail("INVALID_WALLET_ADDRESS", `Invalid wallet address: ${input.walletAddress}`, false, "estimate_gas");
|
|
28
|
-
}
|
|
29
|
-
const walletAddr = input.walletAddress;
|
|
30
|
-
try {
|
|
31
|
-
const gasPrice = await publicClient.getGasPrice();
|
|
32
|
-
const balance = await publicClient.getBalance({ address: walletAddr });
|
|
33
|
-
let gasEstimate;
|
|
34
|
-
if (input.action === "transfer") {
|
|
35
|
-
if (!input.toAddress) {
|
|
36
|
-
return fail("MISSING_TO_ADDRESS", "toAddress is required for transfer gas estimation.", false, "estimate_gas");
|
|
37
|
-
}
|
|
38
|
-
if (!isAddress(input.toAddress)) {
|
|
39
|
-
return fail("INVALID_RECIPIENT_ADDRESS", `Invalid recipient address: ${input.toAddress}`, false, "estimate_gas");
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
gasEstimate = await publicClient.estimateGas({
|
|
43
|
-
to: input.toAddress,
|
|
44
|
-
value: parseEther(input.amount),
|
|
45
|
-
account: walletAddr,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
gasEstimate = 21000n;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
if (!input.tokenIn || !input.tokenOut) {
|
|
54
|
-
return fail("MISSING_SWAP_TOKENS", "tokenIn and tokenOut are required for swap gas estimation.", false, "estimate_gas");
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const quote = await getDodoRoute({
|
|
58
|
-
fromToken: input.tokenIn,
|
|
59
|
-
toToken: input.tokenOut,
|
|
60
|
-
amountHuman: input.amount,
|
|
61
|
-
walletAddress: input.walletAddress,
|
|
62
|
-
});
|
|
63
|
-
if (!quote.routeAvailable) {
|
|
64
|
-
return fail("NO_ROUTE_AVAILABLE", "No swap route available; cannot estimate gas.", true, "dodo_api");
|
|
65
|
-
}
|
|
66
|
-
gasEstimate = BigInt(quote.gasLimit);
|
|
67
|
-
}
|
|
68
|
-
catch (err) {
|
|
69
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
70
|
-
if (message.includes("DODO_API_AUTH_REQUIRED")) {
|
|
71
|
-
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");
|
|
72
|
-
}
|
|
73
|
-
if (message.includes("DODO_API_RATE_LIMITED")) {
|
|
74
|
-
return fail("DODO_API_RATE_LIMITED", message, true, "dodo_api");
|
|
75
|
-
}
|
|
76
|
-
return classifyExternalError("dodo_api", err);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
const gasCostWei = gasEstimate * gasPrice;
|
|
80
|
-
const gasCostPHRS = formatEther(gasCostWei);
|
|
81
|
-
let gasCostUsd = null;
|
|
82
|
-
let priceSourceStatus = "unavailable";
|
|
83
|
-
try {
|
|
84
|
-
const priceQuote = await getDodoRoute({
|
|
85
|
-
fromToken: "PHRS",
|
|
86
|
-
toToken: "USDC",
|
|
87
|
-
amountHuman: "1",
|
|
88
|
-
walletAddress: QUOTE_WALLET,
|
|
89
|
-
});
|
|
90
|
-
if (priceQuote.routeAvailable) {
|
|
91
|
-
gasCostUsd = (parseFloat(gasCostPHRS) * parseFloat(priceQuote.amountOut)).toFixed(6);
|
|
92
|
-
priceSourceStatus = "ok";
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
priceSourceStatus = "no_route_available";
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
priceSourceStatus = "unavailable";
|
|
100
|
-
}
|
|
101
|
-
let totalNeeded = gasCostWei;
|
|
102
|
-
if (input.action === "transfer" || (input.action === "swap" && isNativeToken(input.tokenIn || ""))) {
|
|
103
|
-
totalNeeded += parseEther(input.amount);
|
|
104
|
-
}
|
|
105
|
-
const isSufficient = balance >= totalNeeded;
|
|
106
|
-
return ok({
|
|
107
|
-
action: input.action,
|
|
108
|
-
gasEstimate: { value: gasEstimate.toString(), unit: "gas" },
|
|
109
|
-
gasPrice: { value: formatGwei(gasPrice), unit: "gwei" },
|
|
110
|
-
gasCostPHRS: { value: gasCostPHRS, unit: "PHRS" },
|
|
111
|
-
gasCostUsd: gasCostUsd ? { value: gasCostUsd, unit: "USD" } : null,
|
|
112
|
-
walletBalance: { value: formatEther(balance), unit: "PHRS" },
|
|
113
|
-
isSufficient,
|
|
114
|
-
priceSourceStatus,
|
|
115
|
-
chainId: CHAIN_ID,
|
|
116
|
-
environment: PHAROS_ENVIRONMENT,
|
|
117
|
-
isMainnet: false,
|
|
118
|
-
source: "pharos_rpc",
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
catch (err) {
|
|
122
|
-
return classifyExternalError("pharos_rpc", err);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
1
|
+
// ─── Tool: estimate_gas ────────────────────────────────────────────────
|
|
2
|
+
// Estimates gas cost for a swap or transfer before executing.
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { publicClient } from "../lib/pharosClient.js";
|
|
6
|
+
import { getDodoRoute, isNativeToken } from "../lib/dodoApi.js";
|
|
7
|
+
import { formatEther, formatGwei, isAddress, parseEther } from "viem";
|
|
8
|
+
import { CHAIN_ID, PHAROS_ENVIRONMENT } from "../lib/constants.js";
|
|
9
|
+
import { classifyExternalError, fail, ok } from "../lib/toolResponse.js";
|
|
10
|
+
export const estimateGasSchema = z.object({
|
|
11
|
+
action: z.enum(["swap", "transfer"]).describe("Type of action to estimate gas for"),
|
|
12
|
+
tokenIn: z.string().optional().describe("Token to swap from (for swaps)"),
|
|
13
|
+
tokenOut: z.string().optional().describe("Token to swap to (for swaps)"),
|
|
14
|
+
amount: z.string().describe("Human-readable amount"),
|
|
15
|
+
walletAddress: z.string().describe("Sender wallet address"),
|
|
16
|
+
toAddress: z.string().optional().describe("Recipient address (for transfers)"),
|
|
17
|
+
});
|
|
18
|
+
export const estimateGasTool = {
|
|
19
|
+
name: "estimate_gas",
|
|
20
|
+
description: "Estimate gas cost for a swap or transfer before executing. Returns gas units, cost in PHRS/USD, and whether the wallet has sufficient gas.",
|
|
21
|
+
inputSchema: estimateGasSchema,
|
|
22
|
+
};
|
|
23
|
+
const QUOTE_WALLET = "0x0000000000000000000000000000000000000001";
|
|
24
|
+
export async function handleEstimateGas(raw) {
|
|
25
|
+
const input = estimateGasSchema.parse(raw);
|
|
26
|
+
if (!isAddress(input.walletAddress)) {
|
|
27
|
+
return fail("INVALID_WALLET_ADDRESS", `Invalid wallet address: ${input.walletAddress}`, false, "estimate_gas");
|
|
28
|
+
}
|
|
29
|
+
const walletAddr = input.walletAddress;
|
|
30
|
+
try {
|
|
31
|
+
const gasPrice = await publicClient.getGasPrice();
|
|
32
|
+
const balance = await publicClient.getBalance({ address: walletAddr });
|
|
33
|
+
let gasEstimate;
|
|
34
|
+
if (input.action === "transfer") {
|
|
35
|
+
if (!input.toAddress) {
|
|
36
|
+
return fail("MISSING_TO_ADDRESS", "toAddress is required for transfer gas estimation.", false, "estimate_gas");
|
|
37
|
+
}
|
|
38
|
+
if (!isAddress(input.toAddress)) {
|
|
39
|
+
return fail("INVALID_RECIPIENT_ADDRESS", `Invalid recipient address: ${input.toAddress}`, false, "estimate_gas");
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
gasEstimate = await publicClient.estimateGas({
|
|
43
|
+
to: input.toAddress,
|
|
44
|
+
value: parseEther(input.amount),
|
|
45
|
+
account: walletAddr,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
gasEstimate = 21000n;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
if (!input.tokenIn || !input.tokenOut) {
|
|
54
|
+
return fail("MISSING_SWAP_TOKENS", "tokenIn and tokenOut are required for swap gas estimation.", false, "estimate_gas");
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const quote = await getDodoRoute({
|
|
58
|
+
fromToken: input.tokenIn,
|
|
59
|
+
toToken: input.tokenOut,
|
|
60
|
+
amountHuman: input.amount,
|
|
61
|
+
walletAddress: input.walletAddress,
|
|
62
|
+
});
|
|
63
|
+
if (!quote.routeAvailable) {
|
|
64
|
+
return fail("NO_ROUTE_AVAILABLE", "No swap route available; cannot estimate gas.", true, "dodo_api");
|
|
65
|
+
}
|
|
66
|
+
gasEstimate = BigInt(quote.gasLimit);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
70
|
+
if (message.includes("DODO_API_AUTH_REQUIRED")) {
|
|
71
|
+
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");
|
|
72
|
+
}
|
|
73
|
+
if (message.includes("DODO_API_RATE_LIMITED")) {
|
|
74
|
+
return fail("DODO_API_RATE_LIMITED", message, true, "dodo_api");
|
|
75
|
+
}
|
|
76
|
+
return classifyExternalError("dodo_api", err);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const gasCostWei = gasEstimate * gasPrice;
|
|
80
|
+
const gasCostPHRS = formatEther(gasCostWei);
|
|
81
|
+
let gasCostUsd = null;
|
|
82
|
+
let priceSourceStatus = "unavailable";
|
|
83
|
+
try {
|
|
84
|
+
const priceQuote = await getDodoRoute({
|
|
85
|
+
fromToken: "PHRS",
|
|
86
|
+
toToken: "USDC",
|
|
87
|
+
amountHuman: "1",
|
|
88
|
+
walletAddress: QUOTE_WALLET,
|
|
89
|
+
});
|
|
90
|
+
if (priceQuote.routeAvailable) {
|
|
91
|
+
gasCostUsd = (parseFloat(gasCostPHRS) * parseFloat(priceQuote.amountOut)).toFixed(6);
|
|
92
|
+
priceSourceStatus = "ok";
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
priceSourceStatus = "no_route_available";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
priceSourceStatus = "unavailable";
|
|
100
|
+
}
|
|
101
|
+
let totalNeeded = gasCostWei;
|
|
102
|
+
if (input.action === "transfer" || (input.action === "swap" && isNativeToken(input.tokenIn || ""))) {
|
|
103
|
+
totalNeeded += parseEther(input.amount);
|
|
104
|
+
}
|
|
105
|
+
const isSufficient = balance >= totalNeeded;
|
|
106
|
+
return ok({
|
|
107
|
+
action: input.action,
|
|
108
|
+
gasEstimate: { value: gasEstimate.toString(), unit: "gas" },
|
|
109
|
+
gasPrice: { value: formatGwei(gasPrice), unit: "gwei" },
|
|
110
|
+
gasCostPHRS: { value: gasCostPHRS, unit: "PHRS" },
|
|
111
|
+
gasCostUsd: gasCostUsd ? { value: gasCostUsd, unit: "USD" } : null,
|
|
112
|
+
walletBalance: { value: formatEther(balance), unit: "PHRS" },
|
|
113
|
+
isSufficient,
|
|
114
|
+
priceSourceStatus,
|
|
115
|
+
chainId: CHAIN_ID,
|
|
116
|
+
environment: PHAROS_ENVIRONMENT,
|
|
117
|
+
isMainnet: false,
|
|
118
|
+
source: "pharos_rpc",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
return classifyExternalError("pharos_rpc", err);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
125
|
//# sourceMappingURL=estimateGas.js.map
|