Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements and fixes of nep11 command #391

Merged
merged 25 commits into from
Nov 28, 2023
Merged

Conversation

chenzhitong
Copy link
Member

@chenzhitong chenzhitong commented Nov 27, 2023

  • Add TokenIds as base64 as well
  • Fix error output to show inter error
  • Make wording say [Argument(1, Description = "TokenId of NFT (Format: HEX, BASE64)")]
  • Make wording say [Argument(0, Description = "NFT Contract (Symbol or Script Hash)")]
  • Add transfernft command to batch commands
  • Fix show nft
  • Remove regular expressions
  • Remove support for little-endian on TokenId
  • Allow contract names

@chenzhitong chenzhitong marked this pull request as ready for review November 27, 2023 03:51
@chenzhitong chenzhitong mentioned this pull request Nov 27, 2023
22 tasks
@chenzhitong
Copy link
Member Author

chenzhitong commented Nov 27, 2023

test:

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp transfernft -h
Transfer NFT asset between accounts

Usage: neoxp transfernft [options] <Contract> <TokenId> <Sender> <Receiver>

Arguments:
  Contract                  NFT Contract (Symbol or Script Hash)
  TokenId                   TokenId of NFT (Format: HEX, BASE64)
  Sender                    Account to send NFT from (Format: Wallet name, WIF)
  Receiver                  Account to send NFT to (Format: Script Hash, Address, Wallet name)

Options:
  -d|--data <DATA>          Optional data parameter to pass to transfer operation
  -p|--password <PASSWORD>  password to use for NEP-2/NEP-6 sender
  -i|--input <INPUT>        Path to neo-express data file
  -t|--trace                Enable contract execution tracing
  -j|--json                 Output as JSON
  -?|-h|--help              Show help information.

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp show nft -h
Show NFT Tokens for account

Usage: neoxp show nft [options] <Contract> <Account>

Arguments:
  Contract            NFT Contract (Symbol or Script Hash)
  Account             TokenId of NFT (Format: Script Hash, Address, Wallet name)

