Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ jobs:
--name pattern-core-api \
--network pattern_core_network \
-p 5001:8000 \
-e OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} \
-e POSTGRES_HOST=api-postgres-1 \
-e POSTGRES_PORT=5432 \
-e POSTGRES_DB=pattern-core \
Expand All @@ -71,17 +70,15 @@ jobs:
-e JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} \
-e QDRANT_HOST=http://qdrant:6333 \
-e QDRANT_COLLECTION=pattern-core \
-e LANGCHAIN_API_KEY=${{ secrets.LANGCHAIN_API_KEY }} \
-e GOOGLE_SEARCH_URL=https://google.serper.dev/search \
-e REDDIT_SEARCH_URL=https://reddit-scraper2.p.rapidapi.com/search_posts \
-e LINKEDIN_SEARCH_URL=https://linkedin-data-api.p.rapidapi.com/search-posts \
-e WEATHER_URL=https://api.weatherapi.com/v1/current.json \
-e ETH_RPC=https://ethereum-rpc.publicnode.com \
-e GOLDRUSH_URL=https://api.covalenthq.com \
-e EXA_URL=https://api.exa.ai \
-e PERPLEXITY_URL=https://api.perplexity.ai \
-e TAVILY_URL=https://api.tavily.com \
-e SECRET_KEY=${{ secrets.SECRET_KEY }} \
-e MORALIS_API_KEY=${{ secrets.MORALIS_API_KEY }} \
-e ETHER_SCAN_API_KEY=${{ secrets.ETHER_SCAN_API_KEY }} \
-e GOLDRUSH_API_KEY=${{ secrets.GOLDRUSH_API_KEY }} \
-e ETH_RPC_URL=${{ secrets.ETH_RPC_URL }} \
-e LLM_PROVIDER=${{ secrets.LLM_PROVIDER }} \
-e LLM_MODEL=${{ secrets.LLM_MODEL }} \
-e LLM_API_KEY=${{ secrets.LLM_API_KEY }} \
-e AGENTS=${{ secrets.AGENTS }} \
-e SENTRY_DNS=${{ secrets.SENTRY_DNS }} \
patterntechnology/pattern-core-api:latest

# Wait a few seconds to give the container time to start
Expand Down
43 changes: 42 additions & 1 deletion api/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,45 @@ log_max_bytes=5242880 # 5 * 1024 * 1024
#------------------------
# SENTRY (Optional)
#------------------------
SENTRY_DSN=
SENTRY_DNS=


#------------------------
# LLM
#------------------------

# +-------------+------------------------------------------------+
# | Provider | Recommended Model |
# +-------------+------------------------------------------------+
# | openai | gpt-4o-mini |
# | google | gemini-2.0-flash |
# | together | deepseek-ai/DeepSeek-R1-Distill-Llama-70B-free |
# | ollama | llama3.3 |
# | groq | llama-3.3-70b-versatile |
# | firework | accounts/fireworks/models/firefunction-v2 |
# | huggingface | meta-llama/Llama-3.3-70B-Instruct |
# +-------------+------------------------------------------------+
LLM_PROVIDER=openai
LLM_MODEL=gpt-4o-mini
LLM_API_KEY=
LLM_HOST=
LLM_MODELS_PATH=


#------------------------
# SERVICES
#------------------------
ETHER_SCAN_API_KEY=
GOLDRUSH_API_KEY=
MORALIS_API_KEY=
EXA_API_KEY=
PERPLEXITY_API_KEY=
TAVILY_API_KEY=

ETH_RPC_URL=


#------------------------
# Agents
#------------------------
AGENTS=ETHER_SCAN,GOLDRUSH,MORALIS
45 changes: 2 additions & 43 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,16 @@ To install the required dependencies, run:

```sh
cp .env.example .env
cp config.json.example config.json
pip install -r requirements.txt
```

Note: Fill up the .env and config.json file according to your config
Note: Fill up the `.env` file according to your config

### Configuration
Configuration file is in `config.json`. Edit it according to your needs.

