Example #1
0
        public void DecryptNEP2()
        {
            var passphrase = "Satoshi";
            var encrypted  = "6PYN6mjwYfjPUuYT3Exajvx25UddFVLpCw4bMsmtLdnKwZ9t1Mi3CfKe8S";

            var keys = NeoKeys.FromNEP2(encrypted, passphrase);
            var wif  = keys.WIF;

            var expectedWIF = "KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7";

            Assert.IsTrue(expectedWIF == wif);
        }
Example #2
0
        public async Task <object> InvokeSettleTx(NeoKeys neoKeys, PhantasmaKeys phantasmaKeys, string txHash, string symbol)
        {
            try
            {
                Hash neoTxHash         = Hash.Parse(txHash);
                var  transcodedAddress = Address.FromKey(neoKeys);

                var script = ScriptUtils.BeginScript()
                             .CallContract("interop", "SettleTransaction", transcodedAddress, NeoWallet.NeoPlatform, NeoWallet.NeoPlatform, neoTxHash)
                             .CallContract("swap", "SwapFee", transcodedAddress, symbol, UnitConversion.ToBigInteger(0.1m, DomainSettings.FuelTokenDecimals))
                             .TransferBalance(symbol, transcodedAddress, phantasmaKeys.Address)
                             .AllowGas(transcodedAddress, Address.Null, MinimumFee, 800)
                             .SpendGas(transcodedAddress)
                             .EndScript();

                var nexusName = WalletConfig.Network;
                var tx        = new Phantasma.Blockchain.Transaction(nexusName, "main", script, DateTime.UtcNow + TimeSpan.FromMinutes(30), "PHT-0-8-7");

                tx.Sign(neoKeys);

                var txResult = await _phantasmaRpcService.SendRawTx.SendRequestAsync(tx.ToByteArray(true).Encode());

                Log.Information("txResult: " + txResult);
                return(txResult);
            }
            catch (RpcResponseException rpcEx)
            {
                Log.Error($"RPC Exception occurred: {rpcEx.RpcError.Message}");
                return(new ErrorRes {
                    error = rpcEx.RpcError.Message
                });
            }
            catch (Exception ex)
            {
                Log.Error($"Exception occurred: {ex.Message}");
                return(new ErrorRes {
                    error = ex.Message
                });
            }
        }
Example #3
0
        private static Hash NeoTransfer(NeoKeys neoKeys, string toAddress, string tokenSymbol, decimal tempAmount, NeoAPI neoAPI)
        {
            Neo.Core.Transaction neoTx;

            logger.Message($"Sending {tempAmount} {tokenSymbol} to {toAddress}...");

            Thread.Sleep(500);

            try
            {
                if (tokenSymbol == "NEO" || tokenSymbol == "GAS")
                {
                    neoTx = neoAPI.SendAsset(neoKeys, toAddress, tokenSymbol, tempAmount, out string usedRpc);
                }
                else
                {
                    var nep5 = neoAPI.GetToken(tokenSymbol);
                    if (nep5 == null)
                    {
                        throw new CommandException($"Could not find interface for NEP5: {tokenSymbol}");
                    }
                    neoTx = nep5.Transfer(neoKeys, toAddress, tempAmount);
                }

                logger.Success($"Waiting for confirmations, could take up to a minute...");
                Thread.Sleep(45000);
                logger.Success($"Sent transaction with hash {neoTx.Hash}!");

                var hash = Hash.Parse(neoTx.Hash.ToString());
                return(hash);
            }
            catch (Exception e)
            {
                logger.Message("Error sending NEO transaction: " + e);
                return(Hash.Null);
            }
        }
