Exemple #1
0
 private async Task SeedBlocks(ExplorerDbContext context)
 {
     foreach (var chain in context.Chains)
     {
         Console.WriteLine($"Seeding {chain.Name} chain blocks");
         await SeedBlocksByChain(context, chain);
     }
 }
Exemple #2
0
        public static async Task <bool> Initialize(ExplorerDbContext context)
        {
            if (context.Chains.Any())
            {
                return(false);
            }

            var initializer = new ExplorerInicializer();
            await initializer.SeedEverythingAsync(context);

            return(true);
        }
        internal async Task UpdateAccountBalances(ExplorerDbContext context, List <string> addressList)
        {
            Console.WriteLine("*********************************");
            Console.WriteLine("Updating account balances");

            foreach (var address in addressList)
            {
                var account = context.Accounts.Find(address);

                if (account != null)
                {
                    var accountResult = await _phantasmaRpcService.GetAccount.SendRequestAsync(account.Address);

                    account.Name       = accountResult.Name;
                    account.SoulStaked = accountResult.Stake;
                    account.TokenBalance.Clear();
                    account.NonFungibleTokens.Clear();

                    foreach (var tokenBalance in accountResult.Tokens)
                    {
                        var token = context.Tokens.Find(tokenBalance.Symbol) ?? await SyncToken(context, tokenBalance.Symbol);

                        if ((token.Flags & TokenFlags.Fungible) != 0)
                        {
                            account.TokenBalance.Add(new FungibleBalance
                            {
                                Chain       = tokenBalance.ChainName,
                                TokenSymbol = tokenBalance.Symbol,
                                Amount      = tokenBalance.Amount
                            });
                        }
                        else
                        {
                            UpdateNfTokenBalance(context, account, tokenBalance);
                        }

                        await context.SaveChangesAsync();
                    }
                }
                else
                {
                    account = new Account
                    {
                        Address = address
                    };

                    await context.Accounts.AddAsync(account);
                }
            }
        }
Exemple #4
0
        public async Task Sync(ExplorerDbContext context)
        {
            SyncAdditionalDataCounter++;

            foreach (var chain in context.Chains)
            {
                while (await _phantasmaRpcService.GetBlockHeight.SendRequestAsync(chain.Address) > chain.Height)
                {
                    if (ContinueSync)
                    {
                        Console.WriteLine($"NEW BLOCK: Chain: {chain.Name}, block: {chain.Height + 1}");
                        var block = await _phantasmaRpcService.GetBlockByHeight.SendRequestAsync(chain.Address, (int)(chain.Height + 1));

                        await SyncBlock(context, chain, block);
                    }
                    else
                    {
                        Console.WriteLine("Sync has stopped");
                        return;
                    }
                }
            }
            //todo find smarter way to do this
            await UpdateAccountBalances(context, _addressChanged);

            _addressChanged.Clear();

            if (SyncAdditionalDataCounter >= 5)
            {
                Console.WriteLine("Sync new chains?");
                await SyncChains(context);

                Console.WriteLine("Sync new apps?");
                var appList = await _phantasmaRpcService.GetApplications.SendRequestAsync();

                await SyncUtils.SyncApps(context, appList);

                Console.WriteLine("Sync new tokens?");
                var tokenList = await _phantasmaRpcService.GetTokens.SendRequestAsync();

                await SyncUtils.SyncToken(context, tokenList);

                SyncAdditionalDataCounter = 0;
            }
        }
