Exemplo n.º 1
0
        private InteropBlock GetInteropBlock(BigInteger blockId)
        {
            var url = DomainExtensions.GetOracleBlockURL(
                "neo", "neo", PBigInteger.FromUnsignedArray(blockId.ToByteArray(), true));

            return(OracleReader.Read <InteropBlock>(DateTime.Now, url));
        }
Exemplo n.º 2
0
        private List <Task <InteropBlock> > CreateTaskList(BigInteger batchCount, BigInteger[] blockIds = null)
        {
            List <Task <InteropBlock> > taskList = new List <Task <InteropBlock> >();

            if (blockIds == null)
            {
                var _interopBlockHeight = BigInteger.Parse(OracleReader.GetCurrentHeight("neo", "neo"));

                var nextCurrentBlockHeight = _interopBlockHeight + batchCount;

                for (var i = _interopBlockHeight; i < nextCurrentBlockHeight; i++)
                {
                    var url = DomainExtensions.GetOracleBlockURL(
                        "neo", "neo", PBigInteger.FromUnsignedArray(i.ToByteArray(), true));

                    taskList.Add(CreateTask(url));
                }
            }
            else
            {
                foreach (var blockId in blockIds)
                {
                    var url = DomainExtensions.GetOracleBlockURL(
                        "neo", "neo", PBigInteger.FromUnsignedArray(blockId.ToByteArray(), true));
                    taskList.Add(CreateTask(url));
                }
            }

            return(taskList);
        }
Exemplo n.º 3
0
        public BSCInterop(TokenSwapper swapper, EthAPI ethAPI, PBigInteger interopBlockHeight, string[] contracts, uint confirmations)
            : base(swapper, BSCWallet.BSCPlatform)
        {
            string lastBlockHeight = OracleReader.GetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform);

            if (string.IsNullOrEmpty(lastBlockHeight))
            {
                OracleReader.SetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, new BigInteger(interopBlockHeight.ToSignedByteArray()).ToString());
            }

            Logger.Message($"interopHeight: {OracleReader.GetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform)}");
            Console.WriteLine("encoded bsc: " + BSCWallet.EncodeAddress("0x44E8743A6CAC3E59594C19DD462863A5AA5E06BB"));
            Console.WriteLine("encoded eth: " + EthereumWallet.EncodeAddress("0x44E8743A6CAC3E59594C19DD462863A5AA5E06BB"));

            Console.WriteLine("from encoded bsc: " + BSCWallet.EncodeAddress("0xA89a34c37Da826085E458c17067DA2F38b6e4763"));
            Console.WriteLine("from encoded eth: " + EthereumWallet.EncodeAddress("0xA89a34c37Da826085E458c17067DA2F38b6e4763"));

            this.contracts = contracts.ToList();

            // add local swap address to contracts
            this.contracts.Add(LocalAddress);

            this.confirmations = confirmations;
            this.ethAPI        = ethAPI;
        }
Exemplo n.º 4
0
        public override List <Block> GetBlockRange(PBigInteger start, PBigInteger end)
        {
            List <Task <DataNode> > taskList  = new List <Task <DataNode> >();
            List <Block>            blockList = new List <Block>();

            for (var i = start; i < end; i++)
            {
                var      height     = i;
                object[] heightData = new object[] { (int)height };

                taskList.Add(
                    new Task <DataNode>(() =>
                {
                    return(QueryRPC("getblock", heightData, 1, true));
                })
                    );
            }

            foreach (var task in taskList)
            {
                task.Start();
            }

            Task.WaitAll(taskList.ToArray());

            foreach (var task in taskList)
            {
                var response = task.Result;

                if (response == null || !response.HasNode("result"))
                {
                    return(null);
                }

                var result = response.GetString("result");

                var bytes = result.HexToBytes();

                using (var stream = new MemoryStream(bytes))
                {
                    using (var reader = new BinaryReader(stream))
                    {
                        var block = Block.Unserialize(reader);
                        blockList.Add(block);
                    }
                }
            }

            return(blockList);
        }
Exemplo n.º 5
0
        public NeoInterop(TokenSwapper swapper, NeoAPI neoAPI, PBigInteger interopBlockHeight, bool quickSync)
            : base(swapper, NeoWallet.NeoPlatform)
        {
            string lastBlockHeight = OracleReader.GetCurrentHeight("neo", "neo");

            if (string.IsNullOrEmpty(lastBlockHeight))
            {
                OracleReader.SetCurrentHeight("neo", "neo", new BigInteger(interopBlockHeight.ToUnsignedByteArray()).ToString());
            }

            this.quickSync = quickSync;

            Logger.Message($"interopHeight: {OracleReader.GetCurrentHeight("neo", "neo")}");
            this.neoAPI = neoAPI;

            this.lastScan = DateTime.UtcNow.AddYears(-1);;
        }
Exemplo n.º 6
0
        public EthereumInterop(TokenSwapper swapper, EthAPI ethAPI, PBigInteger interopBlockHeight, string[] contracts, uint confirmations)
            : base(swapper, EthereumWallet.EthereumPlatform)
        {
            string lastBlockHeight = OracleReader.GetCurrentHeight(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform);

            if (string.IsNullOrEmpty(lastBlockHeight))
            {
                OracleReader.SetCurrentHeight(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, new BigInteger(interopBlockHeight.ToSignedByteArray()).ToString());
            }

            Logger.Message($"interopHeight: {OracleReader.GetCurrentHeight(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform)}");

            this.contracts = contracts.ToList();

            // add local swap address to contracts
            this.contracts.Add(LocalAddress);

            this.confirmations = confirmations;
            this.ethAPI        = ethAPI;
        }
Exemplo n.º 7
0
        private void ProcessBlock(InteropBlock block, List <PendingSwap> result)
        {
            foreach (var txHash in block.Transactions)
            {
                var interopTx = OracleReader.ReadTransaction("neo", "neo", txHash);

                if (interopTx.Transfers.Length == 0)
                {
                    continue;
                }

                if (interopTx.Transfers.Length == 0)
                {
                    continue;
                }

                InteropTransfer transfer;

                if (interopTx.Transfers.Length != 1)
                {
                    var sources = interopTx.Transfers.Select(x => x.sourceAddress).Distinct();
                    if (sources.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple source addresses not supported yet");
                    }

                    var dests = interopTx.Transfers.Select(x => x.destinationAddress).Distinct();
                    if (dests.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple destination addresses not supported yet");
                    }

                    var interops = interopTx.Transfers.Select(x => x.interopAddress).Distinct();
                    if (interops.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple interop addresses not supported yet");
                    }

                    var symbols = interopTx.Transfers.Select(x => x.Symbol).Distinct();

                    if (symbols.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple tokens not supported yet");
                    }

                    PBigInteger sum = 0;

                    foreach (var temp in interopTx.Transfers)
                    {
                        sum += temp.Value;
                    }

                    var first = interopTx.Transfers.First();

                    if (first.Data != null && first.Data.Length > 0)
                    {
                        throw new OracleException("neo transfers with custom data are not supported yet");
                    }

                    transfer = new InteropTransfer(first.sourceChain, first.sourceAddress, first.destinationChain, first.destinationAddress, first.interopAddress, first.Symbol, sum);
                }
                else
                {
                    transfer = interopTx.Transfers.First();
                }

                if (transfer.sourceAddress == transfer.destinationAddress) // ignore this tx, this is a utxo consolidation
                {
                    continue;
                }

                result.Add(
                    new PendingSwap(
                        this.PlatformName
                        , txHash
                        , transfer.sourceAddress
                        , transfer.interopAddress)
                    );
            }
        }
