private void OnDeployCommand(string filePath, string manifestPath = null, JObject data = null)
        {
            if (NoWallet())
            {
                return;
            }
            byte[]      script = LoadDeploymentScript(filePath, manifestPath, data, out var nef, out var manifest);
            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, script);
            }
            catch (InvalidOperationException e)
            {
                ConsoleHelper.Error(GetExceptionMessage(e));
                return;
            }
            UInt160 hash = SmartContract.Helper.GetContractHash(tx.Sender, nef.CheckSum, manifest.Name);

            ConsoleHelper.Info("Contract hash: ", $"{hash}");
            ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)}");
            ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}");
            ConsoleHelper.Info("Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS");
            if (!ReadUserInput("Relay tx? (no|yes)").IsYes()) // Add this in case just want to get hash but not relay
            {
                return;
            }
            SignAndSendTx(NeoSystem.StoreView, tx);
        }
Esempio n. 2
0
        private void OnDeployCommand(string filePath, string manifestPath = null)
        {
            if (NoWallet())
            {
                return;
            }
            byte[] script = LoadDeploymentScript(filePath, manifestPath, out var nef, out var manifest);

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, script);
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Error: " + GetExceptionMessage(e));
                return;
            }

            UInt160 hash = SmartContract.Helper.GetContractHash(tx.Sender, nef.CheckSum, manifest.Name);

            Console.WriteLine($"Contract hash: {hash}");
            Console.WriteLine($"Gas: {new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)}");
            Console.WriteLine();
            SignAndSendTx(NeoSystem.StoreView, tx);
        }
Esempio n. 3
0
        private void OnSendCommand(UInt160 asset, UInt160 to, string amount)
        {
            if (NoWallet())
            {
                return;
            }
            string password = ReadUserInput("password", true);

            if (password.Length == 0)
            {
                Console.WriteLine("Cancelled");
                return;
            }
            if (!CurrentWallet.VerifyPassword(password))
            {
                Console.WriteLine("Incorrect password");
                return;
            }

            Transaction     tx;
            AssetDescriptor descriptor = new AssetDescriptor(asset);

            if (!BigDecimal.TryParse(amount, descriptor.Decimals, out BigDecimal decimalAmount) || decimalAmount.Sign <= 0)
            {
                Console.WriteLine("Incorrect Amount Format");
                return;
            }
            tx = CurrentWallet.MakeTransaction(new[]
            {
                new TransferOutput
                {
                    AssetId    = asset,
                    Value      = decimalAmount,
                    ScriptHash = to
                }
            });

            if (tx == null)
            {
                Console.WriteLine("Insufficient funds");
                return;
            }

            ContractParametersContext context = new ContractParametersContext(tx);

            CurrentWallet.Sign(context);
            if (context.Completed)
            {
                tx.Witnesses = context.GetWitnesses();
                NeoSystem.LocalNode.Tell(new LocalNode.Relay {
                    Inventory = tx
                });
                Console.WriteLine($"TXID: {tx.Hash}");
            }
            else
            {
                Console.WriteLine("SignatureContext:");
                Console.WriteLine(context.ToString());
            }
        }
