intentkit 0.6.9.dev1__py3-none-any.whl → 0.6.10.dev1__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/abstracts/graph.py +17 -2
- intentkit/core/engine.py +29 -30
- intentkit/core/node.py +10 -20
- intentkit/models/agent.py +3 -0
- intentkit/models/chat.py +9 -1
- intentkit/skills/acolyt/ask.py +2 -5
- intentkit/skills/acolyt/base.py +16 -6
- intentkit/skills/aixbt/__init__.py +3 -7
- intentkit/skills/aixbt/projects.py +12 -36
- intentkit/skills/allora/base.py +16 -6
- intentkit/skills/allora/price.py +2 -4
- intentkit/skills/base.py +8 -1
- intentkit/skills/carv/base.py +12 -10
- intentkit/skills/carv/fetch_news.py +90 -92
- intentkit/skills/carv/onchain_query.py +162 -164
- intentkit/skills/carv/token_info_and_price.py +108 -110
- intentkit/skills/chainlist/chain_lookup.py +1 -2
- intentkit/skills/common/current_time.py +1 -2
- intentkit/skills/cookiefun/base.py +20 -12
- intentkit/skills/cookiefun/get_account_details.py +1 -3
- intentkit/skills/cookiefun/get_account_feed.py +1 -3
- intentkit/skills/cookiefun/get_account_smart_followers.py +1 -3
- intentkit/skills/cookiefun/get_sectors.py +2 -3
- intentkit/skills/cookiefun/search_accounts.py +1 -3
- intentkit/skills/cryptocompare/fetch_news.py +3 -4
- intentkit/skills/cryptocompare/fetch_price.py +3 -4
- intentkit/skills/cryptocompare/fetch_top_exchanges.py +3 -4
- intentkit/skills/cryptocompare/fetch_top_market_cap.py +3 -4
- intentkit/skills/cryptocompare/fetch_top_volume.py +3 -4
- intentkit/skills/cryptocompare/fetch_trading_signals.py +3 -4
- intentkit/skills/cryptopanic/base.py +13 -9
- intentkit/skills/cryptopanic/fetch_crypto_news.py +150 -153
- intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +133 -136
- intentkit/skills/dapplooker/base.py +16 -6
- intentkit/skills/dapplooker/dapplooker_token_data.py +2 -4
- intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +2 -3
- intentkit/skills/defillama/coins/fetch_block.py +2 -3
- intentkit/skills/defillama/coins/fetch_current_prices.py +2 -5
- intentkit/skills/defillama/coins/fetch_first_price.py +2 -5
- intentkit/skills/defillama/coins/fetch_historical_prices.py +2 -3
- intentkit/skills/defillama/coins/fetch_price_chart.py +2 -5
- intentkit/skills/defillama/coins/fetch_price_percentage.py +2 -5
- intentkit/skills/defillama/fees/fetch_fees_overview.py +2 -3
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +2 -3
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +2 -3
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +2 -3
- intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +2 -3
- intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +2 -5
- intentkit/skills/defillama/tvl/fetch_chains.py +2 -3
- intentkit/skills/defillama/tvl/fetch_historical_tvl.py +2 -3
- intentkit/skills/defillama/tvl/fetch_protocol.py +2 -5
- intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +2 -5
- intentkit/skills/defillama/tvl/fetch_protocols.py +2 -3
- intentkit/skills/defillama/volumes/fetch_dex_overview.py +2 -3
- intentkit/skills/defillama/volumes/fetch_dex_summary.py +2 -5
- intentkit/skills/defillama/volumes/fetch_options_overview.py +2 -3
- intentkit/skills/defillama/yields/fetch_pool_chart.py +2 -5
- intentkit/skills/defillama/yields/fetch_pools.py +2 -3
- intentkit/skills/dune_analytics/base.py +15 -9
- intentkit/skills/dune_analytics/fetch_kol_buys.py +125 -128
- intentkit/skills/dune_analytics/fetch_nation_metrics.py +234 -237
- intentkit/skills/elfa/base.py +16 -6
- intentkit/skills/elfa/mention.py +2 -7
- intentkit/skills/elfa/stats.py +2 -6
- intentkit/skills/elfa/tokens.py +1 -4
- intentkit/skills/enso/base.py +25 -13
- intentkit/skills/enso/best_yield.py +1 -4
- intentkit/skills/enso/networks.py +2 -5
- intentkit/skills/enso/prices.py +1 -5
- intentkit/skills/enso/route.py +2 -5
- intentkit/skills/enso/tokens.py +1 -4
- intentkit/skills/enso/wallet.py +3 -9
- intentkit/skills/firecrawl/base.py +16 -6
- intentkit/skills/firecrawl/clear.py +1 -3
- intentkit/skills/firecrawl/crawl.py +7 -8
- intentkit/skills/firecrawl/query.py +7 -9
- intentkit/skills/firecrawl/scrape.py +7 -8
- intentkit/skills/github/github_search.py +1 -3
- intentkit/skills/heurist/base.py +15 -0
- intentkit/skills/heurist/image_generation_animagine_xl.py +3 -4
- intentkit/skills/heurist/image_generation_arthemy_comics.py +3 -4
- intentkit/skills/heurist/image_generation_arthemy_real.py +3 -4
- intentkit/skills/heurist/image_generation_braindance.py +3 -4
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +3 -4
- intentkit/skills/heurist/image_generation_flux_1_dev.py +3 -4
- intentkit/skills/heurist/image_generation_sdxl.py +3 -4
- intentkit/skills/http/get.py +0 -2
- intentkit/skills/http/post.py +0 -2
- intentkit/skills/http/put.py +0 -2
- intentkit/skills/lifi/token_execute.py +1 -3
- intentkit/skills/lifi/token_quote.py +0 -2
- intentkit/skills/moralis/base.py +15 -1
- intentkit/skills/nation/nft_check.py +2 -5
- intentkit/skills/openai/base.py +14 -5
- intentkit/skills/openai/dalle_image_generation.py +6 -5
- intentkit/skills/openai/gpt_image_generation.py +6 -5
- intentkit/skills/openai/gpt_image_to_image.py +6 -5
- intentkit/skills/openai/image_to_text.py +6 -6
- intentkit/skills/portfolio/base.py +4 -3
- intentkit/skills/portfolio/token_balances.py +2 -4
- intentkit/skills/portfolio/wallet_approvals.py +2 -4
- intentkit/skills/portfolio/wallet_defi_positions.py +3 -4
- intentkit/skills/portfolio/wallet_history.py +2 -4
- intentkit/skills/portfolio/wallet_net_worth.py +2 -4
- intentkit/skills/portfolio/wallet_nfts.py +2 -4
- intentkit/skills/portfolio/wallet_profitability.py +2 -4
- intentkit/skills/portfolio/wallet_profitability_summary.py +2 -4
- intentkit/skills/portfolio/wallet_stats.py +2 -4
- intentkit/skills/portfolio/wallet_swaps.py +2 -4
- intentkit/skills/slack/base.py +18 -0
- intentkit/skills/slack/get_channel.py +3 -4
- intentkit/skills/slack/get_message.py +3 -4
- intentkit/skills/slack/schedule_message.py +3 -4
- intentkit/skills/slack/send_message.py +3 -4
- intentkit/skills/supabase/delete_data.py +3 -6
- intentkit/skills/supabase/fetch_data.py +3 -6
- intentkit/skills/supabase/insert_data.py +3 -6
- intentkit/skills/supabase/invoke_function.py +3 -6
- intentkit/skills/supabase/update_data.py +3 -6
- intentkit/skills/supabase/upsert_data.py +3 -6
- intentkit/skills/system/add_autonomous_task.py +1 -3
- intentkit/skills/system/delete_autonomous_task.py +1 -3
- intentkit/skills/system/edit_autonomous_task.py +1 -3
- intentkit/skills/system/list_autonomous_tasks.py +1 -3
- intentkit/skills/system/read_agent_api_key.py +2 -3
- intentkit/skills/system/regenerate_agent_api_key.py +2 -5
- intentkit/skills/tavily/base.py +14 -5
- intentkit/skills/tavily/tavily_extract.py +7 -8
- intentkit/skills/tavily/tavily_search.py +11 -9
- intentkit/skills/token/base.py +4 -6
- intentkit/skills/token/erc20_transfers.py +2 -4
- intentkit/skills/token/token_analytics.py +2 -4
- intentkit/skills/token/token_price.py +2 -4
- intentkit/skills/token/token_search.py +2 -4
- intentkit/skills/twitter/base.py +41 -0
- intentkit/skills/twitter/follow_user.py +4 -4
- intentkit/skills/twitter/get_mentions.py +4 -4
- intentkit/skills/twitter/get_timeline.py +4 -4
- intentkit/skills/twitter/get_user_by_username.py +4 -4
- intentkit/skills/twitter/get_user_tweets.py +4 -4
- intentkit/skills/twitter/like_tweet.py +4 -4
- intentkit/skills/twitter/post_tweet.py +3 -4
- intentkit/skills/twitter/reply_tweet.py +3 -4
- intentkit/skills/twitter/retweet.py +4 -4
- intentkit/skills/twitter/search_tweets.py +4 -4
- intentkit/skills/unrealspeech/base.py +16 -0
- intentkit/skills/unrealspeech/text_to_speech.py +4 -4
- intentkit/skills/venice_audio/base.py +11 -9
- intentkit/skills/venice_audio/venice_audio.py +238 -240
- intentkit/skills/venice_image/base.py +23 -19
- intentkit/skills/venice_image/image_enhance/image_enhance.py +78 -80
- intentkit/skills/venice_image/image_generation/image_generation_base.py +115 -117
- intentkit/skills/venice_image/image_upscale/image_upscale.py +88 -90
- intentkit/skills/venice_image/image_vision/image_vision.py +98 -100
- intentkit/skills/web_scraper/document_indexer.py +3 -5
- intentkit/skills/web_scraper/scrape_and_index.py +14 -17
- intentkit/skills/web_scraper/website_indexer.py +8 -10
- intentkit/skills/xmtp/README.md +110 -0
- intentkit/skills/xmtp/__init__.py +82 -0
- intentkit/skills/xmtp/base.py +13 -0
- intentkit/skills/xmtp/schema.json +41 -0
- intentkit/skills/xmtp/transfer.py +170 -0
- intentkit/skills/xmtp/xmtp.svg +26 -0
- {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dev1.dist-info}/METADATA +3 -3
- {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dev1.dist-info}/RECORD +168 -162
- {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dev1.dist-info}/WHEEL +0 -0
- {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dev1.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
|
-
from langchain.schema.runnable import RunnableConfig
|
|
6
5
|
from pydantic import BaseModel, Field
|
|
7
6
|
|
|
8
7
|
from intentkit.skills.defillama.api import fetch_pools
|
|
@@ -99,7 +98,7 @@ class DefiLlamaFetchPools(DefiLlamaBaseTool):
|
|
|
99
98
|
description: str = FETCH_POOLS_PROMPT
|
|
100
99
|
args_schema: None = None # No input parameters needed
|
|
101
100
|
|
|
102
|
-
async def _arun(self,
|
|
101
|
+
async def _arun(self, **kwargs) -> FetchPoolsResponse:
|
|
103
102
|
"""Fetch pool data.
|
|
104
103
|
|
|
105
104
|
Returns:
|
|
@@ -107,7 +106,7 @@ class DefiLlamaFetchPools(DefiLlamaBaseTool):
|
|
|
107
106
|
"""
|
|
108
107
|
try:
|
|
109
108
|
# Check rate limiting
|
|
110
|
-
context = self.
|
|
109
|
+
context = self.get_context()
|
|
111
110
|
is_rate_limited, error_msg = await self.check_rate_limit(context)
|
|
112
111
|
if is_rate_limited:
|
|
113
112
|
return FetchPoolsResponse(error=error_msg)
|
|
@@ -9,7 +9,7 @@ from langchain.tools.base import ToolException
|
|
|
9
9
|
from pydantic import BaseModel, Field
|
|
10
10
|
|
|
11
11
|
from intentkit.abstracts.skill import SkillStoreABC
|
|
12
|
-
from intentkit.skills.base import IntentKitSkill
|
|
12
|
+
from intentkit.skills.base import IntentKitSkill
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class DuneBaseTool(IntentKitSkill):
|
|
@@ -23,22 +23,28 @@ class DuneBaseTool(IntentKitSkill):
|
|
|
23
23
|
args_schema: Type[BaseModel]
|
|
24
24
|
skill_store: SkillStoreABC = Field(description="Skill store for data persistence")
|
|
25
25
|
|
|
26
|
-
def get_api_key(self
|
|
26
|
+
def get_api_key(self) -> str:
|
|
27
27
|
"""Retrieve the Dune Analytics API key from context.
|
|
28
28
|
|
|
29
|
-
Args:
|
|
30
|
-
context: Skill context containing configuration.
|
|
31
|
-
|
|
32
29
|
Returns:
|
|
33
30
|
API key string.
|
|
34
31
|
|
|
35
32
|
Raises:
|
|
36
33
|
ToolException: If the API key is not found.
|
|
37
34
|
"""
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
context = self.get_context()
|
|
36
|
+
skill_config = context.agent.skill_config(self.category)
|
|
37
|
+
api_key_provider = skill_config.get("api_key_provider")
|
|
38
|
+
if api_key_provider == "agent_owner":
|
|
39
|
+
api_key = skill_config.get("api_key")
|
|
40
|
+
if api_key:
|
|
41
|
+
return api_key
|
|
42
|
+
else:
|
|
43
|
+
raise ToolException("No api_key found in agent_owner configuration")
|
|
44
|
+
else:
|
|
45
|
+
raise ToolException(
|
|
46
|
+
f"Invalid API key provider: {api_key_provider}. Only 'agent_owner' is supported for Dune Analytics."
|
|
47
|
+
)
|
|
42
48
|
|
|
43
49
|
@property
|
|
44
50
|
def category(self) -> str:
|
|
@@ -1,128 +1,125 @@
|
|
|
1
|
-
"""Skill to fetch KOL memecoin buys on Solana from Dune Analytics API.
|
|
2
|
-
|
|
3
|
-
Uses query ID 4832844 to retrieve a list of KOL buy transactions.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from typing import Any, Dict, Type
|
|
7
|
-
|
|
8
|
-
import httpx
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
from intentkit.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
default
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
response
|
|
82
|
-
response.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def _run(self, question: str):
|
|
128
|
-
raise NotImplementedError("Use _arun for async execution")
|
|
1
|
+
"""Skill to fetch KOL memecoin buys on Solana from Dune Analytics API.
|
|
2
|
+
|
|
3
|
+
Uses query ID 4832844 to retrieve a list of KOL buy transactions.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any, Dict, Type
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
from pydantic import BaseModel, Field
|
|
10
|
+
from tenacity import retry, stop_after_attempt, wait_exponential
|
|
11
|
+
|
|
12
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
13
|
+
from intentkit.skills.dune_analytics.base import DuneBaseTool
|
|
14
|
+
|
|
15
|
+
BASE_URL = "https://api.dune.com/api/v1/query"
|
|
16
|
+
KOL_BUYS_QUERY_ID = 4832844
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class KOLBuysInput(BaseModel):
|
|
20
|
+
"""Input schema for fetching KOL memecoin buys."""
|
|
21
|
+
|
|
22
|
+
limit: int = Field(
|
|
23
|
+
default=10,
|
|
24
|
+
description="Maximum number of buy transactions to fetch (default 10).",
|
|
25
|
+
ge=1,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class KOLBuyData(BaseModel):
|
|
30
|
+
"""Data model for KOL buy results."""
|
|
31
|
+
|
|
32
|
+
data: Dict[str, Any] = Field(description="KOL buy data from Dune API")
|
|
33
|
+
error: str = Field(default="", description="Error message if fetch failed")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class KOLBuysOutput(BaseModel):
|
|
37
|
+
"""Output schema for KOL memecoin buys."""
|
|
38
|
+
|
|
39
|
+
buys: KOLBuyData = Field(description="KOL buy transaction data")
|
|
40
|
+
summary: str = Field(description="Summary of fetched data")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class FetchKOLBuys(DuneBaseTool):
|
|
44
|
+
"""Skill to fetch KOL memecoin buys on Solana from Dune Analytics API."""
|
|
45
|
+
|
|
46
|
+
name: str = "dune_fetch_kol_buys"
|
|
47
|
+
description: str = (
|
|
48
|
+
"Fetches a list of KOL memecoin buy transactions on Solana from Dune Analytics API using query ID 4832844. "
|
|
49
|
+
"Supports a configurable limit for the number of results. Handles rate limits with retries."
|
|
50
|
+
)
|
|
51
|
+
args_schema: Type[BaseModel] = KOLBuysInput
|
|
52
|
+
skill_store: SkillStoreABC = Field(description="Skill store for data persistence")
|
|
53
|
+
|
|
54
|
+
@retry(
|
|
55
|
+
stop=stop_after_attempt(3), wait=wait_exponential(multiplier=5, min=5, max=60)
|
|
56
|
+
)
|
|
57
|
+
async def fetch_data(
|
|
58
|
+
self, query_id: int, api_key: str, limit: int = 10
|
|
59
|
+
) -> Dict[str, Any]:
|
|
60
|
+
"""Fetch data for a specific Dune query.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
query_id: Dune query ID.
|
|
64
|
+
api_key: Dune API key.
|
|
65
|
+
limit: Maximum number of results (default 10).
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Dictionary of query results.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
ToolException: If the API request fails.
|
|
72
|
+
"""
|
|
73
|
+
from langchain.tools.base import ToolException
|
|
74
|
+
|
|
75
|
+
url = f"{BASE_URL}/{query_id}/results?limit={limit}"
|
|
76
|
+
headers = {"X-Dune-API-Key": api_key}
|
|
77
|
+
|
|
78
|
+
async with httpx.AsyncClient() as client:
|
|
79
|
+
try:
|
|
80
|
+
response = await client.get(url, headers=headers, timeout=10)
|
|
81
|
+
response.raise_for_status()
|
|
82
|
+
return response.json().get("result", {})
|
|
83
|
+
except (httpx.RequestError, httpx.HTTPStatusError) as e:
|
|
84
|
+
raise ToolException(f"Error fetching data from Dune API: {e}")
|
|
85
|
+
|
|
86
|
+
async def _arun(
|
|
87
|
+
self,
|
|
88
|
+
limit: int = 10,
|
|
89
|
+
**kwargs,
|
|
90
|
+
) -> str:
|
|
91
|
+
"""Fetch KOL memecoin buys asynchronously and return formatted output.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
limit: Maximum number of buy transactions to fetch (default 10).
|
|
95
|
+
config: Runnable configuration.
|
|
96
|
+
**kwargs: Additional keyword arguments.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Formatted string with KOL buy transactions or error message.
|
|
100
|
+
"""
|
|
101
|
+
import logging
|
|
102
|
+
|
|
103
|
+
logger = logging.getLogger(__name__)
|
|
104
|
+
api_key = self.get_api_key()
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
data = await self.fetch_data(KOL_BUYS_QUERY_ID, api_key, limit)
|
|
108
|
+
rows = data.get("rows", [])
|
|
109
|
+
if not rows:
|
|
110
|
+
return "No KOL buy transactions found."
|
|
111
|
+
|
|
112
|
+
output = f"Fetched {len(rows)} KOL memecoin buy transactions:\n"
|
|
113
|
+
for row in rows:
|
|
114
|
+
output += (
|
|
115
|
+
f"- {row['kol_with_link']} bought {row['token_with_chart']} "
|
|
116
|
+
f"(${row['amount_usd']:.2f}) at {row['buy_time']}\n"
|
|
117
|
+
)
|
|
118
|
+
return output.strip()
|
|
119
|
+
except Exception as e:
|
|
120
|
+
error_msg = f"Error fetching KOL memecoin buys: {str(e)}"
|
|
121
|
+
logger.warning(error_msg)
|
|
122
|
+
return error_msg
|
|
123
|
+
|
|
124
|
+
def _run(self, question: str):
|
|
125
|
+
raise NotImplementedError("Use _arun for async execution")
|