using System; using System.Text; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using Console = HyperCube.Utils.AdvConsole; namespace HyperCube.Models { public class Blockchain { public static string Connected { get { var bc = GetMain(); if (bc != null) return $"{bc.name}"; return "none"; } } public static string URLdefault = "127.0.0.1"; public static int defaultPort = 8545; public static string defaultName = "Ethereum dev network"; public static bool newData = false; public static Dictionary loaded = new(); public Dictionary contracts = new(); public Dictionary contractNames = new(); public int port; public string url; public string address = ""; public string name; static Blockchain instance; public static Blockchain GetInstance() { if (instance == null) instance = new Blockchain(URLdefault, defaultPort); return instance; } Blockchain() { } public Blockchain(string url, int port) { this.url = url; this.port = port; } public async Task CreateBlockchainAccount(AccountModel account) { var res = await GetMain().RunFunction("personal_newAccount", "\"password\""); Console.WriteLine($"CreateBlockchainAccount {account}: {res}"); var query = $"update aspnetusers set eth_address='{res}' where UserName='{account.Name}'"; account.eth_address = res; Console.WriteLine($"CreateBlockchainAccount query {query}"); MySQLConnector.Instance().SQLInsert(query); return res; } public static string bin2hex(string code) { //code = "0x".bin2hex('getCount()'); var bytes = Encoding.UTF8.GetBytes(code); var hex = BitConverter.ToString(bytes).Replace("-", ""); Console.WriteLine("hex " + hex); return "0x" + hex; } public static string zerofill(string hex, int charCount, bool hexPrefix0x) { if (hexPrefix0x) hex = hex.Remove(0, 2); Console.WriteLine($"zerofill input {hex} count {hex.Length}"); var res = hex.PadLeft(charCount, '0'); Console.WriteLine($"zerofill out {hex} count {res.Length}"); return res; } public static Blockchain GetMain() { if (loaded.Count > 0) return loaded.Last().Value; return null; } public async Task Initialize() { string addr = await ListAccounts(); if (!loaded.ContainsKey(addr)) loaded.Add(addr, this); name = defaultName; url = URLdefault; port = defaultPort; Console.WriteLine("Initialize: loaded blockchains " + loaded.Count); await LoadContracts(); Console.WriteLine("LoadContracts count " + contracts.Count); Console.WriteLine("connected " + Connected); return $"{name} {url}:{port}"; } public async Task LoadContracts() { MySQLConnector dbCon = MySQLConnector.Instance(); contracts = await dbCon.SQLSelectContracts(); foreach (var contract in contracts.Values) { await contract.LoadFunction(); } } public static async Task GetSHA3(string code) { var hex = bin2hex(code); var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"web3_sha3\",\"params\":[\"{hex}\"], \"id\":1}}"; var answer = await Post.PostRequestAsync(req); dynamic jsonDe = JsonConvert.DeserializeObject(answer); Console.WriteLine("result " + jsonDe.result); return jsonDe.result; } public async Task RunFunction(string name, string parms) { Console.WriteLine($"RunFunction {name} params {parms}"); var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"{name}\",\"params\":[{parms}], \"id\":1}}"; var answer = await Post.PostRequestAsync(req); dynamic jsonDe = JsonConvert.DeserializeObject(answer); Console.WriteLine("RunFunction result " + jsonDe.result); return jsonDe.result; //return "test answer"; } public async Task GetBalance(string address) { var ret = await RunFunction("eth_getBalance", $"\"{address}\",\"latest\""); return ret; } public async void RunContractRead() { string answer = "no"; string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"to\":\"0x874c6a51e62680d4594cd2555ed8fa47b63ed253\", \"data\":\"0xa87d942c\"},\"latest\"],\"id\":1}"; //string req = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x0000000000000000000000000000000000000000000000000000000000000004\"}"; //Console.WriteLine($"req " + req); await Post.PostRequestAsync(req); //Console.WriteLine($"answer {answer} len {answer.Length}" ); address = answer; } public async Task SendTransaction(string fromAddress, string toAddress, string sum) { Console.WriteLine($"SendTransaction from {fromAddress} to {toAddress} sum {sum}"); var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{toAddress}\",\"gas\":\"0x31b2ef\", \"data\":\"\", \"value\":\"{sum}\"}}"); return answer; } //{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ "from":"0xD81eeE6b39d9556c3067A3551A3FB2882b92F327", "to":"0x119b58faddcdbc09cafcd272530aa079cec10004", "gas":"0x31b2ef", "data":"0x11111111"}], "id":1} public async Task RunContractWrite(string contractAddress, string data) { Console.WriteLine("RunContract contractAddress " + contractAddress); var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{contractAddress}\",\"gas\":\"0x31b2ef\", \"data\":\"{data}\", \"value\":\"0x32555\"}}"); //$"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_sendTransaction\",\"params\":[{{\"from\":\"{address}\",\"to\":\"{contractAddress}\",\"gas\":\"0x31b2ef\", \"data\":\"{data}\"}}], \"id\":1}}"; //var answer = await Post.PostRequestAsync(req); //dynamic jsonDe = JsonConvert.DeserializeObject(answer); //Console.WriteLine("result " + answer); return answer; } public async Task GetReceipt(string transactionAddress, bool returnAddress = false) { Console.WriteLine("transactionAddress " + transactionAddress); var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionReceipt\",\"params\":[\"{transactionAddress}\"], \"id\":1}}"; var answer = await Post.PostRequestAsync(req); dynamic jsonDe = JsonConvert.DeserializeObject(answer); var blockHash = jsonDe.result.blockHash; var blockNumber = jsonDe.result.blockNumber; var contractAddress = jsonDe.result.contractAddress; MySQLConnector.Instance().SQLInsert($"insert into transactions (result, name) values ('{Convert.ToString(jsonDe.result)}', 'eth_getTransactionReceipt')"); Console.WriteLine("result " + answer); if (returnAddress) return contractAddress; else return Convert.ToString(jsonDe.result); } public async void GetGas(string bytecode) { } public async Task AddContract(string name, string code, string bytecode) { Console.WriteLine("bytecode " + bytecode); var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_sendTransaction\",\"params\":[{{\"from\":\"{address}\",\"gas\":\"0x31b2e\", \"data\":\"{bytecode}\"}}], \"id\":1}}"; var answer = await Post.PostRequestAsync(req); dynamic jsonDe = JsonConvert.DeserializeObject(answer); var res = jsonDe.result; Console.WriteLine("result AddContract transactionAddress: " + res); if (res != null) { int id = (int)MySQLConnector.Instance().SQLInsert($"insert into smart_contracts (code, bytecode, name, date_add) values ('{code}','{bytecode}','{name}',NOW())"); SmartContract newctr = new SmartContract(id, name, code, bytecode); contracts.Add(id, newctr); contractNames.Add(name, newctr); return new object[] { res, newctr }; } return null; } public async Task ListAccounts() { string answer = "no"; //{ "jsonrpc":"2.0","method":"eth_getCode","params":["0x938cae6f6c21ed9d55196e96ef880f562e530553", "latest" ],"id":1} //string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getCode\",\"params\":[\"0x874c6a51e62680d4594cd2555ed8fa47b63ed253\",\"latest\"],\"id\":1}"; string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_accounts\", \"params\":[],\"id\":1}"; answer = await Post.PostRequestAsync(req); //string json = Encoding.UTF8.GetString(bytedata, 1, bytedata.Length - 1); //try //{ Console.WriteLine("Json string " + answer); dynamic jsonDe = JsonConvert.DeserializeObject(answer); address = jsonDe.result[0]; var query = $"update blockchains set address_main='{address}' where id=1"; Console.WriteLine("query " + query); MySQLConnector.Instance().SQLInsert(query); Console.WriteLine("Json addr " + jsonDe.result[0]); var methodName = (string)jsonDe.name; newData = true; return address; } public string GetAddress() { //this.address = address; return address; //post запрос } } }