Esempio n. 4
0
        private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount)
        {
            var asset = new AssetDescriptor(tokenHash);
            var value = BigDecimal.Parse(amount.ToString(CultureInfo.InvariantCulture), asset.Decimals);

            if (NoWallet())
            {
                return;
            }

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(new[]
                {
                    new TransferOutput
                    {
                        AssetId    = tokenHash,
                        Value      = value,
                        ScriptHash = to
                    }
                }, from: null);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Error: insufficient balance.");
                return;
            }
            if (!ReadUserInput("Relay tx(no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(tx);
        }
        private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null)
        {
            List <Cosigner> signCollection = new List <Cosigner>();

            if (witnessAddress != null && !NoWallet())
            {
                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;
                            }
                        }
                    }
                }
            }

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

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

            if (NoWallet())
            {
                return;
            }
            try
            {
                tx = CurrentWallet.MakeTransaction(tx.Script, null, tx.Attributes);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Error: insufficient balance.");
                return;
            }
            if (!ReadUserInput("Relay tx(no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(tx);
        }
Esempio n. 6
0
        private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160 sender = null, UInt160[] signerAccounts = null, decimal maxGas = 20)
        {
            var gas = new BigDecimal(maxGas, NativeContract.GAS.Decimals);

            Signer[] signers = Array.Empty <Signer>();
            if (signerAccounts != null && !NoWallet())
            {
                if (sender != null)
                {
                    if (signerAccounts.Contains(sender) && signerAccounts[0] != sender)
                    {
                        var signersList = signerAccounts.ToList();
                        signersList.Remove(sender);
                        signerAccounts = signersList.Prepend(sender).ToArray();
                    }
                    else if (!signerAccounts.Contains(sender))
                    {
                        signerAccounts = signerAccounts.Prepend(sender).ToArray();
                    }
                }
                signers = signerAccounts.Select(p => new Signer()
                {
                    Account = p, Scopes = WitnessScope.CalledByEntry
                }).ToArray();
            }

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

            if (!OnInvokeWithResult(scriptHash, operation, out _, tx, contractParameters, gas: (long)gas.Value))
            {
                return;
            }

            if (NoWallet())
            {
                return;
            }
            try
            {
                tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, tx.Script, sender, signers, maxGas: (long)gas.Value);
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Error: " + GetExceptionMessage(e));
                return;
            }
            if (!ReadUserInput("Relay tx(no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(NeoSystem.StoreView, tx);
        }
Esempio n. 7
0
        /// <summary>
        /// Make and send transaction with script, sender
        /// </summary>
        /// <param name="script">script</param>
        /// <param name="account">sender</param>
        private void SendTransaction(byte[] script, UInt160 account = null)
        {
            List <Cosigner> signCollection = new List <Cosigner>();

            if (account != 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 (account.Equals(signAccount))
                        {
                            signCollection.Add(new Cosigner()
                            {
                                Account = signAccount
                            });
                            break;
                        }
                    }
                }
            }

            try
            {
                Transaction tx = CurrentWallet.MakeTransaction(script, account, signCollection?.ToArray());
                Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'");

                using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx, null, 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 (!ReadUserInput("relay tx(no|yes)").IsYes())
                {
                    return;
                }

                SignAndSendTx(tx);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Error: insufficient balance.");
                return;
            }

            return;
        }
Esempio n. 8
0
        /// <summary>
        /// Make and send transaction with script, sender
        /// </summary>
        /// <param name="script">script</param>
        /// <param name="account">sender</param>
        private void SendTransaction(byte[] script, UInt160 account = null)
        {
            Signer[] signers = System.Array.Empty <Signer>();

            if (account != null)
            {
                using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot())
                {
                    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(script, account, signers);
                Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'");

                using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx, null, 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.ToJson()))}");
                    Console.WriteLine();
                    if (engine.State.HasFlag(VMState.FAULT))
                    {
                        Console.WriteLine("Error: " + GetExceptionMessage(engine.FaultException));
                        return;
                    }
                }

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

                SignAndSendTx(tx);
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Error: " + GetExceptionMessage(e));
                return;
            }

            return;
        }
Esempio n. 9
0
        /// <summary>
        /// Make and send transaction with script, sender
        /// </summary>
        /// <param name="script">script</param>
        /// <param name="account">sender</param>
        private void SendTransaction(byte[] script, UInt160 account = null)
        {
            Signer[] signers = System.Array.Empty <Signer>();

            if (account != null)
            {
                using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot())
                {
                    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(script, account, signers);
                Console.WriteLine($"Invoking script with: '{tx.Script.ToBase64String()}'");

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

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

                SignAndSendTx(tx);
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Error: " + GetExceptionMessage(e));
                return;
            }

            return;
        }
Esempio n. 10
0
        /// <summary>
        /// show private key
        /// </summary>
        /// <returns></returns>
        public async Task <object> ClaimGas()
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            var addresses = CurrentWallet.GetAccounts().Where(a => !a.Lock && !a.WatchOnly && a.Contract.Script.IsSignatureContract()).Select(a => a.ScriptHash).ToList();

            var balances = addresses.GetBalanceOf(NativeContract.NEO.Hash);

            balances = balances.Where(b => b.Value > 0).ToList();
            if (balances.IsEmpty())
            {
                return(Error(ErrorCode.NoNeedClaimGas));
            }
            var outputs = balances.Select((t, index) => new TransferOutput()
            {
                AssetId    = NativeContract.NEO.Hash,
                Value      = t,
                ScriptHash = addresses[index],
            }).ToArray();

            try
            {
                Transaction tx = CurrentWallet.MakeTransaction(Helpers.GetDefaultSnapshot(), outputs);
                if (tx == null)
                {
                    return(Error(ErrorCode.ClaimGasFail));
                }
                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                return(new TransactionModel(tx));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                return(Error(ErrorCode.ClaimGasFail, ex.Message));
            }
        }
