intentkit 0.7.5.dev16__py3-none-any.whl → 0.7.5.dev18__py3-none-any.whl
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.
Potentially problematic release.
This version of intentkit might be problematic. Click here for more details.
- intentkit/__init__.py +1 -1
- intentkit/config/config.py +0 -5
- intentkit/core/engine.py +61 -42
- intentkit/models/agent.py +82 -13
- intentkit/models/llm.py +8 -8
- intentkit/skills/enso/__init__.py +1 -1
- intentkit/skills/enso/base.py +44 -17
- intentkit/skills/enso/best_yield.py +11 -17
- intentkit/skills/enso/networks.py +3 -2
- intentkit/skills/enso/prices.py +9 -9
- intentkit/skills/enso/route.py +27 -23
- intentkit/skills/enso/tokens.py +24 -21
- intentkit/skills/enso/wallet.py +71 -186
- intentkit/skills/lifi/__init__.py +4 -4
- intentkit/skills/lifi/token_execute.py +24 -12
- intentkit/skills/lifi/token_quote.py +2 -2
- intentkit/skills/lifi/utils.py +96 -43
- {intentkit-0.7.5.dev16.dist-info → intentkit-0.7.5.dev18.dist-info}/METADATA +1 -1
- {intentkit-0.7.5.dev16.dist-info → intentkit-0.7.5.dev18.dist-info}/RECORD +21 -21
- {intentkit-0.7.5.dev16.dist-info → intentkit-0.7.5.dev18.dist-info}/WHEEL +0 -0
- {intentkit-0.7.5.dev16.dist-info → intentkit-0.7.5.dev18.dist-info}/licenses/LICENSE +0 -0
intentkit/skills/enso/wallet.py
CHANGED
|
@@ -4,23 +4,13 @@ import httpx
|
|
|
4
4
|
from langchain.tools.base import ToolException
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
|
-
from .base import EnsoBaseTool, base_url
|
|
7
|
+
from .base import EnsoBaseTool, base_url
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class EnsoGetBalancesInput(BaseModel):
|
|
11
|
-
"""
|
|
12
|
-
Input model for retrieving wallet balances.
|
|
13
|
-
"""
|
|
11
|
+
"""Input model for retrieving wallet balances."""
|
|
14
12
|
|
|
15
|
-
chainId: int = Field(
|
|
16
|
-
default_chain_id, description="Chain ID of the blockchain network"
|
|
17
|
-
)
|
|
18
|
-
# eoaAddress: str = Field(
|
|
19
|
-
# description="Address of the eoa with which to associate the ensoWallet for balances"
|
|
20
|
-
# )
|
|
21
|
-
# useEoa: bool = Field(
|
|
22
|
-
# description="If true returns balances for the provided eoaAddress, instead of the associated ensoWallet"
|
|
23
|
-
# )
|
|
13
|
+
chainId: int | None = Field(None, description="Chain ID of the blockchain network")
|
|
24
14
|
|
|
25
15
|
|
|
26
16
|
class WalletBalance(BaseModel):
|
|
@@ -31,9 +21,7 @@ class WalletBalance(BaseModel):
|
|
|
31
21
|
|
|
32
22
|
|
|
33
23
|
class EnsoGetBalancesOutput(BaseModel):
|
|
34
|
-
"""
|
|
35
|
-
Output model for retrieving wallet balances.
|
|
36
|
-
"""
|
|
24
|
+
"""Output model for retrieving wallet balances."""
|
|
37
25
|
|
|
38
26
|
res: list[WalletBalance] | None = Field(
|
|
39
27
|
None, description="The wallet's balances along with token details."
|
|
@@ -41,15 +29,7 @@ class EnsoGetBalancesOutput(BaseModel):
|
|
|
41
29
|
|
|
42
30
|
|
|
43
31
|
class EnsoGetWalletBalances(EnsoBaseTool):
|
|
44
|
-
"""
|
|
45
|
-
This tool allows querying for first 20 token balances of a specific wallet
|
|
46
|
-
and blockchain network.
|
|
47
|
-
|
|
48
|
-
Attributes:
|
|
49
|
-
name (str): Name of the tool, specifically "enso_get_wallet_balances".
|
|
50
|
-
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
51
|
-
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
52
|
-
"""
|
|
32
|
+
"""Retrieve token balances of a wallet on a specified blockchain network."""
|
|
53
33
|
|
|
54
34
|
name: str = "enso_get_wallet_balances"
|
|
55
35
|
description: str = (
|
|
@@ -59,61 +39,48 @@ class EnsoGetWalletBalances(EnsoBaseTool):
|
|
|
59
39
|
|
|
60
40
|
async def _arun(
|
|
61
41
|
self,
|
|
62
|
-
chainId: int =
|
|
63
|
-
**
|
|
42
|
+
chainId: int | None = None,
|
|
43
|
+
**_: object,
|
|
64
44
|
) -> EnsoGetBalancesOutput:
|
|
65
|
-
"""
|
|
66
|
-
Run the tool to get token balances of a wallet.
|
|
67
|
-
|
|
68
|
-
Args:
|
|
69
|
-
chainId (int): Chain ID of the blockchain network.
|
|
70
|
-
|
|
71
|
-
Returns:
|
|
72
|
-
EnsoGetBalancesOutput: The list of balances or an error message.
|
|
73
|
-
"""
|
|
74
|
-
url = f"{base_url}/api/v1/wallet/balances"
|
|
75
|
-
|
|
76
45
|
context = self.get_context()
|
|
46
|
+
resolved_chain_id = self.resolve_chain_id(context, chainId)
|
|
77
47
|
api_token = self.get_api_token(context)
|
|
78
|
-
|
|
48
|
+
wallet_address = await self.get_wallet_address(context)
|
|
49
|
+
|
|
79
50
|
headers = {
|
|
80
51
|
"accept": "application/json",
|
|
81
52
|
"Authorization": f"Bearer {api_token}",
|
|
82
53
|
}
|
|
83
54
|
|
|
84
|
-
params = EnsoGetBalancesInput(chainId=
|
|
85
|
-
|
|
55
|
+
params = EnsoGetBalancesInput(chainId=resolved_chain_id).model_dump(
|
|
56
|
+
exclude_none=True
|
|
57
|
+
)
|
|
58
|
+
params["eoaAddress"] = wallet_address
|
|
86
59
|
params["useEoa"] = True
|
|
87
60
|
|
|
88
61
|
async with httpx.AsyncClient() as client:
|
|
89
62
|
try:
|
|
90
|
-
|
|
91
|
-
|
|
63
|
+
response = await client.get(
|
|
64
|
+
f"{base_url}/api/v1/wallet/balances",
|
|
65
|
+
headers=headers,
|
|
66
|
+
params=params,
|
|
67
|
+
)
|
|
92
68
|
response.raise_for_status()
|
|
93
|
-
|
|
94
|
-
# Map the response JSON into the WalletBalance model
|
|
95
69
|
json_dict = response.json()[:20]
|
|
96
70
|
res = [WalletBalance(**item) for item in json_dict]
|
|
97
|
-
|
|
98
|
-
# Return the parsed response
|
|
99
71
|
return EnsoGetBalancesOutput(res=res)
|
|
100
72
|
except httpx.RequestError as req_err:
|
|
101
73
|
raise ToolException("request error from Enso API") from req_err
|
|
102
74
|
except httpx.HTTPStatusError as http_err:
|
|
103
75
|
raise ToolException("http error from Enso API") from http_err
|
|
104
|
-
except Exception as
|
|
105
|
-
raise ToolException(f"error from Enso API: {
|
|
76
|
+
except Exception as exc: # pragma: no cover - defensive
|
|
77
|
+
raise ToolException(f"error from Enso API: {exc}") from exc
|
|
106
78
|
|
|
107
79
|
|
|
108
80
|
class EnsoGetApprovalsInput(BaseModel):
|
|
109
|
-
"""
|
|
110
|
-
Input model for retrieving wallet approvals.
|
|
111
|
-
"""
|
|
81
|
+
"""Input model for retrieving wallet approvals."""
|
|
112
82
|
|
|
113
|
-
chainId: int = Field(
|
|
114
|
-
default_chain_id, description="Chain ID of the blockchain network"
|
|
115
|
-
)
|
|
116
|
-
fromAddress: str = Field(description="Address of the wallet")
|
|
83
|
+
chainId: int | None = Field(None, description="Chain ID of the blockchain network")
|
|
117
84
|
routingStrategy: Literal["ensowallet", "router", "delegate"] | None = Field(
|
|
118
85
|
None, description="Routing strategy to use"
|
|
119
86
|
)
|
|
@@ -126,9 +93,7 @@ class WalletAllowance(BaseModel):
|
|
|
126
93
|
|
|
127
94
|
|
|
128
95
|
class EnsoGetApprovalsOutput(BaseModel):
|
|
129
|
-
"""
|
|
130
|
-
Output model for retrieving wallet approvals.
|
|
131
|
-
"""
|
|
96
|
+
"""Output model for retrieving wallet approvals."""
|
|
132
97
|
|
|
133
98
|
res: list[WalletAllowance] | None = Field(
|
|
134
99
|
None, description="Response containing the list of token approvals."
|
|
@@ -136,42 +101,24 @@ class EnsoGetApprovalsOutput(BaseModel):
|
|
|
136
101
|
|
|
137
102
|
|
|
138
103
|
class EnsoGetWalletApprovals(EnsoBaseTool):
|
|
139
|
-
"""
|
|
140
|
-
This tool allows querying for first 50 token spend approvals associated with a specific wallet
|
|
141
|
-
and blockchain network.
|
|
142
|
-
|
|
143
|
-
Attributes:
|
|
144
|
-
name (str): Name of the tool, specifically "enso_get_wallet_approvals".
|
|
145
|
-
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
146
|
-
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
147
|
-
"""
|
|
104
|
+
"""Retrieve token spend approvals for a wallet on a specified blockchain network."""
|
|
148
105
|
|
|
149
106
|
name: str = "enso_get_wallet_approvals"
|
|
150
107
|
description: str = (
|
|
151
108
|
"Retrieve token spend approvals for a wallet on a specified blockchain network."
|
|
152
109
|
)
|
|
153
|
-
args_schema: Type[BaseModel] =
|
|
110
|
+
args_schema: Type[BaseModel] = EnsoGetApprovalsInput
|
|
154
111
|
|
|
155
112
|
async def _arun(
|
|
156
113
|
self,
|
|
157
|
-
chainId: int =
|
|
158
|
-
|
|
114
|
+
chainId: int | None = None,
|
|
115
|
+
routingStrategy: Literal["ensowallet", "router", "delegate"] | None = None,
|
|
116
|
+
**_: object,
|
|
159
117
|
) -> EnsoGetApprovalsOutput:
|
|
160
|
-
"""
|
|
161
|
-
Run the tool to get token approvals for a wallet.
|
|
162
|
-
|
|
163
|
-
Args:
|
|
164
|
-
chainId (int): Chain ID of the blockchain network.
|
|
165
|
-
**kwargs: optional kwargs for the tool with args schema defined in EnsoGetApprovalsInput.
|
|
166
|
-
|
|
167
|
-
Returns:
|
|
168
|
-
EnsoGetApprovalsOutput: The list of approvals or an error message.
|
|
169
|
-
"""
|
|
170
|
-
url = f"{base_url}/api/v1/wallet/approvals"
|
|
171
|
-
|
|
172
118
|
context = self.get_context()
|
|
119
|
+
resolved_chain_id = self.resolve_chain_id(context, chainId)
|
|
173
120
|
api_token = self.get_api_token(context)
|
|
174
|
-
|
|
121
|
+
wallet_address = await self.get_wallet_address(context)
|
|
175
122
|
|
|
176
123
|
headers = {
|
|
177
124
|
"accept": "application/json",
|
|
@@ -179,26 +126,21 @@ class EnsoGetWalletApprovals(EnsoBaseTool):
|
|
|
179
126
|
}
|
|
180
127
|
|
|
181
128
|
params = EnsoGetApprovalsInput(
|
|
182
|
-
chainId=
|
|
183
|
-
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
if kwargs.get("routingStrategy"):
|
|
187
|
-
params.routingStrategy = kwargs["routingStrategy"]
|
|
129
|
+
chainId=resolved_chain_id,
|
|
130
|
+
routingStrategy=routingStrategy,
|
|
131
|
+
).model_dump(exclude_none=True)
|
|
132
|
+
params["fromAddress"] = wallet_address
|
|
188
133
|
|
|
189
134
|
async with httpx.AsyncClient() as client:
|
|
190
135
|
try:
|
|
191
|
-
# Send the GET request
|
|
192
136
|
response = await client.get(
|
|
193
|
-
|
|
137
|
+
f"{base_url}/api/v1/wallet/approvals",
|
|
138
|
+
headers=headers,
|
|
139
|
+
params=params,
|
|
194
140
|
)
|
|
195
141
|
response.raise_for_status()
|
|
196
|
-
|
|
197
|
-
# Map the response JSON into the ApprovalsResponse model
|
|
198
142
|
json_dict = response.json()[:50]
|
|
199
143
|
res = [WalletAllowance(**item) for item in json_dict]
|
|
200
|
-
|
|
201
|
-
# Return the parsed response
|
|
202
144
|
return EnsoGetApprovalsOutput(res=res)
|
|
203
145
|
except httpx.RequestError as req_err:
|
|
204
146
|
raise ToolException(
|
|
@@ -208,29 +150,23 @@ class EnsoGetWalletApprovals(EnsoBaseTool):
|
|
|
208
150
|
raise ToolException(
|
|
209
151
|
f"http error from Enso API: {http_err}"
|
|
210
152
|
) from http_err
|
|
211
|
-
except Exception as
|
|
212
|
-
raise ToolException(f"error from Enso API: {
|
|
153
|
+
except Exception as exc: # pragma: no cover - defensive
|
|
154
|
+
raise ToolException(f"error from Enso API: {exc}") from exc
|
|
213
155
|
|
|
214
156
|
|
|
215
157
|
class EnsoWalletApproveInput(BaseModel):
|
|
216
|
-
"""
|
|
217
|
-
Input model for approve the wallet.
|
|
218
|
-
"""
|
|
158
|
+
"""Input model for approving token spend for the wallet."""
|
|
219
159
|
|
|
220
160
|
tokenAddress: str = Field(description="ERC20 token address of the token to approve")
|
|
221
161
|
amount: int = Field(description="Amount of tokens to approve in wei")
|
|
222
|
-
chainId: int = Field(
|
|
223
|
-
default_chain_id, description="Chain ID of the blockchain network"
|
|
224
|
-
)
|
|
162
|
+
chainId: int | None = Field(None, description="Chain ID of the blockchain network")
|
|
225
163
|
routingStrategy: Literal["ensowallet", "router", "delegate"] | None = Field(
|
|
226
164
|
None, description="Routing strategy to use"
|
|
227
165
|
)
|
|
228
166
|
|
|
229
167
|
|
|
230
168
|
class EnsoWalletApproveOutput(BaseModel):
|
|
231
|
-
"""
|
|
232
|
-
Output model for approve token for the wallet.
|
|
233
|
-
"""
|
|
169
|
+
"""Output model for approve token for the wallet."""
|
|
234
170
|
|
|
235
171
|
gas: str | None = Field(None, description="The gas estimate for the transaction")
|
|
236
172
|
token: str | None = Field(None, description="The token address to approve")
|
|
@@ -239,133 +175,82 @@ class EnsoWalletApproveOutput(BaseModel):
|
|
|
239
175
|
|
|
240
176
|
|
|
241
177
|
class EnsoWalletApproveArtifact(BaseModel):
|
|
242
|
-
"""
|
|
243
|
-
Output model for approve token for the wallet.
|
|
244
|
-
"""
|
|
178
|
+
"""Artifact returned after broadcasting an approval transaction."""
|
|
245
179
|
|
|
246
|
-
tx: object | None = Field(
|
|
180
|
+
tx: object | None = Field(
|
|
181
|
+
None, description="The transaction object to use in `ethers`"
|
|
182
|
+
)
|
|
247
183
|
txHash: str | None = Field(None, description="The transaction hash")
|
|
248
184
|
|
|
249
185
|
|
|
250
186
|
class EnsoWalletApprove(EnsoBaseTool):
|
|
251
|
-
"""
|
|
252
|
-
This tool is used specifically for broadcasting a ERC20 token spending approval transaction to the network.
|
|
253
|
-
It should only be used when the user explicitly requests to broadcast an approval transaction with a specific amount for a certain token.
|
|
254
|
-
|
|
255
|
-
**Example Usage:**
|
|
256
|
-
|
|
257
|
-
"Broadcast an approval transaction for 10 USDC to the wallet."
|
|
258
|
-
|
|
259
|
-
**Important:**
|
|
260
|
-
- This tool should be used with extreme caution.
|
|
261
|
-
- Approving token spending grants another account permission to spend your tokens.
|
|
262
|
-
|
|
263
|
-
Attributes:
|
|
264
|
-
name (str): Name of the tool, specifically "enso_wallet_approve".
|
|
265
|
-
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
266
|
-
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
267
|
-
"""
|
|
187
|
+
"""Broadcast an ERC20 token spending approval transaction."""
|
|
268
188
|
|
|
269
189
|
name: str = "enso_wallet_approve"
|
|
270
|
-
description: str =
|
|
190
|
+
description: str = (
|
|
191
|
+
"This tool is used specifically for broadcasting a ERC20 token spending approval transaction to the "
|
|
192
|
+
"network. It should only be used when the user explicitly requests to broadcast an approval transaction "
|
|
193
|
+
"with a specific amount for a certain token."
|
|
194
|
+
)
|
|
271
195
|
args_schema: Type[BaseModel] = EnsoWalletApproveInput
|
|
272
196
|
response_format: str = "content_and_artifact"
|
|
273
197
|
|
|
274
|
-
# def _run(
|
|
275
|
-
# self,
|
|
276
|
-
# tokenAddress: str,
|
|
277
|
-
# amount: int,
|
|
278
|
-
# chainId: int = default_chain_id,
|
|
279
|
-
# **kwargs,
|
|
280
|
-
# ) -> Tuple[EnsoBroadcastWalletApproveOutput, EnsoBroadcastWalletApproveArtifact]:
|
|
281
|
-
# """Run the tool to approve enso router for a wallet.
|
|
282
|
-
|
|
283
|
-
# Returns:
|
|
284
|
-
# Tuple[EnsoBroadcastWalletApproveOutput, EnsoBroadcastWalletApproveArtifact]: A structured output containing the result of token approval.
|
|
285
|
-
|
|
286
|
-
# Raises:
|
|
287
|
-
# Exception: If there's an error accessing the Enso API.
|
|
288
|
-
# """
|
|
289
|
-
# raise NotImplementedError("Use _arun instead")
|
|
290
|
-
|
|
291
198
|
async def _arun(
|
|
292
199
|
self,
|
|
293
200
|
tokenAddress: str,
|
|
294
201
|
amount: int,
|
|
295
|
-
chainId: int =
|
|
296
|
-
|
|
202
|
+
chainId: int | None = None,
|
|
203
|
+
routingStrategy: Literal["ensowallet", "router", "delegate"] | None = None,
|
|
204
|
+
**_: object,
|
|
297
205
|
) -> Tuple[EnsoWalletApproveOutput, EnsoWalletApproveArtifact]:
|
|
298
|
-
"""
|
|
299
|
-
Run the tool to approve enso router for a wallet.
|
|
300
|
-
|
|
301
|
-
Args:
|
|
302
|
-
tokenAddress (str): ERC20 token address of the token to approve.
|
|
303
|
-
amount (int): Amount of tokens to approve in wei.
|
|
304
|
-
chainId (int): Chain ID of the blockchain network.
|
|
305
|
-
**kwargs: optional kwargs for the tool with args schema defined in EnsoGetApproveInput.
|
|
306
|
-
|
|
307
|
-
Returns:
|
|
308
|
-
Tuple[EnsoBroadcastWalletApproveOutput, EnsoBroadcastWalletApproveArtifact]: The list of approve transaction output or an error message.
|
|
309
|
-
"""
|
|
310
|
-
url = f"{base_url}/api/v1/wallet/approve"
|
|
311
206
|
context = self.get_context()
|
|
207
|
+
resolved_chain_id = self.resolve_chain_id(context, chainId)
|
|
312
208
|
api_token = self.get_api_token(context)
|
|
313
|
-
|
|
209
|
+
wallet_address = await self.get_wallet_address(context)
|
|
314
210
|
|
|
315
211
|
headers = {
|
|
316
212
|
"accept": "application/json",
|
|
317
213
|
"Authorization": f"Bearer {api_token}",
|
|
318
214
|
}
|
|
319
215
|
|
|
320
|
-
from_address = account.address
|
|
321
|
-
|
|
322
216
|
params = EnsoWalletApproveInput(
|
|
323
217
|
tokenAddress=tokenAddress,
|
|
324
218
|
amount=amount,
|
|
325
|
-
chainId=
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
params.routingStrategy = kwargs["routingStrategy"]
|
|
330
|
-
|
|
331
|
-
params = params.model_dump(exclude_none=True)
|
|
219
|
+
chainId=resolved_chain_id,
|
|
220
|
+
routingStrategy=routingStrategy,
|
|
221
|
+
).model_dump(exclude_none=True)
|
|
222
|
+
params["fromAddress"] = wallet_address
|
|
332
223
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
with httpx.Client() as client:
|
|
224
|
+
async with httpx.AsyncClient() as client:
|
|
336
225
|
try:
|
|
337
|
-
|
|
338
|
-
|
|
226
|
+
response = await client.get(
|
|
227
|
+
f"{base_url}/api/v1/wallet/approve",
|
|
228
|
+
headers=headers,
|
|
229
|
+
params=params,
|
|
230
|
+
)
|
|
339
231
|
response.raise_for_status()
|
|
340
232
|
|
|
341
|
-
# Map the response JSON into the WalletApproveTransaction model
|
|
342
233
|
json_dict = response.json()
|
|
343
234
|
content = EnsoWalletApproveOutput(**json_dict)
|
|
344
235
|
artifact = EnsoWalletApproveArtifact(**json_dict)
|
|
345
236
|
|
|
346
|
-
# Use the wallet provider to send the transaction
|
|
347
237
|
wallet_provider = await self.get_wallet_provider(context)
|
|
348
|
-
|
|
349
|
-
# Extract transaction data from the Enso API response
|
|
350
238
|
tx_data = json_dict.get("tx", {})
|
|
351
239
|
if tx_data:
|
|
352
|
-
# Send the transaction using the wallet provider
|
|
353
240
|
tx_hash = wallet_provider.send_transaction(
|
|
354
241
|
{
|
|
355
242
|
"to": tx_data.get("to"),
|
|
356
243
|
"data": tx_data.get("data", "0x"),
|
|
357
244
|
"value": tx_data.get("value", 0),
|
|
245
|
+
"from": wallet_address,
|
|
358
246
|
}
|
|
359
247
|
)
|
|
360
248
|
|
|
361
|
-
# Wait for transaction confirmation
|
|
362
249
|
wallet_provider.wait_for_transaction_receipt(tx_hash)
|
|
363
250
|
artifact.txHash = tx_hash
|
|
364
251
|
else:
|
|
365
|
-
# For now, return without executing the transaction if no tx data
|
|
366
252
|
artifact.txHash = "0x0000000000000000000000000000000000000000000000000000000000000000"
|
|
367
253
|
|
|
368
|
-
# Return the parsed response
|
|
369
254
|
return (content, artifact)
|
|
370
255
|
except httpx.RequestError as req_err:
|
|
371
256
|
raise ToolException(
|
|
@@ -375,5 +260,5 @@ class EnsoWalletApprove(EnsoBaseTool):
|
|
|
375
260
|
raise ToolException(
|
|
376
261
|
f"http error from Enso API: {http_err}"
|
|
377
262
|
) from http_err
|
|
378
|
-
except Exception as
|
|
379
|
-
raise ToolException(f"error from Enso API: {
|
|
263
|
+
except Exception as exc: # pragma: no cover - defensive
|
|
264
|
+
raise ToolException(f"error from Enso API: {exc}") from exc
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import List, Optional, TypedDict
|
|
2
|
+
from typing import Any, List, Optional, TypedDict
|
|
3
3
|
|
|
4
4
|
from intentkit.abstracts.skill import SkillStoreABC
|
|
5
5
|
from intentkit.skills.base import SkillConfig, SkillState
|
|
@@ -32,10 +32,10 @@ async def get_skills(
|
|
|
32
32
|
config: "Config",
|
|
33
33
|
is_private: bool,
|
|
34
34
|
store: SkillStoreABC,
|
|
35
|
-
**_,
|
|
35
|
+
**_: Any,
|
|
36
36
|
) -> list[LiFiBaseTool]:
|
|
37
37
|
"""Get all LiFi skills."""
|
|
38
|
-
available_skills = []
|
|
38
|
+
available_skills: list[str] = []
|
|
39
39
|
|
|
40
40
|
# Log configuration
|
|
41
41
|
logger.info(f"[LiFi_Skills] Initializing with config: {config}")
|
|
@@ -57,7 +57,7 @@ async def get_skills(
|
|
|
57
57
|
logger.info(f"[LiFi_Skills] Available skills: {available_skills}")
|
|
58
58
|
|
|
59
59
|
# Get each skill using the cached getter
|
|
60
|
-
skills = []
|
|
60
|
+
skills: list[LiFiBaseTool] = []
|
|
61
61
|
for name in available_skills:
|
|
62
62
|
try:
|
|
63
63
|
skill = get_lifi_skill(name, store, config)
|
|
@@ -2,11 +2,12 @@ import asyncio
|
|
|
2
2
|
from typing import Any, Dict, List, Optional, Type
|
|
3
3
|
|
|
4
4
|
import httpx
|
|
5
|
+
from coinbase_agentkit import CdpEvmWalletProvider
|
|
5
6
|
from pydantic import BaseModel, Field
|
|
6
7
|
from web3 import Web3
|
|
7
8
|
|
|
8
9
|
from intentkit.abstracts.skill import SkillStoreABC
|
|
9
|
-
from intentkit.clients import get_cdp_client
|
|
10
|
+
from intentkit.clients import CdpClient, get_cdp_client
|
|
10
11
|
from intentkit.skills.lifi.base import LiFiBaseTool
|
|
11
12
|
from intentkit.skills.lifi.token_quote import TokenQuote
|
|
12
13
|
from intentkit.skills.lifi.utils import (
|
|
@@ -69,7 +70,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
69
70
|
default_slippage: float = 0.03
|
|
70
71
|
allowed_chains: Optional[List[str]] = None
|
|
71
72
|
max_execution_time: int = 300
|
|
72
|
-
quote_tool: TokenQuote = Field(default=None, exclude=True)
|
|
73
|
+
quote_tool: Optional[TokenQuote] = Field(default=None, exclude=True)
|
|
73
74
|
|
|
74
75
|
def __init__(
|
|
75
76
|
self,
|
|
@@ -77,7 +78,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
77
78
|
default_slippage: float = 0.03,
|
|
78
79
|
allowed_chains: Optional[List[str]] = None,
|
|
79
80
|
max_execution_time: int = 300,
|
|
80
|
-
):
|
|
81
|
+
) -> None:
|
|
81
82
|
"""Initialize the TokenExecute skill with configuration options."""
|
|
82
83
|
super().__init__(skill_store=skill_store)
|
|
83
84
|
self.default_slippage = default_slippage
|
|
@@ -93,6 +94,8 @@ class TokenExecute(LiFiBaseTool):
|
|
|
93
94
|
|
|
94
95
|
def _format_quote_result(self, data: Dict[str, Any]) -> str:
|
|
95
96
|
"""Format the quote result in a readable format."""
|
|
97
|
+
if self.quote_tool is None:
|
|
98
|
+
raise RuntimeError("Quote tool is not initialized")
|
|
96
99
|
# Use the same formatting as token_quote
|
|
97
100
|
return self.quote_tool._format_quote_result(data)
|
|
98
101
|
|
|
@@ -103,7 +106,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
103
106
|
from_token: str,
|
|
104
107
|
to_token: str,
|
|
105
108
|
from_amount: str,
|
|
106
|
-
slippage: float = None,
|
|
109
|
+
slippage: Optional[float] = None,
|
|
107
110
|
**kwargs,
|
|
108
111
|
) -> str:
|
|
109
112
|
"""Execute a token transfer."""
|
|
@@ -168,7 +171,9 @@ class TokenExecute(LiFiBaseTool):
|
|
|
168
171
|
|
|
169
172
|
# Step 3: Execute transaction
|
|
170
173
|
tx_hash = await self._execute_transfer_transaction(
|
|
171
|
-
cdp_wallet_provider,
|
|
174
|
+
cdp_wallet_provider,
|
|
175
|
+
quote_data,
|
|
176
|
+
from_address,
|
|
172
177
|
)
|
|
173
178
|
|
|
174
179
|
# Step 4: Monitor status and return result
|
|
@@ -180,10 +185,12 @@ class TokenExecute(LiFiBaseTool):
|
|
|
180
185
|
self.logger.error("LiFi_Error: %s", str(e))
|
|
181
186
|
return f"An unexpected error occurred: {str(e)}"
|
|
182
187
|
|
|
183
|
-
async def _get_cdp_wallet_provider(
|
|
188
|
+
async def _get_cdp_wallet_provider(
|
|
189
|
+
self, agent_id: str
|
|
190
|
+
) -> CdpEvmWalletProvider | str:
|
|
184
191
|
"""Get CDP wallet provider with error handling."""
|
|
185
192
|
try:
|
|
186
|
-
cdp_client = await get_cdp_client(agent_id, self.skill_store)
|
|
193
|
+
cdp_client: CdpClient = await get_cdp_client(agent_id, self.skill_store)
|
|
187
194
|
if not cdp_client:
|
|
188
195
|
return "CDP client not available. Please ensure your agent has CDP wallet configuration."
|
|
189
196
|
|
|
@@ -207,7 +214,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
207
214
|
from_amount: str,
|
|
208
215
|
slippage: float,
|
|
209
216
|
from_address: str,
|
|
210
|
-
) -> Dict[str, Any]:
|
|
217
|
+
) -> Dict[str, Any] | str:
|
|
211
218
|
"""Get quote from LiFi API."""
|
|
212
219
|
api_params = build_quote_params(
|
|
213
220
|
from_chain,
|
|
@@ -249,7 +256,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
249
256
|
return data
|
|
250
257
|
|
|
251
258
|
async def _handle_token_approval(
|
|
252
|
-
self, wallet_provider, quote_data: Dict[str, Any]
|
|
259
|
+
self, wallet_provider: CdpEvmWalletProvider, quote_data: Dict[str, Any]
|
|
253
260
|
) -> Optional[str]:
|
|
254
261
|
"""Handle ERC20 token approval if needed."""
|
|
255
262
|
estimate = quote_data.get("estimate", {})
|
|
@@ -273,13 +280,18 @@ class TokenExecute(LiFiBaseTool):
|
|
|
273
280
|
raise Exception(f"Failed to approve token: {str(e)}")
|
|
274
281
|
|
|
275
282
|
async def _execute_transfer_transaction(
|
|
276
|
-
self,
|
|
283
|
+
self,
|
|
284
|
+
wallet_provider: CdpEvmWalletProvider,
|
|
285
|
+
quote_data: Dict[str, Any],
|
|
286
|
+
from_address: str,
|
|
277
287
|
) -> str:
|
|
278
288
|
"""Execute the main transfer transaction."""
|
|
279
289
|
transaction_request = quote_data.get("transactionRequest")
|
|
280
290
|
|
|
281
291
|
try:
|
|
282
|
-
tx_params = prepare_transaction_params(
|
|
292
|
+
tx_params = prepare_transaction_params(
|
|
293
|
+
transaction_request, wallet_address=from_address
|
|
294
|
+
)
|
|
283
295
|
self.logger.info(
|
|
284
296
|
f"Sending transaction to {tx_params['to']} with value {tx_params['value']}"
|
|
285
297
|
)
|
|
@@ -407,7 +419,7 @@ class TokenExecute(LiFiBaseTool):
|
|
|
407
419
|
|
|
408
420
|
async def _check_and_set_allowance(
|
|
409
421
|
self,
|
|
410
|
-
wallet_provider,
|
|
422
|
+
wallet_provider: CdpEvmWalletProvider,
|
|
411
423
|
token_address: str,
|
|
412
424
|
approval_address: str,
|
|
413
425
|
amount: str,
|
|
@@ -65,7 +65,7 @@ class TokenQuote(LiFiBaseTool):
|
|
|
65
65
|
skill_store: SkillStoreABC,
|
|
66
66
|
default_slippage: float = 0.03,
|
|
67
67
|
allowed_chains: Optional[List[str]] = None,
|
|
68
|
-
):
|
|
68
|
+
) -> None:
|
|
69
69
|
"""Initialize the TokenQuote skill with configuration options."""
|
|
70
70
|
super().__init__(skill_store=skill_store)
|
|
71
71
|
self.default_slippage = default_slippage
|
|
@@ -78,7 +78,7 @@ class TokenQuote(LiFiBaseTool):
|
|
|
78
78
|
from_token: str,
|
|
79
79
|
to_token: str,
|
|
80
80
|
from_amount: str,
|
|
81
|
-
slippage: float = None,
|
|
81
|
+
slippage: Optional[float] = None,
|
|
82
82
|
**kwargs,
|
|
83
83
|
) -> str:
|
|
84
84
|
"""Get a quote for token transfer."""
|