Notes:
- Add your own tool services or use existing ones
- Add provided agents. (on top of each service tool is an agent so the name of agent should be same as service name)
- Add provided agents (currently : ``ETHER_SCAN, MORALIS, GOLDRUSH``)
- Choose the llm provider
<table>
<thead>
<tr>
<th>Supported Provider</th>
<th>Recommended Model</th>
</tr>
</thead>
<tbody>
<tr>
<td>openai</td>
<td>gpt-4o-mini</td>
</tr>
<tr>
<td>google</td>
<td>gemini-2.0-flash</td>
</tr>
<tr>
<td>together</td>
<td>deepseek-ai/DeepSeek-R1-Distill-Llama-70B-free</td>
</tr>
<tr>
<td>ollama</td>
<td>llama3.3</td>
</tr>
<tr>
<td>groq</td>
<td>llama-3.3-70b-versatile</td>
</tr>
<tr>
<td>firework</td>
<td>accounts/fireworks/models/firefunction-v2</td>
</tr>
<tr>
<td>huggingface</td>
<td>meta-llama/Llama-3.3-70B-Instruct</td>
</tr>
</tbody>
</table>

### Running the Application

Expand Down
53 changes: 0 additions & 53 deletions api/config.json.sample

This file was deleted.

6 changes: 3 additions & 3 deletions api/src/agentflow/agents/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class AgentHub:

def __init__(self):
self.agents = {
"etherscan": ether_scan_agent.etherscan_agent,
"goldrush": goldrush_agent.goldrush_agent,
"moralis": moralis_agent.moralis_agent
"ETHER_SCAN": ether_scan_agent.etherscan_agent,
"GOLDRUSH": goldrush_agent.goldrush_agent,
"MORALIS": moralis_agent.moralis_agent
}

def get_agents(self, agent_names: List[str]) -> List[Any]:
Expand Down
15 changes: 8 additions & 7 deletions api/src/agentflow/providers/ether_scan_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@


_config = Config.get_config()
_eth_rpc_config = Config.get_service_config(_config, "eth_rpc")
_ether_scan_config = Config.get_service_config(_config, "etherscan")
_ether_scan_config = Config.get_service_config(_config, "ETHER_SCAN")

_ETHERSCAN_URL = "https://api.etherscan.io/v2/api"
_ETH_RPC = os.environ["ETH_RPC"]