Esempio n. 11
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;
        }
Esempio n. 12
0
        private Transaction MakeTransaction(List <TransferRequestModel> transfers)
        {
            var lookup = transfers.ToLookup(t => new
            {
                t.Sender,
                t.Asset
            });

            using var sb = new ScriptBuilder();
            var snapshot = Helpers.GetDefaultSnapshot();

            foreach (var transferRequests in lookup)
            {
                var        sender    = transferRequests.Key.Sender;
                var        assetHash = transferRequests.Key.Asset;
                BigInteger amount    = 0;
                transferRequests.ForEach(t => amount += t.Amount.Value);
                Console.WriteLine($"Transfer[{transferRequests.Key.Asset}]:{transferRequests.Key.Sender}=>{amount}");
                var balance = sender.GetBalanceOf(assetHash, snapshot).Value;
                if (balance < amount)
                {
                    //balance not enough
                    return(null);
                }
                foreach (var transfer in transferRequests)
                {
                    sb.EmitDynamicCall(assetHash, "transfer", sender, transfer.Receiver, transfer.Amount.Value, null);
                    sb.Emit(OpCode.ASSERT);
                }
            }

            var script    = sb.ToArray();
            var senders   = transfers.Select(t => t.Sender).ToHashSet();
            var cosigners = senders.Select(p =>
                                           new Signer()
            {
                // default access for transfers should be valid only for first invocation
                Scopes  = WitnessScope.CalledByEntry,
                Account = p
            }).ToArray();

            return(CurrentWallet.MakeTransaction(snapshot, script, null, cosigners, new TransactionAttribute[0]));
        }
Esempio n. 13
0
        private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount, UInt160 from = null, string data = null, UInt160[] signersAccounts = null)
        {
            var snapshot = NeoSystem.StoreView;
            var asset    = new AssetDescriptor(snapshot, NeoSystem.Settings, tokenHash);
            var value    = new BigDecimal(amount, asset.Decimals);

            if (NoWallet())
            {
                return;
            }

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(snapshot, new[]
                {
                    new TransferOutput
                    {
                        AssetId    = tokenHash,
                        Value      = value,
                        ScriptHash = to,
                        Data       = data
                    }
                }, from: from, cosigners: signersAccounts?.Select(p => new Signer
                {
                    // default access for transfers should be valid only for first invocation
                    Scopes  = WitnessScope.CalledByEntry,
                    Account = p
                })
                                                   .ToArray() ?? Array.Empty <Signer>());
            }
            catch (InvalidOperationException e)
            {
                ConsoleHelper.Error(GetExceptionMessage(e));
                return;
            }
            if (!ReadUserInput("Relay tx(no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(snapshot, tx);
        }
Esempio n. 14
0
        private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount, string data = null, UInt160 from = null, UInt160[] signersAccounts = null)
        {
            var asset = new AssetDescriptor(tokenHash);
            var value = BigDecimal.Parse(amount.ToString(CultureInfo.InvariantCulture), asset.Decimals);

            if (NoWallet())
            {
                return;
            }

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(new[]
                {
                    new TransferOutput
                    {
                        AssetId    = tokenHash,
                        Value      = value,
                        ScriptHash = to,
                        Data       = data
                    }
                }, from: from, cosigners: signersAccounts?.Select(p => new Signer
                {
                    // default access for transfers should be valid only for first invocation
                    Scopes  = WitnessScope.CalledByEntry,
                    Account = p
                })
                                                   .ToArray() ?? new Signer[0]);
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Error: " + GetExceptionMessage(e));
                return;
            }
            if (!ReadUserInput("Relay tx(no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(tx);
        }
Esempio n. 15
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);
        }