Example #4
0
        public InteropTransaction ReadTransaction(Hash hash)
        {
            var hashText = hash.ToString();

            var apiCall = $"get_transaction/{hashText}";
            var json    = ExecuteRequest(apiCall);

            if (json == null)
            {
                throw new OracleException("Network read failure: " + apiCall);
            }

            string inputSource = null;

            try
            {
                var root = JSONReader.ReadFromString(json);

                var scripts = root.GetNode("scripts");
                Throw.IfNull(scripts, nameof(scripts));

                if (scripts.ChildCount != 1)
                {
                    throw new OracleException("Transactions with multiple sources not supported yet");
                }

                Address interopAddress = Address.Null;
                foreach (var scriptEntry in scripts.Children)
                {
                    var vs = scriptEntry.GetNode("verification");
                    if (vs == null)
                    {
                        continue;
                    }

                    var verificationScript = Base16.Decode(vs.Value);
                    var pubKey             = new byte[33];
                    Core.Utils.ByteArrayUtils.CopyBytes(verificationScript, 1, pubKey, 0, 33);

                    var signatureScript = NeoKeys.CreateSignatureScript(pubKey);
                    var signatureHash   = Neo.Utils.CryptoUtils.ToScriptHash(signatureScript);
                    inputSource = Neo.Utils.CryptoUtils.ToAddress(signatureHash);

                    pubKey         = Core.Utils.ByteArrayUtils.ConcatBytes((byte)AddressKind.User, pubKey);
                    interopAddress = Address.FromBytes(pubKey);
                    break;
                }

                if (interopAddress.IsNull)
                {
                    throw new OracleException("Could not fetch public key from transaction");
                }

                if (string.IsNullOrEmpty(inputSource))
                {
                    throw new OracleException("Could not fetch source address from transaction");
                }

                var attrNodes = root.GetNode("attributes");
                if (attrNodes != null)
                {
                    foreach (var entry in attrNodes.Children)
                    {
                        var kind = entry.GetString("usage");
                        if (kind == "Description")
                        {
                            var data  = entry.GetString("data");
                            var bytes = Base16.Decode(data);

                            var text = Encoding.UTF8.GetString(bytes);
                            if (Address.IsValidAddress(text))
                            {
                                interopAddress = Address.FromText(text);
                            }
                        }
                    }
                }

                return(FillTransaction(hashText, inputSource, interopAddress));
            }
            catch (Exception e)
            {
                throw new OracleException(e.Message);
            }
        }
Example #5
0
        // NOTE no locks happen here because this callback is called from within a lock
        internal override Hash SettleSwap(Hash sourceHash, Address destination, IToken token, Numerics.BigInteger amount)
        {
            Hash   txHash = Hash.Null;
            string txStr  = null;

            var inProgressMap = new StorageMap(TokenSwapper.InProgressTag, Swapper.Storage);
            var rpcMap        = new StorageMap(TokenSwapper.UsedRpcTag, Swapper.Storage);

            if (inProgressMap.ContainsKey <Hash>(sourceHash))
            {
                txStr = inProgressMap.Get <Hash, string>(sourceHash);

                if (!string.IsNullOrEmpty(txStr))
                {
                    return(VerifyNeoTx(sourceHash, txStr));
                }
            }

            var total = Numerics.UnitConversion.ToDecimal(amount, token.Decimals);

            var neoKeys = NeoKeys.FromWIF(this.WIF);

            var destAddress = NeoWallet.DecodeAddress(destination);

            Logger.Debug($"NEOSWAP: Trying transfer of {total} {token.Symbol} from {neoKeys.Address} to {destAddress}");

            var nonce = sourceHash.ToByteArray();

            Neo.Core.Transaction tx = null;
            string usedRpc          = null;

            try
            {
                if (token.Symbol == "NEO" || token.Symbol == "GAS")
                {
                    tx = neoAPI.SendAsset(neoKeys, destAddress, token.Symbol, total, out usedRpc);
                }
                else
                {
                    var nep5 = neoAPI.GetToken(token.Symbol);
                    tx = nep5.Transfer(neoKeys, destAddress, total, nonce, x => usedRpc = x);
                }

                // persist resulting tx hash as in progress
                inProgressMap.Set <Hash, string>(sourceHash, tx.Hash.ToString());
                rpcMap.Set <Hash, string>(sourceHash, usedRpc);

                Logger.Debug("broadcasted neo tx: " + tx);
            }
            catch (Exception e)
            {
                Logger.Error("Error during transfering {token.Symbol}: " + e);
                return(Hash.Null);
            }

            if (tx == null)
            {
                Logger.Error($"NeoAPI error {neoAPI.LastError} or possible failed neo swap sourceHash: {sourceHash} no transfer happend.");
                return(Hash.Null);
            }

            var strHash = tx.Hash.ToString();

            return(VerifyNeoTx(sourceHash, strHash));
        }
