public static async Task SyncBlock(Func<int, int> dispalyProgress = null) { //获取当前区块高度和远端区块高度 ApiResponse response = await NetworkApi.GetBlockChainInfo(); if (!response.HasError) { BlockChainInfo info = response.GetResult<BlockChainInfo>(); if (info.IsRunning) { if (info.RemoteLatestBlockHeight > info.LocalLastBlockHeight) { //开始同步 long localBlockHeight = info.LocalLastBlockHeight; long remoteBlockHeight = info.RemoteLatestBlockHeight; while (remoteBlockHeight > localBlockHeight) { dispalyProgress?.Invoke(Convert.ToInt32(((double)localBlockHeight / (double)remoteBlockHeight) * 100)); System.Threading.Thread.Sleep(3000); ApiResponse newResponse = await NetworkApi.GetBlockChainInfo(); if (!newResponse.HasError) { BlockChainInfo newBlockInfo = newResponse.GetResult<BlockChainInfo>(); localBlockHeight = newBlockInfo.LocalLastBlockHeight; remoteBlockHeight = newBlockInfo.RemoteLatestBlockHeight; if (remoteBlockHeight <= localBlockHeight) { dispalyProgress?.Invoke(100); } } } } } } }
public async Task GetBlockChainInfo() { ApiResponse response = await NetworkApi.GetBlockChainInfo(); Assert.IsFalse(response.HasError); BlockChainInfo result = response.GetResult <BlockChainInfo>(); Assert.IsNotNull(result); }
public static async Task<bool> IsNeedSyncBlock() { ApiResponse response = await NetworkApi.GetBlockChainInfo(); if (!response.HasError) { BlockChainInfo info = response.GetResult<BlockChainInfo>(); if (info.IsRunning) { if (info.RemoteLatestBlockHeight > info.LocalLastBlockHeight) { return true; } } } return false; }
static void Run(string[] args) { var app = new CommandLineApplication(false); app.HelpOption("-?|-h|--help"); app.OnExecute(() => { app.ShowHelp(); return; }); app.Command("mining", command => { command.Description = "begin mining"; command.HelpOption("-?|-h|--help"); CommandArgument nameArgument = command.Argument("[minerName]", "minerName"); CommandArgument addressArgument = command.Argument("[walletAddress]", "walletAddress"); command.OnExecute(async() => { if (nameArgument != null && !string.IsNullOrEmpty(nameArgument.Value) && addressArgument != null && !string.IsNullOrEmpty(addressArgument.Value)) { string name = nameArgument.Value; string address = addressArgument.Value; Program program = new Program(); BlockChainStatus chainStatus = await program.GetChainStatus(); if (chainStatus == null) { app.Out.WriteLine("there is something wrong with the api, you should check the fiiichain"); return; } //验证本地区块高度和网络区块高度 ApiResponse response = await NetworkApi.GetBlockChainInfo(); if (!response.HasError) { BlockChainInfo info = response.GetResult <BlockChainInfo>(); if (info.IsRunning) { if (info.RemoteLatestBlockHeight <= info.LocalLastBlockHeight) { command.Out.WriteLine($"current network is {chainStatus.ChainNetwork}"); //validate wallet address if (AddressTools.AddressVerfy(chainStatus.ChainNetwork, address)) { command.Out.WriteLine($"address verify success. prepare to mine"); await BlockMining.MiningAsync(name, address); } else { command.Out.WriteLine($"address verify fail. address: {address} is invalid"); return; } } else { command.Out.WriteLine("Block Chain is in sync, please try it later"); return; } } else { command.Out.WriteLine("Block Chain has stopped"); return; } } else { command.Out.WriteLine(response.Error.Message); return; } } else { command.ShowHelp(); return; } }); }); app.Command("height", command => { command.Description = "view current block height"; command.OnExecute(async() => { Program program = new Program(); BlockChainStatus chainStatus = await program.GetChainStatus(); if (chainStatus == null) { app.Out.WriteLine("there is something wrong with the api, you should check the fiiichain"); return; } ApiResponse response = await BlockChainEngineApi.GetBlockCount(); if (!response.HasError) { long result = response.GetResult <long>(); command.Out.WriteLine($"current block height is {result}"); } else { command.Out.WriteLine($"{response.Error.Message}"); } }); }); app.Command("balance", command => { command.Description = "view wallet balance"; command.OnExecute(async() => { Program program = new Program(); BlockChainStatus chainStatus = await program.GetChainStatus(); if (chainStatus == null) { app.Out.WriteLine("there is something wrong with the api, you should check the fiiichain"); return; } ApiResponse response = await UtxoApi.GetTxOutSetInfo(); if (!response.HasError) { TxOutSet set = response.GetResult <TxOutSet>(); command.Out.WriteLine($"wallet balance is :{set.Total_amount}"); } }); }); app.Command("transaction", command => { command.Description = "view recent transaction record(default 5 content)"; CommandArgument recordArgument = command.Argument("[count]", "record content"); command.OnExecute(async() => { if (recordArgument != null && !string.IsNullOrEmpty(recordArgument.Value)) { if (int.TryParse(recordArgument.Value, out int count)) { Program program = new Program(); BlockChainStatus chainStatus = await program.GetChainStatus(); if (chainStatus == null) { app.Out.WriteLine("there is something wrong with the api, you should check the fiiichain"); return; } ApiResponse response = await TransactionApi.ListTransactions("*", count); if (!response.HasError) { List <Payment> result = response.GetResult <List <Payment> >(); if (result != null && result.Count > 0) { command.Out.WriteLine("recent transaction record blow:"); foreach (var item in result) { //time(需要转换为DataTime), comment, amount string time = new DateTime(1970, 1, 1).AddMilliseconds(item.Time).ToString("yyyy-MM-dd HH:mm:ss"); command.Out.WriteLine($"Time:{time}; Comment:{item.Comment}; Amount:{item.Amount}"); } } else { command.Out.WriteLine("no recent transaction record."); } } } else { command.ShowHelp(); } } else { Program program = new Program(); BlockChainStatus chainStatus = await program.GetChainStatus(); if (chainStatus == null) { app.Out.WriteLine("there is something wrong with the api, you should check the fiiichain"); return; } ApiResponse response = await TransactionApi.ListTransactions(); if (!response.HasError) { List <Payment> result = response.GetResult <List <Payment> >(); if (result != null && result.Count > 0) { command.Out.WriteLine("recent transaction record blow:"); foreach (var item in result) { //time(需要转换为DataTime), comment, amount string time = new DateTime(1970, 1, 1).AddMilliseconds(item.Time).ToString("yyyy-MM-dd HH:mm:ss"); command.Out.WriteLine($"Time:{time}; Comment:{item.Comment}; Amount:{item.Amount}"); } } else { command.Out.WriteLine("no recent transaction record."); } } } }); }); /* * if (args.Length > 1 && args[0].ToLower() == "fiiipay" && IsContainsCommand(args[1])) * { * List<string> list = new List<string>(args); * list.RemoveAt(0); * app.Execute(list.ToArray()); * } */ if (args != null && args.Length > 0 && IsContainsCommand(args[0])) { app.Execute(args); } else { app.Execute(new[] { "-?" }); } }
public BlockSyncInfo SyncBlock() { /* 页面开始的区块同步 * 1、剩余区块数 1466 ↓ * 2、最后区块时间 周三 7月4 01:55:39:2018 ↑ * 3、进度 99.93% ↑ * 4、每小时增长速度 1.00% 速率(可大可小) * 5、剩余同步时间 4 minute(s) ↓ * * 讲解 * 已知变量: * 远端区块高度:远端的区块高度,总的区块高度,每5分钟打包一次,5分钟变化一次 * 本地区块高度:本地的区块高度,会有延迟 * 时间偏移量:时间戳,需要和当前时间比较,两者的差即为区块落后时间,注意单位变换 * * 刚开始会从那边接口获取三个数据字段,一个是当前区块高度,另一个是总的区块高度,先用一个全局变量存储总的区块高度,然后总的区块高度和当前区块高度两个的差就是未同步的区块高度即剩余区块数, * 循环任务 * 剩余区块数:获取到的remoteLastBlockHeight和全局变量存储的区块高度对比,如果大于存储的就更新, remoteLastBlockHeight-localLastBlockHeight * 最后区块时间:暂无 * 进度:(localLastBlockHeight/总的区块高度)*100% * 每小时增长速度:((进度2-进度1)/ 时间2-时间1) *3600=(((localLastBlockHeight2/总的区块高度)-(localLastBlockHeight1/总的区块高度))/ 1s) *3600=((localLastBlockHeight2-localLastBlockHeight1)/总的区块高度)*3600 * 剩余同步时间:剩余区块数/增长速度 * 同步区块个数除以总区块个数就是进度 * 剩余同步时间就是进度除以每小时增长速度 */ long AllBlockHeight = 0; long beforeTimeOffset = 0; long beforeLocalLastBlockHeight = 0; BlockSyncInfo block = new BlockSyncInfo(); Schedule(async() => { ApiResponse response = await NetworkApi.GetBlockChainInfo(); if (!response.HasError) { BlockChainInfo info = response.GetResult <BlockChainInfo>(); if (info.IsRunning) { if (info.RemoteLatestBlockHeight > info.LocalLastBlockHeight + 2) { if (AllBlockHeight == 0) { //第一次获取数据 AllBlockHeight = info.RemoteLatestBlockHeight; beforeTimeOffset = info.TimeOffset; beforeLocalLastBlockHeight = info.LocalLastBlockHeight; } else { //不是第一次,开始组织数据 if (info.RemoteLatestBlockHeight > AllBlockHeight) { AllBlockHeight = info.RemoteLatestBlockHeight; } //剩余区块数:总区块高度-本地最后区块高度 block.BlockLeft = AllBlockHeight - info.LocalLastBlockHeight; //最后区块时间 block.LastBlockTime = null; //区块同步进度:已同步的区块数目 / 总区块数目 block.Progress = (1 - (block.BlockLeft / AllBlockHeight)) * 100; //区块每小时增加进度: block.ProgressSpeed = ((info.LocalLastBlockHeight - beforeLocalLastBlockHeight) / AllBlockHeight) * 3600; //剩余时间 block.TimeLeft = (block.Progress / block.ProgressSpeed).ToString(); block.BehindTime = (double)info.TimeOffset - (DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds; // beforeLocalLastBlockHeight = info.LocalLastBlockHeight; beforeTimeOffset = info.TimeOffset; } } } } }).ToRunNow().AndEvery(1).Seconds(); return(block); }
public Result <BlockSyncInfo> GetBlockChainInfoSync(BlockSyncInfo block) { Result <BlockSyncInfo> result = new Result <BlockSyncInfo>(); ApiResponse response = NetworkApi.GetBlockChainInfo().Result; result.IsFail = response.HasError; result.Value = block; result.ApiResponse = response; if (!response.HasError) { BlockChainInfo info = response.GetResult <BlockChainInfo>(); if (!info.IsRunning) { return(result); } block.ConnectCount = info.Connections; //当前区块高度+缓存的区块高度 var localBlockHeight = info.LocalLastBlockHeight; //剩余的区块高度 block.BlockLeft = info.RemoteLatestBlockHeight - localBlockHeight; if (block.BlockLeft < 0) { block.BlockLeft = 0; } if (localBlockHeight < 0 || info.RemoteLatestBlockHeight < 0 || info.Connections < 2) { return(result); } if (!block.IsStartSync && block.BlockLeft > 0) { block.IsStartSync = true; block.beforeLocalLastBlockHeight = localBlockHeight; block.StartTimeOffset = DateTimeUtil.GetDateTimeStamp(DateTime.Now); } //BehindTime if (info.LocalLastBlockTime > 0 && info.LocalLastBlockHeight < info.RemoteLatestBlockHeight) { var content = GetTimeBehindContent(info.LocalLastBlockTime); if (!string.IsNullOrEmpty(content)) { block.BehindTime = content; } } else { block.BehindTime = ""; } //已经更新的区块高度 var syncedHeight = localBlockHeight - block.beforeLocalLastBlockHeight; //更新区块花了多长时间 var syncedTime = DateTimeUtil.GetDateTimeStamp(DateTime.Now) - block.StartTimeOffset; //当前更新进度 if ((info.RemoteLatestBlockHeight - block.beforeLocalLastBlockHeight) != 0) { var progress = (Convert.ToDouble(syncedHeight) / (info.RemoteLatestBlockHeight - block.beforeLocalLastBlockHeight)) * 100; block.Progress = progress; } //剩余更新时间 if (syncedHeight > 0) { block.TimeLeft = (syncedTime / syncedHeight) * block.BlockLeft; } } return(result); }
public Result <BlockSyncInfo> GetBlockChainInfoSync(BlockSyncInfo block) { Result <BlockSyncInfo> result = new Result <BlockSyncInfo>(); ApiResponse response = NetworkApi.GetBlockChainInfo().Result; result.IsFail = false; result.Value = block; result.ApiResponse = response; if (!response.HasError) { BlockChainInfo info = response.GetResult <BlockChainInfo>(); if (!info.IsRunning) { return(result);; } block.ConnectCount = info.Connections; if (block.AllBlockHeight < 0) { //远程没同步的时候 block.Progress = 100; block.AllBlockHeight = 0; block.beforeLocalLastBlockHeight = info.LocalLastBlockHeight; } if (block.AllBlockHeight == 0) { //第一次获取数据,远程区块高度 block.AllBlockHeight = info.RemoteLatestBlockHeight; //本地更新之前区块的高度 block.beforeLocalLastBlockHeight = info.LocalLastBlockHeight; //刚开始时剩余区块高度 block.BlockLeft = block.AllBlockHeight - block.beforeLocalLastBlockHeight; if (block.AllBlockHeight < 0 || block.BlockLeft < 0) { block.Progress = 100; } else { //本次更新开始时间 block.StartTimeOffset = DateTimeUtil.GetDateTimeStamp(DateTime.Now); block.needUpdateBlocksHeight = block.BlockLeft; if (block.AllBlockHeight == info.LocalLastBlockHeight) { block.Progress = 100; } else { block.Progress = 0; } } } else { if (info.TimeOffset == -1) { return(result); } //不是第一次,开始组织数据 block.BlockLeft = block.AllBlockHeight - info.LocalLastBlockHeight - info.TempBlockCount; var doubleValue = Convert.ToDouble(info.LocalLastBlockHeight + info.TempBlockCount - block.beforeLocalLastBlockHeight); if (block.AllBlockHeight <= info.LocalLastBlockHeight) { if (info.TempBlockCount > 5) { block.Progress = 99; } block.Progress = 100; block.TimeLeft = 0; } else { block.Progress = (doubleValue / block.needUpdateBlocksHeight) * 100; } //剩余时间 = 当前更新时间 / 进度 if (block.Progress > 0 && block.Progress < 100) { block.TimeLeft = Convert.ToInt64((DateTimeUtil.GetDateTimeStamp(DateTime.Now) - block.StartTimeOffset) / block.Progress) * 100; } if (block.BlockLeft < 0) { block.BlockLeft = 0; } } } return(result); }