Esempio n. 16
0
        private void OnDeployCommand(string filePath, string manifestPath = null)
        {
            if (NoWallet())
            {
                return;
            }
            byte[] script = LoadDeploymentScript(filePath, manifestPath, out var scriptHash);

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(script);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Engine faulted.");
                return;
            }
            Console.WriteLine($"Script hash: {scriptHash.ToString()}");
            Console.WriteLine($"Gas: {new BigDecimal(tx.SystemFee, NativeContract.GAS.Decimals)}");
            Console.WriteLine();
            SignAndSendTx(tx);
        }
Esempio n. 17
0
        private void OnSendCommand(UInt160 asset, UInt160 to, string amount, UInt160 from = null, string data = null, UInt160[] signerAccounts = null)
        {
            if (NoWallet())
            {
                return;
            }
            string password = ReadUserInput("password", true);

            if (password.Length == 0)
            {
                ConsoleHelper.Info("Cancelled");
                return;
            }
            if (!CurrentWallet.VerifyPassword(password))
            {
                ConsoleHelper.Error("Incorrect password");
                return;
            }
            var             snapshot = NeoSystem.StoreView;
            Transaction     tx;
            AssetDescriptor descriptor = new(snapshot, NeoSystem.Settings, asset);

            if (!BigDecimal.TryParse(amount, descriptor.Decimals, out BigDecimal decimalAmount) || decimalAmount.Sign <= 0)
            {
                ConsoleHelper.Error("Incorrect Amount Format");
                return;
            }
            try
            {
                tx = CurrentWallet.MakeTransaction(snapshot, new[]
                {
                    new TransferOutput
                    {
                        AssetId    = asset,
                        Value      = decimalAmount,
                        ScriptHash = to,
                        Data       = data
                    }
                }, from: from, cosigners: signerAccounts?.Select(p => new Signer
                {
                    // default access for transfers should be valid only for first invocation
                    Scopes  = WitnessScope.CalledByEntry,
                    Account = p
                })
                                                   .ToArray() ?? Array.Empty <Signer>());
            }
            catch (Exception e)
            {
                ConsoleHelper.Error(GetExceptionMessage(e));
                return;
            }

            if (tx == null)
            {
                ConsoleHelper.Warning("Insufficient funds");
                return;
            }

            ConsoleHelper.Info("Network fee: ",
                               $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}\t",
                               "Total fee: ",
                               $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS");
            if (!ReadUserInput("Relay tx? (no|yes)").IsYes())
            {
                return;
            }
            SignAndSendTx(NeoSystem.StoreView, tx);
        }
Esempio n. 18
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);
        }
Esempio n. 19
0
        /// <summary>
        /// send asset
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="receivers"></param>
        /// <param name="asset"></param>
        /// <returns></returns>
        public async Task <object> SendToMultiAddress(MultiReceiverRequest[] receivers, string asset = "neo", UInt160 sender = null)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }

            if (receivers.IsEmpty())
            {
                return(Error(ErrorCode.ParameterIsNull, $"receivers is null!"));
            }
            UInt160 assetHash = ConvertToAssetId(asset, out var convertError);

            if (assetHash == null)
            {
                return(Error(ErrorCode.InvalidPara, $"asset is not valid:{convertError}"));
            }

            var assetInfo = AssetCache.GetAssetInfo(assetHash);

            if (assetInfo == null)
            {
                return(Error(ErrorCode.InvalidPara, $"asset is not valid:{convertError}"));
            }
            if (sender != null)
            {
                var account = CurrentWallet.GetAccount(sender);
                if (account == null)
                {
                    return(Error(ErrorCode.AddressNotFound));
                }
            }
            var toes = new List <(UInt160 scriptHash, BigDecimal amount)>();

            foreach (var receiver in receivers)
            {
                if (!BigDecimal.TryParse(receiver.Amount, assetInfo.Decimals, out BigDecimal sendAmount) || sendAmount.Sign <= 0)
                {
                    return(Error(ErrorCode.InvalidPara, $"Incorrect Amount Format:{receiver.Amount}"));
                }
                toes.Add((receiver.Address, sendAmount));
            }
            var outputs = toes.Select(t => new TransferOutput()
            {
                AssetId    = assetHash,
                Value      = t.amount,
                ScriptHash = t.scriptHash,
            }).ToArray();

            try
            {
                Transaction tx = CurrentWallet.MakeTransaction(Helpers.GetDefaultSnapshot(), outputs, sender);
                if (tx == null)
                {
                    return(Error(ErrorCode.BalanceNotEnough, "Insufficient funds"));
                }

                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                return(new TransactionModel(tx));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                return(Error(ErrorCode.TransferError, ex.Message));
            }
        }
