예제 #1
0
        /// <summary>
        /// Make and send transaction with script, sender
        /// </summary>
        /// <param name="script">script</param>
        /// <param name="account">sender</param>
        /// <param name="gas">Max fee for running the script</param>
        private void SendTransaction(byte[] script, UInt160 account = null, long gas = TestModeGas)
        {
            Signer[] signers  = System.Array.Empty <Signer>();
            var      snapshot = NeoSystem.StoreView;

            if (account != null)
            {
                signers = CurrentWallet.GetAccounts()
                          .Where(p => !p.Lock && !p.WatchOnly && p.ScriptHash == account && NativeContract.GAS.BalanceOf(snapshot, p.ScriptHash).Sign > 0)
                          .Select(p => new Signer()
                {
                    Account = p.ScriptHash, Scopes = WitnessScope.CalledByEntry
                })
                          .ToArray();
            }

            try
            {
                Transaction tx = CurrentWallet.MakeTransaction(snapshot, script, account, signers, maxGas: gas);
                ConsoleHelper.Info("Invoking script with: ", $"'{tx.Script.ToBase64String()}'");

                using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, snapshot, container: tx, settings: NeoSystem.Settings, gas: gas))
                {
                    PrintExecutionOutput(engine, true);
                    if (engine.State == VMState.FAULT)
                    {
                        return;
                    }
                }

                if (!ReadUserInput("Relay tx(no|yes)").IsYes())
                {
                    return;
                }

                SignAndSendTx(NeoSystem.StoreView, tx);
            }
            catch (InvalidOperationException e)
            {
                ConsoleHelper.Error(GetExceptionMessage(e));
                return;
            }

            return;
        }
예제 #2
0
        private void OnExportKeyCommand(string path = null, UInt160 scriptHash = null)
        {
            if (NoWallet())
            {
                return;
            }
            if (path != null && File.Exists(path))
            {
                Console.WriteLine($"Error: File '{path}' already exists");
                return;
            }
            string password = ReadUserInput("password", true);

            if (password.Length == 0)
            {
                Console.WriteLine("cancelled");
                return;
            }
            if (!CurrentWallet.VerifyPassword(password))
            {
                Console.WriteLine("Incorrect password");
                return;
            }
            IEnumerable <KeyPair> keys;

            if (scriptHash == null)
            {
                keys = CurrentWallet.GetAccounts().Where(p => p.HasKey).Select(p => p.GetKey());
            }
            else
            {
                keys = new[] { CurrentWallet.GetAccount(scriptHash).GetKey() }
            };
            if (path == null)
            {
                foreach (KeyPair key in keys)
                {
                    Console.WriteLine(key.Export());
                }
            }
            else
            {
                File.WriteAllLines(path, keys.Select(p => p.Export()));
            }
        }
예제 #3
0
        /// <summary>
        /// show unclaimed gas amount
        /// </summary>
        /// <returns></returns>
        public async Task <object> ShowGas()
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            BigInteger gas      = BigInteger.Zero;
            var        snapshot = Helpers.GetDefaultSnapshot();

            foreach (UInt160 account in CurrentWallet.GetAccounts().Where(a => !a.WatchOnly).Select(p => p.ScriptHash))
            {
                gas += NativeContract.NEO.UnclaimedGas(snapshot, account, snapshot.GetHeight() + 1);
            }
            return(new UnclaimedGasModel()
            {
                UnclaimedGas = new BigDecimal(gas, NativeContract.GAS.Decimals)
            });
        }
예제 #4
0
        private void OnShowGasCommand()
        {
            if (NoWallet())
            {
                return;
            }
            BigInteger gas = BigInteger.Zero;

            using (var snapshot = Blockchain.Singleton.GetSnapshot())
            {
                uint height = NativeContract.Ledger.CurrentIndex(snapshot) + 1;
                foreach (UInt160 account in CurrentWallet.GetAccounts().Select(p => p.ScriptHash))
                {
                    gas += NativeContract.NEO.UnclaimedGas(snapshot, account, height);
                }
            }
            Console.WriteLine($"Unclaimed gas: {new BigDecimal(gas, NativeContract.GAS.Decimals)}");
        }