Exemplo n.º 8
0
        public override ApplicationLog[] GetApplicationLog(UInt256 hash)
        {
            if (!HasPlugin("ApplicationLogs"))
            {
                return(null);
            }

            var response = QueryRPC("getapplicationlog", new object[] { hash.ToString() });

            if (response != null && response.HasNode("result"))
            {
                //var json = LunarLabs.Parser.JSON.JSONReader.ReadFromString(response);
                List <ApplicationLog> appLogList = new List <ApplicationLog>();

                var executions = response["result"]["executions"];
                //LogData(executions);
                for (var i = 0; i < executions.ChildCount; i++)
                {
                    VMState vmstate;
                    if (Enum.TryParse(executions[i].GetString("vmstate"), out vmstate))
                    {
                        //LogData(executions[i]["notifications"][0]["state"]["value"]);
                        var notifications = executions[i]["notifications"];
                        for (var j = 0; j < notifications.ChildCount; j++)
                        {
                            var         states   = notifications[j]["state"]["value"];
                            string      txevent  = "";
                            UInt160     source   = UInt160.Zero;
                            UInt160     target   = UInt160.Zero;
                            PBigInteger amount   = 0;
                            var         contract = notifications[j].GetString("contract");

                            if (states[0].GetString("type") == "ByteArray")
                            {
                                txevent = (states[0].GetString("value"));
                            }

                            if (states[1].GetString("type") == "ByteArray" &&
                                !string.IsNullOrEmpty(states[1].GetString("value")))
                            {
                                source = UInt160.Parse(states[1].GetString("value"));
                            }

                            if (states[2].GetString("type") == "ByteArray" &&
                                !string.IsNullOrEmpty(states[2].GetString("value")))
                            {
                                target = UInt160.Parse(states[2].GetString("value"));
                            }

                            if (states[3].GetString("type") == "ByteArray")
                            {
                                amount = PBigInteger.FromUnsignedArray(states[3].GetString("value").HexToBytes(), true); // needs to be Phantasma.Numerics.BigInteger for now.
                            }
                            appLogList.Add(new ApplicationLog(vmstate, contract, txevent, source, target, amount));
                        }
                    }
                }

                return(appLogList.ToArray());
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 9
0
        private static Dictionary <string, List <InteropTransfer> > GetInteropTransfers(Nexus nexus, Logger logger,
                                                                                        TransactionReceipt txr, EthAPI api, string[] swapAddresses)
        {
            logger.Debug($"get interop transfers for tx {txr.TransactionHash}");
            var interopTransfers = new Dictionary <string, List <InteropTransfer> >();

            Nethereum.RPC.Eth.DTOs.Transaction tx = null;
            try
            {
                // tx to get the eth transfer if any
                tx = api.GetTransaction(txr.TransactionHash);
            }
            catch (Exception e)
            {
                logger.Error("Getting eth tx failed: " + e.Message);
            }

            logger.Debug("Transaction status: " + txr.Status.Value);
            // check if tx has failed
            if (txr.Status.Value == 0)
            {
                logger.Error($"tx {txr.TransactionHash} failed");
                return(interopTransfers);
            }

            var     nodeSwapAddresses = swapAddresses.Select(x => EthereumWallet.EncodeAddress(x));
            Address interopAddress;

            try
            {
                interopAddress = ExtractInteropAddress(tx, logger);
            }
            catch (Exception e)
            {
                if (e.ToString().Contains("Header byte out of range"))
                {
                    // Ignoring this exception and skipping this tx.
                    // RecoverFromSignature() crashed and we cannot avoid it atm.
                    // Related to EIP-1559, example of probematic tx: https://etherscan.io/tx/0xb022c146d8d1e684de0c1faae43e7ce36afb6969719adfdcafcc5bb7d5913185
                    // TODO Fix by updating to new Nethereum and dealing with EIP-1559 better.
                    logger.Debug("Warning: Skipping 'Header byte out of range' tx: " + tx.TransactionHash);
                    return(interopTransfers);
                }
                else
                {
                    throw;
                }
            }

            // ERC721 (NFT)
            // TODO currently this code block is mostly copypaste from ERC20 block, later make a single method for both...
            //var erc721_events = txr.DecodeAllEvents<Nethereum.StandardNonFungibleTokenERC721.ContractDefinition.TransferEventDTOBase>();
            //foreach (var evt in erc721_events)
            //{
            //    var asset = EthUtils.FindSymbolFromAsset(nexus, evt.Log.Address);
            //    if (asset == null)
            //    {
            //        logger.Warning($"Asset [{evt.Log.Address}] not supported");
            //        continue;
            //    }

            //    var targetAddress = EthereumWallet.EncodeAddress(evt.Event.To);
            //    var sourceAddress = EthereumWallet.EncodeAddress(evt.Event.From);
            //    var tokenID = PBigInteger.Parse(evt.Event.TokenId.ToString());

            //    if (nodeSwapAddresses.Contains(targetAddress))
            //    {
            //        if (!interopTransfers.ContainsKey(evt.Log.TransactionHash))
            //        {
            //            interopTransfers.Add(evt.Log.TransactionHash, new List<InteropTransfer>());
            //        }

            //        string tokenURI = FetchTokenURI(evt.Log.Address, evt.Event.TokenId);

            //        interopTransfers[evt.Log.TransactionHash].Add
            //        (
            //            new InteropTransfer
            //            (
            //                EthereumWallet.EthereumPlatform,
            //                sourceAddress,
            //                DomainSettings.PlatformName,
            //                targetAddress,
            //                interopAddress,
            //                asset,
            //                tokenID,
            //                System.Text.Encoding.UTF8.GetBytes(tokenURI)
            //            )
            //        );
            //    }
            //}

            // ERC20
            var erc20_events = txr.DecodeAllEvents <TransferEventDTO>();

            foreach (var evt in erc20_events)
            {
                var asset = EthUtils.FindSymbolFromAsset(EthereumWallet.EthereumPlatform, nexus, evt.Log.Address);
                if (asset == null)
                {
                    logger.Warning($"Asset [{evt.Log.Address}] not supported");
                    continue;
                }

                var targetAddress = EthereumWallet.EncodeAddress(evt.Event.To);
                var sourceAddress = EthereumWallet.EncodeAddress(evt.Event.From);
                var amount        = PBigInteger.Parse(evt.Event.Value.ToString());

                if (nodeSwapAddresses.Contains(targetAddress))
                {
                    if (!interopTransfers.ContainsKey(evt.Log.TransactionHash))
                    {
                        interopTransfers.Add(evt.Log.TransactionHash, new List <InteropTransfer>());
                    }

                    interopTransfers[evt.Log.TransactionHash].Add
                    (
                        new InteropTransfer
                        (
                            EthereumWallet.EthereumPlatform,
                            sourceAddress,
                            DomainSettings.PlatformName,
                            targetAddress,
                            interopAddress,
                            asset,
                            amount
                        )
                    );
                }
            }

            if (tx.Value != null && tx.Value.Value > 0)
            {
                var targetAddress = EthereumWallet.EncodeAddress(tx.To);
                var sourceAddress = EthereumWallet.EncodeAddress(tx.From);

                if (nodeSwapAddresses.Contains(targetAddress))
                {
                    var amount = PBigInteger.Parse(tx.Value.ToString());

                    if (!interopTransfers.ContainsKey(tx.TransactionHash))
                    {
                        interopTransfers.Add(tx.TransactionHash, new List <InteropTransfer>());
                    }

                    interopTransfers[tx.TransactionHash].Add
                    (
                        new InteropTransfer
                        (
                            EthereumWallet.EthereumPlatform,
                            sourceAddress,
                            DomainSettings.PlatformName,
                            targetAddress,
                            interopAddress,
                            "ETH", // TODO use const
                            amount
                        )
                    );
                }
            }


            return(interopTransfers);
        }
Exemplo n.º 10
0
        public override IEnumerable <PendingSwap> Update()
        {
            // wait another 10s to execute eth interop
            //Task.Delay(10000).Wait();
            try
            {
                lock (String.Intern("PendingSetCurrentHeight_" + BSCWallet.BSCPlatform))
                {
                    var result = new List <PendingSwap>();

                    // initial start, we have to verify all processed swaps
                    if (initialStart)
                    {
                        Logger.Debug($"Read all bsc blocks now.");
                        var allInteropBlocks = OracleReader.ReadAllBlocks(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform);

                        Logger.Debug($"Found {allInteropBlocks.Count} blocks");

                        foreach (var block in allInteropBlocks)
                        {
                            ProcessBlock(block, ref result);
                        }

                        initialStart = false;

                        // return after the initial start to be able to process all swaps that happend in the mean time.
                        return(result);
                    }

                    var currentHeight       = ethAPI.GetBlockHeight();
                    var _interopBlockHeight = BigInteger.Parse(OracleReader.GetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform));
                    Logger.Debug($"Swaps: Current Eth chain height: {currentHeight}, interop: {_interopBlockHeight}, delta: {currentHeight - _interopBlockHeight}");

                    var blocksProcessedInOneBatch = 0;
                    while (blocksProcessedInOneBatch < 50)
                    {
                        if (_resyncBlockIds.Any())
                        {
                            for (var i = 0; i < _resyncBlockIds.Count; i++)
                            {
                                var blockId = _resyncBlockIds.ElementAt(i);
                                if (blockId > _interopBlockHeight)
                                {
                                    this.Logger.Warning($"EthInterop:Update() resync block {blockId} higher than current interop height, can't resync.");
                                    _resyncBlockIds.RemoveAt(i);
                                    continue;
                                }

                                try
                                {
                                    this.Logger.Debug($"EthInterop:Update() resync block {blockId} now.");
                                    var block = GetInteropBlock(blockId);
                                    ProcessBlock(block, ref result);
                                }
                                catch (Exception e)
                                {
                                    this.Logger.Error($"EthInterop:Update() resync block {blockId} failed: " + e);
                                }
                                _resyncBlockIds.RemoveAt(i);
                            }
                        }

                        blocksProcessedInOneBatch++;

                        var blockDifference = currentHeight - _interopBlockHeight;
                        if (blockDifference < confirmations)
                        {
                            // no need to query the node yet
                            break;
                        }

                        //TODO quick sync not done yet, requieres a change to the oracle impl to fetch multiple blocks
                        //var nextHeight = (blockDifference > 50) ? 50 : blockDifference; //TODO

                        //var transfers = new Dictionary<string, Dictionary<string, List<InteropTransfer>>>();

                        //if (nextHeight > 1)
                        //{
                        //    var blockCrawler = new EthBlockCrawler(logger, contracts.ToArray(), 0/*confirmations*/, ethAPI); //TODO settings confirmations

                        //    blockCrawler.Fetch(currentHeight, nextHeight);
                        //    transfers = blockCrawler.ExtractInteropTransfers(logger, LocalAddress);
                        //    foreach (var entry in transfers)
                        //    {
                        //        foreach (var txInteropTransfer in entry.Value)
                        //        {
                        //            foreach (var interopTransfer in txInteropTransfer.Value)
                        //            {
                        //                result.Add(new PendingSwap(
                        //                    this.PlatformName
                        //                    ,Hash.Parse(entry.Key)
                        //                    ,interopTransfer.sourceAddress
                        //                    ,interopTransfer.interopAddress)
                        //                );
                        //            }
                        //        }
                        //    }

                        //    _interopBlockHeight = nextHeight;
                        //    oracleReader.SetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, _interopBlockHeight.ToString());
                        //}
                        //else
                        //{

                        /* Future improvement, implement oracle call to fetch multiple blocks */
                        var url = DomainExtensions.GetOracleBlockURL(
                            BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, PBigInteger.FromUnsignedArray(_interopBlockHeight.ToByteArray(), true));

                        var interopBlock = OracleReader.Read <InteropBlock>(DateTime.Now, url);

                        ProcessBlock(interopBlock, ref result);

                        _interopBlockHeight++;
                        //}
                    }

                    OracleReader.SetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, _interopBlockHeight.ToString());

                    var total = result.Count();
                    if (total > 0)
                    {
                        Logger.Message($"startup: found {total} bsc swaps");
                    }
                    else
                    {
                        Logger.Debug($"did not find any bsc swaps");
                    }
                    return(result);
                }
            }
            catch (Exception e)
            {
                var logMessage = "BSCInterop.Update() exception caught:\n" + e.Message;
                var inner      = e.InnerException;
                while (inner != null)
                {
                    logMessage += "\n---> " + inner.Message + "\n\n" + inner.StackTrace;
                    inner       = inner.InnerException;
                }
                logMessage += "\n\n" + e.StackTrace;

                Logger.Error(logMessage);

                return(new List <PendingSwap>());
            }
        }
