@smartagentkit/langchain 0.1.1 → 0.1.3

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/dist/index.d.mts CHANGED
@@ -16,6 +16,11 @@ import { ISmartAgentKitClient } from '@smartagentkit/sdk';
16
16
  * @param client - An initialized SmartAgentKitClient
17
17
  * @param walletAddress - The smart wallet address to operate on
18
18
  * @param sessionKey - Optional session key private key for signing transactions
19
+ * @param options - Optional configuration
20
+ * @param options.confirmBeforeExecute - Async callback invoked before executing any
21
+ * transaction (send_transaction or send_batch_transaction). Receives the transaction
22
+ * parameters and must return `true` to proceed or `false` to reject the transaction.
23
+ * Useful for adding human-in-the-loop approval, logging, or rate-limiting.
19
24
  * @returns Array of DynamicStructuredTool instances for use with LangChain agents
20
25
  *
21
26
  * @example
@@ -23,10 +28,21 @@ import { ISmartAgentKitClient } from '@smartagentkit/sdk';
23
28
  * import { createSmartAgentKitTools } from "@smartagentkit/langchain";
24
29
  * import { createReactAgent } from "@langchain/langgraph/prebuilt";
25
30
  *
26
- * const tools = createSmartAgentKitTools(client, wallet.address, sessionKey);
31
+ * const tools = createSmartAgentKitTools(client, wallet.address, sessionKey, {
32
+ * confirmBeforeExecute: async ({ target, value, data }) => {
33
+ * console.log(`Transaction to ${target} for ${value ?? "0"} wei`);
34
+ * return true; // or false to reject
35
+ * },
36
+ * });
27
37
  * const agent = createReactAgent({ llm: chatModel, tools });
28
38
  * ```
29
39
  */
30
- declare function createSmartAgentKitTools(client: ISmartAgentKitClient, walletAddress: string, sessionKey?: string): DynamicStructuredTool[];
40
+ declare function createSmartAgentKitTools(client: ISmartAgentKitClient, walletAddress: string, sessionKey?: string, options?: {
41
+ confirmBeforeExecute?: (params: {
42
+ target: string;
43
+ value?: string;
44
+ data?: string;
45
+ }) => Promise<boolean>;
46
+ }): DynamicStructuredTool[];
31
47
 
32
48
  export { createSmartAgentKitTools };
package/dist/index.d.ts CHANGED
@@ -16,6 +16,11 @@ import { ISmartAgentKitClient } from '@smartagentkit/sdk';
16
16
  * @param client - An initialized SmartAgentKitClient
17
17
  * @param walletAddress - The smart wallet address to operate on
18
18
  * @param sessionKey - Optional session key private key for signing transactions
19
+ * @param options - Optional configuration
20
+ * @param options.confirmBeforeExecute - Async callback invoked before executing any
21
+ * transaction (send_transaction or send_batch_transaction). Receives the transaction
22
+ * parameters and must return `true` to proceed or `false` to reject the transaction.
23
+ * Useful for adding human-in-the-loop approval, logging, or rate-limiting.
19
24
  * @returns Array of DynamicStructuredTool instances for use with LangChain agents
20
25
  *
21
26
  * @example
@@ -23,10 +28,21 @@ import { ISmartAgentKitClient } from '@smartagentkit/sdk';
23
28
  * import { createSmartAgentKitTools } from "@smartagentkit/langchain";
24
29
  * import { createReactAgent } from "@langchain/langgraph/prebuilt";
25
30
  *
26
- * const tools = createSmartAgentKitTools(client, wallet.address, sessionKey);
31
+ * const tools = createSmartAgentKitTools(client, wallet.address, sessionKey, {
32
+ * confirmBeforeExecute: async ({ target, value, data }) => {
33
+ * console.log(`Transaction to ${target} for ${value ?? "0"} wei`);
34
+ * return true; // or false to reject
35
+ * },
36
+ * });
27
37
  * const agent = createReactAgent({ llm: chatModel, tools });
28
38
  * ```
29
39
  */