Esempio n. 20
0
        public async Task <object> DeployContract(string nefPath, string manifestPath = null, bool sendTx = false, UInt160 sender = null)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (nefPath.IsNull())
            {
                return(Error(ErrorCode.ParameterIsNull, "nefPath is empty."));
            }
            if (manifestPath.IsNull())
            {
                manifestPath = Path.ChangeExtension(nefPath, ".manifest.json");
            }
            // Read nef
            NefFile nefFile = ReadNefFile(nefPath);
            // Read manifest
            ContractManifest manifest = ReadManifestFile(manifestPath);

            // Basic script checks
            await CheckBadOpcode(nefFile.Script);

            // Build script
            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", nefFile.ToArray(),
                               manifest.ToJson().ToString());
            //sb.EmitAppCall(NativeContract.Management.Hash, "deploy", nefFile.ToArray(), manifest.ToJson().ToString());
            var script = sb.ToArray();

            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(Helpers.GetDefaultSnapshot(), script, sender);
            }
            catch (InvalidOperationException ex)
            {
                return(Error(ErrorCode.EngineFault, ex.GetExMessage()));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            UInt160 hash = SmartContract.Helper.GetContractHash(tx.Sender, nefFile.CheckSum, manifest.Name);

            var oldContract = hash.GetContract();

            if (oldContract != null)
            {
                return(Error(ErrorCode.ContractAlreadyExist));
            }
            var result = new DeployResultModel
            {
                ContractHash = hash,
                GasConsumed  = new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)
            };

            if (sendTx)
            {
                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                result.TxId = tx.Hash;
            }
            return(result);
        }
Esempio n. 21
0
        /// <summary>
        /// send asset
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="receiver"></param>
        /// <param name="amount"></param>
        /// <param name="asset"></param>
        /// <returns></returns>
        public async Task <object> SendToAddress(UInt160 receiver, string amount, string asset = "neo", UInt160 sender = null)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (receiver == null)
            {
                return(Error(ErrorCode.ParameterIsNull, $"receiver address is null!"));
            }
            UInt160 assetHash = ConvertToAssetId(asset, out var convertError);

            if (assetHash == null)
            {
                return(Error(ErrorCode.InvalidPara, $"asset is not valid:{convertError}"));
            }
            var assetInfo = AssetCache.GetAssetInfo(assetHash);

            if (assetInfo == null)
            {
                return(Error(ErrorCode.InvalidPara, $"asset is not valid:{convertError}"));
            }
            if (!BigDecimal.TryParse(amount, assetInfo.Decimals, out BigDecimal sendAmount) || sendAmount.Sign <= 0)
            {
                return(Error(ErrorCode.InvalidPara, "Incorrect Amount Format"));
            }

            if (sender != null)
            {
                var account = CurrentWallet.GetAccount(sender);
                if (account == null)
                {
                    return(Error(ErrorCode.AddressNotFound));
                }
                var balance = sender.GetBalanceOf(assetHash);
                if (balance.Value < sendAmount.Value)
                {
                    return(Error(ErrorCode.BalanceNotEnough));
                }
            }

            try
            {
                Transaction tx = CurrentWallet.MakeTransaction(Helpers.GetDefaultSnapshot(), new[]
                {
                    new TransferOutput
                    {
                        AssetId    = assetHash,
                        Value      = sendAmount,
                        ScriptHash = receiver
                    }
                }, sender);

                if (tx == null)
                {
                    return(Error(ErrorCode.BalanceNotEnough, "Insufficient funds"));
                }

                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                return(new TransactionModel(tx));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                return(Error(ErrorCode.TransferError, ex.Message));
            }
        }