Exemplo n.º 11
0
        private static Dictionary <string, List <InteropTransfer> > GetInteropTransfers(Nexus nexus, Logger logger,
                                                                                        TransactionReceipt txr, EthAPI api, string[] swapAddresses)
        {
            logger.Debug($"get interop transfers for tx {txr.TransactionHash}");
            var interopTransfers = new Dictionary <string, List <InteropTransfer> >();

            Nethereum.RPC.Eth.DTOs.Transaction tx = null;
            try
            {
                // tx to get the eth transfer if any
                tx = api.GetTransaction(txr.TransactionHash);
            }
            catch (Exception e)
            {
                logger.Error("Getting eth tx failed: " + e.Message);
            }

            Console.WriteLine("txr: " + txr.Status);
            logger.Debug("Transaction status: " + txr.Status.Value);
            // check if tx has failed
            if (txr.Status.Value == 0)
            {
                logger.Error($"tx {txr.TransactionHash} failed");
                return(interopTransfers);
            }

            foreach (var a in swapAddresses)
            {
                Console.WriteLine("swap address: " + a);
            }
            var nodeSwapAddresses = swapAddresses.Select(x => BSCWallet.EncodeAddress(x));
            var interopAddress    = ExtractInteropAddress(tx);

            Console.WriteLine("interop address: " + interopAddress);

            // ERC721 (NFT)
            // TODO currently this code block is mostly copypaste from BEP20 block, later make a single method for both...
            //var erc721_events = txr.DecodeAllEvents<Nethereum.StandardNonFungibleTokenERC721.ContractDefinition.TransferEventDTOBase>();
            //foreach (var evt in erc721_events)
            //{
            //    var asset = EthUtils.FindSymbolFromAsset(nexus, evt.Log.Address);
            //    if (asset == null)
            //    {
            //        logger.Warning($"Asset [{evt.Log.Address}] not supported");
            //        continue;
            //    }

            //    var targetAddress = BSCWallet.EncodeAddress(evt.Event.To);
            //    var sourceAddress = BSCWallet.EncodeAddress(evt.Event.From);
            //    var tokenID = PBigInteger.Parse(evt.Event.TokenId.ToString());

            //    if (nodeSwapAddresses.Contains(targetAddress))
            //    {
            //        if (!interopTransfers.ContainsKey(evt.Log.TransactionHash))
            //        {
            //            interopTransfers.Add(evt.Log.TransactionHash, new List<InteropTransfer>());
            //        }

            //        string tokenURI = FetchTokenURI(evt.Log.Address, evt.Event.TokenId);

            //        interopTransfers[evt.Log.TransactionHash].Add
            //        (
            //            new InteropTransfer
            //            (
            //                BSCWallet.BSCPlatform,
            //                sourceAddress,
            //                DomainSettings.PlatformName,
            //                targetAddress,
            //                interopAddress,
            //                asset,
            //                tokenID,
            //                System.Text.Encoding.UTF8.GetBytes(tokenURI)
            //            )
            //        );
            //    }
            //}

            // BEP20
            var bep20_events = txr.DecodeAllEvents <TransferEventDTO>();

            foreach (var evt in bep20_events)
            {
                var asset = EthUtils.FindSymbolFromAsset(BSCWallet.BSCPlatform, nexus, evt.Log.Address);
                if (asset == null)
                {
                    logger.Warning($"Asset [{evt.Log.Address}] not supported");
                    continue;
                }

                var targetAddress = BSCWallet.EncodeAddress(evt.Event.To);
                var sourceAddress = BSCWallet.EncodeAddress(evt.Event.From);
                var amount        = PBigInteger.Parse(evt.Event.Value.ToString());

                if (nodeSwapAddresses.Contains(targetAddress))
                {
                    if (!interopTransfers.ContainsKey(evt.Log.TransactionHash))
                    {
                        interopTransfers.Add(evt.Log.TransactionHash, new List <InteropTransfer>());
                    }

                    interopTransfers[evt.Log.TransactionHash].Add
                    (
                        new InteropTransfer
                        (
                            BSCWallet.BSCPlatform,
                            sourceAddress,
                            DomainSettings.PlatformName,
                            targetAddress,
                            interopAddress,
                            asset,
                            amount
                        )
                    );
                }
            }

            Console.WriteLine("value: " + tx.Value);
            Console.WriteLine("value: " + tx.Value.Value);
            if (tx.Value != null && tx.Value.Value > 0)
            {
                var targetAddress = BSCWallet.EncodeAddress(tx.To);
                var sourceAddress = BSCWallet.EncodeAddress(tx.From);

                foreach (var a in nodeSwapAddresses)
                {
                    Console.WriteLine("node swap address: " + a);
                }
                Console.WriteLine("target address: " + targetAddress);

                if (nodeSwapAddresses.Contains(targetAddress))
                {
                    var amount = PBigInteger.Parse(tx.Value.ToString());

                    if (!interopTransfers.ContainsKey(tx.TransactionHash))
                    {
                        interopTransfers.Add(tx.TransactionHash, new List <InteropTransfer>());
                    }

                    interopTransfers[tx.TransactionHash].Add
                    (
                        new InteropTransfer
                        (
                            BSCWallet.BSCPlatform,
                            sourceAddress,
                            DomainSettings.PlatformName,
                            targetAddress,
                            interopAddress,
                            "BSC", // TODO use const
                            amount
                        )
                    );
                }
            }


            return(interopTransfers);
        }