Exemple #5
0
        public async Task SeedEverythingAsync(ExplorerDbContext context)
        {
            try
            {
                var sw = new Stopwatch();
                sw.Start();
                context.Database.EnsureCreated();
                _phantasmaRpcService = (IPhantasmaRpcService)Explorer.AppServices.GetService(typeof(IPhantasmaRpcService));

                if (!context.Apps.Any())
                {
                    var appList = await _phantasmaRpcService.GetApplications.SendRequestAsync();

                    await SyncUtils.SyncApps(context, appList);
                }

                if (!context.Tokens.Any())
                {
                    var tokenList = await _phantasmaRpcService.GetTokens.SendRequestAsync();

                    await SyncUtils.SyncToken(context, tokenList);
                }

                if (!context.Chains.Any())
                {
                    await SeedChains(context);
                }

                if (!context.Blocks.Any())
                {
                    await SeedBlocks(context);
                }

                sw.Stop();
                Console.WriteLine("Elapsed time to initializing db = {0}", sw.Elapsed);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                Console.WriteLine("Exception occurred during DB initialization, explorer cannot start");
            }
        }
        private async Task <Token> SyncToken(ExplorerDbContext context, string symbol)
        {
            var tokensDto = await _phantasmaRpcService.GetTokens.SendRequestAsync();

            var tokenDto = tokensDto.SingleOrDefault(p => p.Symbol.Equals(symbol));

            if (tokenDto != null)
            {
                Token token = new Token
                {
                    Name          = tokenDto.Name,
                    Symbol        = tokenDto.Symbol,
                    Decimals      = (uint)tokenDto.Decimals,
                    Flags         = tokenDto.Flags,
                    MaxSupply     = tokenDto.MaxSupply,
                    CurrentSupply = tokenDto.CurrentSupply,
                    OwnerAddress  = tokenDto.OwnerAddress
                };

                if (tokenDto.MetadataList != null)
                {
                    foreach (var metadataDto in tokenDto.MetadataList)
                    {
                        token.MetadataList.Add(new TokenMetadata
                        {
                            Key   = metadataDto.Key,
                            Value = metadataDto.Value
                        });
                    }
                }

                await context.Tokens.AddAsync(token);

                await context.SaveChangesAsync();

                return(token);
            }

            return(null);
        }
        private void UpdateNfTokenBalance(ExplorerDbContext context, Account account, BalanceSheetDto tokenBalance)
        {
            foreach (var tokenId in tokenBalance.Ids)
            {
                var existingToken = context.NonFungibleTokens.SingleOrDefault(p => p.Id.Equals(tokenId));
                if (existingToken == null)
                {
                    var nftoken = new NonFungibleToken
                    {
                        Chain       = tokenBalance.ChainName,
                        TokenSymbol = tokenBalance.Symbol,
                        Id          = tokenId,
                        Account     = account,
                    };

                    account.NonFungibleTokens.Add(nftoken);
                }
                else
                {
                    existingToken.Account = account;
                }
            }
        }
        public static void StartSync(ExplorerDbContext context)
        {
            var explorerSync = new ExplorerSync();

            new Thread(async() =>
            {
                Thread.CurrentThread.IsBackground = true;
                try
                {
                    if (_retries >= MaxRetries)
                    {
                        Console.WriteLine("There are no new blocks to sync.");
                        _retries = 0;
                        return;
                    }
                    while (ContinueSync)
                    {
                        Console.WriteLine("Remember, to stop sync process safely, press 3");
                        Console.WriteLine("It may take a while to stop");
                        Console.WriteLine("\n\n");

                        await explorerSync.Sync(context);
                        Thread.Sleep(AppSettings.SyncTime);
                    }

                    Console.WriteLine("Sync has stopped!");

                    _retries = 0;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    StartSync(context);
                    _retries++;
                }
            }).Start();
        }
        private async Task SyncBlock(ExplorerDbContext context, Chain chain, BlockDto blockDto)
        {
            if (context.Blocks.FirstOrDefault(p => p.Hash.Equals(blockDto.Hash)) != null)
            {
                return;
            }

            Console.WriteLine($"Seeding block {blockDto.Height}");

            var block = new Block
            {
                Chain            = chain,
                ChainName        = chain.Name,
                Hash             = blockDto.Hash,
                PreviousHash     = blockDto.PreviousHash,
                Timestamp        = blockDto.Timestamp,
                Height           = blockDto.Height,
                Payload          = blockDto.Payload,
                Reward           = blockDto.Reward,
                ValidatorAddress = blockDto.ValidatorAddress
            };

            //Transactions
            foreach (var transactionDto in blockDto.Txs)
            {
                var transaction = new Transaction
                {
                    Block     = block,
                    Hash      = transactionDto.Txid,
                    Timestamp = transactionDto.Timestamp,
                    Script    = transactionDto.Script,
                    Result    = transactionDto.Result
                };

                //Events
                foreach (var eventDto in transactionDto.Events)
                {
                    var domainEvent = new Event
                    {
                        Data         = eventDto.Data,
                        EventAddress = eventDto.EventAddress,
                        EventKind    = eventDto.EventKind,
                        Contract     = eventDto.Contract
                    };

                    transaction.Events.Add(domainEvent);

                    AddToUpdateList(eventDto.EventAddress);
                    await SyncUtils.UpdateAccount(context, transaction, eventDto.EventAddress);
                }
            }

            chain.Height = block.Height;
            context.Update(chain);

            await context.SaveChangesAsync();

            Console.WriteLine($"Finished syncing block {blockDto.Height}");
            Console.WriteLine("****************************************");
            Console.WriteLine();
        }
        private async Task SyncChains(ExplorerDbContext context)
        {
            var chainsDto = await _phantasmaRpcService.GetChains.SendRequestAsync();

            await SyncUtils.SyncChains(chainsDto, context);
        }