Esempio n. 22
0
        private bool OnInvokeCommand(string[] args)
        {
            var scriptHash = UInt160.Parse(args[1]);

            List <ContractParameter> contractParameters = new List <ContractParameter>();

            for (int i = 3; i < args.Length; i++)
            {
                contractParameters.Add(new ContractParameter()
                {
                    // TODO: support contract params of type other than string.
                    Type  = ContractParameterType.String,
                    Value = args[i]
                });
            }

            Transaction tx = new Transaction
            {
                Signers = new Signer[] { new Signer()
                                         {
                                             Account = UInt160.Zero
                                         } },
                Attributes = new TransactionAttribute[0],
                Witnesses  = new Witness[0]
            };

            using (ScriptBuilder scriptBuilder = new ScriptBuilder())
            {
                scriptBuilder.EmitDynamicCall(scriptHash, args[2], contractParameters.ToArray());
                tx.Script = scriptBuilder.ToArray();
                Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'");
            }

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

            if (NoWallet())
            {
                return(true);
            }
            try
            {
                tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, tx.Script);
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Error: insufficient balance.");
                return(true);
            }
            if (!ReadUserInput("relay tx(no|yes)").IsYes())
            {
                return(true);
            }
            return(SignAndSendTx(tx));
        }
Esempio n. 23
0
        private bool OnSendCommand(string[] args)
        {
            if (args.Length != 4)
            {
                Console.WriteLine("error");
                return(true);
            }
            if (NoWallet())
            {
                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);
            }
            UInt160 assetId;

            switch (args[1].ToLower())
            {
            case "neo":
                assetId = NativeContract.NEO.Hash;
                break;

            case "gas":
                assetId = NativeContract.GAS.Hash;
                break;

            default:
                assetId = UInt160.Parse(args[1]);
                break;
            }
            UInt160         to       = args[2].ToScriptHash();
            var             snapshot = NeoSystem.StoreView;
            Transaction     tx;
            AssetDescriptor descriptor = new AssetDescriptor(snapshot, CliSettings.Default.Protocol, assetId);

            if (!BigDecimal.TryParse(args[3], descriptor.Decimals, out BigDecimal amount) || amount.Sign <= 0)
            {
                Console.WriteLine("Incorrect Amount Format");
                return(true);
            }
            tx = CurrentWallet.MakeTransaction(snapshot, new[]
            {
                new TransferOutput
                {
                    AssetId    = assetId,
                    Value      = amount,
                    ScriptHash = to
                }
            });

            if (tx == null)
            {
                Console.WriteLine("Insufficient funds");
                return(true);
            }

            ContractParametersContext context = new ContractParametersContext(snapshot, tx, CliSettings.Default.Protocol.Network);

            CurrentWallet.Sign(context);
            if (context.Completed)
            {
                tx.Witnesses = context.GetWitnesses();
                NeoSystem.Blockchain.Tell(tx);
                //NeoSystem.LocalNode.Tell(new LocalNode.Relay { Inventory = tx });
                Console.WriteLine($"TXID: {tx.Hash}");
            }
            else
            {
                Console.WriteLine("SignatureContext:");
                Console.WriteLine(context.ToString());
            }

            return(true);
        }
        private void OnUpdateCommand(UInt160 scriptHash, string filePath, string manifestPath, UInt160 sender, UInt160[] signerAccounts = null, JObject data = null)
        {
            Signer[] signers = Array.Empty <Signer>();

            if (NoWallet())
            {
                return;
            }
            if (sender != null)
            {
                if (signerAccounts == null)
                {
                    signerAccounts = new UInt160[1] {
                        sender
                    }
                }
                ;
                else if (signerAccounts.Contains(sender) && signerAccounts[0] != sender)
                {
                    var signersList = signerAccounts.ToList();
                    signersList.Remove(sender);
                    signerAccounts = signersList.Prepend(sender).ToArray();
                }
                else if (!signerAccounts.Contains(sender))
                {
                    signerAccounts = signerAccounts.Prepend(sender).ToArray();
                }
                signers = signerAccounts.Select(p => new Signer()
                {
                    Account = p, Scopes = WitnessScope.CalledByEntry
                }).ToArray();
            }

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

            try
            {
                byte[] script = LoadUpdateScript(scriptHash, filePath, manifestPath, data, out var nef, out var manifest);
                tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, script, sender, signers);
            }
            catch (InvalidOperationException e)
            {
                ConsoleHelper.Error(GetExceptionMessage(e));
                return;
            }
            ContractState contract = NativeContract.ContractManagement.GetContract(NeoSystem.StoreView, scriptHash);

            if (contract == null)
            {
                ConsoleHelper.Warning($"Can't upgrade, contract hash not exist: {scriptHash}");
            }
            else
            {
                ConsoleHelper.Info("Contract hash: ", $"{scriptHash}");
                ConsoleHelper.Info("Updated times: ", $"{contract.UpdateCounter}");
                ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)}");
                ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}");
                ConsoleHelper.Info("Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS");
                if (!ReadUserInput("Relay tx? (no|yes)").IsYes()) // Add this in case just want to get hash but not relay
                {
                    return;
                }
                SignAndSendTx(NeoSystem.StoreView, tx);
            }
        }