Exemplo n.º 12
0
        private static Dictionary <string, List <InteropTransfer> > GetInteropTransfers(Nexus nexus, Logger logger,
                                                                                        TransactionReceipt txr, EthAPI api, string swapAddress)
        {
            logger.Debug($"get interop transfers for tx {txr.TransactionHash}");
            var interopTransfers = new Dictionary <string, List <InteropTransfer> >();

            Nethereum.RPC.Eth.DTOs.Transaction tx = null;
            try
            {
                // tx to get the eth transfer if any
                tx = api.GetTransaction(txr.TransactionHash);
            }
            catch (Exception e)
            {
                logger.Error("Getting eth tx failed: " + e.Message);
            }

            logger.Debug("Transaction status: " + txr.Status.Value);
            // check if tx has failed
            if (txr.Status.Value == 0)
            {
                logger.Error($"tx {txr.TransactionHash} failed");
                return(interopTransfers);
            }

            var nodeSwapAddress = EthereumWallet.EncodeAddress(swapAddress);
            var events          = txr.DecodeAllEvents <TransferEventDTO>();
            var interopAddress  = ExtractInteropAddress(tx);

            // ERC20
            foreach (var evt in events)
            {
                var asset = EthUtils.FindSymbolFromAsset(nexus, evt.Log.Address);
                if (asset == null)
                {
                    logger.Warning($"Asset [{evt.Log.Address}] not supported");
                    continue;
                }

                var targetAddress = EthereumWallet.EncodeAddress(evt.Event.To);
                var sourceAddress = EthereumWallet.EncodeAddress(evt.Event.From);
                var amount        = PBigInteger.Parse(evt.Event.Value.ToString());

                if (targetAddress.Equals(nodeSwapAddress))
                {
                    if (!interopTransfers.ContainsKey(evt.Log.TransactionHash))
                    {
                        interopTransfers.Add(evt.Log.TransactionHash, new List <InteropTransfer>());
                    }

                    interopTransfers[evt.Log.TransactionHash].Add
                    (
                        new InteropTransfer
                        (
                            EthereumWallet.EthereumPlatform,
                            sourceAddress,
                            DomainSettings.PlatformName,
                            targetAddress,
                            interopAddress,
                            asset,
                            amount
                        )
                    );
                }
            }

            if (tx.Value != null && tx.Value.Value > 0)
            {
                var targetAddress = EthereumWallet.EncodeAddress(tx.To);
                var sourceAddress = EthereumWallet.EncodeAddress(tx.From);

                if (targetAddress.Equals(nodeSwapAddress))
                {
                    var amount = PBigInteger.Parse(tx.Value.ToString());

                    if (!interopTransfers.ContainsKey(tx.TransactionHash))
                    {
                        interopTransfers.Add(tx.TransactionHash, new List <InteropTransfer>());
                    }

                    interopTransfers[tx.TransactionHash].Add
                    (
                        new InteropTransfer
                        (
                            EthereumWallet.EthereumPlatform,
                            sourceAddress,
                            DomainSettings.PlatformName,
                            targetAddress,
                            interopAddress,
                            "ETH", // TODO use const
                            amount
                        )
                    );
                }
            }


            return(interopTransfers);
        }