예제 #5
0
 private void OnListAssetCommand()
 {
     if (NoWallet())
     {
         return;
     }
     foreach (UInt160 account in CurrentWallet.GetAccounts().Select(p => p.ScriptHash))
     {
         Console.WriteLine(account.ToAddress());
         Console.WriteLine($"NEO: {CurrentWallet.GetBalance(NativeContract.NEO.Hash, account)}");
         Console.WriteLine($"GAS: {CurrentWallet.GetBalance(NativeContract.GAS.Hash, account)}");
         Console.WriteLine();
     }
     Console.WriteLine("----------------------------------------------------");
     Console.WriteLine("Total:   " + "NEO: " + CurrentWallet.GetAvailable(NativeContract.NEO.Hash) + "    GAS: " + CurrentWallet.GetAvailable(NativeContract.GAS.Hash));
     Console.WriteLine();
     Console.WriteLine("NEO hash: " + NativeContract.NEO.Hash);
     Console.WriteLine("GAS hash: " + NativeContract.GAS.Hash);
 }
예제 #6
0
        private void OnListAssetCommand()
        {
            var snapshot = NeoSystem.StoreView;

            if (NoWallet())
            {
                return;
            }
            foreach (UInt160 account in CurrentWallet.GetAccounts().Select(p => p.ScriptHash))
            {
                Console.WriteLine(account.ToAddress(NeoSystem.Settings.AddressVersion));
                ConsoleHelper.Info("NEO: ", $"{CurrentWallet.GetBalance(snapshot, NativeContract.NEO.Hash, account)}");
                ConsoleHelper.Info("GAS: ", $"{CurrentWallet.GetBalance(snapshot, NativeContract.GAS.Hash, account)}");
                Console.WriteLine();
            }
            Console.WriteLine("----------------------------------------------------");
            ConsoleHelper.Info("Total:   NEO: ", $"{CurrentWallet.GetAvailable(snapshot, NativeContract.NEO.Hash),10}     ", "GAS: ", $"{CurrentWallet.GetAvailable(snapshot, NativeContract.GAS.Hash),18}");
            Console.WriteLine();
            ConsoleHelper.Info("NEO hash: ", NativeContract.NEO.Hash.ToString());
            ConsoleHelper.Info("GAS hash: ", NativeContract.GAS.Hash.ToString());
        }
예제 #7
0
        private bool OnListAssetCommand(string[] args)
        {
            if (NoWallet())
            {
                return(true);
            }
            var snapshot = NeoSystem.StoreView;

            foreach (UInt160 account in CurrentWallet.GetAccounts().Select(p => p.ScriptHash))
            {
                Console.WriteLine(account.ToAddress(NeoSystem.Settings.AddressVersion));
                Console.WriteLine($"NEO: {CurrentWallet.GetBalance(snapshot, NativeContract.NEO.Hash, account)}");
                Console.WriteLine($"GAS: {CurrentWallet.GetBalance(snapshot, NativeContract.GAS.Hash, account)}");
                Console.WriteLine();
            }
            Console.WriteLine("----------------------------------------------------");
            Console.WriteLine($"Total:   NEO: {CurrentWallet.GetAvailable(snapshot, NativeContract.NEO.Hash),10}     GAS: {CurrentWallet.GetAvailable(snapshot, NativeContract.GAS.Hash),18}");
            Console.WriteLine();
            Console.WriteLine("NEO hash: " + NativeContract.NEO.Hash);
            Console.WriteLine("GAS hash: " + NativeContract.GAS.Hash);
            return(true);
        }
예제 #8
0
        private bool OnImportMultisigAddress(string[] args)
        {
            if (NoWallet())
            {
                return(true);
            }

            if (args.Length < 4)
            {
                Console.WriteLine("Error. Invalid parameters.");
                return(true);
            }

            int m = int.Parse(args[2]);
            int n = args.Length - 3;

            if (m < 1 || m > n || n > 1024)
            {
                Console.WriteLine("Error. Invalid parameters.");
                return(true);
            }

            ECPoint[] publicKeys = args.Skip(3).Select(p => ECPoint.Parse(p, ECCurve.Secp256r1)).ToArray();

            Contract multiSignContract = Contract.CreateMultiSigContract(m, publicKeys);
            KeyPair  keyPair           = CurrentWallet.GetAccounts().FirstOrDefault(p => p.HasKey && publicKeys.Contains(p.GetKey().PublicKey))?.GetKey();

            WalletAccount account = CurrentWallet.CreateAccount(multiSignContract, keyPair);

            if (CurrentWallet is NEP6Wallet wallet)
            {
                wallet.Save();
            }

            Console.WriteLine("Multisig. Addr.: " + multiSignContract.ScriptHash.ToAddress());

            return(true);
        }
