示例#1
0
        private InteropTransaction FillTransaction(string hashText, string inputAddress, Address interopAddress)
        {
            int page     = 1;
            int maxPages = 9999;

            while (page <= maxPages)
            {
                var apiCall = $"get_address_abstracts/{inputAddress}/{page}";
                var json    = ExecuteRequest(apiCall);
                if (json == null)
                {
                    throw new OracleException("Network read failure: " + apiCall);
                }

                var root    = JSONReader.ReadFromString(json);
                var entries = root.GetNode("entries");

                for (int i = 0; i < entries.ChildCount; i++)
                {
                    var entry = entries.GetNodeByIndex(i);
                    var txId  = entry.GetString("txid");
                    if (hashText.Equals(txId, StringComparison.OrdinalIgnoreCase))
                    {
                        var inputAsset = entry.GetString("asset");
                        var symbol     = FindSymbolFromAsset(inputAsset);

                        if (symbol == null)
                        {
                            throw new OracleException("transaction contains unknown asset: " + inputAsset);
                        }

                        var inputAmount = entry.GetDecimal("amount");

                        var sourceAddress = entry.GetString("address_from");
                        var destAddress   = entry.GetString("address_to");

                        var info   = nexus.GetTokenInfo(nexus.RootStorage, symbol);
                        var amount = UnitConversion.ToBigInteger(inputAmount, info.Decimals);

                        var txHash = Hash.Parse(hashText);
                        var tx     = new InteropTransaction(txHash, new InteropTransfer[] {
                            new InteropTransfer("neo", NeoWallet.EncodeAddress(sourceAddress), "neo", NeoWallet.EncodeAddress(destAddress), interopAddress, symbol, amount)
                        });
                        return(tx);
                    }
                }

                page++;
            }

            throw new Exception("could not fill oracle transaction: " + hashText);
        }
示例#2
0
        protected override InteropTransaction PullPlatformTransaction(string platformName, string chainName, Hash hash)
        {
            logger.Debug($"{platformName} pull tx: {hash}");
            InteropTransaction tx = Read <InteropTransaction>(platformName, chainName, hash, StorageConst.Transaction);

            if (tx != null && tx.Hash != null)
            {
                logger.Debug($"Found tx {hash} in oracle storage");
                return(tx);
            }

            switch (platformName)
            {
            case NeoWallet.NeoPlatform:
                NeoTx   neoTx;
                UInt256 uHash = new UInt256(LuxUtils.ReverseHex(hash.ToString()).HexToBytes());
                neoTx = _cli.NeoAPI.GetTransaction(uHash);
                var coldStorage = _cli.Settings.Oracle.SwapColdStorageNeo;
                tx = NeoInterop.MakeInteropTx(logger, neoTx, _cli.NeoAPI,
                                              _cli.TokenSwapper.SwapAddresses[SwapPlatformChain.Neo], coldStorage);
                break;

            case EthereumWallet.EthereumPlatform:
            {
                var txRcpt = _cli.EthAPI.GetTransactionReceipt(hash.ToString());
                tx = EthereumInterop.MakeInteropTx(_cli.Nexus, logger, txRcpt, _cli.EthAPI,
                                                   _cli.TokenSwapper.SwapAddresses[SwapPlatformChain.Ethereum]);
                break;
            }

            case BSCWallet.BSCPlatform:
            {
                var txRcpt = _cli.BscAPI.GetTransactionReceipt(hash.ToString());
                tx = BSCInterop.MakeInteropTx(_cli.Nexus, logger, txRcpt, _cli.BscAPI,
                                              _cli.TokenSwapper.SwapAddresses[SwapPlatformChain.BSC]);
                break;
            }

            default:
                throw new OracleException("Uknown oracle platform: " + platformName);
            }

            if (!Persist <InteropTransaction>(platformName, chainName, tx.Hash, StorageConst.Transaction, tx))
            {
                logger.Error($"Oracle transaction { hash } on platform { platformName } updated!");
            }

            return(tx);
        }
示例#3
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()));
        }