Options:
  -i|--input <INPUT>  Path to neo-express data file
  -?|-h|--help        Show help information.

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp show nft MyNFT node1
TokenId(Base64): QmxpbmQgQm94ICMx, TokenId(Hex): 0x312320786f4220646e696c42
TokenId(Base64): RnJhZ21lbnQgQiAjMTAwMA==, TokenId(Hex): 0x3030303123204220746e656d67617246
TokenId(Base64): RnJhZ21lbnQgQyAjMTAwMA==, TokenId(Hex): 0x3030303123204320746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRCAjMTAwMA==, TokenId(Hex): 0x3030303123204420746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRSAjMTAwMA==, TokenId(Hex): 0x3030303123204520746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRiAjMTAwMA==, TokenId(Hex): 0x3030303123204620746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRyAjMTAwMA==, TokenId(Hex): 0x3030303123204720746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSCAjMTAwMA==, TokenId(Hex): 0x3030303123204820746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSSAjMTAwMA==, TokenId(Hex): 0x3030303123204920746e656d67617246

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp show nft MyNFT 0x46a89f1eb2a90851a01fc8068dd9e9a2b15dcbdf
TokenId(Base64): QmxpbmQgQm94ICMx, TokenId(Hex): 0x312320786f4220646e696c42
TokenId(Base64): RnJhZ21lbnQgQiAjMTAwMA==, TokenId(Hex): 0x3030303123204220746e656d67617246
TokenId(Base64): RnJhZ21lbnQgQyAjMTAwMA==, TokenId(Hex): 0x3030303123204320746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRCAjMTAwMA==, TokenId(Hex): 0x3030303123204420746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRSAjMTAwMA==, TokenId(Hex): 0x3030303123204520746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRiAjMTAwMA==, TokenId(Hex): 0x3030303123204620746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRyAjMTAwMA==, TokenId(Hex): 0x3030303123204720746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSCAjMTAwMA==, TokenId(Hex): 0x3030303123204820746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSSAjMTAwMA==, TokenId(Hex): 0x3030303123204920746e656d67617246

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp show nft MyNFT NgKHVei5eA2pkkzJJFFSVB2QJLLrwpYJk5
TokenId(Base64): QmxpbmQgQm94ICMx, TokenId(Hex): 0x312320786f4220646e696c42
TokenId(Base64): RnJhZ21lbnQgQiAjMTAwMA==, TokenId(Hex): 0x3030303123204220746e656d67617246
TokenId(Base64): RnJhZ21lbnQgQyAjMTAwMA==, TokenId(Hex): 0x3030303123204320746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRCAjMTAwMA==, TokenId(Hex): 0x3030303123204420746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRSAjMTAwMA==, TokenId(Hex): 0x3030303123204520746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRiAjMTAwMA==, TokenId(Hex): 0x3030303123204620746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRyAjMTAwMA==, TokenId(Hex): 0x3030303123204720746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSCAjMTAwMA==, TokenId(Hex): 0x3030303123204820746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSSAjMTAwMA==, TokenId(Hex): 0x3030303123204920746e656d67617246

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp show nft 0x6ff1b0a3d731b676b2331dd16b91ecb8e8d97b34 node1
TokenId(Base64): QmxpbmQgQm94ICMx, TokenId(Hex): 0x312320786f4220646e696c42
TokenId(Base64): RnJhZ21lbnQgQiAjMTAwMA==, TokenId(Hex): 0x3030303123204220746e656d67617246
TokenId(Base64): RnJhZ21lbnQgQyAjMTAwMA==, TokenId(Hex): 0x3030303123204320746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRCAjMTAwMA==, TokenId(Hex): 0x3030303123204420746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRSAjMTAwMA==, TokenId(Hex): 0x3030303123204520746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRiAjMTAwMA==, TokenId(Hex): 0x3030303123204620746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRyAjMTAwMA==, TokenId(Hex): 0x3030303123204720746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSCAjMTAwMA==, TokenId(Hex): 0x3030303123204820746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSSAjMTAwMA==, TokenId(Hex): 0x3030303123204920746e656d67617246

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp show nft 0x6ff1b0a3d731b676b2331dd16b91ecb8e8d97b34 0x46a89f1eb2a90851a01fc8068dd9e9a2b15dcbdf
TokenId(Base64): QmxpbmQgQm94ICMx, TokenId(Hex): 0x312320786f4220646e696c42
TokenId(Base64): RnJhZ21lbnQgQiAjMTAwMA==, TokenId(Hex): 0x3030303123204220746e656d67617246
TokenId(Base64): RnJhZ21lbnQgQyAjMTAwMA==, TokenId(Hex): 0x3030303123204320746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRCAjMTAwMA==, TokenId(Hex): 0x3030303123204420746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRSAjMTAwMA==, TokenId(Hex): 0x3030303123204520746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRiAjMTAwMA==, TokenId(Hex): 0x3030303123204620746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRyAjMTAwMA==, TokenId(Hex): 0x3030303123204720746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSCAjMTAwMA==, TokenId(Hex): 0x3030303123204820746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSSAjMTAwMA==, TokenId(Hex): 0x3030303123204920746e656d67617246

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp show nft 0x6ff1b0a3d731b676b2331dd16b91ecb8e8d97b34 NgKHVei5eA2pkkzJJFFSVB2QJLLrwpYJk5
TokenId(Base64): QmxpbmQgQm94ICMx, TokenId(Hex): 0x312320786f4220646e696c42
TokenId(Base64): RnJhZ21lbnQgQiAjMTAwMA==, TokenId(Hex): 0x3030303123204220746e656d67617246
TokenId(Base64): RnJhZ21lbnQgQyAjMTAwMA==, TokenId(Hex): 0x3030303123204320746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRCAjMTAwMA==, TokenId(Hex): 0x3030303123204420746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRSAjMTAwMA==, TokenId(Hex): 0x3030303123204520746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRiAjMTAwMA==, TokenId(Hex): 0x3030303123204620746e656d67617246
TokenId(Base64): RnJhZ21lbnQgRyAjMTAwMA==, TokenId(Hex): 0x3030303123204720746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSCAjMTAwMA==, TokenId(Hex): 0x3030303123204820746e656d67617246
TokenId(Base64): RnJhZ21lbnQgSSAjMTAwMA==, TokenId(Hex): 0x3030303123204920746e656d67617246

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp transfernft MyNFT RnJhZ21lbnQgQiAjMTAwMA== node1 NgKHVei5eA2pkkzJJFFSVB2QJLLrwpYJk5
TransferNFT Transaction 0xe3a81ace47f59c998b324ec18e9900a23ed536bcaff2482e57d80a9364f58c82 submitted

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp transfernft MyNFT 0x3030303123204320746e656d67617246 node1 NgKHVei5eA2pkkzJJFFSVB2QJLLrwpYJk5
TransferNFT Transaction 0x83514c723b01dfecea67b3eef6ff8e9ea76f59aed6af8399d4d84b63baa9f189 submitted

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp transfernft MyNFT RnJhZ21lbnQgSSAjMTAwMA== node1 node2
TransferNFT Transaction 0x99248ace1320b08ca59a5f37342818975fad7ca014d8db22c44d02bf525409f8 submitted

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp transfernft MyNFT RnJhZ21lbnQgQiAjMTAwMA== node1 0x46a89f1eb2a90851a01fc8068dd9e9a2b15dcbdf
TransferNFT Transaction 0x0dd3b3cbcfeee2dc9ee732138d44dada527011e59631390dd006c6ac695b0e15 submitted

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp transfernft 0x6ff1b0a3d731b676b2331dd16b91ecb8e8d97b34 RnJhZ21lbnQgRCAjMTAwMA== node1 NgKHVei5eA2pkkzJJFFSVB2QJLLrwpYJk5
TransferNFT Transaction 0x9c08798a954be199bcbb1ecda5cf6c866fbff4b69f20820be975e5d5b915d106 submitted