Exemple #11
0
        private async Task SeedBlocksByChain(ExplorerDbContext context, Chain chain)
        {
            try
            {
                var height = await _phantasmaRpcService.GetBlockHeight.SendRequestAsync(chain.Address);

                using (var progress = new ProgressBar())
                {
                    for (int i = 1; i <= height; i++)
                    {
                        progress.Report((double)i / height);

                        var blockDto = await _phantasmaRpcService.GetBlockByHeight.SendRequestAsync(chain.Address, i);

                        var block = new Block
                        {
                            Chain            = chain,
                            ChainName        = chain.Name,
                            Hash             = blockDto.Hash,
                            PreviousHash     = blockDto.PreviousHash,
                            Timestamp        = blockDto.Timestamp,
                            Height           = blockDto.Height,
                            Payload          = blockDto.Payload,
                            Reward           = blockDto.Reward,
                            ValidatorAddress = blockDto.ValidatorAddress
                        };

                        //Transactions
                        foreach (var transactionDto in blockDto.Txs)
                        {
                            var transaction = new Transaction
                            {
                                Block     = block,
                                Hash      = transactionDto.Txid,
                                Timestamp = transactionDto.Timestamp,
                                Script    = transactionDto.Script,
                                Result    = transactionDto.Result
                            };
                            bool addedToTokenList = false;

                            //Events
                            foreach (var eventDto in transactionDto.Events)
                            {
                                var domainEvent = new Domain.ValueObjects.Event
                                {
                                    Data         = eventDto.Data,
                                    EventAddress = eventDto.EventAddress,
                                    EventKind    = eventDto.EventKind,
                                    Contract     = eventDto.Contract
                                };

                                transaction.Events.Add(domainEvent);
                                if (!addedToTokenList)
                                {
                                    if (domainEvent.EventKind == EventKind.TokenBurn ||
                                        domainEvent.EventKind == EventKind.TokenSend ||
                                        domainEvent.EventKind == EventKind.TokenStake ||
                                        domainEvent.EventKind == EventKind.TokenUnstake ||
                                        domainEvent.EventKind == EventKind.TokenReceive ||
                                        domainEvent.EventKind == EventKind.TokenClaim ||
                                        domainEvent.EventKind == EventKind.TokenMint
                                        )
                                    {
                                        var data  = Serialization.Unserialize <TokenEventData>(eventDto.Data.Decode());
                                        var token = context.Tokens.SingleOrDefault(p => p.Symbol == data.Symbol);
                                        if (token != null)
                                        {
                                            token.Transactions.Add(transaction);
                                            addedToTokenList = true;
                                            await context.SaveChangesAsync();
                                        }
                                    }
                                }

                                await SyncUtils.UpdateAccount(context, transaction, eventDto.EventAddress);
                            }

                            block.Transactions.Add(transaction);
                        }

                        chain.Height = block.Height;
                        chain.Blocks.Add(block);
                    }
                }

                await context.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
Exemple #12
0
        private async Task SeedBlocksByChain(ExplorerDbContext context, Chain chain)
        {
            try
            {
                var height = await _phantasmaRpcService.GetBlockHeight.SendRequestAsync(chain.Address);

                using (var progress = new ProgressBar())
                {
                    for (int i = 1; i <= height; i++)
                    {
                        progress.Report((double)i / height);

                        var blockDto = await _phantasmaRpcService.GetBlockByHeight.SendRequestAsync(chain.Address, i);

                        var block = new Block
                        {
                            Chain            = chain,
                            ChainName        = chain.Name,
                            Hash             = blockDto.Hash,
                            PreviousHash     = blockDto.PreviousHash,
                            Timestamp        = blockDto.Timestamp,
                            Height           = blockDto.Height,
                            Payload          = blockDto.Payload,
                            Reward           = blockDto.Reward,
                            ValidatorAddress = blockDto.ValidatorAddress
                        };

                        //Transactions
                        foreach (var transactionDto in blockDto.Txs)
                        {
                            var transaction = new Transaction
                            {
                                Block     = block,
                                Hash      = transactionDto.Txid,
                                Timestamp = transactionDto.Timestamp,
                                Script    = transactionDto.Script,
                                Result    = transactionDto.Result
                            };

                            bool counterIncremented = false;
                            //Events
                            foreach (var eventDto in transactionDto.Events)
                            {
                                var domainEvent = new Event
                                {
                                    Data         = eventDto.Data,
                                    EventAddress = eventDto.EventAddress,
                                    EventKind    = eventDto.EventKind,
                                };

                                transaction.Events.Add(domainEvent);

                                await SyncUtils.UpdateAccount(context, transaction, eventDto.EventAddress);

                                if (!counterIncremented)
                                {
                                    if (TransactionUtils.IsTransferEvent(domainEvent))
                                    {
                                        var tokenSymbol = TransactionUtils.GetTokenSymbolFromTokenEventData(domainEvent);
                                        SyncUtils.AddToTokenTxCounter(context, tokenSymbol);
                                        counterIncremented = true;
                                    }
                                }
                            }

                            block.Transactions.Add(transaction);
                        }

                        chain.Height = block.Height;
                        chain.Blocks.Add(block);
                    }
                }

                await context.SaveChangesAsync();
            }
            catch (Exception ex)
            {
            }
        }