/// <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; }
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())); } }
/// <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) }); }
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)}"); }
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); }
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()); }
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); }
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); }
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); }
/// <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, }); }
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); }
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"); } } }
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); }
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); }