Exemplo n.º 13
0
 public abstract List <Block> GetBlockRange(PBigInteger start, PBigInteger end);
Exemplo n.º 14
0
        public static InteropTransaction MakeInteropTx(Logger logger, NeoTx tx, NeoAPI api, string[] origSwapAddresses,
                                                       string coldStorage)
        {
            logger.Debug("checking tx: " + tx.Hash);
            var swapAddresses = new List <Address>();

            foreach (var addr in origSwapAddresses)
            {
                swapAddresses.Add(NeoWallet.EncodeAddress(addr));
            }

            List <InteropTransfer> interopTransfers = new List <InteropTransfer>();

            var emptyTx = new InteropTransaction(Hash.Null, interopTransfers.ToArray());

            PBigInteger amount;
            var         witness = tx.witnesses.ElementAtOrDefault(0);

            if (witness == null)
            {
                // tx has no witness
                return(emptyTx);
            }

            var interopAddress = witness.ExtractAddress();

            if (tx.witnesses.Length != 1 || interopAddress == Address.Null || interopAddress == null)
            {
                //currently only one witness allowed
                // if ExtractAddress returns Address.Null, the tx is not properly signed
                return(emptyTx);
            }

            var sourceScriptHash = witness.verificationScript.Sha256().RIPEMD160();
            var sourceAddress    = NeoWallet.EncodeByteArray(sourceScriptHash);
            var sourceDecoded    = NeoWallet.DecodeAddress(sourceAddress);

            if (sourceAddress == interopAddress || sourceDecoded == coldStorage)
            {
                logger.Warning("self send tx or cold storage transfer found, ignoring: " + tx.Hash);
                // self send, probably consolidation tx, ignore
                return(emptyTx);
            }

            //logger.Debug("interop address: " + interopAddress);
            //logger.Debug("xswapAddress: " + swapAddress);
            //logger.Debug("interop sourceAddress: " + sourceAddress);
            //logger.Debug("neo sourceAddress: " + NeoWallet.DecodeAddress(sourceAddress));

            if (tx.attributes != null && tx.attributes.Length > 0)
            {
                foreach (var attr in tx.attributes)
                {
                    if (attr.Usage == TransactionAttributeUsage.Description)
                    {
                        try
                        {
                            var text = Encoding.UTF8.GetString(attr.Data);
                            if (Address.IsValidAddress(text))
                            {
                                interopAddress = Address.FromText(text);
                                //logger.Debug("new interop address: " + interopAddress);
                            }
                        }
                        catch {}
                    }
                }
            }

            if (tx.outputs.Length > 0)
            {
                foreach (var output in tx.outputs)
                {
                    var targetAddress = NeoWallet.EncodeByteArray(output.scriptHash.ToArray());
                    //logger.Debug("interop targetAddress : " + targetAddress);
                    //logger.Debug("neo targetAddress: " + NeoWallet.DecodeAddress(targetAddress));
                    //logger.Debug("interopSwapAddress: " + interopSwapAddress);
                    //logger.Debug("targetAddress: " + targetAddress);

                    //var swpAddress = NeoWallet.EncodeAddress(swapAddress);
                    //logger.Debug("interop swpAddress: " + swpAddress);
                    //logger.Debug("neo swpAddress: " + NeoWallet.DecodeAddress(swpAddress));
                    //if (targetAddress.ToString() == swapAddress)
                    if (swapAddresses.Contains(targetAddress))
                    {
                        var token = FindSymbolFromAsset(new UInt256(output.assetID).ToString());
                        CryptoCurrencyInfo tokenInfo;
                        if (NeoTokenInfo.TryGetValue(token, out tokenInfo))
                        {
                            amount = Phantasma.Numerics.UnitConversion.ToBigInteger(
                                output.value, tokenInfo.Decimals);
                        }
                        else
                        {
                            // asset not swapable at the moment...
                            //logger.Debug("Asset not swapable");
                            return(emptyTx);
                        }

                        //logger.Debug("UTXO " + amount);
                        interopTransfers.Add
                        (
                            new InteropTransfer
                            (
                                NeoWallet.NeoPlatform,
                                sourceAddress,
                                DomainSettings.PlatformName,
                                targetAddress,
                                interopAddress, // interop address
                                token.ToString(),
                                amount
                            )
                        );
                    }
                }
            }

            if (tx.script != null && tx.script.Length > 0) // NEP5 transfers
            {
                var script = NeoDisassembler.Disassemble(tx.script, true);

                //logger.Debug("SCRIPT ====================");
                //foreach (var entry in script.lines)
                //{
                //    logger.Debug($"{entry.name} : { entry.opcode }");
                //}
                //logger.Debug("SCRIPT ====================");

                if (script.lines.Count() < 7)
                {
                    //logger.Debug("NO SCRIPT!!!!");
                    return(emptyTx);
                }

                var disasmEntry = script.lines.ElementAtOrDefault(6);

                //if ( disasmEntry == null )
                //{
                //    logger.Debug("disasmEntry is null");
                //}
                //if ( disasmEntry != null )
                //{
                //    if ( disasmEntry.data == null)
                //        logger.Debug("disasmEntry.data is 0");
                //}

                if (disasmEntry.name != "APPCALL" || disasmEntry.data == null || disasmEntry.data.Length == 0)
                {
                    //logger.Debug("NO APPCALL");
                    return(emptyTx);
                }
                else
                {
                    var assetString = new UInt160(disasmEntry.data).ToString();
                    if (string.IsNullOrEmpty(assetString) || FindSymbolFromAsset(assetString) == null)
                    {
                        //logger.Debug("Ignore TX due to non swapable token.");
                        return(emptyTx);
                    }
                }

                int pos = 0;
                foreach (var entry in script.lines)
                {
                    pos++;
                    if (pos > 3)
                    {
                        // we are only interested in the first three elements
                        break;
                    }

                    if (entry.data == null || entry.data.Length == 0)
                    {
                        logger.Debug("Ignore tx, invalid data field: " + tx);
                        return(emptyTx);
                    }

                    if (pos == 1)
                    {
                        amount = PBigInteger.FromUnsignedArray(entry.data, true);
                    }
                    if (pos == 2 || pos == 3)
                    {
                        if (pos == 2)
                        {
                            if (entry.data == null || entry.data.Length == 0)
                            {
                                logger.Debug("Invalid op on pos 2, ignoring tx: " + tx);
                                return(emptyTx);
                            }
                            var targetScriptHash = new UInt160(entry.data);
                            //logger.Debug("neo targetAddress: " + targetScriptHash.ToAddress());
                            var targetAddress = NeoWallet.EncodeByteArray(entry.data);
                            //logger.Debug("targetAddress : " + targetAddress);
                            //logger.Debug("interopSwapAddress: " + interopSwapAddress);
                            //logger.Debug("SwapAddress: " + swapAddress);
                            if (swapAddresses.Contains(targetAddress))
                            {
                                // found a swap, call getapplicationlog now to get transaction details and verify the tx was actually processed.
                                ApplicationLog[] appLogs = null;
                                try
                                {
                                    appLogs = api.GetApplicationLog(tx.Hash);
                                }
                                catch (Exception e)
                                {
                                    logger.Error("Getting application logs failed: " + e.Message);
                                    return(new InteropTransaction(Hash.Null, interopTransfers.ToArray()));
                                }

                                if (appLogs != null)
                                {
                                    for (var i = 0; i < appLogs.Length; i++)
                                    {
                                        //logger.Debug("appLogs[i].contract" + appLogs[i].contract);
                                        var token = FindSymbolFromAsset(appLogs[i].contract);
                                        //logger.Debug("TOKEN::::::::::::::::::: " + token);
                                        //logger.Debug("amount: " + appLogs[i].amount + " " + token);
                                        var sadd = NeoWallet.EncodeByteArray(appLogs[i].sourceAddress.ToArray());
                                        var tadd = NeoWallet.EncodeByteArray(appLogs[i].targetAddress.ToArray());


                                        interopTransfers.Add
                                        (
                                            new InteropTransfer
                                            (
                                                "neo", // todo Pay.Chains.NeoWallet.NeoPlatform
                                                       //NeoWallet.EncodeByteArray(appLogs[i].sourceAddress.ToArray()),
                                                sourceAddress,
                                                DomainSettings.PlatformName,
                                                targetAddress,
                                                interopAddress, // interop address
                                                token,
                                                appLogs[i].amount
                                            )
                                        );
                                    }
                                }
                                else
                                {
                                    logger.Warning("Neo swap is found but application log is not available for tx " + tx.Hash);
                                }
                            }
                        }
                        else
                        {
                            //TODO reverse swap
                            sourceScriptHash = new UInt160(entry.data).ToArray();
                            sourceAddress    = NeoWallet.EncodeByteArray(sourceScriptHash.ToArray());
                        }
                    }
                }
            }

            var total = interopTransfers.Count();

            if (total > 0)
            {
                logger.Message($"Found {total} swaps in neo tx {tx.Hash}");
            }
            else
            {
                logger.Debug($"No swaps in neo tx {tx.Hash}");
            }

            return((interopTransfers.Count() > 0)
                ? new InteropTransaction(Hash.Parse(tx.Hash.ToString()), interopTransfers.ToArray())
                : new InteropTransaction(Hash.Null, interopTransfers.ToArray()));
        }