Example #6
0
        public static void Transfer(SpookSettings settings, NexusAPI api, BigInteger minimumFee, NeoAPI neoAPI, string[] args)
        {
            if (args.Length != 4)
            {
                throw new CommandException("Expected args: source_address target_address amount symbol");
            }

            DoChecks(api);

            var tempAmount  = decimal.Parse(args[2]);
            var tokenSymbol = args[3];


            var tokenInfo = FetchTokenInfo(api, tokenSymbol);

            if (!tokenInfo.flags.Contains("Fungible"))
            {
                throw new CommandException("Token must be fungible!");
            }

            var amount = UnitConversion.ToBigInteger(tempAmount, tokenInfo.decimals);

            var    sourceName = args[0];
            string sourcePlatform;

            if (Address.IsValidAddress(sourceName))
            {
                sourcePlatform = PhantasmaWallet.PhantasmaPlatform;
            }
            else
            if (NeoWallet.IsValidAddress(sourceName))
            {
                sourcePlatform = NeoWallet.NeoPlatform;
            }
            else
            {
                throw new CommandException("Invalid source address " + sourceName);
            }

            var    destName = args[1];
            string destPlatform;

            if (Address.IsValidAddress(destName))
            {
                destPlatform = PhantasmaWallet.PhantasmaPlatform;
            }
            else
            if (NeoWallet.IsValidAddress(destName))
            {
                destPlatform = NeoWallet.NeoPlatform;
            }
            else
            {
                throw new CommandException("Invalid destination address " + destName);
            }

            if (destName == sourceName)
            {
                throw new CommandException("Cannot transfer to same address");
            }

            if (sourcePlatform != PhantasmaWallet.PhantasmaPlatform)
            {
                if (destPlatform != PhantasmaWallet.PhantasmaPlatform)
                {
                    if (sourcePlatform != destPlatform)
                    {
                        throw new CommandException($"Cannot transfer directly from {sourcePlatform} to {destPlatform}");
                    }
                    else
                    {
                        switch (destPlatform)
                        {
                        case NeoWallet.NeoPlatform:
                        {
                            var neoKeys = new NeoKeys(Keys.PrivateKey);

                            if (sourceName != neoKeys.Address)
                            {
                                throw new CommandException("The current open wallet does not have keys that match address " + sourceName);
                            }

                            var neoHash = NeoTransfer(neoKeys, destName, tokenSymbol, tempAmount, neoAPI);
                            return;
                        }

                        default:
                            throw new CommandException($"Not implemented yet :(");
                        }
                    }
                }
                else
                {
                    logger.Message($"Source is {sourcePlatform} address, a swap will be performed using an interop address.");

                    IPlatform platformInfo = api.Nexus.GetPlatformInfo(api.Nexus.RootStorage, sourcePlatform);

                    Hash     extHash;
                    IKeyPair extKeys;

                    switch (sourcePlatform)
                    {
                    case NeoWallet.NeoPlatform:
                    {
                        try
                        {
                            var neoKeys = new NeoKeys(Keys.PrivateKey);

                            if (sourceName != neoKeys.Address)
                            {
                                throw new CommandException("The current open wallet does not have keys that match address " + sourceName);
                            }

                            extHash = NeoTransfer(neoKeys, platformInfo.InteropAddresses[0].ExternalAddress, tokenSymbol, tempAmount, neoAPI);

                            if (extHash == Hash.Null)
                            {
                                return;
                            }

                            extKeys = neoKeys;
                        }
                        catch (Exception e)
                        {
                            logger.Message($"{sourcePlatform} error: " + e.Message);
                            return;
                        }

                        break;
                    }

                    default:
                        logger.Message($"Transactions using platform {sourcePlatform} are not supported yet");
                        return;
                    }

                    var destAddress = Address.FromText(destName);
                    SettleSwap(settings, api, minimumFee, sourcePlatform, tokenSymbol, extHash, extKeys, destAddress);
                }
                return;
            }
            else
            {
                Address destAddress;

                if (destPlatform != PhantasmaWallet.PhantasmaPlatform)
                {
                    switch (destPlatform)
                    {
                    case NeoWallet.NeoPlatform:
                        destAddress = NeoWallet.EncodeAddress(destName);
                        break;

                    default:
                        logger.Message($"Transactions to platform {destPlatform} are not supported yet");
                        return;
                    }

                    logger.Message($"Target is {destPlatform} address, a swap will be performed through interop address {destAddress}.");
                }
                else
                {
                    destAddress = Address.FromText(destName);
                }

                var script = ScriptUtils.BeginScript().
                             CallContract("swap", "SwapFee", Keys.Address, tokenSymbol, UnitConversion.ToBigInteger(0.01m, DomainSettings.FuelTokenDecimals)).
                             AllowGas(Keys.Address, Address.Null, minimumFee, 9999).
                             TransferTokens(tokenSymbol, Keys.Address, destAddress, amount).
                             SpendGas(Keys.Address).
                             EndScript();

                logger.Message($"Sending {tempAmount} {tokenSymbol} to {destAddress.Text}...");
                ExecuteTransaction(settings, api, script, ProofOfWork.None, Keys);
            }
        }