30
- declare function createSmartAgentKitTools(client: ISmartAgentKitClient, walletAddress: string, sessionKey?: string): DynamicStructuredTool[];
40
+ declare function createSmartAgentKitTools(client: ISmartAgentKitClient, walletAddress: string, sessionKey?: string, options?: {
41
+ confirmBeforeExecute?: (params: {
42
+ target: string;
43
+ value?: string;
44
+ data?: string;
45
+ }) => Promise<boolean>;
46
+ }): DynamicStructuredTool[];
31
47
 
32
48
  export { createSmartAgentKitTools };
package/dist/index.js CHANGED
@@ -27,10 +27,11 @@ module.exports = __toCommonJS(index_exports);
27
27
  // src/tools.ts
28
28
  var import_tools = require("@langchain/core/tools");
29
29
  var import_zod = require("zod");
30
+ var import_viem = require("viem");
30
31
  var addressSchema = import_zod.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "Must be a 0x-prefixed 20-byte hex address");
31
32
  var weiValueSchema = import_zod.z.string().regex(/^\d+$/, "Must be a non-negative integer string (wei)");
32
33
  var calldataSchema = import_zod.z.string().regex(/^0x([0-9a-fA-F]{2})*$/, "Must be 0x-prefixed hex calldata (even length)");