Exemplo n.º 15
0
        public InteropTransfers ExtractInteropTransfers(Blockchain.Nexus nexus, Logger logger, string swapAddress)
        {
            var interopTransfers = new InteropTransfers();

            lock (transactions)
            {
                foreach (var txVo in transactions)
                {
                    var block = txVo.Block;
                    var txr   = txVo.TransactionReceipt;
                    var tx    = txVo.Transaction;

                    var interopAddress = EthereumInterop.ExtractInteropAddress(tx);
                    var transferEvents = txr.DecodeAllEvents <TransferEventDTO>();
                    //var swapEvents = txr.DecodeAllEvents<SwapEventDTO>();
                    var nodeSwapAddress = EthereumWallet.EncodeAddress(swapAddress);

                    if (transferEvents.Count > 0 || tx.Value != null && tx.Value.Value > 0)
                    {
                        if (!interopTransfers.ContainsKey(block.BlockHash))
                        {
                            interopTransfers.Add(block.BlockHash, new Dictionary <string, List <InteropTransfer> >());
                        }
                    }

                    if (transferEvents.Count > 0)
                    {
                        var blockId = block.Number.ToString();
                        var hash    = txr.TransactionHash;

                        foreach (var evt in transferEvents)
                        {
                            var targetAddress = EthereumWallet.EncodeAddress(evt.Event.To);

                            // If it's not our address, skip immediatly, don't log it
                            if (targetAddress != nodeSwapAddress)
                            {
                                continue;
                            }

                            logger.Message($"Found ERC20 swap: {blockId} hash: {hash} to: {evt.Event.To} from: {evt.Event.From} value: {evt.Event.Value}");
                            var asset = EthUtils.FindSymbolFromAsset(nexus, evt.Log.Address);
                            logger.Message("asset: " + asset);
                            if (asset == null)
                            {
                                logger.Message($"Asset [{evt.Log.Address}] not supported");
                                continue;
                            }


                            var sourceAddress = EthereumWallet.EncodeAddress(evt.Event.From);
                            var amount        = PBigInteger.Parse(evt.Event.Value.ToString());

                            logger.Message("nodeSwapAddress: " + nodeSwapAddress);
                            logger.Message("sourceAddress: " + sourceAddress);
                            logger.Message("targetAddress: " + targetAddress);
                            logger.Message("amount: " + amount);

                            if (!interopTransfers[block.BlockHash].ContainsKey(evt.Log.TransactionHash))
                            {
                                interopTransfers[block.BlockHash].Add(evt.Log.TransactionHash, new List <InteropTransfer>());
                            }

                            interopTransfers[block.BlockHash][evt.Log.TransactionHash].Add
                            (
                                new InteropTransfer
                                (
                                    EthereumWallet.EthereumPlatform,
                                    sourceAddress,
                                    DomainSettings.PlatformName,
                                    targetAddress,
                                    interopAddress, // interop address
                                    asset,
                                    amount
                                )
                            );
                        }
                    }

                    if (tx.Value != null && tx.Value.Value > 0)
                    {
                        logger.Message("ETH:");
                        logger.Message(block.Number.ToString());
                        logger.Message(tx.TransactionHash);
                        logger.Message(tx.To);
                        logger.Message(tx.From);
                        logger.Message(tx.Value.ToString());

                        var targetAddress = EthereumWallet.EncodeAddress(tx.To);

                        if (targetAddress != nodeSwapAddress)
                        {
                            continue;
                        }

                        if (!interopTransfers[block.BlockHash].ContainsKey(tx.TransactionHash))
                        {
                            interopTransfers[block.BlockHash].Add(tx.TransactionHash, new List <InteropTransfer>());
                        }

                        var sourceAddress = EthereumWallet.EncodeAddress(tx.From);
                        var amount        = PBigInteger.Parse(tx.Value.ToString());

                        interopTransfers[block.BlockHash][tx.TransactionHash].Add
                        (
                            new InteropTransfer
                            (
                                EthereumWallet.EthereumPlatform,
                                sourceAddress,
                                DomainSettings.PlatformName,
                                targetAddress,
                                interopAddress, // interop address
                                "ETH",          // TODO use const
                                amount
                            )
                        );
                    }
                }

                transactions.Clear();
            }

            // clear transactions after extraction was done
            return(interopTransfers);
        }