Esempio n. 25
0
        public async Task <object> UpdateContract(UInt160 contractHash, string nefPath, string manifestPath = null, bool sendTx = false, UInt160[] cosigners = null)
        {
            if (CurrentWallet == null)
            {
                return(Error(ErrorCode.WalletNotOpen));
            }
            if (nefPath.IsNull())
            {
                return(Error(ErrorCode.ParameterIsNull, "nefPath is empty."));
            }
            if (manifestPath.IsNull())
            {
                manifestPath = Path.ChangeExtension(nefPath, ".manifest.json");
            }
            // Read nef
            NefFile nefFile = ReadNefFile(nefPath);
            // Read manifest
            ContractManifest manifest = ReadManifestFile(manifestPath);

            // Basic script checks
            await CheckBadOpcode(nefFile.Script);

            // Build script
            using ScriptBuilder sb = new ScriptBuilder();
            sb.EmitDynamicCall(contractHash, "update", nefFile.ToArray(), manifest.ToJson().ToString(), null);
            var script = sb.ToArray();

            var singers = new List <Signer> {
            };

            if (cosigners != null)
            {
                singers.AddRange(cosigners.Select(s => new Signer()
                {
                    Account = s, Scopes = WitnessScope.Global
                }));
            }
            Transaction tx;

            try
            {
                tx = CurrentWallet.MakeTransaction(Helpers.GetDefaultSnapshot(), script, null, singers.ToArray());
            }
            catch (InvalidOperationException ex)
            {
                return(Error(ErrorCode.EngineFault, ex.GetExMessage()));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("Insufficient GAS"))
                {
                    return(Error(ErrorCode.GasNotEnough));
                }
                throw;
            }

            var result = new DeployResultModel
            {
                ContractHash = contractHash,
                GasConsumed  = new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)
            };

            if (sendTx)
            {
                var(signSuccess, context) = CurrentWallet.TrySignTx(tx);
                if (!signSuccess)
                {
                    return(Error(ErrorCode.SignFail, context.SafeSerialize()));
                }
                await tx.Broadcast();

                result.TxId = tx.Hash;
            }
            return(result);
        }
Esempio n. 26
0
        private void OnSendCommand(UInt160 asset, UInt160 to, string amount, UInt160 from = null, UInt160[] signerAccounts = null)
        {
            if (NoWallet())
            {
                return;
            }
            string password = ReadUserInput("password", true);

            if (password.Length == 0)
            {
                Console.WriteLine("Cancelled");
                return;
            }
            if (!CurrentWallet.VerifyPassword(password))
            {
                Console.WriteLine("Incorrect password");
                return;
            }

            Transaction     tx;
            AssetDescriptor descriptor = new AssetDescriptor(asset);

            if (!BigDecimal.TryParse(amount, descriptor.Decimals, out BigDecimal decimalAmount) || decimalAmount.Sign <= 0)
            {
                Console.WriteLine("Incorrect Amount Format");
                return;
            }
            try
            {
                tx = CurrentWallet.MakeTransaction(new[]
                {
                    new TransferOutput
                    {
                        AssetId    = asset,
                        Value      = decimalAmount,
                        ScriptHash = to
                    }
                }, from: from, cosigners: signerAccounts?.Select(p => new Signer
                {
                    // default access for transfers should be valid only for first invocation
                    Scopes  = WitnessScope.CalledByEntry,
                    Account = p
                })
                                                   .ToArray() ?? new Signer[0]);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + GetExceptionMessage(e));
                return;
            }

            if (tx == null)
            {
                Console.WriteLine("Insufficient funds");
                return;
            }

            ContractParametersContext context = new ContractParametersContext(tx);

            CurrentWallet.Sign(context);
            if (context.Completed)
            {
                tx.Witnesses = context.GetWitnesses();
                NeoSystem.Blockchain.Tell(tx);
                Console.WriteLine($"TXID: {tx.Hash}");
            }
            else
            {
                Console.WriteLine("SignatureContext:");
                Console.WriteLine(context.ToString());
            }
        }