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
{
///
/// transaction sender
///
public string from;
///
/// transaction receiver
///
public string to;
///
/// payload - function pointer and all other custom parameters
///
public string data;
///
/// gas amount
///
public string gas;
///
/// value in Wei
///
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 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 loaded = new();
public Dictionary contracts = new();
public Dictionary 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 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 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 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 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 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 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 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 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 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 GetBalance()
{
return await GetBalance(address);
}
//eth.getBalance('0xb504ba124b74333D8536DB534F7fcdC174d6Ee3d')
public async Task 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 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 RunFunction2(string name, TransactionObject to, string defaultBlock = null)
{
//транзакция добавления контракта 0x00bdbf1571aa69a2cf8c8c7913a01eaca3a4b7e5e7e49fc787cb81c0df2c2682
Dictionary paramDict = new Dictionary();
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 ExecuteCommand(string cmd)
{
List output = new List();
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 output)
{
//if (num > 0)
if (msg != null && msg.Length > 0)
{
Console.WriteLine("output >>" + msg);
output.Add(msg);
}
num++;
}
async Task mySHA3(string code)
{
var res = await GetSHA3(code);
Console.WriteLine($"GetSHA3 {code} {res}");
var ret = res.Substring(2, 8);
return ret;
}
public async Task 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 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 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 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 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 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