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.

@@ -4,14 +4,7 @@ import httpx
4
4
  from langchain.tools.base import ToolException
5
5
  from pydantic import BaseModel, Field
6
6
 
7
- from intentkit.skills.enso.base import (
8
- EnsoBaseTool,
9
- base_url,
10
- )
11
- from intentkit.utils.chain import NetworkId
12
-
13
- # Chain ID for Base Mainnet
14
- BASE_CHAIN_ID = int(NetworkId.BaseMainnet)
7
+ from intentkit.skills.enso.base import EnsoBaseTool, base_url
15
8
 
16
9
 
17
10
  class EnsoGetBestYieldInput(BaseModel):
@@ -21,9 +14,9 @@ class EnsoGetBestYieldInput(BaseModel):
21
14
  "USDC",
22
15
  description="Symbol of the token to find the best yield for (e.g., 'USDC', 'ETH', 'USDT')",
23
16
  )
24
- chain_id: int = Field(
25
- BASE_CHAIN_ID,
26
- description="The blockchain chain ID. Default is Base Mainnet (8453)",
17
+ chain_id: int | None = Field(
18
+ None,
19
+ description="The blockchain chain ID. Defaults to the agent's configured network.",
27
20
  )
28
21
  top_n: int = Field(
29
22
  5,
@@ -80,7 +73,7 @@ class EnsoGetBestYield(EnsoBaseTool):
80
73
  async def _arun(
81
74
  self,
82
75
  token_symbol: str = "USDC",
83
- chain_id: int = BASE_CHAIN_ID,
76
+ chain_id: int | None = None,
84
77
  top_n: int = 5,
85
78
  **kwargs,
86
79
  ) -> EnsoGetBestYieldOutput:
@@ -89,7 +82,7 @@ class EnsoGetBestYield(EnsoBaseTool):
89
82
 
90
83
  Args:
91
84
  token_symbol (str): Symbol of the token to find the best yield for (default: USDC)
92
- chain_id (int): The chain id of the network (default: Base Mainnet)
85
+ chain_id (int | None): The chain id of the network. Defaults to the agent's configured network.
93
86
  top_n (int): Number of top yield options to return
94
87
 
95
88
  Returns:
@@ -99,16 +92,17 @@ class EnsoGetBestYield(EnsoBaseTool):
99
92
  ToolException: If there's an error accessing the Enso API.
100
93
  """
101
94
  context = self.get_context()
95
+ resolved_chain_id = self.resolve_chain_id(context, chain_id)
102
96
  api_token = self.get_api_token(context)
103
97
 
104
98
  if not api_token:
105
99
  raise ToolException("No API token found for Enso Finance")
106
100
 
107
101
  # Get the chain name for the given chain ID
108
- chain_name = await self._get_chain_name(api_token, chain_id)
102
+ chain_name = await self._get_chain_name(api_token, resolved_chain_id)
109
103
 
110
104
  # Get all protocols on the specified chain
111
- protocols = await self._get_protocols(api_token, chain_id)
105
+ protocols = await self._get_protocols(api_token, resolved_chain_id)
112
106
 
113
107
  # Collect all yield options from all protocols
114
108
  all_yield_options = []
@@ -119,7 +113,7 @@ class EnsoGetBestYield(EnsoBaseTool):
119
113
 
120
114
  # Get yield-bearing tokens for this protocol
121
115
  tokens = await self._get_protocol_tokens(
122
- api_token, chain_id, protocol_slug, token_symbol
116
+ api_token, resolved_chain_id, protocol_slug, token_symbol
123
117
  )
124
118
 
125
119
  # Process tokens to extract yield options
@@ -170,7 +164,7 @@ class EnsoGetBestYield(EnsoBaseTool):
170
164
  return EnsoGetBestYieldOutput(
171
165
  best_options=top_options,
172
166
  token_symbol=token_symbol,
173
- chain_id=chain_id,
167
+ chain_id=resolved_chain_id,
174
168
  chain_name=chain_name,
175
169
  )
176
170
 
@@ -7,8 +7,6 @@ from pydantic import BaseModel, Field
7
7
 
8
8
  from .base import EnsoBaseTool, base_url
9
9
 
10
- logger = logging.getLogger(__name__)
11
-
12
10
 
13
11
  class EnsoGetNetworksInput(BaseModel):
14
12
  """
@@ -38,6 +36,9 @@ class EnsoGetNetworksOutput(BaseModel):
38
36
  )
39
37
 
40
38
 
39
+ logger = logging.getLogger(__name__)
40
+
41
+
41
42
  class EnsoGetNetworks(EnsoBaseTool):
42
43
  """
43
44
  Tool for retrieving networks and their corresponding chainId, the output should be kept.
@@ -4,13 +4,11 @@ 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, default_chain_id
7
+ from .base import EnsoBaseTool, base_url
8
8
 
9
9
 
10
10
  class EnsoGetPricesInput(BaseModel):
11
- chainId: int = Field(
12
- default_chain_id, description="Blockchain chain ID of the token"
13
- )
11
+ chainId: int | None = Field(None, description="Blockchain chain ID of the token")
14
12
  address: str = Field(
15
13
  "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
16
14
  description="Contract address of the token",
@@ -43,22 +41,21 @@ class EnsoGetPrices(EnsoBaseTool):
43
41
  async def _arun(
44
42
  self,
45
43
  address: str,
46
- chainId: int = default_chain_id,
44
+ chainId: int | None = None,
47
45
  **kwargs,
48
46
  ) -> EnsoGetPricesOutput:
49
47
  """
50
48
  Asynchronous function to request the token price from the API.
51
49
 
52
50
  Args:
53
- chainId (int): The blockchain's chain ID.
51
+ chainId (int | None): The blockchain's chain ID. Defaults to the agent's configured network.
54
52
  address (str): Contract address of the token.
55
53
 
56
54
  Returns:
57
55
  EnsoGetPricesOutput: Token price response or error message.
58
56
  """
59
- url = f"{base_url}/api/v1/prices/{str(chainId)}/{address}"
60
-
61
57
  context = self.get_context()
58
+ resolved_chain_id = self.resolve_chain_id(context, chainId)
62
59
  api_token = self.get_api_token(context)
63
60
 
64
61
  headers = {
@@ -68,7 +65,10 @@ class EnsoGetPrices(EnsoBaseTool):
68
65
 
69
66
  async with httpx.AsyncClient() as client:
70
67
  try:
71
- response = await client.get(url, headers=headers)
68
+ response = await client.get(
69
+ f"{base_url}/api/v1/prices/{str(resolved_chain_id)}/{address}",
70
+ headers=headers,
71
+ )
72
72
  response.raise_for_status()
73
73
  json_dict = response.json()
74
74
 
@@ -6,7 +6,7 @@ from pydantic import BaseModel, Field
6
6
 
7
7
  from intentkit.skills.enso.networks import EnsoGetNetworks
8
8
 
9
- from .base import EnsoBaseTool, base_url, default_chain_id
9
+ from .base import EnsoBaseTool, base_url, format_amount_with_decimals
10
10
 
11
11
 
12
12
  class EnsoRouteShortcutInput(BaseModel):
@@ -18,9 +18,9 @@ class EnsoRouteShortcutInput(BaseModel):
18
18
  False,
19
19
  description="Whether to broadcast the transaction or not, this is false by default.",
20
20
  )
21
- chainId: int = Field(
22
- default_chain_id,
23
- description="(Optional) Chain ID of the network to execute the transaction on. the default value is the chain_id extracted from networks according to tokenIn and tokenOut",
21
+ chainId: int | None = Field(
22
+ None,
23
+ description="(Optional) Chain ID of the network to execute the transaction on. Defaults to the agent's configured network.",
24
24
  )
25
25
  amountIn: list[int] = Field(
26
26
  description="Amount of tokenIn to swap in wei, you should multiply user's requested value by token decimals."
@@ -162,7 +162,7 @@ class EnsoRouteShortcut(EnsoBaseTool):
162
162
  amountIn: list[int],
163
163
  tokenIn: list[str],
164
164
  tokenOut: list[str],
165
- chainId: int = default_chain_id,
165
+ chainId: int | None = None,
166
166
  broadcast_requested: bool = False,
167
167
  **kwargs,
168
168
  ) -> EnsoRouteShortcutOutput:
@@ -173,7 +173,7 @@ class EnsoRouteShortcut(EnsoBaseTool):
173
173
  amountIn (list[int]): Amount of tokenIn to swap in wei, you should multiply user's requested value by token decimals.
174
174
  tokenIn (list[str]): Ethereum address of the token to swap or enter into a position from (For ETH, use 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee).
175
175
  tokenOut (list[str]): Ethereum address of the token to swap or enter into a position to (For ETH, use 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee).
176
- chainId (int): The chain id of the network to be used for swap, deposit and routing.
176
+ chainId (int | None): The chain id of the network to be used for swap, deposit and routing. Defaults to the agent's configured network.
177
177
  broadcast_requested (bool): User should ask for broadcasting the transaction explicitly, otherwise it is always false.
178
178
 
179
179
  Returns:
@@ -182,8 +182,9 @@ class EnsoRouteShortcut(EnsoBaseTool):
182
182
 
183
183
  context = self.get_context()
184
184
  agent_id = context.agent_id
185
+ resolved_chain_id = self.resolve_chain_id(context, chainId)
185
186
  api_token = self.get_api_token(context)
186
- account = await self.get_account(context)
187
+ wallet_address = await self.get_wallet_address(context)
187
188
 
188
189
  async with httpx.AsyncClient() as client:
189
190
  try:
@@ -193,9 +194,10 @@ class EnsoRouteShortcut(EnsoBaseTool):
193
194
  )
194
195
 
195
196
  if networks:
197
+ resolved_key = str(resolved_chain_id)
196
198
  network_name = (
197
- networks.get(str(chainId)).get("name")
198
- if networks.get(str(chainId))
199
+ networks.get(resolved_key).get("name")
200
+ if networks.get(resolved_key)
199
201
  else None
200
202
  )
201
203
  if network_name is None:
@@ -204,12 +206,12 @@ class EnsoRouteShortcut(EnsoBaseTool):
204
206
  ).arun()
205
207
 
206
208
  for network in networks.res:
207
- if network.id == chainId:
209
+ if network.id == resolved_chain_id:
208
210
  network_name = network.name
209
211
 
210
212
  if not network_name:
211
213
  raise ToolException(
212
- f"network name not found for chainId: {chainId}"
214
+ f"network name not found for chainId: {resolved_chain_id}"
213
215
  )
214
216
 
215
217
  headers = {
@@ -242,13 +244,13 @@ class EnsoRouteShortcut(EnsoBaseTool):
242
244
 
243
245
  # Prepare query parameters
244
246
  params = EnsoRouteShortcutInput(
245
- chainId=chainId,
247
+ chainId=resolved_chain_id,
246
248
  amountIn=amountIn,
247
249
  tokenIn=tokenIn,
248
250
  tokenOut=tokenOut,
249
251
  ).model_dump(exclude_none=True)
250
252
 
251
- params["fromAddress"] = account.address
253
+ params["fromAddress"] = wallet_address
252
254
 
253
255
  response = await client.get(url, headers=headers, params=params)
254
256
  response.raise_for_status() # Raise HTTPError for non-2xx responses
@@ -256,10 +258,12 @@ class EnsoRouteShortcut(EnsoBaseTool):
256
258
 
257
259
  res = EnsoRouteShortcutOutput(**json_dict)
258
260
  res.network = network_name
259
-
260
- res.amountOut = str(
261
- float(res.amountOut) / 10 ** token_decimals[tokenOut[0]]
261
+ decimals = token_decimals.get(tokenOut[0])
262
+ amount_out = format_amount_with_decimals(
263
+ json_dict.get("amountOut"), decimals
262
264
  )
265
+ if amount_out is not None:
266
+ res.amountOut = amount_out
263
267
 
264
268
  if broadcast_requested:
265
269
  # Use the wallet provider to send the transaction
@@ -269,13 +273,13 @@ class EnsoRouteShortcut(EnsoBaseTool):
269
273
  tx_data = json_dict.get("tx", {})
270
274
  if tx_data:
271
275
  # Send the transaction using the wallet provider
272
- tx_hash = wallet_provider.send_transaction(
273
- {
274
- "to": tx_data.get("to"),
275
- "data": tx_data.get("data", "0x"),
276
- "value": tx_data.get("value", 0),
277
- }
278
- )
276
+ tx_params = {
277
+ "to": tx_data.get("to"),
278
+ "data": tx_data.get("data", "0x"),
279
+ "value": tx_data.get("value", 0),
280
+ "from": wallet_address,
281
+ }
282
+ tx_hash = wallet_provider.send_transaction(tx_params)
279
283
 
280
284
  # Wait for transaction confirmation
281
285
  wallet_provider.wait_for_transaction_receipt(tx_hash)
@@ -4,11 +4,7 @@ import httpx
4
4
  from langchain.tools.base import ToolException
5
5
  from pydantic import BaseModel, Field
6
6
 
7
- from intentkit.skills.enso.base import (
8
- EnsoBaseTool,
9
- base_url,
10
- default_chain_id,
11
- )
7
+ from intentkit.skills.enso.base import EnsoBaseTool, base_url
12
8
 
13
9
  # Actual Enso output types
14
10
  # class UnderlyingToken(BaseModel):
@@ -50,9 +46,9 @@ from intentkit.skills.enso.base import (
50
46
 
51
47
 
52
48
  class EnsoGetTokensInput(BaseModel):
53
- chainId: int = Field(
54
- default_chain_id,
55
- description="The blockchain chain ID",
49
+ chainId: int | None = Field(
50
+ None,
51
+ description="The blockchain chain ID. Defaults to the agent's configured network.",
56
52
  )
57
53
  protocolSlug: str | None = Field(
58
54
  None,
@@ -110,7 +106,10 @@ class TokenResponseCompact(BaseModel):
110
106
 
111
107
 
112
108
  class EnsoGetTokensOutput(BaseModel):
113
- res: list[TokenResponseCompact] | None
109
+ res: list[TokenResponseCompact] = Field(
110
+ default_factory=list,
111
+ description="List of token information entries",
112
+ )
114
113
 
115
114
 
116
115
  class EnsoGetTokens(EnsoBaseTool):
@@ -138,7 +137,7 @@ class EnsoGetTokens(EnsoBaseTool):
138
137
 
139
138
  async def _arun(
140
139
  self,
141
- chainId: int = default_chain_id,
140
+ chainId: int | None = None,
142
141
  protocolSlug: str | None = None,
143
142
  **kwargs,
144
143
  ) -> EnsoGetTokensOutput:
@@ -156,15 +155,17 @@ class EnsoGetTokens(EnsoBaseTool):
156
155
 
157
156
  context = self.get_context()
158
157
  agent_id = context.agent_id
158
+ resolved_chain_id = self.resolve_chain_id(context, chainId)
159
159
  api_token = self.get_api_token(context)
160
160
  main_tokens = self.get_main_tokens(context)
161
+ main_tokens_upper = {token.upper() for token in main_tokens}
161
162
  headers = {
162
163
  "accept": "application/json",
163
164
  "Authorization": f"Bearer {api_token}",
164
165
  }
165
166
 
166
167
  params = EnsoGetTokensInput(
167
- chainId=chainId,
168
+ chainId=resolved_chain_id,
168
169
  protocolSlug=protocolSlug,
169
170
  ).model_dump(exclude_none=True)
170
171
 
@@ -186,19 +187,21 @@ class EnsoGetTokens(EnsoBaseTool):
186
187
  token_decimals = {}
187
188
 
188
189
  # filter the main tokens from config or the ones that have apy assigned.
189
- res = EnsoGetTokensOutput(res=list[TokenResponseCompact]())
190
- for item in json_dict["data"]:
191
- main_tokens = [item.upper() for item in main_tokens]
192
- if item.get("apy") or (item.get("symbol").upper() in main_tokens):
190
+ res = EnsoGetTokensOutput()
191
+ for item in json_dict.get("data", []):
192
+ symbol = item.get("symbol", "").upper()
193
+ has_apy = bool(item.get("apy"))
194
+ if has_apy or symbol in main_tokens_upper:
193
195
  token_response = TokenResponseCompact(**item)
194
196
  res.res.append(token_response)
195
- token_decimals[token_response.address] = token_response.decimals
196
- if (
197
- token_response.underlyingTokens
198
- and len(token_response.underlyingTokens) > 0
199
- ):
197
+ if token_response.address:
198
+ token_decimals[token_response.address] = (
199
+ token_response.decimals
200
+ )
201
+ if token_response.underlyingTokens:
200
202
  for u_token in token_response.underlyingTokens:
201
- token_decimals[u_token.address] = u_token.decimals
203
+ if u_token.address:
204
+ token_decimals[u_token.address] = u_token.decimals
202
205
 
203
206
  await self.skill_store.save_agent_skill_data(
204
207
  agent_id,