PS D:\1Code\chen\neo-express\src\neoxp\bin\Debug\net7.0> ./neoxp transfernft 0x6ff1b0a3d731b676b2331dd16b91ecb8e8d97b34 0x3030303123204520746e656d67617246 node1 NgKHVei5eA2pkkzJJFFSVB2QJLLrwpYJk5
TransferNFT Transaction 0x14f034b5fab5fbfaef20fe7e8794af0ad2281067258f0637a565c54bd1322c81 submitted

@cschuchardt88
Copy link
Member

Just a reminder for the future. We need to add transfernft to batch commands.

[Required]
internal string Contract { get; init; } = string.Empty;

[Argument(1, Description = "Account to show asset balance for")]
[Argument(1, Description = "TokenId of NFT (Format: Script Hash, Address, Wallet name)")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this should read as Account?

@chenzhitong
Copy link
Member Author

Just a reminder for the future. We need to add transfernft to batch commands.

I have added TransferNFT to BatchCommand, please check if I have added it right

@cschuchardt88
Copy link
Member

You have to add here as well.

switch (pr.SelectedCommand)
{
case CommandLineApplication<BatchFileCommands.Checkpoint.Create> cmd:
{
_ = await chainManager.CreateCheckpointAsync(
txExec.ExpressNode,
cmd.Model.Name,
cmd.Model.Force,
writer).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Contract.Deploy> cmd:
{
await txExec.ContractDeployAsync(
root.Resolve(cmd.Model.Contract),
cmd.Model.Account,
cmd.Model.Password,
cmd.Model.WitnessScope,
cmd.Model.Data,
cmd.Model.Force).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Contract.Download> cmd:
{
if (cmd.Model.Height == 0)
{
throw new ArgumentException("Height cannot be 0. Please specify a height > 0");
}
if (chainManager.Chain.ConsensusNodes.Count != 1)
{
throw new ArgumentException("Contract download is only supported for single-node consensus");
}
var force = ContractCommand.Download.ParseOverwriteForceOption(cmd);
await ContractCommand.Download.ExecuteAsync(
txExec.ExpressNode,
cmd.Model.Contract,
cmd.Model.RpcUri,
cmd.Model.Height,
force,
writer).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Contract.Invoke> cmd:
{
var script = await txExec.LoadInvocationScriptAsync(
root.Resolve(cmd.Model.InvocationFile)).ConfigureAwait(false);
await txExec.ContractInvokeAsync(
script,
cmd.Model.Account,
cmd.Model.Password,
cmd.Model.WitnessScope).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Contract.Run> cmd:
{
var script = await txExec.BuildInvocationScriptAsync(
cmd.Model.Contract,
cmd.Model.Method,
cmd.Model.Arguments).ConfigureAwait(false);
await txExec.ContractInvokeAsync(
script,
cmd.Model.Account,
cmd.Model.Password,
cmd.Model.WitnessScope).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Contract.Update> cmd:
{
await txExec.ContractUpdateAsync(
cmd.Model.Contract,
cmd.Model.NefFile,
cmd.Model.Account,
cmd.Model.Password,
cmd.Model.WitnessScope).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.FastForward> cmd:
{
var timestampDelta = FastForwardCommand.ParseTimestampDelta(cmd.Model.TimestampDelta);
await txExec.ExpressNode.FastForwardAsync(
cmd.Model.Count,
timestampDelta).ConfigureAwait(false);
await writer.WriteLineAsync($"{cmd.Model.Count} empty blocks minted").ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Oracle.Enable> cmd:
{
await txExec.OracleEnableAsync(
cmd.Model.Account,
cmd.Model.Password).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Oracle.Response> cmd:
{
await txExec.OracleResponseAsync(
cmd.Model.Url,
root.Resolve(cmd.Model.ResponsePath),
cmd.Model.RequestId).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Policy.Block> cmd:
{
await txExec.BlockAsync(
cmd.Model.ScriptHash,
cmd.Model.Account,
cmd.Model.Password).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Policy.Set> cmd:
{
await txExec.SetPolicyAsync(
cmd.Model.Policy,
cmd.Model.Value,
cmd.Model.Account,
cmd.Model.Password).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Policy.Sync> cmd:
{
if (string.IsNullOrEmpty(cmd.Model.Account))
throw new ArgumentException("Policy sync requires --account field");
var values = await txExec.TryGetRemoteNetworkPolicyAsync(cmd.Model.Source).ConfigureAwait(false);
if (values.IsT1)
values = await txExec.TryLoadPolicyFromFileSystemAsync(cmd.Model.Source)
.ConfigureAwait(false);
if (values.TryPickT0(out var policyValues, out _))
{
await txExec.SetPolicyAsync(policyValues, cmd.Model.Account, cmd.Model.Password);
}
else
{
throw new ArgumentException($"Could not load policy values from \"{cmd.Model.Source}\"");
}
break;
}
case CommandLineApplication<BatchFileCommands.Policy.Unblock> cmd:
{
await txExec.UnblockAsync(
cmd.Model.ScriptHash,
cmd.Model.Account,
cmd.Model.Password).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Transfer> cmd:
{
await txExec.TransferAsync(
cmd.Model.Quantity,
cmd.Model.Asset,
cmd.Model.Sender,
cmd.Model.Password,
cmd.Model.Receiver,
cmd.Model.Data).ConfigureAwait(false);
break;
}
case CommandLineApplication<BatchFileCommands.Wallet.Create> cmd:
{
var wallet = chainManager.CreateWallet(
cmd.Model.Name,
cmd.Model.PrivateKey,
cmd.Model.Force);
chainManager.SaveChain(chainFilename!);
await writer.WriteLineAsync($"Created Wallet {cmd.Model.Name}");
for (int x = 0; x < wallet.Accounts.Count; x++)
await writer.WriteLineAsync($" Address: {wallet.Accounts[x].ScriptHash}");
break;
}
default:
throw new Exception($"Unknown batch command {pr.SelectedCommand.GetType()}");
}

@cschuchardt88
Copy link
Member

Also here too (as subcommand)

[Subcommand(typeof(Checkpoint), typeof(Contract), typeof(FastForward), typeof(Oracle), typeof(Policy), typeof(Transfer), typeof(Wallet))]

@chenzhitong
Copy link
Member Author

@cschuchardt88 It's added.

{
return Encoding.UTF8.GetString(hex.HexToBytes());
return input.StartsWith("0x") ? Encoding.UTF8.GetString(input[2..].HexToBytes().Reverse().ToArray()) : Encoding.UTF8.GetString(Convert.FromBase64String(input));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure reverse is appropriate?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure, it starting with 0x is big-endian hex string, need to remove 0x and revert to byte array. Same deal here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but that is only for UInt160. Normally with just hexstring it isnt reversed. I know people complained about this. But we can leave for now.

Copy link
Member Author

@chenzhitong chenzhitong Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a note in the documentation would be nice, like this

NOTE
In Neo, hexadecimal strings are processed in big-endian order if they are preceded by 0x, or little-endian order if they are not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the results in reverse?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jim8y Jim8y merged commit 2021390 into neo-project:master Nov 28, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants