mezoAgent 0.2.4__py3-none-any.whl → 0.3.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {mezoAgent-0.2.4.dist-info → mezoAgent-0.3.1.dist-info}/METADATA +1 -1
- mezoAgent-0.3.1.dist-info/RECORD +9 -0
- mezo_agent/__init__.py +2 -1
- mezo_agent/config.py +23 -19
- mezo_agent/parsing.py +30 -1
- mezo_agent/swap_musd_btc.py +112 -0
- mezoAgent-0.2.4.dist-info/RECORD +0 -8
- {mezoAgent-0.2.4.dist-info → mezoAgent-0.3.1.dist-info}/WHEEL +0 -0
- {mezoAgent-0.2.4.dist-info → mezoAgent-0.3.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,9 @@
|
|
1
|
+
mezo_agent/__init__.py,sha256=XOJWLvrxgH7jBkKdXFLVGLV2dmCyyRpo8VcjicWBD0I,133
|
2
|
+
mezo_agent/config.py,sha256=WXzqmJ52kwMcRLIX5Pziq6cP4Zxj9wL6r7CIWvmmURk,2150
|
3
|
+
mezo_agent/parsing.py,sha256=rolPVE8r_RS6BqKe25r1nyZQ47rvTPG2Hv09Kxxfv4c,2821
|
4
|
+
mezo_agent/swap_musd_btc.py,sha256=Co-XcfK73spm94VC6qzGY0VYoGwsMDKKHM8ToGh2JxU,4289
|
5
|
+
mezo_agent/transaction.py,sha256=YpfWrkEaf0YGM_Kc4cFwlT9GmBGZkeJHWm0VGHs9Gks,4199
|
6
|
+
mezoAgent-0.3.1.dist-info/METADATA,sha256=VXHIaC450cMMhGoxON7TAcepsqilXN2OkIkSRpMzHSM,323
|
7
|
+
mezoAgent-0.3.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
8
|
+
mezoAgent-0.3.1.dist-info/top_level.txt,sha256=rrAci_NyTR9z6w_BrQhQrAhzMW_A0NYhVa0x2USl0nQ,11
|
9
|
+
mezoAgent-0.3.1.dist-info/RECORD,,
|
mezo_agent/__init__.py
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
from .transaction import mezo_agent_transaction_btc, mezo_agent_musd_transaction
|
1
|
+
from .transaction import mezo_agent_transaction_btc, mezo_agent_musd_transaction
|
2
|
+
from .swap_musd_btc import mezo_agent_swap_musd_btc
|
mezo_agent/config.py
CHANGED
@@ -2,9 +2,10 @@ import os
|
|
2
2
|
import json
|
3
3
|
from dotenv import load_dotenv
|
4
4
|
from web3 import Web3
|
5
|
-
from web3.exceptions import Web3Exception
|
6
5
|
|
7
|
-
#
|
6
|
+
# Load environment variables
|
7
|
+
load_dotenv()
|
8
|
+
|
8
9
|
USER_PROJECT_DIR = os.getcwd()
|
9
10
|
USER_ENV_PATH = os.path.join(USER_PROJECT_DIR, ".env")
|
10
11
|
|
@@ -13,7 +14,6 @@ if os.path.exists(USER_ENV_PATH):
|
|
13
14
|
else:
|
14
15
|
print("⚠️ Warning: No `.env` file found in your project directory! Transactions requiring signing may fail.")
|
15
16
|
|
16
|
-
# ✅ Load keys from the environment
|
17
17
|
PRIVATE_KEY = os.getenv("PRIVATE_KEY")
|
18
18
|
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
19
19
|
|
@@ -21,26 +21,30 @@ if not PRIVATE_KEY:
|
|
21
21
|
print("⚠️ Warning: PRIVATE_KEY not set. Please create a `.env` file in your project with your keys.")
|
22
22
|
PRIVATE_KEY = None # Allow package to be installed but prevent transactions
|
23
23
|
|
24
|
-
#
|
24
|
+
# Mezo Testnet RPC and Web3 initialization
|
25
25
|
RPC_URL = "https://rpc.test.mezo.org"
|
26
26
|
web3_instance = Web3(Web3.HTTPProvider(RPC_URL))
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# ✅ Initialize account and sender address
|
32
|
-
if PRIVATE_KEY:
|
33
|
-
account = web3_instance.eth.account.from_key(PRIVATE_KEY)
|
34
|
-
sender_address = account.address
|
35
|
-
else:
|
36
|
-
account = None
|
37
|
-
sender_address = None
|
28
|
+
# Create Account Object
|
29
|
+
account = web3_instance.eth.account.from_key(PRIVATE_KEY)
|
30
|
+
sender_address = account.address
|
38
31
|
|
39
|
-
#
|
32
|
+
# mUSD Contract Setup using approve/allowance ABI
|
40
33
|
MUSD_ADDRESS = "0x637e22A1EBbca50EA2d34027c238317fD10003eB"
|
41
34
|
ERC20_ABI = json.loads(
|
42
|
-
'[{"constant": false, "inputs": [{"name": "
|
43
|
-
'
|
44
|
-
'"
|
35
|
+
'[{"constant": false, "inputs": [{"name": "spender", "type": "address"}, {"name": "amount", "type": "uint256"}],'
|
36
|
+
'"name": "approve", "outputs": [{"name": "", "type": "bool"}], "stateMutability": "nonpayable", "type": "function"},'
|
37
|
+
'{"constant": true, "inputs": [{"name": "owner", "type": "address"}, {"name": "spender", "type": "address"}],'
|
38
|
+
'"name": "allowance", "outputs": [{"name": "remaining", "type": "uint256"}], "stateMutability": "view", "type": "function"}]'
|
45
39
|
)
|
46
|
-
musd_contract = web3_instance.eth.contract(address=MUSD_ADDRESS, abi=ERC20_ABI)
|
40
|
+
musd_contract = web3_instance.eth.contract(address=MUSD_ADDRESS, abi=ERC20_ABI)
|
41
|
+
|
42
|
+
# Wrapped BTC and Swap Router setup
|
43
|
+
WRAPPED_BTC_ADDRESS = "0xA460F83cdd9584E4bD6a9838abb0baC58EAde999"
|
44
|
+
ROUTER_ADDRESS = "0xC2E61936a542D78b9c3AA024fA141c4C632DF6c1"
|
45
|
+
|
46
|
+
# Load router ABI from a JSON file packaged with mezoAgent
|
47
|
+
router_abi_path = os.path.join(os.path.dirname(__file__), "new_router_abi.json")
|
48
|
+
with open(router_abi_path, "r") as f:
|
49
|
+
router_abi = json.load(f)
|
50
|
+
router_contract = web3_instance.eth.contract(address=ROUTER_ADDRESS, abi=router_abi)
|
mezo_agent/parsing.py
CHANGED
@@ -33,4 +33,33 @@ def extract_transaction_details(prompt: str):
|
|
33
33
|
try:
|
34
34
|
return output_parser.parse(response.content)
|
35
35
|
except Exception as e:
|
36
|
-
return f"❌ Failed to extract transaction details: {str(e)}"
|
36
|
+
return f"❌ Failed to extract transaction details: {str(e)}"
|
37
|
+
|
38
|
+
|
39
|
+
swap_response_schemas = [
|
40
|
+
ResponseSchema(name="amount", description="The amount of mUSD to swap."),
|
41
|
+
ResponseSchema(name="from_currency", description="The token to swap from (should always be 'mUSD')."),
|
42
|
+
ResponseSchema(name="to_currency", description="The token to receive (should always be 'BTC')."),
|
43
|
+
ResponseSchema(name="router_address", description="The Dumpy Swap router address for executing the swap."),
|
44
|
+
]
|
45
|
+
swap_output_parser = StructuredOutputParser.from_response_schemas(swap_response_schemas)
|
46
|
+
|
47
|
+
swap_prompt_template = PromptTemplate(
|
48
|
+
template=(
|
49
|
+
"Extract swap transaction details from this request:\n{input}\n\n"
|
50
|
+
"- The token to swap from should always be 'mUSD'.\n"
|
51
|
+
"- The token to receive should always be 'BTC'.\n"
|
52
|
+
"- The router address should always be '0xC2E61936a542D78b9c3AA024fA141c4C632DF6c1'.\n\n"
|
53
|
+
"{format_instructions}"
|
54
|
+
),
|
55
|
+
input_variables=["input"],
|
56
|
+
partial_variables={"format_instructions": swap_output_parser.get_format_instructions()},
|
57
|
+
)
|
58
|
+
|
59
|
+
def extract_swap_details(prompt: str):
|
60
|
+
formatted_prompt = swap_prompt_template.format(input=prompt)
|
61
|
+
response = llm.invoke(formatted_prompt)
|
62
|
+
try:
|
63
|
+
return swap_output_parser.parse(response.content)
|
64
|
+
except Exception as e:
|
65
|
+
return f"Failed to extract swap details: {str(e)}"
|
@@ -0,0 +1,112 @@
|
|
1
|
+
import time
|
2
|
+
from langchain.tools import tool
|
3
|
+
from .config import (
|
4
|
+
web3_instance,
|
5
|
+
sender_address,
|
6
|
+
account,
|
7
|
+
PRIVATE_KEY,
|
8
|
+
musd_contract,
|
9
|
+
ROUTER_ADDRESS,
|
10
|
+
router_contract,
|
11
|
+
MUSD_ADDRESS,
|
12
|
+
WRAPPED_BTC_ADDRESS
|
13
|
+
)
|
14
|
+
from .parsing import extract_swap_details
|
15
|
+
|
16
|
+
def approve_if_needed(token_contract, amount_wei):
|
17
|
+
"""
|
18
|
+
Checks if the router has enough allowance to spend tokens.
|
19
|
+
If not, sends an approval transaction.
|
20
|
+
"""
|
21
|
+
current_allowance = token_contract.functions.allowance(sender_address, ROUTER_ADDRESS).call()
|
22
|
+
if current_allowance < amount_wei:
|
23
|
+
print(f"Current allowance ({current_allowance}) is less than required ({amount_wei}). Approving...")
|
24
|
+
nonce = web3_instance.eth.get_transaction_count(sender_address)
|
25
|
+
gas_price = web3_instance.eth.gas_price
|
26
|
+
approve_tx = token_contract.functions.approve(ROUTER_ADDRESS, amount_wei).build_transaction({
|
27
|
+
"from": sender_address,
|
28
|
+
"nonce": nonce,
|
29
|
+
"gas": 50000,
|
30
|
+
"gasPrice": gas_price,
|
31
|
+
})
|
32
|
+
signed_tx = web3_instance.eth.account.sign_transaction(approve_tx, PRIVATE_KEY)
|
33
|
+
tx_hash = web3_instance.eth.send_raw_transaction(signed_tx.raw_transaction)
|
34
|
+
receipt = web3_instance.eth.wait_for_transaction_receipt(tx_hash)
|
35
|
+
if receipt.status != 1:
|
36
|
+
raise Exception("Approval transaction failed.")
|
37
|
+
print(f"Approval successful. TX Hash: {tx_hash.hex()}")
|
38
|
+
else:
|
39
|
+
print("Sufficient allowance already set.")
|
40
|
+
|
41
|
+
@tool
|
42
|
+
def mezo_agent_swap_musd_btc(prompt: str) -> str:
|
43
|
+
"""
|
44
|
+
Swaps mUSD for Wrapped BTC using the Dumpy Swap router.
|
45
|
+
|
46
|
+
This tool extracts swap details from the prompt, approves the router if needed,
|
47
|
+
and executes the swap transaction.
|
48
|
+
|
49
|
+
The prompt should specify the mUSD amount to swap.
|
50
|
+
"""
|
51
|
+
swap_details = extract_swap_details(prompt)
|
52
|
+
if isinstance(swap_details, str):
|
53
|
+
return swap_details
|
54
|
+
|
55
|
+
try:
|
56
|
+
amount_musd = float(swap_details["amount"])
|
57
|
+
except KeyError as e:
|
58
|
+
return f"❌ Missing key in swap details: {str(e)}"
|
59
|
+
|
60
|
+
# For demonstration, we use a dummy minimum Wrapped BTC amount.
|
61
|
+
min_wrapped_btc = 0.000000000000001 # in BTC
|
62
|
+
|
63
|
+
# Convert amounts to Wei (assuming 18 decimals)
|
64
|
+
amount_musd_wei = int(amount_musd * 10**18)
|
65
|
+
min_wrapped_btc_wei = int(min_wrapped_btc * 10**18)
|
66
|
+
deadline = int(time.time()) + 600 # 10 minutes from now
|
67
|
+
|
68
|
+
# Approve the router to spend mUSD if needed
|
69
|
+
try:
|
70
|
+
approve_if_needed(musd_contract, amount_musd_wei)
|
71
|
+
except Exception as e:
|
72
|
+
return f"❌ Approval failed: {str(e)}"
|
73
|
+
|
74
|
+
# Define the swap path: mUSD -> Wrapped BTC
|
75
|
+
path = [MUSD_ADDRESS, WRAPPED_BTC_ADDRESS]
|
76
|
+
|
77
|
+
nonce = web3_instance.eth.get_transaction_count(sender_address)
|
78
|
+
gas_price = web3_instance.eth.gas_price
|
79
|
+
|
80
|
+
try:
|
81
|
+
swap_tx = router_contract.functions.swapExactTokensForTokens(
|
82
|
+
amount_musd_wei, # mUSD amount
|
83
|
+
min_wrapped_btc_wei, # Minimum Wrapped BTC to receive
|
84
|
+
path, # Swap path
|
85
|
+
sender_address, # Recipient address
|
86
|
+
deadline # Transaction deadline
|
87
|
+
).build_transaction({
|
88
|
+
"from": sender_address,
|
89
|
+
"nonce": nonce,
|
90
|
+
"gasPrice": gas_price,
|
91
|
+
})
|
92
|
+
except Exception as e:
|
93
|
+
return f"❌ Failed to build swap transaction: {str(e)}"
|
94
|
+
|
95
|
+
# Estimate gas and add a buffer
|
96
|
+
try:
|
97
|
+
estimated_gas = web3_instance.eth.estimate_gas(swap_tx)
|
98
|
+
swap_tx["gas"] = estimated_gas + 10000
|
99
|
+
except Exception as e:
|
100
|
+
swap_tx["gas"] = 250000 # Fallback gas limit
|
101
|
+
|
102
|
+
try:
|
103
|
+
signed_swap_tx = web3_instance.eth.account.sign_transaction(swap_tx, PRIVATE_KEY)
|
104
|
+
tx_hash = web3_instance.eth.send_raw_transaction(signed_swap_tx.raw_transaction)
|
105
|
+
except Exception as e:
|
106
|
+
return f"❌ Swap transaction failed: {str(e)}"
|
107
|
+
|
108
|
+
receipt = web3_instance.eth.wait_for_transaction_receipt(tx_hash)
|
109
|
+
if receipt.status != 1:
|
110
|
+
return f"❌ Swap transaction failed. Receipt: {receipt}"
|
111
|
+
|
112
|
+
return f"✅ Swap Successful! TX Hash: {tx_hash.hex()}"
|
mezoAgent-0.2.4.dist-info/RECORD
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
mezo_agent/__init__.py,sha256=lsonH0-yY3Die0cRmiwsPSHwZQDh_UEAVIpc2uwZYIM,80
|
2
|
-
mezo_agent/config.py,sha256=c16-JHEbK5rFBKO-QdxBRtrl4DSlYzGckD9BzbTw2dY,1708
|
3
|
-
mezo_agent/parsing.py,sha256=dFqNHGH0LoG4_TEsHKcorj6aY_Rh4H8f5Yj7ZdfKJzE,1454
|
4
|
-
mezo_agent/transaction.py,sha256=YpfWrkEaf0YGM_Kc4cFwlT9GmBGZkeJHWm0VGHs9Gks,4199
|
5
|
-
mezoAgent-0.2.4.dist-info/METADATA,sha256=ACNVZPv9OaqSgU_81bYj8BDGR3-ze1IPqkH89PEcD0g,323
|
6
|
-
mezoAgent-0.2.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
7
|
-
mezoAgent-0.2.4.dist-info/top_level.txt,sha256=rrAci_NyTR9z6w_BrQhQrAhzMW_A0NYhVa0x2USl0nQ,11
|
8
|
-
mezoAgent-0.2.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|