public TokenSwapper(Spook node, PhantasmaKeys swapKey, NeoAPI neoAPI, EthAPI ethAPI, EthAPI bscAPI, BigInteger minFee) { this.Node = node; this.SwapKeys = swapKey; this.OracleReader = Nexus.GetOracleReader(); this.MinimumFee = minFee; this.neoAPI = neoAPI; this.ethAPI = ethAPI; this.bscAPI = bscAPI; this.Storage = new KeyStoreStorage(Nexus.CreateKeyStoreAdapter("swaps")); this._interopBlocks = new Dictionary <SwapPlatformChain, BigInteger>(); foreach (var platform in Settings.Oracle.SwapPlatforms) { _interopBlocks[platform.Chain] = platform.InteropHeight; } var inProgressMap = new StorageMap(InProgressTag, this.Storage); Console.WriteLine($"inProgress count: {inProgressMap.Count()}"); inProgressMap.Visit <Hash, string>((key, value) => { if (!string.IsNullOrEmpty(value)) { Console.WriteLine($"inProgress: {key} - {value}"); } }); }
public TokenSwapper(Spook node, PhantasmaKeys swapKey, NeoAPI neoAPI, EthAPI ethAPI, BigInteger minFee, string[] supportedPlatforms) { this.Node = node; this.SwapKeys = swapKey; this.OracleReader = Nexus.GetOracleReader(); this.MinimumFee = minFee; this.neoAPI = neoAPI; this.ethAPI = ethAPI; this.Storage = new KeyStoreStorage(Nexus.CreateKeyStoreAdapter("swaps")); this.interopBlocks = new Dictionary <string, BigInteger>(); interopBlocks[DomainSettings.PlatformName] = BigInteger.Parse(Settings.Oracle.PhantasmaInteropHeight); interopBlocks["neo"] = BigInteger.Parse(Settings.Oracle.NeoInteropHeight); interopBlocks["ethereum"] = BigInteger.Parse(Settings.Oracle.EthInteropHeight); _supportedPlatforms.Add(DomainSettings.PlatformName); foreach (var entry in supportedPlatforms) { if (_supportedPlatforms.Contains(entry)) { throw new SwapException($"Duplicated swap platform {entry}, check config"); } if (!interopBlocks.ContainsKey(entry)) { throw new SwapException($"Unknown swap platform {entry}, check config"); } _supportedPlatforms.Add(entry); } }
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; }
private void SetupOracleApis() { var neoPlatform = Settings.Oracle.SwapPlatforms.FirstOrDefault(x => x.Chain == SwapPlatformChain.Neo); if (neoPlatform != null && neoPlatform.Enabled) { var neoScanURL = Settings.Oracle.NeoscanUrl; this._neoAPI = new Neo.Core.RemoteRPCNode(neoScanURL, neoPlatform.RpcNodes); this._neoAPI.SetLogger((s) => Logger.Message(s)); this._neoScanAPI = new NeoScanAPI(neoScanURL, Logger, _nexus, _nodeKeys); } var bscPlatform = Settings.Oracle.SwapPlatforms.FirstOrDefault(x => x.Chain == SwapPlatformChain.BSC); if (bscPlatform != null && bscPlatform.Enabled) { var bscWIF = Settings.GetInteropWif(Nexus, _nodeKeys, BSCWallet.BSCPlatform); var bscKeys = PhantasmaKeys.FromWIF(bscWIF); this._bscAPI = new EthAPI(SwapPlatformChain.BSC, this.Nexus, this.Settings, new EthAccount(bscKeys.PrivateKey.ToHex()), Logger); } var ethPlatform = Settings.Oracle.SwapPlatforms.FirstOrDefault(x => x.Chain == SwapPlatformChain.Ethereum); if (ethPlatform != null && ethPlatform.Enabled) { var ethWIF = Settings.GetInteropWif(Nexus, _nodeKeys, EthereumWallet.EthereumPlatform); var ethKeys = PhantasmaKeys.FromWIF(ethWIF); this._ethAPI = new EthAPI(SwapPlatformChain.Ethereum, this.Nexus, this.Settings, new EthAccount(ethKeys.PrivateKey.ToHex()), Logger); } this._cryptoCompareAPIKey = Settings.Oracle.CryptoCompareAPIKey; if (!string.IsNullOrEmpty(this._cryptoCompareAPIKey)) { Logger.Message($"CryptoCompare API enabled."); } else { throw new Exception($"CryptoCompare API key missing, oracles won't work properly and oracles are no longer optional..."); } }
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; }
private void Init() { Hdd = DEV9Header.HDD_DEF; HddSize = 8 * 1024; Eth = DEV9Header.ETH_DEF; EthType = EthAPI.Winsock; EthEnable = true; HddEnable = false; DirectConnectionSettings = new ConfigDirectIP(); SocketConnectionSettings = new ConfigSocketIP(); EnableLogging = new ConfigLogging(); Hosts = new HashSet <ConfigHost>(); Hosts.Add(new ConfigHost() { Desc = "Set DNS to 192.0.2.1 to use this host list", URL = "www.example.com", IP = "0.0.0.0", Enabled = false }); }
private void SetupOracleApis() { var neoScanURL = Settings.Oracle.NeoscanUrl; var neoRpcList = Settings.Oracle.NeoRpcNodes; this._neoAPI = new Neo.Core.RemoteRPCNode(neoScanURL, neoRpcList.ToArray()); this._neoAPI.SetLogger((s) => Logger.Message(s)); var ethRpcList = Settings.Oracle.EthRpcNodes; var ethWIF = Settings.GetInteropWif(Nexus, _nodeKeys, EthereumWallet.EthereumPlatform); var ethKeys = PhantasmaKeys.FromWIF(ethWIF); this._ethAPI = new EthAPI(this.Nexus, this.Settings, new EthAccount(ethKeys.PrivateKey.ToHex()), Logger); this._neoScanAPI = new NeoScanAPI(neoScanURL, Logger, _nexus, _nodeKeys); this._cryptoCompareAPIKey = Settings.Oracle.CryptoCompareAPIKey; if (!string.IsNullOrEmpty(this._cryptoCompareAPIKey)) { Logger.Message($"CryptoCompare API enabled..."); } }
public static InteropTransaction MakeInteropTx(Nexus nexus, Logger logger, TransactionReceipt txr, EthAPI api, string[] swapAddresses) { logger.Debug("checking tx: " + txr.TransactionHash); IList <InteropTransfer> interopTransfers = new List <InteropTransfer>(); interopTransfers = GetInteropTransfers(nexus, logger, txr, api, swapAddresses).SelectMany(x => x.Value).ToList(); logger.Debug($"Found {interopTransfers.Count} interop transfers!"); return((interopTransfers.Count() > 0) ? new InteropTransaction(Hash.Parse(txr.TransactionHash), interopTransfers.ToArray()) : new InteropTransaction(Hash.Null, interopTransfers.ToArray())); }
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); }
public static Tuple <InteropBlock, InteropTransaction[]> MakeInteropBlock(Nexus nexus, Logger logger, EthAPI api , BigInteger height, string[] contracts, uint confirmations, string[] swapAddress) { Hash blockHash = Hash.Null; var interopTransactions = new List <InteropTransaction>(); //TODO HACK var combinedAddresses = contracts.ToList(); combinedAddresses.AddRange(swapAddress); Dictionary <string, Dictionary <string, List <InteropTransfer> > > transfers = new Dictionary <string, Dictionary <string, List <InteropTransfer> > >(); try { // TODO pass from outside to not instantiate for each call to MakeInteropBlock Func <string, Address> addressEncoder = (address) => { return(BSCWallet.EncodeAddress(address)); }; Func <Nethereum.RPC.Eth.DTOs.Transaction, Address> addressExtractor = (tx) => { return(BSCInterop.ExtractInteropAddress(tx)); }; var crawler = new EvmBlockCrawler(logger, combinedAddresses.ToArray(), confirmations, api, addressEncoder, addressExtractor, BSCWallet.BSCPlatform); // fetch blocks crawler.Fetch(height); transfers = crawler.ExtractInteropTransfers(nexus, logger, swapAddress); } catch (Exception e) { logger.Error("Failed to fetch eth blocks: " + e); } if (transfers.Count == 0) { var emptyBlock = new InteropBlock(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, Hash.Null, new Hash[] {}); return(Tuple.Create(emptyBlock, interopTransactions.ToArray())); } blockHash = Hash.Parse(transfers.FirstOrDefault().Key); foreach (var block in transfers) { var txTransferDict = block.Value; foreach (var tx in txTransferDict) { var interopTx = MakeInteropTx(logger, tx.Key, tx.Value); if (interopTx.Hash != Hash.Null) { interopTransactions.Add(interopTx); } } } var hashes = interopTransactions.Select(x => x.Hash).ToArray(); InteropBlock interopBlock = (interopTransactions.Count() > 0) ? new InteropBlock(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, blockHash, hashes) : new InteropBlock(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, Hash.Null, hashes); return(Tuple.Create(interopBlock, interopTransactions.ToArray())); }
public static Tuple <InteropBlock, InteropTransaction[]> MakeInteropBlock(Logger logger, BlockWithTransactions block, EthAPI api , string[] swapAddress) { //TODO return(null); }
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); }
public static Tuple <InteropBlock, InteropTransaction[]> MakeInteropBlock(Nexus nexus, Logger logger, EthAPI api , BigInteger height, string[] contracts, uint confirmations, string swapAddress) { Hash blockHash = Hash.Null; var interopTransactions = new List <InteropTransaction>(); //TODO HACK var combinedAddresses = contracts.ToList(); combinedAddresses.Add(swapAddress); Dictionary <string, Dictionary <string, List <InteropTransfer> > > transfers = new Dictionary <string, Dictionary <string, List <InteropTransfer> > >(); try { var crawler = new EthBlockCrawler(logger, combinedAddresses.ToArray(), confirmations, api); // fetch blocks crawler.Fetch(height); transfers = crawler.ExtractInteropTransfers(nexus, logger, swapAddress); } catch (Exception e) { logger.Error("Failed to fetch eth blocks: " + e); } if (transfers.Count == 0) { var emptyBlock = new InteropBlock(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, Hash.Null, new Hash[] {}); return(Tuple.Create(emptyBlock, interopTransactions.ToArray())); } blockHash = Hash.Parse(transfers.FirstOrDefault().Key); foreach (var block in transfers) { var txTransferDict = block.Value; foreach (var tx in txTransferDict) { var interopTx = MakeInteropTx(logger, tx.Key, tx.Value); if (interopTx.Hash != Hash.Null) { interopTransactions.Add(interopTx); } } } var hashes = interopTransactions.Select(x => x.Hash).ToArray(); InteropBlock interopBlock = (interopTransactions.Count() > 0) ? new InteropBlock(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, blockHash, hashes) : new InteropBlock(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, Hash.Null, hashes); return(Tuple.Create(interopBlock, interopTransactions.ToArray())); }
private void Init() { Hdd = DEV9Header.HDD_DEF; HddSize = 8 * 1024; Eth = DEV9Header.ETH_DEF; EthType = EthAPI.Winsock; EthEnable = true; HddEnable = false; DirectConnectionSettings = new ConfigDirectIP(); SocketConnectionSettings = new ConfigSocketIP(); }
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); }