Exemplo n.º 16
0
        public override IEnumerable <PendingSwap> Update()
        {
            lock (String.Intern("PendingSetCurrentHeight_" + "neo"))
            {
                var result = new List <PendingSwap>();
                try
                {
                    var _interopBlockHeight = BigInteger.Parse(OracleReader.GetCurrentHeight("neo", "neo"));

                    // initial start, we have to verify all processed swaps
                    if (initialStart)
                    {
                        Logger.Debug($"Read all neo blocks now.");
                        // TODO check if quick sync nodes are configured, if so use quick sync
                        // we need to find a better solution for that though
                        var allInteropBlocks = OracleReader.ReadAllBlocks("neo", "neo");

                        Logger.Debug($"Found {allInteropBlocks.Count} blocks");

                        foreach (var block in allInteropBlocks)
                        {
                            try
                            {
                                ProcessBlock(block, result);
                            }
                            catch (Exception e)
                            {
                                Logger.Debug($"Block {block.Hash} was not processed correctly: " + e);
                            }
                        }

                        initialStart = false;

                        Logger.Debug($"QuickSync: " + quickSync);
                        // quick sync is only done once after startup
                        if (quickSync)
                        {
                            // if quick sync is active, we can use a specific plugin installed on the nodes (EventTracker)
                            try
                            {
                                var blockIds = neoAPI.GetSwapBlocks("ed07cffad18f1308db51920d99a2af60ac66a7b3", LocalAddress, _interopBlockHeight.ToString());
                                Logger.Debug($"Found {blockIds.Count} blocks to process ");
                                List <InteropBlock> blockList = new List <InteropBlock>();
                                foreach (var entry in blockIds)
                                {
                                    //logger.Debug($"read block {entry.Value}");
                                    var url = DomainExtensions.GetOracleBlockURL("neo", "neo", PBigInteger.Parse(entry.Value.ToString()));
                                    blockList.Add(OracleReader.Read <InteropBlock>(DateTime.Now, url));
                                }

                                // get blocks and order them for processing
                                var blocksToProcess = blockList.Where(x => blockIds.ContainsKey(x.Hash.ToString()))
                                                      .Select(x => new { block = x, id = blockIds[x.Hash.ToString()] })
                                                      .OrderBy(x => x.id);

                                Logger.Debug($"blocks to process: {blocksToProcess.Count()}");

                                foreach (var entry in blocksToProcess.OrderBy(x => x.id))
                                {
                                    Logger.Debug($"process block {entry.id}");
                                    ProcessBlock(entry.block, result);
                                    OracleReader.SetCurrentHeight("neo", "neo", _interopBlockHeight.ToString());
                                    _interopBlockHeight = BigInteger.Parse(entry.id.ToString());
                                }
                            }
                            catch (Exception e)
                            {
                                Logger.Error("Inital start failed: " + e.ToString());
                            }
                        }

                        // return after the initial start to be able to process all swaps that happend in the mean time.
                        return(result);
                    }

                    var blockIterator   = new BlockIterator(neoAPI);
                    var blockDifference = blockIterator.currentBlock - _interopBlockHeight;
                    var batchCount      = (blockDifference > 8) ? 8 : blockDifference; //TODO make it a constant, should be no more than 8

                    while (blockIterator.currentBlock > _interopBlockHeight)
                    {
                        if (_resyncBlockIds.Any())
                        {
                            for (var i = 0; i < _resyncBlockIds.Count; i++)
                            {
                                var blockId = _resyncBlockIds.ElementAt(i);
                                if (blockId > _interopBlockHeight)
                                {
                                    Logger.Debug($"NeoInterop: Update() resync block {blockId} higher than current interop height, can't resync.");
                                    _resyncBlockIds.RemoveAt(i);
                                    continue;
                                }

                                try
                                {
                                    Logger.Debug($"NeoInterop: Update() resync block {blockId} now.");
                                    var interopBlock = GetInteropBlock(blockId);
                                    ProcessBlock(interopBlock, result);
                                }
                                catch (Exception e)
                                {
                                    Logger.Error($"NeoInterop: Update() resync block {blockId} failed: " + e);
                                }
                                _resyncBlockIds.RemoveAt(i);
                            }
                        }

                        Logger.Debug($"Swaps: Current Neo chain height: {blockIterator.currentBlock}, interop: {_interopBlockHeight}, delta: {blockIterator.currentBlock - _interopBlockHeight}");
                        blockDifference = blockIterator.currentBlock - _interopBlockHeight;
                        batchCount      = (blockDifference > 8) ? 8 : blockDifference;

                        if (batchCount > 1)
                        {
                            List <Task <InteropBlock> > taskList = CreateTaskList(batchCount);

                            foreach (var task in taskList)
                            {
                                task.Start();
                            }

                            Task.WaitAll(taskList.ToArray());

                            foreach (var task in taskList)
                            {
                                var block = task.Result;

                                ProcessBlock(block, result);
                            }

                            OracleReader.SetCurrentHeight("neo", "neo", _interopBlockHeight.ToString());
                            _interopBlockHeight += batchCount;
                        }
                        else
                        {
                            var interopBlock = GetInteropBlock(_interopBlockHeight);

                            ProcessBlock(interopBlock, result);

                            OracleReader.SetCurrentHeight("neo", "neo", _interopBlockHeight.ToString());
                            _interopBlockHeight++;
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Error("Neo block sync failed: " + e);
                }
                return(result);
            }
        }
Exemplo n.º 17
0
        public InteropTransfers ExtractInteropTransfers(Blockchain.Nexus nexus, Logger logger, string[] swapAddresses)
        {
            var interopTransfers = new InteropTransfers();

            lock (transactions)
            {
                foreach (var txVo in transactions)
                {
                    var block = txVo.Block;
                    var txr   = txVo.TransactionReceipt;
                    var tx    = txVo.Transaction;

                    Address interopAddress;
                    try
                    {
                        interopAddress = EthereumInterop.ExtractInteropAddress(tx, logger);
                    }
                    catch (Exception e)
                    {
                        if (e.ToString().Contains("Header byte out of range"))
                        {
                            // Ignoring this exception and skipping this tx.
                            // RecoverFromSignature() crashed and we cannot avoid it atm.
                            // Related to EIP-1559, example of probematic tx: https://etherscan.io/tx/0xb022c146d8d1e684de0c1faae43e7ce36afb6969719adfdcafcc5bb7d5913185
                            // TODO Fix by updating to new Nethereum and dealing with EIP-1559 better.
                            logger.Debug("Warning: Skipping 'Header byte out of range' tx: " + tx.TransactionHash);
                            continue;
                        }
                        else
                        {
                            throw;
                        }
                    }
                    var transferEvents = txr.DecodeAllEvents <TransferEventDTO>();
                    //var swapEvents = txr.DecodeAllEvents<SwapEventDTO>();
                    var nodeSwapAddresses = swapAddresses.Select(x => encodeHandler(x)).ToList();
                    //var nodeSwapAddresses = encodeHandler(swapAddress);

                    if (transferEvents.Count > 0 || tx.Value != null && tx.Value.Value > 0)
                    {
                        if (!interopTransfers.ContainsKey(block.BlockHash))
                        {
                            interopTransfers.Add(block.BlockHash, new Dictionary <string, List <InteropTransfer> >());
                        }
                    }

                    if (transferEvents.Count > 0)
                    {
                        var blockId = block.Number.ToString();
                        var hash    = txr.TransactionHash;

                        foreach (var evt in transferEvents)
                        {
                            var targetAddress = encodeHandler(evt.Event.To);

                            // If it's not our address, skip immediatly, don't log it
                            if (!nodeSwapAddresses.Contains(targetAddress))
                            {
                                continue;
                            }

                            var asset = EthUtils.FindSymbolFromAsset(this.platform, nexus, evt.Log.Address);
                            logger.Debug($@"Found {this.platform} swap: {blockId} hash: {hash} to: {evt.Event.To}
                                from: {evt.Event.From} value: {evt.Event.Value} asset: {asset}");
                            if (asset == null)
                            {
                                logger.Debug($"Asset [{evt.Log.Address}] not supported");
                                continue;
                            }


                            var sourceAddress = encodeHandler(evt.Event.From);
                            var amount        = PBigInteger.Parse(evt.Event.Value.ToString());

                            //logger.Message("nodeSwapAddress: " + nodeSwapAddress);
                            //logger.Message("sourceAddress: " + sourceAddress);
                            //logger.Message("targetAddress: " + targetAddress);
                            //logger.Message("amount: " + amount);

                            if (!interopTransfers[block.BlockHash].ContainsKey(evt.Log.TransactionHash))
                            {
                                interopTransfers[block.BlockHash].Add(evt.Log.TransactionHash, new List <InteropTransfer>());
                            }

                            interopTransfers[block.BlockHash][evt.Log.TransactionHash].Add
                            (
                                new InteropTransfer
                                (
                                    this.platform,
                                    sourceAddress,
                                    DomainSettings.PlatformName,
                                    targetAddress,
                                    interopAddress, // interop address
                                    asset,
                                    amount
                                )
                            );
                        }
                    }

                    if (tx.Value != null && tx.Value.Value > 0)
                    {
                        //logger.Message("ETH:");
                        //logger.Message(block.Number.ToString());
                        //logger.Message(tx.TransactionHash);
                        //logger.Message(tx.To);
                        //logger.Message(tx.From);
                        //logger.Message(tx.Value.ToString());

                        var targetAddress = encodeHandler(tx.To);
                        Console.WriteLine("target eth: " + targetAddress);

                        if (!nodeSwapAddresses.Contains(targetAddress))
                        {
                            continue;
                        }

                        if (!interopTransfers[block.BlockHash].ContainsKey(tx.TransactionHash))
                        {
                            interopTransfers[block.BlockHash].Add(tx.TransactionHash, new List <InteropTransfer>());
                        }

                        var sourceAddress = encodeHandler(tx.From);
                        var amount        = PBigInteger.Parse(tx.Value.ToString());

                        var nativeSymbol = (this.platform == "ethereum") ? "ETH" : "BNB";

                        interopTransfers[block.BlockHash][tx.TransactionHash].Add
                        (
                            new InteropTransfer
                            (
                                this.platform,
                                sourceAddress,
                                DomainSettings.PlatformName,
                                targetAddress,
                                interopAddress, // interop address
                                nativeSymbol,
                                amount
                            )
                        );
                    }
                }

                transactions.Clear();
            }

            // clear transactions after extraction was done
            return(interopTransfers);
        }