diff --git a/neo-cli/CLI/MainService.Contracts.cs b/neo-cli/CLI/MainService.Contracts.cs
index b7ab38503..6f3b42bca 100644
--- a/neo-cli/CLI/MainService.Contracts.cs
+++ b/neo-cli/CLI/MainService.Contracts.cs
@@ -41,6 +41,55 @@ private void OnDeployCommand(string filePath, string manifestPath = null)
SignAndSendTx(tx);
}
+ ///
+ /// Process "invoke" command
+ ///
+ /// Script hash
+ /// Operation
+ /// Transaction
+ /// Contract parameters
+ private VM.Types.StackItem OnInvokeWithResult(UInt160 scriptHash, string operation, IVerifiable verificable = null, JArray contractParameters = null)
+ {
+ List parameters = new List();
+
+ if (contractParameters != null)
+ {
+ foreach (var contractParameter in contractParameters)
+ {
+ parameters.Add(ContractParameter.FromJson(contractParameter));
+ }
+ }
+
+ byte[] script;
+
+ using (ScriptBuilder scriptBuilder = new ScriptBuilder())
+ {
+ scriptBuilder.EmitAppCall(scriptHash, operation, parameters.ToArray());
+ script = scriptBuilder.ToArray();
+ Console.WriteLine($"Invoking script with: '{script.ToHexString()}'");
+ }
+
+ if (verificable is Transaction tx)
+ {
+ tx.Script = script;
+ }
+
+ using (ApplicationEngine engine = ApplicationEngine.Run(script, verificable, testMode: true))
+ {
+ Console.WriteLine($"VM State: {engine.State}");
+ Console.WriteLine($"Gas Consumed: {new BigDecimal(engine.GasConsumed, NativeContract.GAS.Decimals)}");
+ Console.WriteLine($"Result Stack: {new JArray(engine.ResultStack.Select(p => p.ToJson()))}");
+
+ if (engine.State.HasFlag(VMState.FAULT) || !engine.ResultStack.TryPop(out VM.Types.StackItem ret))
+ {
+ Console.WriteLine("Engine faulted.");
+ return null;
+ }
+
+ return ret;
+ }
+ }
+
///
/// Process "invoke" command
///
@@ -51,10 +100,9 @@ private void OnDeployCommand(string filePath, string manifestPath = null)
[ConsoleCommand("invoke", Category = "Contract Commands")]
private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null)
{
- List parameters = new List();
List signCollection = new List();
- if (!NoWallet() && witnessAddress != null)
+ if (witnessAddress != null && !NoWallet())
{
using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot())
{
@@ -77,14 +125,6 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contra
}
}
- if (contractParameters != null)
- {
- foreach (var contractParameter in contractParameters)
- {
- parameters.Add(ContractParameter.FromJson(contractParameter));
- }
- }
-
Transaction tx = new Transaction
{
Sender = UInt160.Zero,
@@ -93,25 +133,7 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contra
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.ToJson()))}");
- Console.WriteLine();
- if (engine.State.HasFlag(VMState.FAULT))
- {
- Console.WriteLine("Engine faulted.");
- return;
- }
- }
+ _ = OnInvokeWithResult(scriptHash, operation, tx, contractParameters);
if (NoWallet()) return;
try
diff --git a/neo-cli/CLI/MainService.NEP5.cs b/neo-cli/CLI/MainService.NEP5.cs
new file mode 100644
index 000000000..3987c307d
--- /dev/null
+++ b/neo-cli/CLI/MainService.NEP5.cs
@@ -0,0 +1,94 @@
+using Neo.ConsoleService;
+using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
+using Neo.VM;
+using Neo.VM.Types;
+using Neo.Wallets;
+using System;
+using System.Globalization;
+
+namespace Neo.CLI
+{
+ partial class MainService
+ {
+ ///
+ /// Process "transfer" command
+ ///
+ /// Script hash
+ /// To
+ /// Ammount
+ [ConsoleCommand("transfer", Category = "NEP5 Commands")]
+ 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);
+ }
+
+ ///
+ /// Process "balanceOf" command
+ ///
+ /// Script hash
+ /// Address
+ [ConsoleCommand("balanceOf", Category = "NEP5 Commands")]
+ private void OnBalanceOfCommand(UInt160 tokenHash, UInt160 address)
+ {
+ var arg = new JObject();
+ arg["type"] = "Hash160";
+ arg["value"] = address.ToString();
+
+ var result = OnInvokeWithResult(tokenHash, "balanceOf", null, new JArray(arg));
+
+ Console.WriteLine($"Result : {((PrimitiveType)result).GetBigInteger()}");
+ }
+
+ ///
+ /// Process "name" command
+ ///
+ /// Script hash
+ [ConsoleCommand("name", Category = "NEP5 Commands")]
+ private void OnNameCommand(UInt160 tokenHash)
+ {
+ var result = OnInvokeWithResult(tokenHash, "name", null);
+
+ Console.WriteLine($"Result : {((PrimitiveType)result).GetString()}");
+ }
+
+ ///
+ /// Process "decimals" command
+ ///
+ /// Script hash
+ [ConsoleCommand("decimals", Category = "NEP5 Commands")]
+ private void OnDecimalsCommand(UInt160 tokenHash)
+ {
+ var result = OnInvokeWithResult(tokenHash, "decimals", null);
+
+ Console.WriteLine($"Result : {((PrimitiveType)result).GetBigInteger()}");
+ }
+ }
+}
diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs
index efb22c8be..ece3cca1f 100644
--- a/neo-cli/CLI/MainService.cs
+++ b/neo-cli/CLI/MainService.cs
@@ -18,6 +18,7 @@
using Neo.Wallets.SQLite;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
@@ -117,6 +118,7 @@ public MainService() : base()
RegisterCommandHander((str) => ECPoint.Parse(str.Trim(), ECCurve.Secp256r1));
RegisterCommandHander((str) => str.Select(u => ECPoint.Parse(u.Trim(), ECCurve.Secp256r1)).ToArray());
RegisterCommandHander((str) => JObject.Parse(str));
+ RegisterCommandHander((str) => decimal.Parse(str, CultureInfo.InvariantCulture));
RegisterCommandHander((obj) => (JArray)obj);
RegisterCommand(this);