11from config .config import DatabaseConfig
22from lib .errors import ValidationError
3+ from tools .agent_templates import get_all_agents
34import logging
45from pydantic import BaseModel
56from fastapi import HTTPException
67from typing import Dict , Any , List
78import hashlib
89import re
910import uuid
11+ from datetime import datetime
12+ import json
1013
1114logger = logging .getLogger ("mcp.wallet" )
1215logger .setLevel (logging .INFO )
@@ -75,6 +78,18 @@ class WalletQuantumLinkOutput(BaseModel):
7578class WalletTool :
7679 def __init__ (self , db : DatabaseConfig ):
7780 self .db = db
81+ self .agents = {agent .get_metadata ()["vial_id" ]: agent .get_metadata () for agent in get_all_agents ()}
82+
83+ async def initialize_new_wallet (self , user_id : str , wallet_address : str , api_key : str , api_secret : str ):
84+ await self .db .query (
85+ "INSERT INTO users (user_id, balance, wallet_address, api_key, api_secret, reputation) VALUES ($1, $2, $3, $4, $5, $6)" ,
86+ [user_id , 0.0 , wallet_address , api_key , api_secret , 0 ]
87+ )
88+ for agent in self .agents .values ():
89+ await self .db .query (
90+ "INSERT INTO vials (user_id, vial_id, code, wallet_address, webxos_hash) VALUES ($1, $2, $3, $4, $5)" ,
91+ [user_id , agent ["vial_id" ], agent ["code" ], agent ["wallet_address" ], agent ["webxos_hash" ]]
92+ )
7893
7994 async def execute (self , input : Dict [str , Any ]) -> Any :
8095 try :
@@ -114,9 +129,10 @@ async def get_vial_balance(self, input: WalletBalanceInput) -> WalletBalanceOutp
114129 user = await self .db .query ("SELECT user_id, balance FROM users WHERE user_id = $1" , [input .user_id ])
115130 if not user .rows :
116131 raise ValidationError (f"User not found: { input .user_id } " )
117- balance = float (user .rows [0 ]["balance" ])
118- logger .info (f"Retrieved vial balance for { input .user_id } , vial { input .vial_id } : { balance } " )
119- return WalletBalanceOutput (vial_id = input .vial_id , balance = balance )
132+ total_balance = float (user .rows [0 ]["balance" ])
133+ vial_balance = total_balance / 4 # Split evenly across 4 vials
134+ logger .info (f"Retrieved vial balance for { input .user_id } , vial { input .vial_id } : { vial_balance } " )
135+ return WalletBalanceOutput (vial_id = input .vial_id , balance = vial_balance )
120136 except Exception as e :
121137 logger .error (f"Get vial balance error: { str (e )} " )
122138 raise HTTPException (400 , str (e ))
@@ -132,9 +148,20 @@ async def import_wallet(self, input: WalletImportInput) -> WalletImportOutput:
132148 raise ValidationError (f"User not found: { input .user_id } " )
133149
134150 balances = []
135- for line in input .markdown .splitlines ():
136- if match := re .match (r".*balance\s*=\s*(\d+\.\d+)" , line ):
151+ vials = []
152+ for section in input .markdown .split ("---" ):
153+ if match := re .search (r"Wallet Balance: (\d+\.\d{4}) \$WEBXOS" , section ):
137154 balances .append (float (match .group (1 )))
155+ if match := re .search (r"# Vial Agent: (vial\d+)" , section ):
156+ vials .append (match .group (1 ))
157+ if match := re .search (r"```python\n([\s\S]+?)\n```" , section ):
158+ code = match .group (1 )
159+ vial_id = section .split ("Vial Agent: " )[1 ].split ("\n " )[0 ]
160+ webxos_hash = hashlib .sha256 (f"{ vial_id } { uuid .uuid4 ()} " .encode ()).hexdigest ()
161+ await self .db .query (
162+ "UPDATE vials SET code = $1, webxos_hash = $2 WHERE user_id = $3 AND vial_id = $4" ,
163+ [code , webxos_hash , input .user_id , vial_id ]
164+ )
138165
139166 total_balance = sum (balances )
140167 current_balance = float (user .rows [0 ]["balance" ])
@@ -147,7 +174,7 @@ async def import_wallet(self, input: WalletImportInput) -> WalletImportOutput:
147174
148175 logger .info (f"Imported wallet for { input .user_id } , new balance: { new_balance } " )
149176 return WalletImportOutput (
150- imported_vials = [ f"vial { i + 1 } " for i in range ( len ( balances ))] ,
177+ imported_vials = vials ,
151178 total_balance = new_balance
152179 )
153180 except Exception as e :
@@ -162,6 +189,8 @@ async def batch_sync(self, input: WalletBatchSyncInput) -> WalletBatchSyncOutput
162189
163190 current_balance = float (user .rows [0 ]["balance" ])
164191 results = []
192+ import_vials = []
193+ mining_ops = []
165194
166195 for op in input .operations :
167196 if op ["method" ] == "importWallet" :
@@ -171,30 +200,52 @@ async def batch_sync(self, input: WalletBatchSyncInput) -> WalletBatchSyncOutput
171200 continue
172201
173202 balances = []
174- for line in op ["markdown" ].splitlines ():
175- if match := re .match (r".*balance\s*=\s*(\d+\.\d+)" , line ):
203+ vials = []
204+ for section in op ["markdown" ].split ("---" ):
205+ if match := re .search (r"Wallet Balance: (\d+\.\d{4}) \$WEBXOS" , section ):
176206 balances .append (float (match .group (1 )))
207+ if match := re .search (r"# Vial Agent: (vial\d+)" , section ):
208+ vials .append (match .group (1 ))
209+ if match := re .search (r"```python\n([\s\S]+?)\n```" , section ):
210+ code = match .group (1 )
211+ vial_id = section .split ("Vial Agent: " )[1 ].split ("\n " )[0 ]
212+ webxos_hash = hashlib .sha256 (f"{ vial_id } { uuid .uuid4 ()} " .encode ()).hexdigest ()
213+ await self .db .query (
214+ "UPDATE vials SET code = $1, webxos_hash = $2 WHERE user_id = $3 AND vial_id = $4" ,
215+ [code , webxos_hash , input .user_id , vial_id ]
216+ )
177217
178218 total_balance = sum (balances )
179- current_balance += total_balance
180- results .append ({"imported_vials" : [f"vial{ i + 1 } " for i in range (len (balances ))], "total_balance" : current_balance })
219+ import_vials .append ((total_balance , vials ))
181220
182221 elif op ["method" ] == "mineVial" :
183- data = f"{ input .user_id } { op ['vial_id' ]} { op ['nonce' ]} "
184- hash_value = hashlib .sha256 (data .encode ()).hexdigest ()
185- difficulty = 2
186- reward = 0.0
187-
188- if hash_value .startswith ("0" * difficulty ):
189- reward = 1.0
190- current_balance += reward
191-
192- results .append ({"hash" : hash_value , "reward" : reward , "balance" : current_balance })
222+ mining_ops .append ((op ["vial_id" ], op ["nonce" ]))
193223
194- await self .db .query (
195- "UPDATE users SET balance = $1 WHERE user_id = $2" ,
196- [current_balance , input .user_id ]
197- )
224+ if import_vials :
225+ total_import_balance = sum (v [0 ] for v in import_vials )
226+ current_balance += total_import_balance
227+ await self .db .query (
228+ "UPDATE users SET balance = $1 WHERE user_id = $2" ,
229+ [current_balance , input .user_id ]
230+ )
231+ for total_balance , vials in import_vials :
232+ results .append ({"imported_vials" : vials , "total_balance" : current_balance })
233+
234+ for vial_id , nonce in mining_ops :
235+ data = f"{ input .user_id } { vial_id } { nonce } "
236+ hash_value = hashlib .sha256 (data .encode ()).hexdigest ()
237+ difficulty = 2
238+ reward = 0.0
239+
240+ if hash_value .startswith ("0" * difficulty ):
241+ reward = 1.0
242+ current_balance += reward
243+ await self .db .query (
244+ "UPDATE users SET balance = $1 WHERE user_id = $2" ,
245+ [current_balance , input .user_id ]
246+ )
247+
248+ results .append ({"hash" : hash_value , "reward" : reward , "balance" : current_balance })
198249
199250 logger .info (f"Batch synced operations for { input .user_id } , new balance: { current_balance } " )
200251 return WalletBatchSyncOutput (results = results )
@@ -204,18 +255,81 @@ async def batch_sync(self, input: WalletBatchSyncInput) -> WalletBatchSyncOutput
204255
205256 async def export_vials (self , input : WalletBalanceInput ) -> WalletExportOutput :
206257 try :
207- user = await self .db .query ("SELECT user_id, balance FROM users WHERE user_id = $1" , [input .user_id ])
258+ user = await self .db .query ("SELECT user_id, balance, wallet_address, api_key, api_secret, reputation FROM users WHERE user_id = $1" , [input .user_id ])
208259 if not user .rows :
209260 raise ValidationError (f"User not found: { input .user_id } " )
210261
211- balance = float (user .rows [0 ]["balance" ])
212- markdown = f"""# Wallet Export for { input .user_id }
213- ## Vial Balances
214- - { input .vial_id } : { balance }
262+ total_balance = float (user .rows [0 ]["balance" ])
263+ wallet_address = user .rows [0 ]["wallet_address" ]
264+ api_key = user .rows [0 ]["api_key" ]
265+ api_secret = user .rows [0 ]["api_secret" ]
266+ reputation = user .rows [0 ]["reputation" ]
267+ network_id = str (uuid .uuid4 ())
268+ timestamp = datetime .utcnow ().strftime ("%Y-%m-%dT%H:%M:%S.%fZ" )[:- 3 ]
269+ vial_balance = total_balance / 4 # Split evenly across 4 vials
270+ blocks = 1958 # Static for demo
271+ hash_value = hashlib .sha256 (f"{ input .user_id } { wallet_address } { timestamp } " .encode ()).hexdigest ()
272+
273+ vials = await self .db .query ("SELECT vial_id, code, wallet_address, webxos_hash FROM vials WHERE user_id = $1" , [input .user_id ])
274+ vial_data = {row ["vial_id" ]: row for row in vials .rows } if vials .rows else self .agents
275+
276+ markdown = f"""# WebXOS Vial and Wallet Export
277+
278+ ## Agentic Network
279+ - Network ID: { network_id }
280+ - Session Start: { timestamp }
281+ - Session Duration: 0.00 seconds
282+ - Reputation: { reputation }
283+
284+ ## Wallet
285+ - Wallet Key: { str (uuid .uuid4 ())}
286+ - Session Balance: { total_balance :.4f} $WEBXOS
287+ - Address: { wallet_address }
288+ - Hash: { hash_value }
289+
290+ ## API Credentials
291+ - Key: { api_key }
292+ - Secret: { api_secret }
293+
294+ ## Blockchain
295+ - Blocks: { blocks }
296+ - Last Hash: { hash_value }
297+
298+ ## Vials
299+ """
300+ for vial_id in ["vial1" , "vial2" , "vial3" , "vial4" ]:
301+ agent = vial_data .get (vial_id , self .agents [vial_id ])
302+ markdown += f"""# Vial Agent: { vial_id }
303+ - Status: running
304+ - Language: Python
305+ - Code Length: { agent ["code_length" ]} bytes
306+ - $WEBXOS Hash: { agent ["webxos_hash" ]}
307+ - Wallet Balance: { vial_balance :.4f} $WEBXOS
308+ - Wallet Address: { agent ["wallet_address" ]}
309+ - Wallet Hash: { hash_value }
310+ - Tasks: none
311+ - Quantum State: { json .dumps (agent ["quantum_state" ], indent = 6 )}
312+ - Training Data: { json .dumps (agent ["training_data" ], indent = 6 )}
313+ - Config: {{}}
314+
315+ ```python
316+ { agent ["code" ]}
317+ ```
318+
319+ ---
320+ """
321+ markdown += """## Instructions
322+ - **Reuse**: Import this .md file via the "Import" button to resume training.
323+ - **Extend**: Modify agent code externally, then reimport.
324+ - **Share**: Send this .md file to others to continue training with the same wallet.
325+ - **API**: Use API credentials with LangChain to train vials (online mode only).
326+ - **Cash Out**: $WEBXOS balance and reputation are tied to the wallet address and hash for secure verification (online mode only).
327+
328+ Generated by Vial MCP Controller
215329"""
216- hash_value = hashlib .sha256 (markdown .encode ()).hexdigest ()
330+ final_hash = hashlib .sha256 (markdown .encode ()).hexdigest ()
217331 logger .info (f"Exported vials for { input .user_id } " )
218- return WalletExportOutput (markdown = markdown , hash = hash_value )
332+ return WalletExportOutput (markdown = markdown , hash = final_hash )
219333 except Exception as e :
220334 logger .error (f"Export vials error: { str (e )} " )
221335 raise HTTPException (400 , str (e ))
@@ -295,8 +409,8 @@ async def quantum_link(self, input: WalletQuantumLinkInput) -> WalletQuantumLink
295409
296410 link_id = str (uuid .uuid4 ())
297411 await self .db .query (
298- "INSERT INTO quantum_links (link_id, user_id) VALUES ($1, $2)" ,
299- [link_id , input .user_id ]
412+ "INSERT INTO quantum_links (link_id, user_id, quantum_state ) VALUES ($1, $2, $3 )" ,
413+ [link_id , input .user_id , json . dumps ({ "qubits" : [], "entanglement" : "synced" }) ]
300414 )
301415 logger .info (f"Established quantum link for { input .user_id } : { link_id } " )
302416 return WalletQuantumLinkOutput (link_id = link_id )
0 commit comments