@handle_exceptions
def fetch_contract_abi(contract_address: str, api_key: str) -> Dict:
Expand All @@ -29,7 +30,7 @@ def fetch_contract_abi(contract_address: str, api_key: str) -> Dict:
Returns:
Dict: A dictionary representing the contract ABI.
"""
url = _ether_scan_config["url"]
url = _ETHERSCAN_URL
params = {
"chainid": "1",
"module": "contract",
Expand Down Expand Up @@ -58,7 +59,7 @@ def fetch_contract_source_code(contract_address: str, api_key: str) -> str:
Returns:
str: The contract source code.
"""
url = _ether_scan_config["url"]
url = _ETHERSCAN_URL
params = {
"chainid": "1",
"module": "contract",
Expand Down Expand Up @@ -100,7 +101,7 @@ def timestamp_to_block_number(timestamp: int, api_key: str) -> int:
Returns:
int: The closest block number.
"""
url = _ether_scan_config["url"]
url = _ETHERSCAN_URL
params = {
"chainid": "1",
"module": "block",
Expand Down Expand Up @@ -229,7 +230,7 @@ def get_contract_events(
api_key = _ether_scan_config["api_key"]
abi = fetch_contract_abi(contract_address, api_key)

web3 = Web3(Web3.HTTPProvider(_eth_rpc_config["url"]))
web3 = Web3(Web3.HTTPProvider(_ETH_RPC))
contract = web3.eth.contract(address=contract_address, abi=abi)

# Resolve the actual event name case-insensitively
Expand Down Expand Up @@ -262,7 +263,7 @@ def get_latest_eth_block_number() -> int:
Returns:
int: The current block number on the Ethereum mainnet.
"""
web3 = Web3(Web3.HTTPProvider(_eth_rpc_config["url"]))
web3 = Web3(Web3.HTTPProvider(_ETH_RPC))
return web3.eth.block_number


Expand Down
16 changes: 9 additions & 7 deletions api/src/agentflow/providers/goldrush_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@


_config = Config.get_config()
_goldrush_config = Config.get_service_config(_config, "goldrush")
_goldrush_config = Config.get_service_config(_config, "GOLDRUSH")

_GOLDRUSH_URL = "https://api.covalenthq.com"


def _call_goldrush_api(url: str, params: Optional[Dict[str, Any]] = None) -> Dict:
Expand Down Expand Up @@ -49,7 +51,7 @@ def get_wallet_activity(wallet_address: str, output_include: list[str]) -> List[
- name, chain_id, is_testnet, db_schema_name, label, category_label, logo_url,
black_logo_url, white_logo_url, color_theme, is_appchain, appchain_of, last_seen_at
"""
base_url = _goldrush_config["url"]
base_url = _GOLDRUSH_URL
url = f"{base_url}/v1/address/{wallet_address}/activity/"
data = _call_goldrush_api(url)
results = data["data"]["items"]
Expand Down Expand Up @@ -82,7 +84,7 @@ def get_balance_for_address(wallet_address: str, output_include: list[str]) -> s
supports_erc, logo_url, logo_urls, last_transferred_at, native_token, type, is_spam, balance, balance_24h,
quote_rate, quote_rate_24h, quote, quote_24h, pretty_quote, pretty_quote_24h, protocol_metadata.
"""
base_url = _goldrush_config["url"]
base_url = _GOLDRUSH_URL
chain_name = "eth-mainnet"
url = f"{base_url}/v1/{chain_name}/address/{wallet_address}/balances_v2/"
data = _call_goldrush_api(url)
Expand Down Expand Up @@ -117,7 +119,7 @@ def get_wallet_transactions(wallet_address: str, output_include: List[str], page
gas_offered, gas_spent, gas_price, fees_paid, gas_quote, pretty_gas_quote, gas_quote_rate, explorers,
log_events
"""
base_url = _goldrush_config["url"]
base_url = _GOLDRUSH_URL
chain_name = "eth-mainnet"
url = f"{base_url}/v1/{chain_name}/address/{wallet_address}/transactions_v3/page/{page}/"
data = _call_goldrush_api(url)
Expand All @@ -142,7 +144,7 @@ def get_transactions_summary(wallet_address: str) -> Dict:
Returns:
Dict: The transactions summary data.
"""
base_url = _goldrush_config["url"]
base_url = _GOLDRUSH_URL
chain_name = "eth-mainnet"
url = f"{base_url}/v1/{chain_name}/address/{wallet_address}/transactions_summary/"
data = _call_goldrush_api(url)
Expand Down Expand Up @@ -170,7 +172,7 @@ def get_transaction_detail(tx_hash: str, output_include: List[str]) -> List[Dict
gas_offered, gas_spent, gas_price, fees_paid, gas_quote, pretty_gas_quote, gas_quote_rate, explorers,
log_events, internal_transfers, state_changes, input_data
"""
base_url = _goldrush_config["url"]
base_url = _GOLDRUSH_URL
chain_name = "eth-mainnet"
url = f"{base_url}/v1/{chain_name}/transaction_v2/{tx_hash}/"
data = _call_goldrush_api(url)
Expand Down Expand Up @@ -203,7 +205,7 @@ def get_token_approvals(wallet_address: str, output_include: List[str]) -> Dict:
quote_rate, balance, balance_quote, pretty_balance_quote, value_at_risk, value_at_risk_quote,
pretty_value_at_risk_quote, spenders
"""
base_url = _goldrush_config["url"]
base_url = _GOLDRUSH_URL
chain_name = "eth-mainnet"
url = f"{base_url}/v1/{chain_name}/approvals/{wallet_address}/"
data = _call_goldrush_api(url)
Expand Down
5 changes: 3 additions & 2 deletions api/src/agentflow/providers/moralis_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
from src.agentflow.utils.shared_tools import handle_exceptions

_config = Config.get_config()
_moralis_config = Config.get_service_config(_config, "moralis")
_moralis_config = Config.get_service_config(_config, "MORALIS")

_MORALIS_URL = "https://deep-index.moralis.io/api/v2"

@tool
@handle_exceptions
Expand Down Expand Up @@ -226,7 +227,7 @@ def get_token_approvals(wallet_address: str, output_include: list[str], cursor:

- block_number, block_timestamp, transaction_hash, value, value_formatted, token, spender
"""
base_url = _moralis_config["url"]
base_url = _MORALIS_URL
api_url = f"{base_url}/wallets/{wallet_address}/approvals"

params = {'chain': 'eth'}
Expand Down
4 changes: 2 additions & 2 deletions api/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
load_dotenv()
_logger = Logging().get_logger()

if os.environ.get("SENTRY_DSN"):
if os.environ.get("SENTRY_DNS"):
# Initialize Sentry with your DSN
sentry_sdk.init(
dsn=os.environ.get("SENTRY_DSN"),
dsn=os.environ.get("SENTRY_DNS"),
# Add data like request headers and IP for users,
# see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
send_default_pii=True,
Expand Down
Loading