diff --git a/Neo.ConsoleService/ConsoleServiceBase.cs b/Neo.ConsoleService/ConsoleServiceBase.cs
index 26d157ed0..4374dd632 100644
--- a/Neo.ConsoleService/ConsoleServiceBase.cs
+++ b/Neo.ConsoleService/ConsoleServiceBase.cs
@@ -416,7 +416,7 @@ protected ConsoleServiceBase()
}
else
{
- return CommandToken.ReadString(args, false).Split(',', ' ');
+ return CommandToken.ReadString(args, false).Split(',', ' ', StringSplitOptions.RemoveEmptyEntries);
}
});
diff --git a/neo-cli/CLI/MainService.Contracts.cs b/neo-cli/CLI/MainService.Contracts.cs
index f3f4f3d56..711f446a1 100644
--- a/neo-cli/CLI/MainService.Contracts.cs
+++ b/neo-cli/CLI/MainService.Contracts.cs
@@ -6,14 +6,47 @@
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.VM;
+using Neo.Wallets;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Numerics;
namespace Neo.CLI
{
partial class MainService
{
+ private class AttachAsset
+ {
+ public AssetDescriptor Asset;
+ public BigDecimal Amount;
+
+ ///
+ /// Parse from string
+ /// Format: neo=1 gas=2.456 0x0..=123.5
+ ///
+ /// Input
+ ///
+ internal static AttachAsset Parse(string input)
+ {
+ var split = input.Split('=', StringSplitOptions.RemoveEmptyEntries);
+ if (split.Length != 2) throw new FormatException("Format expected: neo=1");
+
+ var ret = new AttachAsset
+ {
+ Asset = (split[0].ToLowerInvariant()) switch
+ {
+ "neo" => new AssetDescriptor(NativeContract.NEO.Hash),
+ "gas" => new AssetDescriptor(NativeContract.GAS.Hash),
+ _ => new AssetDescriptor(UInt160.Parse(split[0])),
+ }
+ };
+
+ ret.Amount = BigDecimal.Parse(split[1], ret.Asset.Decimals);
+ return ret;
+ }
+ }
+
///
/// Process "deploy" command
///
@@ -48,8 +81,9 @@ private void OnDeployCommand(string filePath, string manifestPath = null)
/// Operation
/// Contract parameters
/// Witness address
+ /// Attach
[ConsoleCommand("invoke", Category = "Contract Commands")]
- private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null)
+ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null, AttachAsset[] attach = null)
{
List parameters = new List();
List signCollection = new List();
@@ -95,6 +129,54 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contra
using (ScriptBuilder scriptBuilder = new ScriptBuilder())
{
+ if (attach != null)
+ {
+ if (NoWallet()) return;
+
+ foreach (var entry in attach.GroupBy(u => u.Asset.AssetId))
+ {
+ // Get amount
+
+ var amount = BigInteger.Zero;
+ foreach (var am in entry) amount += am.Amount.Value;
+
+ // Find a valid sender
+
+ var tempTx = CurrentWallet.MakeTransaction(new[]
+ {
+ new TransferOutput
+ {
+ AssetId = entry.Key,
+ Value = new BigDecimal(amount, entry.First().Asset.Decimals),
+ ScriptHash = scriptHash
+ }
+ });
+
+ if (tempTx == null)
+ {
+ Console.WriteLine("Insufficient funds of: " + entry.First().Asset.AssetName);
+ return;
+ }
+
+ // Append at the begining the right script
+
+ scriptBuilder.EmitAppCall(entry.Key, "transfer", tempTx.Sender, scriptHash, amount);
+
+ // Compute new cosigners
+
+ signCollection.Add(new Cosigner()
+ {
+ Account = tempTx.Sender,
+ AllowedContracts = new UInt160[] { entry.Key },
+ Scopes = WitnessScope.CustomContracts
+ });
+ }
+
+ // Add new cosigners
+
+ tx.Cosigners = signCollection.ToArray();
+ }
+
scriptBuilder.EmitAppCall(scriptHash, operation, parameters.ToArray());
tx.Script = scriptBuilder.ToArray();
Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'");
diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs
index f543dba16..ac2891c66 100644
--- a/neo-cli/CLI/MainService.cs
+++ b/neo-cli/CLI/MainService.cs
@@ -115,6 +115,7 @@ public MainService() : base()
RegisterCommandHander((str) => str.Select(u => ECPoint.Parse(u.Trim(), ECCurve.Secp256r1)).ToArray());
RegisterCommandHander((str) => JObject.Parse(str));
RegisterCommandHander((obj) => (JArray)obj);
+ RegisterCommandHander((str) => str.Select(u => AttachAsset.Parse(u)).ToArray());
RegisterCommand(this);