예제 #9
0
        private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] signerAccounts = null)
        {
            Signer[] signers = Array.Empty <Signer>();
            if (signerAccounts != null && !NoWallet())
            {
                signers = CurrentWallet.GetAccounts().Where(p => !p.Lock && !p.WatchOnly && signerAccounts.Contains(p.ScriptHash)).Select(p => new Signer()
                {
                    Account = p.ScriptHash, Scopes = WitnessScope.CalledByEntry
                }).ToArray();
            }

            Transaction tx = new Transaction
            {
                Signers   = signers,
                Witnesses = Array.Empty <Witness>(),
            };

            _ = OnInvokeWithResult(scriptHash, operation, tx, contractParameters);

            if (NoWallet())
            {
                return;
            }
            try
            {
                tx = CurrentWallet.MakeTransaction(tx.Script, signers.Length > 0 ? signers[0].Account : null, signers);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Error: insufficient balance.");
                return;
            }
            if (!ReadUserInput("Relay tx(no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(tx);
        }
예제 #10
0
        /// <summary>
        /// create new multi address
        /// </summary>
        /// <returns></returns>
        public async Task <object> CreateMultiAddress(int limit, string[] publicKeys)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }

            ECPoint[] points = null;
            try
            {
                points = publicKeys.Select(p => ECPoint.DecodePoint(Helper.HexToBytes(p), ECCurve.Secp256r1)).ToArray();
            }
            catch (FormatException ex)
            {
                return(Error(ErrorCode.InvalidPara, ex.Message));
            }
            Contract contract = Contract.CreateMultiSigContract(limit, points);

            if (contract == null)
            {
                return(Error(ErrorCode.CreateMultiContractFail));
            }
            var hashSet    = new HashSet <ECPoint>(points);
            var key        = CurrentWallet.GetAccounts().FirstOrDefault(p => p.HasKey && hashSet.Contains(p.GetKey().PublicKey))?.GetKey();
            var newAccount = CurrentWallet.CreateAccount(contract, key);

            if (CurrentWallet is NEP6Wallet wallet)
            {
                wallet.Save();
            }
            return(new AccountModel()
            {
                AccountType = AccountType.MultiSignature,
                Address = newAccount.Address,
                ScriptHash = newAccount.ScriptHash,
            });
        }
예제 #11
0
        private bool OnListAddressCommand(string[] args)
        {
            if (NoWallet())
            {
                return(true);
            }

            var snapshot = NeoSystem.StoreView;

            foreach (var account in CurrentWallet.GetAccounts())
            {
                var contract = account.Contract;
                var type     = "Nonstandard";

                if (account.WatchOnly)
                {
                    type = "WatchOnly";
                }
                else if (contract.Script.IsMultiSigContract())
                {
                    type = "MultiSignature";
                }
                else if (contract.Script.IsSignatureContract())
                {
                    type = "Standard";
                }
                else if (NativeContract.ContractManagement.GetContract(snapshot, account.ScriptHash) != null)
                {
                    type = "Deployed-Nonstandard";
                }

                Console.WriteLine($"{"   Address: "}{account.Address}\t{type}");
                Console.WriteLine($"{"ScriptHash: "}{account.ScriptHash}\n");
            }

            return(true);
        }
예제 #12
0
        private void OnListAddressCommand()
        {
            if (NoWallet())
            {
                return;
            }

            using (var snapshot = Blockchain.Singleton.GetSnapshot())
            {
                foreach (var account in CurrentWallet.GetAccounts())
                {
                    var contract = account.Contract;
                    var type     = "Nonstandard";

                    if (account.WatchOnly)
                    {
                        type = "WatchOnly";
                    }
                    else if (contract.Script.IsMultiSigContract())
                    {
                        type = "MultiSignature";
                    }
                    else if (contract.Script.IsSignatureContract())
                    {
                        type = "Standard";
                    }
                    else if (snapshot.Contracts.TryGet(account.ScriptHash) != null)
                    {
                        type = "Deployed-Nonstandard";
                    }

                    Console.WriteLine($"{"   Address: "}{account.Address}\t{type}");
                    Console.WriteLine($"{"ScriptHash: "}{account.ScriptHash}\n");
                }
            }
        }