33
- function createSmartAgentKitTools(client, walletAddress, sessionKey) {
34
+ function createSmartAgentKitTools(client, walletAddress, sessionKey, options) {
34
35
  const address = walletAddress;
35
36
  const checkWalletBalance = new import_tools.DynamicStructuredTool({
36
37
  name: "check_wallet_balance",
@@ -39,10 +40,10 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
39
40
  func: async () => {
40
41
  try {
41
42
  const balances = await client.getBalances(address);
42
- const ethBalance = Number(balances.eth) / 1e18;
43
+ const ethBalance = (0, import_viem.formatEther)(balances.eth);
43
44
  return JSON.stringify({
44
45
  wallet: walletAddress,
45
- eth: ethBalance.toString(),
46
+ eth: ethBalance,
46
47
  ethWei: balances.eth.toString()
47
48
  });
48
49
  } catch (error) {
@@ -54,7 +55,7 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
54
55
  });
55
56
  const checkSpendingAllowance = new import_tools.DynamicStructuredTool({
56
57
  name: "check_spending_allowance",
57
- description: 'Check how much spending allowance remains for a token on the wallet. The wallet has policy-enforced spending limits per token per time window. Use this to verify you can spend a certain amount before sending a transaction. Use "0x0000000000000000000000000000000000000000" for native ETH.',
58
+ description: `Check how much spending allowance remains for a token on the wallet. The wallet has policy-enforced spending limits per token per time window. Use this to verify you can spend a certain amount before sending a transaction. Use "0x0000000000000000000000000000000000000000" for native ETH. The 'remaining' field assumes 18 decimals (ETH). For non-ETH tokens, use the 'remainingWei' field and divide by the token's actual decimals.`,
58
59
  schema: import_zod.z.object({
59
60
  token: addressSchema.describe(
60
61
  "Token contract address. Use 0x0000000000000000000000000000000000000000 for native ETH."
@@ -66,12 +67,12 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
66
67
  address,
67
68
  token
68
69
  );
69
- const remainingEth = Number(remaining) / 1e18;
70
+ const remainingFormatted = (0, import_viem.formatEther)(remaining);
70
71
  return JSON.stringify({
71
72
  wallet: walletAddress,
72
73
  token,
73
74
  remainingWei: remaining.toString(),
74
- remaining: remainingEth.toString()
75
+ remaining: remainingFormatted
75
76
  });
76
77
  } catch (error) {
77
78
  return JSON.stringify({
@@ -96,6 +97,19 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
96
97
  }),
97
98
  func: async ({ target, value, data }) => {
98
99
  try {
100
+ if (options?.confirmBeforeExecute) {
101
+ const confirmed = await options.confirmBeforeExecute({
102
+ target,
103
+ value,
104
+ data
105
+ });
106
+ if (!confirmed) {
107
+ return JSON.stringify({
108
+ success: false,
109
+ error: "Transaction rejected by confirmation callback"
110
+ });
111
+ }
112
+ }
99
113
  const wallet = {
100
114
  address,
101
115
  owner: address,
@@ -134,12 +148,27 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
134
148
  "Target contract address (0x-prefixed 20-byte hex)"
135
149
  ),
136
150
  value: weiValueSchema.optional().describe("ETH value in wei (as string). Defaults to '0'."),
137
- data: import_zod.z.string().optional().describe("Calldata (0x-prefixed hex). Defaults to '0x'.")
151
+ data: calldataSchema.optional().describe("Calldata (0x-prefixed hex). Defaults to '0x'.")
138
152
  })
139
153
  ).min(1).describe("Array of calls to execute atomically")
140
154
  }),
141
155
  func: async ({ calls }) => {
142
156
  try {
157
+ if (options?.confirmBeforeExecute) {
158
+ for (const call of calls) {
159
+ const confirmed = await options.confirmBeforeExecute({
160
+ target: call.target,
161
+ value: call.value,
162
+ data: call.data
163
+ });
164
+ if (!confirmed) {
165
+ return JSON.stringify({
166
+ success: false,
167
+ error: "Transaction rejected by confirmation callback"
168
+ });
169
+ }
170
+ }
171
+ }
143
172
  const wallet = {
144
173
  address,
145
174
  owner: address,
@@ -200,4 +229,3 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
200
229
  0 && (module.exports = {
201
230
  createSmartAgentKitTools
202
231
  });
203
- //# sourceMappingURL=index.js.map
package/dist/index.mjs CHANGED
@@ -1,10 +1,11 @@
1
1
  // src/tools.ts
2
2
  import { DynamicStructuredTool } from "@langchain/core/tools";
3
3
  import { z } from "zod";
4
+ import { formatEther } from "viem";
4
5
  var addressSchema = z.string().regex(/^0x[0-9a-fA-F]{40}$/, "Must be a 0x-prefixed 20-byte hex address");
5
6
  var weiValueSchema = z.string().regex(/^\d+$/, "Must be a non-negative integer string (wei)");
6
7
  var calldataSchema = z.string().regex(/^0x([0-9a-fA-F]{2})*$/, "Must be 0x-prefixed hex calldata (even length)");
7
- function createSmartAgentKitTools(client, walletAddress, sessionKey) {
8
+ function createSmartAgentKitTools(client, walletAddress, sessionKey, options) {
8
9
  const address = walletAddress;
9
10
  const checkWalletBalance = new DynamicStructuredTool({
10
11
  name: "check_wallet_balance",
@@ -13,10 +14,10 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
13
14
  func: async () => {
14
15
  try {
15
16
  const balances = await client.getBalances(address);
16
- const ethBalance = Number(balances.eth) / 1e18;
17
+ const ethBalance = formatEther(balances.eth);
17
18
  return JSON.stringify({
18
19
  wallet: walletAddress,
19
- eth: ethBalance.toString(),
20
+ eth: ethBalance,
20
21
  ethWei: balances.eth.toString()
21
22
  });
22
23
  } catch (error) {
@@ -28,7 +29,7 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
28
29
  });
29
30
  const checkSpendingAllowance = new DynamicStructuredTool({
30
31
  name: "check_spending_allowance",
31
- description: 'Check how much spending allowance remains for a token on the wallet. The wallet has policy-enforced spending limits per token per time window. Use this to verify you can spend a certain amount before sending a transaction. Use "0x0000000000000000000000000000000000000000" for native ETH.',
32
+ description: `Check how much spending allowance remains for a token on the wallet. The wallet has policy-enforced spending limits per token per time window. Use this to verify you can spend a certain amount before sending a transaction. Use "0x0000000000000000000000000000000000000000" for native ETH. The 'remaining' field assumes 18 decimals (ETH). For non-ETH tokens, use the 'remainingWei' field and divide by the token's actual decimals.`,
32
33
  schema: z.object({
33
34
  token: addressSchema.describe(
34
35
  "Token contract address. Use 0x0000000000000000000000000000000000000000 for native ETH."
@@ -40,12 +41,12 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
40
41
  address,
41
42
  token
42
43
  );
43
- const remainingEth = Number(remaining) / 1e18;
44
+ const remainingFormatted = formatEther(remaining);
44
45
  return JSON.stringify({
45
46
  wallet: walletAddress,
46
47
  token,
47
48
  remainingWei: remaining.toString(),
48
- remaining: remainingEth.toString()
49
+ remaining: remainingFormatted
49
50
  });
50
51
  } catch (error) {
51
52
  return JSON.stringify({
@@ -70,6 +71,19 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
70
71
  }),
71
72
  func: async ({ target, value, data }) => {
72
73
  try {
74
+ if (options?.confirmBeforeExecute) {
75
+ const confirmed = await options.confirmBeforeExecute({
76
+ target,
77
+ value,
78
+ data
79
+ });
80
+ if (!confirmed) {
81
+ return JSON.stringify({
82
+ success: false,
83
+ error: "Transaction rejected by confirmation callback"
84
+ });
85
+ }
86
+ }
73
87
  const wallet = {
74
88
  address,
75
89
  owner: address,
@@ -108,12 +122,27 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
108
122
  "Target contract address (0x-prefixed 20-byte hex)"
109
123
  ),
110
124
  value: weiValueSchema.optional().describe("ETH value in wei (as string). Defaults to '0'."),
111
- data: z.string().optional().describe("Calldata (0x-prefixed hex). Defaults to '0x'.")
125
+ data: calldataSchema.optional().describe("Calldata (0x-prefixed hex). Defaults to '0x'.")
112
126
  })
113
127
  ).min(1).describe("Array of calls to execute atomically")
114
128
  }),
115
129
  func: async ({ calls }) => {
116
130
  try {
131
+ if (options?.confirmBeforeExecute) {
132
+ for (const call of calls) {
133
+ const confirmed = await options.confirmBeforeExecute({
134
+ target: call.target,
135
+ value: call.value,
136
+ data: call.data
137
+ });
138
+ if (!confirmed) {
139
+ return JSON.stringify({
140
+ success: false,
141
+ error: "Transaction rejected by confirmation callback"
142
+ });
143
+ }
144
+ }
145
+ }
117
146
  const wallet = {
118
147
  address,
119
148
  owner: address,
@@ -173,4 +202,3 @@ function createSmartAgentKitTools(client, walletAddress, sessionKey) {
173
202
  export {
174
203
  createSmartAgentKitTools
175
204
  };
176
- //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartagentkit/langchain",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "LangChain integration for SmartAgentKit — AI agent smart wallet tools",
5
5
  "license": "MIT",
6
6
  "author": "SmartAgentKit Contributors",
@@ -40,8 +40,9 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
+ "viem": "^2.46.0",
43
44
  "zod": "^3.24.0",
44
- "@smartagentkit/sdk": "0.1.1"
45
+ "@smartagentkit/sdk": "0.1.3"
45
46
  },
46
47
  "peerDependencies": {
47
48
  "@langchain/core": ">=0.3.0"
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/tools.ts"],"sourcesContent":["export { createSmartAgentKitTools } from \"./tools.js\";\n","import { DynamicStructuredTool } from \"@langchain/core/tools\";\nimport { z } from \"zod\";\nimport type { ISmartAgentKitClient } from \"@smartagentkit/sdk\";\n\n// Reusable Zod pattern for 0x-prefixed Ethereum addresses (20 bytes)\nconst addressSchema = z\n .string()\n .regex(/^0x[0-9a-fA-F]{40}$/, \"Must be a 0x-prefixed 20-byte hex address\");\n\n// Reusable Zod pattern for non-negative integer strings (wei values)\nconst weiValueSchema = z\n .string()\n .regex(/^\\d+$/, \"Must be a non-negative integer string (wei)\");\n\n// Reusable Zod pattern for 0x-prefixed hex calldata (even-length)\nconst calldataSchema = z\n .string()\n .regex(/^0x([0-9a-fA-F]{2})*$/, \"Must be 0x-prefixed hex calldata (even length)\");\n\n/**\n * Creates LangChain tools for interacting with a SmartAgentKit wallet.\n *\n * Returns 5 tools that an LLM agent can use to manage and transact\n * from a policy-governed smart wallet:\n *\n * - **check_wallet_balance** — Get ETH balance\n * - **check_spending_allowance** — Query remaining spending limit for a token\n * - **send_transaction** — Execute an on-chain transaction\n * - **send_batch_transaction** — Execute multiple calls atomically\n * - **check_wallet_status** — Check if wallet is paused\n *\n * @param client - An initialized SmartAgentKitClient\n * @param walletAddress - The smart wallet address to operate on\n * @param sessionKey - Optional session key private key for signing transactions\n * @returns Array of DynamicStructuredTool instances for use with LangChain agents\n *\n * @example\n * ```ts\n * import { createSmartAgentKitTools } from \"@smartagentkit/langchain\";\n * import { createReactAgent } from \"@langchain/langgraph/prebuilt\";\n *\n * const tools = createSmartAgentKitTools(client, wallet.address, sessionKey);\n * const agent = createReactAgent({ llm: chatModel, tools });\n * ```\n */\nexport function createSmartAgentKitTools(\n client: ISmartAgentKitClient,\n walletAddress: string,\n sessionKey?: string,\n): DynamicStructuredTool[] {\n const address = walletAddress as `0x${string}`;\n\n // ─── check_wallet_balance ─────────────────────────────────────\n\n const checkWalletBalance = new DynamicStructuredTool({\n name: \"check_wallet_balance\",\n description:\n \"Check the ETH balance of the agent's smart wallet. \" +\n \"Returns the balance in ETH (assuming 18 decimals). \" +\n \"The raw wei value is also returned for precision. \" +\n \"Use this before sending transactions to ensure sufficient funds.\",\n schema: z.object({}),\n func: async () => {\n try {\n const balances = await client.getBalances(address);\n // Note: Division by 1e18 assumes 18 decimals (correct for native ETH).\n // For ERC-20 tokens, use the raw wei value and the token's actual decimals.\n const ethBalance = Number(balances.eth) / 1e18;\n return JSON.stringify({\n wallet: walletAddress,\n eth: ethBalance.toString(),\n ethWei: balances.eth.toString(),\n });\n } catch (error) {\n return JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── check_spending_allowance ────────────────────────────────\n\n const checkSpendingAllowance = new DynamicStructuredTool({\n name: \"check_spending_allowance\",\n description:\n \"Check how much spending allowance remains for a token on the wallet. \" +\n \"The wallet has policy-enforced spending limits per token per time window. \" +\n \"Use this to verify you can spend a certain amount before sending a transaction. \" +\n 'Use \"0x0000000000000000000000000000000000000000\" for native ETH.',\n schema: z.object({\n token: addressSchema.describe(\n \"Token contract address. Use 0x0000000000000000000000000000000000000000 for native ETH.\",\n ),\n }),\n func: async ({ token }) => {\n try {\n const remaining = await client.getRemainingAllowance(\n address,\n token as `0x${string}`,\n );\n // Note: Division by 1e18 assumes 18 decimals (correct for native ETH).\n // For tokens with different decimals (e.g., USDC = 6), use remainingWei\n // and divide by the token's actual decimal factor.\n const remainingEth = Number(remaining) / 1e18;\n return JSON.stringify({\n wallet: walletAddress,\n token,\n remainingWei: remaining.toString(),\n remaining: remainingEth.toString(),\n });\n } catch (error) {\n return JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── send_transaction ─────────────────────────────────────────\n\n const sendTransaction = new DynamicStructuredTool({\n name: \"send_transaction\",\n description:\n \"Send a transaction from the agent's smart wallet. \" +\n \"The transaction is executed as a UserOperation through ERC-4337 \" +\n \"and is subject to the wallet's policy constraints (spending limits, \" +\n \"allowlist, pause state). All values are in wei (1 ETH = 1e18 wei). \" +\n \"Returns the transaction hash on success.\",\n schema: z.object({\n target: addressSchema.describe(\n \"Target contract address to call (0x-prefixed 20-byte hex)\",\n ),\n value: weiValueSchema\n .optional()\n .describe(\n \"ETH value to send in wei (as string). Defaults to '0'. Example: '1000000000000000' for 0.001 ETH.\",\n ),\n data: calldataSchema\n .optional()\n .describe(\n \"Calldata for the transaction (0x-prefixed hex). Defaults to '0x' for simple ETH transfer.\",\n ),\n }),\n func: async ({ target, value, data }) => {\n try {\n const wallet = {\n address,\n owner: address, // Resolved from connected wallet\n chain: {} as never, // Not used in execute\n isDeployed: true,\n policies: [],\n sessions: [],\n };\n\n const txHash = await client.execute(wallet, {\n target: target as `0x${string}`,\n value: value ? BigInt(value) : 0n,\n data: (data as `0x${string}`) ?? \"0x\",\n sessionKey: sessionKey as `0x${string}` | undefined,\n });\n\n return JSON.stringify({\n success: true,\n transactionHash: txHash,\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── send_batch_transaction ───────────────────────────────────\n\n const sendBatchTransaction = new DynamicStructuredTool({\n name: \"send_batch_transaction\",\n description:\n \"Send multiple transactions atomically from the agent's smart wallet. \" +\n \"All calls are bundled into a single UserOperation and either all succeed or all revert. \" +\n \"Useful for approve+swap, multi-transfer, or any multi-step operation. \" +\n \"Subject to the wallet's policy constraints. All values are in wei.\",\n schema: z.object({\n calls: z\n .array(\n z.object({\n target: addressSchema.describe(\n \"Target contract address (0x-prefixed 20-byte hex)\",\n ),\n value: weiValueSchema\n .optional()\n .describe(\"ETH value in wei (as string). Defaults to '0'.\"),\n data: z\n .string()\n .optional()\n .describe(\"Calldata (0x-prefixed hex). Defaults to '0x'.\"),\n }),\n )\n .min(1)\n .describe(\"Array of calls to execute atomically\"),\n }),\n func: async ({ calls }) => {\n try {\n const wallet = {\n address,\n owner: address,\n chain: {} as never,\n isDeployed: true,\n policies: [],\n sessions: [],\n };\n\n const txHash = await client.executeBatch(wallet, {\n calls: calls.map((c) => ({\n target: c.target as `0x${string}`,\n value: c.value ? BigInt(c.value) : 0n,\n data: (c.data as `0x${string}`) ?? \"0x\",\n })),\n sessionKey: sessionKey as `0x${string}` | undefined,\n });\n\n return JSON.stringify({\n success: true,\n transactionHash: txHash,\n callCount: calls.length,\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── check_wallet_status ─────────────────────────────────────\n\n const checkWalletStatus = new DynamicStructuredTool({\n name: \"check_wallet_status\",\n description:\n \"Check if the agent's smart wallet is currently paused. \" +\n \"A paused wallet cannot execute any transactions. \" +\n \"The guardian can pause the wallet in emergencies.\",\n schema: z.object({}),\n func: async () => {\n try {\n const paused = await client.isPaused(address);\n return JSON.stringify({\n wallet: walletAddress,\n paused,\n status: paused ? \"paused\" : \"active\",\n });\n } catch (error) {\n return JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n return [\n checkWalletBalance,\n checkSpendingAllowance,\n sendTransaction,\n sendBatchTransaction,\n checkWalletStatus,\n ];\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/tools.ts"],"sourcesContent":["import { DynamicStructuredTool } from \"@langchain/core/tools\";\nimport { z } from \"zod\";\nimport type { ISmartAgentKitClient } from \"@smartagentkit/sdk\";\n\n// Reusable Zod pattern for 0x-prefixed Ethereum addresses (20 bytes)\nconst addressSchema = z\n .string()\n .regex(/^0x[0-9a-fA-F]{40}$/, \"Must be a 0x-prefixed 20-byte hex address\");\n\n// Reusable Zod pattern for non-negative integer strings (wei values)\nconst weiValueSchema = z\n .string()\n .regex(/^\\d+$/, \"Must be a non-negative integer string (wei)\");\n\n// Reusable Zod pattern for 0x-prefixed hex calldata (even-length)\nconst calldataSchema = z\n .string()\n .regex(/^0x([0-9a-fA-F]{2})*$/, \"Must be 0x-prefixed hex calldata (even length)\");\n\n/**\n * Creates LangChain tools for interacting with a SmartAgentKit wallet.\n *\n * Returns 5 tools that an LLM agent can use to manage and transact\n * from a policy-governed smart wallet:\n *\n * - **check_wallet_balance** — Get ETH balance\n * - **check_spending_allowance** — Query remaining spending limit for a token\n * - **send_transaction** — Execute an on-chain transaction\n * - **send_batch_transaction** — Execute multiple calls atomically\n * - **check_wallet_status** — Check if wallet is paused\n *\n * @param client - An initialized SmartAgentKitClient\n * @param walletAddress - The smart wallet address to operate on\n * @param sessionKey - Optional session key private key for signing transactions\n * @returns Array of DynamicStructuredTool instances for use with LangChain agents\n *\n * @example\n * ```ts\n * import { createSmartAgentKitTools } from \"@smartagentkit/langchain\";\n * import { createReactAgent } from \"@langchain/langgraph/prebuilt\";\n *\n * const tools = createSmartAgentKitTools(client, wallet.address, sessionKey);\n * const agent = createReactAgent({ llm: chatModel, tools });\n * ```\n */\nexport function createSmartAgentKitTools(\n client: ISmartAgentKitClient,\n walletAddress: string,\n sessionKey?: string,\n): DynamicStructuredTool[] {\n const address = walletAddress as `0x${string}`;\n\n // ─── check_wallet_balance ─────────────────────────────────────\n\n const checkWalletBalance = new DynamicStructuredTool({\n name: \"check_wallet_balance\",\n description:\n \"Check the ETH balance of the agent's smart wallet. \" +\n \"Returns the balance in ETH (assuming 18 decimals). \" +\n \"The raw wei value is also returned for precision. \" +\n \"Use this before sending transactions to ensure sufficient funds.\",\n schema: z.object({}),\n func: async () => {\n try {\n const balances = await client.getBalances(address);\n // Note: Division by 1e18 assumes 18 decimals (correct for native ETH).\n // For ERC-20 tokens, use the raw wei value and the token's actual decimals.\n const ethBalance = Number(balances.eth) / 1e18;\n return JSON.stringify({\n wallet: walletAddress,\n eth: ethBalance.toString(),\n ethWei: balances.eth.toString(),\n });\n } catch (error) {\n return JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── check_spending_allowance ────────────────────────────────\n\n const checkSpendingAllowance = new DynamicStructuredTool({\n name: \"check_spending_allowance\",\n description:\n \"Check how much spending allowance remains for a token on the wallet. \" +\n \"The wallet has policy-enforced spending limits per token per time window. \" +\n \"Use this to verify you can spend a certain amount before sending a transaction. \" +\n 'Use \"0x0000000000000000000000000000000000000000\" for native ETH.',\n schema: z.object({\n token: addressSchema.describe(\n \"Token contract address. Use 0x0000000000000000000000000000000000000000 for native ETH.\",\n ),\n }),\n func: async ({ token }) => {\n try {\n const remaining = await client.getRemainingAllowance(\n address,\n token as `0x${string}`,\n );\n // Note: Division by 1e18 assumes 18 decimals (correct for native ETH).\n // For tokens with different decimals (e.g., USDC = 6), use remainingWei\n // and divide by the token's actual decimal factor.\n const remainingEth = Number(remaining) / 1e18;\n return JSON.stringify({\n wallet: walletAddress,\n token,\n remainingWei: remaining.toString(),\n remaining: remainingEth.toString(),\n });\n } catch (error) {\n return JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── send_transaction ─────────────────────────────────────────\n\n const sendTransaction = new DynamicStructuredTool({\n name: \"send_transaction\",\n description:\n \"Send a transaction from the agent's smart wallet. \" +\n \"The transaction is executed as a UserOperation through ERC-4337 \" +\n \"and is subject to the wallet's policy constraints (spending limits, \" +\n \"allowlist, pause state). All values are in wei (1 ETH = 1e18 wei). \" +\n \"Returns the transaction hash on success.\",\n schema: z.object({\n target: addressSchema.describe(\n \"Target contract address to call (0x-prefixed 20-byte hex)\",\n ),\n value: weiValueSchema\n .optional()\n .describe(\n \"ETH value to send in wei (as string). Defaults to '0'. Example: '1000000000000000' for 0.001 ETH.\",\n ),\n data: calldataSchema\n .optional()\n .describe(\n \"Calldata for the transaction (0x-prefixed hex). Defaults to '0x' for simple ETH transfer.\",\n ),\n }),\n func: async ({ target, value, data }) => {\n try {\n const wallet = {\n address,\n owner: address, // Resolved from connected wallet\n chain: {} as never, // Not used in execute\n isDeployed: true,\n policies: [],\n sessions: [],\n };\n\n const txHash = await client.execute(wallet, {\n target: target as `0x${string}`,\n value: value ? BigInt(value) : 0n,\n data: (data as `0x${string}`) ?? \"0x\",\n sessionKey: sessionKey as `0x${string}` | undefined,\n });\n\n return JSON.stringify({\n success: true,\n transactionHash: txHash,\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── send_batch_transaction ───────────────────────────────────\n\n const sendBatchTransaction = new DynamicStructuredTool({\n name: \"send_batch_transaction\",\n description:\n \"Send multiple transactions atomically from the agent's smart wallet. \" +\n \"All calls are bundled into a single UserOperation and either all succeed or all revert. \" +\n \"Useful for approve+swap, multi-transfer, or any multi-step operation. \" +\n \"Subject to the wallet's policy constraints. All values are in wei.\",\n schema: z.object({\n calls: z\n .array(\n z.object({\n target: addressSchema.describe(\n \"Target contract address (0x-prefixed 20-byte hex)\",\n ),\n value: weiValueSchema\n .optional()\n .describe(\"ETH value in wei (as string). Defaults to '0'.\"),\n data: z\n .string()\n .optional()\n .describe(\"Calldata (0x-prefixed hex). Defaults to '0x'.\"),\n }),\n )\n .min(1)\n .describe(\"Array of calls to execute atomically\"),\n }),\n func: async ({ calls }) => {\n try {\n const wallet = {\n address,\n owner: address,\n chain: {} as never,\n isDeployed: true,\n policies: [],\n sessions: [],\n };\n\n const txHash = await client.executeBatch(wallet, {\n calls: calls.map((c) => ({\n target: c.target as `0x${string}`,\n value: c.value ? BigInt(c.value) : 0n,\n data: (c.data as `0x${string}`) ?? \"0x\",\n })),\n sessionKey: sessionKey as `0x${string}` | undefined,\n });\n\n return JSON.stringify({\n success: true,\n transactionHash: txHash,\n callCount: calls.length,\n });\n } catch (error) {\n return JSON.stringify({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n // ─── check_wallet_status ─────────────────────────────────────\n\n const checkWalletStatus = new DynamicStructuredTool({\n name: \"check_wallet_status\",\n description:\n \"Check if the agent's smart wallet is currently paused. \" +\n \"A paused wallet cannot execute any transactions. \" +\n \"The guardian can pause the wallet in emergencies.\",\n schema: z.object({}),\n func: async () => {\n try {\n const paused = await client.isPaused(address);\n return JSON.stringify({\n wallet: walletAddress,\n paused,\n status: paused ? \"paused\" : \"active\",\n });\n } catch (error) {\n return JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n\n return [\n checkWalletBalance,\n checkSpendingAllowance,\n sendTransaction,\n sendBatchTransaction,\n checkWalletStatus,\n ];\n}\n"],"mappings":"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","names":[]}