Blockchain.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. using System;
  2. using System.Diagnostics;
  3. using System.Text;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Drawing;
  7. using System.Drawing.Imaging;
  8. using System.Threading.Tasks;
  9. using Newtonsoft.Json;
  10. using Console = HyperCube.Utils.AdvConsole;
  11. using System.Text.RegularExpressions;
  12. using QRCoder;
  13. using System.IO;
  14. //0xe5D682717955d6C35d465A3485625C64655a04f4 - HCB in rinkeby
  15. //0xb504ba124b74333d8536db534f7fcdc174d6ee3d - system address rinkeby
  16. //0x413D9500A675d9b645034aC5f4325BF12ddeb7c1 bitcoin
  17. namespace HyperCube.Models
  18. {
  19. public struct TransactionObject
  20. {
  21. public string from;
  22. public string to;
  23. public string data;
  24. public string gas;
  25. public string value;
  26. }
  27. public class Blockchain
  28. {
  29. public static Blockchain Dev
  30. {
  31. get {
  32. return loaded[0];
  33. }
  34. set { }
  35. }
  36. public static string tokenName;
  37. public static string decimals;
  38. public static string symbol;
  39. public static string tokenBalance;
  40. public static string balanceHCB;
  41. public static Dictionary<int, Blockchain> supported;
  42. public static string Connected
  43. {
  44. get {
  45. var bc = GetMain();
  46. if (bc != null)
  47. return $"{bc.name}";
  48. return "none";
  49. }
  50. }
  51. public static string URLdefault = "127.0.0.1";
  52. //public static int defaultPort = 8545;
  53. public static int defaultPort = 8666;
  54. public static string defaultName = "Ethereum dev network";
  55. public static bool blockChainsInitialized = false;
  56. public static Dictionary<int, Blockchain> loaded = new();
  57. public Dictionary<int, SmartContract> contracts = new();
  58. public Dictionary<string, SmartContract> contractNames = new();
  59. public int id;
  60. public int port;
  61. public string url;
  62. public string address = "";
  63. public string name;
  64. public string balance;
  65. static Blockchain instance;
  66. public async static Task RegisterNetworks()
  67. {
  68. if (!blockChainsInitialized)
  69. {
  70. Console.WriteLine($"RegisterNetworks");
  71. var ethDev = new Blockchain(0, "Ethereum Dev Network", "127.0.0.1", 8545);
  72. var ethRinkeby = new Blockchain(1, "Ethereum Test Network", "127.0.0.1", 8666);
  73. await ethDev.Initialize();
  74. await ethRinkeby.Initialize();
  75. blockChainsInitialized = true;
  76. }
  77. }
  78. public static Blockchain Find(int id)
  79. {
  80. if (loaded.ContainsKey(id))
  81. return loaded[id];
  82. return null;
  83. }
  84. public async Task<string> GetBalanceToken(string contractAddress, string address)
  85. {
  86. TransactionObject transObj = new TransactionObject();
  87. transObj.to = contractAddress;
  88. //compile data
  89. //to.data = await compileFunction("decimals");
  90. //transObj.data = await compileFunction("name");
  91. //var answer = await RunFunction2("eth_call", transObj, "latest");
  92. ////Console.WriteLine("ImportERC20 len "+ answer.Length + " answer " + answer);
  93. //var parsed = ParseStringAnswer(answer);
  94. //int tokenlen = hex2dec(parsed[1]);
  95. //tokenName = HextoString(parsed[2]).Substring(0, tokenlen);
  96. //to.data = await compileFunction("balanceOf(address)");
  97. transObj.data = await compileFunction("symbol");
  98. var answer = await RunFunction2("eth_call", transObj, "latest");
  99. var parsed = ParseStringAnswer(answer);
  100. int symlen = hex2dec(parsed[1]);
  101. symbol = HextoString(parsed[2]).Substring(0, symlen);
  102. //Console.WriteLine("ImportERC20 len " + answer.Length + " answer " + answer);
  103. transObj.data = await compileFunction("decimals");
  104. answer = await RunFunction2("eth_call", transObj, "latest");
  105. decimals = hex2dec(ParseStringAnswer(answer)[0]).ToString();
  106. transObj.data = await compileFunction($"function balanceOf(address account)");
  107. if (address != null)
  108. transObj.data += zerofill(address, 64, true);
  109. //answer = await RunFunction2("eth_call", to, AccountModel.Current.GetActualAddress(this));
  110. answer = await RunFunction2("eth_call", transObj, "latest");
  111. balanceHCB = ((double)AccountModel.ConvertBalance(ParseStringAnswer(answer)[0]) / 1000000000000000000.0).ToString();
  112. return null;
  113. }
  114. public async Task<string> Initialize()
  115. {
  116. if (!loaded.ContainsKey(id))
  117. loaded.Add(id, this);
  118. Console.WriteLine($"Initialize: {name}, loaded blockchains " + loaded.Count);
  119. string addr = await ListAccounts();
  120. await LoadContracts();
  121. Console.WriteLine("LoadContracts count " + contracts.Count);
  122. Console.WriteLine("connected " + Connected);
  123. return $"{name} {url}:{port}";
  124. }
  125. public static string dec2hex(int decValue, bool prefix = true)
  126. {
  127. string hexValue = decValue.ToString("X");
  128. if (prefix)
  129. hexValue = "0x" + hexValue;
  130. return hexValue;
  131. }
  132. public static int hex2dec(string hexValue)
  133. {
  134. return Convert.ToInt32(hexValue, 16);
  135. }
  136. //public static Blockchain GetInstance()
  137. //{
  138. // if (instance == null)
  139. // instance = new Blockchain(URLdefault, defaultPort);
  140. // return instance;
  141. //}
  142. //Blockchain()
  143. //{
  144. //}
  145. public Blockchain(int id, string name, string url, int port)
  146. {
  147. this.id = id;
  148. this.url = url;
  149. this.port = port;
  150. this.name = name;
  151. }
  152. public async Task<string> CreateBlockchainAccount(AccountModel account, string pass)
  153. {
  154. Console.WriteLine($"Run CreateBlockchainAccount {account}");
  155. var res = await RunFunction("personal_newAccount", $"\"{pass}\"");
  156. string query;
  157. if (account != null)
  158. {
  159. Console.WriteLine($"CreateBlockchainAccount {account}: {res}");
  160. //query = $"update aspnetusers set eth_address='{res}' where UserName='{account.Name}'";
  161. var addr = account.GetActualAddress(this);
  162. if (addr == null)
  163. query = $"insert into account_wallets (uuid, blockchain_id, account_uuid, password_plain) values ('{res}',{id},'{account.UUID}','{account.PWDHash}')";
  164. else
  165. query = $"update account_wallets set uuid='{res}', password_plain='{account.PWDHash}' where account_uuid='{account.UUID}' and blockchain_id={id}";
  166. account.SetActualAddress(res, this);
  167. Console.WriteLine($"CreateBlockchainAccount query {query}");
  168. await MySQLConnector.Instance().SQLInsert(query);
  169. }
  170. else
  171. Console.WriteLine($"CreateBlockchainAccount {id}: {res}");
  172. query = $"update blockchains set address_main='{res}' where id={id}";
  173. address = res;
  174. Console.WriteLine($"CreateBlockchainAccount query {query}");
  175. await MySQLConnector.Instance().SQLInsert(query);
  176. return res;
  177. }
  178. public static string hex2bin(string hexstring)
  179. {
  180. string binarystring = String.Join(String.Empty, hexstring.Select( c => Convert.ToString(Convert.ToInt32(c.ToString(), 16), 2).PadLeft(4, '0') ));
  181. Console.WriteLine("bin " + binarystring);
  182. return binarystring;
  183. }
  184. public static string bin2hex(string code)
  185. {
  186. //code = "0x".bin2hex('getCount()');
  187. var bytes = Encoding.UTF8.GetBytes(code);
  188. var hex = BitConverter.ToString(bytes).Replace("-", "");
  189. Console.WriteLine("hex " + hex);
  190. return "0x" + hex;
  191. }
  192. public static string zerofill(string hex, int charCount, bool hexPrefix0x)
  193. {
  194. if (hexPrefix0x)
  195. hex = hex.Remove(0, 2);
  196. Console.WriteLine($"zerofill input {hex} count {hex.Length}");
  197. var res = hex.PadLeft(charCount, '0');
  198. Console.WriteLine($"zerofill out {hex} count {res.Length}");
  199. return res;
  200. }
  201. public static Blockchain GetMain()
  202. {
  203. if (loaded.Count > AccountModel.GetCurrent()?.blockchain_selected)
  204. {
  205. var bc = loaded[AccountModel.GetCurrent().blockchain_selected];
  206. Console.WriteLine($"GetMain blockchain_selected {AccountModel.GetCurrent().blockchain_selected} " + bc.address);
  207. return bc;
  208. }
  209. else
  210. Console.WriteLine($"Error: blockchains loaded {loaded.Count}");
  211. return null;
  212. }
  213. public async Task<string> ListAccounts()
  214. {
  215. Console.WriteLine($"ListAccounts blockchain {id}");
  216. string answer = "no";
  217. //{ "jsonrpc":"2.0","method":"eth_getCode","params":["0x938cae6f6c21ed9d55196e96ef880f562e530553", "latest" ],"id":1}
  218. //string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getCode\",\"params\":[\"0x874c6a51e62680d4594cd2555ed8fa47b63ed253\",\"latest\"],\"id\":1}";
  219. string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_accounts\", \"params\":[],\"id\":1}";
  220. answer = await Post.PostRequestAsync(this, req);
  221. //string json = Encoding.UTF8.GetString(bytedata, 1, bytedata.Length - 1);
  222. //try
  223. //{
  224. Console.WriteLine("Json string " + answer);
  225. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  226. var res = (Newtonsoft.Json.Linq.JArray)jsonDe.result;
  227. if (res.Count > 0 && id == 0) //Dev
  228. {
  229. address = jsonDe.result[0];
  230. }
  231. else
  232. {
  233. address = await GetAddress();
  234. if (address == "" || address == null)
  235. address = await CreateEthAddress("test_Password_212");
  236. }
  237. var query = $"update blockchains set address_main='{address}' where id={id}";
  238. Console.WriteLine("query " + query);
  239. await MySQLConnector.Instance().SQLInsert(query);
  240. Console.WriteLine("Json addr " + jsonDe.result[0]);
  241. return address;
  242. }
  243. public async Task<string> CreateEthAddress(string pass)
  244. {
  245. return await CreateBlockchainAccount(null, pass);
  246. }
  247. public async Task LoadContracts()
  248. {
  249. MySQLConnector dbCon = MySQLConnector.Instance();
  250. contracts = await dbCon.SQLSelectContracts(id);
  251. foreach (var contract in contracts.Values)
  252. {
  253. await contract.LoadFunction();
  254. }
  255. }
  256. public async Task<string> GetSHA3(string code)
  257. {
  258. var hex = bin2hex(code);
  259. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"web3_sha3\",\"params\":[\"{hex}\"], \"id\":1}}";
  260. var answer = await Post.PostRequestAsync(this, req);
  261. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  262. Console.WriteLine("result " + jsonDe.result);
  263. return jsonDe.result;
  264. }
  265. public async Task<string> GetBalance(AccountModel account)
  266. {
  267. var addr = await account.GetOrCreateActualAddress(this);
  268. //var ret = await RunFunction("eth_getBalance", $"\"{addr}\",\"latest\"");
  269. Console.WriteLine($"GetBalance AccountModel addr {addr}");
  270. return await GetBalance(addr);
  271. }
  272. public async Task<string> GetBalance()
  273. {
  274. return await GetBalance(address);
  275. }
  276. //eth.getBalance('0xb504ba124b74333D8536DB534F7fcdC174d6Ee3d')
  277. public async Task<string> GetBalance(string address)
  278. {
  279. var ret = await RunFunction("eth_getBalance", $"\"{address}\",\"latest\"");
  280. var balanceWei = AccountModel.ConvertBalance(ret);
  281. var balanceToken = (double)balanceWei / 1000000000000000000.0;
  282. Console.WriteLine($"GetBalance balanceToken {balanceToken}");
  283. balance = balanceToken.ToString();
  284. return balance;
  285. }
  286. public async Task<string> RunFunction(string name, string parms)
  287. {
  288. Console.WriteLine($"RunFunction {name} params {parms}");
  289. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"{name}\",\"params\":[{parms}], \"id\":1}}";
  290. var answer = await Post.PostRequestAsync(this, req);
  291. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  292. Console.WriteLine("RunFunction result " + jsonDe.result);
  293. return jsonDe.result;
  294. //return "test answer";
  295. }
  296. public async Task<string> RunFunction2(string name, TransactionObject to, string defaultBlock = null)
  297. {
  298. //транзакция добавления контракта 0x00bdbf1571aa69a2cf8c8c7913a01eaca3a4b7e5e7e49fc787cb81c0df2c2682
  299. Dictionary<string, string> paramDict = new Dictionary<string, string>();
  300. string parms = "{";
  301. if (to.from != null)
  302. paramDict["from"] = to.from;
  303. if (to.to != null)
  304. paramDict["to"] = to.to;
  305. if (to.data != null)
  306. {
  307. paramDict["data"] = "0x"+to.data;
  308. }
  309. int count = 0;
  310. foreach (var p in paramDict)
  311. {
  312. parms += $"\"{p.Key}\":\"{p.Value}\"";
  313. count++;
  314. if (paramDict.Count > count)
  315. {
  316. parms += ",";
  317. }
  318. }
  319. parms += "}";
  320. if (defaultBlock != null)
  321. parms += $", \"{defaultBlock}\"";
  322. Console.WriteLine($"RunFunction {name} params {parms} active bc: {this.address}");
  323. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"{name}\",\"params\":[{parms}], \"id\":1}}";
  324. var answer = await Post.PostRequestAsync(this, req);
  325. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  326. Console.WriteLine("RunFunction result " + jsonDe.result);
  327. return jsonDe.result;
  328. //return "test answer";
  329. }
  330. public static string QRtest(string input)
  331. {
  332. QRCodeGenerator qrGenerator = new QRCodeGenerator();
  333. QRCodeData qrCodeData = qrGenerator.CreateQrCode(input, QRCodeGenerator.ECCLevel.Q);
  334. QRCode qrCode = new QRCode(qrCodeData);
  335. Bitmap qrCodeImage = qrCode.GetGraphic(7);
  336. //Image img = qrCodeImage;
  337. MemoryStream ms = new MemoryStream();
  338. BinaryWriter bw = new BinaryWriter(ms);
  339. //var fulltexname = Encoding.UTF8.GetBytes("http://" + myHostName + "/" + filename);
  340. //bw.Write(loc_id);
  341. //bw.Write(fulltexname);
  342. //return base64String;
  343. qrCodeImage.Save(ms, ImageFormat.Png);
  344. byte[] imageBytes = ms.ToArray();
  345. string base64String = Convert.ToBase64String(imageBytes);
  346. Console.WriteLine($"base64String {base64String}");
  347. return base64String;
  348. //Image.FromStream(ms);
  349. }
  350. public static List<string> ExecuteCommand(string cmd)
  351. {
  352. List<string> output = new List<string>();
  353. var processInfo = new ProcessStartInfo(@"e:\www\nodejs\test.bat", cmd );
  354. processInfo.CreateNoWindow = true;
  355. processInfo.UseShellExecute = false;
  356. processInfo.RedirectStandardError = true;
  357. processInfo.RedirectStandardOutput = true;
  358. var process = Process.Start(processInfo);
  359. process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => Echo(e.Data, ref output);
  360. process.BeginOutputReadLine();
  361. process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
  362. Console.WriteLine("error>>" + e.Data);
  363. process.BeginErrorReadLine();
  364. process.WaitForExit();
  365. Console.WriteLine($"ExitCode: {process.ExitCode}");
  366. num = 0;
  367. process.Close();
  368. return output;
  369. }
  370. static int num = 0;
  371. static void Echo(string msg, ref List<string> output)
  372. {
  373. //if (num > 0)
  374. if (msg != null && msg.Length > 0)
  375. {
  376. Console.WriteLine("output >>" + msg);
  377. output.Add(msg);
  378. }
  379. num++;
  380. }
  381. async Task<string> mySHA3(string code)
  382. {
  383. var res = await GetSHA3(code);
  384. Console.WriteLine($"GetSHA3 {code} {res}");
  385. var ret = res.Substring(2, 8);
  386. return ret;
  387. }
  388. public async Task<string> compileFunction(string input, bool getsha = true)
  389. {
  390. //\s = пробел
  391. //\S = любой символ, кроме промельного
  392. //+ одно или более вхождений
  393. //. любой сивол, кроме перевода строки
  394. //* ноль или более вхождений «а»
  395. //скобки без экранирования = группы
  396. //function transfer(address recipient, uint256 amount)
  397. string pattern = @"function\s+(\S+)\s*\((.*)\).*";
  398. string replacement_name = "$1"; //номер найденной группы
  399. string replacement_params = "$2";
  400. string resultname = Regex.Replace(input, pattern, replacement_name).Trim();
  401. string param_pattern = @"(uint8|address|uint256)";
  402. string final = resultname + "(";
  403. if (input != resultname)
  404. {
  405. string resultparams = Regex.Replace(input, pattern, replacement_params).Trim();
  406. if (input != resultparams)
  407. {
  408. int i = 0;
  409. foreach (Match match in Regex.Matches(resultparams, param_pattern))
  410. {
  411. if (i > 0)
  412. final += "," + match.Value;
  413. else
  414. final += match.Value;
  415. i++;
  416. }
  417. }
  418. }
  419. string function_processed = final + ")";
  420. Console.WriteLine($"function_processed {function_processed}");
  421. if (getsha)
  422. {
  423. function_processed = await mySHA3(function_processed);
  424. }
  425. return function_processed;
  426. }
  427. //public double UInt256Conv(string input)
  428. //{
  429. // System.Numerics.BigInteger bigint1 = System.Numerics.BigInteger.Parse("329974300448100608374211110737048701521");
  430. // System.Numerics.BigInteger bigint2 = new System.Numerics.BigInteger(18);
  431. // return bigint1 / 18.0;
  432. //}
  433. public static string HextoString(string InputText)
  434. {
  435. byte[] bb = Enumerable.Range(0, InputText.Length)
  436. .Where(x => x % 2 == 0)
  437. .Select(x => Convert.ToByte(InputText.Substring(x, 2), 16))
  438. .ToArray();
  439. //return System.Text.Encoding.ASCII.GetString(bb);
  440. // or System.Text.Encoding.UTF7.GetString
  441. return System.Text.Encoding.UTF8.GetString(bb);
  442. // or System.Text.Encoding.Unicode.GetString
  443. // or etc.
  444. }
  445. public string[] ParseStringAnswer(string answer)
  446. {
  447. var ret = new string[] { };
  448. if (answer.Length > 2)
  449. {
  450. answer = answer.Substring(2, answer.Length - 2);
  451. int words = answer.Length / 64;
  452. ret = new string[words];
  453. for (int i = 0; i < words; i++)
  454. {
  455. var word = answer.Substring(i * 64, 64);
  456. ret[i] = word;
  457. Console.WriteLine($"word {i} {word}");
  458. Console.WriteLine($"str {i} {HextoString(word)}");
  459. var testbalance1 = (double)(AccountModel.ConvertBalance(word)/ 1000000000000000000);
  460. var testbalance2 = ((double)AccountModel.ConvertBalance(word) / 1000000000000000000.0);
  461. Console.WriteLine($"testbalance1 {testbalance1} testbalance2 {testbalance2} ");
  462. }
  463. }
  464. return ret;
  465. }
  466. public async Task TransferToken(string sender, string tokenContract, string addressTo, string tokenAmount)
  467. {
  468. //transfer(address recipient, uint256 amount)
  469. TransactionObject transObj = new TransactionObject();
  470. transObj.from = sender;
  471. transObj.to = tokenContract;
  472. transObj.gas = "9000";
  473. transObj.value = tokenAmount;
  474. transObj.data = await compileFunction($"function transfer(address recipient, uint256 amount)");
  475. if (addressTo != null && tokenAmount != null)
  476. {
  477. transObj.data += zerofill(addressTo, 64, true);
  478. transObj.data += zerofill(dec2hex(Convert.ToInt32(tokenAmount)), 64, true);
  479. }
  480. var answer = await RunFunction2("eth_sendTransaction", transObj);
  481. }
  482. public async Task ImportERC20(string contractAddress, string importAddress)
  483. {
  484. //"0xb504ba124b74333D8536DB534F7fcdC174d6Ee3d"
  485. //var gbh = await GetTByHash("0x00bdbf1571aa69a2cf8c8c7913a01eaca3a4b7e5e7e49fc787cb81c0df2c2682");
  486. //Console.WriteLine("GetTByHash " + gbh );
  487. //runfunction balanceOf totalSupply symbol name
  488. //RunContractRead
  489. TransactionObject transObj = new TransactionObject();
  490. transObj.to = contractAddress;
  491. //compile data
  492. //to.data = await compileFunction("decimals");
  493. transObj.data = await compileFunction("name");
  494. var answer = await RunFunction2("eth_call", transObj, "latest");
  495. //Console.WriteLine("ImportERC20 len "+ answer.Length + " answer " + answer);
  496. var parsed = ParseStringAnswer(answer);
  497. int tokenlen = hex2dec(parsed[1]);
  498. tokenName = HextoString(parsed[2]).Substring(0,tokenlen);
  499. //to.data = await compileFunction("balanceOf(address)");
  500. transObj.data = await compileFunction("symbol");
  501. answer = await RunFunction2("eth_call", transObj, "latest");
  502. parsed = ParseStringAnswer(answer);
  503. int symlen = hex2dec(parsed[1]);
  504. symbol = HextoString(parsed[2]).Substring(0, symlen);
  505. //Console.WriteLine("ImportERC20 len " + answer.Length + " answer " + answer);
  506. transObj.data = await compileFunction("decimals");
  507. answer = await RunFunction2("eth_call", transObj, "latest");
  508. decimals = hex2dec(ParseStringAnswer(answer)[0]).ToString();
  509. transObj.data = await compileFunction($"function balanceOf(address account)");
  510. if (address != null)
  511. transObj.data += zerofill(importAddress, 64, true);
  512. //answer = await RunFunction2("eth_call", to, AccountModel.Current.GetActualAddress(this));
  513. answer = await RunFunction2("eth_call", transObj, "latest");
  514. tokenBalance = ((double)AccountModel.ConvertBalance(ParseStringAnswer(answer)[0]) / 1000000000000000000.0).ToString();
  515. }
  516. public async void RunContractRead()
  517. {
  518. string answer = "no";
  519. string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"to\":\"0x874c6a51e62680d4594cd2555ed8fa47b63ed253\", \"data\":\"0xa87d942c\"},\"latest\"],\"id\":1}";
  520. //string req = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x0000000000000000000000000000000000000000000000000000000000000004\"}";
  521. //Console.WriteLine($"req " + req);
  522. await Post.PostRequestAsync(this, req);
  523. //Console.WriteLine($"answer {answer} len {answer.Length}" );
  524. address = answer;
  525. }
  526. public async Task<string> SendTransaction(string fromAddress, string toAddress, int wei)
  527. {
  528. var sum = dec2hex(wei);
  529. var gas = await GetEstimatedGasTransaction(wei);
  530. Console.WriteLine($"SendTransaction from {fromAddress} to {toAddress} sum {sum}");
  531. var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{toAddress}\",\"gas\":\"{gas}\", \"data\":\"\", \"value\":\"{sum}\"}}");
  532. return answer;
  533. }
  534. //{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ "from":"0xD81eeE6b39d9556c3067A3551A3FB2882b92F327", "to":"0x119b58faddcdbc09cafcd272530aa079cec10004", "gas":"0x31b2ef", "data":"0x11111111"}], "id":1}
  535. public async Task<string> RunContractWrite(string contractAddress, string data, string gas, string value)
  536. {
  537. Console.WriteLine("RunContract contractAddress " + contractAddress);
  538. var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{contractAddress}\",\"gas\":\"{gas}\", \"data\":\"{data}\", \"value\":\"{value}\"}}");
  539. //$"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_sendTransaction\",\"params\":[{{\"from\":\"{address}\",\"to\":\"{contractAddress}\",\"gas\":\"0x31b2ef\", \"data\":\"{data}\"}}], \"id\":1}}";
  540. //var answer = await Post.PostRequestAsync(req);
  541. //dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  542. //Console.WriteLine("result " + answer);
  543. return answer;
  544. }
  545. public async Task<string> GetTByHash(string transactionAddress)
  546. {
  547. string req = $"{{\"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionByHash\",\"params\":[\"{transactionAddress}\"],\"id\":1}}";
  548. Console.WriteLine("GetTByHash " + req);
  549. return await Post.PostRequestAsync(this, req);
  550. }
  551. public async Task<string> GetReceipt(string transactionAddress, bool returnAddress = false)
  552. {
  553. Console.WriteLine("transactionAddress " + transactionAddress);
  554. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionReceipt\",\"params\":[\"{transactionAddress}\"], \"id\":1}}";
  555. var answer = await Post.PostRequestAsync(this, req);
  556. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  557. if (jsonDe.result != null)
  558. {
  559. var blockHash = jsonDe.result.blockHash;
  560. var blockNumber = jsonDe.result.blockNumber;
  561. var contractAddress = jsonDe.result.contractAddress;
  562. await MySQLConnector.Instance().SQLInsert($"insert into transactions (result, name) values ('{Convert.ToString(jsonDe.result)}', 'eth_getTransactionReceipt')");
  563. Console.WriteLine("result " + answer);
  564. if (returnAddress)
  565. return contractAddress;
  566. else
  567. return Convert.ToString(jsonDe.result);
  568. }
  569. else
  570. {
  571. Console.WriteLine("eth_getTransactionReceipt reuslt NULL " + transactionAddress);
  572. return null;
  573. }
  574. }
  575. //TODO add GAS!!!
  576. public async Task<object[]> AddContract(string name, string code, string bytecode)
  577. {
  578. Console.WriteLine("bytecode " + bytecode);
  579. var gas = await GetEstimatedGasContractAdd(bytecode);
  580. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_sendTransaction\",\"params\":[{{\"from\":\"{address}\",\"gas\":\"{gas}\", \"data\":\"{bytecode}\"}}], \"id\":1}}";
  581. var answer = await Post.PostRequestAsync(this, req);
  582. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  583. var res = jsonDe.result;
  584. Console.WriteLine("result AddContract transactionAddress: " + res);
  585. if (res != null)
  586. {
  587. SmartContract newctr = new SmartContract(name, code, bytecode, this.id, gas);
  588. if (gas == null)
  589. gas = "invalid";
  590. long id = await MySQLConnector.Instance().SQLInsert($"insert into smart_contracts (code, bytecode, name, date_add, gas_cost, blockchain_id) values ('{code}','{bytecode}','{name}',NOW(), '{gas}', {this.id})");
  591. newctr.ID = (int) id;
  592. contracts.Add((int)id, newctr);
  593. contractNames.Add(name, newctr);
  594. return new object[] { res, newctr };
  595. }
  596. return null;
  597. }
  598. public async Task<string> GetEstimatedGasTransaction(int weiAmount)
  599. {
  600. if (weiAmount > 0)
  601. {
  602. var ret = await RunFunction("eth_estimateGas", $"{{\"from\":\"{address}\",\"value\":\"{dec2hex(weiAmount)}\"}}");
  603. Console.WriteLine("GetEstimatedGas " + ret);
  604. return ret;
  605. }
  606. return null;
  607. }
  608. public async Task<string> GetEstimatedGasContractAdd(string bytecode)
  609. {
  610. var ret = await RunFunction("eth_estimateGas", $"{{\"from\":\"{address}\",\"data\":\"{bytecode}\"}}");
  611. Console.WriteLine("GetEstimatedGasContractAdd " + ret);
  612. return ret;
  613. }
  614. public async Task<string> GetAddress()
  615. {
  616. if (address == "")
  617. {
  618. address = await MySQLConnector.Instance().SQLSelectUUID("select address_main from blockchains where id="+id);
  619. }
  620. return address;
  621. //post запрос
  622. }
  623. }
  624. }