예제 #13
0
        private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null)
        {
            List <ContractParameter> parameters     = new List <ContractParameter>();
            List <Cosigner>          signCollection = new List <Cosigner>();

            if (!NoWallet() && witnessAddress != null)
            {
                using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot())
                {
                    UInt160[] accounts = CurrentWallet.GetAccounts().Where(p => !p.Lock && !p.WatchOnly).Select(p => p.ScriptHash).Where(p => NativeContract.GAS.BalanceOf(snapshot, p).Sign > 0).ToArray();
                    foreach (var signAccount in accounts)
                    {
                        if (witnessAddress is null)
                        {
                            break;
                        }
                        foreach (var witness in witnessAddress)
                        {
                            if (witness.Equals(signAccount))
                            {
                                signCollection.Add(new Cosigner()
                                {
                                    Account = signAccount
                                });
                                break;
                            }
                        }
                    }
                }
            }

            if (contractParameters != null)
            {
                foreach (var contractParameter in contractParameters)
                {
                    parameters.Add(ContractParameter.FromJson(contractParameter));
                }
            }

            Transaction tx = new Transaction
            {
                Sender     = UInt160.Zero,
                Attributes = Array.Empty <TransactionAttribute>(),
                Witnesses  = Array.Empty <Witness>(),
                Cosigners  = signCollection.ToArray()
            };

            using (ScriptBuilder scriptBuilder = new ScriptBuilder())
            {
                scriptBuilder.EmitAppCall(scriptHash, operation, parameters.ToArray());
                tx.Script = scriptBuilder.ToArray();
                Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'");
            }

            using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx, testMode: true))
            {
                Console.WriteLine($"VM State: {engine.State}");
                Console.WriteLine($"Gas Consumed: {new BigDecimal(engine.GasConsumed, NativeContract.GAS.Decimals)}");
                Console.WriteLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToParameter().ToJson()))}");
                Console.WriteLine();
                if (engine.State.HasFlag(VMState.FAULT))
                {
                    Console.WriteLine("Engine faulted.");
                    return;
                }
            }

            if (NoWallet())
            {
                return;
            }
            try
            {
                tx = CurrentWallet.MakeTransaction(tx.Script, null, tx.Attributes, tx.Cosigners);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Error: insufficient balance.");
                return;
            }
            if (!ReadUserInput("relay tx(no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(tx);
        }
예제 #14
0
        private bool OnExportKeyCommand(string[] args)
        {
            if (NoWallet())
            {
                return(true);
            }
            if (args.Length < 2 || args.Length > 4)
            {
                Console.WriteLine("error");
                return(true);
            }
            UInt160 scriptHash = null;
            string  path       = null;

            if (args.Length == 3)
            {
                try
                {
                    scriptHash = args[2].ToScriptHash();
                }
                catch (FormatException)
                {
                    path = args[2];
                }
            }
            else if (args.Length == 4)
            {
                scriptHash = args[2].ToScriptHash();
                path       = args[3];
            }
            if (File.Exists(path))
            {
                Console.WriteLine($"Error: File '{path}' already exists");
                return(true);
            }
            string password = ReadUserInput("password", true);

            if (password.Length == 0)
            {
                Console.WriteLine("cancelled");
                return(true);
            }
            if (!CurrentWallet.VerifyPassword(password))
            {
                Console.WriteLine("Incorrect password");
                return(true);
            }
            IEnumerable <KeyPair> keys;

            if (scriptHash == null)
            {
                keys = CurrentWallet.GetAccounts().Where(p => p.HasKey).Select(p => p.GetKey());
            }
            else
            {
                keys = new[] { CurrentWallet.GetAccount(scriptHash).GetKey() }
            };
            if (path == null)
            {
                foreach (KeyPair key in keys)
                {
                    Console.WriteLine(key.Export());
                }
            }
            else
            {
                File.WriteAllLines(path, keys.Select(p => p.Export()));
            }
            return(true);
        }