mezoAgent 0.2.4__py3-none-any.whl → 0.3.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mezoAgent
3
- Version: 0.2.4
3
+ Version: 0.3.1
4
4
  Summary: A LangChain based tool kit for AI Agents to send BTC and mUSD transactions on Mezo Matsnet.
5
5
  Author: Dreadwulf, Duck, Digi
6
6
  Requires-Python: >=3.7
@@ -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
- # Load environment variables
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
- # Define RPC URL and initialize Web3
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
- if not web3_instance.is_connected():
29
- raise ConnectionError("❌ Failed to connect to Mezo Matsnet RPC.")
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
- # Set up contract details (for mUSD)
32
+ # mUSD Contract Setup using approve/allowance ABI
40
33
  MUSD_ADDRESS = "0x637e22A1EBbca50EA2d34027c238317fD10003eB"
41
34
  ERC20_ABI = json.loads(
42
- '[{"constant": false, "inputs": [{"name": "recipient", "type": "address"},'
43
- '{"name": "amount", "type": "uint256"}],"name": "transfer","outputs": [{"name": "", "type": "bool"}],'
44
- '"stateMutability": "nonpayable","type":"function"}]'
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()}"
@@ -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,,