123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925 |
- using System;
- using System.Diagnostics;
- using System.Text;
- using System.Collections.Generic;
- using System.Linq;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Threading.Tasks;
- using Newtonsoft.Json;
- using Console = HyperCube.Utils.AdvConsole;
- using System.Text.RegularExpressions;
- using QRCoder;
- using System.IO;
- using Microsoft.AspNetCore.Components;
- using System.Numerics;
- //0xe5D682717955d6C35d465A3485625C64655a04f4 - HCB in rinkeby
- //0xb504ba124b74333d8536db534f7fcdc174d6ee3d - system address rinkeby
- //0x413D9500A675d9b645034aC5f4325BF12ddeb7c1 bitcoin
- namespace HyperCube.Models
- {
- public struct TransactionObject
- {
- /// <summary>
- /// transaction sender
- /// </summary>
- public string from;
- /// <summary>
- /// transaction receiver
- /// </summary>
- public string to;
- /// <summary>
- /// payload - function pointer and all other custom parameters
- /// </summary>
- public string data;
- /// <summary>
- /// gas amount
- /// </summary>
- public string gas;
- /// <summary>
- /// value in Wei
- /// </summary>
- public string value;
- }
- public class Blockchain
- {
- [Inject]
- AppData AppData { get; set; }
- public static Blockchain Dev
- {
- get {
- return loaded[0];
- }
- set { }
- }
- public const string MultiOwnerContractRinkeby = "0x7eca4E373De5E9ad27Be283612a75e632aCB81f2";
- public const string HCBAddress = "0xe5D682717955d6C35d465A3485625C64655a04f4";
- public const string QNMAddress = "0xE895a91B041e8450A1AFb9F54b8362a8ae3bb3d3";
- public static string tokenName;
- public static string decimals;
- public static string symbol;
- public static string tokenBalance;
- public static string balanceToken;
- public static Dictionary<int, Blockchain> supported;
- //public static string Connected
- //{
- // get
- // {
- // var bc = AppData.CurrentAccount.GetSelectedBlockChain(); //acc selected
- // if (bc != null)
- // return $"{bc.name}";
- // return "none";
- // }
- //}
- public static string URLdefault = "127.0.0.1";
- //public static int defaultPort = 8545;
- public static int defaultPort = 8666;
- public static string defaultName = "Ethereum dev network";
- public static bool blockChainsInitialized = false;
- public static Dictionary<int, Blockchain> loaded = new();
- public Dictionary<int, SmartContract> contracts = new();
- public Dictionary<string, SmartContract> contractNames = new();
- public int id;
- public int port;
- public string url;
- public string address = "";
- public string name;
- public string balance;
- static Blockchain instance;
- public async static Task RegisterNetworks()
- {
- if (!blockChainsInitialized)
- {
- Console.WriteLine($"RegisterNetworks");
- var ethDev = new Blockchain(0, "Ethereum Dev Network", "127.0.0.1", 8545);
- var ethRinkeby = new Blockchain(1, "Ethereum Test Network", "127.0.0.1", 8666);
- await ethDev.Initialize();
- await ethRinkeby.Initialize();
- blockChainsInitialized = true;
- }
- }
- public static Blockchain Find(int id)
- {
- if (loaded.ContainsKey(id))
- return loaded[id];
- return null;
- }
- public async Task<string> GetBalanceToken(string contractAddress, string address)
- {
- TransactionObject transObj = new TransactionObject();
- transObj.to = contractAddress;
- //compile data
- //to.data = await compileFunction("decimals");
- //transObj.data = await compileFunction("name");
- //var answer = await RunFunction2("eth_call", transObj, "latest");
- ////Console.WriteLine("ImportERC20 len "+ answer.Length + " answer " + answer);
- //var parsed = ParseStringAnswer(answer);
- //int tokenlen = hex2dec(parsed[1]);
- //tokenName = HextoString(parsed[2]).Substring(0, tokenlen);
- //to.data = await compileFunction("balanceOf(address)");
- transObj.data = await compileFunction("symbol");
- var answer = await RunFunction2("eth_call", transObj, "latest");
- var parsed = ParseStringAnswer(answer);
- if (parsed.Length == 0)
- return null;
- int symlen = hex2dec(parsed[1]);
- symbol = HextoString(parsed[2]).Substring(0, symlen);
- //Console.WriteLine("ImportERC20 len " + answer.Length + " answer " + answer);
- transObj.data = await compileFunction("decimals");
- answer = await RunFunction2("eth_call", transObj, "latest");
- decimals = hex2dec(ParseStringAnswer(answer)[0]).ToString();
- transObj.data = await compileFunction($"function balanceOf(address account)");
- if (address != null)
- transObj.data += zerofill(address, 64, true);
- //answer = await RunFunction2("eth_call", to, AccountModel.Current.GetActualAddress(this));
- answer = await RunFunction2("eth_call", transObj, "latest");
- balanceToken = ((double)AccountModel.ConvertBalance(ParseStringAnswer(answer)[0]) / 1000000000000000000.0).ToString();
- return balanceToken;
- }
- public async Task<string> Initialize()
- {
- if (!loaded.ContainsKey(id))
- loaded.Add(id, this);
- Console.WriteLine($"Initialize: {name}, loaded blockchains " + loaded.Count);
- string addr = await ListAccounts();
- await LoadContracts();
- Console.WriteLine("LoadContracts count " + contracts.Count);
- //Console.WriteLine("connected " + Connected);
- return $"{name} {url}:{port}";
- }
- public async Task ChangeOwner(string ERC20Address, string contractAddress)
- {
- TransactionObject transObj = new TransactionObject();
- transObj.from = address;
- transObj.to = ERC20Address;
- transObj.data = await compileFunction($"function transferOwnership(address newOwner)");
- var answer = await RunFunction2("eth_sendTransaction", transObj);
- }
- public async Task ChangeOwnerMulti()
- {
- TransactionObject transObj = new TransactionObject();
- transObj.from = address;
- transObj.to = MultiOwnerContractRinkeby;
- //transObj.data = zerofill(dec2hex(36), 64, true); //36 bytes len of data. Для ремикса это не нужно, он сам вставляет длину массива
- transObj.data += await compileFunction($"function transferOwnership(address newOwner)"); //4 bytes
- transObj.data += zerofill("0xD3ae749f1253b320ea2b90dc235ed72c80447AFF", 64, true); //32 bytes
- Console.WriteLine($"transObj.data {transObj.data}");
- //var answer = await RunFunction2("eth_sendTransaction", transObj);
- }
- public async Task Transactions(string multiOwnerContract)
- {
- TransactionObject transObj = new TransactionObject();
- transObj.to = multiOwnerContract;
- transObj.data = await compileFunction($"transactionCount");
- var answer = await RunFunction2("eth_call", transObj, "latest");
- }
- public async Task Approve(string owner, string spender, string amount, string tokenAddress)
- {
- TransactionObject transObj = new TransactionObject();
- transObj.from = owner;
- transObj.to = tokenAddress;
- transObj.data = await compileFunction($"function approve(address spender, uint256 amount)");
- if (tokenAddress != null)
- {
- transObj.data += zerofill(spender, 64, true);
- transObj.data += zerofill(dec2hex(amount), 64, true);
- }
- var answer = await RunFunction2("eth_sendTransaction", transObj);
- }
- public async Task<string> SubmitTransaction(string owner, long tokenvalue, string receiver, string tokenAddress = QNMAddress)
- {
- //"submitTransaction(address destination, uint value, address tokenAddress)"
- //var tokenAmount = float.Parse(tokenvalue, System.Globalization.CultureInfo.InvariantCulture);// * 1000000000000000000;
-
- //ETHtoERC20(address tokenAddress)
- //ERC20toETH(address tokenAddress, address sender, uint256 tokenAmount, uint256 ethAmount) public payable returns(bool)
- TransactionObject transObj = new TransactionObject();
- transObj.from = owner;
- transObj.to = MultiOwnerContractRinkeby;
- transObj.data = await compileFunction($"function submitTransaction(address destination, uint256 value, address tokenAddress)");
- if (tokenvalue > 0)
- {
- transObj.data += zerofill(receiver, 64, true);
- transObj.data += zerofill(dec2hex(tokenvalue), 64, true);
- transObj.data += zerofill(tokenAddress, 64, true);
- }
- var answer = await RunFunction2("eth_sendTransaction", transObj);
- return ParseStringAnswer(answer)[0];
- }
- //
- //ETHtoERC20 - шлем эфир на контракт, контракт шлет юзеру ERC20 по курсу со своего счета через transfer
- //ETHtoERC20 - шлем ERC20 на контракт, получаем эфир по курсу
- //запуск контрактом TransferFrom юзером на адрес контракта
- //контракт шлет юзеру эфир по курсу со своего счета
- //нужна проверка балансов системы и юзера перед обменом
- public async Task ExchangeCurrency(string from_token_selected, string to_token_selected, string tokenAddress, string senderAccountAddress, string fi, string ti)
- {
- //ETHtoERC20(address tokenAddress, uint256 tokenAmount)
- //ERC20toETH(address tokenAddress, address sender, uint256 tokenAmount, uint256 ethAmount) public payable returns(bool)
- TransactionObject transObj = new TransactionObject();
- transObj.from = senderAccountAddress;
- transObj.to = MultiOwnerContractRinkeby;
- transObj.gas = dec2hex("90000");
- var valFrom = decimal.Parse(fi, System.Globalization.CultureInfo.InvariantCulture);
- var valTo = decimal.Parse(ti, System.Globalization.CultureInfo.InvariantCulture);
-
- if (to_token_selected == "qnm")
- {
- transObj.data = await compileFunction($"function ETHtoERC20(address tokenAddress, uint256 tokenAmount)");
- BigInteger tokenAmount = (BigInteger)(valTo * 1000000000000000000m);
- BigInteger ethAmount = (BigInteger)(valFrom * 1000000000000000000m);
- Console.WriteLine($"######################################ETHtoERC20 valTo {valTo} tokenAmount {tokenAmount} valFrom {valFrom} ethAmount {ethAmount}");
- transObj.value = dec2hex(ethAmount);
- if (tokenAddress != null && tokenAmount > 0)
- {
- transObj.data += zerofill(tokenAddress, 64, true);
- transObj.data += zerofill(dec2hex(tokenAmount), 64, true);
- }
- }
- else
- {
- BigInteger tokenAmount = (BigInteger)(valFrom * 1000000000000000000);
- BigInteger ethAmount = (BigInteger)(valTo * 1000000000000000000);
- //сначала нужен аппрув перевода!
- //from=erc20 to=eth
- var amount = float.Parse(fi, System.Globalization.CultureInfo.InvariantCulture);
- var appr = Approve(senderAccountAddress, MultiOwnerContractRinkeby, tokenAmount.ToString(), QNMAddress);
- await Task.WhenAll(appr);
- //sender возможно можно заменить на msg.sender
- transObj.data = await compileFunction($"function ERC20toETH(address tokenAddress, address sender, uint256 tokenAmount, uint256 ethAmount)");
- Console.WriteLine($"######################################ERC20toETH valTo {valTo} tokenAmount {tokenAmount} valFrom {valFrom} ethAmount {ethAmount}");
- if (tokenAddress != null && tokenAmount != null)
- {
- transObj.data += zerofill(tokenAddress, 64, true);
- transObj.data += zerofill(senderAccountAddress, 64, true);
- transObj.data += zerofill(dec2hex(tokenAmount), 64, true);
- transObj.data += zerofill(dec2hex(ethAmount), 64, true);
- }
- }
- var answer = await RunFunction2("eth_sendTransaction", transObj);
- }
- //ETHtoERC20(address tokenAddress, uint256 tokenAmount)
- public async Task<string> Verify(AccountModel verifier, ArticleModel article)
- {
- Console.WriteLine($"Verify starting");
- try
- {
- var bc = await verifier.GetSelectedBlockChain();
- VerifyContract verifyContract = SmartContract.Find("Verify", bc) as VerifyContract;
- if (verifyContract != null)
- {
- Console.WriteLine($"VerifyContract found");
- var transactionId = await verifyContract.Run(verifier, article);
- return transactionId;
- }
- else
- Console.WriteLine($"VerifyContract null");
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message + "stack trace" + e.StackTrace);
- }
- return "Verify failed";
- }
- public static string dec2hex(BigInteger decValue, bool prefix = true)
- {
- var hexValue = decValue.ToString("X");
- if (prefix)
- hexValue = "0x" + hexValue;
- return hexValue;
- }
- public static string dec2hex(string decValue, bool prefix = true)
- {
- var hexValue = BigInteger.Parse(decValue, System.Globalization.CultureInfo.InvariantCulture).ToString("X");
- if (prefix)
- hexValue = "0x" + hexValue;
- return hexValue;
- }
- public static int hex2dec(string hexValue)
- {
- return Convert.ToInt32(hexValue, 16);
- }
- //public static Blockchain GetInstance()
- //{
- // if (instance == null)
- // instance = new Blockchain(URLdefault, defaultPort);
- // return instance;
- //}
- //Blockchain()
- //{
- //}
- public Blockchain(int id, string name, string url, int port)
- {
- this.id = id;
- this.url = url;
- this.port = port;
- this.name = name;
- }
- public async Task<string> CreateBlockchainAccount(AccountModel account, string pass)
- {
- Console.WriteLine($"Run CreateBlockchainAccount {account}");
- var res = await RunFunction("personal_newAccount", $"\"{pass}\"");
- string query;
- if (account != null)
- {
- Console.WriteLine($"CreateBlockchainAccount {account}: {res}");
- //query = $"update aspnetusers set eth_address='{res}' where UserName='{account.Name}'";
- var addr = account.GetActualAddress(this);
- if (addr == null)
- query = $"insert into account_wallets (uuid, blockchain_id, account_uuid, password_plain, added) values ('{res}',{id},'{account.UUID}','{account.PWDHash}', NOW())";
- else
- query = $"update account_wallets set uuid='{res}', password_plain='{account.PWDHash}', added = NOW() where account_uuid='{account.UUID}' and blockchain_id={id}";
- account.SetActualAddress(res, this);
- Console.WriteLine($"CreateBlockchainAccount query {query}");
- await MySQLConnector.Instance().SQLInsert(query);
- }
- else
- Console.WriteLine($"CreateBlockchainAccount {id}: {res}");
- address = res;
- if (account == null)
- {
- query = $"update blockchains set address_main='{res}' where id={id}";
- Console.WriteLine($"CreateBlockchainAccount query {query}");
- await MySQLConnector.Instance().SQLInsert(query);
- }
- return res;
- }
- public static string hex2bin(string hexstring)
- {
- string binarystring = String.Join(String.Empty, hexstring.Select( c => Convert.ToString(Convert.ToInt32(c.ToString(), 16), 2).PadLeft(4, '0') ));
- Console.WriteLine("bin " + binarystring);
- return binarystring;
- }
- 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 async Task<string> ListAccounts()
- {
- Console.WriteLine($"ListAccounts blockchain {id}");
- 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(this, req);
- //string json = Encoding.UTF8.GetString(bytedata, 1, bytedata.Length - 1);
- //try
- //{
- Console.WriteLine("Json string " + answer);
- dynamic jsonDe = JsonConvert.DeserializeObject(answer);
- var res = (Newtonsoft.Json.Linq.JArray)jsonDe.result;
- if (res.Count > 0 && id == 0) //Dev
- {
- address = jsonDe.result[0];
- }
- else
- {
- address = await GetAddress();
- if (address == "" || address == null)
- address = await CreateEthAddress("test_Password_212");
- }
- var query = $"update blockchains set address_main='{address}' where id={id}";
- Console.WriteLine("query " + query);
- await MySQLConnector.Instance().SQLInsert(query);
- Console.WriteLine("Json addr " + jsonDe.result[0]);
- return address;
- }
- public async Task<string> CreateEthAddress(string pass)
- {
- return await CreateBlockchainAccount(null, pass);
- }
- public async Task LoadContracts()
- {
- MySQLConnector dbCon = MySQLConnector.Instance();
- contracts = await dbCon.SQLSelectContracts(id);
- foreach (var contract in contracts.Values)
- {
- await contract.LoadFunction();
- }
- }
- public async Task<string> GetSHA3(string code)
- {
- var hex = bin2hex(code);
- var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"web3_sha3\",\"params\":[\"{hex}\"], \"id\":1}}";
- var answer = await Post.PostRequestAsync(this, req);
- dynamic jsonDe = JsonConvert.DeserializeObject(answer);
- Console.WriteLine("result " + jsonDe.result);
- return jsonDe.result;
- }
- public async Task<string> GetBalance(AccountModel account)
- {
- var addr = await account.GetOrCreateActualAddress(this);
- //var ret = await RunFunction("eth_getBalance", $"\"{addr}\",\"latest\"");
- Console.WriteLine($"GetBalance AccountModel addr {addr}");
- return await GetBalance(addr);
- }
- public async Task<string> GetBalance()
- {
- return await GetBalance(address);
- }
- //eth.getBalance('0xb504ba124b74333D8536DB534F7fcdC174d6Ee3d')
- public async Task<string> GetBalance(string address)
- {
- var ret = await RunFunction("eth_getBalance", $"\"{address}\",\"latest\"");
- var balanceWei = AccountModel.ConvertBalance(ret);
- var balanceEth = Math.Round((double)balanceWei / 1000000000000000000.0, 4);
- Console.WriteLine($"GetBalance balanceEth {balanceEth}");
- balance = balanceEth.ToString();
- return balance;
- }
-
- public async Task<string> 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(this, req);
- dynamic jsonDe = JsonConvert.DeserializeObject(answer);
- Console.WriteLine("RunFunction result " + jsonDe.result);
- return jsonDe.result;
- //return "test answer";
- }
- public async Task<string> RunFunction2(string name, TransactionObject to, string defaultBlock = null)
- {
- //транзакция добавления контракта 0x00bdbf1571aa69a2cf8c8c7913a01eaca3a4b7e5e7e49fc787cb81c0df2c2682
- Dictionary<string, string> paramDict = new Dictionary<string, string>();
- string parms = "{";
- if (to.from != null)
- paramDict["from"] = to.from;
- if (to.to != null)
- paramDict["to"] = to.to;
- if (to.gas != null)
- paramDict["gas"] = to.gas;
- if (to.value != null)
- paramDict["value"] = to.value;
- if (to.data != null)
- {
- paramDict["data"] = "0x"+to.data;
- }
- int count = 0;
- foreach (var p in paramDict)
- {
- parms += $"\"{p.Key}\":\"{p.Value}\"";
- count++;
- if (paramDict.Count > count)
- {
- parms += ",";
- }
- }
- parms += "}";
- if (defaultBlock != null)
- parms += $", \"{defaultBlock}\"";
- Console.WriteLine($"RunFunction {name} params {parms} active bc: {this.address}");
- var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"{name}\",\"params\":[{parms}], \"id\":1}}";
- var answer = await Post.PostRequestAsync(this, req);
- dynamic jsonDe = JsonConvert.DeserializeObject(answer);
- Console.WriteLine("RunFunction result " + jsonDe.result);
- return jsonDe.result;
- //return "test answer";
- }
- public static string QRtest(string input)
- {
- QRCodeGenerator qrGenerator = new QRCodeGenerator();
- QRCodeData qrCodeData = qrGenerator.CreateQrCode(input, QRCodeGenerator.ECCLevel.Q);
- QRCode qrCode = new QRCode(qrCodeData);
- Bitmap qrCodeImage = qrCode.GetGraphic(7);
- //Image img = qrCodeImage;
- MemoryStream ms = new MemoryStream();
- BinaryWriter bw = new BinaryWriter(ms);
- //var fulltexname = Encoding.UTF8.GetBytes("http://" + myHostName + "/" + filename);
- //bw.Write(loc_id);
- //bw.Write(fulltexname);
-
- //return base64String;
- qrCodeImage.Save(ms, ImageFormat.Png);
- byte[] imageBytes = ms.ToArray();
- string base64String = Convert.ToBase64String(imageBytes);
- Console.WriteLine($"base64String {base64String}");
- return base64String;
- //Image.FromStream(ms);
- }
- public static List<string> ExecuteCommand(string cmd)
- {
- List<string> output = new List<string>();
- var processInfo = new ProcessStartInfo(@"e:\www\nodejs\test.bat", cmd );
- processInfo.CreateNoWindow = true;
- processInfo.UseShellExecute = false;
- processInfo.RedirectStandardError = true;
- processInfo.RedirectStandardOutput = true;
- var process = Process.Start(processInfo);
- process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => Echo(e.Data, ref output);
- process.BeginOutputReadLine();
- process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
- Console.WriteLine("error>>" + e.Data);
- process.BeginErrorReadLine();
- process.WaitForExit();
- Console.WriteLine($"ExitCode: {process.ExitCode}");
- num = 0;
- process.Close();
- return output;
- }
- static int num = 0;
-
- static void Echo(string msg, ref List<string> output)
- {
- //if (num > 0)
- if (msg != null && msg.Length > 0)
- {
- Console.WriteLine("output >>" + msg);
- output.Add(msg);
- }
- num++;
- }
- async Task<string> mySHA3(string code)
- {
- var res = await GetSHA3(code);
- Console.WriteLine($"GetSHA3 {code} {res}");
- var ret = res.Substring(2, 8);
- return ret;
- }
- public async Task<string> compileFunction(string input, bool getsha = true)
- {
- //\s = пробел
- //\S = любой символ, кроме пробельного
- //+ одно или более вхождений
- //. любой сивол, кроме перевода строки
- //* ноль или более вхождений «а»
- //скобки без экранирования = группы
- //function transfer(address recipient, uint256 amount)
- string pattern = @"function\s+(\S+)\s*\((.*)\).*";
- string replacement_name = "$1"; //номер найденной группы
- string replacement_params = "$2";
- string resultname = Regex.Replace(input, pattern, replacement_name).Trim();
- string param_pattern = @"(uint8|address|uint256)";
- string final = resultname + "(";
- if (input != resultname)
- {
- string resultparams = Regex.Replace(input, pattern, replacement_params).Trim();
- if (input != resultparams)
- {
- int i = 0;
- foreach (Match match in Regex.Matches(resultparams, param_pattern))
- {
- if (i > 0)
- final += "," + match.Value;
- else
- final += match.Value;
- i++;
- }
- }
- }
- string function_processed = final + ")";
- Console.WriteLine($"function_processed {function_processed}");
- if (getsha)
- {
- function_processed = await mySHA3(function_processed);
- }
- return function_processed;
- }
- //public double UInt256Conv(string input)
- //{
- // System.Numerics.BigInteger bigint1 = System.Numerics.BigInteger.Parse("329974300448100608374211110737048701521");
- // System.Numerics.BigInteger bigint2 = new System.Numerics.BigInteger(18);
- // return bigint1 / 18.0;
- //}
- public static string HextoString(string InputText)
- {
- byte[] bb = Enumerable.Range(0, InputText.Length)
- .Where(x => x % 2 == 0)
- .Select(x => Convert.ToByte(InputText.Substring(x, 2), 16))
- .ToArray();
- //return System.Text.Encoding.ASCII.GetString(bb);
- // or System.Text.Encoding.UTF7.GetString
- return System.Text.Encoding.UTF8.GetString(bb);
- // or System.Text.Encoding.Unicode.GetString
- // or etc.
- }
- public string[] ParseStringAnswer(string answer)
- {
- var ret = new string[] { };
- Console.WriteLine($"ParseStringAnswer: {name}, answer.Length " + answer.Length);
- if (answer.Length > 2)
- {
- answer = answer.Substring(2, answer.Length - 2);
- int words = answer.Length / 64;
- ret = new string[words];
- for (int i = 0; i < words; i++)
- {
- var word = answer.Substring(i * 64, 64);
- ret[i] = word;
- Console.WriteLine($"word {i} {word}");
- Console.WriteLine($"str {i} {HextoString(word)}");
- var testbalance1 = (double)(AccountModel.ConvertBalance(word)/ 1000000000000000000);
- var testbalance2 = ((double)AccountModel.ConvertBalance(word) / 1000000000000000000.0);
- Console.WriteLine($"testbalance1 {testbalance1} testbalance2 {testbalance2} ");
- }
- }
- return ret;
- }
- //верификация запускает запрос на минт/перевод токенов от системы
- //количество вычисляется по конечной ценности, переданной в смарт и курсу к $$$$???
- //комиссия владельцам
- //4. Рабочий стол. Верификация
- //7. Календарь событий - тут добавление мероприятия запускает транзакции спонсирования
- //8. Персональные данные - роль
- //13. Цифровые активы
- //14. Блокчейн
- //накапать токенов эксперту и автору материала
- //0. делаем новый контракт с массивом ролей
- //1. делаем в нем управляющий код с подтверждениями на выпуск токенов
- //2. в рамках текущего токена - делаем овнером токена мульти контракт с ролями
- //3. этим же контрактом запускаем verify и другие контракты - функции
- //4. что должен фиксировать Verify?
- //5. как и где определять параметры запускаемых функций во внешних контрактах
- //6. определение курса токенов
- public async Task Mint(string tokenAmount, string addressTo)
- {
- //mint(address to, uint256 amount)
- TransactionObject transObj = new TransactionObject();
- transObj.from = address;
- transObj.to = QNMAddress;
- transObj.gas = "9000";
- transObj.data = await compileFunction($"function mint(address to, uint256 amount)");
- if (addressTo != null && tokenAmount != null)
- {
- transObj.data += zerofill(addressTo, 64, true);
- transObj.data += zerofill(dec2hex(tokenAmount), 64, true);
- }
- var answer = await RunFunction2("eth_sendTransaction", transObj);
- }
- public async Task TransferToken(string sender, string tokenContract, string addressTo, string tokenAmount)
- {
- //transfer(address recipient, uint256 amount)
- TransactionObject transObj = new TransactionObject();
- transObj.from = sender;
- transObj.to = tokenContract;
- transObj.data = await compileFunction($"function transfer(address recipient, uint256 amount)");
- if (addressTo != null && tokenAmount != null)
- {
- transObj.data += zerofill(addressTo, 64, true);
- transObj.data += zerofill(dec2hex(Convert.ToInt32(tokenAmount)), 64, true);
- }
- var answer = await RunFunction2("eth_sendTransaction", transObj);
- }
- public async Task ImportERC20(string contractAddress, string importAddress)
- {
- //"0xb504ba124b74333D8536DB534F7fcdC174d6Ee3d"
- //var gbh = await GetTByHash("0x00bdbf1571aa69a2cf8c8c7913a01eaca3a4b7e5e7e49fc787cb81c0df2c2682");
- //Console.WriteLine("GetTByHash " + gbh );
- //runfunction balanceOf totalSupply symbol name
- //RunContractRead
- TransactionObject transObj = new TransactionObject();
- transObj.to = contractAddress;
- //compile data
- //to.data = await compileFunction("decimals");
- transObj.data = await compileFunction("name");
- var answer = await RunFunction2("eth_call", transObj, "latest");
- //Console.WriteLine("ImportERC20 len "+ answer.Length + " answer " + answer);
- var parsed = ParseStringAnswer(answer);
- int tokenlen = hex2dec(parsed[1]);
- tokenName = HextoString(parsed[2]).Substring(0,tokenlen);
- //to.data = await compileFunction("balanceOf(address)");
- transObj.data = await compileFunction("symbol");
- answer = await RunFunction2("eth_call", transObj, "latest");
- parsed = ParseStringAnswer(answer);
- int symlen = hex2dec(parsed[1]);
- symbol = HextoString(parsed[2]).Substring(0, symlen);
- //Console.WriteLine("ImportERC20 len " + answer.Length + " answer " + answer);
- transObj.data = await compileFunction("decimals");
- answer = await RunFunction2("eth_call", transObj, "latest");
- decimals = hex2dec(ParseStringAnswer(answer)[0]).ToString();
-
- transObj.data = await compileFunction($"function balanceOf(address account)");
- if (address != null)
- transObj.data += zerofill(importAddress, 64, true);
- //answer = await RunFunction2("eth_call", to, AccountModel.Current.GetActualAddress(this));
- answer = await RunFunction2("eth_call", transObj, "latest");
- tokenBalance = ((double)AccountModel.ConvertBalance(ParseStringAnswer(answer)[0]) / 1000000000000000000.0).ToString();
-
- }
- public async Task<string> BalanceOf(string contractAddress, string holderAddress)
- {
- TransactionObject transObj = new TransactionObject();
- transObj.to = contractAddress;
- transObj.data = await compileFunction($"function balanceOf(address account)");
- if (address != null)
- transObj.data += zerofill(holderAddress, 64, true);
- //answer = await RunFunction2("eth_call", to, AccountModel.Current.GetActualAddress(this));
- var answer = await RunFunction2("eth_call", transObj, "latest");
- tokenBalance = ((double)AccountModel.ConvertBalance(ParseStringAnswer(answer)[0]) / 1000000000000000000.0).ToString();
- return tokenBalance;
- }
- 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(this, req);
- //Console.WriteLine($"answer {answer} len {answer.Length}" );
- address = answer;
- }
- public async Task<string> SendTransaction(string fromAddress, string toAddress, int wei)
- {
- var sum = dec2hex(wei);
- var gas = await GetEstimatedGasTransaction(wei);
- Console.WriteLine($"SendTransaction from {fromAddress} to {toAddress} sum {sum}");
- var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{toAddress}\",\"gas\":\"{gas}\", \"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<string> RunContractWrite(string contractAddress, string data, string gas, string value)
- {
- Console.WriteLine("RunContract contractAddress " + contractAddress);
- var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{contractAddress}\",\"gas\":\"{gas}\", \"data\":\"{data}\", \"value\":\"{value}\"}}");
- //$"{{ \"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<string> GetTByHash(string transactionAddress)
- {
- string req = $"{{\"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionByHash\",\"params\":[\"{transactionAddress}\"],\"id\":1}}";
- Console.WriteLine("GetTByHash " + req);
- return await Post.PostRequestAsync(this, req);
- }
- public async Task<string> 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(this, req);
- dynamic jsonDe = JsonConvert.DeserializeObject(answer);
- if (jsonDe.result != null)
- {
- var blockHash = jsonDe.result.blockHash;
- var blockNumber = jsonDe.result.blockNumber;
- var contractAddress = jsonDe.result.contractAddress;
- await 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);
- }
- else
- {
- Console.WriteLine("eth_getTransactionReceipt reuslt NULL " + transactionAddress);
- return null;
- }
- }
- //TODO add GAS!!!
- public async Task<object[]> AddContract(string name, string code, string bytecode)
- {
- Console.WriteLine("bytecode " + bytecode);
- var gas = await GetEstimatedGasContractAdd(bytecode);
- var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_sendTransaction\",\"params\":[{{\"from\":\"{address}\",\"gas\":\"{gas}\", \"data\":\"{bytecode}\"}}], \"id\":1}}";
- var answer = await Post.PostRequestAsync(this, req);
- dynamic jsonDe = JsonConvert.DeserializeObject(answer);
- var res = jsonDe.result;
- Console.WriteLine("result AddContract transactionAddress: " + res);
- if (res != null)
- {
- SmartContract newctr = new SmartContract(name, code, bytecode, this.id, gas);
-
- if (gas == null)
- gas = "invalid";
- 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})");
- newctr.ID = (int) id;
- contracts.Add((int)id, newctr);
- contractNames.Add(name, newctr);
- return new object[] { res, newctr };
- }
- return null;
- }
- public async Task<string> GetEstimatedGasTransaction(int weiAmount)
- {
- if (weiAmount > 0)
- {
- var ret = await RunFunction("eth_estimateGas", $"{{\"from\":\"{address}\",\"value\":\"{dec2hex(weiAmount)}\"}}");
- Console.WriteLine("GetEstimatedGas " + ret);
- return ret;
- }
- return null;
- }
- public async Task<string> GetEstimatedGasContractAdd(string bytecode)
- {
- var ret = await RunFunction("eth_estimateGas", $"{{\"from\":\"{address}\",\"data\":\"{bytecode}\"}}");
- Console.WriteLine("GetEstimatedGasContractAdd " + ret);
- return ret;
- }
- public async Task<string> GetAddress()
- {
- if (address == "")
- {
- address = await MySQLConnector.Instance().SQLSelectUUID("select address_main from blockchains where id="+id);
- }
- return address;
- //post запрос
- }
- }
- }
|