Skip to content
This repository has been archived by the owner on Dec 7, 2023. It is now read-only.

Add NEP5 commands #575

Merged
merged 6 commits into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 51 additions & 29 deletions neo-cli/CLI/MainService.Contracts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,55 @@ private void OnDeployCommand(string filePath, string manifestPath = null)
SignAndSendTx(tx);
}

/// <summary>
/// Process "invoke" command
/// </summary>
/// <param name="scriptHash">Script hash</param>
/// <param name="operation">Operation</param>
/// <param name="verificable">Transaction</param>
/// <param name="contractParameters">Contract parameters</param>
private VM.Types.StackItem OnInvokeWithResult(UInt160 scriptHash, string operation, IVerifiable verificable = null, JArray contractParameters = null)
{
List<ContractParameter> parameters = new List<ContractParameter>();

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;
}
}

/// <summary>
/// Process "invoke" command
/// </summary>
Expand All @@ -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<ContractParameter> parameters = new List<ContractParameter>();
List<Cosigner> signCollection = new List<Cosigner>();

if (!NoWallet() && witnessAddress != null)
if (witnessAddress != null && !NoWallet())
{
using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot())
{
Expand All @@ -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,
Expand All @@ -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
Expand Down
94 changes: 94 additions & 0 deletions neo-cli/CLI/MainService.NEP5.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Process "transfer" command
/// </summary>
/// <param name="tokenHash">Script hash</param>
/// <param name="to">To</param>
/// <param name="amount">Ammount</param>
[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);
}

/// <summary>
/// Process "balanceOf" command
/// </summary>
/// <param name="tokenHash">Script hash</param>
/// <param name="address">Address</param>
[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()}");
}

/// <summary>
/// Process "name" command
/// </summary>
/// <param name="tokenHash">Script hash</param>
[ConsoleCommand("name", Category = "NEP5 Commands")]
private void OnNameCommand(UInt160 tokenHash)
{
var result = OnInvokeWithResult(tokenHash, "name", null);

Console.WriteLine($"Result : {((PrimitiveType)result).GetString()}");
}

/// <summary>
/// Process "decimals" command
/// </summary>
/// <param name="tokenHash">Script hash</param>
[ConsoleCommand("decimals", Category = "NEP5 Commands")]
private void OnDecimalsCommand(UInt160 tokenHash)
{
var result = OnInvokeWithResult(tokenHash, "decimals", null);

Console.WriteLine($"Result : {((PrimitiveType)result).GetBigInteger()}");
}
}
}
2 changes: 2 additions & 0 deletions neo-cli/CLI/MainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -117,6 +118,7 @@ public MainService() : base()
RegisterCommandHander<string, ECPoint>((str) => ECPoint.Parse(str.Trim(), ECCurve.Secp256r1));
RegisterCommandHander<string[], ECPoint[]>((str) => str.Select(u => ECPoint.Parse(u.Trim(), ECCurve.Secp256r1)).ToArray());
RegisterCommandHander<string, JObject>((str) => JObject.Parse(str));
RegisterCommandHander<string, decimal>((str) => decimal.Parse(str, CultureInfo.InvariantCulture));
RegisterCommandHander<JObject, JArray>((obj) => (JArray)obj);

RegisterCommand(this);
Expand Down