From 8b9de3371d3e34e347c2daafff62e26cd1074ebe Mon Sep 17 00:00:00 2001 From: Ricardo Prado Date: Wed, 22 Nov 2023 21:00:19 -0300 Subject: [PATCH 1/3] Neo Node Migration --- neo.sln | 28 + src/Neo.CLI/CLI/ConsolePercent.cs | 145 ++ src/Neo.CLI/CLI/Helper.cs | 41 + src/Neo.CLI/CLI/MainService.Blockchain.cs | 45 + src/Neo.CLI/CLI/MainService.Contracts.cs | 182 ++ src/Neo.CLI/CLI/MainService.Logger.cs | 171 ++ src/Neo.CLI/CLI/MainService.NEP17.cs | 140 ++ src/Neo.CLI/CLI/MainService.Native.cs | 29 + src/Neo.CLI/CLI/MainService.Network.cs | 164 ++ src/Neo.CLI/CLI/MainService.Node.cs | 118 ++ src/Neo.CLI/CLI/MainService.Plugins.cs | 244 +++ src/Neo.CLI/CLI/MainService.Tools.cs | 462 +++++ src/Neo.CLI/CLI/MainService.Vote.cs | 239 +++ src/Neo.CLI/CLI/MainService.Wallet.cs | 743 ++++++++ src/Neo.CLI/CLI/MainService.cs | 609 +++++++ src/Neo.CLI/Dockerfile | 20 + src/Neo.CLI/Extensions.cs | 28 + src/Neo.CLI/Neo.CLI.csproj | 29 + src/Neo.CLI/Program.cs | 23 + src/Neo.CLI/Settings.cs | 120 ++ src/Neo.CLI/config.fs.mainnet.json | 53 + src/Neo.CLI/config.fs.testnet.json | 53 + src/Neo.CLI/config.json | 69 + src/Neo.CLI/config.mainnet.json | 69 + src/Neo.CLI/config.testnet.json | 69 + src/Neo.CLI/neo.ico | Bin 0 -> 21317 bytes src/Neo.ConsoleService/CommandQuoteToken.cs | 53 + src/Neo.ConsoleService/CommandSpaceToken.cs | 64 + src/Neo.ConsoleService/CommandStringToken.cs | 90 + src/Neo.ConsoleService/CommandToken.cs | 225 +++ src/Neo.ConsoleService/CommandTokenType.cs | 19 + src/Neo.ConsoleService/ConsoleColorSet.cs | 51 + .../ConsoleCommandAttribute.cs | 45 + .../ConsoleCommandMethod.cs | 120 ++ src/Neo.ConsoleService/ConsoleHelper.cs | 65 + src/Neo.ConsoleService/ConsoleServiceBase.cs | 627 +++++++ .../Neo.ConsoleService.csproj | 12 + .../Properties/AssemblyInfo.cs | 13 + src/Neo.ConsoleService/ServiceProxy.cs | 34 + src/Neo.GUI/GUI/BulkPayDialog.Designer.cs | 129 ++ src/Neo.GUI/GUI/BulkPayDialog.cs | 80 + src/Neo.GUI/GUI/BulkPayDialog.es-ES.resx | 148 ++ src/Neo.GUI/GUI/BulkPayDialog.resx | 354 ++++ src/Neo.GUI/GUI/BulkPayDialog.zh-Hans.resx | 157 ++ .../GUI/ChangePasswordDialog.Designer.cs | 137 ++ src/Neo.GUI/GUI/ChangePasswordDialog.cs | 53 + .../GUI/ChangePasswordDialog.es-ES.resx | 181 ++ src/Neo.GUI/GUI/ChangePasswordDialog.resx | 369 ++++ .../GUI/ChangePasswordDialog.zh-Hans.resx | 172 ++ src/Neo.GUI/GUI/ConsoleForm.Designer.cs | 91 + src/Neo.GUI/GUI/ConsoleForm.cs | 67 + src/Neo.GUI/GUI/ConsoleForm.resx | 120 ++ .../CreateMultiSigContractDialog.Designer.cs | 153 ++ .../GUI/CreateMultiSigContractDialog.cs | 71 + .../CreateMultiSigContractDialog.es-ES.resx | 179 ++ .../GUI/CreateMultiSigContractDialog.resx | 399 +++++ .../CreateMultiSigContractDialog.zh-Hans.resx | 178 ++ src/Neo.GUI/GUI/CreateWalletDialog.cs | 71 + .../GUI/CreateWalletDialog.designer.cs | 143 ++ src/Neo.GUI/GUI/CreateWalletDialog.es-ES.resx | 169 ++ src/Neo.GUI/GUI/CreateWalletDialog.resx | 363 ++++ .../GUI/CreateWalletDialog.zh-Hans.resx | 181 ++ .../GUI/DeployContractDialog.Designer.cs | 308 ++++ src/Neo.GUI/GUI/DeployContractDialog.cs | 60 + .../GUI/DeployContractDialog.es-ES.resx | 217 +++ src/Neo.GUI/GUI/DeployContractDialog.resx | 972 +++++++++++ .../GUI/DeployContractDialog.zh-Hans.resx | 259 +++ .../DeveloperToolsForm.ContractParameters.cs | 117 ++ .../GUI/DeveloperToolsForm.Designer.cs | 259 +++ .../GUI/DeveloperToolsForm.TxBuilder.cs | 36 + src/Neo.GUI/GUI/DeveloperToolsForm.cs | 23 + src/Neo.GUI/GUI/DeveloperToolsForm.es-ES.resx | 153 ++ src/Neo.GUI/GUI/DeveloperToolsForm.resx | 669 ++++++++ .../GUI/DeveloperToolsForm.zh-Hans.resx | 153 ++ src/Neo.GUI/GUI/ElectionDialog.Designer.cs | 92 + src/Neo.GUI/GUI/ElectionDialog.cs | 51 + src/Neo.GUI/GUI/ElectionDialog.es-ES.resx | 123 ++ src/Neo.GUI/GUI/ElectionDialog.resx | 231 +++ src/Neo.GUI/GUI/ElectionDialog.zh-Hans.resx | 146 ++ src/Neo.GUI/GUI/Helper.cs | 74 + .../ImportCustomContractDialog.Designer.cs | 137 ++ src/Neo.GUI/GUI/ImportCustomContractDialog.cs | 53 + .../GUI/ImportCustomContractDialog.es-ES.resx | 154 ++ .../GUI/ImportCustomContractDialog.resx | 366 ++++ .../ImportCustomContractDialog.zh-Hans.resx | 160 ++ src/Neo.GUI/GUI/ImportPrivateKeyDialog.cs | 40 + .../GUI/ImportPrivateKeyDialog.designer.cs | 102 ++ .../GUI/ImportPrivateKeyDialog.es-ES.resx | 136 ++ src/Neo.GUI/GUI/ImportPrivateKeyDialog.resx | 267 +++ .../GUI/ImportPrivateKeyDialog.zh-Hans.resx | 132 ++ src/Neo.GUI/GUI/InformationBox.Designer.cs | 100 ++ src/Neo.GUI/GUI/InformationBox.cs | 43 + src/Neo.GUI/GUI/InformationBox.es-ES.resx | 129 ++ src/Neo.GUI/GUI/InformationBox.resx | 255 +++ src/Neo.GUI/GUI/InformationBox.zh-Hans.resx | 126 ++ src/Neo.GUI/GUI/InputBox.Designer.cs | 102 ++ src/Neo.GUI/GUI/InputBox.cs | 32 + src/Neo.GUI/GUI/InputBox.es-ES.resx | 126 ++ src/Neo.GUI/GUI/InputBox.resx | 249 +++ src/Neo.GUI/GUI/InputBox.zh-Hans.resx | 126 ++ .../GUI/InvokeContractDialog.Designer.cs | 270 +++ src/Neo.GUI/GUI/InvokeContractDialog.cs | 145 ++ .../GUI/InvokeContractDialog.es-ES.resx | 154 ++ src/Neo.GUI/GUI/InvokeContractDialog.resx | 735 ++++++++ .../GUI/InvokeContractDialog.zh-Hans.resx | 184 ++ src/Neo.GUI/GUI/MainForm.Designer.cs | 732 ++++++++ src/Neo.GUI/GUI/MainForm.cs | 615 +++++++ src/Neo.GUI/GUI/MainForm.es-ES.resx | 437 +++++ src/Neo.GUI/GUI/MainForm.resx | 1488 +++++++++++++++++ src/Neo.GUI/GUI/MainForm.zh-Hans.resx | 445 +++++ src/Neo.GUI/GUI/OpenWalletDialog.cs | 65 + src/Neo.GUI/GUI/OpenWalletDialog.designer.cs | 125 ++ src/Neo.GUI/GUI/OpenWalletDialog.es-ES.resx | 151 ++ src/Neo.GUI/GUI/OpenWalletDialog.resx | 315 ++++ src/Neo.GUI/GUI/OpenWalletDialog.zh-Hans.resx | 157 ++ src/Neo.GUI/GUI/ParametersEditor.Designer.cs | 200 +++ src/Neo.GUI/GUI/ParametersEditor.cs | 197 +++ src/Neo.GUI/GUI/ParametersEditor.es-ES.resx | 141 ++ src/Neo.GUI/GUI/ParametersEditor.resx | 489 ++++++ src/Neo.GUI/GUI/ParametersEditor.zh-Hans.resx | 144 ++ src/Neo.GUI/GUI/PayToDialog.Designer.cs | 142 ++ src/Neo.GUI/GUI/PayToDialog.cs | 105 ++ src/Neo.GUI/GUI/PayToDialog.es-ES.resx | 163 ++ src/Neo.GUI/GUI/PayToDialog.resx | 384 +++++ src/Neo.GUI/GUI/PayToDialog.zh-Hans.resx | 193 +++ src/Neo.GUI/GUI/QueueReader.cs | 48 + src/Neo.GUI/GUI/SigningDialog.Designer.cs | 172 ++ src/Neo.GUI/GUI/SigningDialog.cs | 106 ++ src/Neo.GUI/GUI/SigningDialog.es-ES.resx | 141 ++ src/Neo.GUI/GUI/SigningDialog.resx | 462 +++++ src/Neo.GUI/GUI/SigningDialog.zh-Hans.resx | 151 ++ src/Neo.GUI/GUI/SigningTxDialog.Designer.cs | 142 ++ src/Neo.GUI/GUI/SigningTxDialog.cs | 66 + src/Neo.GUI/GUI/SigningTxDialog.es-ES.resx | 141 ++ src/Neo.GUI/GUI/SigningTxDialog.resx | 372 +++++ src/Neo.GUI/GUI/SigningTxDialog.zh-Hans.resx | 141 ++ src/Neo.GUI/GUI/TextBoxWriter.cs | 39 + src/Neo.GUI/GUI/TransferDialog.Designer.cs | 131 ++ src/Neo.GUI/GUI/TransferDialog.cs | 41 + src/Neo.GUI/GUI/TransferDialog.es-ES.resx | 132 ++ src/Neo.GUI/GUI/TransferDialog.resx | 369 ++++ src/Neo.GUI/GUI/TransferDialog.zh-Hans.resx | 142 ++ src/Neo.GUI/GUI/TxOutListBox.Designer.cs | 109 ++ src/Neo.GUI/GUI/TxOutListBox.cs | 102 ++ src/Neo.GUI/GUI/TxOutListBox.resx | 300 ++++ src/Neo.GUI/GUI/TxOutListBoxItem.cs | 24 + src/Neo.GUI/GUI/UpdateDialog.Designer.cs | 149 ++ src/Neo.GUI/GUI/UpdateDialog.cs | 76 + src/Neo.GUI/GUI/UpdateDialog.es-ES.resx | 157 ++ src/Neo.GUI/GUI/UpdateDialog.resx | 399 +++++ src/Neo.GUI/GUI/UpdateDialog.zh-Hans.resx | 160 ++ .../GUI/ViewContractDialog.Designer.cs | 143 ++ src/Neo.GUI/GUI/ViewContractDialog.cs | 29 + src/Neo.GUI/GUI/ViewContractDialog.es-ES.resx | 187 +++ src/Neo.GUI/GUI/ViewContractDialog.resx | 387 +++++ .../GUI/ViewContractDialog.zh-Hans.resx | 172 ++ src/Neo.GUI/GUI/ViewPrivateKeyDialog.cs | 28 + .../GUI/ViewPrivateKeyDialog.designer.cs | 155 ++ .../GUI/ViewPrivateKeyDialog.es-ES.resx | 160 ++ src/Neo.GUI/GUI/ViewPrivateKeyDialog.resx | 408 +++++ .../GUI/ViewPrivateKeyDialog.zh-Hans.resx | 178 ++ src/Neo.GUI/GUI/VotingDialog.Designer.cs | 111 ++ src/Neo.GUI/GUI/VotingDialog.cs | 53 + src/Neo.GUI/GUI/VotingDialog.es-ES.resx | 132 ++ src/Neo.GUI/GUI/VotingDialog.resx | 300 ++++ src/Neo.GUI/GUI/VotingDialog.zh-Hans.resx | 132 ++ src/Neo.GUI/GUI/Wrappers/HexConverter.cs | 48 + src/Neo.GUI/GUI/Wrappers/ScriptEditor.cs | 35 + src/Neo.GUI/GUI/Wrappers/SignerWrapper.cs | 37 + .../Wrappers/TransactionAttributeWrapper.cs | 29 + .../GUI/Wrappers/TransactionWrapper.cs | 58 + src/Neo.GUI/GUI/Wrappers/UIntBaseConverter.cs | 53 + src/Neo.GUI/GUI/Wrappers/WitnessWrapper.cs | 35 + src/Neo.GUI/IO/Actors/EventWrapper.cs | 42 + src/Neo.GUI/Neo.GUI.csproj | 55 + src/Neo.GUI/Program.cs | 95 ++ src/Neo.GUI/Properties/Resources.Designer.cs | 133 ++ src/Neo.GUI/Properties/Resources.resx | 139 ++ src/Neo.GUI/Properties/Strings.Designer.cs | 542 ++++++ src/Neo.GUI/Properties/Strings.es-Es.resx | 259 +++ src/Neo.GUI/Properties/Strings.resx | 277 +++ src/Neo.GUI/Properties/Strings.zh-Hans.resx | 277 +++ src/Neo.GUI/Resources/add.png | Bin 0 -> 299 bytes src/Neo.GUI/Resources/add2.png | Bin 0 -> 419 bytes src/Neo.GUI/Resources/remark.png | Bin 0 -> 386 bytes src/Neo.GUI/Resources/remove.png | Bin 0 -> 291 bytes src/Neo.GUI/Resources/search.png | Bin 0 -> 442 bytes src/Neo.GUI/Resources/update.bat | 13 + .../CommandTokenTest.cs | 92 + .../Neo.ConsoleService.Tests.csproj | 10 + 190 files changed, 33306 insertions(+) create mode 100644 src/Neo.CLI/CLI/ConsolePercent.cs create mode 100644 src/Neo.CLI/CLI/Helper.cs create mode 100644 src/Neo.CLI/CLI/MainService.Blockchain.cs create mode 100644 src/Neo.CLI/CLI/MainService.Contracts.cs create mode 100644 src/Neo.CLI/CLI/MainService.Logger.cs create mode 100644 src/Neo.CLI/CLI/MainService.NEP17.cs create mode 100644 src/Neo.CLI/CLI/MainService.Native.cs create mode 100644 src/Neo.CLI/CLI/MainService.Network.cs create mode 100644 src/Neo.CLI/CLI/MainService.Node.cs create mode 100644 src/Neo.CLI/CLI/MainService.Plugins.cs create mode 100644 src/Neo.CLI/CLI/MainService.Tools.cs create mode 100644 src/Neo.CLI/CLI/MainService.Vote.cs create mode 100644 src/Neo.CLI/CLI/MainService.Wallet.cs create mode 100644 src/Neo.CLI/CLI/MainService.cs create mode 100644 src/Neo.CLI/Dockerfile create mode 100644 src/Neo.CLI/Extensions.cs create mode 100644 src/Neo.CLI/Neo.CLI.csproj create mode 100644 src/Neo.CLI/Program.cs create mode 100644 src/Neo.CLI/Settings.cs create mode 100644 src/Neo.CLI/config.fs.mainnet.json create mode 100644 src/Neo.CLI/config.fs.testnet.json create mode 100644 src/Neo.CLI/config.json create mode 100644 src/Neo.CLI/config.mainnet.json create mode 100644 src/Neo.CLI/config.testnet.json create mode 100644 src/Neo.CLI/neo.ico create mode 100644 src/Neo.ConsoleService/CommandQuoteToken.cs create mode 100644 src/Neo.ConsoleService/CommandSpaceToken.cs create mode 100644 src/Neo.ConsoleService/CommandStringToken.cs create mode 100644 src/Neo.ConsoleService/CommandToken.cs create mode 100644 src/Neo.ConsoleService/CommandTokenType.cs create mode 100644 src/Neo.ConsoleService/ConsoleColorSet.cs create mode 100644 src/Neo.ConsoleService/ConsoleCommandAttribute.cs create mode 100644 src/Neo.ConsoleService/ConsoleCommandMethod.cs create mode 100644 src/Neo.ConsoleService/ConsoleHelper.cs create mode 100644 src/Neo.ConsoleService/ConsoleServiceBase.cs create mode 100644 src/Neo.ConsoleService/Neo.ConsoleService.csproj create mode 100644 src/Neo.ConsoleService/Properties/AssemblyInfo.cs create mode 100644 src/Neo.ConsoleService/ServiceProxy.cs create mode 100644 src/Neo.GUI/GUI/BulkPayDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/BulkPayDialog.cs create mode 100644 src/Neo.GUI/GUI/BulkPayDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/BulkPayDialog.resx create mode 100644 src/Neo.GUI/GUI/BulkPayDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/ChangePasswordDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/ChangePasswordDialog.cs create mode 100644 src/Neo.GUI/GUI/ChangePasswordDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/ChangePasswordDialog.resx create mode 100644 src/Neo.GUI/GUI/ChangePasswordDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/ConsoleForm.Designer.cs create mode 100644 src/Neo.GUI/GUI/ConsoleForm.cs create mode 100644 src/Neo.GUI/GUI/ConsoleForm.resx create mode 100644 src/Neo.GUI/GUI/CreateMultiSigContractDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/CreateMultiSigContractDialog.cs create mode 100644 src/Neo.GUI/GUI/CreateMultiSigContractDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/CreateMultiSigContractDialog.resx create mode 100644 src/Neo.GUI/GUI/CreateMultiSigContractDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/CreateWalletDialog.cs create mode 100644 src/Neo.GUI/GUI/CreateWalletDialog.designer.cs create mode 100644 src/Neo.GUI/GUI/CreateWalletDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/CreateWalletDialog.resx create mode 100644 src/Neo.GUI/GUI/CreateWalletDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/DeployContractDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/DeployContractDialog.cs create mode 100644 src/Neo.GUI/GUI/DeployContractDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/DeployContractDialog.resx create mode 100644 src/Neo.GUI/GUI/DeployContractDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/DeveloperToolsForm.ContractParameters.cs create mode 100644 src/Neo.GUI/GUI/DeveloperToolsForm.Designer.cs create mode 100644 src/Neo.GUI/GUI/DeveloperToolsForm.TxBuilder.cs create mode 100644 src/Neo.GUI/GUI/DeveloperToolsForm.cs create mode 100644 src/Neo.GUI/GUI/DeveloperToolsForm.es-ES.resx create mode 100644 src/Neo.GUI/GUI/DeveloperToolsForm.resx create mode 100644 src/Neo.GUI/GUI/DeveloperToolsForm.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/ElectionDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/ElectionDialog.cs create mode 100644 src/Neo.GUI/GUI/ElectionDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/ElectionDialog.resx create mode 100644 src/Neo.GUI/GUI/ElectionDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/Helper.cs create mode 100644 src/Neo.GUI/GUI/ImportCustomContractDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/ImportCustomContractDialog.cs create mode 100644 src/Neo.GUI/GUI/ImportCustomContractDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/ImportCustomContractDialog.resx create mode 100644 src/Neo.GUI/GUI/ImportCustomContractDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/ImportPrivateKeyDialog.cs create mode 100644 src/Neo.GUI/GUI/ImportPrivateKeyDialog.designer.cs create mode 100644 src/Neo.GUI/GUI/ImportPrivateKeyDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/ImportPrivateKeyDialog.resx create mode 100644 src/Neo.GUI/GUI/ImportPrivateKeyDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/InformationBox.Designer.cs create mode 100644 src/Neo.GUI/GUI/InformationBox.cs create mode 100644 src/Neo.GUI/GUI/InformationBox.es-ES.resx create mode 100644 src/Neo.GUI/GUI/InformationBox.resx create mode 100644 src/Neo.GUI/GUI/InformationBox.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/InputBox.Designer.cs create mode 100644 src/Neo.GUI/GUI/InputBox.cs create mode 100644 src/Neo.GUI/GUI/InputBox.es-ES.resx create mode 100644 src/Neo.GUI/GUI/InputBox.resx create mode 100644 src/Neo.GUI/GUI/InputBox.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/InvokeContractDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/InvokeContractDialog.cs create mode 100644 src/Neo.GUI/GUI/InvokeContractDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/InvokeContractDialog.resx create mode 100644 src/Neo.GUI/GUI/InvokeContractDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/MainForm.Designer.cs create mode 100644 src/Neo.GUI/GUI/MainForm.cs create mode 100644 src/Neo.GUI/GUI/MainForm.es-ES.resx create mode 100644 src/Neo.GUI/GUI/MainForm.resx create mode 100644 src/Neo.GUI/GUI/MainForm.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/OpenWalletDialog.cs create mode 100644 src/Neo.GUI/GUI/OpenWalletDialog.designer.cs create mode 100644 src/Neo.GUI/GUI/OpenWalletDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/OpenWalletDialog.resx create mode 100644 src/Neo.GUI/GUI/OpenWalletDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/ParametersEditor.Designer.cs create mode 100644 src/Neo.GUI/GUI/ParametersEditor.cs create mode 100644 src/Neo.GUI/GUI/ParametersEditor.es-ES.resx create mode 100644 src/Neo.GUI/GUI/ParametersEditor.resx create mode 100644 src/Neo.GUI/GUI/ParametersEditor.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/PayToDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/PayToDialog.cs create mode 100644 src/Neo.GUI/GUI/PayToDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/PayToDialog.resx create mode 100644 src/Neo.GUI/GUI/PayToDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/QueueReader.cs create mode 100644 src/Neo.GUI/GUI/SigningDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/SigningDialog.cs create mode 100644 src/Neo.GUI/GUI/SigningDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/SigningDialog.resx create mode 100644 src/Neo.GUI/GUI/SigningDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/SigningTxDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/SigningTxDialog.cs create mode 100644 src/Neo.GUI/GUI/SigningTxDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/SigningTxDialog.resx create mode 100644 src/Neo.GUI/GUI/SigningTxDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/TextBoxWriter.cs create mode 100644 src/Neo.GUI/GUI/TransferDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/TransferDialog.cs create mode 100644 src/Neo.GUI/GUI/TransferDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/TransferDialog.resx create mode 100644 src/Neo.GUI/GUI/TransferDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/TxOutListBox.Designer.cs create mode 100644 src/Neo.GUI/GUI/TxOutListBox.cs create mode 100644 src/Neo.GUI/GUI/TxOutListBox.resx create mode 100644 src/Neo.GUI/GUI/TxOutListBoxItem.cs create mode 100644 src/Neo.GUI/GUI/UpdateDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/UpdateDialog.cs create mode 100644 src/Neo.GUI/GUI/UpdateDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/UpdateDialog.resx create mode 100644 src/Neo.GUI/GUI/UpdateDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/ViewContractDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/ViewContractDialog.cs create mode 100644 src/Neo.GUI/GUI/ViewContractDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/ViewContractDialog.resx create mode 100644 src/Neo.GUI/GUI/ViewContractDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/ViewPrivateKeyDialog.cs create mode 100644 src/Neo.GUI/GUI/ViewPrivateKeyDialog.designer.cs create mode 100644 src/Neo.GUI/GUI/ViewPrivateKeyDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/ViewPrivateKeyDialog.resx create mode 100644 src/Neo.GUI/GUI/ViewPrivateKeyDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/VotingDialog.Designer.cs create mode 100644 src/Neo.GUI/GUI/VotingDialog.cs create mode 100644 src/Neo.GUI/GUI/VotingDialog.es-ES.resx create mode 100644 src/Neo.GUI/GUI/VotingDialog.resx create mode 100644 src/Neo.GUI/GUI/VotingDialog.zh-Hans.resx create mode 100644 src/Neo.GUI/GUI/Wrappers/HexConverter.cs create mode 100644 src/Neo.GUI/GUI/Wrappers/ScriptEditor.cs create mode 100644 src/Neo.GUI/GUI/Wrappers/SignerWrapper.cs create mode 100644 src/Neo.GUI/GUI/Wrappers/TransactionAttributeWrapper.cs create mode 100644 src/Neo.GUI/GUI/Wrappers/TransactionWrapper.cs create mode 100644 src/Neo.GUI/GUI/Wrappers/UIntBaseConverter.cs create mode 100644 src/Neo.GUI/GUI/Wrappers/WitnessWrapper.cs create mode 100644 src/Neo.GUI/IO/Actors/EventWrapper.cs create mode 100644 src/Neo.GUI/Neo.GUI.csproj create mode 100644 src/Neo.GUI/Program.cs create mode 100644 src/Neo.GUI/Properties/Resources.Designer.cs create mode 100644 src/Neo.GUI/Properties/Resources.resx create mode 100644 src/Neo.GUI/Properties/Strings.Designer.cs create mode 100644 src/Neo.GUI/Properties/Strings.es-Es.resx create mode 100644 src/Neo.GUI/Properties/Strings.resx create mode 100644 src/Neo.GUI/Properties/Strings.zh-Hans.resx create mode 100644 src/Neo.GUI/Resources/add.png create mode 100644 src/Neo.GUI/Resources/add2.png create mode 100644 src/Neo.GUI/Resources/remark.png create mode 100644 src/Neo.GUI/Resources/remove.png create mode 100644 src/Neo.GUI/Resources/search.png create mode 100644 src/Neo.GUI/Resources/update.bat create mode 100644 tests/Neo.ConsoleService.Tests/CommandTokenTest.cs create mode 100644 tests/Neo.ConsoleService.Tests/Neo.ConsoleService.Tests.csproj diff --git a/neo.sln b/neo.sln index 827bddc1b2..2168c241b3 100644 --- a/neo.sln +++ b/neo.sln @@ -24,6 +24,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.VM", "src\Neo.VM\Neo.VM EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.VM.Tests", "tests\Neo.VM.Tests\Neo.VM.Tests.csproj", "{005F84EB-EA2E-449F-930A-7B4173DDC7EC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.ConsoleService", "src\Neo.ConsoleService\Neo.ConsoleService.csproj", "{9E886812-7243-48D8-BEAF-47AADC11C054}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.GUI", "src\Neo.GUI\Neo.GUI.csproj", "{02ABDE42-9880-43B4-B6F7-8D618602A277}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.CLI", "src\Neo.CLI\Neo.CLI.csproj", "{BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.ConsoleService.Tests", "tests\Neo.ConsoleService.Tests\Neo.ConsoleService.Tests.csproj", "{B40F8584-5AFB-452C-AEFA-009C80CC23A9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -62,6 +70,22 @@ Global {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Debug|Any CPU.Build.0 = Debug|Any CPU {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|Any CPU.ActiveCfg = Release|Any CPU {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|Any CPU.Build.0 = Release|Any CPU + {9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E886812-7243-48D8-BEAF-47AADC11C054}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E886812-7243-48D8-BEAF-47AADC11C054}.Release|Any CPU.Build.0 = Release|Any CPU + {02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|Any CPU.Build.0 = Release|Any CPU + {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|Any CPU.Build.0 = Release|Any CPU + {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -75,6 +99,10 @@ Global {E83633BA-FCF0-4A1A-B5BC-42000E24D437} = {C25EB0B0-0CAC-4CC1-8F36-F9229EFB99EC} {0603710E-E0BA-494C-AA0F-6FB0C8A8C754} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} {005F84EB-EA2E-449F-930A-7B4173DDC7EC} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1} + {9E886812-7243-48D8-BEAF-47AADC11C054} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} + {02ABDE42-9880-43B4-B6F7-8D618602A277} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} + {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} + {B40F8584-5AFB-452C-AEFA-009C80CC23A9} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BCBA19D9-F868-4C6D-8061-A2B91E06E3EC} diff --git a/src/Neo.CLI/CLI/ConsolePercent.cs b/src/Neo.CLI/CLI/ConsolePercent.cs new file mode 100644 index 0000000000..09077f2503 --- /dev/null +++ b/src/Neo.CLI/CLI/ConsolePercent.cs @@ -0,0 +1,145 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; + +namespace Neo.CLI +{ + public class ConsolePercent : IDisposable + { + #region Variables + + private readonly long _maxValue; + private long _value; + private decimal _lastFactor; + private string _lastPercent; + + private readonly int _x, _y; + + private bool _inputRedirected; + + #endregion + + #region Properties + + /// + /// Value + /// + public long Value + { + get => _value; + set + { + if (value == _value) return; + + _value = Math.Min(value, _maxValue); + Invalidate(); + } + } + + /// + /// Maximum value + /// + public long MaxValue + { + get => _maxValue; + init + { + if (value == _maxValue) return; + + _maxValue = value; + + if (_value > _maxValue) + _value = _maxValue; + + Invalidate(); + } + } + + /// + /// Percent + /// + public decimal Percent + { + get + { + if (_maxValue == 0) return 0; + return (_value * 100M) / _maxValue; + } + } + + #endregion + + /// + /// Constructor + /// + /// Value + /// Maximum value + public ConsolePercent(long value = 0, long maxValue = 100) + { + _inputRedirected = Console.IsInputRedirected; + _lastFactor = -1; + _x = _inputRedirected ? 0 : Console.CursorLeft; + _y = _inputRedirected ? 0 : Console.CursorTop; + + MaxValue = maxValue; + Value = value; + Invalidate(); + } + + /// + /// Invalidate + /// + public void Invalidate() + { + var factor = Math.Round((Percent / 100M), 1); + var percent = Percent.ToString("0.0").PadLeft(5, ' '); + + if (_lastFactor == factor && _lastPercent == percent) + { + return; + } + + _lastFactor = factor; + _lastPercent = percent; + + var fill = string.Empty.PadLeft((int)(10 * factor), '■'); + var clean = string.Empty.PadLeft(10 - fill.Length, _inputRedirected ? '□' : '■'); + + if (_inputRedirected) + { + Console.WriteLine("[" + fill + clean + "] (" + percent + "%)"); + } + else + { + Console.SetCursorPosition(_x, _y); + + var prevColor = Console.ForegroundColor; + + Console.ForegroundColor = ConsoleColor.White; + Console.Write("["); + Console.ForegroundColor = Percent > 50 ? ConsoleColor.Green : ConsoleColor.DarkGreen; + Console.Write(fill); + Console.ForegroundColor = ConsoleColor.White; + Console.Write(clean + "] (" + percent + "%)"); + + Console.ForegroundColor = prevColor; + } + } + + /// + /// Free console + /// + public void Dispose() + { + Console.WriteLine(""); + } + } +} diff --git a/src/Neo.CLI/CLI/Helper.cs b/src/Neo.CLI/CLI/Helper.cs new file mode 100644 index 0000000000..d0bc4e8d34 --- /dev/null +++ b/src/Neo.CLI/CLI/Helper.cs @@ -0,0 +1,41 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using Neo.SmartContract.Manifest; + +namespace Neo.CLI +{ + internal static class Helper + { + public static bool IsYes(this string input) + { + if (input == null) return false; + + input = input.ToLowerInvariant(); + + return input == "yes" || input == "y"; + } + + public static string ToBase64String(this byte[] input) => System.Convert.ToBase64String(input); + + public static void IsScriptValid(this ReadOnlyMemory script, ContractAbi abi) + { + try + { + SmartContract.Helper.Check(script.ToArray(), abi); + } + catch (Exception e) + { + throw new FormatException($"Bad Script or Manifest Format: {e.Message}"); + } + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Blockchain.cs b/src/Neo.CLI/CLI/MainService.Blockchain.cs new file mode 100644 index 0000000000..d363688701 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Blockchain.cs @@ -0,0 +1,45 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.ConsoleService; +using Neo.SmartContract.Native; +using System; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "export blocks" command + /// + /// Start + /// Number of blocks + /// Path + [ConsoleCommand("export blocks", Category = "Blockchain Commands")] + private void OnExportBlocksStartCountCommand(uint start, uint count = uint.MaxValue, string path = null) + { + uint height = NativeContract.Ledger.CurrentIndex(NeoSystem.StoreView); + if (height < start) + { + ConsoleHelper.Error("invalid start height."); + return; + } + + count = Math.Min(count, height - start + 1); + + if (string.IsNullOrEmpty(path)) + { + path = $"chain.{start}.acc"; + } + + WriteBlocks(start, count, path, true); + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Contracts.cs b/src/Neo.CLI/CLI/MainService.Contracts.cs new file mode 100644 index 0000000000..77b4a77219 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Contracts.cs @@ -0,0 +1,182 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.ConsoleService; +using Neo.Json; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using System; +using System.Linq; +using System.Numerics; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "deploy" command + /// + /// File path + /// Manifest path + /// Extra data for deploy + [ConsoleCommand("deploy", Category = "Contract Commands")] + private void OnDeployCommand(string filePath, string manifestPath = null, JObject data = null) + { + if (NoWallet()) return; + byte[] script = LoadDeploymentScript(filePath, manifestPath, data, out var nef, out var manifest); + Transaction tx; + try + { + tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, script); + } + catch (InvalidOperationException e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + return; + } + UInt160 hash = SmartContract.Helper.GetContractHash(tx.Sender, nef.CheckSum, manifest.Name); + + ConsoleHelper.Info("Contract hash: ", $"{hash}"); + ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)}"); + ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}"); + ConsoleHelper.Info("Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); + if (!ReadUserInput("Relay tx? (no|yes)").IsYes()) // Add this in case just want to get hash but not relay + { + return; + } + SignAndSendTx(NeoSystem.StoreView, tx); + } + + /// + /// Process "update" command + /// + /// Script hash + /// File path + /// Manifest path + /// Sender + /// Signer Accounts + /// Extra data for update + [ConsoleCommand("update", Category = "Contract Commands")] + private void OnUpdateCommand(UInt160 scriptHash, string filePath, string manifestPath, UInt160 sender, UInt160[] signerAccounts = null, JObject data = null) + { + Signer[] signers = Array.Empty(); + + if (NoWallet()) return; + if (sender != null) + { + if (signerAccounts == null) + signerAccounts = new[] { sender }; + else if (signerAccounts.Contains(sender) && signerAccounts[0] != sender) + { + var signersList = signerAccounts.ToList(); + signersList.Remove(sender); + signerAccounts = signersList.Prepend(sender).ToArray(); + } + else if (!signerAccounts.Contains(sender)) + { + signerAccounts = signerAccounts.Prepend(sender).ToArray(); + } + signers = signerAccounts.Select(p => new Signer() { Account = p, Scopes = WitnessScope.CalledByEntry }).ToArray(); + } + + Transaction tx; + try + { + byte[] script = LoadUpdateScript(scriptHash, filePath, manifestPath, data, out var nef, out var manifest); + tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, script, sender, signers); + } + catch (InvalidOperationException e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + return; + } + ContractState contract = NativeContract.ContractManagement.GetContract(NeoSystem.StoreView, scriptHash); + if (contract == null) + { + ConsoleHelper.Warning($"Can't upgrade, contract hash not exist: {scriptHash}"); + } + else + { + ConsoleHelper.Info("Contract hash: ", $"{scriptHash}"); + ConsoleHelper.Info("Updated times: ", $"{contract.UpdateCounter}"); + ConsoleHelper.Info("Gas consumed: ", $"{new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals)}"); + ConsoleHelper.Info("Network fee: ", $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}"); + ConsoleHelper.Info("Total fee: ", $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); + if (!ReadUserInput("Relay tx? (no|yes)").IsYes()) // Add this in case just want to get hash but not relay + { + return; + } + SignAndSendTx(NeoSystem.StoreView, tx); + } + } + + /// + /// Process "invoke" command + /// + /// Script hash + /// Operation + /// Contract parameters + /// Transaction's sender + /// Signer's accounts + /// Max fee for running the script + [ConsoleCommand("invoke", Category = "Contract Commands")] + private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160 sender = null, UInt160[] signerAccounts = null, decimal maxGas = 20) + { + var gas = new BigDecimal(maxGas, NativeContract.GAS.Decimals); + Signer[] signers = Array.Empty(); + if (!NoWallet() && sender != null) + { + if (signerAccounts == null) + signerAccounts = new UInt160[1] { sender }; + else if (signerAccounts.Contains(sender) && signerAccounts[0] != sender) + { + var signersList = signerAccounts.ToList(); + signersList.Remove(sender); + signerAccounts = signersList.Prepend(sender).ToArray(); + } + else if (!signerAccounts.Contains(sender)) + { + signerAccounts = signerAccounts.Prepend(sender).ToArray(); + } + signers = signerAccounts.Select(p => new Signer() { Account = p, Scopes = WitnessScope.CalledByEntry }).ToArray(); + } + + Transaction tx = new Transaction + { + Signers = signers, + Attributes = Array.Empty(), + Witnesses = Array.Empty(), + }; + + if (!OnInvokeWithResult(scriptHash, operation, out _, tx, contractParameters, gas: (long)gas.Value)) return; + + if (NoWallet()) return; + try + { + tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, tx.Script, sender, signers, maxGas: (long)gas.Value); + } + catch (InvalidOperationException e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + return; + } + ConsoleHelper.Info("Network fee: ", + $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}\t", + "Total fee: ", + $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); + if (!ReadUserInput("Relay tx? (no|yes)").IsYes()) + { + return; + } + SignAndSendTx(NeoSystem.StoreView, tx); + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Logger.cs b/src/Neo.CLI/CLI/MainService.Logger.cs new file mode 100644 index 0000000000..6624f931a6 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Logger.cs @@ -0,0 +1,171 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.ConsoleService; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using static System.IO.Path; + +namespace Neo.CLI +{ + partial class MainService + { + private static readonly ConsoleColorSet DebugColor = new(ConsoleColor.Cyan); + private static readonly ConsoleColorSet InfoColor = new(ConsoleColor.White); + private static readonly ConsoleColorSet WarningColor = new(ConsoleColor.Yellow); + private static readonly ConsoleColorSet ErrorColor = new(ConsoleColor.Red); + private static readonly ConsoleColorSet FatalColor = new(ConsoleColor.Red); + + private readonly object syncRoot = new(); + private bool _showLog = Settings.Default.Logger.ConsoleOutput; + + private void Initialize_Logger() + { + Utility.Logging += OnLog; + } + + private void Dispose_Logger() + { + Utility.Logging -= OnLog; + } + + /// + /// Process "console log off" command to turn off console log + /// + [ConsoleCommand("console log off", Category = "Log Commands")] + private void OnLogOffCommand() + { + _showLog = false; + } + + /// + /// Process "console log on" command to turn on the console log + /// + [ConsoleCommand("console log on", Category = "Log Commands")] + private void OnLogOnCommand() + { + _showLog = true; + } + + private static void GetErrorLogs(StringBuilder sb, Exception ex) + { + sb.AppendLine(ex.GetType().ToString()); + sb.AppendLine(ex.Message); + sb.AppendLine(ex.StackTrace); + if (ex is AggregateException ex2) + { + foreach (Exception inner in ex2.InnerExceptions) + { + sb.AppendLine(); + GetErrorLogs(sb, inner); + } + } + else if (ex.InnerException != null) + { + sb.AppendLine(); + GetErrorLogs(sb, ex.InnerException); + } + } + + private void OnLog(string source, LogLevel level, object message) + { + if (!Settings.Default.Logger.Active) + return; + + if (message is Exception ex) + { + var sb = new StringBuilder(); + GetErrorLogs(sb, ex); + message = sb.ToString(); + } + + lock (syncRoot) + { + DateTime now = DateTime.Now; + var log = $"[{now.TimeOfDay:hh\\:mm\\:ss\\.fff}]"; + if (_showLog) + { + var currentColor = new ConsoleColorSet(); + var messages = message is string msg ? Parse(msg) : new[] { message.ToString() }; + ConsoleColorSet logColor; + string logLevel; + switch (level) + { + case LogLevel.Debug: logColor = DebugColor; logLevel = "DEBUG"; break; + case LogLevel.Error: logColor = ErrorColor; logLevel = "ERROR"; break; + case LogLevel.Fatal: logColor = FatalColor; logLevel = "FATAL"; break; + case LogLevel.Info: logColor = InfoColor; logLevel = "INFO"; break; + case LogLevel.Warning: logColor = WarningColor; logLevel = "WARN"; break; + default: logColor = InfoColor; logLevel = "INFO"; break; + } + logColor.Apply(); + Console.Write($"{logLevel} {log} \t{messages[0],-20}"); + for (var i = 1; i < messages.Length; i++) + { + if (messages[i].Length > 20) + { + messages[i] = $"{messages[i][..10]}...{messages[i][(messages[i].Length - 10)..]}"; + } + Console.Write(i % 2 == 0 ? $"={messages[i]} " : $" {messages[i]}"); + } + currentColor.Apply(); + Console.WriteLine(); + } + + if (string.IsNullOrEmpty(Settings.Default.Logger.Path)) return; + var sb = new StringBuilder(source); + foreach (var c in GetInvalidFileNameChars()) + sb.Replace(c, '-'); + var path = Combine(Settings.Default.Logger.Path, sb.ToString()); + Directory.CreateDirectory(path); + path = Combine(path, $"{now:yyyy-MM-dd}.log"); + try + { + File.AppendAllLines(path, new[] { $"[{level}]{log} {message}" }); + } + catch (IOException) + { + Console.WriteLine("Error writing the log file: " + path); + } + } + } + + /// + /// Parse the log message + /// + /// expected format [key1 = msg1 key2 = msg2] + /// + private static string[] Parse(string message) + { + var equals = message.Trim().Split('='); + + if (equals.Length == 1) return new[] { message }; + + var messages = new List(); + foreach (var t in @equals) + { + var msg = t.Trim(); + var parts = msg.Split(' '); + var d = parts.Take(parts.Length - 1); + + if (parts.Length > 1) + { + messages.Add(string.Join(" ", d)); + } + messages.Add(parts.LastOrDefault()); + } + + return messages.ToArray(); + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.NEP17.cs b/src/Neo.CLI/CLI/MainService.NEP17.cs new file mode 100644 index 0000000000..34de5e58e5 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.NEP17.cs @@ -0,0 +1,140 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.ConsoleService; +using Neo.Json; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM.Types; +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Linq; +using Array = System.Array; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "transfer" command + /// + /// Script hash + /// To + /// Amount + /// From + /// Data + /// Signer's accounts + [ConsoleCommand("transfer", Category = "NEP17 Commands")] + private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount, UInt160 from = null, string data = null, UInt160[] signersAccounts = null) + { + var snapshot = NeoSystem.StoreView; + var asset = new AssetDescriptor(snapshot, NeoSystem.Settings, tokenHash); + var value = new BigDecimal(amount, asset.Decimals); + + if (NoWallet()) return; + + Transaction tx; + try + { + tx = CurrentWallet.MakeTransaction(snapshot, new[] + { + new TransferOutput + { + AssetId = tokenHash, + Value = value, + ScriptHash = to, + Data = data + } + }, from: from, cosigners: signersAccounts?.Select(p => new Signer + { + // default access for transfers should be valid only for first invocation + Scopes = WitnessScope.CalledByEntry, + Account = p + }) + .ToArray() ?? Array.Empty()); + } + catch (InvalidOperationException e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + return; + } + if (!ReadUserInput("Relay tx(no|yes)").IsYes()) + { + return; + } + SignAndSendTx(snapshot, tx); + } + + /// + /// Process "balanceOf" command + /// + /// Script hash + /// Address + [ConsoleCommand("balanceOf", Category = "NEP17 Commands")] + private void OnBalanceOfCommand(UInt160 tokenHash, UInt160 address) + { + var arg = new JObject + { + ["type"] = "Hash160", + ["value"] = address.ToString() + }; + + var asset = new AssetDescriptor(NeoSystem.StoreView, NeoSystem.Settings, tokenHash); + + if (!OnInvokeWithResult(tokenHash, "balanceOf", out StackItem balanceResult, null, new JArray(arg))) return; + + var balance = new BigDecimal(((PrimitiveType)balanceResult).GetInteger(), asset.Decimals); + + Console.WriteLine(); + ConsoleHelper.Info($"{asset.AssetName} balance: ", $"{balance}"); + } + + /// + /// Process "name" command + /// + /// Script hash + [ConsoleCommand("name", Category = "NEP17 Commands")] + private void OnNameCommand(UInt160 tokenHash) + { + ContractState contract = NativeContract.ContractManagement.GetContract(NeoSystem.StoreView, tokenHash); + if (contract == null) Console.WriteLine($"Contract hash not exist: {tokenHash}"); + else ConsoleHelper.Info("Result: ", contract.Manifest.Name); + } + + /// + /// Process "decimals" command + /// + /// Script hash + [ConsoleCommand("decimals", Category = "NEP17 Commands")] + private void OnDecimalsCommand(UInt160 tokenHash) + { + if (!OnInvokeWithResult(tokenHash, "decimals", out StackItem result)) return; + + ConsoleHelper.Info("Result: ", $"{((PrimitiveType)result).GetInteger()}"); + } + + /// + /// Process "totalSupply" command + /// + /// Script hash + [ConsoleCommand("totalSupply", Category = "NEP17 Commands")] + private void OnTotalSupplyCommand(UInt160 tokenHash) + { + if (!OnInvokeWithResult(tokenHash, "totalSupply", out StackItem result)) return; + + var asset = new AssetDescriptor(NeoSystem.StoreView, NeoSystem.Settings, tokenHash); + var totalSupply = new BigDecimal(((PrimitiveType)result).GetInteger(), asset.Decimals); + + ConsoleHelper.Info("Result: ", $"{totalSupply}"); + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Native.cs b/src/Neo.CLI/CLI/MainService.Native.cs new file mode 100644 index 0000000000..189168b73e --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Native.cs @@ -0,0 +1,29 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.ConsoleService; +using Neo.SmartContract.Native; +using System; +using System.Linq; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "list nativecontract" command + /// + [ConsoleCommand("list nativecontract", Category = "Native Contract")] + private void OnListNativeContract() + { + NativeContract.Contracts.ToList().ForEach(p => ConsoleHelper.Info($"\t{p.Name,-20}", $"{p.Hash}")); + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Network.cs b/src/Neo.CLI/CLI/MainService.Network.cs new file mode 100644 index 0000000000..b09bd5aeda --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Network.cs @@ -0,0 +1,164 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.ConsoleService; +using Neo.IO; +using Neo.Json; +using Neo.Network.P2P; +using Neo.Network.P2P.Capabilities; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using System; +using System.Net; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "broadcast addr" command + /// + /// Payload + /// Port + [ConsoleCommand("broadcast addr", Category = "Network Commands")] + private void OnBroadcastAddressCommand(IPAddress payload, ushort port) + { + if (payload == null) + { + ConsoleHelper.Warning("You must input the payload to relay."); + return; + } + + OnBroadcastCommand(MessageCommand.Addr, + AddrPayload.Create( + NetworkAddressWithTime.Create( + payload, DateTime.UtcNow.ToTimestamp(), + new FullNodeCapability(), + new ServerCapability(NodeCapabilityType.TcpServer, port)) + )); + } + + /// + /// Process "broadcast block" command + /// + /// Hash + [ConsoleCommand("broadcast block", Category = "Network Commands")] + private void OnBroadcastGetBlocksByHashCommand(UInt256 hash) + { + OnBroadcastCommand(MessageCommand.Block, NativeContract.Ledger.GetBlock(NeoSystem.StoreView, hash)); + } + + /// + /// Process "broadcast block" command + /// + /// Block index + [ConsoleCommand("broadcast block", Category = "Network Commands")] + private void OnBroadcastGetBlocksByHeightCommand(uint height) + { + OnBroadcastCommand(MessageCommand.Block, NativeContract.Ledger.GetBlock(NeoSystem.StoreView, height)); + } + + /// + /// Process "broadcast getblocks" command + /// + /// Hash + [ConsoleCommand("broadcast getblocks", Category = "Network Commands")] + private void OnBroadcastGetBlocksCommand(UInt256 hash) + { + OnBroadcastCommand(MessageCommand.GetBlocks, GetBlocksPayload.Create(hash)); + } + + /// + /// Process "broadcast getheaders" command + /// + /// Index + [ConsoleCommand("broadcast getheaders", Category = "Network Commands")] + private void OnBroadcastGetHeadersCommand(uint index) + { + OnBroadcastCommand(MessageCommand.GetHeaders, GetBlockByIndexPayload.Create(index)); + } + + /// + /// Process "broadcast getdata" command + /// + /// Type + /// Payload + [ConsoleCommand("broadcast getdata", Category = "Network Commands")] + private void OnBroadcastGetDataCommand(InventoryType type, UInt256[] payload) + { + OnBroadcastCommand(MessageCommand.GetData, InvPayload.Create(type, payload)); + } + + /// + /// Process "broadcast inv" command + /// + /// Type + /// Payload + [ConsoleCommand("broadcast inv", Category = "Network Commands")] + private void OnBroadcastInvCommand(InventoryType type, UInt256[] payload) + { + OnBroadcastCommand(MessageCommand.Inv, InvPayload.Create(type, payload)); + } + + /// + /// Process "broadcast transaction" command + /// + /// Hash + [ConsoleCommand("broadcast transaction", Category = "Network Commands")] + private void OnBroadcastTransactionCommand(UInt256 hash) + { + if (NeoSystem.MemPool.TryGetValue(hash, out Transaction tx)) + OnBroadcastCommand(MessageCommand.Transaction, tx); + } + + private void OnBroadcastCommand(MessageCommand command, ISerializable ret) + { + NeoSystem.LocalNode.Tell(Message.Create(command, ret)); + } + + /// + /// Process "relay" command + /// + /// Json object + [ConsoleCommand("relay", Category = "Network Commands")] + private void OnRelayCommand(JObject jsonObjectToRelay) + { + if (jsonObjectToRelay == null) + { + ConsoleHelper.Warning("You must input JSON object to relay."); + return; + } + + try + { + ContractParametersContext context = ContractParametersContext.Parse(jsonObjectToRelay.ToString(), NeoSystem.StoreView); + if (!context.Completed) + { + ConsoleHelper.Error("The signature is incomplete."); + return; + } + if (!(context.Verifiable is Transaction tx)) + { + ConsoleHelper.Warning("Only support to relay transaction."); + return; + } + tx.Witnesses = context.GetWitnesses(); + NeoSystem.Blockchain.Tell(tx); + Console.WriteLine($"Data relay success, the hash is shown as follows: {Environment.NewLine}{tx.Hash}"); + } + catch (Exception e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + } + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Node.cs b/src/Neo.CLI/CLI/MainService.Node.cs new file mode 100644 index 0000000000..9752dfd5ea --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Node.cs @@ -0,0 +1,118 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.ConsoleService; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract.Native; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "show pool" command + /// + [ConsoleCommand("show pool", Category = "Node Commands", Description = "Show the current state of the mempool")] + private void OnShowPoolCommand(bool verbose = false) + { + int verifiedCount, unverifiedCount; + if (verbose) + { + NeoSystem.MemPool.GetVerifiedAndUnverifiedTransactions( + out IEnumerable verifiedTransactions, + out IEnumerable unverifiedTransactions); + ConsoleHelper.Info("Verified Transactions:"); + foreach (Transaction tx in verifiedTransactions) + Console.WriteLine($" {tx.Hash} {tx.GetType().Name} {tx.NetworkFee} GAS_NetFee"); + ConsoleHelper.Info("Unverified Transactions:"); + foreach (Transaction tx in unverifiedTransactions) + Console.WriteLine($" {tx.Hash} {tx.GetType().Name} {tx.NetworkFee} GAS_NetFee"); + + verifiedCount = verifiedTransactions.Count(); + unverifiedCount = unverifiedTransactions.Count(); + } + else + { + verifiedCount = NeoSystem.MemPool.VerifiedCount; + unverifiedCount = NeoSystem.MemPool.UnVerifiedCount; + } + Console.WriteLine($"total: {NeoSystem.MemPool.Count}, verified: {verifiedCount}, unverified: {unverifiedCount}"); + } + + /// + /// Process "show state" command + /// + [ConsoleCommand("show state", Category = "Node Commands", Description = "Show the current state of the node")] + private void OnShowStateCommand() + { + var cancel = new CancellationTokenSource(); + + Console.CursorVisible = false; + Console.Clear(); + + Task broadcast = Task.Run(async () => + { + while (!cancel.Token.IsCancellationRequested) + { + NeoSystem.LocalNode.Tell(Message.Create(MessageCommand.Ping, PingPayload.Create(NativeContract.Ledger.CurrentIndex(NeoSystem.StoreView)))); + await Task.Delay(NeoSystem.Settings.TimePerBlock, cancel.Token); + } + }); + Task task = Task.Run(async () => + { + int maxLines = 0; + while (!cancel.Token.IsCancellationRequested) + { + uint height = NativeContract.Ledger.CurrentIndex(NeoSystem.StoreView); + uint headerHeight = NeoSystem.HeaderCache.Last?.Index ?? height; + + Console.SetCursorPosition(0, 0); + WriteLineWithoutFlicker($"block: {height}/{headerHeight} connected: {LocalNode.ConnectedCount} unconnected: {LocalNode.UnconnectedCount}", Console.WindowWidth - 1); + + int linesWritten = 1; + foreach (RemoteNode node in LocalNode.GetRemoteNodes().OrderByDescending(u => u.LastBlockIndex).Take(Console.WindowHeight - 2).ToArray()) + { + ConsoleHelper.Info(" ip: ", + $"{node.Remote.Address,-15}\t", + "port: ", + $"{node.Remote.Port,-5}\t", + "listen: ", + $"{node.ListenerTcpPort,-5}\t", + "height: ", + $"{node.LastBlockIndex,-7}"); + linesWritten++; + } + + maxLines = Math.Max(maxLines, linesWritten); + + while (linesWritten < maxLines) + { + WriteLineWithoutFlicker("", Console.WindowWidth - 1); + maxLines--; + } + + await Task.Delay(500, cancel.Token); + } + }); + ReadLine(); + cancel.Cancel(); + try { Task.WaitAll(task, broadcast); } catch { } + Console.WriteLine(); + Console.CursorVisible = true; + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Plugins.cs b/src/Neo.CLI/CLI/MainService.Plugins.cs new file mode 100644 index 0000000000..6373c9c4a7 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Plugins.cs @@ -0,0 +1,244 @@ +// Copyright (C) 2016-2023 The Neo Project. +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Microsoft.Extensions.Configuration; +using Neo.ConsoleService; +using Neo.Json; +using Neo.Plugins; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Security.Cryptography; +using System.Threading.Tasks; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "install" command + /// + /// Plugin name + [ConsoleCommand("install", Category = "Plugin Commands")] + private async Task OnInstallCommandAsync(string pluginName) + { + if (PluginExists(pluginName)) + { + ConsoleHelper.Warning($"Plugin already exist."); + return; + } + + await InstallPluginAsync(pluginName); + ConsoleHelper.Warning("Install successful, please restart neo-cli."); + } + + /// + /// Force to install a plugin again. This will overwrite + /// existing plugin files, in case of any file missing or + /// damage to the old version. + /// + /// name of the plugin + [ConsoleCommand("reinstall", Category = "Plugin Commands", Description = "Overwrite existing plugin by force.")] + private async Task OnReinstallCommand(string pluginName) + { + await InstallPluginAsync(pluginName, overWrite: true); + ConsoleHelper.Warning("Reinstall successful, please restart neo-cli."); + } + + /// + /// Download plugin from github release + /// The function of download and install are divided + /// for the consideration of `update` command that + /// might be added in the future. + /// + /// name of the plugin + /// Downloaded content + private async Task DownloadPluginAsync(string pluginName) + { + var url = + $"https://github.com/neo-project/neo-modules/releases/download/v{typeof(Plugin).Assembly.GetVersion()}/{pluginName}.zip"; + using HttpClient http = new(); + HttpResponseMessage response = await http.GetAsync(url); + if (response.StatusCode == HttpStatusCode.NotFound) + { + response.Dispose(); + Version versionCore = typeof(Plugin).Assembly.GetName().Version; + HttpRequestMessage request = new(HttpMethod.Get, + "https://api.github.com/repos/neo-project/neo-modules/releases"); + request.Headers.UserAgent.ParseAdd( + $"{GetType().Assembly.GetName().Name}/{GetType().Assembly.GetVersion()}"); + using HttpResponseMessage responseApi = await http.SendAsync(request); + byte[] buffer = await responseApi.Content.ReadAsByteArrayAsync(); + var releases = JObject.Parse(buffer); + var asset = ((JArray)releases) + .Where(p => !p["tag_name"].GetString().Contains('-')) + .Select(p => new + { + Version = Version.Parse(p["tag_name"].GetString().TrimStart('v')), + Assets = (JArray)p["assets"] + }) + .OrderByDescending(p => p.Version) + .First(p => p.Version <= versionCore).Assets + .FirstOrDefault(p => p["name"].GetString() == $"{pluginName}.zip"); + if (asset is null) throw new Exception("Plugin doesn't exist."); + response = await http.GetAsync(asset["browser_download_url"].GetString()); + } + + using (response) + { + var totalRead = 0L; + byte[] buffer = new byte[1024]; + int read; + await using Stream stream = await response.Content.ReadAsStreamAsync(); + ConsoleHelper.Info("From ", $"{url}"); + var output = new MemoryStream(); + while ((read = await stream.ReadAsync(buffer)) > 0) + { + output.Write(buffer, 0, read); + totalRead += read; + Console.Write( + $"\rDownloading {pluginName}.zip {totalRead / 1024}KB/{response.Content.Headers.ContentLength / 1024}KB {(totalRead * 100) / response.Content.Headers.ContentLength}%"); + } + + Console.WriteLine(); + return output; + } + } + + /// + /// Install plugin from stream + /// + /// name of the plugin + /// Install by force for `update` + private async Task InstallPluginAsync(string pluginName, HashSet installed = null, + bool overWrite = false) + { + installed ??= new HashSet(); + if (!installed.Add(pluginName)) return; + if (!overWrite && PluginExists(pluginName)) return; + + await using MemoryStream stream = await DownloadPluginAsync(pluginName); + using (SHA256 sha256 = SHA256.Create()) + { + ConsoleHelper.Info("SHA256: ", $"{sha256.ComputeHash(stream.ToArray()).ToHexString()}"); + } + + using ZipArchive zip = new(stream, ZipArchiveMode.Read); + ZipArchiveEntry entry = zip.Entries.FirstOrDefault(p => p.Name == "config.json"); + if (entry is not null) + { + await using Stream es = entry.Open(); + await InstallDependenciesAsync(es, installed); + } + zip.ExtractToDirectory("./", true); + } + + /// + /// Install the dependency of the plugin + /// + /// plugin config path in temp + /// Dependency set + private async Task InstallDependenciesAsync(Stream config, HashSet installed) + { + IConfigurationSection dependency = new ConfigurationBuilder() + .AddJsonStream(config) + .Build() + .GetSection("Dependency"); + + if (!dependency.Exists()) return; + var dependencies = dependency.GetChildren().Select(p => p.Get()).ToArray(); + if (dependencies.Length == 0) return; + + foreach (string plugin in dependencies.Where(p => !PluginExists(p))) + { + ConsoleHelper.Info($"Installing dependency: {plugin}"); + await InstallPluginAsync(plugin, installed); + } + } + + /// + /// Check that the plugin has all necessary files + /// + /// Name of the plugin + /// + private static bool PluginExists(string pluginName) + { + return Plugin.Plugins.Any(p => p.Name.Equals(pluginName, StringComparison.InvariantCultureIgnoreCase)); + } + + /// + /// Process "uninstall" command + /// + /// Plugin name + [ConsoleCommand("uninstall", Category = "Plugin Commands")] + private void OnUnInstallCommand(string pluginName) + { + if (!PluginExists(pluginName)) + { + ConsoleHelper.Warning("Plugin not found"); + return; + } + + foreach (var p in Plugin.Plugins) + { + try + { + using var reader = File.OpenRead($"./Plugins/{p.Name}/config.json"); + if (new ConfigurationBuilder() + .AddJsonStream(reader) + .Build() + .GetSection("Dependency") + .GetChildren() + .Select(d => d.Get()) + .Any(v => v.Equals(pluginName, StringComparison.InvariantCultureIgnoreCase))) + { + ConsoleHelper.Error( + $"Can not uninstall. Other plugins depend on this plugin, try `reinstall {pluginName}` if the plugin is broken."); + return; + } + } + catch (Exception) + { + // ignored + } + } + try + { + Directory.Delete($"Plugins/{pluginName}", true); + } + catch (IOException) { } + ConsoleHelper.Info("Uninstall successful, please restart neo-cli."); + } + + /// + /// Process "plugins" command + /// + [ConsoleCommand("plugins", Category = "Plugin Commands")] + private void OnPluginsCommand() + { + if (Plugin.Plugins.Count > 0) + { + Console.WriteLine("Loaded plugins:"); + foreach (Plugin plugin in Plugin.Plugins) + { + var name = $"{plugin.Name}@{plugin.Version}"; + Console.WriteLine($"\t{name,-25}{plugin.Description}"); + } + } + else + { + ConsoleHelper.Warning("No loaded plugins"); + } + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Tools.cs b/src/Neo.CLI/CLI/MainService.Tools.cs new file mode 100644 index 0000000000..0136617729 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Tools.cs @@ -0,0 +1,462 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.ConsoleService; +using Neo.IO; +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "parse" command + /// + [ConsoleCommand("parse", Category = "Base Commands", Description = "Parse a value to its possible conversions.")] + private void OnParseCommand(string value) + { + var parseFunctions = new Dictionary>() + { + { "Address to ScriptHash", AddressToScripthash }, + { "Address to Base64", AddressToBase64 }, + { "ScriptHash to Address", ScripthashToAddress }, + { "Base64 to Address", Base64ToAddress }, + { "Base64 to String", Base64ToString }, + { "Base64 to Big Integer", Base64ToNumber }, + { "Big Integer to Hex String", NumberToHex }, + { "Big Integer to Base64", NumberToBase64 }, + { "Hex String to String", HexToString }, + { "Hex String to Big Integer", HexToNumber }, + { "String to Hex String", StringToHex }, + { "String to Base64", StringToBase64 } + }; + + bool any = false; + + foreach (var pair in parseFunctions) + { + var parseMethod = pair.Value; + var result = parseMethod(value); + + if (result != null) + { + Console.WriteLine($"{pair.Key,-30}\t{result}"); + any = true; + } + } + + if (!any) + { + ConsoleHelper.Warning($"Was not possible to convert: '{value}'"); + } + } + + /// + /// Converts an hexadecimal value to an UTF-8 string + /// + /// + /// Hexadecimal value to be converted + /// + /// + /// Returns null when is not possible to parse the hexadecimal value to a UTF-8 + /// string or when the converted string is not printable; otherwise, returns + /// the string represented by the hexadecimal value + /// + private string HexToString(string hexString) + { + try + { + var clearHexString = ClearHexString(hexString); + var bytes = clearHexString.HexToBytes(); + var utf8String = Utility.StrictUTF8.GetString(bytes); + return IsPrintable(utf8String) ? utf8String : null; + } + catch + { + return null; + } + } + + /// + /// Converts an hex value to a big integer + /// + /// + /// Hexadecimal value to be converted + /// + /// + /// Returns null when is not possible to parse the hex value to big integer value; + /// otherwise, returns the string that represents the converted big integer. + /// + private string HexToNumber(string hexString) + { + try + { + var clearHexString = ClearHexString(hexString); + var bytes = clearHexString.HexToBytes(); + var number = new BigInteger(bytes); + + return number.ToString(); + } + catch + { + return null; + } + } + + /// + /// Formats a string value to a default hexadecimal representation of a byte array + /// + /// + /// The string value to be formatted + /// + /// + /// Returns the formatted string. + /// + /// + /// Throw when is the string is not a valid hex representation of a byte array. + /// + private string ClearHexString(string hexString) + { + bool hasHexPrefix = hexString.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase); + + try + { + if (hasHexPrefix) + { + hexString = hexString.Substring(2); + } + + if (hexString.Length % 2 == 1) + { + // if the length is an odd number, it cannot be parsed to a byte array + // it may be a valid hex string, so include a leading zero to parse correctly + hexString = "0" + hexString; + } + + if (hasHexPrefix) + { + // if the input value starts with '0x', the first byte is the less significant + // to parse correctly, reverse the byte array + return hexString.HexToBytes().Reverse().ToArray().ToHexString(); + } + } + catch (FormatException) + { + throw new ArgumentException(); + } + + return hexString; + } + + /// + /// Converts a string in a hexadecimal value + /// + /// + /// String value to be converted + /// + /// + /// Returns null when it is not possible to parse the string value to a hexadecimal + /// value; otherwise returns the hexadecimal value that represents the converted string + /// + private string StringToHex(string strParam) + { + try + { + var bytesParam = Utility.StrictUTF8.GetBytes(strParam); + return bytesParam.ToHexString(); + } + catch + { + return null; + } + } + + /// + /// Converts a string in Base64 string + /// + /// + /// String value to be converted + /// + /// + /// Returns null when is not possible to parse the string value to a Base64 value; + /// otherwise returns the Base64 value that represents the converted string + /// + /// + /// Throw . + /// + private string StringToBase64(string strParam) + { + try + { + byte[] bytearray = Utility.StrictUTF8.GetBytes(strParam); + string base64 = Convert.ToBase64String(bytearray.AsSpan()); + return base64; + } + catch + { + return null; + } + } + + /// + /// Converts a string number in hexadecimal format + /// + /// + /// String that represents the number to be converted + /// + /// + /// Returns null when the string does not represent a big integer value or when + /// it is not possible to parse the big integer value to hexadecimal; otherwise, + /// returns the string that represents the converted hexadecimal value + /// + private string NumberToHex(string strParam) + { + try + { + if (!BigInteger.TryParse(strParam, out var numberParam)) + { + return null; + } + return numberParam.ToByteArray().ToHexString(); + } + catch + { + return null; + } + } + + /// + /// Converts a string number in Base64 byte array + /// + /// + /// String that represents the number to be converted + /// + /// + /// Returns null when the string does not represent a big integer value or when + /// it is not possible to parse the big integer value to Base64 value; otherwise, + /// returns the string that represents the converted Base64 value + /// + private string NumberToBase64(string strParam) + { + try + { + if (!BigInteger.TryParse(strParam, out var number)) + { + return null; + } + byte[] bytearray = number.ToByteArray(); + string base64 = Convert.ToBase64String(bytearray.AsSpan()); + + return base64; + } + catch + { + return null; + } + } + + /// + /// Converts an address to its corresponding scripthash + /// + /// + /// String that represents the address to be converted + /// + /// + /// Returns null when the string does not represent an address or when + /// it is not possible to parse the address to scripthash; otherwise returns + /// the string that represents the converted scripthash + /// + private string AddressToScripthash(string address) + { + try + { + var bigEndScript = address.ToScriptHash(NeoSystem.Settings.AddressVersion); + + return bigEndScript.ToString(); + } + catch + { + return null; + } + } + + /// + /// Converts an address to Base64 byte array + /// + /// + /// String that represents the address to be converted + /// + /// + /// Returns null when the string does not represent an address or when it is + /// not possible to parse the address to Base64 value; otherwise returns + /// the string that represents the converted Base64 value. + /// + private string AddressToBase64(string address) + { + try + { + var script = address.ToScriptHash(NeoSystem.Settings.AddressVersion); + string base64 = Convert.ToBase64String(script.ToArray().AsSpan()); + + return base64; + } + catch + { + return null; + } + } + + /// + /// Converts a big end script hash to its equivalent address + /// + /// + /// String that represents the scripthash to be converted + /// + /// + /// Returns null when the string does not represent an scripthash; + /// otherwise, returns the string that represents the converted address + /// + private string ScripthashToAddress(string script) + { + try + { + UInt160 scriptHash; + if (script.StartsWith("0x")) + { + if (!UInt160.TryParse(script, out scriptHash)) + { + return null; + } + } + else + { + if (!UInt160.TryParse(script, out UInt160 littleEndScript)) + { + return null; + } + string bigEndScript = littleEndScript.ToArray().ToHexString(); + if (!UInt160.TryParse(bigEndScript, out scriptHash)) + { + return null; + } + } + + var hexScript = scriptHash.ToAddress(NeoSystem.Settings.AddressVersion); + return hexScript; + } + catch + { + return null; + } + } + + /// + /// Converts an Base64 byte array to address + /// + /// + /// String that represents the Base64 value + /// + /// + /// Returns null when the string does not represent an Base64 value or when + /// it is not possible to parse the Base64 value to address; otherwise, + /// returns the string that represents the converted address + /// + private string Base64ToAddress(string bytearray) + { + try + { + byte[] result = Convert.FromBase64String(bytearray).Reverse().ToArray(); + string hex = result.ToHexString(); + + if (!UInt160.TryParse(hex, out var scripthash)) + { + return null; + } + + string address = scripthash.ToAddress(NeoSystem.Settings.AddressVersion); + return address; + } + catch + { + return null; + } + } + + /// + /// Converts an Base64 hex string to string + /// + /// + /// String that represents the Base64 value + /// + /// + /// Returns null when the string does not represent an Base64 value or when + /// it is not possible to parse the Base64 value to string value or the converted + /// string is not printable; otherwise, returns the string that represents + /// the Base64 value. + /// + private string Base64ToString(string bytearray) + { + try + { + byte[] result = Convert.FromBase64String(bytearray); + string utf8String = Utility.StrictUTF8.GetString(result); + return IsPrintable(utf8String) ? utf8String : null; + } + catch + { + return null; + } + } + + /// + /// Converts an Base64 hex string to big integer value + /// + /// + /// String that represents the Base64 value + /// + /// + /// Returns null when the string does not represent an Base64 value or when + /// it is not possible to parse the Base64 value to big integer value; otherwise + /// returns the string that represents the converted big integer + /// + private string Base64ToNumber(string bytearray) + { + try + { + var bytes = Convert.FromBase64String(bytearray); + var number = new BigInteger(bytes); + return number.ToString(); + } + catch + { + return null; + } + } + + /// + /// Checks if the string is null or cannot be printed. + /// + /// + /// The string to test + /// + /// + /// Returns false if the string is null, or if it is empty, or if each character cannot be printed; + /// otherwise, returns true. + /// + private bool IsPrintable(string value) + { + return !string.IsNullOrWhiteSpace(value) && value.Any(c => !char.IsControl(c)); + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Vote.cs b/src/Neo.CLI/CLI/MainService.Vote.cs new file mode 100644 index 0000000000..aa23562eb9 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Vote.cs @@ -0,0 +1,239 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.ConsoleService; +using Neo.Cryptography.ECC; +using Neo.Json; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; +using Neo.Wallets; +using System; +using System.Linq; +using System.Numerics; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "register candidate" command + /// + /// register account scriptHash + [ConsoleCommand("register candidate", Category = "Vote Commands")] + private void OnRegisterCandidateCommand(UInt160 account) + { + var testGas = NativeContract.NEO.GetRegisterPrice(NeoSystem.StoreView) + (BigInteger)Math.Pow(10, NativeContract.GAS.Decimals) * 10; + if (NoWallet()) return; + WalletAccount currentAccount = CurrentWallet.GetAccount(account); + + if (currentAccount == null) + { + ConsoleHelper.Warning("This address isn't in your wallet!"); + return; + } + else + { + if (currentAccount.Lock || currentAccount.WatchOnly) + { + ConsoleHelper.Warning("Locked or WatchOnly address."); + return; + } + } + + ECPoint publicKey = currentAccount.GetKey()?.PublicKey; + byte[] script; + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitDynamicCall(NativeContract.NEO.Hash, "registerCandidate", publicKey); + script = scriptBuilder.ToArray(); + } + + SendTransaction(script, account, (long)testGas); + } + + /// + /// Process "unregister candidate" command + /// + /// unregister account scriptHash + [ConsoleCommand("unregister candidate", Category = "Vote Commands")] + private void OnUnregisterCandidateCommand(UInt160 account) + { + if (NoWallet()) return; + WalletAccount currentAccount = CurrentWallet.GetAccount(account); + + if (currentAccount == null) + { + ConsoleHelper.Warning("This address isn't in your wallet!"); + return; + } + else + { + if (currentAccount.Lock || currentAccount.WatchOnly) + { + ConsoleHelper.Warning("Locked or WatchOnly address."); + return; + } + } + + ECPoint publicKey = currentAccount?.GetKey()?.PublicKey; + byte[] script; + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitDynamicCall(NativeContract.NEO.Hash, "unregisterCandidate", publicKey); + script = scriptBuilder.ToArray(); + } + + SendTransaction(script, account); + } + + /// + /// Process "vote" command + /// + /// Sender account + /// Voting publicKey + [ConsoleCommand("vote", Category = "Vote Commands")] + private void OnVoteCommand(UInt160 senderAccount, ECPoint publicKey) + { + if (NoWallet()) return; + byte[] script; + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitDynamicCall(NativeContract.NEO.Hash, "vote", senderAccount, publicKey); + script = scriptBuilder.ToArray(); + } + + SendTransaction(script, senderAccount); + } + + /// + /// Process "unvote" command + /// + /// Sender account + [ConsoleCommand("unvote", Category = "Vote Commands")] + private void OnUnvoteCommand(UInt160 senderAccount) + { + if (NoWallet()) return; + byte[] script; + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitDynamicCall(NativeContract.NEO.Hash, "vote", senderAccount, null); + script = scriptBuilder.ToArray(); + } + + SendTransaction(script, senderAccount); + } + + /// + /// Process "get candidates" + /// + [ConsoleCommand("get candidates", Category = "Vote Commands")] + private void OnGetCandidatesCommand() + { + if (!OnInvokeWithResult(NativeContract.NEO.Hash, "getCandidates", out StackItem result, null, null, false)) return; + + var resJArray = (VM.Types.Array)result; + + if (resJArray.Count > 0) + { + Console.WriteLine(); + ConsoleHelper.Info("Candidates:"); + + foreach (var item in resJArray) + { + var value = (VM.Types.Array)item; + + Console.Write(((ByteString)value?[0])?.GetSpan().ToHexString() + "\t"); + Console.WriteLine(((Integer)value?[1]).GetInteger()); + } + } + } + + /// + /// Process "get committee" + /// + [ConsoleCommand("get committee", Category = "Vote Commands")] + private void OnGetCommitteeCommand() + { + if (!OnInvokeWithResult(NativeContract.NEO.Hash, "getCommittee", out StackItem result, null, null, false)) return; + + var resJArray = (VM.Types.Array)result; + + if (resJArray.Count > 0) + { + Console.WriteLine(); + ConsoleHelper.Info("Committee:"); + + foreach (var item in resJArray) + { + Console.WriteLine(((ByteString)item)?.GetSpan().ToHexString()); + } + } + } + + /// + /// Process "get next validators" + /// + [ConsoleCommand("get next validators", Category = "Vote Commands")] + private void OnGetNextBlockValidatorsCommand() + { + if (!OnInvokeWithResult(NativeContract.NEO.Hash, "getNextBlockValidators", out StackItem result, null, null, false)) return; + + var resJArray = (VM.Types.Array)result; + + if (resJArray.Count > 0) + { + Console.WriteLine(); + ConsoleHelper.Info("Next validators:"); + + foreach (var item in resJArray) + { + Console.WriteLine(((ByteString)item)?.GetSpan().ToHexString()); + } + } + } + + /// + /// Process "get accountstate" + /// + [ConsoleCommand("get accountstate", Category = "Vote Commands")] + private void OnGetAccountState(UInt160 address) + { + string notice = "No vote record!"; + var arg = new JObject + { + ["type"] = "Hash160", + ["value"] = address.ToString() + }; + + if (!OnInvokeWithResult(NativeContract.NEO.Hash, "getAccountState", out StackItem result, null, new JArray(arg))) return; + Console.WriteLine(); + if (result.IsNull) + { + ConsoleHelper.Warning(notice); + return; + } + var resJArray = (VM.Types.Array)result; + foreach (StackItem value in resJArray) + { + if (value.IsNull) + { + ConsoleHelper.Warning(notice); + return; + } + } + var publickey = ECPoint.Parse(((ByteString)resJArray?[2])?.GetSpan().ToHexString(), ECCurve.Secp256r1); + ConsoleHelper.Info("Voted: ", Contract.CreateSignatureRedeemScript(publickey).ToScriptHash().ToAddress(NeoSystem.Settings.AddressVersion)); + ConsoleHelper.Info("Amount: ", new BigDecimal(((Integer)resJArray?[0]).GetInteger(), NativeContract.NEO.Decimals).ToString()); + ConsoleHelper.Info("Block: ", ((Integer)resJArray?[1]).GetInteger().ToString()); + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.Wallet.cs b/src/Neo.CLI/CLI/MainService.Wallet.cs new file mode 100644 index 0000000000..f916ea1bbc --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.Wallet.cs @@ -0,0 +1,743 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.ConsoleService; +using Neo.Cryptography.ECC; +using Neo.Json; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using Neo.Wallets.NEP6; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Threading.Tasks; +using static Neo.SmartContract.Helper; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "open wallet" command + /// + /// Path + [ConsoleCommand("open wallet", Category = "Wallet Commands")] + private void OnOpenWallet(string path) + { + if (!File.Exists(path)) + { + ConsoleHelper.Error("File does not exist"); + return; + } + string password = ReadUserInput("password", true); + if (password.Length == 0) + { + ConsoleHelper.Info("Cancelled"); + return; + } + try + { + OpenWallet(path, password); + } + catch (System.Security.Cryptography.CryptographicException) + { + ConsoleHelper.Error($"Failed to open file \"{path}\""); + } + } + + /// + /// Process "close wallet" command + /// + [ConsoleCommand("close wallet", Category = "Wallet Commands")] + private void OnCloseWalletCommand() + { + if (NoWallet()) return; + CurrentWallet = null; + ConsoleHelper.Info("Wallet is closed"); + } + + /// + /// Process "upgrade wallet" command + /// + [ConsoleCommand("upgrade wallet", Category = "Wallet Commands")] + private void OnUpgradeWalletCommand(string path) + { + if (Path.GetExtension(path).ToLowerInvariant() != ".db3") + { + ConsoleHelper.Warning("Can't upgrade the wallet file. Check if your wallet is in db3 format."); + return; + } + if (!File.Exists(path)) + { + ConsoleHelper.Error("File does not exist."); + return; + } + string password = ReadUserInput("password", true); + if (password.Length == 0) + { + ConsoleHelper.Info("Cancelled"); + return; + } + string pathNew = Path.ChangeExtension(path, ".json"); + if (File.Exists(pathNew)) + { + ConsoleHelper.Warning($"File '{pathNew}' already exists"); + return; + } + NEP6Wallet.Migrate(pathNew, path, password, NeoSystem.Settings).Save(); + Console.WriteLine($"Wallet file upgrade complete. New wallet file has been auto-saved at: {pathNew}"); + } + + /// + /// Process "create address" command + /// + /// Count + [ConsoleCommand("create address", Category = "Wallet Commands")] + private void OnCreateAddressCommand(ushort count = 1) + { + if (NoWallet()) return; + string path = "address.txt"; + if (File.Exists(path)) + { + if (!ReadUserInput($"The file '{path}' already exists, do you want to overwrite it? (yes|no)", false).IsYes()) + { + return; + } + } + + List addresses = new List(); + using (var percent = new ConsolePercent(0, count)) + { + Parallel.For(0, count, (i) => + { + WalletAccount account = CurrentWallet.CreateAccount(); + lock (addresses) + { + addresses.Add(account.Address); + percent.Value++; + } + }); + } + + if (CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + + Console.WriteLine($"Export addresses to {path}"); + File.WriteAllLines(path, addresses); + } + + /// + /// Process "delete address" command + /// + /// Address + [ConsoleCommand("delete address", Category = "Wallet Commands")] + private void OnDeleteAddressCommand(UInt160 address) + { + if (NoWallet()) return; + + if (ReadUserInput($"Warning: Irrevocable operation!\nAre you sure to delete account {address.ToAddress(NeoSystem.Settings.AddressVersion)}? (no|yes)").IsYes()) + { + if (CurrentWallet.DeleteAccount(address)) + { + if (CurrentWallet is NEP6Wallet wallet) + { + wallet.Save(); + } + ConsoleHelper.Info($"Address {address} deleted."); + } + else + { + ConsoleHelper.Warning($"Address {address} doesn't exist."); + } + } + } + + /// + /// Process "export key" command + /// + /// Path + /// ScriptHash + [ConsoleCommand("export key", Category = "Wallet Commands")] + private void OnExportKeyCommand(string path = null, UInt160 scriptHash = null) + { + if (NoWallet()) return; + if (path != null && File.Exists(path)) + { + ConsoleHelper.Error($"File '{path}' already exists"); + return; + } + string password = ReadUserInput("password", true); + if (password.Length == 0) + { + ConsoleHelper.Info("Cancelled"); + return; + } + if (!CurrentWallet.VerifyPassword(password)) + { + ConsoleHelper.Error("Incorrect password"); + return; + } + IEnumerable keys; + if (scriptHash == null) + keys = CurrentWallet.GetAccounts().Where(p => p.HasKey).Select(p => p.GetKey()); + else + { + var account = CurrentWallet.GetAccount(scriptHash); + keys = account?.HasKey != true ? Array.Empty() : new[] { account.GetKey() }; + } + if (path == null) + foreach (KeyPair key in keys) + Console.WriteLine(key.Export()); + else + File.WriteAllLines(path, keys.Select(p => p.Export())); + } + + /// + /// Process "create wallet" command + /// + [ConsoleCommand("create wallet", Category = "Wallet Commands")] + private void OnCreateWalletCommand(string path, string wifOrFile = null) + { + string password = ReadUserInput("password", true); + if (password.Length == 0) + { + ConsoleHelper.Info("Cancelled"); + return; + } + string password2 = ReadUserInput("repeat password", true); + if (password != password2) + { + ConsoleHelper.Error("Two passwords not match."); + return; + } + if (File.Exists(path)) + { + Console.WriteLine("This wallet already exists, please create another one."); + return; + } + bool createDefaultAccount = wifOrFile is null; + CreateWallet(path, password, createDefaultAccount); + if (!createDefaultAccount) OnImportKeyCommand(wifOrFile); + } + + /// + /// Process "import multisigaddress" command + /// + /// Required signatures + /// Public keys + [ConsoleCommand("import multisigaddress", Category = "Wallet Commands")] + private void OnImportMultisigAddress(ushort m, ECPoint[] publicKeys) + { + if (NoWallet()) return; + int n = publicKeys.Length; + + if (m < 1 || m > n || n > 1024) + { + ConsoleHelper.Error("Invalid parameters."); + return; + } + + Contract multiSignContract = Contract.CreateMultiSigContract(m, publicKeys); + KeyPair keyPair = CurrentWallet.GetAccounts().FirstOrDefault(p => p.HasKey && publicKeys.Contains(p.GetKey().PublicKey))?.GetKey(); + + CurrentWallet.CreateAccount(multiSignContract, keyPair); + if (CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + + ConsoleHelper.Info("Multisig. Addr.: ", multiSignContract.ScriptHash.ToAddress(NeoSystem.Settings.AddressVersion)); + } + + /// + /// Process "import key" command + /// + [ConsoleCommand("import key", Category = "Wallet Commands")] + private void OnImportKeyCommand(string wifOrFile) + { + if (NoWallet()) return; + byte[] prikey = null; + try + { + prikey = Wallet.GetPrivateKeyFromWIF(wifOrFile); + } + catch (FormatException) { } + if (prikey == null) + { + var fileInfo = new FileInfo(wifOrFile); + + if (!fileInfo.Exists) + { + ConsoleHelper.Error($"File '{fileInfo.FullName}' doesn't exists"); + return; + } + + if (wifOrFile.Length > 1024 * 1024) + { + if (!ReadUserInput($"The file '{fileInfo.FullName}' is too big, do you want to continue? (yes|no)", false).IsYes()) + { + return; + } + } + + string[] lines = File.ReadAllLines(fileInfo.FullName).Where(u => !string.IsNullOrEmpty(u)).ToArray(); + using (var percent = new ConsolePercent(0, lines.Length)) + { + for (int i = 0; i < lines.Length; i++) + { + if (lines[i].Length == 64) + prikey = lines[i].HexToBytes(); + else + prikey = Wallet.GetPrivateKeyFromWIF(lines[i]); + CurrentWallet.CreateAccount(prikey); + Array.Clear(prikey, 0, prikey.Length); + percent.Value++; + } + } + } + else + { + WalletAccount account = CurrentWallet.CreateAccount(prikey); + Array.Clear(prikey, 0, prikey.Length); + ConsoleHelper.Info("Address: ", account.Address); + ConsoleHelper.Info(" Pubkey: ", account.GetKey().PublicKey.EncodePoint(true).ToHexString()); + } + if (CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + } + + /// + /// Process "import watchonly" command + /// + [ConsoleCommand("import watchonly", Category = "Wallet Commands")] + private void OnImportWatchOnlyCommand(string addressOrFile) + { + if (NoWallet()) return; + UInt160 address = null; + try + { + address = StringToAddress(addressOrFile, NeoSystem.Settings.AddressVersion); + } + catch (FormatException) { } + if (address is null) + { + var fileInfo = new FileInfo(addressOrFile); + + if (!fileInfo.Exists) + { + ConsoleHelper.Warning($"File '{fileInfo.FullName}' doesn't exists"); + return; + } + + if (fileInfo.Length > 1024 * 1024) + { + if (!ReadUserInput($"The file '{fileInfo.FullName}' is too big, do you want to continue? (yes|no)", false).IsYes()) + { + return; + } + } + + string[] lines = File.ReadAllLines(fileInfo.FullName).Where(u => !string.IsNullOrEmpty(u)).ToArray(); + using (var percent = new ConsolePercent(0, lines.Length)) + { + for (int i = 0; i < lines.Length; i++) + { + address = StringToAddress(lines[i], NeoSystem.Settings.AddressVersion); + CurrentWallet.CreateAccount(address); + percent.Value++; + } + } + } + else + { + WalletAccount account = CurrentWallet.GetAccount(address); + if (account is not null) + { + ConsoleHelper.Warning("This address is already in your wallet"); + } + else + { + account = CurrentWallet.CreateAccount(address); + ConsoleHelper.Info("Address: ", account.Address); + } + } + if (CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + } + + /// + /// Process "list address" command + /// + [ConsoleCommand("list address", Category = "Wallet Commands")] + private void OnListAddressCommand() + { + if (NoWallet()) return; + var snapshot = NeoSystem.StoreView; + foreach (var account in CurrentWallet.GetAccounts()) + { + var contract = account.Contract; + var type = "Nonstandard"; + + if (account.WatchOnly) + { + type = "WatchOnly"; + } + else if (IsMultiSigContract(contract.Script)) + { + type = "MultiSignature"; + } + else if (IsSignatureContract(contract.Script)) + { + type = "Standard"; + } + else if (NativeContract.ContractManagement.GetContract(snapshot, account.ScriptHash) != null) + { + type = "Deployed-Nonstandard"; + } + + ConsoleHelper.Info(" Address: ", $"{account.Address}\t{type}"); + ConsoleHelper.Info("ScriptHash: ", $"{account.ScriptHash}\n"); + } + } + + /// + /// Process "list asset" command + /// + [ConsoleCommand("list asset", Category = "Wallet Commands")] + 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()); + } + + /// + /// Process "list key" command + /// + [ConsoleCommand("list key", Category = "Wallet Commands")] + private void OnListKeyCommand() + { + if (NoWallet()) return; + foreach (WalletAccount account in CurrentWallet.GetAccounts().Where(p => p.HasKey)) + { + ConsoleHelper.Info(" Address: ", account.Address); + ConsoleHelper.Info("ScriptHash: ", account.ScriptHash.ToString()); + ConsoleHelper.Info(" PublicKey: ", account.GetKey().PublicKey.EncodePoint(true).ToHexString()); + Console.WriteLine(); + } + } + + /// + /// Process "sign" command + /// + /// Json object to sign + [ConsoleCommand("sign", Category = "Wallet Commands")] + private void OnSignCommand(JObject jsonObjectToSign) + { + if (NoWallet()) return; + + if (jsonObjectToSign == null) + { + ConsoleHelper.Warning("You must input JSON object pending signature data."); + return; + } + try + { + var snapshot = NeoSystem.StoreView; + ContractParametersContext context = ContractParametersContext.Parse(jsonObjectToSign.ToString(), snapshot); + if (context.Network != _neoSystem.Settings.Network) + { + ConsoleHelper.Warning("Network mismatch."); + return; + } + else if (!CurrentWallet.Sign(context)) + { + ConsoleHelper.Warning("Non-existent private key in wallet."); + return; + } + ConsoleHelper.Info("Signed Output: ", $"{Environment.NewLine}{context}"); + } + catch (Exception e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + } + } + + /// + /// Process "send" command + /// + /// Asset id + /// To + /// Amount + /// From + /// Data + /// Signer's accounts + [ConsoleCommand("send", Category = "Wallet Commands")] + private void OnSendCommand(UInt160 asset, UInt160 to, string amount, UInt160 from = null, string data = null, UInt160[] signerAccounts = null) + { + if (NoWallet()) return; + string password = ReadUserInput("password", true); + if (password.Length == 0) + { + ConsoleHelper.Info("Cancelled"); + return; + } + if (!CurrentWallet.VerifyPassword(password)) + { + ConsoleHelper.Error("Incorrect password"); + return; + } + var snapshot = NeoSystem.StoreView; + Transaction tx; + AssetDescriptor descriptor = new(snapshot, NeoSystem.Settings, asset); + if (!BigDecimal.TryParse(amount, descriptor.Decimals, out BigDecimal decimalAmount) || decimalAmount.Sign <= 0) + { + ConsoleHelper.Error("Incorrect Amount Format"); + return; + } + try + { + tx = CurrentWallet.MakeTransaction(snapshot, new[] + { + new TransferOutput + { + AssetId = asset, + Value = decimalAmount, + ScriptHash = to, + Data = data + } + }, from: from, cosigners: signerAccounts?.Select(p => new Signer + { + // default access for transfers should be valid only for first invocation + Scopes = WitnessScope.CalledByEntry, + Account = p + }) + .ToArray() ?? Array.Empty()); + } + catch (Exception e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + return; + } + + if (tx == null) + { + ConsoleHelper.Warning("Insufficient funds"); + return; + } + + ConsoleHelper.Info("Network fee: ", + $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}\t", + "Total fee: ", + $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); + if (!ReadUserInput("Relay tx? (no|yes)").IsYes()) + { + return; + } + SignAndSendTx(NeoSystem.StoreView, tx); + } + + /// + /// Process "cancel" command + /// + /// conflict txid + /// Transaction's sender + /// Signer's accounts + [ConsoleCommand("cancel", Category = "Wallet Commands")] + private void OnCancelCommand(UInt256 txid, UInt160 sender = null, UInt160[] signerAccounts = null) + { + TransactionState state = NativeContract.Ledger.GetTransactionState(NeoSystem.StoreView, txid); + if (state != null) + { + ConsoleHelper.Error("This tx is already confirmed, can't be cancelled."); + return; + } + + var conflict = new TransactionAttribute[] { new Conflicts() { Hash = txid } }; + Signer[] signers = Array.Empty(); + if (!NoWallet() && sender != null) + { + if (signerAccounts == null) + signerAccounts = new UInt160[1] { sender }; + else if (signerAccounts.Contains(sender) && signerAccounts[0] != sender) + { + var signersList = signerAccounts.ToList(); + signersList.Remove(sender); + signerAccounts = signersList.Prepend(sender).ToArray(); + } + else if (!signerAccounts.Contains(sender)) + { + signerAccounts = signerAccounts.Prepend(sender).ToArray(); + } + signers = signerAccounts.Select(p => new Signer() { Account = p, Scopes = WitnessScope.None }).ToArray(); + } + + Transaction tx = new Transaction + { + Signers = signers, + Attributes = conflict, + Witnesses = Array.Empty(), + }; + + try + { + using ScriptBuilder scriptBuilder = new(); + scriptBuilder.Emit(OpCode.RET); + tx = CurrentWallet.MakeTransaction(NeoSystem.StoreView, scriptBuilder.ToArray(), sender, signers, conflict); + } + catch (InvalidOperationException e) + { + ConsoleHelper.Error(GetExceptionMessage(e)); + return; + } + + if (NeoSystem.MemPool.TryGetValue(txid, out Transaction conflictTx)) + { + tx.NetworkFee = Math.Max(tx.NetworkFee, conflictTx.NetworkFee) + 1; + } + else + { + var snapshot = NeoSystem.StoreView; + AssetDescriptor descriptor = new(snapshot, NeoSystem.Settings, NativeContract.GAS.Hash); + string extracFee = ReadUserInput("This tx is not in mempool, please input extra fee manually"); + if (!BigDecimal.TryParse(extracFee, descriptor.Decimals, out BigDecimal decimalExtraFee) || decimalExtraFee.Sign <= 0) + { + ConsoleHelper.Error("Incorrect Amount Format"); + return; + } + tx.NetworkFee += (long)decimalExtraFee.Value; + }; + + ConsoleHelper.Info("Network fee: ", + $"{new BigDecimal((BigInteger)tx.NetworkFee, NativeContract.GAS.Decimals)}\t", + "Total fee: ", + $"{new BigDecimal((BigInteger)(tx.SystemFee + tx.NetworkFee), NativeContract.GAS.Decimals)} GAS"); + if (!ReadUserInput("Relay tx? (no|yes)").IsYes()) + { + return; + } + SignAndSendTx(NeoSystem.StoreView, tx); + } + + /// + /// Process "show gas" command + /// + [ConsoleCommand("show gas", Category = "Wallet Commands")] + private void OnShowGasCommand() + { + if (NoWallet()) return; + BigInteger gas = BigInteger.Zero; + var snapshot = NeoSystem.StoreView; + uint height = NativeContract.Ledger.CurrentIndex(snapshot) + 1; + foreach (UInt160 account in CurrentWallet.GetAccounts().Select(p => p.ScriptHash)) + gas += NativeContract.NEO.UnclaimedGas(snapshot, account, height); + ConsoleHelper.Info("Unclaimed gas: ", new BigDecimal(gas, NativeContract.GAS.Decimals).ToString()); + } + + /// + /// Process "change password" command + /// + [ConsoleCommand("change password", Category = "Wallet Commands")] + private void OnChangePasswordCommand() + { + if (NoWallet()) return; + string oldPassword = ReadUserInput("password", true); + if (oldPassword.Length == 0) + { + ConsoleHelper.Info("Cancelled"); + return; + } + if (!CurrentWallet.VerifyPassword(oldPassword)) + { + ConsoleHelper.Error("Incorrect password"); + return; + } + string newPassword = ReadUserInput("New password", true); + string newPasswordReEntered = ReadUserInput("Re-Enter Password", true); + if (!newPassword.Equals(newPasswordReEntered)) + { + ConsoleHelper.Error("Two passwords entered are inconsistent!"); + return; + } + + if (CurrentWallet is NEP6Wallet wallet) + { + string backupFile = wallet.Path + ".bak"; + if (!File.Exists(wallet.Path) || File.Exists(backupFile)) + { + ConsoleHelper.Error("Wallet backup fail"); + return; + } + try + { + File.Copy(wallet.Path, backupFile); + } + catch (IOException) + { + ConsoleHelper.Error("Wallet backup fail"); + return; + } + } + + bool succeed = CurrentWallet.ChangePassword(oldPassword, newPassword); + if (succeed) + { + if (CurrentWallet is NEP6Wallet nep6Wallet) + nep6Wallet.Save(); + Console.WriteLine("Password changed successfully"); + } + else + { + ConsoleHelper.Error("Failed to change password"); + } + } + + private void SignAndSendTx(DataCache snapshot, Transaction tx) + { + ContractParametersContext context; + try + { + context = new ContractParametersContext(snapshot, tx, _neoSystem.Settings.Network); + } + catch (InvalidOperationException e) + { + ConsoleHelper.Error("Failed creating contract params: " + GetExceptionMessage(e)); + throw; + } + CurrentWallet.Sign(context); + if (context.Completed) + { + tx.Witnesses = context.GetWitnesses(); + NeoSystem.Blockchain.Tell(tx); + ConsoleHelper.Info("Signed and relayed transaction with hash:\n", $"{tx.Hash}"); + } + else + { + ConsoleHelper.Info("Incomplete signature:\n", $"{context}"); + } + } + } +} diff --git a/src/Neo.CLI/CLI/MainService.cs b/src/Neo.CLI/CLI/MainService.cs new file mode 100644 index 0000000000..7beea39310 --- /dev/null +++ b/src/Neo.CLI/CLI/MainService.cs @@ -0,0 +1,609 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.ConsoleService; +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.Json; +using Neo.Ledger; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.Plugins; +using Neo.SmartContract; +using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net; +using System.Numerics; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using Array = System.Array; + +namespace Neo.CLI +{ + public partial class MainService : ConsoleServiceBase, IWalletProvider + { + public event EventHandler WalletChanged; + + public const long TestModeGas = 20_00000000; + + private Wallet _currentWallet; + public LocalNode LocalNode; + + public Wallet CurrentWallet + { + get => _currentWallet; + private set + { + _currentWallet = value; + WalletChanged?.Invoke(this, value); + } + } + + private NeoSystem _neoSystem; + public NeoSystem NeoSystem + { + get => _neoSystem; + private set => _neoSystem = value; + } + + protected override string Prompt => "neo"; + public override string ServiceName => "NEO-CLI"; + + /// + /// Constructor + /// + public MainService() : base() + { + RegisterCommandHandler(false, str => StringToAddress(str, NeoSystem.Settings.AddressVersion)); + RegisterCommandHandler(false, UInt256.Parse); + RegisterCommandHandler(str => str.Select(u => UInt256.Parse(u.Trim())).ToArray()); + RegisterCommandHandler(arr => arr.Select(str => StringToAddress(str, NeoSystem.Settings.AddressVersion)).ToArray()); + RegisterCommandHandler(str => ECPoint.Parse(str.Trim(), ECCurve.Secp256r1)); + RegisterCommandHandler(str => str.Select(u => ECPoint.Parse(u.Trim(), ECCurve.Secp256r1)).ToArray()); + RegisterCommandHandler(str => JToken.Parse(str)); + RegisterCommandHandler(str => (JObject)JToken.Parse(str)); + RegisterCommandHandler(str => decimal.Parse(str, CultureInfo.InvariantCulture)); + RegisterCommandHandler(obj => (JArray)obj); + + RegisterCommand(this); + + Initialize_Logger(); + } + + internal static UInt160 StringToAddress(string input, byte version) + { + switch (input.ToLowerInvariant()) + { + case "neo": return NativeContract.NEO.Hash; + case "gas": return NativeContract.GAS.Hash; + } + + // Try to parse as UInt160 + + if (UInt160.TryParse(input, out var addr)) + { + return addr; + } + + // Accept wallet format + + return input.ToScriptHash(version); + } + + Wallet IWalletProvider.GetWallet() + { + return CurrentWallet; + } + + public override void RunConsole() + { + Console.ForegroundColor = ConsoleColor.DarkGreen; + + var cliV = Assembly.GetAssembly(typeof(Program)).GetVersion(); + var neoV = Assembly.GetAssembly(typeof(NeoSystem)).GetVersion(); + var vmV = Assembly.GetAssembly(typeof(ExecutionEngine)).GetVersion(); + Console.WriteLine($"{ServiceName} v{cliV} - NEO v{neoV} - NEO-VM v{vmV}"); + Console.WriteLine(); + + base.RunConsole(); + } + + public void CreateWallet(string path, string password, bool createDefaultAccount = true) + { + Wallet wallet = Wallet.Create(null, path, password, NeoSystem.Settings); + if (wallet == null) + { + ConsoleHelper.Warning("Wallet files in that format are not supported, please use a .json or .db3 file extension."); + return; + } + if (createDefaultAccount) + { + WalletAccount account = wallet.CreateAccount(); + ConsoleHelper.Info(" Address: ", account.Address); + ConsoleHelper.Info(" Pubkey: ", account.GetKey().PublicKey.EncodePoint(true).ToHexString()); + ConsoleHelper.Info("ScriptHash: ", $"{account.ScriptHash}"); + } + wallet.Save(); + CurrentWallet = wallet; + } + + private IEnumerable GetBlocks(Stream stream, bool read_start = false) + { + using BinaryReader r = new BinaryReader(stream); + uint start = read_start ? r.ReadUInt32() : 0; + uint count = r.ReadUInt32(); + uint end = start + count - 1; + uint currentHeight = NativeContract.Ledger.CurrentIndex(NeoSystem.StoreView); + if (end <= currentHeight) yield break; + for (uint height = start; height <= end; height++) + { + var size = r.ReadInt32(); + if (size > Message.PayloadMaxSize) + throw new ArgumentException($"Block {height} exceeds the maximum allowed size"); + + byte[] array = r.ReadBytes(size); + if (height > currentHeight) + { + Block block = array.AsSerializable(); + yield return block; + } + } + } + + private IEnumerable GetBlocksFromFile() + { + const string pathAcc = "chain.acc"; + if (File.Exists(pathAcc)) + using (FileStream fs = new FileStream(pathAcc, FileMode.Open, FileAccess.Read, FileShare.Read)) + foreach (var block in GetBlocks(fs)) + yield return block; + + const string pathAccZip = pathAcc + ".zip"; + if (File.Exists(pathAccZip)) + using (FileStream fs = new FileStream(pathAccZip, FileMode.Open, FileAccess.Read, FileShare.Read)) + using (ZipArchive zip = new ZipArchive(fs, ZipArchiveMode.Read)) + using (Stream zs = zip.GetEntry(pathAcc).Open()) + foreach (var block in GetBlocks(zs)) + yield return block; + + var paths = Directory.EnumerateFiles(".", "chain.*.acc", SearchOption.TopDirectoryOnly).Concat(Directory.EnumerateFiles(".", "chain.*.acc.zip", SearchOption.TopDirectoryOnly)).Select(p => new + { + FileName = Path.GetFileName(p), + Start = uint.Parse(Regex.Match(p, @"\d+").Value), + IsCompressed = p.EndsWith(".zip") + }).OrderBy(p => p.Start); + + uint height = NativeContract.Ledger.CurrentIndex(NeoSystem.StoreView); + foreach (var path in paths) + { + if (path.Start > height + 1) break; + if (path.IsCompressed) + using (FileStream fs = new FileStream(path.FileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + using (ZipArchive zip = new ZipArchive(fs, ZipArchiveMode.Read)) + using (Stream zs = zip.GetEntry(Path.GetFileNameWithoutExtension(path.FileName)).Open()) + foreach (var block in GetBlocks(zs, true)) + yield return block; + else + using (FileStream fs = new FileStream(path.FileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + foreach (var block in GetBlocks(fs, true)) + yield return block; + } + } + + private bool NoWallet() + { + if (CurrentWallet != null) return false; + ConsoleHelper.Error("You have to open the wallet first."); + return true; + } + + private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, JObject data, out NefFile nef, out ContractManifest manifest) + { + if (string.IsNullOrEmpty(manifestFilePath)) + { + manifestFilePath = Path.ChangeExtension(nefFilePath, ".manifest.json"); + } + + // Read manifest + + var info = new FileInfo(manifestFilePath); + if (!info.Exists || info.Length >= Transaction.MaxTransactionSize) + { + throw new ArgumentException(nameof(manifestFilePath)); + } + + manifest = ContractManifest.Parse(File.ReadAllBytes(manifestFilePath)); + + // Read nef + + info = new FileInfo(nefFilePath); + if (!info.Exists || info.Length >= Transaction.MaxTransactionSize) + { + throw new ArgumentException(nameof(nefFilePath)); + } + + nef = File.ReadAllBytes(nefFilePath).AsSerializable(); + + ContractParameter dataParameter = null; + if (data is not null) + try + { + dataParameter = ContractParameter.FromJson(data); + } + catch + { + throw new FormatException("invalid data"); + } + + // Basic script checks + nef.Script.IsScriptValid(manifest.Abi); + + // Build script + + using (ScriptBuilder sb = new ScriptBuilder()) + { + if (dataParameter is not null) + sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", nef.ToArray(), manifest.ToJson().ToString(), dataParameter); + else + sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", nef.ToArray(), manifest.ToJson().ToString()); + return sb.ToArray(); + } + } + + private byte[] LoadUpdateScript(UInt160 scriptHash, string nefFilePath, string manifestFilePath, JObject data, out NefFile nef, out ContractManifest manifest) + { + if (string.IsNullOrEmpty(manifestFilePath)) + { + manifestFilePath = Path.ChangeExtension(nefFilePath, ".manifest.json"); + } + + // Read manifest + + var info = new FileInfo(manifestFilePath); + if (!info.Exists || info.Length >= Transaction.MaxTransactionSize) + { + throw new ArgumentException(nameof(manifestFilePath)); + } + + manifest = ContractManifest.Parse(File.ReadAllBytes(manifestFilePath)); + + // Read nef + + info = new FileInfo(nefFilePath); + if (!info.Exists || info.Length >= Transaction.MaxTransactionSize) + { + throw new ArgumentException(nameof(nefFilePath)); + } + + nef = File.ReadAllBytes(nefFilePath).AsSerializable(); + + ContractParameter dataParameter = null; + if (data is not null) + try + { + dataParameter = ContractParameter.FromJson(data); + } + catch + { + throw new FormatException("invalid data"); + } + + // Basic script checks + nef.Script.IsScriptValid(manifest.Abi); + + // Build script + + using (ScriptBuilder sb = new ScriptBuilder()) + { + if (dataParameter is null) + sb.EmitDynamicCall(scriptHash, "update", nef.ToArray(), manifest.ToJson().ToString()); + else + sb.EmitDynamicCall(scriptHash, "update", nef.ToArray(), manifest.ToJson().ToString(), dataParameter); + return sb.ToArray(); + } + } + + public override void OnStart(string[] args) + { + base.OnStart(args); + Start(args); + } + + public override void OnStop() + { + base.OnStop(); + Stop(); + } + + public void OpenWallet(string path, string password) + { + if (!File.Exists(path)) + { + throw new FileNotFoundException(); + } + + CurrentWallet = Wallet.Open(path, password, NeoSystem.Settings) ?? throw new NotSupportedException(); + } + + public async void Start(string[] args) + { + if (NeoSystem != null) return; + bool verifyImport = true; + for (int i = 0; i < args.Length; i++) + switch (args[i]) + { + case "/noverify": + case "--noverify": + verifyImport = false; + break; + } + + ProtocolSettings protocol = ProtocolSettings.Load("config.json"); + + NeoSystem = new NeoSystem(protocol, Settings.Default.Storage.Engine, string.Format(Settings.Default.Storage.Path, protocol.Network.ToString("X8"))); + NeoSystem.AddService(this); + + LocalNode = NeoSystem.LocalNode.Ask(new LocalNode.GetInstance()).Result; + + foreach (var plugin in Plugin.Plugins) + { + // Register plugins commands + + RegisterCommand(plugin, plugin.Name); + } + + using (IEnumerator blocksBeingImported = GetBlocksFromFile().GetEnumerator()) + { + while (true) + { + List blocksToImport = new List(); + for (int i = 0; i < 10; i++) + { + if (!blocksBeingImported.MoveNext()) break; + blocksToImport.Add(blocksBeingImported.Current); + } + if (blocksToImport.Count == 0) break; + await NeoSystem.Blockchain.Ask(new Blockchain.Import + { + Blocks = blocksToImport, + Verify = verifyImport + }); + if (NeoSystem is null) return; + } + } + NeoSystem.StartNode(new ChannelsConfig + { + Tcp = new IPEndPoint(IPAddress.Any, Settings.Default.P2P.Port), + WebSocket = new IPEndPoint(IPAddress.Any, Settings.Default.P2P.WsPort), + MinDesiredConnections = Settings.Default.P2P.MinDesiredConnections, + MaxConnections = Settings.Default.P2P.MaxConnections, + MaxConnectionsPerAddress = Settings.Default.P2P.MaxConnectionsPerAddress + }); + + if (Settings.Default.UnlockWallet.IsActive) + { + try + { + OpenWallet(Settings.Default.UnlockWallet.Path, Settings.Default.UnlockWallet.Password); + } + catch (FileNotFoundException) + { + ConsoleHelper.Warning($"wallet file \"{Settings.Default.UnlockWallet.Path}\" not found."); + } + catch (System.Security.Cryptography.CryptographicException) + { + ConsoleHelper.Error($"Failed to open file \"{Settings.Default.UnlockWallet.Path}\""); + } + catch (Exception ex) + { + ConsoleHelper.Error(ex.GetBaseException().Message); + } + } + } + + public void Stop() + { + Dispose_Logger(); + Interlocked.Exchange(ref _neoSystem, null)?.Dispose(); + } + + private void WriteBlocks(uint start, uint count, string path, bool writeStart) + { + uint end = start + count - 1; + using FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.WriteThrough); + if (fs.Length > 0) + { + byte[] buffer = new byte[sizeof(uint)]; + if (writeStart) + { + fs.Seek(sizeof(uint), SeekOrigin.Begin); + fs.Read(buffer, 0, buffer.Length); + start += BitConverter.ToUInt32(buffer, 0); + fs.Seek(sizeof(uint), SeekOrigin.Begin); + } + else + { + fs.Read(buffer, 0, buffer.Length); + start = BitConverter.ToUInt32(buffer, 0); + fs.Seek(0, SeekOrigin.Begin); + } + } + else + { + if (writeStart) + { + fs.Write(BitConverter.GetBytes(start), 0, sizeof(uint)); + } + } + if (start <= end) + fs.Write(BitConverter.GetBytes(count), 0, sizeof(uint)); + fs.Seek(0, SeekOrigin.End); + Console.WriteLine("Export block from " + start + " to " + end); + + using (var percent = new ConsolePercent(start, end)) + { + for (uint i = start; i <= end; i++) + { + Block block = NativeContract.Ledger.GetBlock(NeoSystem.StoreView, i); + byte[] array = block.ToArray(); + fs.Write(BitConverter.GetBytes(array.Length), 0, sizeof(int)); + fs.Write(array, 0, array.Length); + percent.Value = i; + } + } + } + + private static void WriteLineWithoutFlicker(string message = "", int maxWidth = 80) + { + if (message.Length > 0) Console.Write(message); + var spacesToErase = maxWidth - message.Length; + if (spacesToErase < 0) spacesToErase = 0; + Console.WriteLine(new string(' ', spacesToErase)); + } + + /// + /// Make and send transaction with script, sender + /// + /// script + /// sender + /// Max fee for running the script + private void SendTransaction(byte[] script, UInt160 account = null, long gas = TestModeGas) + { + Signer[] signers = Array.Empty(); + 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: ", $"'{Convert.ToBase64String(tx.Script.Span)}'"); + + 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)); + } + } + + /// + /// Process "invoke" command + /// + /// Script hash + /// Operation + /// Result + /// Transaction + /// Contract parameters + /// Show result stack if it is true + /// Max fee for running the script + /// Return true if it was successful + private bool OnInvokeWithResult(UInt160 scriptHash, string operation, out StackItem result, IVerifiable verifiable = null, JArray contractParameters = null, bool showStack = true, long gas = TestModeGas) + { + List parameters = new List(); + + if (contractParameters != null) + { + foreach (var contractParameter in contractParameters) + { + parameters.Add(ContractParameter.FromJson((JObject)contractParameter)); + } + } + + ContractState contract = NativeContract.ContractManagement.GetContract(NeoSystem.StoreView, scriptHash); + if (contract == null) + { + ConsoleHelper.Error("Contract does not exist."); + result = StackItem.Null; + return false; + } + else + { + if (contract.Manifest.Abi.GetMethod(operation, parameters.Count) == null) + { + ConsoleHelper.Error("This method does not not exist in this contract."); + result = StackItem.Null; + return false; + } + } + + byte[] script; + + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitDynamicCall(scriptHash, operation, parameters.ToArray()); + script = scriptBuilder.ToArray(); + ConsoleHelper.Info("Invoking script with: ", $"'{script.ToBase64String()}'"); + } + + if (verifiable is Transaction tx) + { + tx.Script = script; + } + + using ApplicationEngine engine = ApplicationEngine.Run(script, NeoSystem.StoreView, container: verifiable, settings: NeoSystem.Settings, gas: gas); + PrintExecutionOutput(engine, showStack); + result = engine.State == VMState.FAULT ? null : engine.ResultStack.Peek(); + return engine.State != VMState.FAULT; + } + + private void PrintExecutionOutput(ApplicationEngine engine, bool showStack = true) + { + ConsoleHelper.Info("VM State: ", engine.State.ToString()); + ConsoleHelper.Info("Gas Consumed: ", new BigDecimal((BigInteger)engine.GasConsumed, NativeContract.GAS.Decimals).ToString()); + + if (showStack) + ConsoleHelper.Info("Result Stack: ", new JArray(engine.ResultStack.Select(p => p.ToJson())).ToString()); + + if (engine.State == VMState.FAULT) + ConsoleHelper.Error(GetExceptionMessage(engine.FaultException)); + } + + static string GetExceptionMessage(Exception exception) + { + if (exception == null) return "Engine faulted."; + + if (exception.InnerException != null) + { + return GetExceptionMessage(exception.InnerException); + } + + return exception.Message; + } + } +} diff --git a/src/Neo.CLI/Dockerfile b/src/Neo.CLI/Dockerfile new file mode 100644 index 0000000000..7b67a6812d --- /dev/null +++ b/src/Neo.CLI/Dockerfile @@ -0,0 +1,20 @@ +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:7.0 AS Build + +# Run this from the repository root folder +COPY src . +COPY NuGet.Config /Neo.CLI + +WORKDIR /Neo.CLI +RUN dotnet restore && dotnet publish -f net7.0 -c Release -o /app + +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/aspnet:7.0 AS Final +RUN apt-get update && apt-get install -y \ + screen \ + libleveldb-dev \ + sqlite3 +RUN rm -rf /var/lib/apt/lists/* + +WORKDIR /Neo.CLI +COPY --from=Build /app . + +ENTRYPOINT ["screen","-DmS","node","dotnet","neo-cli.dll","-r"] diff --git a/src/Neo.CLI/Extensions.cs b/src/Neo.CLI/Extensions.cs new file mode 100644 index 0000000000..d3dd1aa5ed --- /dev/null +++ b/src/Neo.CLI/Extensions.cs @@ -0,0 +1,28 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.Linq; +using System.Reflection; + +namespace Neo +{ + /// + /// Extension methods + /// + internal static class Extensions + { + public static string GetVersion(this Assembly assembly) + { + CustomAttributeData attribute = assembly.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(AssemblyInformationalVersionAttribute)); + if (attribute == null) return assembly.GetName().Version.ToString(3); + return (string)attribute.ConstructorArguments[0].Value; + } + } +} diff --git a/src/Neo.CLI/Neo.CLI.csproj b/src/Neo.CLI/Neo.CLI.csproj new file mode 100644 index 0000000000..19f92a92cc --- /dev/null +++ b/src/Neo.CLI/Neo.CLI.csproj @@ -0,0 +1,29 @@ + + + + Neo.CLI + neo-cli + Exe + Neo.CLI + Neo + Neo.CLI + neo.ico + + + + + + + + + PreserveNewest + PreserveNewest + + + + + + + + + diff --git a/src/Neo.CLI/Program.cs b/src/Neo.CLI/Program.cs new file mode 100644 index 0000000000..8a12b7dddb --- /dev/null +++ b/src/Neo.CLI/Program.cs @@ -0,0 +1,23 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.CLI; + +namespace Neo +{ + static class Program + { + static void Main(string[] args) + { + var mainService = new MainService(); + mainService.Run(args); + } + } +} diff --git a/src/Neo.CLI/Settings.cs b/src/Neo.CLI/Settings.cs new file mode 100644 index 0000000000..ace4cb4863 --- /dev/null +++ b/src/Neo.CLI/Settings.cs @@ -0,0 +1,120 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-cli is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Microsoft.Extensions.Configuration; +using Neo.Network.P2P; +using System.Threading; + +namespace Neo +{ + public class Settings + { + public LoggerSettings Logger { get; } + public StorageSettings Storage { get; } + public P2PSettings P2P { get; } + public UnlockWalletSettings UnlockWallet { get; } + + static Settings _default; + + static bool UpdateDefault(IConfiguration configuration) + { + var settings = new Settings(configuration.GetSection("ApplicationConfiguration")); + return null == Interlocked.CompareExchange(ref _default, settings, null); + } + + public static bool Initialize(IConfiguration configuration) + { + return UpdateDefault(configuration); + } + + public static Settings Default + { + get + { + if (_default == null) + { + IConfigurationRoot config = new ConfigurationBuilder().AddJsonFile("config.json", optional: true).Build(); + Initialize(config); + } + + return _default; + } + } + + public Settings(IConfigurationSection section) + { + this.Logger = new LoggerSettings(section.GetSection("Logger")); + this.Storage = new StorageSettings(section.GetSection("Storage")); + this.P2P = new P2PSettings(section.GetSection("P2P")); + this.UnlockWallet = new UnlockWalletSettings(section.GetSection("UnlockWallet")); + } + } + + public class LoggerSettings + { + public string Path { get; } + public bool ConsoleOutput { get; } + public bool Active { get; } + + public LoggerSettings(IConfigurationSection section) + { + this.Path = section.GetValue("Path", "Logs"); + this.ConsoleOutput = section.GetValue("ConsoleOutput", false); + this.Active = section.GetValue("Active", false); + } + } + + public class StorageSettings + { + public string Engine { get; } + public string Path { get; } + + public StorageSettings(IConfigurationSection section) + { + this.Engine = section.GetValue("Engine", "LevelDBStore"); + this.Path = section.GetValue("Path", "Data_LevelDB_{0}"); + } + } + + public class P2PSettings + { + public ushort Port { get; } + public ushort WsPort { get; } + public int MinDesiredConnections { get; } + public int MaxConnections { get; } + public int MaxConnectionsPerAddress { get; } + + public P2PSettings(IConfigurationSection section) + { + this.Port = ushort.Parse(section.GetValue("Port", "10333")); + this.WsPort = ushort.Parse(section.GetValue("WsPort", "10334")); + this.MinDesiredConnections = section.GetValue("MinDesiredConnections", Peer.DefaultMinDesiredConnections); + this.MaxConnections = section.GetValue("MaxConnections", Peer.DefaultMaxConnections); + this.MaxConnectionsPerAddress = section.GetValue("MaxConnectionsPerAddress", 3); + } + } + + public class UnlockWalletSettings + { + public string Path { get; } + public string Password { get; } + public bool IsActive { get; } + + public UnlockWalletSettings(IConfigurationSection section) + { + if (section.Exists()) + { + this.Path = section.GetValue("Path", ""); + this.Password = section.GetValue("Password", ""); + this.IsActive = bool.Parse(section.GetValue("IsActive", "false")); + } + } + } +} diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json new file mode 100644 index 0000000000..1e1b5fc92d --- /dev/null +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -0,0 +1,53 @@ +{ + "ApplicationConfiguration": { + "Logger": { + "Path": "Logs", + "ConsoleOutput": false, + "Active": false + }, + "Storage": { + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" + }, + "P2P": { + "Port": 40333, + "WsPort": 40334, + "MinDesiredConnections": 10, + "MaxConnections": 40, + "MaxConnectionsPerAddress": 3 + }, + "UnlockWallet": { + "Path": "", + "Password": "", + "IsActive": false + } + }, + "ProtocolConfiguration": { + "Network": 91414437, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 512, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086", + "039a9db2a30942b1843db673aeb0d4fd6433f74cec1d879de6343cb9fcf7628fa4", + "0366d255e7ce23ea6f7f1e4bedf5cbafe598705b47e6ec213ef13b2f0819e8ab33", + "023f9cb7bbe154d529d5c719fdc39feaa831a43ae03d2a4280575b60f52fa7bc52", + "039ba959e0ab6dc616df8b803692f1c30ba9071b76b05535eb994bf5bbc402ad5f", + "035a2a18cddafa25ad353dea5e6730a1b9fcb4b918c4a0303c4387bb9c3b816adf", + "031f4d9c66f2ec348832c48fd3a16dfaeb59e85f557ae1e07f6696d0375c64f97b" + ], + "SeedList": [ + "morph1.fs.neo.org:40333", + "morph2.fs.neo.org:40333", + "morph3.fs.neo.org:40333", + "morph4.fs.neo.org:40333", + "morph5.fs.neo.org:40333", + "morph6.fs.neo.org:40333", + "morph7.fs.neo.org:40333" + ] + } +} diff --git a/src/Neo.CLI/config.fs.testnet.json b/src/Neo.CLI/config.fs.testnet.json new file mode 100644 index 0000000000..5e827a8480 --- /dev/null +++ b/src/Neo.CLI/config.fs.testnet.json @@ -0,0 +1,53 @@ +{ + "ApplicationConfiguration": { + "Logger": { + "Path": "Logs", + "ConsoleOutput": false, + "Active": false + }, + "Storage": { + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" + }, + "P2P": { + "Port": 50333, + "WsPort": 50334, + "MinDesiredConnections": 10, + "MaxConnections": 40, + "MaxConnectionsPerAddress": 3 + }, + "UnlockWallet": { + "Path": "", + "Password": "", + "IsActive": false + } + }, + "ProtocolConfiguration": { + "Network": 91466898, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 512, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "02082828ec6efc92e5e7790da851be72d2091a961c1ac9a1772acbf181ac56b831", + "02b2bcf7e09c0237ab6ef21808e6f7546329823bc6b43488335bd357aea443fabe", + "03577029a5072ebbab12d2495b59e2cf27afb37f9640c1c1354f1bdd221e6fb82d", + "03e6ea086e4b42fa5f0535179862db7eea7e44644e5e9608d6131aa48868c12cfc", + "0379328ab4907ea7c47f61e5c9d2c78c39dc9d1c4341ca496376070a0a5e20131e", + "02f8af6440dfe0e676ae2bb6727e5cc31a6f2459e29f48e85428862b7577dbc203", + "02e19c0634c85d35937699cdeaa10595ec2e18bfe86ba0494cf6c5c6861c66b97d" + ], + "SeedList": [ + "morph01.testnet.fs.neo.org:50333", + "morph02.testnet.fs.neo.org:50333", + "morph03.testnet.fs.neo.org:50333", + "morph04.testnet.fs.neo.org:50333", + "morph05.testnet.fs.neo.org:50333", + "morph06.testnet.fs.neo.org:50333", + "morph07.testnet.fs.neo.org:50333" + ] + } +} diff --git a/src/Neo.CLI/config.json b/src/Neo.CLI/config.json new file mode 100644 index 0000000000..6c9423ed05 --- /dev/null +++ b/src/Neo.CLI/config.json @@ -0,0 +1,69 @@ +{ + "ApplicationConfiguration": { + "Logger": { + "Path": "Logs", + "ConsoleOutput": false, + "Active": false + }, + "Storage": { + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" + }, + "P2P": { + "Port": 10333, + "WsPort": 10334, + "MinDesiredConnections": 10, + "MaxConnections": 40, + "MaxConnectionsPerAddress": 3 + }, + "UnlockWallet": { + "Path": "", + "Password": "", + "IsActive": false + } + }, + "ProtocolConfiguration": { + "Network": 860833102, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 512, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "Hardforks": { + "HF_Aspidochelone": 1730000, + "HF_Basilisk": 4120000 + }, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", + "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", + "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", + "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", + "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", + "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", + "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", + "023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", + "03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", + "03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", + "03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", + "02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", + "03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", + "0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", + "020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", + "0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", + "03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", + "02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", + "0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", + "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", + "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" + ], + "SeedList": [ + "seed1.neo.org:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed4.neo.org:10333", + "seed5.neo.org:10333" + ] + } +} diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json new file mode 100644 index 0000000000..6c9423ed05 --- /dev/null +++ b/src/Neo.CLI/config.mainnet.json @@ -0,0 +1,69 @@ +{ + "ApplicationConfiguration": { + "Logger": { + "Path": "Logs", + "ConsoleOutput": false, + "Active": false + }, + "Storage": { + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" + }, + "P2P": { + "Port": 10333, + "WsPort": 10334, + "MinDesiredConnections": 10, + "MaxConnections": 40, + "MaxConnectionsPerAddress": 3 + }, + "UnlockWallet": { + "Path": "", + "Password": "", + "IsActive": false + } + }, + "ProtocolConfiguration": { + "Network": 860833102, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 512, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "Hardforks": { + "HF_Aspidochelone": 1730000, + "HF_Basilisk": 4120000 + }, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", + "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", + "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", + "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", + "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", + "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", + "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", + "023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", + "03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", + "03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", + "03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", + "02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", + "03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", + "0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", + "020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", + "0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", + "03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", + "02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", + "0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", + "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", + "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" + ], + "SeedList": [ + "seed1.neo.org:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed4.neo.org:10333", + "seed5.neo.org:10333" + ] + } +} diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json new file mode 100644 index 0000000000..1d118016a3 --- /dev/null +++ b/src/Neo.CLI/config.testnet.json @@ -0,0 +1,69 @@ +{ + "ApplicationConfiguration": { + "Logger": { + "Path": "Logs", + "ConsoleOutput": false, + "Active": false + }, + "Storage": { + "Engine": "LevelDBStore", + "Path": "Data_LevelDB_{0}" + }, + "P2P": { + "Port": 20333, + "WsPort": 20334, + "MinDesiredConnections": 10, + "MaxConnections": 40, + "MaxConnectionsPerAddress": 3 + }, + "UnlockWallet": { + "Path": "", + "Password": "", + "IsActive": false + } + }, + "ProtocolConfiguration": { + "Network": 894710606, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 5000, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "Hardforks": { + "HF_Aspidochelone": 210000, + "HF_Basilisk": 2680000 + }, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", + "03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", + "02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", + "03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806", + "02a7834be9b32e2981d157cb5bbd3acb42cfd11ea5c3b10224d7a44e98c5910f1b", + "0214baf0ceea3a66f17e7e1e839ea25fd8bed6cd82e6bb6e68250189065f44ff01", + "030205e9cefaea5a1dfc580af20c8d5aa2468bb0148f1a5e4605fc622c80e604ba", + "025831cee3708e87d78211bec0d1bfee9f4c85ae784762f042e7f31c0d40c329b8", + "02cf9dc6e85d581480d91e88e8cbeaa0c153a046e89ded08b4cefd851e1d7325b5", + "03840415b0a0fcf066bcc3dc92d8349ebd33a6ab1402ef649bae00e5d9f5840828", + "026328aae34f149853430f526ecaa9cf9c8d78a4ea82d08bdf63dd03c4d0693be6", + "02c69a8d084ee7319cfecf5161ff257aa2d1f53e79bf6c6f164cff5d94675c38b3", + "0207da870cedb777fceff948641021714ec815110ca111ccc7a54c168e065bda70", + "035056669864feea401d8c31e447fb82dd29f342a9476cfd449584ce2a6165e4d7", + "0370c75c54445565df62cfe2e76fbec4ba00d1298867972213530cae6d418da636", + "03957af9e77282ae3263544b7b2458903624adc3f5dee303957cb6570524a5f254", + "03d84d22b8753cf225d263a3a782a4e16ca72ef323cfde04977c74f14873ab1e4c", + "02147c1b1d5728e1954958daff2f88ee2fa50a06890a8a9db3fa9e972b66ae559f", + "03c609bea5a4825908027e4ab217e7efc06e311f19ecad9d417089f14927a173d5", + "0231edee3978d46c335e851c76059166eb8878516f459e085c0dd092f0f1d51c21", + "03184b018d6b2bc093e535519732b3fd3f7551c8cffaf4621dd5a0b89482ca66c9" + ], + "SeedList": [ + "seed1t5.neo.org:20333", + "seed2t5.neo.org:20333", + "seed3t5.neo.org:20333", + "seed4t5.neo.org:20333", + "seed5t5.neo.org:20333" + ] + } +} diff --git a/src/Neo.CLI/neo.ico b/src/Neo.CLI/neo.ico new file mode 100644 index 0000000000000000000000000000000000000000..60786c424d8ec4c41a72a023d1aead2a8995a515 GIT binary patch literal 21317 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 literal 0 HcmV?d00001 diff --git a/src/Neo.ConsoleService/CommandQuoteToken.cs b/src/Neo.ConsoleService/CommandQuoteToken.cs new file mode 100644 index 0000000000..497a956a7f --- /dev/null +++ b/src/Neo.ConsoleService/CommandQuoteToken.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Diagnostics; + +namespace Neo.ConsoleService +{ + [DebuggerDisplay("Value={Value}, Value={Value}")] + internal class CommandQuoteToken : CommandToken + { + /// + /// Constructor + /// + /// Offset + /// Value + public CommandQuoteToken(int offset, char value) : base(CommandTokenType.Quote, offset) + { + if (value != '\'' && value != '"') + { + throw new ArgumentException("Not valid quote"); + } + + Value = value.ToString(); + } + + /// + /// Parse command line quotes + /// + /// Command line + /// Index + /// CommandQuoteToken + internal static CommandQuoteToken Parse(string commandLine, ref int index) + { + var c = commandLine[index]; + + if (c == '\'' || c == '"') + { + index++; + return new CommandQuoteToken(index - 1, c); + } + + throw new ArgumentException("No quote found"); + } + } +} diff --git a/src/Neo.ConsoleService/CommandSpaceToken.cs b/src/Neo.ConsoleService/CommandSpaceToken.cs new file mode 100644 index 0000000000..9a59f14410 --- /dev/null +++ b/src/Neo.ConsoleService/CommandSpaceToken.cs @@ -0,0 +1,64 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Diagnostics; + +namespace Neo.ConsoleService +{ + [DebuggerDisplay("Value={Value}, Count={Count}")] + internal class CommandSpaceToken : CommandToken + { + /// + /// Count + /// + public int Count { get; } + + /// + /// Constructor + /// + /// Offset + /// Count + public CommandSpaceToken(int offset, int count) : base(CommandTokenType.Space, offset) + { + Value = "".PadLeft(count, ' '); + Count = count; + } + + /// + /// Parse command line spaces + /// + /// Command line + /// Index + /// CommandSpaceToken + internal static CommandSpaceToken Parse(string commandLine, ref int index) + { + int offset = index; + int count = 0; + + for (int ix = index, max = commandLine.Length; ix < max; ix++) + { + if (commandLine[ix] == ' ') + { + count++; + } + else + { + break; + } + } + + if (count == 0) throw new ArgumentException("No spaces found"); + + index += count; + return new CommandSpaceToken(offset, count); + } + } +} diff --git a/src/Neo.ConsoleService/CommandStringToken.cs b/src/Neo.ConsoleService/CommandStringToken.cs new file mode 100644 index 0000000000..c22d989996 --- /dev/null +++ b/src/Neo.ConsoleService/CommandStringToken.cs @@ -0,0 +1,90 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Diagnostics; + +namespace Neo.ConsoleService +{ + [DebuggerDisplay("Value={Value}, RequireQuotes={RequireQuotes}")] + internal class CommandStringToken : CommandToken + { + /// + /// Require quotes + /// + public bool RequireQuotes { get; } + + /// + /// Constructor + /// + /// Offset + /// Value + public CommandStringToken(int offset, string value) : base(CommandTokenType.String, offset) + { + Value = value; + RequireQuotes = value.IndexOfAny(new char[] { '\'', '"' }) != -1; + } + + /// + /// Parse command line spaces + /// + /// Command line + /// Index + /// Quote (could be null) + /// CommandSpaceToken + internal static CommandStringToken Parse(string commandLine, ref int index, CommandQuoteToken quote) + { + int end; + int offset = index; + + if (quote != null) + { + var ix = index; + + do + { + end = commandLine.IndexOf(quote.Value[0], ix + 1); + + if (end == -1) + { + throw new ArgumentException("String not closed"); + } + + if (IsScaped(commandLine, end - 1)) + { + ix = end; + end = -1; + } + } + while (end < 0); + } + else + { + end = commandLine.IndexOf(' ', index + 1); + } + + if (end == -1) + { + end = commandLine.Length; + } + + var ret = new CommandStringToken(offset, commandLine.Substring(index, end - index)); + index += end - index; + return ret; + } + + private static bool IsScaped(string commandLine, int index) + { + // TODO: Scape the scape + + return (commandLine[index] == '\\'); + } + } +} diff --git a/src/Neo.ConsoleService/CommandToken.cs b/src/Neo.ConsoleService/CommandToken.cs new file mode 100644 index 0000000000..a8b8a47fd6 --- /dev/null +++ b/src/Neo.ConsoleService/CommandToken.cs @@ -0,0 +1,225 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Neo.ConsoleService +{ + internal abstract class CommandToken + { + /// + /// Offset + /// + public int Offset { get; } + + /// + /// Type + /// + public CommandTokenType Type { get; } + + /// + /// Value + /// + public string Value { get; protected init; } + + /// + /// Constructor + /// + /// Type + /// Offset + protected CommandToken(CommandTokenType type, int offset) + { + Type = type; + Offset = offset; + } + + /// + /// Parse command line + /// + /// Command line + /// + public static IEnumerable Parse(string commandLine) + { + CommandToken lastToken = null; + + for (int index = 0, count = commandLine.Length; index < count;) + { + switch (commandLine[index]) + { + case ' ': + { + lastToken = CommandSpaceToken.Parse(commandLine, ref index); + yield return lastToken; + break; + } + case '"': + case '\'': + { + // "'" + if (lastToken is CommandQuoteToken quote && quote.Value[0] != commandLine[index]) + { + goto default; + } + + lastToken = CommandQuoteToken.Parse(commandLine, ref index); + yield return lastToken; + break; + } + default: + { + lastToken = CommandStringToken.Parse(commandLine, ref index, + lastToken is CommandQuoteToken quote ? quote : null); + + yield return lastToken; + break; + } + } + } + } + + /// + /// Create string arguments + /// + /// Tokens + /// Remove escape + /// Arguments + public static string[] ToArguments(IEnumerable tokens, bool removeEscape = true) + { + var list = new List(); + + CommandToken lastToken = null; + + foreach (var token in tokens) + { + if (token is CommandStringToken str) + { + if (removeEscape && lastToken is CommandQuoteToken quote) + { + // Remove escape + + list.Add(str.Value.Replace("\\" + quote.Value, quote.Value)); + } + else + { + list.Add(str.Value); + } + } + + lastToken = token; + } + + return list.ToArray(); + } + + /// + /// Create a string from token list + /// + /// Tokens + /// String + public static string ToString(IEnumerable tokens) + { + var sb = new StringBuilder(); + + foreach (var token in tokens) + { + sb.Append(token.Value); + } + + return sb.ToString(); + } + + /// + /// Trim + /// + /// Args + public static void Trim(List args) + { + // Trim start + + while (args.Count > 0 && args[0].Type == CommandTokenType.Space) + { + args.RemoveAt(0); + } + + // Trim end + + while (args.Count > 0 && args[^1].Type == CommandTokenType.Space) + { + args.RemoveAt(args.Count - 1); + } + } + + /// + /// Read String + /// + /// Args + /// Consume all if not quoted + /// String + public static string ReadString(List args, bool consumeAll) + { + Trim(args); + + var quoted = false; + + if (args.Count > 0 && args[0].Type == CommandTokenType.Quote) + { + quoted = true; + args.RemoveAt(0); + } + else + { + if (consumeAll) + { + // Return all if it's not quoted + + var ret = ToString(args); + args.Clear(); + + return ret; + } + } + + if (args.Count > 0) + { + switch (args[0]) + { + case CommandQuoteToken _: + { + if (quoted) + { + args.RemoveAt(0); + return ""; + } + + throw new ArgumentException(); + } + case CommandSpaceToken _: throw new ArgumentException(); + case CommandStringToken str: + { + args.RemoveAt(0); + + if (quoted && args.Count > 0 && args[0].Type == CommandTokenType.Quote) + { + // Remove last quote + + args.RemoveAt(0); + } + + return str.Value; + } + } + } + + return null; + } + } +} diff --git a/src/Neo.ConsoleService/CommandTokenType.cs b/src/Neo.ConsoleService/CommandTokenType.cs new file mode 100644 index 0000000000..828ea34b4e --- /dev/null +++ b/src/Neo.ConsoleService/CommandTokenType.cs @@ -0,0 +1,19 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.ConsoleService +{ + internal enum CommandTokenType : byte + { + String, + Space, + Quote, + } +} diff --git a/src/Neo.ConsoleService/ConsoleColorSet.cs b/src/Neo.ConsoleService/ConsoleColorSet.cs new file mode 100644 index 0000000000..465ab39f98 --- /dev/null +++ b/src/Neo.ConsoleService/ConsoleColorSet.cs @@ -0,0 +1,51 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; + +namespace Neo.ConsoleService +{ + public class ConsoleColorSet + { + public ConsoleColor Foreground; + public ConsoleColor Background; + + /// + /// Create a new color set with the current console colors + /// + public ConsoleColorSet() : this(Console.ForegroundColor, Console.BackgroundColor) { } + + /// + /// Create a new color set + /// + /// Foreground color + public ConsoleColorSet(ConsoleColor foreground) : this(foreground, Console.BackgroundColor) { } + + /// + /// Create a new color set + /// + /// Foreground color + /// Background color + public ConsoleColorSet(ConsoleColor foreground, ConsoleColor background) + { + Foreground = foreground; + Background = background; + } + + /// + /// Apply the current set + /// + public void Apply() + { + Console.ForegroundColor = Foreground; + Console.BackgroundColor = Background; + } + } +} diff --git a/src/Neo.ConsoleService/ConsoleCommandAttribute.cs b/src/Neo.ConsoleService/ConsoleCommandAttribute.cs new file mode 100644 index 0000000000..b880c03bec --- /dev/null +++ b/src/Neo.ConsoleService/ConsoleCommandAttribute.cs @@ -0,0 +1,45 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Diagnostics; +using System.Linq; + +namespace Neo.ConsoleService +{ + [DebuggerDisplay("Verbs={string.Join(' ',Verbs)}")] + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public class ConsoleCommandAttribute : Attribute + { + /// + /// Verbs + /// + public string[] Verbs { get; } + + /// + /// Category + /// + public string Category { get; set; } + + /// + /// Description + /// + public string Description { get; set; } + + /// + /// Constructor + /// + /// Verbs + public ConsoleCommandAttribute(string verbs) + { + Verbs = verbs.Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(u => u.ToLowerInvariant()).ToArray(); + } + } +} diff --git a/src/Neo.ConsoleService/ConsoleCommandMethod.cs b/src/Neo.ConsoleService/ConsoleCommandMethod.cs new file mode 100644 index 0000000000..55176ecbc3 --- /dev/null +++ b/src/Neo.ConsoleService/ConsoleCommandMethod.cs @@ -0,0 +1,120 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; + +namespace Neo.ConsoleService +{ + [DebuggerDisplay("Key={Key}")] + internal class ConsoleCommandMethod + { + /// + /// Verbs + /// + public string[] Verbs { get; } + + /// + /// Key + /// + public string Key => string.Join(' ', Verbs); + + /// + /// Help category + /// + public string HelpCategory { get; set; } + + /// + /// Help message + /// + public string HelpMessage { get; set; } + + /// + /// Instance + /// + public object Instance { get; } + + /// + /// Method + /// + public MethodInfo Method { get; } + + /// + /// Set instance command + /// + /// Instance + /// Method + /// Attribute + public ConsoleCommandMethod(object instance, MethodInfo method, ConsoleCommandAttribute attribute) + { + Method = method; + Instance = instance; + Verbs = attribute.Verbs; + HelpCategory = attribute.Category; + HelpMessage = attribute.Description; + } + + /// + /// Is this command + /// + /// Tokens + /// Consumed Arguments + /// True if is this command + public bool IsThisCommand(CommandToken[] tokens, out int consumedArgs) + { + int checks = Verbs.Length; + bool quoted = false; + var tokenList = new List(tokens); + + while (checks > 0 && tokenList.Count > 0) + { + switch (tokenList[0]) + { + case CommandSpaceToken _: + { + tokenList.RemoveAt(0); + break; + } + case CommandQuoteToken _: + { + quoted = !quoted; + tokenList.RemoveAt(0); + break; + } + case CommandStringToken str: + { + if (Verbs[^checks] != str.Value.ToLowerInvariant()) + { + consumedArgs = 0; + return false; + } + + checks--; + tokenList.RemoveAt(0); + break; + } + } + } + + if (quoted && tokenList.Count > 0 && tokenList[0].Type == CommandTokenType.Quote) + { + tokenList.RemoveAt(0); + } + + // Trim start + + while (tokenList.Count > 0 && tokenList[0].Type == CommandTokenType.Space) tokenList.RemoveAt(0); + + consumedArgs = tokens.Length - tokenList.Count; + return checks == 0; + } + } +} diff --git a/src/Neo.ConsoleService/ConsoleHelper.cs b/src/Neo.ConsoleService/ConsoleHelper.cs new file mode 100644 index 0000000000..fdf6f180cd --- /dev/null +++ b/src/Neo.ConsoleService/ConsoleHelper.cs @@ -0,0 +1,65 @@ +using System; + +namespace Neo.ConsoleService +{ + public static class ConsoleHelper + { + private static readonly ConsoleColorSet InfoColor = new(ConsoleColor.Cyan); + private static readonly ConsoleColorSet WarningColor = new(ConsoleColor.Yellow); + private static readonly ConsoleColorSet ErrorColor = new(ConsoleColor.Red); + + /// + /// Info handles message in the format of "[tag]:[message]", + /// avoid using Info if the `tag` is too long + /// + /// The log message in pairs of (tag, message) + public static void Info(params string[] values) + { + var currentColor = new ConsoleColorSet(); + + for (int i = 0; i < values.Length; i++) + { + if (i % 2 == 0) + InfoColor.Apply(); + else + currentColor.Apply(); + Console.Write(values[i]); + } + currentColor.Apply(); + Console.WriteLine(); + } + + /// + /// Use warning if something unexpected happens + /// or the execution result is not correct. + /// Also use warning if you just want to remind + /// user of doing something. + /// + /// Warning message + public static void Warning(string msg) + { + Log("Warning", WarningColor, msg); + } + + /// + /// Use Error if the verification or input format check fails + /// or exception that breaks the execution of interactive + /// command throws. + /// + /// Error message + public static void Error(string msg) + { + Log("Error", ErrorColor, msg); + } + + private static void Log(string tag, ConsoleColorSet colorSet, string msg) + { + var currentColor = new ConsoleColorSet(); + + colorSet.Apply(); + Console.Write($"{tag}: "); + currentColor.Apply(); + Console.WriteLine(msg); + } + } +} diff --git a/src/Neo.ConsoleService/ConsoleServiceBase.cs b/src/Neo.ConsoleService/ConsoleServiceBase.cs new file mode 100644 index 0000000000..ae55b5fd76 --- /dev/null +++ b/src/Neo.ConsoleService/ConsoleServiceBase.cs @@ -0,0 +1,627 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Runtime.Loader; +using System.Security; +using System.ServiceProcess; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Neo.ConsoleService +{ + public abstract class ConsoleServiceBase + { + protected virtual string Depends => null; + protected virtual string Prompt => "service"; + + public abstract string ServiceName { get; } + + protected bool ShowPrompt { get; set; } = true; + public bool ReadingPassword { get; set; } = false; + + private bool _running; + private readonly CancellationTokenSource _shutdownTokenSource = new(); + private readonly CountdownEvent _shutdownAcknowledged = new(1); + private readonly Dictionary> _verbs = new(); + private readonly Dictionary _instances = new(); + private readonly Dictionary, bool, object>> _handlers = new(); + + private bool OnCommand(string commandLine) + { + if (string.IsNullOrEmpty(commandLine)) + { + return true; + } + + string possibleHelp = null; + var commandArgs = CommandToken.Parse(commandLine).ToArray(); + var availableCommands = new List<(ConsoleCommandMethod Command, object[] Arguments)>(); + + foreach (var entries in _verbs.Values) + { + foreach (var command in entries) + { + if (command.IsThisCommand(commandArgs, out var consumedArgs)) + { + var arguments = new List(); + var args = commandArgs.Skip(consumedArgs).ToList(); + + CommandSpaceToken.Trim(args); + + try + { + var parameters = command.Method.GetParameters(); + + foreach (var arg in parameters) + { + // Parse argument + + if (TryProcessValue(arg.ParameterType, args, arg == parameters.Last(), out var value)) + { + arguments.Add(value); + } + else + { + if (arg.HasDefaultValue) + { + arguments.Add(arg.DefaultValue); + } + else + { + throw new ArgumentException(arg.Name); + } + } + } + + availableCommands.Add((command, arguments.ToArray())); + } + catch + { + // Skip parse errors + possibleHelp = command.Key; + } + } + } + } + + switch (availableCommands.Count) + { + case 0: + { + if (!string.IsNullOrEmpty(possibleHelp)) + { + OnHelpCommand(possibleHelp); + return true; + } + + return false; + } + case 1: + { + var (command, arguments) = availableCommands[0]; + object result = command.Method.Invoke(command.Instance, arguments); + if (result is Task task) task.Wait(); + return true; + } + default: + { + // Show Ambiguous call + + throw new ArgumentException("Ambiguous calls for: " + string.Join(',', availableCommands.Select(u => u.Command.Key).Distinct())); + } + } + } + + private bool TryProcessValue(Type parameterType, List args, bool canConsumeAll, out object value) + { + if (args.Count > 0) + { + if (_handlers.TryGetValue(parameterType, out var handler)) + { + value = handler(args, canConsumeAll); + return true; + } + + if (parameterType.IsEnum) + { + var arg = CommandToken.ReadString(args, canConsumeAll); + value = Enum.Parse(parameterType, arg.Trim(), true); + return true; + } + } + + value = null; + return false; + } + + #region Commands + + /// + /// Process "help" command + /// + [ConsoleCommand("help", Category = "Base Commands")] + protected void OnHelpCommand(string key) + { + var withHelp = new List(); + + // Try to find a plugin with this name + + if (_instances.TryGetValue(key.Trim().ToLowerInvariant(), out var instance)) + { + // Filter only the help of this plugin + + key = ""; + foreach (var commands in _verbs.Values.Select(u => u)) + { + withHelp.AddRange + ( + commands.Where(u => !string.IsNullOrEmpty(u.HelpCategory) && u.Instance == instance) + ); + } + } + else + { + // Fetch commands + + foreach (var commands in _verbs.Values.Select(u => u)) + { + withHelp.AddRange(commands.Where(u => !string.IsNullOrEmpty(u.HelpCategory))); + } + } + + // Sort and show + + withHelp.Sort((a, b) => + { + var cate = string.Compare(a.HelpCategory, b.HelpCategory, StringComparison.Ordinal); + if (cate == 0) + { + cate = string.Compare(a.Key, b.Key, StringComparison.Ordinal); + } + return cate; + }); + + if (string.IsNullOrEmpty(key) || key.Equals("help", StringComparison.InvariantCultureIgnoreCase)) + { + string last = null; + foreach (var command in withHelp) + { + if (last != command.HelpCategory) + { + Console.WriteLine($"{command.HelpCategory}:"); + last = command.HelpCategory; + } + + Console.Write($"\t{command.Key}"); + Console.WriteLine(" " + string.Join(' ', + command.Method.GetParameters() + .Select(u => u.HasDefaultValue ? $"[{u.Name}={(u.DefaultValue == null ? "null" : u.DefaultValue.ToString())}]" : $"<{u.Name}>")) + ); + } + } + else + { + // Show help for this specific command + + string last = null; + string lastKey = null; + bool found = false; + + foreach (var command in withHelp.Where(u => u.Key == key)) + { + found = true; + + if (last != command.HelpMessage) + { + Console.WriteLine($"{command.HelpMessage}"); + last = command.HelpMessage; + } + + if (lastKey != command.Key) + { + Console.WriteLine("You can call this command like this:"); + lastKey = command.Key; + } + + Console.Write($"\t{command.Key}"); + Console.WriteLine(" " + string.Join(' ', + command.Method.GetParameters() + .Select(u => u.HasDefaultValue ? $"[{u.Name}={u.DefaultValue?.ToString() ?? "null"}]" : $"<{u.Name}>")) + ); + } + + if (!found) + { + throw new ArgumentException("Command not found."); + } + } + } + + /// + /// Process "clear" command + /// + [ConsoleCommand("clear", Category = "Base Commands", Description = "Clear is used in order to clean the console output.")] + protected void OnClear() + { + Console.Clear(); + } + + /// + /// Process "version" command + /// + [ConsoleCommand("version", Category = "Base Commands", Description = "Show the current version.")] + protected void OnVersion() + { + Console.WriteLine(Assembly.GetEntryAssembly().GetName().Version); + } + + /// + /// Process "exit" command + /// + [ConsoleCommand("exit", Category = "Base Commands", Description = "Exit the node.")] + protected void OnExit() + { + _running = false; + } + + #endregion + + public virtual void OnStart(string[] args) + { + // Register sigterm event handler + AssemblyLoadContext.Default.Unloading += SigTermEventHandler; + // Register sigint event handler + Console.CancelKeyPress += CancelHandler; + } + + public virtual void OnStop() + { + _shutdownAcknowledged.Signal(); + } + + public string ReadUserInput(string prompt, bool password = false) + { + const string t = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + var sb = new StringBuilder(); + + if (!string.IsNullOrEmpty(prompt)) + { + Console.Write(prompt + ": "); + } + + if (password) ReadingPassword = true; + var prevForeground = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Yellow; + + if (Console.IsInputRedirected) + { + // neo-gui Console require it + sb.Append(Console.ReadLine()); + } + else + { + ConsoleKeyInfo key; + do + { + key = Console.ReadKey(true); + + if (t.IndexOf(key.KeyChar) != -1) + { + sb.Append(key.KeyChar); + Console.Write(password ? '*' : key.KeyChar); + } + else if (key.Key == ConsoleKey.Backspace && sb.Length > 0) + { + sb.Length--; + Console.Write("\b \b"); + } + } while (key.Key != ConsoleKey.Enter); + } + + Console.ForegroundColor = prevForeground; + if (password) ReadingPassword = false; + Console.WriteLine(); + return sb.ToString(); + } + + public SecureString ReadSecureString(string prompt) + { + const string t = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + SecureString securePwd = new SecureString(); + ConsoleKeyInfo key; + + if (!string.IsNullOrEmpty(prompt)) + { + Console.Write(prompt + ": "); + } + + ReadingPassword = true; + Console.ForegroundColor = ConsoleColor.Yellow; + + do + { + key = Console.ReadKey(true); + if (t.IndexOf(key.KeyChar) != -1) + { + securePwd.AppendChar(key.KeyChar); + Console.Write('*'); + } + else if (key.Key == ConsoleKey.Backspace && securePwd.Length > 0) + { + securePwd.RemoveAt(securePwd.Length - 1); + Console.Write(key.KeyChar); + Console.Write(' '); + Console.Write(key.KeyChar); + } + } while (key.Key != ConsoleKey.Enter); + + Console.ForegroundColor = ConsoleColor.White; + ReadingPassword = false; + Console.WriteLine(); + securePwd.MakeReadOnly(); + return securePwd; + } + + private void TriggerGracefulShutdown() + { + if (!_running) return; + _running = false; + _shutdownTokenSource.Cancel(); + // Wait for us to have triggered shutdown. + _shutdownAcknowledged.Wait(); + } + + private void SigTermEventHandler(AssemblyLoadContext obj) + { + TriggerGracefulShutdown(); + } + + private void CancelHandler(object sender, ConsoleCancelEventArgs e) + { + e.Cancel = true; + TriggerGracefulShutdown(); + } + + /// + /// Constructor + /// + protected ConsoleServiceBase() + { + // Register self commands + + RegisterCommandHandler(CommandToken.ReadString); + + RegisterCommandHandler((args, canConsumeAll) => + { + if (canConsumeAll) + { + var ret = CommandToken.ToString(args); + args.Clear(); + return ret.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); + } + + return CommandToken.ReadString(args, false).Split(',', ' '); + }); + + RegisterCommandHandler(false, str => byte.Parse(str)); + RegisterCommandHandler(false, str => str == "1" || str == "yes" || str == "y" || bool.Parse(str)); + RegisterCommandHandler(false, str => ushort.Parse(str)); + RegisterCommandHandler(false, str => uint.Parse(str)); + RegisterCommandHandler(false, IPAddress.Parse); + } + + /// + /// Register command handler + /// + /// Return type + /// Handler + private void RegisterCommandHandler(Func, bool, object> handler) + { + _handlers[typeof(TRet)] = handler; + } + + /// + /// Register command handler + /// + /// Base type + /// Return type + /// Can consume all + /// Handler + public void RegisterCommandHandler(bool canConsumeAll, Func handler) + { + _handlers[typeof(TRet)] = (args, _) => + { + var value = (T)_handlers[typeof(T)](args, canConsumeAll); + return handler(value); + }; + } + + /// + /// Register command handler + /// + /// Base type + /// Return type + /// Handler + public void RegisterCommandHandler(Func handler) + { + _handlers[typeof(TRet)] = (args, consumeAll) => + { + var value = (T)_handlers[typeof(T)](args, consumeAll); + return handler(value); + }; + } + + /// + /// Register commands + /// + /// Instance + /// Name + public void RegisterCommand(object instance, string name = null) + { + if (!string.IsNullOrEmpty(name)) + { + _instances.Add(name.ToLowerInvariant(), instance); + } + + foreach (var method in instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + { + foreach (var attribute in method.GetCustomAttributes()) + { + // Check handlers + + if (!method.GetParameters().All(u => u.ParameterType.IsEnum || _handlers.ContainsKey(u.ParameterType))) + { + throw new ArgumentException("Handler not found for the command: " + method); + } + + // Add command + + var command = new ConsoleCommandMethod(instance, method, attribute); + + if (!_verbs.TryGetValue(command.Key, out var commands)) + { + _verbs.Add(command.Key, new List(new[] { command })); + } + else + { + commands.Add(command); + } + } + } + } + + public void Run(string[] args) + { + if (Environment.UserInteractive) + { + if (args.Length > 0 && args[0] == "/install") + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + ConsoleHelper.Warning("Only support for installing services on Windows."); + return; + } + string arguments = string.Format("create {0} start= auto binPath= \"{1}\"", ServiceName, Process.GetCurrentProcess().MainModule.FileName); + if (!string.IsNullOrEmpty(Depends)) + { + arguments += string.Format(" depend= {0}", Depends); + } + Process process = Process.Start(new ProcessStartInfo + { + Arguments = arguments, + FileName = Path.Combine(Environment.SystemDirectory, "sc.exe"), + RedirectStandardOutput = true, + UseShellExecute = false + }); + process.WaitForExit(); + Console.Write(process.StandardOutput.ReadToEnd()); + } + else if (args.Length > 0 && args[0] == "/uninstall") + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + ConsoleHelper.Warning("Only support for installing services on Windows."); + return; + } + Process process = Process.Start(new ProcessStartInfo + { + Arguments = string.Format("delete {0}", ServiceName), + FileName = Path.Combine(Environment.SystemDirectory, "sc.exe"), + RedirectStandardOutput = true, + UseShellExecute = false + }); + process.WaitForExit(); + Console.Write(process.StandardOutput.ReadToEnd()); + } + else + { + OnStart(args); + RunConsole(); + OnStop(); + } + } + else + { + Debug.Assert(OperatingSystem.IsWindows()); + ServiceBase.Run(new ServiceProxy(this)); + } + } + + protected string ReadLine() + { + Task readLineTask = Task.Run(Console.ReadLine); + + try + { + readLineTask.Wait(_shutdownTokenSource.Token); + } + catch (OperationCanceledException) + { + return null; + } + + return readLineTask.Result; + } + + public virtual void RunConsole() + { + _running = true; + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + try + { + Console.Title = ServiceName; + } + catch { } + + Console.ForegroundColor = ConsoleColor.DarkGreen; + Console.SetIn(new StreamReader(Console.OpenStandardInput(), Console.InputEncoding, false, ushort.MaxValue)); + + while (_running) + { + if (ShowPrompt) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.Write($"{Prompt}> "); + } + + Console.ForegroundColor = ConsoleColor.Yellow; + string line = ReadLine()?.Trim(); + if (line == null) break; + Console.ForegroundColor = ConsoleColor.White; + + try + { + if (!OnCommand(line)) + { + ConsoleHelper.Error("Command not found"); + } + } + catch (TargetInvocationException ex) when (ex.InnerException is not null) + { + ConsoleHelper.Error(ex.InnerException.Message); + } + catch (Exception ex) + { + ConsoleHelper.Error(ex.Message); + } + } + + Console.ResetColor(); + } + } +} diff --git a/src/Neo.ConsoleService/Neo.ConsoleService.csproj b/src/Neo.ConsoleService/Neo.ConsoleService.csproj new file mode 100644 index 0000000000..c5ef250052 --- /dev/null +++ b/src/Neo.ConsoleService/Neo.ConsoleService.csproj @@ -0,0 +1,12 @@ + + + + 1.2.0 + + + + + + + + diff --git a/src/Neo.ConsoleService/Properties/AssemblyInfo.cs b/src/Neo.ConsoleService/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..661513fb43 --- /dev/null +++ b/src/Neo.ConsoleService/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Neo.ConsoleService.Tests")] diff --git a/src/Neo.ConsoleService/ServiceProxy.cs b/src/Neo.ConsoleService/ServiceProxy.cs new file mode 100644 index 0000000000..c8060f0d47 --- /dev/null +++ b/src/Neo.ConsoleService/ServiceProxy.cs @@ -0,0 +1,34 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The Neo.ConsoleService is free software distributed under the MIT +// software license, see the accompanying file LICENSE in the main directory +// of the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.ServiceProcess; + +namespace Neo.ConsoleService +{ + internal class ServiceProxy : ServiceBase + { + private readonly ConsoleServiceBase _service; + + public ServiceProxy(ConsoleServiceBase service) + { + this._service = service; + } + + protected override void OnStart(string[] args) + { + _service.OnStart(args); + } + + protected override void OnStop() + { + _service.OnStop(); + } + } +} diff --git a/src/Neo.GUI/GUI/BulkPayDialog.Designer.cs b/src/Neo.GUI/GUI/BulkPayDialog.Designer.cs new file mode 100644 index 0000000000..41ad15e57a --- /dev/null +++ b/src/Neo.GUI/GUI/BulkPayDialog.Designer.cs @@ -0,0 +1,129 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class BulkPayDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BulkPayDialog)); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.Name = "textBox3"; + this.textBox3.ReadOnly = true; + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.Name = "label4"; + // + // comboBox1 + // + resources.ApplyResources(this.comboBox1, "comboBox1"); + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Name = "comboBox1"; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox1 + // + this.textBox1.AcceptsReturn = true; + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged); + // + // BulkPayDialog + // + resources.ApplyResources(this, "$this"); + this.AcceptButton = this.button1; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label4); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.label3); + this.Controls.Add(this.button1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "BulkPayDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + } +} diff --git a/src/Neo.GUI/GUI/BulkPayDialog.cs b/src/Neo.GUI/GUI/BulkPayDialog.cs new file mode 100644 index 0000000000..b33cb9edec --- /dev/null +++ b/src/Neo.GUI/GUI/BulkPayDialog.cs @@ -0,0 +1,80 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Wallets; +using System; +using System.Linq; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + internal partial class BulkPayDialog : Form + { + public BulkPayDialog(AssetDescriptor asset = null) + { + InitializeComponent(); + if (asset == null) + { + foreach (UInt160 assetId in NEP5Watched) + { + try + { + comboBox1.Items.Add(new AssetDescriptor(Service.NeoSystem.StoreView, Service.NeoSystem.Settings, assetId)); + } + catch (ArgumentException) + { + continue; + } + } + } + else + { + comboBox1.Items.Add(asset); + comboBox1.SelectedIndex = 0; + comboBox1.Enabled = false; + } + } + + public TxOutListBoxItem[] GetOutputs() + { + AssetDescriptor asset = (AssetDescriptor)comboBox1.SelectedItem; + return textBox1.Lines.Where(p => !string.IsNullOrWhiteSpace(p)).Select(p => + { + string[] line = p.Split(new[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); + return new TxOutListBoxItem + { + AssetName = asset.AssetName, + AssetId = asset.AssetId, + Value = BigDecimal.Parse(line[1], asset.Decimals), + ScriptHash = line[0].ToScriptHash(Service.NeoSystem.Settings.AddressVersion) + }; + }).Where(p => p.Value.Value != 0).ToArray(); + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBox1.SelectedItem is AssetDescriptor asset) + { + textBox3.Text = Service.CurrentWallet.GetAvailable(Service.NeoSystem.StoreView, asset.AssetId).ToString(); + } + else + { + textBox3.Text = ""; + } + textBox1_TextChanged(this, EventArgs.Empty); + } + + private void textBox1_TextChanged(object sender, EventArgs e) + { + button1.Enabled = comboBox1.SelectedIndex >= 0 && textBox1.TextLength > 0; + } + } +} diff --git a/src/Neo.GUI/GUI/BulkPayDialog.es-ES.resx b/src/Neo.GUI/GUI/BulkPayDialog.es-ES.resx new file mode 100644 index 0000000000..3aa43a7bae --- /dev/null +++ b/src/Neo.GUI/GUI/BulkPayDialog.es-ES.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 24, 54 + + + 44, 17 + + + Saldo: + + + 22, 17 + + + 46, 17 + + + Activo: + + + Aceptar + + + Pagar a + + + Pago + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/BulkPayDialog.resx b/src/Neo.GUI/GUI/BulkPayDialog.resx new file mode 100644 index 0000000000..0a6c0c3d28 --- /dev/null +++ b/src/Neo.GUI/GUI/BulkPayDialog.resx @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Left, Right + + + + 74, 51 + + + 468, 23 + + + + 12 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + True + + + NoControl + + + 12, 54 + + + 56, 17 + + + 11 + + + Balance: + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Top, Left, Right + + + 74, 14 + + + 468, 25 + + + 10 + + + comboBox1 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + True + + + NoControl + + + 26, 17 + + + 42, 17 + + + 9 + + + Asset: + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Bottom, Right + + + False + + + NoControl + + + 467, 325 + + + 75, 23 + + + 17 + + + OK + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Top, Bottom, Left, Right + + + Fill + + + Consolas, 9pt + + + 3, 19 + + + True + + + Vertical + + + 524, 217 + + + 0 + + + False + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + 12, 80 + + + 530, 239 + + + 18 + + + Pay to + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 554, 360 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Payment + + + BulkPayDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/BulkPayDialog.zh-Hans.resx b/src/Neo.GUI/GUI/BulkPayDialog.zh-Hans.resx new file mode 100644 index 0000000000..e429e3bf5e --- /dev/null +++ b/src/Neo.GUI/GUI/BulkPayDialog.zh-Hans.resx @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 62, 51 + + + 480, 23 + + + 44, 17 + + + 余额: + + + 62, 14 + + + 480, 25 + + + 12, 17 + + + 44, 17 + + + 资产: + + + 确定 + + + 账户和金额 + + + 支付 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ChangePasswordDialog.Designer.cs b/src/Neo.GUI/GUI/ChangePasswordDialog.Designer.cs new file mode 100644 index 0000000000..0d9c6ea80c --- /dev/null +++ b/src/Neo.GUI/GUI/ChangePasswordDialog.Designer.cs @@ -0,0 +1,137 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ChangePasswordDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ChangePasswordDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.UseSystemPasswordChar = true; + this.textBox1.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.UseSystemPasswordChar = true; + this.textBox2.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.Name = "textBox3"; + this.textBox3.UseSystemPasswordChar = true; + this.textBox3.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // ChangePasswordDialog + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ChangePasswordDialog"; + this.ShowInTaskbar = false; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + } +} diff --git a/src/Neo.GUI/GUI/ChangePasswordDialog.cs b/src/Neo.GUI/GUI/ChangePasswordDialog.cs new file mode 100644 index 0000000000..7bda7e93a1 --- /dev/null +++ b/src/Neo.GUI/GUI/ChangePasswordDialog.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class ChangePasswordDialog : Form + { + public string OldPassword + { + get + { + return textBox1.Text; + } + set + { + textBox1.Text = value; + } + } + + public string NewPassword + { + get + { + return textBox2.Text; + } + set + { + textBox2.Text = value; + textBox3.Text = value; + } + } + + public ChangePasswordDialog() + { + InitializeComponent(); + } + + private void textBox_TextChanged(object sender, EventArgs e) + { + button1.Enabled = textBox1.TextLength > 0 && textBox2.TextLength > 0 && textBox3.Text == textBox2.Text; + } + } +} diff --git a/src/Neo.GUI/GUI/ChangePasswordDialog.es-ES.resx b/src/Neo.GUI/GUI/ChangePasswordDialog.es-ES.resx new file mode 100644 index 0000000000..27c58de2d0 --- /dev/null +++ b/src/Neo.GUI/GUI/ChangePasswordDialog.es-ES.resx @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 55, 15 + + + 115, 17 + + + Contraseña actual: + + + 177, 12 + + + 275, 23 + + + 55, 44 + + + 116, 17 + + + Nueva contraseña: + + + 177, 41 + + + 275, 23 + + + 159, 17 + + + Repetir nueva contraseña: + + + 177, 70 + + + 275, 23 + + + 296, 107 + + + Aceptar + + + 377, 107 + + + Cancelar + + + 464, 142 + + + Cambiar contraseña + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ChangePasswordDialog.resx b/src/Neo.GUI/GUI/ChangePasswordDialog.resx new file mode 100644 index 0000000000..89c4851043 --- /dev/null +++ b/src/Neo.GUI/GUI/ChangePasswordDialog.resx @@ -0,0 +1,369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 41, 15 + + + 92, 17 + + + 0 + + + Old Password: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + + Top, Left, Right + + + 139, 12 + + + 234, 23 + + + 1 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + True + + + NoControl + + + 36, 44 + + + 97, 17 + + + 2 + + + New Password: + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Top, Left, Right + + + 139, 41 + + + 234, 23 + + + 3 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + True + + + NoControl + + + 12, 73 + + + 121, 17 + + + 4 + + + Re-Enter Password: + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Top, Left, Right + + + 139, 70 + + + 234, 23 + + + 5 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Right + + + False + + + 217, 107 + + + 75, 23 + + + 6 + + + OK + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Bottom, Right + + + NoControl + + + 298, 107 + + + 75, 23 + + + 7 + + + Cancel + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 385, 142 + + + Microsoft YaHei UI, 9pt + + + 2, 2, 2, 2 + + + CenterScreen + + + Change Password + + + ChangePasswordDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ChangePasswordDialog.zh-Hans.resx b/src/Neo.GUI/GUI/ChangePasswordDialog.zh-Hans.resx new file mode 100644 index 0000000000..9ec5cb724c --- /dev/null +++ b/src/Neo.GUI/GUI/ChangePasswordDialog.zh-Hans.resx @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 24, 15 + + + 47, 17 + + + 旧密码: + + + 77, 12 + + + 296, 23 + + + 24, 44 + + + 47, 17 + + + 新密码: + + + 77, 41 + + + 296, 23 + + + 59, 17 + + + 重复密码: + + + 77, 70 + + + 296, 23 + + + 确定 + + + 取消 + + + 修改密码 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ConsoleForm.Designer.cs b/src/Neo.GUI/GUI/ConsoleForm.Designer.cs new file mode 100644 index 0000000000..e3fd639db0 --- /dev/null +++ b/src/Neo.GUI/GUI/ConsoleForm.Designer.cs @@ -0,0 +1,91 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ConsoleForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox1.Location = new System.Drawing.Point(12, 12); + this.textBox1.Font = new System.Drawing.Font("Consolas", 11.0f); + this.textBox1.MaxLength = 1048576; + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.textBox1.Size = new System.Drawing.Size(609, 367); + this.textBox1.TabIndex = 1; + // + // textBox2 + // + this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox2.Location = new System.Drawing.Point(12, 385); + this.textBox2.Font = new System.Drawing.Font("Consolas", 11.0f); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(609, 21); + this.textBox2.TabIndex = 0; + this.textBox2.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox2_KeyDown); + // + // ConsoleForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(633, 418); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.textBox1); + this.Name = "ConsoleForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Console"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox textBox2; + } +} diff --git a/src/Neo.GUI/GUI/ConsoleForm.cs b/src/Neo.GUI/GUI/ConsoleForm.cs new file mode 100644 index 0000000000..55deace519 --- /dev/null +++ b/src/Neo.GUI/GUI/ConsoleForm.cs @@ -0,0 +1,67 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.IO; +using System.Threading; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class ConsoleForm : Form + { + private Thread thread; + private readonly QueueReader queue = new QueueReader(); + + public ConsoleForm() + { + InitializeComponent(); + } + + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + Console.SetOut(new TextBoxWriter(textBox1)); + Console.SetIn(queue); + thread = new Thread(Program.Service.RunConsole); + thread.Start(); + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + queue.Enqueue($"exit{Environment.NewLine}"); + thread.Join(); + Console.SetIn(new StreamReader(Console.OpenStandardInput())); + Console.SetOut(new StreamWriter(Console.OpenStandardOutput())); + base.OnFormClosing(e); + } + + private void textBox2_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + e.SuppressKeyPress = true; + string line = $"{textBox2.Text}{Environment.NewLine}"; + textBox1.AppendText(Program.Service.ReadingPassword ? "***" : line); + switch (textBox2.Text.ToLower()) + { + case "clear": + textBox1.Clear(); + break; + case "exit": + Close(); + return; + } + queue.Enqueue(line); + textBox2.Clear(); + } + } + } +} diff --git a/src/Neo.GUI/GUI/ConsoleForm.resx b/src/Neo.GUI/GUI/ConsoleForm.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/src/Neo.GUI/GUI/ConsoleForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/CreateMultiSigContractDialog.Designer.cs b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.Designer.cs new file mode 100644 index 0000000000..e91c25c9b7 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.Designer.cs @@ -0,0 +1,153 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class CreateMultiSigContractDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CreateMultiSigContractDialog)); + this.button5 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + this.textBox5 = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.listBox1 = new System.Windows.Forms.ListBox(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.label6 = new System.Windows.Forms.Label(); + this.button6 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + this.SuspendLayout(); + // + // button5 + // + resources.ApplyResources(this.button5, "button5"); + this.button5.Name = "button5"; + this.button5.UseVisualStyleBackColor = true; + this.button5.Click += new System.EventHandler(this.button5_Click); + // + // button4 + // + resources.ApplyResources(this.button4, "button4"); + this.button4.Name = "button4"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // textBox5 + // + resources.ApplyResources(this.textBox5, "textBox5"); + this.textBox5.Name = "textBox5"; + this.textBox5.TextChanged += new System.EventHandler(this.textBox5_TextChanged); + // + // label7 + // + resources.ApplyResources(this.label7, "label7"); + this.label7.Name = "label7"; + // + // listBox1 + // + resources.ApplyResources(this.listBox1, "listBox1"); + this.listBox1.FormattingEnabled = true; + this.listBox1.Name = "listBox1"; + this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); + // + // numericUpDown2 + // + resources.ApplyResources(this.numericUpDown2, "numericUpDown2"); + this.numericUpDown2.Maximum = new decimal(new int[] { + 0, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.ValueChanged += new System.EventHandler(this.numericUpDown2_ValueChanged); + // + // label6 + // + resources.ApplyResources(this.label6, "label6"); + this.label6.Name = "label6"; + // + // button6 + // + resources.ApplyResources(this.button6, "button6"); + this.button6.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button6.Name = "button6"; + this.button6.UseVisualStyleBackColor = true; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // CreateMultiSigContractDialog + // + this.AcceptButton = this.button6; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button1; + this.Controls.Add(this.button1); + this.Controls.Add(this.button6); + this.Controls.Add(this.button5); + this.Controls.Add(this.button4); + this.Controls.Add(this.textBox5); + this.Controls.Add(this.label7); + this.Controls.Add(this.listBox1); + this.Controls.Add(this.numericUpDown2); + this.Controls.Add(this.label6); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CreateMultiSigContractDialog"; + this.ShowInTaskbar = false; + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button5; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.ListBox listBox1; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button button6; + private System.Windows.Forms.Button button1; + } +} diff --git a/src/Neo.GUI/GUI/CreateMultiSigContractDialog.cs b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.cs new file mode 100644 index 0000000000..b94e6c5b1f --- /dev/null +++ b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.cs @@ -0,0 +1,71 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Cryptography.ECC; +using Neo.SmartContract; +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + internal partial class CreateMultiSigContractDialog : Form + { + private ECPoint[] publicKeys; + + public CreateMultiSigContractDialog() + { + InitializeComponent(); + } + + public Contract GetContract() + { + publicKeys = listBox1.Items.OfType().Select(p => ECPoint.DecodePoint(p.HexToBytes(), ECCurve.Secp256r1)).ToArray(); + return Contract.CreateMultiSigContract((int)numericUpDown2.Value, publicKeys); + } + + public KeyPair GetKey() + { + HashSet hashSet = new HashSet(publicKeys); + return Service.CurrentWallet.GetAccounts().FirstOrDefault(p => p.HasKey && hashSet.Contains(p.GetKey().PublicKey))?.GetKey(); + } + + private void numericUpDown2_ValueChanged(object sender, EventArgs e) + { + button6.Enabled = numericUpDown2.Value > 0; + } + + private void listBox1_SelectedIndexChanged(object sender, EventArgs e) + { + button5.Enabled = listBox1.SelectedIndices.Count > 0; + } + + private void textBox5_TextChanged(object sender, EventArgs e) + { + button4.Enabled = textBox5.TextLength > 0; + } + + private void button4_Click(object sender, EventArgs e) + { + listBox1.Items.Add(textBox5.Text); + textBox5.Clear(); + numericUpDown2.Maximum = listBox1.Items.Count; + } + + private void button5_Click(object sender, EventArgs e) + { + listBox1.Items.RemoveAt(listBox1.SelectedIndex); + numericUpDown2.Maximum = listBox1.Items.Count; + } + } +} diff --git a/src/Neo.GUI/GUI/CreateMultiSigContractDialog.es-ES.resx b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.es-ES.resx new file mode 100644 index 0000000000..c5eefc3279 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.es-ES.resx @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 573, 246 + + + 542, 246 + + + 168, 246 + + + 368, 23 + + + 147, 17 + + + Lista de claves públicas: + + + 168, 41 + + + 430, 199 + + + 168, 12 + + + 442, 275 + + + Confirmar + + + 523, 275 + + + Cancelar + + + + NoControl + + + 29, 14 + + + 133, 17 + + + Nº mínimo de firmas: + + + 610, 310 + + + Contrato con múltiples firmas + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/CreateMultiSigContractDialog.resx b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.resx new file mode 100644 index 0000000000..fcd5dfc317 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.resx @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + False + + + + 425, 199 + + + 551, 310 + + + 114, 12 + + + button5 + + + $this + + + + 3, 4, 3, 4 + + + False + + + 514, 246 + + + True + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 12 + + + cancel + + + 5 + + + 14 + + + 12, 14 + + + button6 + + + textBox5 + + + 7, 17 + + + True + + + Min. Sig. Num.: + + + $this + + + Bottom, Right + + + 3 + + + 13 + + + Bottom, Right + + + 464, 275 + + + 114, 41 + + + 75, 23 + + + 93, 17 + + + confirm + + + $this + + + $this + + + numericUpDown2 + + + 483, 246 + + + 2 + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 7 + + + 114, 246 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 15 + + + CenterScreen + + + False + + + 363, 23 + + + label7 + + + Bottom, Right + + + 25, 23 + + + 197, 23 + + + $this + + + 1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 383, 275 + + + Bottom, Right + + + listBox1 + + + 7 + + + 6 + + + $this + + + 4 + + + 微软雅黑, 9pt + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bottom, Left, Right + + + button1 + + + False + + + 15, 41 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 11 + + + $this + + + 0 + + + 8 + + + CreateMultiSigContractDialog + + + $this + + + 25, 23 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + - + + + $this + + + button4 + + + 8 + + + True + + + 96, 17 + + + Multi-Signature + + + 10 + + + 75, 23 + + + 17 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 9 + + + label6 + + + Top, Bottom, Left, Right + + + Public Key List: + + + True + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/CreateMultiSigContractDialog.zh-Hans.resx b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.zh-Hans.resx new file mode 100644 index 0000000000..acd731d2a1 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateMultiSigContractDialog.zh-Hans.resx @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 491, 263 + + + 460, 263 + + + 99, 263 + + + 355, 23 + + + 34, 41 + + + 59, 17 + + + 公钥列表: + + + 99, 41 + + + 417, 216 + + + 99, 12 + + + 120, 23 + + + 83, 17 + + + 最小签名数量: + + + 360, 292 + + + 确定 + + + 441, 292 + + + 取消 + + + 528, 327 + + + 多方签名 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/CreateWalletDialog.cs b/src/Neo.GUI/GUI/CreateWalletDialog.cs new file mode 100644 index 0000000000..4573dad6d4 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateWalletDialog.cs @@ -0,0 +1,71 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class CreateWalletDialog : Form + { + public CreateWalletDialog() + { + InitializeComponent(); + } + + public string Password + { + get + { + return textBox2.Text; + } + set + { + textBox2.Text = value; + textBox3.Text = value; + } + } + + public string WalletPath + { + get + { + return textBox1.Text; + } + set + { + textBox1.Text = value; + } + } + + private void textBox_TextChanged(object sender, EventArgs e) + { + if (textBox1.TextLength == 0 || textBox2.TextLength == 0 || textBox3.TextLength == 0) + { + button2.Enabled = false; + return; + } + if (textBox2.Text != textBox3.Text) + { + button2.Enabled = false; + return; + } + button2.Enabled = true; + } + + private void button1_Click(object sender, EventArgs e) + { + if (saveFileDialog1.ShowDialog() == DialogResult.OK) + { + textBox1.Text = saveFileDialog1.FileName; + } + } + } +} diff --git a/src/Neo.GUI/GUI/CreateWalletDialog.designer.cs b/src/Neo.GUI/GUI/CreateWalletDialog.designer.cs new file mode 100644 index 0000000000..c4f41b6573 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateWalletDialog.designer.cs @@ -0,0 +1,143 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class CreateWalletDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CreateWalletDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.UseSystemPasswordChar = true; + this.textBox2.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.Name = "textBox3"; + this.textBox3.UseSystemPasswordChar = true; + this.textBox3.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // saveFileDialog1 + // + this.saveFileDialog1.DefaultExt = "json"; + resources.ApplyResources(this.saveFileDialog1, "saveFileDialog1"); + // + // CreateWalletDialog + // + this.AcceptButton = this.button2; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.button2); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CreateWalletDialog"; + this.ShowInTaskbar = false; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.SaveFileDialog saveFileDialog1; + } +} diff --git a/src/Neo.GUI/GUI/CreateWalletDialog.es-ES.resx b/src/Neo.GUI/GUI/CreateWalletDialog.es-ES.resx new file mode 100644 index 0000000000..09d7d9f325 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateWalletDialog.es-ES.resx @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 9, 16 + + + 137, 17 + + + Fichero de monedero: + + + 152, 13 + + + 293, 23 + + + Buscar... + + + 69, 51 + + + 77, 17 + + + Contraseña: + + + 152, 48 + + + 25, 84 + + + 121, 17 + + + Repetir contraseña: + + + 152, 81 + + + Confirmar + + + Nuevo monedero + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/CreateWalletDialog.resx b/src/Neo.GUI/GUI/CreateWalletDialog.resx new file mode 100644 index 0000000000..bfe06e458d --- /dev/null +++ b/src/Neo.GUI/GUI/CreateWalletDialog.resx @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + confirm + + + Wallet File: + + + Wallet File|*.json + + + $this + + + 5 + + + + 150, 23 + + + browse + + + label1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 87, 17 + + + $this + + + 7, 17 + + + 0 + + + label3 + + + + True + + + + Top, Right + + + 105, 48 + + + CenterScreen + + + $this + + + 12, 84 + + + 7 + + + $this + + + 75, 23 + + + 0 + + + 5 + + + 70, 17 + + + 340, 23 + + + 6 + + + 105, 13 + + + 9 + + + 6 + + + saveFileDialog1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 451, 12 + + + 4 + + + 67, 17 + + + $this + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + textBox1 + + + 2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 微软雅黑, 9pt + + + Re-Password: + + + 8 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + button1 + + + True + + + 451, 86 + + + True + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + label2 + + + 1 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + Top, Left, Right + + + Bottom, Right + + + 29, 16 + + + New Wallet + + + Password: + + + 7 + + + System.Windows.Forms.SaveFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 32, 51 + + + button2 + + + textBox3 + + + $this + + + 150, 23 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 105, 81 + + + 538, 121 + + + 75, 23 + + + CreateWalletDialog + + + textBox2 + + + 2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + + True + + + 17, 17 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/CreateWalletDialog.zh-Hans.resx b/src/Neo.GUI/GUI/CreateWalletDialog.zh-Hans.resx new file mode 100644 index 0000000000..ae934ad543 --- /dev/null +++ b/src/Neo.GUI/GUI/CreateWalletDialog.zh-Hans.resx @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 12, 15 + + + 83, 17 + + + 钱包文件位置: + + + 101, 12 + + + 289, 23 + + + 396, 12 + + + 浏览 + + + 60, 44 + + + 35, 17 + + + 密码: + + + 101, 41 + + + 36, 73 + + + 59, 17 + + + 重复密码: + + + 101, 70 + + + 396, 70 + + + 确定 + + + 钱包文件|*.json + + + 483, 105 + + + 新建钱包 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/DeployContractDialog.Designer.cs b/src/Neo.GUI/GUI/DeployContractDialog.Designer.cs new file mode 100644 index 0000000000..629b5e96dd --- /dev/null +++ b/src/Neo.GUI/GUI/DeployContractDialog.Designer.cs @@ -0,0 +1,308 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class DeployContractDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeployContractDialog)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox5 = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox7 = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.textBox6 = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.textBox9 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.textBox8 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.label8 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox5); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.textBox4); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.textBox3); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox5 + // + resources.ApplyResources(this.textBox5, "textBox5"); + this.textBox5.AcceptsReturn = true; + this.textBox5.AcceptsTab = true; + this.textBox5.Name = "textBox5"; + this.textBox5.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label5 + // + resources.ApplyResources(this.label5, "label5"); + this.label5.Name = "label5"; + // + // textBox4 + // + resources.ApplyResources(this.textBox4, "textBox4"); + this.textBox4.Name = "textBox4"; + this.textBox4.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.Name = "label4"; + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.Name = "textBox3"; + this.textBox3.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // groupBox2 + // + resources.ApplyResources(this.groupBox2, "groupBox2"); + this.groupBox2.Controls.Add(this.textBox7); + this.groupBox2.Controls.Add(this.label7); + this.groupBox2.Controls.Add(this.textBox6); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.TabStop = false; + // + // textBox7 + // + resources.ApplyResources(this.textBox7, "textBox7"); + this.textBox7.Name = "textBox7"; + // + // label7 + // + resources.ApplyResources(this.label7, "label7"); + this.label7.Name = "label7"; + // + // textBox6 + // + resources.ApplyResources(this.textBox6, "textBox6"); + this.textBox6.Name = "textBox6"; + // + // label6 + // + resources.ApplyResources(this.label6, "label6"); + this.label6.Name = "label6"; + // + // groupBox3 + // + resources.ApplyResources(this.groupBox3, "groupBox3"); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.checkBox2); + this.groupBox3.Controls.Add(this.checkBox3); + this.groupBox3.Controls.Add(this.textBox9); + this.groupBox3.Controls.Add(this.button1); + this.groupBox3.Controls.Add(this.checkBox1); + this.groupBox3.Controls.Add(this.textBox8); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.TabStop = false; + // + // textBox9 + // + resources.ApplyResources(this.textBox9, "textBox9"); + this.textBox9.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.textBox9.Name = "textBox9"; + this.textBox9.ReadOnly = true; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // checkBox1 + // + resources.ApplyResources(this.checkBox1, "checkBox1"); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // textBox8 + // + resources.ApplyResources(this.textBox8, "textBox8"); + this.textBox8.Name = "textBox8"; + this.textBox8.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + // + // openFileDialog1 + // + resources.ApplyResources(this.openFileDialog1, "openFileDialog1"); + this.openFileDialog1.DefaultExt = "avm"; + // + // checkBox2 + // + resources.ApplyResources(this.checkBox2, "checkBox2"); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.UseVisualStyleBackColor = true; + // + // checkBox3 + // + resources.ApplyResources(this.checkBox3, "checkBox3"); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.UseVisualStyleBackColor = true; + // + // label8 + // + resources.ApplyResources(this.label8, "label8"); + this.label8.Name = "label8"; + // + // DeployContractDialog + // + resources.ApplyResources(this, "$this"); + this.AcceptButton = this.button2; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button3; + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.button3); + this.Controls.Add(this.button2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DeployContractDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox textBox6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox textBox7; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.TextBox textBox8; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.TextBox textBox9; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.CheckBox checkBox3; + } +} diff --git a/src/Neo.GUI/GUI/DeployContractDialog.cs b/src/Neo.GUI/GUI/DeployContractDialog.cs new file mode 100644 index 0000000000..aa415ddd90 --- /dev/null +++ b/src/Neo.GUI/GUI/DeployContractDialog.cs @@ -0,0 +1,60 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using System; +using System.IO; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class DeployContractDialog : Form + { + public DeployContractDialog() + { + InitializeComponent(); + } + + public byte[] GetScript() + { + byte[] script = textBox8.Text.HexToBytes(); + string manifest = ""; + using ScriptBuilder sb = new ScriptBuilder(); + sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", script, manifest); + return sb.ToArray(); + } + + private void textBox_TextChanged(object sender, EventArgs e) + { + button2.Enabled = textBox1.TextLength > 0 + && textBox2.TextLength > 0 + && textBox3.TextLength > 0 + && textBox4.TextLength > 0 + && textBox5.TextLength > 0 + && textBox8.TextLength > 0; + try + { + textBox9.Text = textBox8.Text.HexToBytes().ToScriptHash().ToString(); + } + catch (FormatException) + { + textBox9.Text = ""; + } + } + + private void button1_Click(object sender, EventArgs e) + { + if (openFileDialog1.ShowDialog() != DialogResult.OK) return; + textBox8.Text = File.ReadAllBytes(openFileDialog1.FileName).ToHexString(); + } + } +} diff --git a/src/Neo.GUI/GUI/DeployContractDialog.es-ES.resx b/src/Neo.GUI/GUI/DeployContractDialog.es-ES.resx new file mode 100644 index 0000000000..7bd4a2e05b --- /dev/null +++ b/src/Neo.GUI/GUI/DeployContractDialog.es-ES.resx @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 3, 141 + + + 79, 17 + + + Descripción: + + + 31, 112 + + + 52, 17 + + + Correo: + + + 40, 83 + + + 43, 17 + + + Autor: + + + Versión: + + + 23, 25 + + + 60, 17 + + + Nombre: + + + 140, 51 + + + 374, 23 + + + 43, 54 + + + 91, 17 + + + Tipo devuelto: + + + 140, 22 + + + 374, 23 + + + 128, 17 + + + Lista de parámetros: + + + Metadatos + + + Cargar + + + 199, 21 + + + Es necesario almacenamiento + + + Código + + + 368, 530 + + + 83, 23 + + + Desplegar + + + Cancelar + + + Desplegar contrato + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/DeployContractDialog.resx b/src/Neo.GUI/GUI/DeployContractDialog.resx new file mode 100644 index 0000000000..16bd3de8c2 --- /dev/null +++ b/src/Neo.GUI/GUI/DeployContractDialog.resx @@ -0,0 +1,972 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Left, Right + + + Top, Bottom, Left, Right + + + + 114, 163 + + + 4, 4, 4, 4 + + + + True + + + Vertical + + + 545, 99 + + + 9 + + + textBox5 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + True + + + NoControl + + + 8, 165 + + + 4, 0, 4, 0 + + + 97, 20 + + + 8 + + + Description: + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 1 + + + Top, Left, Right + + + 114, 128 + + + 4, 4, 4, 4 + + + 545, 27 + + + 7 + + + textBox4 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 2 + + + True + + + NoControl + + + 53, 132 + + + 4, 0, 4, 0 + + + 51, 20 + + + 6 + + + Email: + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 3 + + + Top, Left, Right + + + 114, 95 + + + 4, 4, 4, 4 + + + 545, 27 + + + 5 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 4 + + + True + + + NoControl + + + 42, 97 + + + 4, 0, 4, 0 + + + 64, 20 + + + 4 + + + Author: + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 5 + + + Top, Left, Right + + + 114, 60 + + + 4, 4, 4, 4 + + + 545, 27 + + + 3 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 6 + + + True + + + NoControl + + + 36, 64 + + + 4, 0, 4, 0 + + + 68, 20 + + + 2 + + + Version: + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 7 + + + Top, Left, Right + + + 114, 25 + + + 4, 4, 4, 4 + + + 545, 27 + + + 1 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 8 + + + True + + + 42, 29 + + + 4, 0, 4, 0 + + + 56, 20 + + + 0 + + + Name: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 9 + + + 15, 15 + + + 4, 4, 4, 4 + + + 4, 4, 4, 4 + + + 669, 268 + + + 0 + + + Information + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + 15, 289 + + + 4, 4, 4, 4 + + + 4, 4, 4, 4 + + + 669, 97 + + + 1 + + + Metadata + + + groupBox2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Top, Left, Right + + + 136, 60 + + + 4, 4, 4, 4 + + + 523, 27 + + + 3 + + + textBox7 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 0 + + + True + + + NoControl + + + 24, 64 + + + 4, 0, 4, 0 + + + 102, 20 + + + 2 + + + Return Type: + + + label7 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 1 + + + Top, Left, Right + + + 136, 25 + + + 4, 4, 4, 4 + + + 523, 27 + + + 1 + + + textBox6 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 2 + + + True + + + 8, 29 + + + 4, 0, 4, 0 + + + 117, 20 + + + 0 + + + Parameter List: + + + label6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 3 + + + Top, Bottom, Left, Right + + + Bottom, Left + + + True + + + NoControl + + + 357, 189 + + + 4, 4, 4, 4 + + + 87, 24 + + + 3 + + + Payable + + + checkBox3 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 0 + + + True + + + NoControl + + + 9, 162 + + + 4, 0, 4, 0 + + + 96, 20 + + + 3 + + + Script Hash: + + + label8 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 1 + + + Bottom, Left + + + True + + + NoControl + + + 180, 189 + + + 4, 4, 4, 4 + + + 127, 24 + + + 2 + + + Need Dyncall + + + checkBox2 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 2 + + + Bottom, Left + + + 112, 162 + + + 4, 4, 4, 4 + + + 401, 20 + + + 4 + + + textBox9 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 3 + + + Bottom, Right + + + 564, 188 + + + 4, 4, 4, 4 + + + 96, 27 + + + 4 + + + Load + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 4 + + + Bottom, Left + + + True + + + 8, 189 + + + 4, 4, 4, 4 + + + 133, 24 + + + 1 + + + Need Storage + + + checkBox1 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 5 + + + Top, Bottom, Left, Right + + + 8, 25 + + + 4, 4, 4, 4 + + + True + + + Vertical + + + 652, 155 + + + 0 + + + textBox8 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 6 + + + 15, 395 + + + 4, 4, 4, 4 + + + 4, 4, 4, 4 + + + 669, 223 + + + 2 + + + Code + + + groupBox3 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Right + + + False + + + 483, 624 + + + 4, 4, 4, 4 + + + 96, 27 + + + 3 + + + Deploy + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Bottom, Right + + + NoControl + + + 588, 624 + + + 4, 4, 4, 4 + + + 96, 27 + + + 4 + + + Cancel + + + button3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 17, 17 + + + AVM File|*.avm + + + True + + + 9, 20 + + + 699, 665 + + + Microsoft YaHei, 9pt + + + 4, 5, 4, 5 + + + CenterScreen + + + Deploy Contract + + + openFileDialog1 + + + System.Windows.Forms.OpenFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + DeployContractDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/src/Neo.GUI/GUI/DeployContractDialog.zh-Hans.resx b/src/Neo.GUI/GUI/DeployContractDialog.zh-Hans.resx new file mode 100644 index 0000000000..ae91b44198 --- /dev/null +++ b/src/Neo.GUI/GUI/DeployContractDialog.zh-Hans.resx @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 70, 122 + + + 444, 75 + + + 30, 125 + + + 34, 15 + + + 说明: + + + 70, 96 + + + 444, 23 + + + 6, 99 + + + 58, 15 + + + 电子邮件: + + + 70, 71 + + + 444, 23 + + + 30, 74 + + + 34, 15 + + + 作者: + + + 70, 45 + + + 444, 23 + + + 30, 48 + + + 34, 15 + + + 版本: + + + 70, 19 + + + 444, 23 + + + 30, 22 + + + 34, 15 + + + 名称: + + + 信息 + + + 70, 45 + + + 444, 23 + + + 18, 48 + + + 46, 15 + + + 返回值: + + + 70, 19 + + + 444, 23 + + + 58, 15 + + + 参数列表: + + + 元数据 + + + 98, 19 + + + 需要动态调用 + + + 加载 + + + 110, 19 + + + 需要创建存储区 + + + 代码 + + + 部署 + + + 取消 + + + AVM文件|*.avm + + + 部署合约 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/DeveloperToolsForm.ContractParameters.cs b/src/Neo.GUI/GUI/DeveloperToolsForm.ContractParameters.cs new file mode 100644 index 0000000000..8fc35b7b88 --- /dev/null +++ b/src/Neo.GUI/GUI/DeveloperToolsForm.ContractParameters.cs @@ -0,0 +1,117 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.Properties; +using Neo.SmartContract; +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + partial class DeveloperToolsForm + { + private ContractParametersContext context; + + private void listBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (listBox1.SelectedIndex < 0) return; + listBox2.Items.Clear(); + if (Service.CurrentWallet == null) return; + UInt160 hash = ((string)listBox1.SelectedItem).ToScriptHash(Service.NeoSystem.Settings.AddressVersion); + var parameters = context.GetParameters(hash); + if (parameters == null) + { + var parameterList = Service.CurrentWallet.GetAccount(hash).Contract.ParameterList; + if (parameterList != null) + { + var pList = new List(); + for (int i = 0; i < parameterList.Length; i++) + { + pList.Add(new ContractParameter(parameterList[i])); + context.Add(Service.CurrentWallet.GetAccount(hash).Contract, i, null); + } + } + } + listBox2.Items.AddRange(context.GetParameters(hash).ToArray()); + button4.Visible = context.Completed; + } + + private void listBox2_SelectedIndexChanged(object sender, EventArgs e) + { + if (listBox2.SelectedIndex < 0) return; + textBox1.Text = listBox2.SelectedItem.ToString(); + textBox2.Clear(); + } + + private void button1_Click(object sender, EventArgs e) + { + string input = InputBox.Show("ParametersContext", "ParametersContext"); + if (string.IsNullOrEmpty(input)) return; + try + { + context = ContractParametersContext.Parse(input, Service.NeoSystem.StoreView); + } + catch (FormatException ex) + { + MessageBox.Show(ex.Message); + return; + } + listBox1.Items.Clear(); + listBox2.Items.Clear(); + textBox1.Clear(); + textBox2.Clear(); + listBox1.Items.AddRange(context.ScriptHashes.Select(p => p.ToAddress(Service.NeoSystem.Settings.AddressVersion)).ToArray()); + button2.Enabled = true; + button4.Visible = context.Completed; + } + + private void button2_Click(object sender, EventArgs e) + { + InformationBox.Show(context.ToString(), "ParametersContext", "ParametersContext"); + } + + private void button3_Click(object sender, EventArgs e) + { + if (listBox1.SelectedIndex < 0) return; + if (listBox2.SelectedIndex < 0) return; + ContractParameter parameter = (ContractParameter)listBox2.SelectedItem; + parameter.SetValue(textBox2.Text); + listBox2.Items[listBox2.SelectedIndex] = parameter; + textBox1.Text = textBox2.Text; + button4.Visible = context.Completed; + } + + private void button4_Click(object sender, EventArgs e) + { + if (!(context.Verifiable is Transaction tx)) + { + MessageBox.Show("Only support to broadcast transaction."); + return; + } + tx.Witnesses = context.GetWitnesses(); + Blockchain.RelayResult reason = Service.NeoSystem.Blockchain.Ask(tx).Result; + if (reason.Result == VerifyResult.Succeed) + { + InformationBox.Show(tx.Hash.ToString(), Strings.RelaySuccessText, Strings.RelaySuccessTitle); + } + else + { + MessageBox.Show($"Transaction cannot be broadcast: {reason}"); + } + } + } +} diff --git a/src/Neo.GUI/GUI/DeveloperToolsForm.Designer.cs b/src/Neo.GUI/GUI/DeveloperToolsForm.Designer.cs new file mode 100644 index 0000000000..31faf836d9 --- /dev/null +++ b/src/Neo.GUI/GUI/DeveloperToolsForm.Designer.cs @@ -0,0 +1,259 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class DeveloperToolsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeveloperToolsForm)); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.propertyGrid1 = new System.Windows.Forms.PropertyGrid(); + this.button8 = new System.Windows.Forms.Button(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.button4 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.listBox2 = new System.Windows.Forms.ListBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.listBox1 = new System.Windows.Forms.ListBox(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + resources.ApplyResources(this.splitContainer1, "splitContainer1"); + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + resources.ApplyResources(this.splitContainer1.Panel1, "splitContainer1.Panel1"); + this.splitContainer1.Panel1.Controls.Add(this.propertyGrid1); + // + // splitContainer1.Panel2 + // + resources.ApplyResources(this.splitContainer1.Panel2, "splitContainer1.Panel2"); + this.splitContainer1.Panel2.Controls.Add(this.button8); + // + // propertyGrid1 + // + resources.ApplyResources(this.propertyGrid1, "propertyGrid1"); + this.propertyGrid1.Name = "propertyGrid1"; + this.propertyGrid1.SelectedObjectsChanged += new System.EventHandler(this.propertyGrid1_SelectedObjectsChanged); + // + // button8 + // + resources.ApplyResources(this.button8, "button8"); + this.button8.Name = "button8"; + this.button8.UseVisualStyleBackColor = true; + this.button8.Click += new System.EventHandler(this.button8_Click); + // + // tabControl1 + // + resources.ApplyResources(this.tabControl1, "tabControl1"); + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + // + // tabPage1 + // + resources.ApplyResources(this.tabPage1, "tabPage1"); + this.tabPage1.Controls.Add(this.splitContainer1); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabPage2 + // + resources.ApplyResources(this.tabPage2, "tabPage2"); + this.tabPage2.Controls.Add(this.button4); + this.tabPage2.Controls.Add(this.button3); + this.tabPage2.Controls.Add(this.button2); + this.tabPage2.Controls.Add(this.button1); + this.tabPage2.Controls.Add(this.groupBox4); + this.tabPage2.Controls.Add(this.groupBox3); + this.tabPage2.Controls.Add(this.groupBox2); + this.tabPage2.Controls.Add(this.groupBox1); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // button4 + // + resources.ApplyResources(this.button4, "button4"); + this.button4.Name = "button4"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // groupBox4 + // + resources.ApplyResources(this.groupBox4, "groupBox4"); + this.groupBox4.Controls.Add(this.textBox2); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.TabStop = false; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + // + // groupBox3 + // + resources.ApplyResources(this.groupBox3, "groupBox3"); + this.groupBox3.Controls.Add(this.textBox1); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.TabStop = false; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + // + // groupBox2 + // + resources.ApplyResources(this.groupBox2, "groupBox2"); + this.groupBox2.Controls.Add(this.listBox2); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.TabStop = false; + // + // listBox2 + // + resources.ApplyResources(this.listBox2, "listBox2"); + this.listBox2.FormattingEnabled = true; + this.listBox2.Name = "listBox2"; + this.listBox2.SelectedIndexChanged += new System.EventHandler(this.listBox2_SelectedIndexChanged); + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.listBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // listBox1 + // + resources.ApplyResources(this.listBox1, "listBox1"); + this.listBox1.FormattingEnabled = true; + this.listBox1.Name = "listBox1"; + this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); + // + // DeveloperToolsForm + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.KeyPreview = true; + this.MaximizeBox = false; + this.Name = "DeveloperToolsForm"; + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.ListBox listBox1; + private System.Windows.Forms.ListBox listBox2; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.PropertyGrid propertyGrid1; + private System.Windows.Forms.Button button8; + } +} diff --git a/src/Neo.GUI/GUI/DeveloperToolsForm.TxBuilder.cs b/src/Neo.GUI/GUI/DeveloperToolsForm.TxBuilder.cs new file mode 100644 index 0000000000..eabb5812b6 --- /dev/null +++ b/src/Neo.GUI/GUI/DeveloperToolsForm.TxBuilder.cs @@ -0,0 +1,36 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.GUI.Wrappers; +using Neo.SmartContract; +using System; + +namespace Neo.GUI +{ + partial class DeveloperToolsForm + { + private void InitializeTxBuilder() + { + propertyGrid1.SelectedObject = new TransactionWrapper(); + } + + private void propertyGrid1_SelectedObjectsChanged(object sender, EventArgs e) + { + splitContainer1.Panel2.Enabled = propertyGrid1.SelectedObject != null; + } + + private void button8_Click(object sender, EventArgs e) + { + TransactionWrapper wrapper = (TransactionWrapper)propertyGrid1.SelectedObject; + ContractParametersContext context = new ContractParametersContext(Program.Service.NeoSystem.StoreView, wrapper.Unwrap(), Program.Service.NeoSystem.Settings.Network); + InformationBox.Show(context.ToString(), "ParametersContext", "ParametersContext"); + } + } +} diff --git a/src/Neo.GUI/GUI/DeveloperToolsForm.cs b/src/Neo.GUI/GUI/DeveloperToolsForm.cs new file mode 100644 index 0000000000..c921599945 --- /dev/null +++ b/src/Neo.GUI/GUI/DeveloperToolsForm.cs @@ -0,0 +1,23 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class DeveloperToolsForm : Form + { + public DeveloperToolsForm() + { + InitializeComponent(); + InitializeTxBuilder(); + } + } +} diff --git a/src/Neo.GUI/GUI/DeveloperToolsForm.es-ES.resx b/src/Neo.GUI/GUI/DeveloperToolsForm.es-ES.resx new file mode 100644 index 0000000000..9e330876eb --- /dev/null +++ b/src/Neo.GUI/GUI/DeveloperToolsForm.es-ES.resx @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Parametros de contexto + + + Parámetros del contrato + + + Emitir + + + Actualizar + + + Mostrar + + + Cargar + + + Nuevo valor + + + Valor actual + + + Parámetros + + + Hash del script + + + Herramienta de desarrollo + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/DeveloperToolsForm.resx b/src/Neo.GUI/GUI/DeveloperToolsForm.resx new file mode 100644 index 0000000000..63e49aa4b5 --- /dev/null +++ b/src/Neo.GUI/GUI/DeveloperToolsForm.resx @@ -0,0 +1,669 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + 3, 3 + + + Fill + + + 0, 0 + + + 444, 414 + + + + 1 + + + propertyGrid1 + + + System.Windows.Forms.PropertyGrid, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer1.Panel1 + + + 0 + + + splitContainer1.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer1 + + + 0 + + + Bottom, Left, Right + + + NoControl + + + 3, 386 + + + 173, 23 + + + 3 + + + Get Parameters Context + + + button8 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer1.Panel2 + + + 0 + + + False + + + splitContainer1.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer1 + + + 1 + + + 627, 414 + + + 444 + + + 1 + + + splitContainer1 + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage1 + + + 0 + + + 4, 26 + + + 3, 3, 3, 3 + + + 633, 420 + + + 3 + + + Tx Builder + + + tabPage1 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 0 + + + Bottom, Left + + + 170, 389 + + + 75, 23 + + + 7 + + + Broadcast + + + False + + + button4 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 0 + + + Bottom, Right + + + 550, 389 + + + 75, 23 + + + 6 + + + Update + + + button3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 1 + + + Bottom, Left + + + False + + + 89, 389 + + + 75, 23 + + + 5 + + + Show + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 2 + + + Bottom, Left + + + 8, 389 + + + 75, 23 + + + 4 + + + Load + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 3 + + + Bottom, Left, Right + + + Fill + + + 3, 19 + + + True + + + 199, 98 + + + 0 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox4 + + + 0 + + + 420, 263 + + + 205, 120 + + + 3 + + + New Value + + + groupBox4 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 4 + + + Top, Bottom, Left, Right + + + Fill + + + 3, 19 + + + True + + + 199, 229 + + + 0 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 0 + + + 420, 6 + + + 205, 251 + + + 2 + + + Current Value + + + groupBox3 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 5 + + + Top, Bottom, Left + + + Fill + + + False + + + 17 + + + 3, 19 + + + 194, 355 + + + 0 + + + listBox2 + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 0 + + + 214, 6 + + + 200, 377 + + + 1 + + + Parameters + + + groupBox2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 6 + + + Top, Bottom, Left + + + Fill + + + False + + + 17 + + + 3, 19 + + + 194, 355 + + + 0 + + + listBox1 + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + 8, 6 + + + 200, 377 + + + 0 + + + ScriptHash + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 7 + + + 4, 26 + + + 3, 3, 3, 3 + + + 633, 420 + + + 2 + + + Contract Parameters + + + tabPage2 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 1 + + + Fill + + + 0, 0 + + + 641, 450 + + + 0 + + + tabControl1 + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 641, 450 + + + 微软雅黑, 9pt + + + CenterScreen + + + Neo Developer Tools + + + DeveloperToolsForm + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/DeveloperToolsForm.zh-Hans.resx b/src/Neo.GUI/GUI/DeveloperToolsForm.zh-Hans.resx new file mode 100644 index 0000000000..2b25fc62cb --- /dev/null +++ b/src/Neo.GUI/GUI/DeveloperToolsForm.zh-Hans.resx @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 获取合约参数上下文 + + + 交易构造器 + + + 广播 + + + 更新 + + + 显示 + + + 加载 + + + 新值 + + + 当前值 + + + 参数 + + + 合约参数 + + + NEO开发人员工具 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ElectionDialog.Designer.cs b/src/Neo.GUI/GUI/ElectionDialog.Designer.cs new file mode 100644 index 0000000000..512c24643a --- /dev/null +++ b/src/Neo.GUI/GUI/ElectionDialog.Designer.cs @@ -0,0 +1,92 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ElectionDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ElectionDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // comboBox1 + // + resources.ApplyResources(this.comboBox1, "comboBox1"); + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Name = "comboBox1"; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // ElectionDialog + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.button1); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ElectionDialog"; + this.ShowInTaskbar = false; + this.Load += new System.EventHandler(this.ElectionDialog_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Button button1; + } +} diff --git a/src/Neo.GUI/GUI/ElectionDialog.cs b/src/Neo.GUI/GUI/ElectionDialog.cs new file mode 100644 index 0000000000..c28bbfa068 --- /dev/null +++ b/src/Neo.GUI/GUI/ElectionDialog.cs @@ -0,0 +1,51 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.SmartContract.Native; +using Neo.VM; +using System; +using System.Linq; +using System.Windows.Forms; +using static Neo.Program; +using static Neo.SmartContract.Helper; + +namespace Neo.GUI +{ + public partial class ElectionDialog : Form + { + public ElectionDialog() + { + InitializeComponent(); + } + + public byte[] GetScript() + { + ECPoint pubkey = (ECPoint)comboBox1.SelectedItem; + using ScriptBuilder sb = new ScriptBuilder(); + sb.EmitDynamicCall(NativeContract.NEO.Hash, "registerValidator", pubkey); + return sb.ToArray(); + } + + private void ElectionDialog_Load(object sender, EventArgs e) + { + comboBox1.Items.AddRange(Service.CurrentWallet.GetAccounts().Where(p => !p.WatchOnly && IsSignatureContract(p.Contract.Script)).Select(p => p.GetKey().PublicKey).ToArray()); + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBox1.SelectedIndex >= 0) + { + button1.Enabled = true; + } + } + } +} diff --git a/src/Neo.GUI/GUI/ElectionDialog.es-ES.resx b/src/Neo.GUI/GUI/ElectionDialog.es-ES.resx new file mode 100644 index 0000000000..5ab76de86d --- /dev/null +++ b/src/Neo.GUI/GUI/ElectionDialog.es-ES.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Votación + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ElectionDialog.resx b/src/Neo.GUI/GUI/ElectionDialog.resx new file mode 100644 index 0000000000..ea655e7977 --- /dev/null +++ b/src/Neo.GUI/GUI/ElectionDialog.resx @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 12, 17 + + + 70, 17 + + + 0 + + + Public Key: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + + Top, Left, Right + + + 83, 14 + + + 442, 25 + + + 9 + + + comboBox1 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Bottom, Right + + + False + + + 450, 56 + + + 75, 26 + + + 12 + + + OK + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 537, 95 + + + 微软雅黑, 9pt + + + 3, 5, 3, 5 + + + CenterScreen + + + Election + + + ElectionDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ElectionDialog.zh-Hans.resx b/src/Neo.GUI/GUI/ElectionDialog.zh-Hans.resx new file mode 100644 index 0000000000..53e9edf8f2 --- /dev/null +++ b/src/Neo.GUI/GUI/ElectionDialog.zh-Hans.resx @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 24, 15 + + + 44, 17 + + + 公钥: + + + 73, 12 + + + 452, 25 + + + 确定 + + + + NoControl + + + 选举 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/Helper.cs b/src/Neo.GUI/GUI/Helper.cs new file mode 100644 index 0000000000..73897f63ca --- /dev/null +++ b/src/Neo.GUI/GUI/Helper.cs @@ -0,0 +1,74 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.Properties; +using Neo.SmartContract; +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + internal static class Helper + { + private static readonly Dictionary tool_forms = new Dictionary(); + + private static void Helper_FormClosing(object sender, FormClosingEventArgs e) + { + tool_forms.Remove(sender.GetType()); + } + + public static void Show() where T : Form, new() + { + Type t = typeof(T); + if (!tool_forms.ContainsKey(t)) + { + tool_forms.Add(t, new T()); + tool_forms[t].FormClosing += Helper_FormClosing; + } + tool_forms[t].Show(); + tool_forms[t].Activate(); + } + + public static void SignAndShowInformation(Transaction tx) + { + if (tx == null) + { + MessageBox.Show(Strings.InsufficientFunds); + return; + } + ContractParametersContext context; + try + { + context = new ContractParametersContext(Service.NeoSystem.StoreView, tx, Program.Service.NeoSystem.Settings.Network); + } + catch (InvalidOperationException) + { + MessageBox.Show(Strings.UnsynchronizedBlock); + return; + } + Service.CurrentWallet.Sign(context); + if (context.Completed) + { + tx.Witnesses = context.GetWitnesses(); + Service.NeoSystem.Blockchain.Tell(tx); + InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle); + } + else + { + InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle); + } + } + } +} diff --git a/src/Neo.GUI/GUI/ImportCustomContractDialog.Designer.cs b/src/Neo.GUI/GUI/ImportCustomContractDialog.Designer.cs new file mode 100644 index 0000000000..d06a03890e --- /dev/null +++ b/src/Neo.GUI/GUI/ImportCustomContractDialog.Designer.cs @@ -0,0 +1,137 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ImportCustomContractDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImportCustomContractDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.TextChanged += new System.EventHandler(this.Input_Changed); + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.TextChanged += new System.EventHandler(this.Input_Changed); + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.Name = "textBox3"; + // + // ImportCustomContractDialog + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.Controls.Add(this.textBox3); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ImportCustomContractDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.TextBox textBox3; + } +} diff --git a/src/Neo.GUI/GUI/ImportCustomContractDialog.cs b/src/Neo.GUI/GUI/ImportCustomContractDialog.cs new file mode 100644 index 0000000000..aa3eef48dc --- /dev/null +++ b/src/Neo.GUI/GUI/ImportCustomContractDialog.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.SmartContract; +using Neo.Wallets; +using System; +using System.Linq; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class ImportCustomContractDialog : Form + { + public Contract GetContract() + { + ContractParameterType[] parameterList = textBox1.Text.HexToBytes().Select(p => (ContractParameterType)p).ToArray(); + byte[] redeemScript = textBox2.Text.HexToBytes(); + return Contract.Create(parameterList, redeemScript); + } + + public KeyPair GetKey() + { + if (textBox3.TextLength == 0) return null; + byte[] privateKey; + try + { + privateKey = Wallet.GetPrivateKeyFromWIF(textBox3.Text); + } + catch (FormatException) + { + privateKey = textBox3.Text.HexToBytes(); + } + return new KeyPair(privateKey); + } + + public ImportCustomContractDialog() + { + InitializeComponent(); + } + + private void Input_Changed(object sender, EventArgs e) + { + button1.Enabled = textBox1.TextLength > 0 && textBox2.TextLength > 0; + } + } +} diff --git a/src/Neo.GUI/GUI/ImportCustomContractDialog.es-ES.resx b/src/Neo.GUI/GUI/ImportCustomContractDialog.es-ES.resx new file mode 100644 index 0000000000..a61aa86444 --- /dev/null +++ b/src/Neo.GUI/GUI/ImportCustomContractDialog.es-ES.resx @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 13, 15 + + + 23, 44 + + + 114, 16 + + + Lista de parámetros: + + + 143, 41 + + + 433, 23 + + + Confirmar + + + Cancelar + + + 143, 12 + + + 433, 23 + + + Importar contrato personalizado + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ImportCustomContractDialog.resx b/src/Neo.GUI/GUI/ImportCustomContractDialog.resx new file mode 100644 index 0000000000..f7b634476e --- /dev/null +++ b/src/Neo.GUI/GUI/ImportCustomContractDialog.resx @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 12, 15 + + + 124, 16 + + + 0 + + + Private Key (optional): + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + True + + + 50, 44 + + + 86, 16 + + + 10 + + + Parameter List: + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + + Top, Left, Right + + + 142, 41 + + + 434, 23 + + + 11 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Fill + + + 3, 19 + + + 131072 + + + True + + + Vertical + + + 558, 323 + + + 13 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + Top, Bottom, Left, Right + + + 12, 70 + + + 564, 345 + + + 14 + + + Script + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Bottom, Right + + + False + + + 420, 421 + + + 75, 23 + + + 15 + + + OK + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Right + + + 501, 421 + + + 75, 23 + + + 16 + + + Cancel + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 142, 12 + + + 434, 23 + + + 17 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 16 + + + 588, 456 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Import Custom Contract + + + ImportCustomContractDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ImportCustomContractDialog.zh-Hans.resx b/src/Neo.GUI/GUI/ImportCustomContractDialog.zh-Hans.resx new file mode 100644 index 0000000000..78fbe3ff92 --- /dev/null +++ b/src/Neo.GUI/GUI/ImportCustomContractDialog.zh-Hans.resx @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 83, 16 + + + 私钥(可选): + + + 36, 44 + + + 59, 16 + + + 形参列表: + + + 101, 41 + + + 475, 23 + + + 脚本代码 + + + 确定 + + + 取消 + + + 101, 12 + + + 475, 23 + + + 导入自定义合约 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ImportPrivateKeyDialog.cs b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.cs new file mode 100644 index 0000000000..30390eb9ce --- /dev/null +++ b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.cs @@ -0,0 +1,40 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class ImportPrivateKeyDialog : Form + { + public ImportPrivateKeyDialog() + { + InitializeComponent(); + } + + public string[] WifStrings + { + get + { + return textBox1.Lines; + } + set + { + textBox1.Lines = value; + } + } + + private void textBox1_TextChanged(object sender, EventArgs e) + { + button1.Enabled = textBox1.TextLength > 0; + } + } +} diff --git a/src/Neo.GUI/GUI/ImportPrivateKeyDialog.designer.cs b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.designer.cs new file mode 100644 index 0000000000..e0df823ec7 --- /dev/null +++ b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.designer.cs @@ -0,0 +1,102 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ImportPrivateKeyDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImportPrivateKeyDialog)); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // ImportPrivateKeyDialog + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ImportPrivateKeyDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.GroupBox groupBox1; + } +} diff --git a/src/Neo.GUI/GUI/ImportPrivateKeyDialog.es-ES.resx b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.es-ES.resx new file mode 100644 index 0000000000..86ff978402 --- /dev/null +++ b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.es-ES.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cancelar + + + Clave privada WIF: + + + + NoControl + + + Aceptar + + + Importar clave privada + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ImportPrivateKeyDialog.resx b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.resx new file mode 100644 index 0000000000..5cf34443a4 --- /dev/null +++ b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.resx @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + 3, 19 + + + + True + + + Vertical + + + 454, 79 + + + 0 + + + False + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + Bottom, Right + + + False + + + 316, 119 + + + 75, 23 + + + 1 + + + OK + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Right + + + 397, 119 + + + 75, 23 + + + 2 + + + Cancel + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Top, Bottom, Left, Right + + + 12, 12 + + + 460, 101 + + + 0 + + + WIF Private Key: + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 484, 154 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Import Private Key + + + ImportPrivateKeyDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ImportPrivateKeyDialog.zh-Hans.resx b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.zh-Hans.resx new file mode 100644 index 0000000000..5db4bf12ea --- /dev/null +++ b/src/Neo.GUI/GUI/ImportPrivateKeyDialog.zh-Hans.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 确定 + + + 取消 + + + WIF私钥: + + + 导入私钥 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InformationBox.Designer.cs b/src/Neo.GUI/GUI/InformationBox.Designer.cs new file mode 100644 index 0000000000..8b41144a9b --- /dev/null +++ b/src/Neo.GUI/GUI/InformationBox.Designer.cs @@ -0,0 +1,100 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class InformationBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InformationBox)); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // InformationBox + // + this.AcceptButton = this.button2; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.Controls.Add(this.label1); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InformationBox"; + this.ShowInTaskbar = false; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Label label1; + } +} diff --git a/src/Neo.GUI/GUI/InformationBox.cs b/src/Neo.GUI/GUI/InformationBox.cs new file mode 100644 index 0000000000..7cdd881255 --- /dev/null +++ b/src/Neo.GUI/GUI/InformationBox.cs @@ -0,0 +1,43 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class InformationBox : Form + { + public InformationBox() + { + InitializeComponent(); + } + + public static DialogResult Show(string text, string message = null, string title = null) + { + using InformationBox box = new InformationBox(); + box.textBox1.Text = text; + if (message != null) + { + box.label1.Text = message; + } + if (title != null) + { + box.Text = title; + } + return box.ShowDialog(); + } + + private void button1_Click(object sender, System.EventArgs e) + { + textBox1.SelectAll(); + textBox1.Copy(); + } + } +} diff --git a/src/Neo.GUI/GUI/InformationBox.es-ES.resx b/src/Neo.GUI/GUI/InformationBox.es-ES.resx new file mode 100644 index 0000000000..1af985f64c --- /dev/null +++ b/src/Neo.GUI/GUI/InformationBox.es-ES.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Copiar + + + Cancelar + + + Información + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InformationBox.resx b/src/Neo.GUI/GUI/InformationBox.resx new file mode 100644 index 0000000000..3aec9d5ab6 --- /dev/null +++ b/src/Neo.GUI/GUI/InformationBox.resx @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Bottom, Left, Right + + + + 12, 29 + + + + True + + + Vertical + + + 489, 203 + + + 0 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Bottom, Right + + + 345, 238 + + + 75, 23 + + + 1 + + + copy + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Right + + + 426, 238 + + + 75, 23 + + + 2 + + + close + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + True + + + 12, 9 + + + 0, 17 + + + 3 + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 513, 273 + + + 微软雅黑, 9pt + + + CenterScreen + + + InformationBox + + + InformationBox + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InformationBox.zh-Hans.resx b/src/Neo.GUI/GUI/InformationBox.zh-Hans.resx new file mode 100644 index 0000000000..ab3b23dc17 --- /dev/null +++ b/src/Neo.GUI/GUI/InformationBox.zh-Hans.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 复制 + + + 关闭 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InputBox.Designer.cs b/src/Neo.GUI/GUI/InputBox.Designer.cs new file mode 100644 index 0000000000..aa376ca91f --- /dev/null +++ b/src/Neo.GUI/GUI/InputBox.Designer.cs @@ -0,0 +1,102 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class InputBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InputBox)); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // InputBox + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InputBox"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + } +} diff --git a/src/Neo.GUI/GUI/InputBox.cs b/src/Neo.GUI/GUI/InputBox.cs new file mode 100644 index 0000000000..cdfc5a63eb --- /dev/null +++ b/src/Neo.GUI/GUI/InputBox.cs @@ -0,0 +1,32 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class InputBox : Form + { + private InputBox(string text, string caption, string content) + { + InitializeComponent(); + this.Text = caption; + groupBox1.Text = text; + textBox1.Text = content; + } + + public static string Show(string text, string caption, string content = "") + { + using InputBox dialog = new InputBox(text, caption, content); + if (dialog.ShowDialog() != DialogResult.OK) return null; + return dialog.textBox1.Text; + } + } +} diff --git a/src/Neo.GUI/GUI/InputBox.es-ES.resx b/src/Neo.GUI/GUI/InputBox.es-ES.resx new file mode 100644 index 0000000000..3e13191c48 --- /dev/null +++ b/src/Neo.GUI/GUI/InputBox.es-ES.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Aceptar + + + Cancelar + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InputBox.resx b/src/Neo.GUI/GUI/InputBox.resx new file mode 100644 index 0000000000..84533a5c93 --- /dev/null +++ b/src/Neo.GUI/GUI/InputBox.resx @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 2 + + + True + + + 0 + + + + 7, 17 + + + InputBox + + + 75, 23 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + button2 + + + InputBox + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 390, 118 + + + 420, 193 + + + 2 + + + + CenterScreen + + + 75, 23 + + + 2, 2, 2, 2 + + + groupBox1 + + + 0 + + + 3, 19 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 12, 12 + + + 1 + + + 0 + + + Fill + + + $this + + + groupBox1 + + + 0 + + + 1 + + + button1 + + + textBox1 + + + OK + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 252, 158 + + + Microsoft YaHei UI, 9pt + + + 396, 140 + + + 333, 158 + + + Cancel + + + $this + + + True + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InputBox.zh-Hans.resx b/src/Neo.GUI/GUI/InputBox.zh-Hans.resx new file mode 100644 index 0000000000..0ede664604 --- /dev/null +++ b/src/Neo.GUI/GUI/InputBox.zh-Hans.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 确定 + + + 取消 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InvokeContractDialog.Designer.cs b/src/Neo.GUI/GUI/InvokeContractDialog.Designer.cs new file mode 100644 index 0000000000..04f845def9 --- /dev/null +++ b/src/Neo.GUI/GUI/InvokeContractDialog.Designer.cs @@ -0,0 +1,270 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class InvokeContractDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InvokeContractDialog)); + this.button6 = new System.Windows.Forms.Button(); + this.textBox6 = new System.Windows.Forms.TextBox(); + this.button3 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + this.label6 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.button5 = new System.Windows.Forms.Button(); + this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.button8 = new System.Windows.Forms.Button(); + this.textBox9 = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.label9 = new System.Windows.Forms.Label(); + this.button7 = new System.Windows.Forms.Button(); + this.textBox8 = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox7 = new System.Windows.Forms.TextBox(); + this.openFileDialog2 = new System.Windows.Forms.OpenFileDialog(); + this.tabControl1.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // button6 + // + resources.ApplyResources(this.button6, "button6"); + this.button6.Name = "button6"; + this.button6.UseVisualStyleBackColor = true; + this.button6.Click += new System.EventHandler(this.button6_Click); + // + // textBox6 + // + resources.ApplyResources(this.textBox6, "textBox6"); + this.textBox6.Name = "textBox6"; + this.textBox6.TextChanged += new System.EventHandler(this.textBox6_TextChanged); + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + // + // button4 + // + resources.ApplyResources(this.button4, "button4"); + this.button4.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button4.Name = "button4"; + this.button4.UseVisualStyleBackColor = true; + // + // label6 + // + resources.ApplyResources(this.label6, "label6"); + this.label6.Name = "label6"; + // + // label7 + // + resources.ApplyResources(this.label7, "label7"); + this.label7.Name = "label7"; + // + // button5 + // + resources.ApplyResources(this.button5, "button5"); + this.button5.Name = "button5"; + this.button5.UseVisualStyleBackColor = true; + this.button5.Click += new System.EventHandler(this.button5_Click); + // + // openFileDialog1 + // + resources.ApplyResources(this.openFileDialog1, "openFileDialog1"); + this.openFileDialog1.DefaultExt = "avm"; + // + // tabControl1 + // + resources.ApplyResources(this.tabControl1, "tabControl1"); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + // + // tabPage3 + // + resources.ApplyResources(this.tabPage3, "tabPage3"); + this.tabPage3.Controls.Add(this.button8); + this.tabPage3.Controls.Add(this.textBox9); + this.tabPage3.Controls.Add(this.label10); + this.tabPage3.Controls.Add(this.comboBox1); + this.tabPage3.Controls.Add(this.label9); + this.tabPage3.Controls.Add(this.button7); + this.tabPage3.Controls.Add(this.textBox8); + this.tabPage3.Controls.Add(this.label8); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // button8 + // + resources.ApplyResources(this.button8, "button8"); + this.button8.Name = "button8"; + this.button8.UseVisualStyleBackColor = true; + this.button8.Click += new System.EventHandler(this.button8_Click); + // + // textBox9 + // + resources.ApplyResources(this.textBox9, "textBox9"); + this.textBox9.Name = "textBox9"; + this.textBox9.ReadOnly = true; + // + // label10 + // + resources.ApplyResources(this.label10, "label10"); + this.label10.Name = "label10"; + // + // comboBox1 + // + resources.ApplyResources(this.comboBox1, "comboBox1"); + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Name = "comboBox1"; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // label9 + // + resources.ApplyResources(this.label9, "label9"); + this.label9.Name = "label9"; + // + // button7 + // + resources.ApplyResources(this.button7, "button7"); + this.button7.Name = "button7"; + this.button7.UseVisualStyleBackColor = true; + this.button7.Click += new System.EventHandler(this.button7_Click); + // + // textBox8 + // + resources.ApplyResources(this.textBox8, "textBox8"); + this.textBox8.Name = "textBox8"; + this.textBox8.ReadOnly = true; + // + // label8 + // + resources.ApplyResources(this.label8, "label8"); + this.label8.Name = "label8"; + // + // tabPage2 + // + resources.ApplyResources(this.tabPage2, "tabPage2"); + this.tabPage2.Controls.Add(this.button6); + this.tabPage2.Controls.Add(this.textBox6); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox7); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox7 + // + resources.ApplyResources(this.textBox7, "textBox7"); + this.textBox7.Name = "textBox7"; + this.textBox7.ReadOnly = true; + // + // openFileDialog2 + // + resources.ApplyResources(this.openFileDialog2, "openFileDialog2"); + this.openFileDialog2.DefaultExt = "abi.json"; + // + // InvokeContractDialog + // + resources.ApplyResources(this, "$this"); + this.AcceptButton = this.button3; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button4; + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.button5); + this.Controls.Add(this.label7); + this.Controls.Add(this.label6); + this.Controls.Add(this.button4); + this.Controls.Add(this.button3); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InvokeContractDialog"; + this.ShowInTaskbar = false; + this.tabControl1.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage2.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.TextBox textBox6; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Button button5; + private System.Windows.Forms.Button button6; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox7; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.TextBox textBox8; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Button button7; + private System.Windows.Forms.OpenFileDialog openFileDialog2; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Button button8; + private System.Windows.Forms.TextBox textBox9; + private System.Windows.Forms.Label label10; + } +} diff --git a/src/Neo.GUI/GUI/InvokeContractDialog.cs b/src/Neo.GUI/GUI/InvokeContractDialog.cs new file mode 100644 index 0000000000..3a92b5afda --- /dev/null +++ b/src/Neo.GUI/GUI/InvokeContractDialog.cs @@ -0,0 +1,145 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Json; +using Neo.Network.P2P.Payloads; +using Neo.Properties; +using Neo.SmartContract; +using Neo.VM; +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + internal partial class InvokeContractDialog : Form + { + private readonly Transaction tx; + private JObject abi; + private UInt160 script_hash; + private ContractParameter[] parameters; + + public InvokeContractDialog() + { + InitializeComponent(); + } + + public InvokeContractDialog(Transaction tx) : this() + { + this.tx = tx; + tabControl1.SelectedTab = tabPage2; + textBox6.Text = tx.Script.Span.ToHexString(); + textBox6.ReadOnly = true; + } + + public InvokeContractDialog(byte[] script) : this() + { + tabControl1.SelectedTab = tabPage2; + textBox6.Text = script.ToHexString(); + } + + public Transaction GetTransaction() + { + byte[] script = textBox6.Text.Trim().HexToBytes(); + return tx ?? Service.CurrentWallet.MakeTransaction(Service.NeoSystem.StoreView, script); + } + + private void UpdateScript() + { + using ScriptBuilder sb = new ScriptBuilder(); + sb.EmitDynamicCall(script_hash, (string)comboBox1.SelectedItem, parameters); + textBox6.Text = sb.ToArray().ToHexString(); + } + + private void textBox6_TextChanged(object sender, EventArgs e) + { + button3.Enabled = false; + button5.Enabled = textBox6.TextLength > 0; + } + + private void button5_Click(object sender, EventArgs e) + { + byte[] script; + try + { + script = textBox6.Text.Trim().HexToBytes(); + } + catch (FormatException ex) + { + MessageBox.Show(ex.Message); + return; + } + Transaction tx_test = tx ?? new Transaction + { + Signers = new Signer[0], + Attributes = new TransactionAttribute[0], + Script = script, + Witnesses = new Witness[0] + }; + using ApplicationEngine engine = ApplicationEngine.Run(tx_test.Script, Service.NeoSystem.StoreView, container: tx_test); + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"VM State: {engine.State}"); + sb.AppendLine($"Gas Consumed: {engine.GasConsumed}"); + sb.AppendLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToParameter().ToJson()))}"); + textBox7.Text = sb.ToString(); + if (engine.State != VMState.FAULT) + { + label7.Text = engine.GasConsumed + " gas"; + button3.Enabled = true; + } + else + { + MessageBox.Show(Strings.ExecutionFailed); + } + } + + private void button6_Click(object sender, EventArgs e) + { + if (openFileDialog1.ShowDialog() != DialogResult.OK) return; + textBox6.Text = File.ReadAllBytes(openFileDialog1.FileName).ToHexString(); + } + + private void button7_Click(object sender, EventArgs e) + { + if (openFileDialog2.ShowDialog() != DialogResult.OK) return; + abi = (JObject)JToken.Parse(File.ReadAllText(openFileDialog2.FileName)); + script_hash = UInt160.Parse(abi["hash"].AsString()); + textBox8.Text = script_hash.ToString(); + comboBox1.Items.Clear(); + comboBox1.Items.AddRange(((JArray)abi["functions"]).Select(p => p["name"].AsString()).Where(p => p != abi["entrypoint"].AsString()).ToArray()); + textBox9.Clear(); + button8.Enabled = false; + } + + private void button8_Click(object sender, EventArgs e) + { + using (ParametersEditor dialog = new ParametersEditor(parameters)) + { + dialog.ShowDialog(); + } + UpdateScript(); + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (!(comboBox1.SelectedItem is string method)) return; + JArray functions = (JArray)abi["functions"]; + var function = functions.First(p => p["name"].AsString() == method); + JArray _params = (JArray)function["parameters"]; + parameters = _params.Select(p => new ContractParameter(p["type"].AsEnum())).ToArray(); + textBox9.Text = string.Join(", ", _params.Select(p => p["name"].AsString())); + button8.Enabled = parameters.Length > 0; + UpdateScript(); + } + } +} diff --git a/src/Neo.GUI/GUI/InvokeContractDialog.es-ES.resx b/src/Neo.GUI/GUI/InvokeContractDialog.es-ES.resx new file mode 100644 index 0000000000..20f5cf4799 --- /dev/null +++ b/src/Neo.GUI/GUI/InvokeContractDialog.es-ES.resx @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cargar + + + Invocar + + + Cancelar + + + + 38, 17 + + + Tasa: + + + 79, 17 + + + no evaluada + + + Prueba + + + 78, 17 + + + Parámetros: + + + Invocar contrato + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InvokeContractDialog.resx b/src/Neo.GUI/GUI/InvokeContractDialog.resx new file mode 100644 index 0000000000..df3c2f0ab5 --- /dev/null +++ b/src/Neo.GUI/GUI/InvokeContractDialog.resx @@ -0,0 +1,735 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Bottom, Right + + + + 376, 190 + + + 75, 23 + + + + 1 + + + Load + + + button6 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 0 + + + Top, Bottom, Left, Right + + + 6, 6 + + + True + + + Vertical + + + 445, 178 + + + 0 + + + textBox6 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 1 + + + Bottom, Right + + + False + + + 321, 482 + + + 75, 23 + + + 6 + + + Invoke + + + button3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + Bottom, Right + + + NoControl + + + 402, 482 + + + 75, 23 + + + 7 + + + Cancel + + + button4 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Bottom, Left + + + True + + + 12, 482 + + + 31, 17 + + + 3 + + + Fee: + + + label6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Bottom, Left + + + True + + + 49, 482 + + + 87, 17 + + + 4 + + + not evaluated + + + label7 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Bottom, Right + + + False + + + 240, 482 + + + 75, 23 + + + 5 + + + Test + + + button5 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 17, 17 + + + AVM File|*.avm + + + Top, Right + + + False + + + NoControl + + + 426, 67 + + + 25, 25 + + + 17 + + + ... + + + button8 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 0 + + + Top, Left, Right + + + 89, 68 + + + 331, 23 + + + 16 + + + textBox9 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 1 + + + True + + + NoControl + + + 6, 71 + + + 77, 17 + + + 15 + + + Parameters: + + + label10 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 2 + + + 89, 36 + + + 362, 25 + + + 14 + + + comboBox1 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 3 + + + True + + + NoControl + + + 26, 39 + + + 57, 17 + + + 13 + + + Method: + + + label9 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 4 + + + Bottom, Right + + + NoControl + + + 354, 188 + + + 97, 25 + + + 12 + + + Open ABI File + + + button7 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 5 + + + Top, Left, Right + + + 89, 7 + + + 362, 23 + + + 2 + + + textBox8 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 6 + + + True + + + NoControl + + + 10, 10 + + + 73, 17 + + + 1 + + + ScriptHash: + + + label8 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 7 + + + 4, 26 + + + 3, 3, 3, 3 + + + 457, 219 + + + 2 + + + ABI + + + tabPage3 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 0 + + + 4, 26 + + + 3, 3, 3, 3 + + + 457, 219 + + + 1 + + + Custom + + + tabPage2 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 1 + + + 12, 12 + + + 465, 249 + + + 8 + + + tabControl1 + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Fill + + + 3, 19 + + + True + + + Both + + + 459, 184 + + + 0 + + + False + + + textBox7 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + 12, 267 + + + 465, 206 + + + 9 + + + Results + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + 165, 17 + + + ABI File|*.abi.json + + + True + + + 7, 17 + + + 489, 514 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Invoke Contract + + + openFileDialog1 + + + System.Windows.Forms.OpenFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + openFileDialog2 + + + System.Windows.Forms.OpenFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + InvokeContractDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/InvokeContractDialog.zh-Hans.resx b/src/Neo.GUI/GUI/InvokeContractDialog.zh-Hans.resx new file mode 100644 index 0000000000..d39deccbfa --- /dev/null +++ b/src/Neo.GUI/GUI/InvokeContractDialog.zh-Hans.resx @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 加载 + + + 调用 + + + 取消 + + + + 47, 17 + + + 手续费: + + + 65, 482 + + + 44, 17 + + + 未评估 + + + 试运行 + + + AVM文件|*.avm + + + 24, 71 + + + 59, 17 + + + 参数列表: + + + 48, 39 + + + 35, 17 + + + 方法: + + + 打开ABI文件 + + + 自定义 + + + 运行结果 + + + ABI文件|*.abi.json + + + 调用合约 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/MainForm.Designer.cs b/src/Neo.GUI/GUI/MainForm.Designer.cs new file mode 100644 index 0000000000..2f4da98d9c --- /dev/null +++ b/src/Neo.GUI/GUI/MainForm.Designer.cs @@ -0,0 +1,732 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class MainForm + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.钱包WToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.创建钱包数据库NToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.打开钱包数据库OToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.修改密码CToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.退出XToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.交易TToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.转账TToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + this.签名SToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.高级AToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.deployContractToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.invokeContractToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator(); + this.选举EToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.signDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); + this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.帮助HToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看帮助VToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.官网WToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.开发人员工具TToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.consoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.关于AntSharesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader11 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.创建新地址NToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.导入私钥IToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.importWIFToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); + this.importWatchOnlyAddressToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.创建智能合约SToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.多方签名MToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); + this.自定义CToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.查看私钥VToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.viewContractToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.voteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.复制到剪贴板CToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除DToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); + this.lbl_height = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripStatusLabel4 = new System.Windows.Forms.ToolStripStatusLabel(); + this.lbl_count_node = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripProgressBar1 = new System.Windows.Forms.ToolStripProgressBar(); + this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripStatusLabel3 = new System.Windows.Forms.ToolStripStatusLabel(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.listView2 = new System.Windows.Forms.ListView(); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.listView3 = new System.Windows.Forms.ListView(); + this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader10 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip3 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.menuStrip1.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.statusStrip1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.contextMenuStrip3.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + resources.ApplyResources(this.menuStrip1, "menuStrip1"); + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.钱包WToolStripMenuItem, + this.交易TToolStripMenuItem, + this.高级AToolStripMenuItem, + this.帮助HToolStripMenuItem}); + this.menuStrip1.Name = "menuStrip1"; + // + // 钱包WToolStripMenuItem + // + resources.ApplyResources(this.钱包WToolStripMenuItem, "钱包WToolStripMenuItem"); + this.钱包WToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.创建钱包数据库NToolStripMenuItem, + this.打开钱包数据库OToolStripMenuItem, + this.toolStripSeparator1, + this.修改密码CToolStripMenuItem, + this.toolStripSeparator2, + this.退出XToolStripMenuItem}); + this.钱包WToolStripMenuItem.Name = "钱包WToolStripMenuItem"; + // + // 创建钱包数据库NToolStripMenuItem + // + resources.ApplyResources(this.创建钱包数据库NToolStripMenuItem, "创建钱包数据库NToolStripMenuItem"); + this.创建钱包数据库NToolStripMenuItem.Name = "创建钱包数据库NToolStripMenuItem"; + this.创建钱包数据库NToolStripMenuItem.Click += new System.EventHandler(this.创建钱包数据库NToolStripMenuItem_Click); + // + // 打开钱包数据库OToolStripMenuItem + // + resources.ApplyResources(this.打开钱包数据库OToolStripMenuItem, "打开钱包数据库OToolStripMenuItem"); + this.打开钱包数据库OToolStripMenuItem.Name = "打开钱包数据库OToolStripMenuItem"; + this.打开钱包数据库OToolStripMenuItem.Click += new System.EventHandler(this.打开钱包数据库OToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1"); + this.toolStripSeparator1.Name = "toolStripSeparator1"; + // + // 修改密码CToolStripMenuItem + // + resources.ApplyResources(this.修改密码CToolStripMenuItem, "修改密码CToolStripMenuItem"); + this.修改密码CToolStripMenuItem.Name = "修改密码CToolStripMenuItem"; + this.修改密码CToolStripMenuItem.Click += new System.EventHandler(this.修改密码CToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + resources.ApplyResources(this.toolStripSeparator2, "toolStripSeparator2"); + this.toolStripSeparator2.Name = "toolStripSeparator2"; + // + // 退出XToolStripMenuItem + // + resources.ApplyResources(this.退出XToolStripMenuItem, "退出XToolStripMenuItem"); + this.退出XToolStripMenuItem.Name = "退出XToolStripMenuItem"; + this.退出XToolStripMenuItem.Click += new System.EventHandler(this.退出XToolStripMenuItem_Click); + // + // 交易TToolStripMenuItem + // + resources.ApplyResources(this.交易TToolStripMenuItem, "交易TToolStripMenuItem"); + this.交易TToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.转账TToolStripMenuItem, + this.toolStripSeparator5, + this.签名SToolStripMenuItem}); + this.交易TToolStripMenuItem.Name = "交易TToolStripMenuItem"; + // + // 转账TToolStripMenuItem + // + resources.ApplyResources(this.转账TToolStripMenuItem, "转账TToolStripMenuItem"); + this.转账TToolStripMenuItem.Name = "转账TToolStripMenuItem"; + this.转账TToolStripMenuItem.Click += new System.EventHandler(this.转账TToolStripMenuItem_Click); + // + // toolStripSeparator5 + // + resources.ApplyResources(this.toolStripSeparator5, "toolStripSeparator5"); + this.toolStripSeparator5.Name = "toolStripSeparator5"; + // + // 签名SToolStripMenuItem + // + resources.ApplyResources(this.签名SToolStripMenuItem, "签名SToolStripMenuItem"); + this.签名SToolStripMenuItem.Name = "签名SToolStripMenuItem"; + this.签名SToolStripMenuItem.Click += new System.EventHandler(this.签名SToolStripMenuItem_Click); + // + // 高级AToolStripMenuItem + // + resources.ApplyResources(this.高级AToolStripMenuItem, "高级AToolStripMenuItem"); + this.高级AToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.deployContractToolStripMenuItem, + this.invokeContractToolStripMenuItem, + this.toolStripSeparator11, + this.选举EToolStripMenuItem, + this.signDataToolStripMenuItem, + this.toolStripSeparator9, + this.optionsToolStripMenuItem}); + this.高级AToolStripMenuItem.Name = "高级AToolStripMenuItem"; + // + // deployContractToolStripMenuItem + // + resources.ApplyResources(this.deployContractToolStripMenuItem, "deployContractToolStripMenuItem"); + this.deployContractToolStripMenuItem.Name = "deployContractToolStripMenuItem"; + this.deployContractToolStripMenuItem.Click += new System.EventHandler(this.deployContractToolStripMenuItem_Click); + // + // invokeContractToolStripMenuItem + // + resources.ApplyResources(this.invokeContractToolStripMenuItem, "invokeContractToolStripMenuItem"); + this.invokeContractToolStripMenuItem.Name = "invokeContractToolStripMenuItem"; + this.invokeContractToolStripMenuItem.Click += new System.EventHandler(this.invokeContractToolStripMenuItem_Click); + // + // toolStripSeparator11 + // + resources.ApplyResources(this.toolStripSeparator11, "toolStripSeparator11"); + this.toolStripSeparator11.Name = "toolStripSeparator11"; + // + // 选举EToolStripMenuItem + // + resources.ApplyResources(this.选举EToolStripMenuItem, "选举EToolStripMenuItem"); + this.选举EToolStripMenuItem.Name = "选举EToolStripMenuItem"; + this.选举EToolStripMenuItem.Click += new System.EventHandler(this.选举EToolStripMenuItem_Click); + // + // signDataToolStripMenuItem + // + resources.ApplyResources(this.signDataToolStripMenuItem, "signDataToolStripMenuItem"); + this.signDataToolStripMenuItem.Name = "signDataToolStripMenuItem"; + this.signDataToolStripMenuItem.Click += new System.EventHandler(this.signDataToolStripMenuItem_Click); + // + // toolStripSeparator9 + // + resources.ApplyResources(this.toolStripSeparator9, "toolStripSeparator9"); + this.toolStripSeparator9.Name = "toolStripSeparator9"; + // + // optionsToolStripMenuItem + // + resources.ApplyResources(this.optionsToolStripMenuItem, "optionsToolStripMenuItem"); + this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; + this.optionsToolStripMenuItem.Click += new System.EventHandler(this.optionsToolStripMenuItem_Click); + // + // 帮助HToolStripMenuItem + // + resources.ApplyResources(this.帮助HToolStripMenuItem, "帮助HToolStripMenuItem"); + this.帮助HToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看帮助VToolStripMenuItem, + this.官网WToolStripMenuItem, + this.toolStripSeparator3, + this.开发人员工具TToolStripMenuItem, + this.consoleToolStripMenuItem, + this.toolStripSeparator4, + this.关于AntSharesToolStripMenuItem}); + this.帮助HToolStripMenuItem.Name = "帮助HToolStripMenuItem"; + // + // 查看帮助VToolStripMenuItem + // + resources.ApplyResources(this.查看帮助VToolStripMenuItem, "查看帮助VToolStripMenuItem"); + this.查看帮助VToolStripMenuItem.Name = "查看帮助VToolStripMenuItem"; + // + // 官网WToolStripMenuItem + // + resources.ApplyResources(this.官网WToolStripMenuItem, "官网WToolStripMenuItem"); + this.官网WToolStripMenuItem.Name = "官网WToolStripMenuItem"; + this.官网WToolStripMenuItem.Click += new System.EventHandler(this.官网WToolStripMenuItem_Click); + // + // toolStripSeparator3 + // + resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3"); + this.toolStripSeparator3.Name = "toolStripSeparator3"; + // + // 开发人员工具TToolStripMenuItem + // + resources.ApplyResources(this.开发人员工具TToolStripMenuItem, "开发人员工具TToolStripMenuItem"); + this.开发人员工具TToolStripMenuItem.Name = "开发人员工具TToolStripMenuItem"; + this.开发人员工具TToolStripMenuItem.Click += new System.EventHandler(this.开发人员工具TToolStripMenuItem_Click); + // + // consoleToolStripMenuItem + // + resources.ApplyResources(this.consoleToolStripMenuItem, "consoleToolStripMenuItem"); + this.consoleToolStripMenuItem.Name = "consoleToolStripMenuItem"; + this.consoleToolStripMenuItem.Click += new System.EventHandler(this.consoleToolStripMenuItem_Click); + // + // toolStripSeparator4 + // + resources.ApplyResources(this.toolStripSeparator4, "toolStripSeparator4"); + this.toolStripSeparator4.Name = "toolStripSeparator4"; + // + // 关于AntSharesToolStripMenuItem + // + resources.ApplyResources(this.关于AntSharesToolStripMenuItem, "关于AntSharesToolStripMenuItem"); + this.关于AntSharesToolStripMenuItem.Name = "关于AntSharesToolStripMenuItem"; + this.关于AntSharesToolStripMenuItem.Click += new System.EventHandler(this.关于AntSharesToolStripMenuItem_Click); + // + // listView1 + // + resources.ApplyResources(this.listView1, "listView1"); + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader4, + this.columnHeader11}); + this.listView1.ContextMenuStrip = this.contextMenuStrip1; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.Groups.AddRange(new System.Windows.Forms.ListViewGroup[] { + ((System.Windows.Forms.ListViewGroup)(resources.GetObject("listView1.Groups"))), + ((System.Windows.Forms.ListViewGroup)(resources.GetObject("listView1.Groups1"))), + ((System.Windows.Forms.ListViewGroup)(resources.GetObject("listView1.Groups2")))}); + this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView1.HideSelection = false; + this.listView1.Name = "listView1"; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.DoubleClick += new System.EventHandler(this.listView1_DoubleClick); + // + // columnHeader1 + // + resources.ApplyResources(this.columnHeader1, "columnHeader1"); + // + // columnHeader4 + // + resources.ApplyResources(this.columnHeader4, "columnHeader4"); + // + // columnHeader11 + // + resources.ApplyResources(this.columnHeader11, "columnHeader11"); + // + // contextMenuStrip1 + // + resources.ApplyResources(this.contextMenuStrip1, "contextMenuStrip1"); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.创建新地址NToolStripMenuItem, + this.导入私钥IToolStripMenuItem, + this.创建智能合约SToolStripMenuItem, + this.toolStripSeparator6, + this.查看私钥VToolStripMenuItem, + this.viewContractToolStripMenuItem, + this.voteToolStripMenuItem, + this.复制到剪贴板CToolStripMenuItem, + this.删除DToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 创建新地址NToolStripMenuItem + // + resources.ApplyResources(this.创建新地址NToolStripMenuItem, "创建新地址NToolStripMenuItem"); + this.创建新地址NToolStripMenuItem.Name = "创建新地址NToolStripMenuItem"; + this.创建新地址NToolStripMenuItem.Click += new System.EventHandler(this.创建新地址NToolStripMenuItem_Click); + // + // 导入私钥IToolStripMenuItem + // + resources.ApplyResources(this.导入私钥IToolStripMenuItem, "导入私钥IToolStripMenuItem"); + this.导入私钥IToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.importWIFToolStripMenuItem, + this.toolStripSeparator10, + this.importWatchOnlyAddressToolStripMenuItem}); + this.导入私钥IToolStripMenuItem.Name = "导入私钥IToolStripMenuItem"; + // + // importWIFToolStripMenuItem + // + resources.ApplyResources(this.importWIFToolStripMenuItem, "importWIFToolStripMenuItem"); + this.importWIFToolStripMenuItem.Name = "importWIFToolStripMenuItem"; + this.importWIFToolStripMenuItem.Click += new System.EventHandler(this.importWIFToolStripMenuItem_Click); + // + // toolStripSeparator10 + // + resources.ApplyResources(this.toolStripSeparator10, "toolStripSeparator10"); + this.toolStripSeparator10.Name = "toolStripSeparator10"; + // + // importWatchOnlyAddressToolStripMenuItem + // + resources.ApplyResources(this.importWatchOnlyAddressToolStripMenuItem, "importWatchOnlyAddressToolStripMenuItem"); + this.importWatchOnlyAddressToolStripMenuItem.Name = "importWatchOnlyAddressToolStripMenuItem"; + this.importWatchOnlyAddressToolStripMenuItem.Click += new System.EventHandler(this.importWatchOnlyAddressToolStripMenuItem_Click); + // + // 创建智能合约SToolStripMenuItem + // + resources.ApplyResources(this.创建智能合约SToolStripMenuItem, "创建智能合约SToolStripMenuItem"); + this.创建智能合约SToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.多方签名MToolStripMenuItem, + this.toolStripSeparator12, + this.自定义CToolStripMenuItem}); + this.创建智能合约SToolStripMenuItem.Name = "创建智能合约SToolStripMenuItem"; + // + // 多方签名MToolStripMenuItem + // + resources.ApplyResources(this.多方签名MToolStripMenuItem, "多方签名MToolStripMenuItem"); + this.多方签名MToolStripMenuItem.Name = "多方签名MToolStripMenuItem"; + this.多方签名MToolStripMenuItem.Click += new System.EventHandler(this.多方签名MToolStripMenuItem_Click); + // + // toolStripSeparator12 + // + resources.ApplyResources(this.toolStripSeparator12, "toolStripSeparator12"); + this.toolStripSeparator12.Name = "toolStripSeparator12"; + // + // 自定义CToolStripMenuItem + // + resources.ApplyResources(this.自定义CToolStripMenuItem, "自定义CToolStripMenuItem"); + this.自定义CToolStripMenuItem.Name = "自定义CToolStripMenuItem"; + this.自定义CToolStripMenuItem.Click += new System.EventHandler(this.自定义CToolStripMenuItem_Click); + // + // toolStripSeparator6 + // + resources.ApplyResources(this.toolStripSeparator6, "toolStripSeparator6"); + this.toolStripSeparator6.Name = "toolStripSeparator6"; + // + // 查看私钥VToolStripMenuItem + // + resources.ApplyResources(this.查看私钥VToolStripMenuItem, "查看私钥VToolStripMenuItem"); + this.查看私钥VToolStripMenuItem.Name = "查看私钥VToolStripMenuItem"; + this.查看私钥VToolStripMenuItem.Click += new System.EventHandler(this.查看私钥VToolStripMenuItem_Click); + // + // viewContractToolStripMenuItem + // + resources.ApplyResources(this.viewContractToolStripMenuItem, "viewContractToolStripMenuItem"); + this.viewContractToolStripMenuItem.Name = "viewContractToolStripMenuItem"; + this.viewContractToolStripMenuItem.Click += new System.EventHandler(this.viewContractToolStripMenuItem_Click); + // + // voteToolStripMenuItem + // + resources.ApplyResources(this.voteToolStripMenuItem, "voteToolStripMenuItem"); + this.voteToolStripMenuItem.Name = "voteToolStripMenuItem"; + this.voteToolStripMenuItem.Click += new System.EventHandler(this.voteToolStripMenuItem_Click); + // + // 复制到剪贴板CToolStripMenuItem + // + resources.ApplyResources(this.复制到剪贴板CToolStripMenuItem, "复制到剪贴板CToolStripMenuItem"); + this.复制到剪贴板CToolStripMenuItem.Name = "复制到剪贴板CToolStripMenuItem"; + this.复制到剪贴板CToolStripMenuItem.Click += new System.EventHandler(this.复制到剪贴板CToolStripMenuItem_Click); + // + // 删除DToolStripMenuItem + // + resources.ApplyResources(this.删除DToolStripMenuItem, "删除DToolStripMenuItem"); + this.删除DToolStripMenuItem.Name = "删除DToolStripMenuItem"; + this.删除DToolStripMenuItem.Click += new System.EventHandler(this.删除DToolStripMenuItem_Click); + // + // statusStrip1 + // + resources.ApplyResources(this.statusStrip1, "statusStrip1"); + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripStatusLabel1, + this.lbl_height, + this.toolStripStatusLabel4, + this.lbl_count_node, + this.toolStripProgressBar1, + this.toolStripStatusLabel2, + this.toolStripStatusLabel3}); + this.statusStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow; + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.SizingGrip = false; + // + // toolStripStatusLabel1 + // + resources.ApplyResources(this.toolStripStatusLabel1, "toolStripStatusLabel1"); + this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; + // + // lbl_height + // + resources.ApplyResources(this.lbl_height, "lbl_height"); + this.lbl_height.Name = "lbl_height"; + // + // toolStripStatusLabel4 + // + resources.ApplyResources(this.toolStripStatusLabel4, "toolStripStatusLabel4"); + this.toolStripStatusLabel4.Name = "toolStripStatusLabel4"; + // + // lbl_count_node + // + resources.ApplyResources(this.lbl_count_node, "lbl_count_node"); + this.lbl_count_node.Name = "lbl_count_node"; + // + // toolStripProgressBar1 + // + resources.ApplyResources(this.toolStripProgressBar1, "toolStripProgressBar1"); + this.toolStripProgressBar1.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.toolStripProgressBar1.Maximum = 15; + this.toolStripProgressBar1.Name = "toolStripProgressBar1"; + this.toolStripProgressBar1.Step = 1; + // + // toolStripStatusLabel2 + // + resources.ApplyResources(this.toolStripStatusLabel2, "toolStripStatusLabel2"); + this.toolStripStatusLabel2.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.toolStripStatusLabel2.Name = "toolStripStatusLabel2"; + // + // toolStripStatusLabel3 + // + resources.ApplyResources(this.toolStripStatusLabel3, "toolStripStatusLabel3"); + this.toolStripStatusLabel3.IsLink = true; + this.toolStripStatusLabel3.Name = "toolStripStatusLabel3"; + this.toolStripStatusLabel3.Click += new System.EventHandler(this.toolStripStatusLabel3_Click); + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 500; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // tabControl1 + // + resources.ApplyResources(this.tabControl1, "tabControl1"); + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + // + // tabPage1 + // + resources.ApplyResources(this.tabPage1, "tabPage1"); + this.tabPage1.Controls.Add(this.listView1); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabPage2 + // + resources.ApplyResources(this.tabPage2, "tabPage2"); + this.tabPage2.Controls.Add(this.listView2); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // listView2 + // + resources.ApplyResources(this.listView2, "listView2"); + this.listView2.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader2, + this.columnHeader6, + this.columnHeader3, + this.columnHeader5}); + this.listView2.FullRowSelect = true; + this.listView2.GridLines = true; + this.listView2.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView2.HideSelection = false; + this.listView2.Name = "listView2"; + this.listView2.ShowGroups = false; + this.listView2.UseCompatibleStateImageBehavior = false; + this.listView2.View = System.Windows.Forms.View.Details; + this.listView2.DoubleClick += new System.EventHandler(this.listView2_DoubleClick); + // + // columnHeader2 + // + resources.ApplyResources(this.columnHeader2, "columnHeader2"); + // + // columnHeader6 + // + resources.ApplyResources(this.columnHeader6, "columnHeader6"); + // + // columnHeader3 + // + resources.ApplyResources(this.columnHeader3, "columnHeader3"); + // + // columnHeader5 + // + resources.ApplyResources(this.columnHeader5, "columnHeader5"); + // + // tabPage3 + // + resources.ApplyResources(this.tabPage3, "tabPage3"); + this.tabPage3.Controls.Add(this.listView3); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // listView3 + // + resources.ApplyResources(this.listView3, "listView3"); + this.listView3.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader7, + this.columnHeader8, + this.columnHeader9, + this.columnHeader10}); + this.listView3.ContextMenuStrip = this.contextMenuStrip3; + this.listView3.FullRowSelect = true; + this.listView3.GridLines = true; + this.listView3.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView3.HideSelection = false; + this.listView3.Name = "listView3"; + this.listView3.ShowGroups = false; + this.listView3.UseCompatibleStateImageBehavior = false; + this.listView3.View = System.Windows.Forms.View.Details; + this.listView3.DoubleClick += new System.EventHandler(this.listView3_DoubleClick); + // + // columnHeader7 + // + resources.ApplyResources(this.columnHeader7, "columnHeader7"); + // + // columnHeader8 + // + resources.ApplyResources(this.columnHeader8, "columnHeader8"); + // + // columnHeader9 + // + resources.ApplyResources(this.columnHeader9, "columnHeader9"); + // + // columnHeader10 + // + resources.ApplyResources(this.columnHeader10, "columnHeader10"); + // + // contextMenuStrip3 + // + resources.ApplyResources(this.contextMenuStrip3, "contextMenuStrip3"); + this.contextMenuStrip3.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1}); + this.contextMenuStrip3.Name = "contextMenuStrip3"; + // + // toolStripMenuItem1 + // + resources.ApplyResources(this.toolStripMenuItem1, "toolStripMenuItem1"); + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // MainForm + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.menuStrip1); + this.MainMenuStrip = this.menuStrip1; + this.Name = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.contextMenuStrip1.ResumeLayout(false); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.contextMenuStrip3.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem 钱包WToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 创建钱包数据库NToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 打开钱包数据库OToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 修改密码CToolStripMenuItem; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 退出XToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 帮助HToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看帮助VToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 官网WToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripMenuItem 开发人员工具TToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripMenuItem 关于AntSharesToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 交易TToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 签名SToolStripMenuItem; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 创建新地址NToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 导入私钥IToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; + private System.Windows.Forms.ToolStripMenuItem 查看私钥VToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 复制到剪贴板CToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除DToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; + private System.Windows.Forms.ToolStripStatusLabel lbl_height; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel4; + private System.Windows.Forms.ToolStripStatusLabel lbl_count_node; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.ListView listView2; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ToolStripMenuItem 转账TToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 高级AToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 创建智能合约SToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 多方签名MToolStripMenuItem; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ToolStripMenuItem importWIFToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 选举EToolStripMenuItem; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.ListView listView3; + private System.Windows.Forms.ColumnHeader columnHeader7; + private System.Windows.Forms.ColumnHeader columnHeader8; + private System.Windows.Forms.ColumnHeader columnHeader9; + private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar1; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel2; + private System.Windows.Forms.ToolStripMenuItem 自定义CToolStripMenuItem; + private System.Windows.Forms.ColumnHeader columnHeader10; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip3; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator9; + private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel3; + private System.Windows.Forms.ToolStripMenuItem viewContractToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator10; + private System.Windows.Forms.ToolStripMenuItem importWatchOnlyAddressToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem voteToolStripMenuItem; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.ColumnHeader columnHeader11; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator11; + private System.Windows.Forms.ToolStripMenuItem deployContractToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem invokeContractToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator12; + private System.Windows.Forms.ToolStripMenuItem signDataToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem consoleToolStripMenuItem; + } +} + diff --git a/src/Neo.GUI/GUI/MainForm.cs b/src/Neo.GUI/GUI/MainForm.cs new file mode 100644 index 0000000000..d8e89c083a --- /dev/null +++ b/src/Neo.GUI/GUI/MainForm.cs @@ -0,0 +1,615 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.IO.Actors; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.Properties; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using Neo.Wallets.NEP6; +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Windows.Forms; +using System.Xml.Linq; +using static Neo.Program; +using static Neo.SmartContract.Helper; +using VMArray = Neo.VM.Types.Array; + +namespace Neo.GUI +{ + internal partial class MainForm : Form + { + private bool check_nep5_balance = false; + private DateTime persistence_time = DateTime.MinValue; + private IActorRef actor; + + public MainForm(XDocument xdoc = null) + { + InitializeComponent(); + + toolStripProgressBar1.Maximum = (int)Service.NeoSystem.Settings.TimePerBlock.TotalSeconds; + + if (xdoc != null) + { + Version version = Assembly.GetExecutingAssembly().GetName().Version; + Version latest = Version.Parse(xdoc.Element("update").Attribute("latest").Value); + if (version < latest) + { + toolStripStatusLabel3.Tag = xdoc; + toolStripStatusLabel3.Text += $": {latest}"; + toolStripStatusLabel3.Visible = true; + } + } + } + + private void AddAccount(WalletAccount account, bool selected = false) + { + ListViewItem item = listView1.Items[account.Address]; + if (item != null) + { + if (!account.WatchOnly && ((WalletAccount)item.Tag).WatchOnly) + { + listView1.Items.Remove(item); + item = null; + } + } + if (item == null) + { + string groupName = account.WatchOnly ? "watchOnlyGroup" : IsSignatureContract(account.Contract.Script) ? "standardContractGroup" : "nonstandardContractGroup"; + item = listView1.Items.Add(new ListViewItem(new[] + { + new ListViewItem.ListViewSubItem + { + Name = "address", + Text = account.Address + }, + new ListViewItem.ListViewSubItem + { + Name = NativeContract.NEO.Symbol + }, + new ListViewItem.ListViewSubItem + { + Name = NativeContract.GAS.Symbol + } + }, -1, listView1.Groups[groupName]) + { + Name = account.Address, + Tag = account + }); + } + item.Selected = selected; + } + + private void Blockchain_PersistCompleted(Blockchain.PersistCompleted e) + { + if (IsDisposed) return; + persistence_time = DateTime.UtcNow; + if (Service.CurrentWallet != null) + check_nep5_balance = true; + BeginInvoke(new Action(RefreshConfirmations)); + } + + private static void OpenBrowser(string url) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Process.Start(new ProcessStartInfo("cmd", $"/c start {url}")); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Process.Start("xdg-open", url); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Process.Start("open", url); + } + } + + private void Service_WalletChanged(object sender, Wallet wallet) + { + if (InvokeRequired) + { + Invoke(new EventHandler(Service_WalletChanged), sender, wallet); + return; + } + + listView3.Items.Clear(); + 修改密码CToolStripMenuItem.Enabled = wallet != null; + 交易TToolStripMenuItem.Enabled = wallet != null; + signDataToolStripMenuItem.Enabled = wallet != null; + deployContractToolStripMenuItem.Enabled = wallet != null; + invokeContractToolStripMenuItem.Enabled = wallet != null; + 选举EToolStripMenuItem.Enabled = wallet != null; + 创建新地址NToolStripMenuItem.Enabled = wallet != null; + 导入私钥IToolStripMenuItem.Enabled = wallet != null; + 创建智能合约SToolStripMenuItem.Enabled = wallet != null; + listView1.Items.Clear(); + if (wallet != null) + { + foreach (WalletAccount account in wallet.GetAccounts().ToArray()) + { + AddAccount(account); + } + } + check_nep5_balance = true; + } + + private void RefreshConfirmations() + { + foreach (ListViewItem item in listView3.Items) + { + uint? height = item.Tag as uint?; + int? confirmations = (int)NativeContract.Ledger.CurrentIndex(Service.NeoSystem.StoreView) - (int?)height + 1; + if (confirmations <= 0) confirmations = null; + item.SubItems["confirmations"].Text = confirmations?.ToString() ?? Strings.Unconfirmed; + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + actor = Service.NeoSystem.ActorSystem.ActorOf(EventWrapper.Props(Blockchain_PersistCompleted)); + Service.WalletChanged += Service_WalletChanged; + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (actor != null) + Service.NeoSystem.ActorSystem.Stop(actor); + Service.WalletChanged -= Service_WalletChanged; + } + + private void timer1_Tick(object sender, EventArgs e) + { + uint height = NativeContract.Ledger.CurrentIndex(Service.NeoSystem.StoreView); + uint headerHeight = Service.NeoSystem.HeaderCache.Last?.Index ?? height; + + lbl_height.Text = $"{height}/{headerHeight}"; + lbl_count_node.Text = Service.LocalNode.ConnectedCount.ToString(); + TimeSpan persistence_span = DateTime.UtcNow - persistence_time; + if (persistence_span < TimeSpan.Zero) persistence_span = TimeSpan.Zero; + if (persistence_span > Service.NeoSystem.Settings.TimePerBlock) + { + toolStripProgressBar1.Style = ProgressBarStyle.Marquee; + } + else + { + toolStripProgressBar1.Value = persistence_span.Seconds; + toolStripProgressBar1.Style = ProgressBarStyle.Blocks; + } + if (Service.CurrentWallet is null) return; + if (!check_nep5_balance || persistence_span < TimeSpan.FromSeconds(2)) return; + check_nep5_balance = false; + UInt160[] addresses = Service.CurrentWallet.GetAccounts().Select(p => p.ScriptHash).ToArray(); + if (addresses.Length == 0) return; + using var snapshot = Service.NeoSystem.GetSnapshot(); + foreach (UInt160 assetId in NEP5Watched) + { + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + for (int i = addresses.Length - 1; i >= 0; i--) + sb.EmitDynamicCall(assetId, "balanceOf", addresses[i]); + sb.Emit(OpCode.DEPTH, OpCode.PACK); + sb.EmitDynamicCall(assetId, "decimals"); + sb.EmitDynamicCall(assetId, "name"); + script = sb.ToArray(); + } + using ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, gas: 0_20000000L * addresses.Length); + if (engine.State.HasFlag(VMState.FAULT)) continue; + string name = engine.ResultStack.Pop().GetString(); + byte decimals = (byte)engine.ResultStack.Pop().GetInteger(); + BigInteger[] balances = ((VMArray)engine.ResultStack.Pop()).Select(p => p.GetInteger()).ToArray(); + string symbol = null; + if (assetId.Equals(NativeContract.NEO.Hash)) + symbol = NativeContract.NEO.Symbol; + else if (assetId.Equals(NativeContract.GAS.Hash)) + symbol = NativeContract.GAS.Symbol; + if (symbol != null) + for (int i = 0; i < addresses.Length; i++) + listView1.Items[addresses[i].ToAddress(Service.NeoSystem.Settings.AddressVersion)].SubItems[symbol].Text = new BigDecimal(balances[i], decimals).ToString(); + BigInteger amount = balances.Sum(); + if (amount == 0) + { + listView2.Items.RemoveByKey(assetId.ToString()); + continue; + } + BigDecimal balance = new BigDecimal(amount, decimals); + if (listView2.Items.ContainsKey(assetId.ToString())) + { + listView2.Items[assetId.ToString()].SubItems["value"].Text = balance.ToString(); + } + else + { + listView2.Items.Add(new ListViewItem(new[] + { + new ListViewItem.ListViewSubItem + { + Name = "name", + Text = name + }, + new ListViewItem.ListViewSubItem + { + Name = "type", + Text = "NEP-5" + }, + new ListViewItem.ListViewSubItem + { + Name = "value", + Text = balance.ToString() + }, + new ListViewItem.ListViewSubItem + { + ForeColor = Color.Gray, + Name = "issuer", + Text = $"ScriptHash:{assetId}" + } + }, -1) + { + Name = assetId.ToString(), + UseItemStyleForSubItems = false + }); + } + } + } + + private void 创建钱包数据库NToolStripMenuItem_Click(object sender, EventArgs e) + { + using CreateWalletDialog dialog = new CreateWalletDialog(); + if (dialog.ShowDialog() != DialogResult.OK) return; + Service.CreateWallet(dialog.WalletPath, dialog.Password); + } + + private void 打开钱包数据库OToolStripMenuItem_Click(object sender, EventArgs e) + { + using OpenWalletDialog dialog = new OpenWalletDialog(); + if (dialog.ShowDialog() != DialogResult.OK) return; + try + { + Service.OpenWallet(dialog.WalletPath, dialog.Password); + } + catch (CryptographicException) + { + MessageBox.Show(Strings.PasswordIncorrect); + } + } + + private void 修改密码CToolStripMenuItem_Click(object sender, EventArgs e) + { + using ChangePasswordDialog dialog = new ChangePasswordDialog(); + if (dialog.ShowDialog() != DialogResult.OK) return; + if (Service.CurrentWallet.ChangePassword(dialog.OldPassword, dialog.NewPassword)) + { + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + MessageBox.Show(Strings.ChangePasswordSuccessful); + } + else + { + MessageBox.Show(Strings.PasswordIncorrect); + } + } + + private void 退出XToolStripMenuItem_Click(object sender, EventArgs e) + { + Close(); + } + + private void 转账TToolStripMenuItem_Click(object sender, EventArgs e) + { + Transaction tx; + using (TransferDialog dialog = new TransferDialog()) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + tx = dialog.GetTransaction(); + } + using (InvokeContractDialog dialog = new InvokeContractDialog(tx)) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + tx = dialog.GetTransaction(); + } + Helper.SignAndShowInformation(tx); + } + + private void 签名SToolStripMenuItem_Click(object sender, EventArgs e) + { + using SigningTxDialog dialog = new SigningTxDialog(); + dialog.ShowDialog(); + } + + private void deployContractToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + byte[] script; + using (DeployContractDialog dialog = new DeployContractDialog()) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + script = dialog.GetScript(); + } + using (InvokeContractDialog dialog = new InvokeContractDialog(script)) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + Helper.SignAndShowInformation(dialog.GetTransaction()); + } + } + catch { } + } + + private void invokeContractToolStripMenuItem_Click(object sender, EventArgs e) + { + using InvokeContractDialog dialog = new InvokeContractDialog(); + if (dialog.ShowDialog() != DialogResult.OK) return; + try + { + Helper.SignAndShowInformation(dialog.GetTransaction()); + } + catch + { + return; + } + } + + private void 选举EToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + byte[] script; + using (ElectionDialog dialog = new ElectionDialog()) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + script = dialog.GetScript(); + } + using (InvokeContractDialog dialog = new InvokeContractDialog(script)) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + Helper.SignAndShowInformation(dialog.GetTransaction()); + } + } + catch { } + } + + private void signDataToolStripMenuItem_Click(object sender, EventArgs e) + { + using SigningDialog dialog = new SigningDialog(); + dialog.ShowDialog(); + } + + private void optionsToolStripMenuItem_Click(object sender, EventArgs e) + { + } + + private void 官网WToolStripMenuItem_Click(object sender, EventArgs e) + { + OpenBrowser("https://neo.org/"); + } + + private void 开发人员工具TToolStripMenuItem_Click(object sender, EventArgs e) + { + Helper.Show(); + } + + private void consoleToolStripMenuItem_Click(object sender, EventArgs e) + { + Helper.Show(); + } + + private void 关于AntSharesToolStripMenuItem_Click(object sender, EventArgs e) + { + MessageBox.Show($"{Strings.AboutMessage} {Strings.AboutVersion}{Assembly.GetExecutingAssembly().GetName().Version}", Strings.About); + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + 查看私钥VToolStripMenuItem.Enabled = + listView1.SelectedIndices.Count == 1 && + !((WalletAccount)listView1.SelectedItems[0].Tag).WatchOnly && + IsSignatureContract(((WalletAccount)listView1.SelectedItems[0].Tag).Contract.Script); + viewContractToolStripMenuItem.Enabled = + listView1.SelectedIndices.Count == 1 && + !((WalletAccount)listView1.SelectedItems[0].Tag).WatchOnly; + voteToolStripMenuItem.Enabled = + listView1.SelectedIndices.Count == 1 && + !((WalletAccount)listView1.SelectedItems[0].Tag).WatchOnly && + !string.IsNullOrEmpty(listView1.SelectedItems[0].SubItems[NativeContract.NEO.Symbol].Text) && + decimal.Parse(listView1.SelectedItems[0].SubItems[NativeContract.NEO.Symbol].Text) > 0; + 复制到剪贴板CToolStripMenuItem.Enabled = listView1.SelectedIndices.Count == 1; + 删除DToolStripMenuItem.Enabled = listView1.SelectedIndices.Count > 0; + } + + private void 创建新地址NToolStripMenuItem_Click(object sender, EventArgs e) + { + listView1.SelectedIndices.Clear(); + WalletAccount account = Service.CurrentWallet.CreateAccount(); + AddAccount(account, true); + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + } + + private void importWIFToolStripMenuItem_Click(object sender, EventArgs e) + { + using ImportPrivateKeyDialog dialog = new ImportPrivateKeyDialog(); + if (dialog.ShowDialog() != DialogResult.OK) return; + listView1.SelectedIndices.Clear(); + foreach (string wif in dialog.WifStrings) + { + WalletAccount account; + try + { + account = Service.CurrentWallet.Import(wif); + } + catch (FormatException) + { + continue; + } + AddAccount(account, true); + } + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + } + + private void importWatchOnlyAddressToolStripMenuItem_Click(object sender, EventArgs e) + { + string text = InputBox.Show(Strings.Address, Strings.ImportWatchOnlyAddress); + if (string.IsNullOrEmpty(text)) return; + using (StringReader reader = new StringReader(text)) + { + while (true) + { + string address = reader.ReadLine(); + if (address == null) break; + address = address.Trim(); + if (string.IsNullOrEmpty(address)) continue; + UInt160 scriptHash; + try + { + scriptHash = address.ToScriptHash(Service.NeoSystem.Settings.AddressVersion); + } + catch (FormatException) + { + continue; + } + WalletAccount account = Service.CurrentWallet.CreateAccount(scriptHash); + AddAccount(account, true); + } + } + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + } + + private void 多方签名MToolStripMenuItem_Click(object sender, EventArgs e) + { + using CreateMultiSigContractDialog dialog = new CreateMultiSigContractDialog(); + if (dialog.ShowDialog() != DialogResult.OK) return; + Contract contract = dialog.GetContract(); + if (contract == null) + { + MessageBox.Show(Strings.AddContractFailedMessage); + return; + } + WalletAccount account = Service.CurrentWallet.CreateAccount(contract, dialog.GetKey()); + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + listView1.SelectedIndices.Clear(); + AddAccount(account, true); + } + + private void 自定义CToolStripMenuItem_Click(object sender, EventArgs e) + { + using ImportCustomContractDialog dialog = new ImportCustomContractDialog(); + if (dialog.ShowDialog() != DialogResult.OK) return; + Contract contract = dialog.GetContract(); + WalletAccount account = Service.CurrentWallet.CreateAccount(contract, dialog.GetKey()); + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + listView1.SelectedIndices.Clear(); + AddAccount(account, true); + } + + private void 查看私钥VToolStripMenuItem_Click(object sender, EventArgs e) + { + WalletAccount account = (WalletAccount)listView1.SelectedItems[0].Tag; + using ViewPrivateKeyDialog dialog = new ViewPrivateKeyDialog(account); + dialog.ShowDialog(); + } + + private void viewContractToolStripMenuItem_Click(object sender, EventArgs e) + { + WalletAccount account = (WalletAccount)listView1.SelectedItems[0].Tag; + using ViewContractDialog dialog = new ViewContractDialog(account.Contract); + dialog.ShowDialog(); + } + + private void voteToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + WalletAccount account = (WalletAccount)listView1.SelectedItems[0].Tag; + byte[] script; + using (VotingDialog dialog = new VotingDialog(account.ScriptHash)) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + script = dialog.GetScript(); + } + using (InvokeContractDialog dialog = new InvokeContractDialog(script)) + { + if (dialog.ShowDialog() != DialogResult.OK) return; + Helper.SignAndShowInformation(dialog.GetTransaction()); + } + } + catch { } + } + + private void 复制到剪贴板CToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + Clipboard.SetText(listView1.SelectedItems[0].Text); + } + catch (ExternalException) { } + } + + private void 删除DToolStripMenuItem_Click(object sender, EventArgs e) + { + if (MessageBox.Show(Strings.DeleteAddressConfirmationMessage, Strings.DeleteAddressConfirmationCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) != DialogResult.Yes) + return; + WalletAccount[] accounts = listView1.SelectedItems.OfType().Select(p => (WalletAccount)p.Tag).ToArray(); + foreach (WalletAccount account in accounts) + { + listView1.Items.RemoveByKey(account.Address); + Service.CurrentWallet.DeleteAccount(account.ScriptHash); + } + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); + check_nep5_balance = true; + } + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + if (listView3.SelectedItems.Count == 0) return; + Clipboard.SetDataObject(listView3.SelectedItems[0].SubItems[1].Text); + } + + private void listView1_DoubleClick(object sender, EventArgs e) + { + if (listView1.SelectedIndices.Count == 0) return; + OpenBrowser($"https://neoscan.io/address/{listView1.SelectedItems[0].Text}"); + } + + private void listView2_DoubleClick(object sender, EventArgs e) + { + if (listView2.SelectedIndices.Count == 0) return; + OpenBrowser($"https://neoscan.io/asset/{listView2.SelectedItems[0].Name[2..]}"); + } + + private void listView3_DoubleClick(object sender, EventArgs e) + { + if (listView3.SelectedIndices.Count == 0) return; + OpenBrowser($"https://neoscan.io/transaction/{listView3.SelectedItems[0].Name[2..]}"); + } + + private void toolStripStatusLabel3_Click(object sender, EventArgs e) + { + using UpdateDialog dialog = new UpdateDialog((XDocument)toolStripStatusLabel3.Tag); + dialog.ShowDialog(); + } + } +} diff --git a/src/Neo.GUI/GUI/MainForm.es-ES.resx b/src/Neo.GUI/GUI/MainForm.es-ES.resx new file mode 100644 index 0000000000..468113ceba --- /dev/null +++ b/src/Neo.GUI/GUI/MainForm.es-ES.resx @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 210, 22 + + + &Nueva base de datos... + + + 210, 22 + + + &Abrir base de datos... + + + 207, 6 + + + 210, 22 + + + &Cambiar contraseña... + + + 207, 6 + + + 210, 22 + + + &Salir + + + 82, 21 + + + &Monedero + + + 141, 22 + + + &Transferir... + + + 138, 6 + + + 141, 22 + + + &Firma... + + + 89, 21 + + + &Transacción + + + 198, 22 + + + &Desplegar contrato... + + + 198, 22 + + + I&nvocar contrato... + + + 195, 6 + + + 198, 22 + + + &Votación... + + + 198, 22 + + + 195, 6 + + + 198, 22 + + + &Opciones... + + + A&vanzado + + + 259, 22 + + + &Obtener ayuda + + + 259, 22 + + + &Web oficial + + + 256, 6 + + + 259, 22 + + + &Herramienta de desarrollo + + + 259, 22 + + + 256, 6 + + + 259, 22 + + + &Acerca de NEO + + + 56, 21 + + + &Ayuda + + + Dirección + + + 275, 22 + + + Crear &nueva dirección + + + 266, 22 + + + Importar desde &WIF... + + + 263, 6 + + + 266, 22 + + + Importar dirección sólo lectur&a... + + + 275, 22 + + + &Importar + + + 178, 22 + + + &Múltiples firmas... + + + 175, 6 + + + 178, 22 + + + &Personalizado... + + + 275, 22 + + + Crear nueva &dirección de contrato + + + 272, 6 + + + 275, 22 + + + Ver clave &privada + + + 275, 22 + + + Ver c&ontrato + + + 275, 22 + + + &Votar... + + + 275, 22 + + + &Copiar al portapapeles + + + 275, 22 + + + &Eliminar... + + + 276, 186 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAABBDdWVudGEgZXN0w6FuZGFyBfz///8oU3lzdGVtLldpbmRvd3MuRm9ybXMuSG9yaXpvbnRhbEFs + aWdubWVudAEAAAAHdmFsdWVfXwAIAgAAAAAAAAAKBgUAAAAVc3RhbmRhcmRDb250cmFjdEdyb3VwCw== + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAABZEaXJlY2Npw7NuIGRlIGNvbnRyYXRvBfz///8oU3lzdGVtLldpbmRvd3MuRm9ybXMuSG9yaXpv + bnRhbEFsaWdubWVudAEAAAAHdmFsdWVfXwAIAgAAAAAAAAAKBgUAAAAYbm9uc3RhbmRhcmRDb250cmFj + dEdyb3VwCw== + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAABhEaXJlY2Npw7NuIHPDs2xvIGxlY3R1cmEF/P///yhTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jp + em9udGFsQWxpZ25tZW50AQAAAAd2YWx1ZV9fAAgCAAAAAAAAAAoGBQAAAA53YXRjaE9ubHlHcm91cAs= + + + + 58, 17 + + + Tamaño: + + + 74, 17 + + + Conectado: + + + 172, 17 + + + Esperando próximo bloque: + + + 152, 17 + + + Descargar nueva versión + + + Cuenta + + + Activo + + + Tipo + + + Saldo + + + Emisor + + + Activos + + + Fecha + + + ID de la transacción + + + Confirmación + + + Tipo + + + 147, 22 + + + &Copiar TXID + + + 148, 26 + + + Historial de transacciones + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/MainForm.resx b/src/Neo.GUI/GUI/MainForm.resx new file mode 100644 index 0000000000..21c7f5a2b2 --- /dev/null +++ b/src/Neo.GUI/GUI/MainForm.resx @@ -0,0 +1,1488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + 216, 22 + + + &New Wallet Database... + + + 216, 22 + + + &Open Wallet Database... + + + 213, 6 + + + + False + + + 216, 22 + + + &Change Password... + + + 213, 6 + + + 216, 22 + + + E&xit + + + 56, 21 + + + &Wallet + + + 140, 22 + + + &Transfer... + + + 137, 6 + + + 140, 22 + + + &Signature... + + + False + + + 87, 21 + + + &Transaction + + + False + + + 179, 22 + + + &Deploy Contract... + + + False + + + 179, 22 + + + In&voke Contract... + + + 176, 6 + + + False + + + 179, 22 + + + &Election... + + + False + + + 179, 22 + + + &Sign Message... + + + 176, 6 + + + 179, 22 + + + &Options... + + + 77, 21 + + + &Advanced + + + 194, 22 + + + Check for &Help + + + 194, 22 + + + Official &Web + + + 191, 6 + + + + F12 + + + 194, 22 + + + Developer &Tool + + + 194, 22 + + + &Console + + + 191, 6 + + + 194, 22 + + + &About NEO + + + 47, 21 + + + &Help + + + 0, 0 + + + 7, 3, 0, 3 + + + 903, 27 + + + 0 + + + menuStrip1 + + + menuStrip1 + + + System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Address + + + 300 + + + NEO + + + 120 + + + GAS + + + 120 + + + 348, 17 + + + False + + + 198, 22 + + + Create &New Add. + + + 248, 22 + + + Import from &WIF... + + + 245, 6 + + + 248, 22 + + + Import Watch-Only &Address... + + + False + + + 198, 22 + + + &Import + + + 174, 22 + + + &Multi-Signature... + + + 171, 6 + + + 174, 22 + + + &Custom... + + + False + + + 198, 22 + + + Create Contract &Add. + + + 195, 6 + + + False + + + 198, 22 + + + View &Private Key + + + False + + + 198, 22 + + + View C&ontract + + + False + + + 198, 22 + + + &Vote... + + + False + + + Ctrl+C + + + False + + + 198, 22 + + + &Copy to Clipboard + + + False + + + 198, 22 + + + &Delete... + + + 199, 186 + + + contextMenuStrip1 + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Fill + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAABBTdGFuZGFyZCBBY2NvdW50Bfz///8oU3lzdGVtLldpbmRvd3MuRm9ybXMuSG9yaXpvbnRhbEFs + aWdubWVudAEAAAAHdmFsdWVfXwAIAgAAAAAAAAAKBgUAAAAVc3RhbmRhcmRDb250cmFjdEdyb3VwCw== + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAABBDb250cmFjdCBBZGRyZXNzBfz///8oU3lzdGVtLldpbmRvd3MuRm9ybXMuSG9yaXpvbnRhbEFs + aWdubWVudAEAAAAHdmFsdWVfXwAIAgAAAAAAAAAKBgUAAAAYbm9uc3RhbmRhcmRDb250cmFjdEdyb3Vw + Cw== + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAABJXYXRjaC1Pbmx5IEFkZHJlc3MF/P///yhTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFs + QWxpZ25tZW50AQAAAAd2YWx1ZV9fAAgCAAAAAAAAAAoGBQAAAA53YXRjaE9ubHlHcm91cAs= + + + + 3, 3 + + + 889, 521 + + + 1 + + + listView1 + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage1 + + + 0 + + + 137, 17 + + + 49, 17 + + + Height: + + + 27, 17 + + + 0/0 + + + 73, 17 + + + Connected: + + + 15, 17 + + + 0 + + + 100, 16 + + + 140, 17 + + + Waiting for next block: + + + 145, 17 + + + Download New Version + + + False + + + 0, 584 + + + 903, 22 + + + 2 + + + statusStrip1 + + + statusStrip1 + + + System.Windows.Forms.StatusStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 258, 17 + + + 4, 26 + + + 3, 3, 3, 3 + + + 895, 527 + + + 0 + + + Account + + + tabPage1 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 0 + + + Asset + + + 160 + + + Type + + + 100 + + + Balance + + + 192 + + + Issuer + + + 398 + + + Fill + + + 3, 3 + + + 889, 521 + + + 2 + + + listView2 + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage2 + + + 0 + + + 4, 26 + + + 3, 3, 3, 3 + + + 895, 527 + + + 1 + + + Asset + + + tabPage2 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 1 + + + Time + + + 132 + + + Transaction ID + + + 482 + + + confirm + + + 78 + + + Transaction Type + + + 163 + + + 513, 17 + + + 138, 22 + + + &Copy TXID + + + 139, 26 + + + contextMenuStrip3 + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Fill + + + 3, 3 + + + 889, 521 + + + 0 + + + listView3 + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + 0 + + + 4, 26 + + + 3, 3, 3, 3 + + + 895, 527 + + + 2 + + + Transaction History + + + tabPage3 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 2 + + + Fill + + + 0, 27 + + + 903, 557 + + + 3 + + + tabControl1 + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + True + + + 7, 17 + + + 903, 606 + + + Microsoft YaHei UI, 9pt + + + + AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAA2G8OANdrdgDWaJMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAADadhYA2XOFANhv7wDXav8A1WarAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAANx+HgDbepMA2nb1ANhx/wDXbP8A1mf/ANVjqwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3oUoAN2BoQDcffsA23j/ANlz/wDYbv8A1mn/ANVk/wDU + YKsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgjTYA34mvAN6E/QDcf/8A23r/ANp1/wDY + cP8A12v/ANZm/wDUYf8A012rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5JgAAOKUQgDhkL0A4Iz/AN+H/wDd + gv8A3H3/ANp4/wDZc/8A2G7/ANZo/wDVZP8A017/ANJaqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmnwIA5JtQAOOXyQDi + k/8A4Y7/AN+J/wDehP8A3H//ANt6/wDadf8A2HD/ANdr/wDVZv8A1GH/ANNc/wDRV6sAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOinBADm + o14A5Z/XAOSa/wDjlf8A4ZD/AOCL/wDehv8A3YH/ANx8/wDad/8A2XL/ANdt/wDWaP8A1WP/ANNe/wDS + Wf8A0VWrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAOipRgDnpuEA5qH/AOWc/wDjl/8A4pL/AOCN/wDfiP8A3oP/ANx+/wDbef8A2XT/ANhv/wDX + av8A1WX/ANRg/wDSW/8A0Vb/ANBSqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + KP8AwyP/AMIfqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL0N2wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0NvwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAADZdH4A2HH/ANds/wDWZ/8A1GL/ANNd/wDRWP8A0FP/AM9O/wDNSf8AzET/AMo//wDJ + Ov8AyDX/AMYw/wDFKv8Awyb/AMIg/wDBHKsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9 + DdsAvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Db8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2XJ+ANhu/wDWaf8A1WT/ANNf/wDSWv8A0VX/AM9Q/wDO + S/8AzEb/AMtB/wDKPP8AyDf/AMcy/wDFLf8AxCj/AMMj/wDBHv8AwBmrAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAvQ3bAL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ2/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANhvfgDXa/8A1Wb/ANRh/wDT + XP8A0Vf/ANBS/wDOTf8AzUj/AMxD/wDKPv8AyTn/AMg0/wDGL/8AxSr/AMMl/wDCIP8AwRv/AL8XqwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL0N2wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0NvwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADX + bH4A1mj/ANVj/wDTXv8A0ln/ANBU/wDPT/8Azkr/AMxF/wDLQP8AyTv/AMg2/wDHMf8AxSz/AMQn/wDD + Iv8AwR3/AMAY/wC/FKsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9DdsAvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Db8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAA1ml+ANVl/wDUYP8A0lv/ANFW/wDQUf8Azkz/AM1H/wDMQv8Ayj3/AMk4/wDH + M/8Axi7/AMUp/wDDJP8Awh//AMAa/wC/Ff8AvhGrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAvQ3bAL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ2/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANZmfgDVY/8A017/ANJZ/wDQVP8Az0//AM5K/wDM + Rf8Ayz//AMk7/wDINf8AxzH/AMUr/wDEJv8AwiH/AMEc/wDAF/8AvhL/AL0OqwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAL0N2wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0NvwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVZH4A1GD/ANJb/wDR + Vv8A0FH/AM5M/wDNR/8Ay0L/AMo9/wDJOP8AxzP/AMYu/wDEKf8AwyT/AMIf/wDAGv8AvxX/AL0Q/wC9 + DasAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9DdsAvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9DL8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAA1GF+ANNd/wDSWP8A0FP/AM9O/wDNSf8AzET/AMs//wDJOv8AyDX/AMYw/wDFK/8AxCb/AMIh/wDB + HP8Avxf/AL4S/wC9Df8AvQ2rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvQ3bAL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + DP8AvQy/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAANNefgDSWv8A0VX/AM9Q/wDOS/8AzUb/AMtB/wDKPP8AyDf/AMcy/wDG + Lf8AxCj/AMMj/wDBHv8AwBn/AL8U/wC9D/8AvQ3VAL0NTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAL0N2wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQz/ALwMvwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADSW34A0Vf/ANBS/wDPTf8AzUj/AMxD/wDK + Pv8AyTn/AMg0/wDGL/8AxSr/AMMl/wDCIP8AwRv/AL8W/wC+EskAvQ5QAL0NMgC9DakAvQ3RAL0NdgC9 + DRwAAAAAAAAAAAAAAAAAAAAAAAAAAAC9DdsAvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQz/ALwM/wC8C78AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0lh+ANFU/wDP + UP8Azkr/AMxG/wDLQP8Ayjv/AMg2/wDHMf8AxSz/AMQn/wDDIv8AwR3/AMAZuwC/FUIAvQ0+AL0NtwC9 + Df8AvQ3/AL0N/wC9Df8AvQ39AL0NvQC9DWIAvQ0OAAAAAAAAAAAAvQ3bAL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQz/AL0M/wC8C/8AvAu/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAANFVfgDQUv8Azk3/AM1I/wDMQ/8Ayj7/AMk5/wDHNP8Axi//AMUq/wDDJf0AwiCtAMEcNgC/ + FEwAvhDFAL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N9wC9DakAvQ1OAL0NJgC9 + DXwAvQ3XAL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0M/wC8 + DP8AvAv/ALwLvwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQU34Az0//AM5K/wDMRf8Ay0D/AMk7/wDINv8AxzH/AMUs+QDE + J58AwyMsAMEbWAC/F9EAvhP/AL0O/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9DesAvQ2VAL0NOAC9DTQAvQ2RAL0N6QC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0M/wC9DP8AvAv/ALwL/wC8C78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAz1B+AM5M/wDNR/8Ay0L/AMo9/wDJ + OP8AxzP1AMYvkwDFKiYAwyNmAMIf3QDAGv8AvxX/AL0Q/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3bAL0NgQC9DSgAvQ1IAL0NpQC9 + DfUAvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9DP8AvAz/ALwL/wC8C/8AvAq/AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM5NfgDN + Sf8AzET/AMs//wDJOu8AyDaFAMcxIgDFKnQAxCbnAMIh/wDBHP8Avxf/AL4S/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0NyQC9DWwAvQ0gAL0NXAC9DbkAvQ37AL0N/wC9DP8AvAz/ALwL/wC8C/8AvAr/ALwKvwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAADOSn4AzUb/AMtC5wDKPXYAyDciAMcxgwDGLe8AxCj/AMMj/wDBHv8AwBn/AL8U/wC9 + D/8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N+wC9DbMAvQ1YAL0NIgC9DXAAvQzNALwM/wC8 + C/8AvAv/ALwK/wC7Cr8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzUhgAMxFaADKPSYAyTmRAMg09QDGMP8AxSv/AMMm/wDC + IP8AwRz/AL8W/wC+Ev8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + DfEAvQyfALwMRAC8CywAvAuHALwK4QC8Cv8Auwm/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADLQEQAyjztAMg3/wDH + Mv8Axi3/AMQo/wDDI/8AwR7/AMAZ/wC/FP8AvQ//AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0M/wC8DP8AvAvlALwLiwC8CjAAuwo+ALsJagAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAMk5CgDINFoAxi+3AMUq+wDDJf8AwiD/AMEb/wC/Fv8AvhH/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0M/wC8DP8AvAv/ALwL/wC8Cv8AvAr/ALsJxQC7 + CRoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEJxYAwyJuAMEdywDAGP8AvhP/AL0O/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0M/wC9DP8AvAv/ALwL/wC8 + Cv8AvArpALsKeAC7CRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAvxUoAL4RgwC9Dd8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + DP8AvAz/ALwL/wC8C98AvApqALwKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvQ0AAL0NPAC9DZcAvQ3tAL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9DP8AvAz/ALwL1QC8C1wAvAsEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL0NBgC9 + DVAAvQ2rAL0N9wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQzJALwMUAC8DAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9DRAAvQ1kAL0NwQC9Df0AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9 + Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9DbsAvQ1CAL0MAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvQ0eAL0NeAC9 + DdUAvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ3/AL0N/wC9Df8AvQ39AL0NrQC9DTQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAL0NMAC9DY0AvQ3lAL0N/wC9Df8AvQ3/AL0N/wC9DfkAvQ2fAL0NKAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL0NAgC9DUYAvQ2hAL0N6QC9 + DZEAvQ0eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/////////////////////////////////////////////////////////+//////////D/// + //////wP////////8A/////////AD////////wAP///////8AA////////AAD///////wAAP///////A + AA///////8AAD///8f//wAAP///B///AAA///wH//8AAD//8Af//wAAP//AB///AAA//gAH//8AAD/4A + Af//wAAP+AAB///AAA/wAAH//8AAD/AAAf//wAAP8AAB///AAA/wAAH//8AAD/AAAf//wAAP8AAB///A + AA/wAAH//8AAD/AAAf//wAAP8AAB///AAA/wAAH//8AAD/AAAf//wAAP8AAB///AAA/wAAH//8AAD/AA + Af//wAAP8AAB///AAA/wAAH//8AAD/AAAf//wAAf8AAB///AAGfwAAH//8ABgPAAAf//wAYAHAAB///A + GAADAAH//8BgAABgAf//wYAAABwB///MAAAAA4H///AAAAAAYf//4AAAAAAP///4AAAAAAP///8AAAAA + D////8AAAAA/////+AAAAP//////AAAD///////gAA////////wAP////////wD/////////4/////// + //////////////////////////////////////////////////8= + + + + 3, 4, 3, 4 + + + CenterScreen + + + neo-gui + + + 钱包WToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 创建钱包数据库NToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 打开钱包数据库OToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator1 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 修改密码CToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator2 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 退出XToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 交易TToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 转账TToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator5 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 签名SToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 高级AToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + deployContractToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + invokeContractToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator11 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 选举EToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + signDataToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator9 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + optionsToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 帮助HToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 查看帮助VToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 官网WToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator3 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 开发人员工具TToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + consoleToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator4 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 关于AntSharesToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader1 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader4 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader11 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 创建新地址NToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 导入私钥IToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + importWIFToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator10 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + importWatchOnlyAddressToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 创建智能合约SToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 多方签名MToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator12 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 自定义CToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator6 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 查看私钥VToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + viewContractToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + voteToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 复制到剪贴板CToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 删除DToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripStatusLabel1 + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbl_height + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripStatusLabel4 + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbl_count_node + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripProgressBar1 + + + System.Windows.Forms.ToolStripProgressBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripStatusLabel2 + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripStatusLabel3 + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + timer1 + + + System.Windows.Forms.Timer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader2 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader6 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader3 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader5 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader7 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader8 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader9 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader10 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripMenuItem1 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + MainForm + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/src/Neo.GUI/GUI/MainForm.zh-Hans.resx b/src/Neo.GUI/GUI/MainForm.zh-Hans.resx new file mode 100644 index 0000000000..086c4e916a --- /dev/null +++ b/src/Neo.GUI/GUI/MainForm.zh-Hans.resx @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 187, 22 + + + 创建钱包数据库(&N)... + + + 187, 22 + + + 打开钱包数据库(&O)... + + + 184, 6 + + + 187, 22 + + + 修改密码(&C)... + + + 184, 6 + + + 187, 22 + + + 退出(&X) + + + 64, 21 + + + 钱包(&W) + + + 124, 22 + + + 转账(&T)... + + + 121, 6 + + + 124, 22 + + + 签名(&S)... + + + 59, 21 + + + 交易(&T) + + + 150, 22 + + + 部署合约(&D)... + + + 150, 22 + + + 调用合约(&V)... + + + 147, 6 + + + 150, 22 + + + 选举(&E)... + + + 150, 22 + + + 消息签名(&S)... + + + 147, 6 + + + 150, 22 + + + 选项(&O)... + + + 60, 21 + + + 高级(&A) + + + 191, 22 + + + 查看帮助(&H) + + + 191, 22 + + + 官网(&W) + + + 188, 6 + + + 191, 22 + + + 开发人员工具(&T) + + + 191, 22 + + + 控制台(&C) + + + 188, 6 + + + 191, 22 + + + 关于&NEO + + + 61, 21 + + + 帮助(&H) + + + 地址 + + + 164, 22 + + + 创建新地址(&N) + + + 173, 22 + + + 导入&WIF... + + + 170, 6 + + + 173, 22 + + + 导入监视地址(&A)... + + + 164, 22 + + + 导入(&I) + + + 153, 22 + + + 多方签名(&M)... + + + 150, 6 + + + 153, 22 + + + 自定义(&C)... + + + 164, 22 + + + 创建合约地址(&A) + + + 161, 6 + + + 164, 22 + + + 查看私钥(&P) + + + 164, 22 + + + 查看合约(&O) + + + 164, 22 + + + 投票(&V)... + + + 164, 22 + + + 复制到剪贴板(&C) + + + 164, 22 + + + 删除(&D)... + + + 165, 186 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAAAzmoIflh4botKbmiLcF/P///yhTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25t + ZW50AQAAAAd2YWx1ZV9fAAgCAAAAAAAAAAoGBQAAABVzdGFuZGFyZENvbnRyYWN0R3JvdXAL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAAAzlkIjnuqblnLDlnYAF/P///yhTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25t + ZW50AQAAAAd2YWx1ZV9fAAgCAAAAAAAAAAoGBQAAABhub25zdGFuZGFyZENvbnRyYWN0R3JvdXAL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACJTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5MaXN0Vmlld0dyb3VwBAAAAAZIZWFkZXIPSGVhZGVyQWxpZ25tZW50A1Rh + ZwROYW1lAQQCAShTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25tZW50AgAAAAIAAAAG + AwAAAAznm5Hop4blnLDlnYAF/P///yhTeXN0ZW0uV2luZG93cy5Gb3Jtcy5Ib3Jpem9udGFsQWxpZ25t + ZW50AQAAAAd2YWx1ZV9fAAgCAAAAAAAAAAoGBQAAAA53YXRjaE9ubHlHcm91cAs= + + + + 35, 17 + + + 高度: + + + 47, 17 + + + 连接数: + + + 95, 17 + + + 等待下一个区块: + + + 68, 17 + + + 发现新版本 + + + 账户 + + + 资产 + + + 类型 + + + 余额 + + + 发行者 + + + 资产 + + + 时间 + + + 交易编号 + + + 确认 + + + 交易类型 + + + 137, 22 + + + 复制交易ID + + + 138, 26 + + + 交易记录 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/OpenWalletDialog.cs b/src/Neo.GUI/GUI/OpenWalletDialog.cs new file mode 100644 index 0000000000..aaeaa0bfd1 --- /dev/null +++ b/src/Neo.GUI/GUI/OpenWalletDialog.cs @@ -0,0 +1,65 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class OpenWalletDialog : Form + { + public OpenWalletDialog() + { + InitializeComponent(); + } + + public string Password + { + get + { + return textBox2.Text; + } + set + { + textBox2.Text = value; + } + } + + public string WalletPath + { + get + { + return textBox1.Text; + } + set + { + textBox1.Text = value; + } + } + + private void textBox_TextChanged(object sender, EventArgs e) + { + if (textBox1.TextLength == 0 || textBox2.TextLength == 0) + { + button2.Enabled = false; + return; + } + button2.Enabled = true; + } + + private void button1_Click(object sender, EventArgs e) + { + if (openFileDialog1.ShowDialog() == DialogResult.OK) + { + textBox1.Text = openFileDialog1.FileName; + } + } + } +} diff --git a/src/Neo.GUI/GUI/OpenWalletDialog.designer.cs b/src/Neo.GUI/GUI/OpenWalletDialog.designer.cs new file mode 100644 index 0000000000..9db0ac01b8 --- /dev/null +++ b/src/Neo.GUI/GUI/OpenWalletDialog.designer.cs @@ -0,0 +1,125 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class OpenWalletDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(OpenWalletDialog)); + this.button2 = new System.Windows.Forms.Button(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.SuspendLayout(); + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.UseSystemPasswordChar = true; + this.textBox2.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // openFileDialog1 + // + this.openFileDialog1.DefaultExt = "json"; + resources.ApplyResources(this.openFileDialog1, "openFileDialog1"); + // + // OpenWalletDialog + // + this.AcceptButton = this.button2; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.button2); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "OpenWalletDialog"; + this.ShowInTaskbar = false; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + } +} diff --git a/src/Neo.GUI/GUI/OpenWalletDialog.es-ES.resx b/src/Neo.GUI/GUI/OpenWalletDialog.es-ES.resx new file mode 100644 index 0000000000..bf023cf9a0 --- /dev/null +++ b/src/Neo.GUI/GUI/OpenWalletDialog.es-ES.resx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 142, 41 + + + 65, 44 + + + 71, 16 + + + Contraseña: + + + Buscar... + + + 142, 12 + + + 204, 23 + + + 124, 16 + + + Fichero de nomedero: + + + Abrir monedero + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/OpenWalletDialog.resx b/src/Neo.GUI/GUI/OpenWalletDialog.resx new file mode 100644 index 0000000000..8b5a8e2e01 --- /dev/null +++ b/src/Neo.GUI/GUI/OpenWalletDialog.resx @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 8 + + + 15 + + + Password: + + + 5 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 7, 16 + + + + Top, Left, Right + + + True + + + OK + + + 16, 44 + + + 352, 68 + + + $this + + + Wallet File: + + + button2 + + + OpenWalletDialog + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Top, Right + + + $this + + + $this + + + 12, 15 + + + textBox1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 263, 23 + + + 439, 103 + + + System.Windows.Forms.OpenFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bottom, Right + + + CenterScreen + + + 75, 23 + + + openFileDialog1 + + + textBox2 + + + label1 + + + label2 + + + 75, 23 + + + 9 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Browse + + + False + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + NEP-6 Wallet|*.json|SQLite Wallet|*.db3 + + + 83, 12 + + + 61, 16 + + + 3 + + + 150, 23 + + + True + + + 65, 16 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + 11 + + + 83, 41 + + + 4 + + + 10 + + + button1 + + + 0 + + + $this + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 352, 12 + + + 微软雅黑, 9pt + + + Open Wallet + + + 2 + + + 12 + + + $this + + + True + + + 17, 17 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/OpenWalletDialog.zh-Hans.resx b/src/Neo.GUI/GUI/OpenWalletDialog.zh-Hans.resx new file mode 100644 index 0000000000..5c4bf63eda --- /dev/null +++ b/src/Neo.GUI/GUI/OpenWalletDialog.zh-Hans.resx @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 确定 + + + 101, 41 + + + 60, 44 + + + 35, 16 + + + 密码: + + + 浏览 + + + 101, 12 + + + 245, 23 + + + 83, 16 + + + 钱包文件位置: + + + NEP-6钱包文件|*.json|SQLite钱包文件|*.db3 + + + 打开钱包 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ParametersEditor.Designer.cs b/src/Neo.GUI/GUI/ParametersEditor.Designer.cs new file mode 100644 index 0000000000..5d6d92d268 --- /dev/null +++ b/src/Neo.GUI/GUI/ParametersEditor.Designer.cs @@ -0,0 +1,200 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ParametersEditor + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ParametersEditor)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.panel1 = new System.Windows.Forms.Panel(); + this.button4 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.groupBox1.SuspendLayout(); + this.panel1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.listView1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // listView1 + // + resources.ApplyResources(this.listView1, "listView1"); + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView1.MultiSelect = false; + this.listView1.Name = "listView1"; + this.listView1.ShowGroups = false; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged); + // + // columnHeader1 + // + resources.ApplyResources(this.columnHeader1, "columnHeader1"); + // + // columnHeader2 + // + resources.ApplyResources(this.columnHeader2, "columnHeader2"); + // + // columnHeader3 + // + resources.ApplyResources(this.columnHeader3, "columnHeader3"); + // + // panel1 + // + resources.ApplyResources(this.panel1, "panel1"); + this.panel1.Controls.Add(this.button4); + this.panel1.Controls.Add(this.button3); + this.panel1.Name = "panel1"; + // + // button4 + // + resources.ApplyResources(this.button4, "button4"); + this.button4.Name = "button4"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // groupBox2 + // + resources.ApplyResources(this.groupBox2, "groupBox2"); + this.groupBox2.Controls.Add(this.textBox1); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.TabStop = false; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + // + // groupBox3 + // + resources.ApplyResources(this.groupBox3, "groupBox3"); + this.groupBox3.Controls.Add(this.panel1); + this.groupBox3.Controls.Add(this.button2); + this.groupBox3.Controls.Add(this.button1); + this.groupBox3.Controls.Add(this.textBox2); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.TabStop = false; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged); + // + // ParametersEditor + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ParametersEditor"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Panel panel1; + } +} diff --git a/src/Neo.GUI/GUI/ParametersEditor.cs b/src/Neo.GUI/GUI/ParametersEditor.cs new file mode 100644 index 0000000000..6a42f8d934 --- /dev/null +++ b/src/Neo.GUI/GUI/ParametersEditor.cs @@ -0,0 +1,197 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Cryptography.ECC; +using Neo.SmartContract; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Numerics; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class ParametersEditor : Form + { + private readonly IList parameters; + + public ParametersEditor(IList parameters) + { + InitializeComponent(); + this.parameters = parameters; + listView1.Items.AddRange(parameters.Select((p, i) => new ListViewItem(new[] + { + new ListViewItem.ListViewSubItem + { + Name = "index", + Text = $"[{i}]" + }, + new ListViewItem.ListViewSubItem + { + Name = "type", + Text = p.Type.ToString() + }, + new ListViewItem.ListViewSubItem + { + Name = "value", + Text = p.ToString() + } + }, -1) + { + Tag = p + }).ToArray()); + panel1.Enabled = !parameters.IsReadOnly; + } + + private void listView1_SelectedIndexChanged(object sender, EventArgs e) + { + if (listView1.SelectedIndices.Count > 0) + { + textBox1.Text = listView1.SelectedItems[0].SubItems["value"].Text; + textBox2.Enabled = ((ContractParameter)listView1.SelectedItems[0].Tag).Type != ContractParameterType.Array; + button2.Enabled = !textBox2.Enabled; + button4.Enabled = true; + } + else + { + textBox1.Clear(); + textBox2.Enabled = true; + button2.Enabled = false; + button4.Enabled = false; + } + textBox2.Clear(); + } + + private void textBox2_TextChanged(object sender, EventArgs e) + { + button1.Enabled = listView1.SelectedIndices.Count > 0 && textBox2.TextLength > 0; + button3.Enabled = textBox2.TextLength > 0; + } + + private void button1_Click(object sender, EventArgs e) + { + if (listView1.SelectedIndices.Count == 0) return; + ContractParameter parameter = (ContractParameter)listView1.SelectedItems[0].Tag; + try + { + parameter.SetValue(textBox2.Text); + listView1.SelectedItems[0].SubItems["value"].Text = parameter.ToString(); + textBox1.Text = listView1.SelectedItems[0].SubItems["value"].Text; + textBox2.Clear(); + } + catch (Exception err) + { + MessageBox.Show(err.Message); + } + } + + private void button2_Click(object sender, EventArgs e) + { + if (listView1.SelectedIndices.Count == 0) return; + ContractParameter parameter = (ContractParameter)listView1.SelectedItems[0].Tag; + using ParametersEditor dialog = new ParametersEditor((IList)parameter.Value); + dialog.ShowDialog(); + listView1.SelectedItems[0].SubItems["value"].Text = parameter.ToString(); + textBox1.Text = listView1.SelectedItems[0].SubItems["value"].Text; + } + + private void button3_Click(object sender, EventArgs e) + { + string s = textBox2.Text; + ContractParameter parameter = new ContractParameter(); + if (string.Equals(s, "true", StringComparison.OrdinalIgnoreCase)) + { + parameter.Type = ContractParameterType.Boolean; + parameter.Value = true; + } + else if (string.Equals(s, "false", StringComparison.OrdinalIgnoreCase)) + { + parameter.Type = ContractParameterType.Boolean; + parameter.Value = false; + } + else if (long.TryParse(s, out long num)) + { + parameter.Type = ContractParameterType.Integer; + parameter.Value = num; + } + else if (s.StartsWith("0x")) + { + if (UInt160.TryParse(s, out UInt160 i160)) + { + parameter.Type = ContractParameterType.Hash160; + parameter.Value = i160; + } + else if (UInt256.TryParse(s, out UInt256 i256)) + { + parameter.Type = ContractParameterType.Hash256; + parameter.Value = i256; + } + else if (BigInteger.TryParse(s.Substring(2), NumberStyles.AllowHexSpecifier, null, out BigInteger bi)) + { + parameter.Type = ContractParameterType.Integer; + parameter.Value = bi; + } + else + { + parameter.Type = ContractParameterType.String; + parameter.Value = s; + } + } + else if (ECPoint.TryParse(s, ECCurve.Secp256r1, out ECPoint point)) + { + parameter.Type = ContractParameterType.PublicKey; + parameter.Value = point; + } + else + { + try + { + parameter.Value = s.HexToBytes(); + parameter.Type = ContractParameterType.ByteArray; + } + catch (FormatException) + { + parameter.Type = ContractParameterType.String; + parameter.Value = s; + } + } + parameters.Add(parameter); + listView1.Items.Add(new ListViewItem(new[] + { + new ListViewItem.ListViewSubItem + { + Name = "index", + Text = $"[{listView1.Items.Count}]" + }, + new ListViewItem.ListViewSubItem + { + Name = "type", + Text = parameter.Type.ToString() + }, + new ListViewItem.ListViewSubItem + { + Name = "value", + Text = parameter.ToString() + } + }, -1) + { + Tag = parameter + }); + } + + private void button4_Click(object sender, EventArgs e) + { + int index = listView1.SelectedIndices[0]; + parameters.RemoveAt(index); + listView1.Items.RemoveAt(index); + } + } +} diff --git a/src/Neo.GUI/GUI/ParametersEditor.es-ES.resx b/src/Neo.GUI/GUI/ParametersEditor.es-ES.resx new file mode 100644 index 0000000000..21e7fad664 --- /dev/null +++ b/src/Neo.GUI/GUI/ParametersEditor.es-ES.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Tipo + + + Valor + + + Lista de parámetros + + + Valor anterior + + + Actualizar + + + Nuevo valor + + + Definir parámetros + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ParametersEditor.resx b/src/Neo.GUI/GUI/ParametersEditor.resx new file mode 100644 index 0000000000..a2f2d31c9e --- /dev/null +++ b/src/Neo.GUI/GUI/ParametersEditor.resx @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + False + + + + + + + 661, 485 + + + ParametersEditor + + + False + + + False + + + + + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + panel1 + + + Value + + + 2 + + + 0 + + + Update + + + 0 + + + + Top, Bottom, Left, Right + + + 1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 233, 126 + + + 3 + + + groupBox3 + + + True + + + 3, 22 + + + 23, 23 + + + 7, 17 + + + 1 + + + 74, 23 + + + 3, 4, 3, 4 + + + panel1 + + + Bottom, Right + + + 0 + + + Type + + + CenterScreen + + + Top, Bottom, Left, Right + + + False + + + textBox1 + + + Parameter List + + + 75, 23 + + + groupBox3 + + + 75, 23 + + + 380, 436 + + + 233, 250 + + + 0 + + + 3, 19 + + + 410, 290 + + + 0 + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 29, 0 + + + 1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 80, 154 + + + 161, 154 + + + 3 + + + Edit Array + + + Bottom, Left, Right + + + Old Value + + + 410, 12 + + + groupBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 微软雅黑, 9pt + + + groupBox3 + + + 2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + button1 + + + listView1 + + + columnHeader3 + + + - + + + 12, 12 + + + columnHeader1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 392, 461 + + + 0 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Fill + + + 0 + + + 3, 154 + + + True + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Top, Bottom, Left, Right + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bottom, Left, Right + + + $this + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + NoControl + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + 0, 0 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 239, 272 + + + 200 + + + columnHeader2 + + + 50 + + + groupBox2 + + + button2 + + + groupBox3 + + + 2 + + + button4 + + + 1 + + + 23, 23 + + + 1 + + + 2 + + + Bottom, Right + + + Set Parameters + + + groupBox1 + + + groupBox1 + + + 0, 0, 0, 0 + + + New Value + + + 0 + + + 100 + + + $this + + + textBox2 + + + 1 + + + $this + + + 2 + + + Top, Bottom, Left + + + button3 + + + 6, 19 + + + 239, 183 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ParametersEditor.zh-Hans.resx b/src/Neo.GUI/GUI/ParametersEditor.zh-Hans.resx new file mode 100644 index 0000000000..8db893dbac --- /dev/null +++ b/src/Neo.GUI/GUI/ParametersEditor.zh-Hans.resx @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 参数列表 + + + 类型 + + + + + + 当前值 + + + 新值 + + + 编辑数组 + + + 更新 + + + 设置参数 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/PayToDialog.Designer.cs b/src/Neo.GUI/GUI/PayToDialog.Designer.cs new file mode 100644 index 0000000000..100d32f50d --- /dev/null +++ b/src/Neo.GUI/GUI/PayToDialog.Designer.cs @@ -0,0 +1,142 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class PayToDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PayToDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // comboBox1 + // + resources.ApplyResources(this.comboBox1, "comboBox1"); + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Name = "comboBox1"; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.Name = "label4"; + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.Name = "textBox3"; + this.textBox3.ReadOnly = true; + // + // PayToDialog + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label4); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.label3); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "PayToDialog"; + this.ShowInTaskbar = false; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox textBox3; + } +} diff --git a/src/Neo.GUI/GUI/PayToDialog.cs b/src/Neo.GUI/GUI/PayToDialog.cs new file mode 100644 index 0000000000..b4dc3abdbd --- /dev/null +++ b/src/Neo.GUI/GUI/PayToDialog.cs @@ -0,0 +1,105 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Wallets; +using System; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + internal partial class PayToDialog : Form + { + public PayToDialog(AssetDescriptor asset = null, UInt160 scriptHash = null) + { + InitializeComponent(); + if (asset is null) + { + foreach (UInt160 assetId in NEP5Watched) + { + try + { + comboBox1.Items.Add(new AssetDescriptor(Service.NeoSystem.StoreView, Service.NeoSystem.Settings, assetId)); + } + catch (ArgumentException) + { + continue; + } + } + } + else + { + comboBox1.Items.Add(asset); + comboBox1.SelectedIndex = 0; + comboBox1.Enabled = false; + } + if (scriptHash != null) + { + textBox1.Text = scriptHash.ToAddress(Service.NeoSystem.Settings.AddressVersion); + textBox1.ReadOnly = true; + } + } + + public TxOutListBoxItem GetOutput() + { + AssetDescriptor asset = (AssetDescriptor)comboBox1.SelectedItem; + return new TxOutListBoxItem + { + AssetName = asset.AssetName, + AssetId = asset.AssetId, + Value = BigDecimal.Parse(textBox2.Text, asset.Decimals), + ScriptHash = textBox1.Text.ToScriptHash(Service.NeoSystem.Settings.AddressVersion) + }; + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBox1.SelectedItem is AssetDescriptor asset) + { + textBox3.Text = Service.CurrentWallet.GetAvailable(Service.NeoSystem.StoreView, asset.AssetId).ToString(); + } + else + { + textBox3.Text = ""; + } + textBox_TextChanged(this, EventArgs.Empty); + } + + private void textBox_TextChanged(object sender, EventArgs e) + { + if (comboBox1.SelectedIndex < 0 || textBox1.TextLength == 0 || textBox2.TextLength == 0) + { + button1.Enabled = false; + return; + } + try + { + textBox1.Text.ToScriptHash(Service.NeoSystem.Settings.AddressVersion); + } + catch (FormatException) + { + button1.Enabled = false; + return; + } + AssetDescriptor asset = (AssetDescriptor)comboBox1.SelectedItem; + if (!BigDecimal.TryParse(textBox2.Text, asset.Decimals, out BigDecimal amount)) + { + button1.Enabled = false; + return; + } + if (amount.Sign <= 0) + { + button1.Enabled = false; + return; + } + button1.Enabled = true; + } + } +} diff --git a/src/Neo.GUI/GUI/PayToDialog.es-ES.resx b/src/Neo.GUI/GUI/PayToDialog.es-ES.resx new file mode 100644 index 0000000000..525ae78e9a --- /dev/null +++ b/src/Neo.GUI/GUI/PayToDialog.es-ES.resx @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 12, 88 + + + 56, 17 + + + Pagar a: + + + 28, 122 + + + 40, 17 + + + Total: + + + Aceptar + + + 22, 17 + + + 46, 17 + + + Activo: + + + 24, 54 + + + 44, 17 + + + Saldo: + + + Pago + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/PayToDialog.resx b/src/Neo.GUI/GUI/PayToDialog.resx new file mode 100644 index 0000000000..2c575df5ab --- /dev/null +++ b/src/Neo.GUI/GUI/PayToDialog.resx @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 21, 88 + + + 47, 17 + + + 4 + + + Pay to: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 8 + + + + Top, Left, Right + + + 74, 85 + + + 468, 23 + + + 5 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + True + + + 12, 122 + + + 56, 17 + + + 6 + + + Amount: + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + Top, Left, Right + + + 74, 119 + + + 468, 23 + + + 7 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Top, Right + + + False + + + 467, 157 + + + 75, 23 + + + 8 + + + OK + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + True + + + 26, 17 + + + 42, 17 + + + 0 + + + Asset: + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Top, Left, Right + + + 74, 14 + + + 468, 25 + + + 1 + + + comboBox1 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + True + + + 12, 54 + + + 56, 17 + + + 2 + + + Balance: + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Top, Left, Right + + + 74, 51 + + + 468, 23 + + + 3 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 554, 192 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Payment + + + PayToDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/PayToDialog.zh-Hans.resx b/src/Neo.GUI/GUI/PayToDialog.zh-Hans.resx new file mode 100644 index 0000000000..9f55c74270 --- /dev/null +++ b/src/Neo.GUI/GUI/PayToDialog.zh-Hans.resx @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 12, 75 + + + 59, 17 + + + 对方账户: + + + 77, 72 + + + 308, 23 + + + 36, 104 + + + 35, 17 + + + 数额: + + + 77, 101 + + + 227, 23 + + + 310, 101 + + + 确定 + + + 36, 15 + + + 35, 17 + + + 资产: + + + 77, 12 + + + 308, 25 + + + 36, 46 + + + 35, 17 + + + 余额: + + + 77, 43 + + + 308, 23 + + + 397, 134 + + + 支付 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/QueueReader.cs b/src/Neo.GUI/GUI/QueueReader.cs new file mode 100644 index 0000000000..12f1260f3f --- /dev/null +++ b/src/Neo.GUI/GUI/QueueReader.cs @@ -0,0 +1,48 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System.Collections.Generic; +using System.IO; +using System.Threading; + +namespace Neo.GUI +{ + internal class QueueReader : TextReader + { + private readonly Queue queue = new Queue(); + private string current; + private int index; + + public void Enqueue(string str) + { + queue.Enqueue(str); + } + + public override int Peek() + { + while (string.IsNullOrEmpty(current)) + { + while (!queue.TryDequeue(out current)) + Thread.Sleep(100); + index = 0; + } + return current[index]; + } + + public override int Read() + { + int c = Peek(); + if (c != -1) + if (++index >= current.Length) + current = null; + return c; + } + } +} diff --git a/src/Neo.GUI/GUI/SigningDialog.Designer.cs b/src/Neo.GUI/GUI/SigningDialog.Designer.cs new file mode 100644 index 0000000000..8c03f84901 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningDialog.Designer.cs @@ -0,0 +1,172 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class SigningDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SigningDialog)); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.cmbFormat = new System.Windows.Forms.ComboBox(); + this.cmbAddress = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + // + // groupBox2 + // + resources.ApplyResources(this.groupBox2, "groupBox2"); + this.groupBox2.Controls.Add(this.textBox2); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.TabStop = false; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.ReadOnly = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + // + // cmbFormat + // + resources.ApplyResources(this.cmbFormat, "cmbFormat"); + this.cmbFormat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbFormat.FormattingEnabled = true; + this.cmbFormat.Items.AddRange(new object[] { + resources.GetString("cmbFormat.Items"), + resources.GetString("cmbFormat.Items1")}); + this.cmbFormat.Name = "cmbFormat"; + // + // cmbAddress + // + resources.ApplyResources(this.cmbAddress, "cmbAddress"); + this.cmbAddress.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbAddress.FormattingEnabled = true; + this.cmbAddress.Name = "cmbAddress"; + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // SigningDialog + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button3; + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.cmbAddress); + this.Controls.Add(this.cmbFormat); + this.Controls.Add(this.button3); + this.Controls.Add(this.button2); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.button1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SigningDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.ComboBox cmbFormat; + private System.Windows.Forms.ComboBox cmbAddress; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + } +} diff --git a/src/Neo.GUI/GUI/SigningDialog.cs b/src/Neo.GUI/GUI/SigningDialog.cs new file mode 100644 index 0000000000..f94d92c438 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningDialog.cs @@ -0,0 +1,106 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Cryptography; +using Neo.Properties; +using Neo.Wallets; +using System; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + internal partial class SigningDialog : Form + { + private class WalletEntry + { + public WalletAccount Account; + + public override string ToString() + { + if (!string.IsNullOrEmpty(Account.Label)) + { + return $"[{Account.Label}] " + Account.Address; + } + return Account.Address; + } + } + + + public SigningDialog() + { + InitializeComponent(); + + cmbFormat.SelectedIndex = 0; + cmbAddress.Items.AddRange(Service.CurrentWallet.GetAccounts() + .Where(u => u.HasKey) + .Select(u => new WalletEntry() { Account = u }) + .ToArray()); + + if (cmbAddress.Items.Count > 0) + { + cmbAddress.SelectedIndex = 0; + } + else + { + textBox2.Enabled = false; + button1.Enabled = false; + } + } + + private void button1_Click(object sender, EventArgs e) + { + if (textBox1.Text == "") + { + MessageBox.Show(Strings.SigningFailedNoDataMessage); + return; + } + + byte[] raw, signedData; + try + { + switch (cmbFormat.SelectedIndex) + { + case 0: raw = Encoding.UTF8.GetBytes(textBox1.Text); break; + case 1: raw = textBox1.Text.HexToBytes(); break; + default: return; + } + } + catch (Exception err) + { + MessageBox.Show(err.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + var account = (WalletEntry)cmbAddress.SelectedItem; + var keys = account.Account.GetKey(); + + try + { + signedData = Crypto.Sign(raw, keys.PrivateKey, keys.PublicKey.EncodePoint(false).Skip(1).ToArray()); + } + catch (Exception err) + { + MessageBox.Show(err.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + textBox2.Text = signedData?.ToHexString(); + } + + private void button2_Click(object sender, EventArgs e) + { + textBox2.SelectAll(); + textBox2.Copy(); + } + } +} diff --git a/src/Neo.GUI/GUI/SigningDialog.es-ES.resx b/src/Neo.GUI/GUI/SigningDialog.es-ES.resx new file mode 100644 index 0000000000..c440dbe4b2 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningDialog.es-ES.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Firma + + + Entrada + + + Salida + + + Copiar + + + Cancelar + + + Emitir + + + Firma + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/SigningDialog.resx b/src/Neo.GUI/GUI/SigningDialog.resx new file mode 100644 index 0000000000..d462a50fac --- /dev/null +++ b/src/Neo.GUI/GUI/SigningDialog.resx @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top + + + + 189, 269 + + + 75, 23 + + + + 2 + + + Sign + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 8 + + + Top, Left, Right + + + Fill + + + 3, 19 + + + True + + + Vertical + + + 424, 139 + + + 1 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + 12, 97 + + + 430, 161 + + + 3 + + + Input + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + Top, Bottom, Left, Right + + + Fill + + + 3, 19 + + + True + + + Vertical + + + 424, 117 + + + 1 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 0 + + + 12, 298 + + + 430, 139 + + + 4 + + + Output + + + groupBox2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + Bottom, Right + + + 286, 453 + + + 75, 23 + + + 5 + + + Copy + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Bottom, Right + + + 367, 453 + + + 75, 23 + + + 6 + + + Close + + + button3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Text + + + Hex + + + 367, 48 + + + 2, 3, 2, 3 + + + 72, 25 + + + 7 + + + cmbFormat + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 15, 48 + + + 2, 3, 2, 3 + + + 349, 25 + + + 8 + + + cmbAddress + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + True + + + 12, 21 + + + 2, 0, 2, 0 + + + 56, 17 + + + 9 + + + Address + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + True + + + NoControl + + + 364, 21 + + + 2, 0, 2, 0 + + + 49, 17 + + + 9 + + + Format + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 454, 488 + + + Microsoft YaHei UI, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Signature + + + SigningDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/SigningDialog.zh-Hans.resx b/src/Neo.GUI/GUI/SigningDialog.zh-Hans.resx new file mode 100644 index 0000000000..282612d0f8 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningDialog.zh-Hans.resx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 签名 + + + 输入 + + + 输出 + + + 复制 + + + 关闭 + + + + 32, 17 + + + 地址 + + + 32, 17 + + + 格式 + + + 签名 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/SigningTxDialog.Designer.cs b/src/Neo.GUI/GUI/SigningTxDialog.Designer.cs new file mode 100644 index 0000000000..45ecb20563 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningTxDialog.Designer.cs @@ -0,0 +1,142 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class SigningTxDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SigningTxDialog)); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + // + // groupBox2 + // + resources.ApplyResources(this.groupBox2, "groupBox2"); + this.groupBox2.Controls.Add(this.textBox2); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.TabStop = false; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.ReadOnly = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + // + // button4 + // + resources.ApplyResources(this.button4, "button4"); + this.button4.Name = "button4"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // SigningTxDialog + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button3; + this.Controls.Add(this.button4); + this.Controls.Add(this.button3); + this.Controls.Add(this.button2); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.button1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SigningTxDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button4; + } +} diff --git a/src/Neo.GUI/GUI/SigningTxDialog.cs b/src/Neo.GUI/GUI/SigningTxDialog.cs new file mode 100644 index 0000000000..718cf07b63 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningTxDialog.cs @@ -0,0 +1,66 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.Properties; +using Neo.SmartContract; +using System; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + internal partial class SigningTxDialog : Form + { + public SigningTxDialog() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + if (textBox1.Text == "") + { + MessageBox.Show(Strings.SigningFailedNoDataMessage); + return; + } + ContractParametersContext context = ContractParametersContext.Parse(textBox1.Text, Service.NeoSystem.StoreView); + if (!Service.CurrentWallet.Sign(context)) + { + MessageBox.Show(Strings.SigningFailedKeyNotFoundMessage); + return; + } + textBox2.Text = context.ToString(); + if (context.Completed) button4.Visible = true; + } + + private void button2_Click(object sender, EventArgs e) + { + textBox2.SelectAll(); + textBox2.Copy(); + } + + private void button4_Click(object sender, EventArgs e) + { + ContractParametersContext context = ContractParametersContext.Parse(textBox2.Text, Service.NeoSystem.StoreView); + if (!(context.Verifiable is Transaction tx)) + { + MessageBox.Show("Only support to broadcast transaction."); + return; + } + tx.Witnesses = context.GetWitnesses(); + Service.NeoSystem.Blockchain.Tell(tx); + InformationBox.Show(tx.Hash.ToString(), Strings.RelaySuccessText, Strings.RelaySuccessTitle); + button4.Visible = false; + } + } +} diff --git a/src/Neo.GUI/GUI/SigningTxDialog.es-ES.resx b/src/Neo.GUI/GUI/SigningTxDialog.es-ES.resx new file mode 100644 index 0000000000..c440dbe4b2 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningTxDialog.es-ES.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Firma + + + Entrada + + + Salida + + + Copiar + + + Cancelar + + + Emitir + + + Firma + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/SigningTxDialog.resx b/src/Neo.GUI/GUI/SigningTxDialog.resx new file mode 100644 index 0000000000..1f1af30e86 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningTxDialog.resx @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top + + + + 190, 191 + + + 75, 23 + + + + 2 + + + Sign + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Top, Left, Right + + + 12, 12 + + + 430, 173 + + + 3 + + + Input + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Fill + + + 3, 19 + + + True + + + Vertical + + + 424, 151 + + + 1 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + Top, Bottom, Left, Right + + + 12, 220 + + + 430, 227 + + + 4 + + + Output + + + groupBox2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Fill + + + 3, 19 + + + True + + + Vertical + + + 424, 205 + + + 1 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 0 + + + Bottom, Right + + + 286, 453 + + + 75, 23 + + + 5 + + + Copy + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Right + + + 367, 453 + + + 75, 23 + + + 6 + + + Close + + + button3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 12, 453 + + + 75, 23 + + + 7 + + + Broadcast + + + False + + + button4 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 454, 488 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Signature + + + SigningTxDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/src/Neo.GUI/GUI/SigningTxDialog.zh-Hans.resx b/src/Neo.GUI/GUI/SigningTxDialog.zh-Hans.resx new file mode 100644 index 0000000000..218f36f8e5 --- /dev/null +++ b/src/Neo.GUI/GUI/SigningTxDialog.zh-Hans.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 签名 + + + 输入 + + + 输出 + + + 复制 + + + 关闭 + + + 广播 + + + 签名 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/TextBoxWriter.cs b/src/Neo.GUI/GUI/TextBoxWriter.cs new file mode 100644 index 0000000000..c8be8a86ed --- /dev/null +++ b/src/Neo.GUI/GUI/TextBoxWriter.cs @@ -0,0 +1,39 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.IO; +using System.Text; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal class TextBoxWriter : TextWriter + { + private readonly TextBoxBase textBox; + + public override Encoding Encoding => Encoding.UTF8; + + public TextBoxWriter(TextBoxBase textBox) + { + this.textBox = textBox; + } + + public override void Write(char value) + { + textBox.Invoke(new Action(() => { textBox.Text += value; })); + } + + public override void Write(string value) + { + textBox.Invoke(new Action(textBox.AppendText), value); + } + } +} diff --git a/src/Neo.GUI/GUI/TransferDialog.Designer.cs b/src/Neo.GUI/GUI/TransferDialog.Designer.cs new file mode 100644 index 0000000000..2d19a83fce --- /dev/null +++ b/src/Neo.GUI/GUI/TransferDialog.Designer.cs @@ -0,0 +1,131 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class TransferDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TransferDialog)); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.txOutListBox1 = new Neo.GUI.TxOutListBox(); + this.button4 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.comboBoxFrom = new System.Windows.Forms.ComboBox(); + this.labelFrom = new System.Windows.Forms.Label(); + this.groupBox3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox3 + // + resources.ApplyResources(this.groupBox3, "groupBox3"); + this.groupBox3.Controls.Add(this.txOutListBox1); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.TabStop = false; + // + // txOutListBox1 + // + resources.ApplyResources(this.txOutListBox1, "txOutListBox1"); + this.txOutListBox1.Asset = null; + this.txOutListBox1.Name = "txOutListBox1"; + this.txOutListBox1.ReadOnly = false; + this.txOutListBox1.ScriptHash = null; + this.txOutListBox1.ItemsChanged += new System.EventHandler(this.txOutListBox1_ItemsChanged); + // + // button4 + // + resources.ApplyResources(this.button4, "button4"); + this.button4.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button4.Name = "button4"; + this.button4.UseVisualStyleBackColor = true; + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.comboBoxFrom); + this.groupBox1.Controls.Add(this.labelFrom); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // comboBoxFrom + // + resources.ApplyResources(this.comboBoxFrom, "comboBoxFrom"); + this.comboBoxFrom.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxFrom.FormattingEnabled = true; + this.comboBoxFrom.Name = "comboBoxFrom"; + // + // labelFrom + // + resources.ApplyResources(this.labelFrom, "labelFrom"); + this.labelFrom.Name = "labelFrom"; + // + // TransferDialog + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.button4); + this.Controls.Add(this.button3); + this.Controls.Add(this.groupBox3); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.Name = "TransferDialog"; + this.ShowInTaskbar = false; + this.groupBox3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Button button3; + private TxOutListBox txOutListBox1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ComboBox comboBoxFrom; + private System.Windows.Forms.Label labelFrom; + } +} diff --git a/src/Neo.GUI/GUI/TransferDialog.cs b/src/Neo.GUI/GUI/TransferDialog.cs new file mode 100644 index 0000000000..16f7764d68 --- /dev/null +++ b/src/Neo.GUI/GUI/TransferDialog.cs @@ -0,0 +1,41 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.Wallets; +using System; +using System.Linq; +using System.Windows.Forms; +using static Neo.Program; + +namespace Neo.GUI +{ + public partial class TransferDialog : Form + { + public TransferDialog() + { + InitializeComponent(); + comboBoxFrom.Items.AddRange(Service.CurrentWallet.GetAccounts().Where(p => !p.WatchOnly).Select(p => p.Address).ToArray()); + } + + public Transaction GetTransaction() + { + TransferOutput[] outputs = txOutListBox1.Items.ToArray(); + UInt160 from = comboBoxFrom.SelectedItem is null ? null : ((string)comboBoxFrom.SelectedItem).ToScriptHash(Service.NeoSystem.Settings.AddressVersion); + return Service.CurrentWallet.MakeTransaction(Service.NeoSystem.StoreView, outputs, from); + } + + private void txOutListBox1_ItemsChanged(object sender, EventArgs e) + { + button3.Enabled = txOutListBox1.ItemCount > 0; + } + } +} diff --git a/src/Neo.GUI/GUI/TransferDialog.es-ES.resx b/src/Neo.GUI/GUI/TransferDialog.es-ES.resx new file mode 100644 index 0000000000..662fc871c4 --- /dev/null +++ b/src/Neo.GUI/GUI/TransferDialog.es-ES.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Lista de destinatarios + + + Cancelar + + + Aceptar + + + Transferir + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/TransferDialog.resx b/src/Neo.GUI/GUI/TransferDialog.resx new file mode 100644 index 0000000000..f902756230 --- /dev/null +++ b/src/Neo.GUI/GUI/TransferDialog.resx @@ -0,0 +1,369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Left, Right + + + Top, Bottom, Left, Right + + + + Microsoft YaHei UI, 9pt + + + 6, 24 + + + 3, 4, 3, 4 + + + 551, 276 + + + + 0 + + + txOutListBox1 + + + Neo.UI.TxOutListBox, neo-gui, Version=2.10.7263.32482, Culture=neutral, PublicKeyToken=null + + + groupBox3 + + + 0 + + + 12, 13 + + + 3, 4, 3, 4 + + + 3, 4, 3, 4 + + + 563, 308 + + + 0 + + + Recipient List + + + groupBox3 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Bottom, Right + + + NoControl + + + 500, 401 + + + 3, 4, 3, 4 + + + 75, 24 + + + 2 + + + Cancel + + + button4 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Bottom, Right + + + False + + + NoControl + + + 419, 401 + + + 3, 4, 3, 4 + + + 75, 24 + + + 1 + + + OK + + + button3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Top, Left, Right + + + Top, Left, Right + + + 78, 22 + + + 418, 0 + + + 479, 25 + + + 2 + + + comboBoxFrom + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + True + + + NoControl + + + 31, 25 + + + 41, 17 + + + 4 + + + From: + + + MiddleLeft + + + labelFrom + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 1 + + + 12, 328 + + + 563, 60 + + + 4 + + + Advanced + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 587, 440 + + + Microsoft YaHei UI, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Transfer + + + TransferDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/TransferDialog.zh-Hans.resx b/src/Neo.GUI/GUI/TransferDialog.zh-Hans.resx new file mode 100644 index 0000000000..33ddb97439 --- /dev/null +++ b/src/Neo.GUI/GUI/TransferDialog.zh-Hans.resx @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 收款人列表 + + + 取消 + + + 确定 + + + 高级 + + + + 44, 17 + + + 转自: + + + 转账 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/TxOutListBox.Designer.cs b/src/Neo.GUI/GUI/TxOutListBox.Designer.cs new file mode 100644 index 0000000000..ad9f54d846 --- /dev/null +++ b/src/Neo.GUI/GUI/TxOutListBox.Designer.cs @@ -0,0 +1,109 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class TxOutListBox + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TxOutListBox)); + this.listBox1 = new System.Windows.Forms.ListBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // listBox1 + // + resources.ApplyResources(this.listBox1, "listBox1"); + this.listBox1.Name = "listBox1"; + this.listBox1.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended; + this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); + // + // panel1 + // + resources.ApplyResources(this.panel1, "panel1"); + this.panel1.Controls.Add(this.button1); + this.panel1.Controls.Add(this.button2); + this.panel1.Controls.Add(this.button3); + this.panel1.Name = "panel1"; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Image = global::Neo.Properties.Resources.add; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.Image = global::Neo.Properties.Resources.remove; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button3 + // + resources.ApplyResources(this.button3, "button3"); + this.button3.Image = global::Neo.Properties.Resources.add2; + this.button3.Name = "button3"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // TxOutListBox + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.panel1); + this.Controls.Add(this.listBox1); + this.Name = "TxOutListBox"; + this.panel1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ListBox listBox1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + } +} diff --git a/src/Neo.GUI/GUI/TxOutListBox.cs b/src/Neo.GUI/GUI/TxOutListBox.cs new file mode 100644 index 0000000000..8157c7c252 --- /dev/null +++ b/src/Neo.GUI/GUI/TxOutListBox.cs @@ -0,0 +1,102 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Windows.Forms; + +namespace Neo.GUI +{ + [DefaultEvent(nameof(ItemsChanged))] + internal partial class TxOutListBox : UserControl + { + public event EventHandler ItemsChanged; + + public AssetDescriptor Asset { get; set; } + + public int ItemCount => listBox1.Items.Count; + + public IEnumerable Items => listBox1.Items.OfType(); + + public bool ReadOnly + { + get + { + return !panel1.Enabled; + } + set + { + panel1.Enabled = !value; + } + } + + private UInt160 _script_hash = null; + public UInt160 ScriptHash + { + get + { + return _script_hash; + } + set + { + _script_hash = value; + button3.Enabled = value == null; + } + } + + public TxOutListBox() + { + InitializeComponent(); + } + + public void Clear() + { + if (listBox1.Items.Count > 0) + { + listBox1.Items.Clear(); + button2.Enabled = false; + ItemsChanged?.Invoke(this, EventArgs.Empty); + } + } + + private void listBox1_SelectedIndexChanged(object sender, EventArgs e) + { + button2.Enabled = listBox1.SelectedIndices.Count > 0; + } + + private void button1_Click(object sender, EventArgs e) + { + using PayToDialog dialog = new PayToDialog(asset: Asset, scriptHash: ScriptHash); + if (dialog.ShowDialog() != DialogResult.OK) return; + listBox1.Items.Add(dialog.GetOutput()); + ItemsChanged?.Invoke(this, EventArgs.Empty); + } + + private void button2_Click(object sender, EventArgs e) + { + while (listBox1.SelectedIndices.Count > 0) + { + listBox1.Items.RemoveAt(listBox1.SelectedIndices[0]); + } + ItemsChanged?.Invoke(this, EventArgs.Empty); + } + + private void button3_Click(object sender, EventArgs e) + { + using BulkPayDialog dialog = new BulkPayDialog(Asset); + if (dialog.ShowDialog() != DialogResult.OK) return; + listBox1.Items.AddRange(dialog.GetOutputs()); + ItemsChanged?.Invoke(this, EventArgs.Empty); + } + } +} diff --git a/src/Neo.GUI/GUI/TxOutListBox.resx b/src/Neo.GUI/GUI/TxOutListBox.resx new file mode 100644 index 0000000000..92bba21c58 --- /dev/null +++ b/src/Neo.GUI/GUI/TxOutListBox.resx @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Bottom, Left, Right + + + + True + + + False + + + 17 + + + + 0, 0 + + + 3, 4, 3, 4 + + + True + + + 349, 167 + + + 0 + + + listBox1 + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Bottom, Left, Right + + + Bottom, Left + + + NoControl + + + 0, 0 + + + 3, 4, 3, 4 + + + 27, 27 + + + 0 + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 0 + + + Bottom, Left + + + False + + + NoControl + + + 33, 0 + + + 3, 4, 3, 4 + + + 27, 27 + + + 1 + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 1 + + + Bottom, Left + + + NoControl + + + 66, 0 + + + 3, 4, 3, 4 + + + 27, 27 + + + 2 + + + button3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 2 + + + 0, 175 + + + 349, 27 + + + 1 + + + panel1 + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + 349, 202 + + + TxOutListBox + + + System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/TxOutListBoxItem.cs b/src/Neo.GUI/GUI/TxOutListBoxItem.cs new file mode 100644 index 0000000000..40356aa8ef --- /dev/null +++ b/src/Neo.GUI/GUI/TxOutListBoxItem.cs @@ -0,0 +1,24 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Wallets; + +namespace Neo.GUI +{ + internal class TxOutListBoxItem : TransferOutput + { + public string AssetName; + + public override string ToString() + { + return $"{ScriptHash.ToAddress(Program.Service.NeoSystem.Settings.AddressVersion)}\t{Value}\t{AssetName}"; + } + } +} diff --git a/src/Neo.GUI/GUI/UpdateDialog.Designer.cs b/src/Neo.GUI/GUI/UpdateDialog.Designer.cs new file mode 100644 index 0000000000..6af087d42b --- /dev/null +++ b/src/Neo.GUI/GUI/UpdateDialog.Designer.cs @@ -0,0 +1,149 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class UpdateDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpdateDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + // + // linkLabel1 + // + resources.ApplyResources(this.linkLabel1, "linkLabel1"); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.TabStop = true; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.ReadOnly = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // linkLabel2 + // + resources.ApplyResources(this.linkLabel2, "linkLabel2"); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.TabStop = true; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // progressBar1 + // + resources.ApplyResources(this.progressBar1, "progressBar1"); + this.progressBar1.Name = "progressBar1"; + // + // UpdateDialog + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button1; + this.Controls.Add(this.progressBar1); + this.Controls.Add(this.linkLabel2); + this.Controls.Add(this.button2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.button1); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UpdateDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.ProgressBar progressBar1; + } +} diff --git a/src/Neo.GUI/GUI/UpdateDialog.cs b/src/Neo.GUI/GUI/UpdateDialog.cs new file mode 100644 index 0000000000..c058c4dcb7 --- /dev/null +++ b/src/Neo.GUI/GUI/UpdateDialog.cs @@ -0,0 +1,76 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Properties; +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Windows.Forms; +using System.Xml.Linq; + +namespace Neo.GUI +{ + internal partial class UpdateDialog : Form + { + private readonly HttpClient http = new(); + private readonly string download_url; + private string download_path; + + public UpdateDialog(XDocument xdoc) + { + InitializeComponent(); + Version latest = Version.Parse(xdoc.Element("update").Attribute("latest").Value); + textBox1.Text = latest.ToString(); + XElement release = xdoc.Element("update").Elements("release").First(p => p.Attribute("version").Value == latest.ToString()); + textBox2.Text = release.Element("changes").Value.Replace("\n", Environment.NewLine); + download_url = release.Attribute("file").Value; + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + Process.Start("https://neo.org/"); + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + Process.Start(download_url); + } + + private async void button2_Click(object sender, EventArgs e) + { + button1.Enabled = false; + button2.Enabled = false; + download_path = "update.zip"; + using (Stream responseStream = await http.GetStreamAsync(download_url)) + using (FileStream fileStream = new(download_path, FileMode.Create, FileAccess.Write, FileShare.None)) + { + await responseStream.CopyToAsync(fileStream); + } + DirectoryInfo di = new DirectoryInfo("update"); + if (di.Exists) di.Delete(true); + di.Create(); + ZipFile.ExtractToDirectory(download_path, di.Name); + FileSystemInfo[] fs = di.GetFileSystemInfos(); + if (fs.Length == 1 && fs[0] is DirectoryInfo directory) + { + directory.MoveTo("update2"); + di.Delete(); + Directory.Move("update2", di.Name); + } + File.WriteAllBytes("update.bat", Resources.UpdateBat); + Close(); + if (Program.MainForm != null) Program.MainForm.Close(); + Process.Start("update.bat"); + } + } +} diff --git a/src/Neo.GUI/GUI/UpdateDialog.es-ES.resx b/src/Neo.GUI/GUI/UpdateDialog.es-ES.resx new file mode 100644 index 0000000000..5f94e9b654 --- /dev/null +++ b/src/Neo.GUI/GUI/UpdateDialog.es-ES.resx @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 94, 17 + + + Última versión: + + + 112, 15 + + + 332, 16 + + + 73, 17 + + + Web oficial + + + Cancelar + + + Registro de cambios + + + Actualizar + + + 68, 17 + + + Descargar + + + Actualización disponible + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/UpdateDialog.resx b/src/Neo.GUI/GUI/UpdateDialog.resx new file mode 100644 index 0000000000..23e774988f --- /dev/null +++ b/src/Neo.GUI/GUI/UpdateDialog.resx @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 12, 15 + + + 102, 17 + + + 0 + + + Newest Version: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + + Top, Left, Right + + + 120, 15 + + + 324, 16 + + + 1 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + Bottom, Left + + + True + + + 12, 335 + + + 79, 17 + + + 4 + + + Official Web + + + linkLabel1 + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Bottom, Right + + + 369, 332 + + + 75, 23 + + + 7 + + + Close + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Top, Bottom, Left, Right + + + Fill + + + 3, 19 + + + True + + + Both + + + 426, 234 + + + 0 + + + False + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + 12, 41 + + + 432, 256 + + + 2 + + + Change logs + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Bottom, Right + + + 288, 332 + + + 75, 23 + + + 6 + + + Update + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Left + + + True + + + NoControl + + + 97, 335 + + + 67, 17 + + + 5 + + + Download + + + linkLabel2 + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 12, 303 + + + 432, 23 + + + 3 + + + progressBar1 + + + System.Windows.Forms.ProgressBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 456, 367 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Update Available + + + UpdateDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/UpdateDialog.zh-Hans.resx b/src/Neo.GUI/GUI/UpdateDialog.zh-Hans.resx new file mode 100644 index 0000000000..6db88c3a6e --- /dev/null +++ b/src/Neo.GUI/GUI/UpdateDialog.zh-Hans.resx @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 59, 17 + + + 最新版本: + + + 77, 15 + + + 367, 16 + + + 32, 17 + + + 官网 + + + 关闭 + + + 更新日志 + + + 更新 + + + 50, 335 + + + 32, 17 + + + 下载 + + + 发现新版本 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ViewContractDialog.Designer.cs b/src/Neo.GUI/GUI/ViewContractDialog.Designer.cs new file mode 100644 index 0000000000..5adbe25451 --- /dev/null +++ b/src/Neo.GUI/GUI/ViewContractDialog.Designer.cs @@ -0,0 +1,143 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ViewContractDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ViewContractDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.ReadOnly = true; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox4); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox4 + // + resources.ApplyResources(this.textBox4, "textBox4"); + this.textBox4.Name = "textBox4"; + this.textBox4.ReadOnly = true; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.Name = "textBox3"; + this.textBox3.ReadOnly = true; + // + // ViewContractDialog + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button1; + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label3); + this.Controls.Add(this.button1); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ViewContractDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox3; + } +} diff --git a/src/Neo.GUI/GUI/ViewContractDialog.cs b/src/Neo.GUI/GUI/ViewContractDialog.cs new file mode 100644 index 0000000000..ada56ef90f --- /dev/null +++ b/src/Neo.GUI/GUI/ViewContractDialog.cs @@ -0,0 +1,29 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.SmartContract; +using System.Linq; +using System.Windows.Forms; +using Neo.Wallets; + +namespace Neo.GUI +{ + public partial class ViewContractDialog : Form + { + public ViewContractDialog(Contract contract) + { + InitializeComponent(); + textBox1.Text = contract.ScriptHash.ToAddress(Program.Service.NeoSystem.Settings.AddressVersion); + textBox2.Text = contract.ScriptHash.ToString(); + textBox3.Text = contract.ParameterList.Cast().ToArray().ToHexString(); + textBox4.Text = contract.Script.ToHexString(); + } + } +} diff --git a/src/Neo.GUI/GUI/ViewContractDialog.es-ES.resx b/src/Neo.GUI/GUI/ViewContractDialog.es-ES.resx new file mode 100644 index 0000000000..c792cfc6ab --- /dev/null +++ b/src/Neo.GUI/GUI/ViewContractDialog.es-ES.resx @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 72, 15 + + + 65, 17 + + + Dirección: + + + 143, 12 + + + 363, 23 + + + 39, 44 + + + 98, 17 + + + Hash del script: + + + 143, 41 + + + 363, 23 + + + 494, 273 + + + Código del script + + + 488, 251 + + + 431, 378 + + + Cancelar + + + 9, 73 + + + 128, 17 + + + Lista de parámetros: + + + 143, 70 + + + 363, 23 + + + 518, 413 + + + Ver contrato + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ViewContractDialog.resx b/src/Neo.GUI/GUI/ViewContractDialog.resx new file mode 100644 index 0000000000..97c2f61083 --- /dev/null +++ b/src/Neo.GUI/GUI/ViewContractDialog.resx @@ -0,0 +1,387 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 47, 15 + + + 59, 17 + + + 0 + + + Address: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + + Top, Left, Right + + + 112, 12 + + + 328, 23 + + + 1 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + True + + + 29, 44 + + + 77, 17 + + + 2 + + + Script Hash: + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + Top, Left, Right + + + 112, 41 + + + 328, 23 + + + 3 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Top, Bottom, Left, Right + + + Fill + + + 3, 19 + + + True + + + Vertical + + + 422, 251 + + + 0 + + + textBox4 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + 12, 99 + + + 428, 273 + + + 6 + + + Redeem Script + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Bottom, Right + + + 365, 378 + + + 75, 23 + + + 7 + + + Close + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + True + + + 12, 73 + + + 94, 17 + + + 4 + + + Parameter List: + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Top, Left, Right + + + 112, 70 + + + 328, 23 + + + 5 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 452, 413 + + + Microsoft YaHei UI, 9pt + + + 2, 2, 2, 2 + + + CenterScreen + + + View Contract + + + ViewContractDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ViewContractDialog.zh-Hans.resx b/src/Neo.GUI/GUI/ViewContractDialog.zh-Hans.resx new file mode 100644 index 0000000000..9a870a5476 --- /dev/null +++ b/src/Neo.GUI/GUI/ViewContractDialog.zh-Hans.resx @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 36, 15 + + + 35, 17 + + + 地址: + + + 77, 12 + + + 363, 23 + + + 12, 44 + + + 59, 17 + + + 脚本散列: + + + 77, 41 + + + 363, 23 + + + 脚本 + + + 关闭 + + + 59, 17 + + + 形参列表: + + + 77, 70 + + + 363, 23 + + + 查看合约 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ViewPrivateKeyDialog.cs b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.cs new file mode 100644 index 0000000000..f273595210 --- /dev/null +++ b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.cs @@ -0,0 +1,28 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Wallets; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class ViewPrivateKeyDialog : Form + { + public ViewPrivateKeyDialog(WalletAccount account) + { + InitializeComponent(); + KeyPair key = account.GetKey(); + textBox3.Text = account.Address; + textBox4.Text = key.PublicKey.EncodePoint(true).ToHexString(); + textBox1.Text = key.PrivateKey.ToHexString(); + textBox2.Text = key.Export(); + } + } +} diff --git a/src/Neo.GUI/GUI/ViewPrivateKeyDialog.designer.cs b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.designer.cs new file mode 100644 index 0000000000..2ba3d9773f --- /dev/null +++ b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.designer.cs @@ -0,0 +1,155 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class ViewPrivateKeyDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ViewPrivateKeyDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox2 + // + resources.ApplyResources(this.textBox2, "textBox2"); + this.textBox2.Name = "textBox2"; + this.textBox2.ReadOnly = true; + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.Name = "label4"; + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // textBox3 + // + resources.ApplyResources(this.textBox3, "textBox3"); + this.textBox3.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.textBox3.Name = "textBox3"; + this.textBox3.ReadOnly = true; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textBox4 + // + resources.ApplyResources(this.textBox4, "textBox4"); + this.textBox4.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.textBox4.Name = "textBox4"; + this.textBox4.ReadOnly = true; + // + // ViewPrivateKeyDialog + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button1; + this.Controls.Add(this.textBox4); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.button1); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ViewPrivateKeyDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox4; + } +} diff --git a/src/Neo.GUI/GUI/ViewPrivateKeyDialog.es-ES.resx b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.es-ES.resx new file mode 100644 index 0000000000..4c3e507b35 --- /dev/null +++ b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.es-ES.resx @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 32, 11 + + + 65, 17 + + + Dirección: + + + Clave privada + + + Cerrar + + + 100, 11 + + + 470, 16 + + + 9, 36 + + + 88, 17 + + + Clave pública: + + + 100, 36 + + + 470, 16 + + + Ver clave pública + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ViewPrivateKeyDialog.resx b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.resx new file mode 100644 index 0000000000..49368fb3f2 --- /dev/null +++ b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.resx @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 29, 11 + + + 59, 17 + + + 0 + + + Address: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + + Top, Left, Right + + + 47, 22 + + + 494, 23 + + + 1 + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 3 + + + Top, Left, Right + + + Top, Left, Right + + + 47, 51 + + + 494, 23 + + + 3 + + + textBox2 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + True + + + 8, 54 + + + 33, 17 + + + 2 + + + WIF: + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 1 + + + True + + + 6, 25 + + + 35, 17 + + + 0 + + + HEX: + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 2 + + + 12, 73 + + + 558, 93 + + + 2 + + + Private Key + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Bottom, Right + + + 495, 172 + + + 75, 23 + + + 3 + + + close + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Top, Left, Right + + + 94, 11 + + + 476, 16 + + + 4 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + True + + + 18, 36 + + + 70, 17 + + + 5 + + + Public Key: + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Top, Left, Right + + + 94, 36 + + + 476, 16 + + + 6 + + + textBox4 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 582, 207 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + View Private Key + + + ViewPrivateKeyDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/ViewPrivateKeyDialog.zh-Hans.resx b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.zh-Hans.resx new file mode 100644 index 0000000000..aac178a792 --- /dev/null +++ b/src/Neo.GUI/GUI/ViewPrivateKeyDialog.zh-Hans.resx @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 18, 9 + + + 35, 17 + + + 地址: + + + 487, 23 + + + 487, 23 + + + 12, 53 + + + 540, 85 + + + 私钥 + + + 477, 153 + + + 关闭 + + + 59, 9 + + + 493, 16 + + + 18, 31 + + + 35, 17 + + + 公钥: + + + 59, 31 + + + 493, 16 + + + 564, 188 + + + 查看私钥 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/VotingDialog.Designer.cs b/src/Neo.GUI/GUI/VotingDialog.Designer.cs new file mode 100644 index 0000000000..0ce4b7ee30 --- /dev/null +++ b/src/Neo.GUI/GUI/VotingDialog.Designer.cs @@ -0,0 +1,111 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +namespace Neo.GUI +{ + partial class VotingDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VotingDialog)); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // groupBox1 + // + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // textBox1 + // + resources.ApplyResources(this.textBox1, "textBox1"); + this.textBox1.AcceptsReturn = true; + this.textBox1.Name = "textBox1"; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + resources.ApplyResources(this.button2, "button2"); + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Name = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // VotingDialog + // + resources.ApplyResources(this, "$this"); + this.AcceptButton = this.button1; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "VotingDialog"; + this.ShowInTaskbar = false; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.TextBox textBox1; + } +} diff --git a/src/Neo.GUI/GUI/VotingDialog.cs b/src/Neo.GUI/GUI/VotingDialog.cs new file mode 100644 index 0000000000..9b827eb00e --- /dev/null +++ b/src/Neo.GUI/GUI/VotingDialog.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using System.Linq; +using System.Windows.Forms; + +namespace Neo.GUI +{ + internal partial class VotingDialog : Form + { + private readonly UInt160 script_hash; + + public byte[] GetScript() + { + ECPoint[] pubkeys = textBox1.Lines.Select(p => ECPoint.Parse(p, ECCurve.Secp256r1)).ToArray(); + using ScriptBuilder sb = new ScriptBuilder(); + sb.EmitDynamicCall(NativeContract.NEO.Hash, "vote", new ContractParameter + { + Type = ContractParameterType.Hash160, + Value = script_hash + }, new ContractParameter + { + Type = ContractParameterType.Array, + Value = pubkeys.Select(p => new ContractParameter + { + Type = ContractParameterType.PublicKey, + Value = p + }).ToArray() + }); + return sb.ToArray(); + } + + public VotingDialog(UInt160 script_hash) + { + InitializeComponent(); + this.script_hash = script_hash; + label1.Text = script_hash.ToAddress(Program.Service.NeoSystem.Settings.AddressVersion); + } + } +} diff --git a/src/Neo.GUI/GUI/VotingDialog.es-ES.resx b/src/Neo.GUI/GUI/VotingDialog.es-ES.resx new file mode 100644 index 0000000000..e2afed46e3 --- /dev/null +++ b/src/Neo.GUI/GUI/VotingDialog.es-ES.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Candidatos + + + Aceptar + + + Cancelar + + + Votación + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/VotingDialog.resx b/src/Neo.GUI/GUI/VotingDialog.resx new file mode 100644 index 0000000000..2416392148 --- /dev/null +++ b/src/Neo.GUI/GUI/VotingDialog.resx @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Left, Right + + + + 微软雅黑, 11pt + + + 12, 23 + + + 562, 39 + + + + 0 + + + label1 + + + MiddleCenter + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Top, Bottom, Left, Right + + + Fill + + + Lucida Console, 9pt + + + 3, 19 + + + True + + + Vertical + + + 556, 368 + + + 0 + + + False + + + textBox1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + 12, 65 + + + 562, 390 + + + 1 + + + Candidates + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Right + + + 418, 461 + + + 75, 23 + + + 2 + + + OK + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Bottom, Right + + + 499, 461 + + + 75, 23 + + + 3 + + + Cancel + + + button2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 17 + + + 586, 496 + + + 微软雅黑, 9pt + + + 3, 4, 3, 4 + + + CenterScreen + + + Voting + + + VotingDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/VotingDialog.zh-Hans.resx b/src/Neo.GUI/GUI/VotingDialog.zh-Hans.resx new file mode 100644 index 0000000000..e41916cae4 --- /dev/null +++ b/src/Neo.GUI/GUI/VotingDialog.zh-Hans.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 候选人 + + + 确定 + + + 取消 + + + 投票 + + \ No newline at end of file diff --git a/src/Neo.GUI/GUI/Wrappers/HexConverter.cs b/src/Neo.GUI/GUI/Wrappers/HexConverter.cs new file mode 100644 index 0000000000..724af82b66 --- /dev/null +++ b/src/Neo.GUI/GUI/Wrappers/HexConverter.cs @@ -0,0 +1,48 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Neo.GUI.Wrappers +{ + internal class HexConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + return true; + return false; + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(string)) + return true; + return false; + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string s) + return s.HexToBytes(); + throw new NotSupportedException(); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType != typeof(string)) + throw new NotSupportedException(); + if (!(value is byte[] array)) return null; + return array.ToHexString(); + } + } +} diff --git a/src/Neo.GUI/GUI/Wrappers/ScriptEditor.cs b/src/Neo.GUI/GUI/Wrappers/ScriptEditor.cs new file mode 100644 index 0000000000..199c33b6f4 --- /dev/null +++ b/src/Neo.GUI/GUI/Wrappers/ScriptEditor.cs @@ -0,0 +1,35 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.ComponentModel; +using System.IO; +using System.Windows.Forms; +using System.Windows.Forms.Design; + +namespace Neo.GUI.Wrappers +{ + internal class ScriptEditor : FileNameEditor + { + public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) + { + string path = (string)base.EditValue(context, provider, null); + if (path == null) return null; + return File.ReadAllBytes(path); + } + + protected override void InitializeDialog(OpenFileDialog openFileDialog) + { + base.InitializeDialog(openFileDialog); + openFileDialog.DefaultExt = "avm"; + openFileDialog.Filter = "NeoContract|*.avm"; + } + } +} diff --git a/src/Neo.GUI/GUI/Wrappers/SignerWrapper.cs b/src/Neo.GUI/GUI/Wrappers/SignerWrapper.cs new file mode 100644 index 0000000000..70f9d4a045 --- /dev/null +++ b/src/Neo.GUI/GUI/Wrappers/SignerWrapper.cs @@ -0,0 +1,37 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Cryptography.ECC; +using Neo.Network.P2P.Payloads; +using System.Collections.Generic; +using System.ComponentModel; + +namespace Neo.GUI.Wrappers +{ + internal class SignerWrapper + { + [TypeConverter(typeof(UIntBaseConverter))] + public UInt160 Account { get; set; } + public WitnessScope Scopes { get; set; } + public List AllowedContracts { get; set; } = new List(); + public List AllowedGroups { get; set; } = new List(); + + public Signer Unwrap() + { + return new Signer + { + Account = Account, + Scopes = Scopes, + AllowedContracts = AllowedContracts.ToArray(), + AllowedGroups = AllowedGroups.ToArray() + }; + } + } +} diff --git a/src/Neo.GUI/GUI/Wrappers/TransactionAttributeWrapper.cs b/src/Neo.GUI/GUI/Wrappers/TransactionAttributeWrapper.cs new file mode 100644 index 0000000000..bb42f9e761 --- /dev/null +++ b/src/Neo.GUI/GUI/Wrappers/TransactionAttributeWrapper.cs @@ -0,0 +1,29 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.IO; +using Neo.Network.P2P.Payloads; +using System.ComponentModel; + +namespace Neo.GUI.Wrappers +{ + internal class TransactionAttributeWrapper + { + public TransactionAttributeType Usage { get; set; } + [TypeConverter(typeof(HexConverter))] + public byte[] Data { get; set; } + + public TransactionAttribute Unwrap() + { + MemoryReader reader = new(Data); + return TransactionAttribute.DeserializeFrom(ref reader); + } + } +} diff --git a/src/Neo.GUI/GUI/Wrappers/TransactionWrapper.cs b/src/Neo.GUI/GUI/Wrappers/TransactionWrapper.cs new file mode 100644 index 0000000000..e1aeef4e96 --- /dev/null +++ b/src/Neo.GUI/GUI/Wrappers/TransactionWrapper.cs @@ -0,0 +1,58 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Network.P2P.Payloads; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing.Design; +using System.Linq; + +namespace Neo.GUI.Wrappers +{ + internal class TransactionWrapper + { + [Category("Basic")] + public byte Version { get; set; } + [Category("Basic")] + public uint Nonce { get; set; } + [Category("Basic")] + public List Signers { get; set; } + [Category("Basic")] + public long SystemFee { get; set; } + [Category("Basic")] + public long NetworkFee { get; set; } + [Category("Basic")] + public uint ValidUntilBlock { get; set; } + [Category("Basic")] + public List Attributes { get; set; } = new List(); + [Category("Basic")] + [Editor(typeof(ScriptEditor), typeof(UITypeEditor))] + [TypeConverter(typeof(HexConverter))] + public byte[] Script { get; set; } + [Category("Basic")] + public List Witnesses { get; set; } = new List(); + + public Transaction Unwrap() + { + return new Transaction + { + Version = Version, + Nonce = Nonce, + Signers = Signers.Select(p => p.Unwrap()).ToArray(), + SystemFee = SystemFee, + NetworkFee = NetworkFee, + ValidUntilBlock = ValidUntilBlock, + Attributes = Attributes.Select(p => p.Unwrap()).ToArray(), + Script = Script, + Witnesses = Witnesses.Select(p => p.Unwrap()).ToArray() + }; + } + } +} diff --git a/src/Neo.GUI/GUI/Wrappers/UIntBaseConverter.cs b/src/Neo.GUI/GUI/Wrappers/UIntBaseConverter.cs new file mode 100644 index 0000000000..20d458577f --- /dev/null +++ b/src/Neo.GUI/GUI/Wrappers/UIntBaseConverter.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Neo.GUI.Wrappers +{ + internal class UIntBaseConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + return true; + return false; + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(string)) + return true; + return false; + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string s) + return context.PropertyDescriptor.PropertyType.GetMethod("Parse").Invoke(null, new[] { s }); + throw new NotSupportedException(); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType != typeof(string)) + throw new NotSupportedException(); + + return value switch + { + UInt160 i => i.ToString(), + UInt256 i => i.ToString(), + _ => null, + }; + } + } +} diff --git a/src/Neo.GUI/GUI/Wrappers/WitnessWrapper.cs b/src/Neo.GUI/GUI/Wrappers/WitnessWrapper.cs new file mode 100644 index 0000000000..bc5ffddc09 --- /dev/null +++ b/src/Neo.GUI/GUI/Wrappers/WitnessWrapper.cs @@ -0,0 +1,35 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Network.P2P.Payloads; +using System.ComponentModel; +using System.Drawing.Design; + +namespace Neo.GUI.Wrappers +{ + internal class WitnessWrapper + { + [Editor(typeof(ScriptEditor), typeof(UITypeEditor))] + [TypeConverter(typeof(HexConverter))] + public byte[] InvocationScript { get; set; } + [Editor(typeof(ScriptEditor), typeof(UITypeEditor))] + [TypeConverter(typeof(HexConverter))] + public byte[] VerificationScript { get; set; } + + public Witness Unwrap() + { + return new Witness + { + InvocationScript = InvocationScript, + VerificationScript = VerificationScript + }; + } + } +} diff --git a/src/Neo.GUI/IO/Actors/EventWrapper.cs b/src/Neo.GUI/IO/Actors/EventWrapper.cs new file mode 100644 index 0000000000..77562aa6f4 --- /dev/null +++ b/src/Neo.GUI/IO/Actors/EventWrapper.cs @@ -0,0 +1,42 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using System; + +namespace Neo.IO.Actors +{ + internal class EventWrapper : UntypedActor + { + private readonly Action callback; + + public EventWrapper(Action callback) + { + this.callback = callback; + Context.System.EventStream.Subscribe(Self, typeof(T)); + } + + protected override void OnReceive(object message) + { + if (message is T obj) callback(obj); + } + + protected override void PostStop() + { + Context.System.EventStream.Unsubscribe(Self); + base.PostStop(); + } + + public static Props Props(Action callback) + { + return Akka.Actor.Props.Create(() => new EventWrapper(callback)); + } + } +} diff --git a/src/Neo.GUI/Neo.GUI.csproj b/src/Neo.GUI/Neo.GUI.csproj new file mode 100644 index 0000000000..7a7193ea30 --- /dev/null +++ b/src/Neo.GUI/Neo.GUI.csproj @@ -0,0 +1,55 @@ + + + + 2016-2023 The Neo Project + Neo.GUI + WinExe + net7.0-windows + true + Neo + true + Neo.GUI + + + + + DeveloperToolsForm.cs + + + DeveloperToolsForm.cs + + + True + True + Resources.resx + + + True + True + Strings.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + ResXFileCodeGenerator + Strings.Designer.cs + + + Strings.resx + + + Strings.resx + + + + + + + + + \ No newline at end of file diff --git a/src/Neo.GUI/Program.cs b/src/Neo.GUI/Program.cs new file mode 100644 index 0000000000..f872706ff5 --- /dev/null +++ b/src/Neo.GUI/Program.cs @@ -0,0 +1,95 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.CLI; +using Neo.GUI; +using Neo.SmartContract.Native; +using System; +using System.IO; +using System.Reflection; +using System.Windows.Forms; +using System.Xml.Linq; + +namespace Neo +{ + static class Program + { + public static MainService Service = new MainService(); + public static MainForm MainForm; + public static UInt160[] NEP5Watched = { NativeContract.NEO.Hash, NativeContract.GAS.Hash }; + + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + using FileStream fs = new FileStream("error.log", FileMode.Create, FileAccess.Write, FileShare.None); + using StreamWriter w = new StreamWriter(fs); + if (e.ExceptionObject is Exception ex) + { + PrintErrorLogs(w, ex); + } + else + { + w.WriteLine(e.ExceptionObject.GetType()); + w.WriteLine(e.ExceptionObject); + } + } + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main(string[] args) + { + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + XDocument xdoc = null; + try + { + xdoc = XDocument.Load("https://raw.githubusercontent.com/neo-project/neo-gui/master/update.xml"); + } + catch { } + if (xdoc != null) + { + Version version = Assembly.GetExecutingAssembly().GetName().Version; + Version minimum = Version.Parse(xdoc.Element("update").Attribute("minimum").Value); + if (version < minimum) + { + using UpdateDialog dialog = new UpdateDialog(xdoc); + dialog.ShowDialog(); + return; + } + } + Service.Start(args); + Application.Run(MainForm = new MainForm(xdoc)); + Service.Stop(); + } + + private static void PrintErrorLogs(StreamWriter writer, Exception ex) + { + writer.WriteLine(ex.GetType()); + writer.WriteLine(ex.Message); + writer.WriteLine(ex.StackTrace); + if (ex is AggregateException ex2) + { + foreach (Exception inner in ex2.InnerExceptions) + { + writer.WriteLine(); + PrintErrorLogs(writer, inner); + } + } + else if (ex.InnerException != null) + { + writer.WriteLine(); + PrintErrorLogs(writer, ex.InnerException); + } + } + } +} diff --git a/src/Neo.GUI/Properties/Resources.Designer.cs b/src/Neo.GUI/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..4cbcca4fd2 --- /dev/null +++ b/src/Neo.GUI/Properties/Resources.Designer.cs @@ -0,0 +1,133 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Neo.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Neo.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap add { + get { + object obj = ResourceManager.GetObject("add", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap add2 { + get { + object obj = ResourceManager.GetObject("add2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap remark { + get { + object obj = ResourceManager.GetObject("remark", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap remove { + get { + object obj = ResourceManager.GetObject("remove", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap search { + get { + object obj = ResourceManager.GetObject("search", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Byte[] 类型的本地化资源。 + /// + internal static byte[] UpdateBat { + get { + object obj = ResourceManager.GetObject("UpdateBat", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/src/Neo.GUI/Properties/Resources.resx b/src/Neo.GUI/Properties/Resources.resx new file mode 100644 index 0000000000..40ca55734d --- /dev/null +++ b/src/Neo.GUI/Properties/Resources.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\add2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\remark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\remove.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\search.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\update.bat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Neo.GUI/Properties/Strings.Designer.cs b/src/Neo.GUI/Properties/Strings.Designer.cs new file mode 100644 index 0000000000..ceafe6ac3a --- /dev/null +++ b/src/Neo.GUI/Properties/Strings.Designer.cs @@ -0,0 +1,542 @@ +// Copyright (C) 2016-2023 The Neo Project. +// +// The neo-gui is free software distributed under the MIT software +// license, see the accompanying file LICENSE in the main directory of +// the project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Neo.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Neo.Properties.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to About. + /// + internal static string About { + get { + return ResourceManager.GetString("About", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NEO. + /// + internal static string AboutMessage { + get { + return ResourceManager.GetString("AboutMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version:. + /// + internal static string AboutVersion { + get { + return ResourceManager.GetString("AboutVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to add smart contract, corresponding private key missing in this wallet.. + /// + internal static string AddContractFailedMessage { + get { + return ResourceManager.GetString("AddContractFailedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Address. + /// + internal static string Address { + get { + return ResourceManager.GetString("Address", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cancel. + /// + internal static string Cancel { + get { + return ResourceManager.GetString("Cancel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change password successful.. + /// + internal static string ChangePasswordSuccessful { + get { + return ResourceManager.GetString("ChangePasswordSuccessful", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirm. + /// + internal static string Confirm { + get { + return ResourceManager.GetString("Confirm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to will be consumed, confirm?. + /// + internal static string CostTips { + get { + return ResourceManager.GetString("CostTips", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cost Warning. + /// + internal static string CostTitle { + get { + return ResourceManager.GetString("CostTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirmation. + /// + internal static string DeleteAddressConfirmationCaption { + get { + return ResourceManager.GetString("DeleteAddressConfirmationCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upon deletion, assets in these addresses will be permanently lost, are you sure to proceed?. + /// + internal static string DeleteAddressConfirmationMessage { + get { + return ResourceManager.GetString("DeleteAddressConfirmationMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Assets cannot be recovered once deleted, are you sure to delete the assets?. + /// + internal static string DeleteAssetConfirmationMessage { + get { + return ResourceManager.GetString("DeleteAssetConfirmationMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirmation. + /// + internal static string DeleteConfirmation { + get { + return ResourceManager.GetString("DeleteConfirmation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter remark here, which will be recorded on the blockchain. + /// + internal static string EnterRemarkMessage { + get { + return ResourceManager.GetString("EnterRemarkMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transaction Remark. + /// + internal static string EnterRemarkTitle { + get { + return ResourceManager.GetString("EnterRemarkTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Execution terminated in fault state.. + /// + internal static string ExecutionFailed { + get { + return ResourceManager.GetString("ExecutionFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expired. + /// + internal static string ExpiredCertificate { + get { + return ResourceManager.GetString("ExpiredCertificate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed. + /// + internal static string Failed { + get { + return ResourceManager.GetString("Failed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to High Priority Transaction. + /// + internal static string HighPriority { + get { + return ResourceManager.GetString("HighPriority", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import Watch-Only Address. + /// + internal static string ImportWatchOnlyAddress { + get { + return ResourceManager.GetString("ImportWatchOnlyAddress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transaction initiated, but the signature is incomplete.. + /// + internal static string IncompletedSignatureMessage { + get { + return ResourceManager.GetString("IncompletedSignatureMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Incomplete signature. + /// + internal static string IncompletedSignatureTitle { + get { + return ResourceManager.GetString("IncompletedSignatureTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have cancelled the certificate installation.. + /// + internal static string InstallCertificateCancel { + get { + return ResourceManager.GetString("InstallCertificateCancel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Install the certificate. + /// + internal static string InstallCertificateCaption { + get { + return ResourceManager.GetString("InstallCertificateCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NEO must install Onchain root certificate to validate assets on the blockchain, install it now?. + /// + internal static string InstallCertificateText { + get { + return ResourceManager.GetString("InstallCertificateText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Insufficient funds, transaction cannot be initiated.. + /// + internal static string InsufficientFunds { + get { + return ResourceManager.GetString("InsufficientFunds", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid. + /// + internal static string InvalidCertificate { + get { + return ResourceManager.GetString("InvalidCertificate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Migrate Wallet. + /// + internal static string MigrateWalletCaption { + get { + return ResourceManager.GetString("MigrateWalletCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Opening wallet files in older versions, update to newest format? + ///Note: updated files cannot be openned by clients in older versions!. + /// + internal static string MigrateWalletMessage { + get { + return ResourceManager.GetString("MigrateWalletMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wallet file relocated. New wallet file has been saved at: . + /// + internal static string MigrateWalletSucceedMessage { + get { + return ResourceManager.GetString("MigrateWalletSucceedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password Incorrect. + /// + internal static string PasswordIncorrect { + get { + return ResourceManager.GetString("PasswordIncorrect", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Data broadcast success, the hash is shown as follows:. + /// + internal static string RelaySuccessText { + get { + return ResourceManager.GetString("RelaySuccessText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Broadcast Success. + /// + internal static string RelaySuccessTitle { + get { + return ResourceManager.GetString("RelaySuccessTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Raw:. + /// + internal static string RelayTitle { + get { + return ResourceManager.GetString("RelayTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transaction sent, TXID:. + /// + internal static string SendTxSucceedMessage { + get { + return ResourceManager.GetString("SendTxSucceedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transaction successful. + /// + internal static string SendTxSucceedTitle { + get { + return ResourceManager.GetString("SendTxSucceedTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The private key that can sign the data is not found.. + /// + internal static string SigningFailedKeyNotFoundMessage { + get { + return ResourceManager.GetString("SigningFailedKeyNotFoundMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You must input JSON object pending signature data.. + /// + internal static string SigningFailedNoDataMessage { + get { + return ResourceManager.GetString("SigningFailedNoDataMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to System. + /// + internal static string SystemIssuer { + get { + return ResourceManager.GetString("SystemIssuer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation failed, the counterparty falsified the transaction content!. + /// + internal static string TradeFailedFakeDataMessage { + get { + return ResourceManager.GetString("TradeFailedFakeDataMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation failed, the counterparty generated illegal transaction content!. + /// + internal static string TradeFailedInvalidDataMessage { + get { + return ResourceManager.GetString("TradeFailedInvalidDataMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation failed, invalid transaction or unsynchronized blockchain, please try again when synchronized!. + /// + internal static string TradeFailedNoSyncMessage { + get { + return ResourceManager.GetString("TradeFailedNoSyncMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Need Signature. + /// + internal static string TradeNeedSignatureCaption { + get { + return ResourceManager.GetString("TradeNeedSignatureCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transaction generated, please send the following information to the counterparty for signing:. + /// + internal static string TradeNeedSignatureMessage { + get { + return ResourceManager.GetString("TradeNeedSignatureMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trade Request. + /// + internal static string TradeRequestCreatedCaption { + get { + return ResourceManager.GetString("TradeRequestCreatedCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transaction request generated, please send it to the counterparty or merge it with the counterparty's request.. + /// + internal static string TradeRequestCreatedMessage { + get { + return ResourceManager.GetString("TradeRequestCreatedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trade Success. + /// + internal static string TradeSuccessCaption { + get { + return ResourceManager.GetString("TradeSuccessCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transaction sent, this is the TXID:. + /// + internal static string TradeSuccessMessage { + get { + return ResourceManager.GetString("TradeSuccessMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to unconfirmed. + /// + internal static string Unconfirmed { + get { + return ResourceManager.GetString("Unconfirmed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to unknown issuer. + /// + internal static string UnknownIssuer { + get { + return ResourceManager.GetString("UnknownIssuer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blockchain unsynchronized, transaction cannot be sent.. + /// + internal static string UnsynchronizedBlock { + get { + return ResourceManager.GetString("UnsynchronizedBlock", resourceCulture); + } + } + } +} diff --git a/src/Neo.GUI/Properties/Strings.es-Es.resx b/src/Neo.GUI/Properties/Strings.es-Es.resx new file mode 100644 index 0000000000..c3ab2fa426 --- /dev/null +++ b/src/Neo.GUI/Properties/Strings.es-Es.resx @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Acerca de + + + NEO + + + Versión: + + + Fallo al añadir el contrato inteligente. Falta la correspondiente clave privada en el monedero. + + + Dirección + + + Contraseña cambiada con éxito. + + + Confirmación + + + Una vez eliminados, los activos de estas direcciones se perderán permanentemente. ¿Deseas continuar? + + + Los activos no se pueden recuperar una vez eliminados. ¿Deseas eliminarlos? + + + Confirmación + + + Notas de la transacción que se grabará en la blockchain. + + + Notas de la transacción + + + La ejecución terminó con un estado de error. + + + Caducado + + + Falló + + + Importar dirección sólo lectura + + + Transacción iniciada aunque la firma está incompleta. + + + Firma incompleta + + + Instalación del certificado cancelada. + + + Instalar certificado + + + NEO debe instalar el certificado raíz de Onchain para validar activos en la blockchain. ¿Instalar ahora? + + + Fondos insuficientes, la transacción no se puede iniciar. + + + Inválido + + + Migrar monedero + + + Abriendo ficheros de monederos antiguos, actualizar al nuevo formato? +Aviso: los ficheros actualizados no podran ser abiertos por clientes de versiones antiguas. + + + Contraseña incorrecta + + + Datos emitidos con éxito. El hash se muestra como sigue: + + + Emisión realizada con éxito + + + Raw: + + + Transacción enviada, TXID: + + + Transacción realizada con éxito + + + Falta la clave privada para firmar los datos. + + + Debes introducir el objeto JSON de los datos pendientes de firmar. + + + System + + + ¡Falló la validación! El contratante falsificó el contenido de la transacción. + + + ¡Falló la validación! El contratante generó una transacción con contenido ilegal. + + + ¡Falló la validación! Transacción no válida o blockchain sin sincronizar. Inténtalo de nuevo después de sincronizar. + + + Firma necesaria. + + + Transacción generada. Por favor, envia la siguiente información al contratante para su firma: + + + Solicitud de transacción. + + + Solicitud de transacción generada. Por favor, enviala al contratante o incorporala a la solicitud del contratante. + + + Transacción realizada con éxito. + + + Transacción enviada, este es el TXID: + + + Sin confirmar. + + + Emisor desconocido. + + + Blockchain sin sincronizar, la transacción no puede ser enviada. + + \ No newline at end of file diff --git a/src/Neo.GUI/Properties/Strings.resx b/src/Neo.GUI/Properties/Strings.resx new file mode 100644 index 0000000000..95a3fced89 --- /dev/null +++ b/src/Neo.GUI/Properties/Strings.resx @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + About + + + NEO + + + Version: + + + Failed to add smart contract, corresponding private key missing in this wallet. + + + Address + + + Cancel + + + Change password successful. + + + Confirm + + + will be consumed, confirm? + + + Cost Warning + + + Confirmation + + + Upon deletion, assets in these addresses will be permanently lost, are you sure to proceed? + + + Assets cannot be recovered once deleted, are you sure to delete the assets? + + + Confirmation + + + Enter remark here, which will be recorded on the blockchain + + + Transaction Remark + + + Execution terminated in fault state. + + + Expired + + + Failed + + + High Priority Transaction + + + Import Watch-Only Address + + + Transaction initiated, but the signature is incomplete. + + + Incomplete signature + + + You have cancelled the certificate installation. + + + Install the certificate + + + NEO must install Onchain root certificate to validate assets on the blockchain, install it now? + + + Insufficient funds, transaction cannot be initiated. + + + Invalid + + + Migrate Wallet + + + Opening wallet files in older versions, update to newest format? +Note: updated files cannot be openned by clients in older versions! + + + Wallet file relocated. New wallet file has been saved at: + + + Password Incorrect + + + Data broadcast success, the hash is shown as follows: + + + Broadcast Success + + + Raw: + + + Transaction sent, TXID: + + + Transaction successful + + + The private key that can sign the data is not found. + + + You must input JSON object pending signature data. + + + System + + + Validation failed, the counterparty falsified the transaction content! + + + Validation failed, the counterparty generated illegal transaction content! + + + Validation failed, invalid transaction or unsynchronized blockchain, please try again when synchronized! + + + Need Signature + + + Transaction generated, please send the following information to the counterparty for signing: + + + Trade Request + + + Transaction request generated, please send it to the counterparty or merge it with the counterparty's request. + + + Trade Success + + + Transaction sent, this is the TXID: + + + unconfirmed + + + unknown issuer + + + Blockchain unsynchronized, transaction cannot be sent. + + \ No newline at end of file diff --git a/src/Neo.GUI/Properties/Strings.zh-Hans.resx b/src/Neo.GUI/Properties/Strings.zh-Hans.resx new file mode 100644 index 0000000000..678c4f324d --- /dev/null +++ b/src/Neo.GUI/Properties/Strings.zh-Hans.resx @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 关于 + + + NEO + + + 版本: + + + 无法添加智能合约,因为当前钱包中不包含签署该合约的私钥。 + + + 地址 + + + 取消 + + + 修改密码成功。 + + + 确认 + + + 费用即将被消耗,确认? + + + 消费提示 + + + 删除地址确认 + + + 删除地址后,这些地址中的资产将永久性地丢失,确认要继续吗? + + + 资产删除后将无法恢复,您确定要删除以下资产吗? + + + 删除确认 + + + 请输入备注信息,该信息将被记录在区块链上 + + + 交易备注 + + + 合约执行遇到错误并退出。 + + + 证书已过期 + + + 失败 + + + 优先交易 + + + 导入监视地址 + + + 交易构造完成,但没有足够的签名: + + + 签名不完整 + + + 您已取消了证书安装过程。 + + + 安装证书 + + + NEO需要安装Onchain的根证书才能对区块链上的资产进行认证,是否现在就安装证书? + + + 余额不足,无法创建交易。 + + + 证书错误 + + + 钱包文件升级 + + + 正在打开旧版本的钱包文件,是否尝试将文件升级为新版格式? +注意,升级后将无法用旧版本的客户端打开该文件! + + + 钱包文件迁移成功,新的钱包文件已经自动保存到以下位置: + + + 密码错误! + + + 数据广播成功,这是广播数据的散列值: + + + 广播成功 + + + 原始数据: + + + 交易已发送,这是交易编号(TXID): + + + 交易成功 + + + 没有找到可以签署该数据的私钥。 + + + 必须输入一段含有待签名数据的JSON对象。 + + + NEO系统 + + + 验证失败,对方篡改了交易内容! + + + 验证失败,对方构造了非法的交易内容! + + + 验证失败,交易无效或者区块链未同步完成,请同步后再试! + + + 签名不完整 + + + 交易构造完成,请将以下信息发送给对方进行签名: + + + 交易请求 + + + 交易请求已生成,请发送给对方,或与对方的请求合并: + + + 交易成功 + + + 交易已发送,这是交易编号(TXID): + + + 未确认 + + + 未知发行者 + + + 区块链未同步完成,无法发送该交易。 + + \ No newline at end of file diff --git a/src/Neo.GUI/Resources/add.png b/src/Neo.GUI/Resources/add.png new file mode 100644 index 0000000000000000000000000000000000000000..08816d65191b4895f0ace827deba9fa9a2cc8818 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+uenMVO6iP5s=4T z;_2(k{*aYJh*eTb?Oiia$k@}xF+}5ha)N^3pY$K+Kg@3wRy^S1aXca5z=;C~J~TJZ zoffu$DJ;W*cT+)v102g|2<56j^?!cXUfa#4u4XKsxbUs7akvVHA%zn z$(LI?`p?_L=bw}oezW#;^h5ppg?9y%*Q#h|r01P2$>&aKl%E?lrTnbnk3&ka#R|XN z1Y8^)ROh+>QI2_VNSe#F_{g^$b@_fZe$BY<7a7wR*#1@fGyCU6UUl0SItGVdN=gBp zty!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZEE?e4l8Mw7hL_;{xG-7x9B932TkuM zPBonPoLh`%;&mP)oRhhi~6SE-h`MwFx^mZVxG7o`Fz1|tJQb6o>dT?2~{Lvt%rLn}i|Z37D{ jpgY3sx==La=BH$)RpQogkh{$csDZ)L)z4*}Q$iB}yEb`l literal 0 HcmV?d00001 diff --git a/src/Neo.GUI/Resources/remove.png b/src/Neo.GUI/Resources/remove.png new file mode 100644 index 0000000000000000000000000000000000000000..a99083bd7046bbb209eee4b1136f75fed3517cc9 GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+uenMVO6iP5s=4T z;_2(k{*aYJh*kgUoN6hckhZ6bV~EE252#JG#5JNMC9x#cD!C{XNHG{07@F%EnCco>gcw>_8JJp` om}?sV83x~7C+$Pgkei>9nO2EgLz{#a6Ho(#r>mdKI;Vst0IJwaK>z>% literal 0 HcmV?d00001 diff --git a/src/Neo.GUI/Resources/search.png b/src/Neo.GUI/Resources/search.png new file mode 100644 index 0000000000000000000000000000000000000000..fb951a1276d9d1707efb3a3ea675ac817b54bb89 GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+uenMVO6iP5s=4T z;_2(k{*aYR*h*oW**k8a&>>G3#}JM4y%!C=m9%librn`LiJRMHFowr+;@+O{OMZ&HK+9v2$(dd`&f_ zdDrdNR|shSb6QtZ%PePNUE6E!aSrGk)e_f;l9a@fRIB8oR3OD*WMF8nYhbEtXb@s( vX=Q3*Wo)EvU}0roz+@y>jiMnpKP5A*61Rrp{AI_18W=oX{an^LB{Ts52>6q{ literal 0 HcmV?d00001 diff --git a/src/Neo.GUI/Resources/update.bat b/src/Neo.GUI/Resources/update.bat new file mode 100644 index 0000000000..fff10101e1 --- /dev/null +++ b/src/Neo.GUI/Resources/update.bat @@ -0,0 +1,13 @@ +@echo off +set "taskname=neo-gui.exe" +echo waiting... +:wait +ping 127.0.1 -n 3 >nul +tasklist | find "%taskname%" /i >nul 2>nul +if "%errorlevel%" NEQ "1" goto wait +echo updating... +copy /Y update\* * +rmdir /S /Q update +del /F /Q update.zip +start %taskname% +del /F /Q update.bat diff --git a/tests/Neo.ConsoleService.Tests/CommandTokenTest.cs b/tests/Neo.ConsoleService.Tests/CommandTokenTest.cs new file mode 100644 index 0000000000..233e486f81 --- /dev/null +++ b/tests/Neo.ConsoleService.Tests/CommandTokenTest.cs @@ -0,0 +1,92 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Linq; + +namespace Neo.ConsoleService.Tests +{ + [TestClass] + public class CommandTokenTest + { + [TestMethod] + public void Test1() + { + var cmd = " "; + var args = CommandToken.Parse(cmd).ToArray(); + + AreEqual(args, new CommandSpaceToken(0, 1)); + Assert.AreEqual(cmd, CommandToken.ToString(args)); + } + + [TestMethod] + public void Test2() + { + var cmd = "show state"; + var args = CommandToken.Parse(cmd).ToArray(); + + AreEqual(args, new CommandStringToken(0, "show"), new CommandSpaceToken(4, 2), new CommandStringToken(6, "state")); + Assert.AreEqual(cmd, CommandToken.ToString(args)); + } + + [TestMethod] + public void Test3() + { + var cmd = "show \"hello world\""; + var args = CommandToken.Parse(cmd).ToArray(); + + AreEqual(args, + new CommandStringToken(0, "show"), + new CommandSpaceToken(4, 1), + new CommandQuoteToken(5, '"'), + new CommandStringToken(6, "hello world"), + new CommandQuoteToken(17, '"') + ); + Assert.AreEqual(cmd, CommandToken.ToString(args)); + } + + [TestMethod] + public void Test4() + { + var cmd = "show \"'\""; + var args = CommandToken.Parse(cmd).ToArray(); + + AreEqual(args, + new CommandStringToken(0, "show"), + new CommandSpaceToken(4, 1), + new CommandQuoteToken(5, '"'), + new CommandStringToken(6, "'"), + new CommandQuoteToken(7, '"') + ); + Assert.AreEqual(cmd, CommandToken.ToString(args)); + } + + [TestMethod] + public void Test5() + { + var cmd = "show \"123\\\"456\""; + var args = CommandToken.Parse(cmd).ToArray(); + + AreEqual(args, + new CommandStringToken(0, "show"), + new CommandSpaceToken(4, 1), + new CommandQuoteToken(5, '"'), + new CommandStringToken(6, "123\\\"456"), + new CommandQuoteToken(14, '"') + ); + Assert.AreEqual(cmd, CommandToken.ToString(args)); + } + + private void AreEqual(CommandToken[] args, params CommandToken[] compare) + { + Assert.AreEqual(compare.Length, args.Length); + + for (int x = 0; x < args.Length; x++) + { + var a = args[x]; + var b = compare[x]; + + Assert.AreEqual(a.Type, b.Type); + Assert.AreEqual(a.Value, b.Value); + Assert.AreEqual(a.Offset, b.Offset); + } + } + } +} diff --git a/tests/Neo.ConsoleService.Tests/Neo.ConsoleService.Tests.csproj b/tests/Neo.ConsoleService.Tests/Neo.ConsoleService.Tests.csproj new file mode 100644 index 0000000000..b4b29127f6 --- /dev/null +++ b/tests/Neo.ConsoleService.Tests/Neo.ConsoleService.Tests.csproj @@ -0,0 +1,10 @@ + + + + neo_cli.Tests + + + + + + From 9a9420268f134e9cbbd98a15116ce4e1c69c322b Mon Sep 17 00:00:00 2001 From: Ricardo Prado Date: Tue, 5 Dec 2023 20:03:08 -0300 Subject: [PATCH 2/3] Added blockchain show block/transactions/contracts commands #905 (cschuchardt88) Added icon to applications #908 (cschuchardt88) --- src/Neo.CLI/CLI/MainService.Blockchain.cs | 272 ++++++++++++++++++++++ src/Neo.CLI/neo.ico | Bin 21317 -> 105486 bytes src/Neo.GUI/Neo.GUI.csproj | 5 + src/Neo.GUI/neo.ico | Bin 0 -> 370070 bytes 4 files changed, 277 insertions(+) create mode 100644 src/Neo.GUI/neo.ico diff --git a/src/Neo.CLI/CLI/MainService.Blockchain.cs b/src/Neo.CLI/CLI/MainService.Blockchain.cs index d363688701..3e5fc90a9b 100644 --- a/src/Neo.CLI/CLI/MainService.Blockchain.cs +++ b/src/Neo.CLI/CLI/MainService.Blockchain.cs @@ -9,8 +9,11 @@ // modifications are permitted. using Neo.ConsoleService; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; using Neo.SmartContract.Native; using System; +using System.Linq; namespace Neo.CLI { @@ -41,5 +44,274 @@ private void OnExportBlocksStartCountCommand(uint start, uint count = uint.MaxVa WriteBlocks(start, count, path, true); } + + [ConsoleCommand("show block", Category = "Blockchain Commands")] + private void OnShowBlockCommand(string indexOrHash) + { + lock (syncRoot) + { + Block block = null; + + if (uint.TryParse(indexOrHash, out var index)) + block = NativeContract.Ledger.GetBlock(_neoSystem.StoreView, index); + else if (UInt256.TryParse(indexOrHash, out var hash)) + block = NativeContract.Ledger.GetBlock(_neoSystem.StoreView, hash); + else + { + ConsoleHelper.Error("Enter a valid block index or hash."); + return; + } + + if (block is null) + { + ConsoleHelper.Error($"Block {indexOrHash} doesn't exist."); + return; + } + + DateTime blockDatetime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + blockDatetime = blockDatetime.AddMilliseconds(block.Timestamp).ToLocalTime(); + + ConsoleHelper.Info("", "-------------", "Block", "-------------"); + ConsoleHelper.Info(); + ConsoleHelper.Info("", " Timestamp: ", $"{blockDatetime}"); + ConsoleHelper.Info("", " Index: ", $"{block.Index}"); + ConsoleHelper.Info("", " Hash: ", $"{block.Hash}"); + ConsoleHelper.Info("", " Nonce: ", $"{block.Nonce}"); + ConsoleHelper.Info("", " MerkleRoot: ", $"{block.MerkleRoot}"); + ConsoleHelper.Info("", " PrevHash: ", $"{block.PrevHash}"); + ConsoleHelper.Info("", " NextConsensus: ", $"{block.NextConsensus}"); + ConsoleHelper.Info("", " PrimaryIndex: ", $"{block.PrimaryIndex}"); + ConsoleHelper.Info("", " PrimaryPubKey: ", $"{NativeContract.NEO.GetCommittee(_neoSystem.GetSnapshot())[block.PrimaryIndex]}"); + ConsoleHelper.Info("", " Version: ", $"{block.Version}"); + ConsoleHelper.Info("", " Size: ", $"{block.Size} Byte(s)"); + ConsoleHelper.Info(); + + ConsoleHelper.Info("", "-------------", "Witness", "-------------"); + ConsoleHelper.Info(); + ConsoleHelper.Info("", " Invocation Script: ", $"{Convert.ToBase64String(block.Witness.InvocationScript.Span)}"); + ConsoleHelper.Info("", " Verification Script: ", $"{Convert.ToBase64String(block.Witness.VerificationScript.Span)}"); + ConsoleHelper.Info("", " ScriptHash: ", $"{block.Witness.ScriptHash}"); + ConsoleHelper.Info("", " Size: ", $"{block.Witness.Size} Byte(s)"); + ConsoleHelper.Info(); + + ConsoleHelper.Info("", "-------------", "Transactions", "-------------"); + ConsoleHelper.Info(); + + if (block.Transactions.Length == 0) + { + ConsoleHelper.Info("", " No Transaction(s)"); + } + else + { + foreach (var tx in block.Transactions) + ConsoleHelper.Info($" {tx.Hash}"); + } + ConsoleHelper.Info(); + ConsoleHelper.Info("", "--------------------------------------"); + } + } + + [ConsoleCommand("show tx", Category = "Blockchain Commands")] + public void OnShowTransactionCommand(UInt256 hash) + { + lock (syncRoot) + { + var tx = NativeContract.Ledger.GetTransactionState(_neoSystem.StoreView, hash); + + if (tx is null) + { + ConsoleHelper.Error($"Transaction {hash} doesn't exist."); + return; + } + + var block = NativeContract.Ledger.GetHeader(_neoSystem.StoreView, tx.BlockIndex); + + DateTime transactionDatetime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + transactionDatetime = transactionDatetime.AddMilliseconds(block.Timestamp).ToLocalTime(); + + ConsoleHelper.Info("", "-------------", "Transaction", "-------------"); + ConsoleHelper.Info(); + ConsoleHelper.Info("", " Timestamp: ", $"{transactionDatetime}"); + ConsoleHelper.Info("", " Hash: ", $"{tx.Transaction.Hash}"); + ConsoleHelper.Info("", " Nonce: ", $"{tx.Transaction.Nonce}"); + ConsoleHelper.Info("", " Sender: ", $"{tx.Transaction.Sender}"); + ConsoleHelper.Info("", " ValidUntilBlock: ", $"{tx.Transaction.ValidUntilBlock}"); + ConsoleHelper.Info("", " FeePerByte: ", $"{tx.Transaction.FeePerByte}"); + ConsoleHelper.Info("", " NetworkFee: ", $"{tx.Transaction.NetworkFee}"); + ConsoleHelper.Info("", " SystemFee: ", $"{tx.Transaction.SystemFee}"); + ConsoleHelper.Info("", " Script: ", $"{Convert.ToBase64String(tx.Transaction.Script.Span)}"); + ConsoleHelper.Info("", " Version: ", $"{tx.Transaction.Version}"); + ConsoleHelper.Info("", " BlockIndex: ", $"{block.Index}"); + ConsoleHelper.Info("", " BlockHash: ", $"{block.Hash}"); + ConsoleHelper.Info("", " Size: ", $"{tx.Transaction.Size} Byte(s)"); + ConsoleHelper.Info(); + + ConsoleHelper.Info("", "-------------", "Signers", "-------------"); + ConsoleHelper.Info(); + + foreach (var signer in tx.Transaction.Signers) + { + if (signer.Rules.Length == 0) + ConsoleHelper.Info("", " Rules: ", "[]"); + else + ConsoleHelper.Info("", " Rules: ", $"[{string.Join(", ", signer.Rules.Select(s => $"\"{s.ToJson()}\""))}]"); + ConsoleHelper.Info("", " Account: ", $"{signer.Account}"); + ConsoleHelper.Info("", " Scopes: ", $"{signer.Scopes}"); + if (signer.AllowedContracts.Length == 0) + ConsoleHelper.Info("", " AllowedContracts: ", "[]"); + else + ConsoleHelper.Info("", " AllowedContracts: ", $"[{string.Join(", ", signer.AllowedContracts.Select(s => s.ToString()))}]"); + if (signer.AllowedGroups.Length == 0) + ConsoleHelper.Info("", " AllowedGroups: ", "[]"); + else + ConsoleHelper.Info("", " AllowedGroups: ", $"[{string.Join(", ", signer.AllowedGroups.Select(s => s.ToString()))}]"); + ConsoleHelper.Info("", " Size: ", $"{signer.Size} Byte(s)"); + ConsoleHelper.Info(); + } + + ConsoleHelper.Info("", "-------------", "Witnesses", "-------------"); + ConsoleHelper.Info(); + foreach (var witness in tx.Transaction.Witnesses) + { + ConsoleHelper.Info("", " InvocationScript: ", $"{Convert.ToBase64String(witness.InvocationScript.Span)}"); + ConsoleHelper.Info("", " VerificationScript: ", $"{Convert.ToBase64String(witness.VerificationScript.Span)}"); + ConsoleHelper.Info("", " ScriptHash: ", $"{witness.ScriptHash}"); + ConsoleHelper.Info("", " Size: ", $"{witness.Size} Byte(s)"); + ConsoleHelper.Info(); + } + + ConsoleHelper.Info("", "-------------", "Attributes", "-------------"); + ConsoleHelper.Info(); + if (tx.Transaction.Attributes.Length == 0) + { + ConsoleHelper.Info("", " No Attribute(s)."); + } + else + { + foreach (var attribute in tx.Transaction.Attributes) + { + switch (attribute) + { + case Conflicts c: + ConsoleHelper.Info("", " Type: ", $"{c.Type}"); + ConsoleHelper.Info("", " Hash: ", $"{c.Hash}"); + ConsoleHelper.Info("", " Size: ", $"{c.Size} Byte(s)"); + break; + case OracleResponse o: + ConsoleHelper.Info("", " Type: ", $"{o.Type}"); + ConsoleHelper.Info("", " Id: ", $"{o.Id}"); + ConsoleHelper.Info("", " Code: ", $"{o.Code}"); + ConsoleHelper.Info("", " Result: ", $"{Convert.ToBase64String(o.Result.Span)}"); + ConsoleHelper.Info("", " Size: ", $"{o.Size} Byte(s)"); + break; + case HighPriorityAttribute p: + ConsoleHelper.Info("", " Type: ", $"{p.Type}"); + break; + case NotValidBefore n: + ConsoleHelper.Info("", " Type: ", $"{n.Type}"); + ConsoleHelper.Info("", " Height: ", $"{n.Height}"); + break; + default: + ConsoleHelper.Info("", " Type: ", $"{attribute.Type}"); + ConsoleHelper.Info("", " Size: ", $"{attribute.Size} Byte(s)"); + break; + } + } + } + ConsoleHelper.Info(); + ConsoleHelper.Info("", "--------------------------------------"); + } + } + + [ConsoleCommand("show contract", Category = "Blockchain Commands")] + public void OnShowContractCommand(string nameOrHash) + { + lock (syncRoot) + { + ContractState contract = null; + + if (UInt160.TryParse(nameOrHash, out var scriptHash)) + contract = NativeContract.ContractManagement.GetContract(_neoSystem.StoreView, scriptHash); + else + { + var nativeContract = NativeContract.Contracts.SingleOrDefault(s => s.Name.Equals(nameOrHash, StringComparison.InvariantCultureIgnoreCase)); + + if (nativeContract != null) + contract = NativeContract.ContractManagement.GetContract(_neoSystem.StoreView, nativeContract.Hash); + } + + if (contract is null) + { + ConsoleHelper.Error($"Contract {nameOrHash} doesn't exist."); + return; + } + + ConsoleHelper.Info("", "-------------", "Contract", "-------------"); + ConsoleHelper.Info(); + ConsoleHelper.Info("", " Name: ", $"{contract.Manifest.Name}"); + ConsoleHelper.Info("", " Hash: ", $"{contract.Hash}"); + ConsoleHelper.Info("", " Id: ", $"{contract.Id}"); + ConsoleHelper.Info("", " UpdateCounter: ", $"{contract.UpdateCounter}"); + ConsoleHelper.Info("", " SupportedStandards: ", $"{string.Join(" ", contract.Manifest.SupportedStandards)}"); + ConsoleHelper.Info("", " Checksum: ", $"{contract.Nef.CheckSum}"); + ConsoleHelper.Info("", " Compiler: ", $"{contract.Nef.Compiler}"); + ConsoleHelper.Info("", " SourceCode: ", $"{contract.Nef.Source}"); + ConsoleHelper.Info("", " Trusts: ", $"[{string.Join(", ", contract.Manifest.Trusts.Select(s => s.ToJson()?.GetString()))}]"); + if (contract.Manifest.Extra is null) + { + foreach (var extra in contract.Manifest.Extra.Properties) + { + ConsoleHelper.Info("", $" {extra.Key,18}: ", $"{extra.Value?.GetString()}"); + } + } + ConsoleHelper.Info(); + + ConsoleHelper.Info("", "-------------", "Groups", "-------------"); + ConsoleHelper.Info(); + if (contract.Manifest.Groups.Length == 0) + { + ConsoleHelper.Info("", " No Group(s)."); + } + else + { + foreach (var group in contract.Manifest.Groups) + { + ConsoleHelper.Info("", " PubKey: ", $"{group.PubKey}"); + ConsoleHelper.Info("", " Signature: ", $"{Convert.ToBase64String(group.Signature)}"); + } + } + ConsoleHelper.Info(); + + ConsoleHelper.Info("", "-------------", "Permissions", "-------------"); + ConsoleHelper.Info(); + foreach (var permission in contract.Manifest.Permissions) + { + ConsoleHelper.Info("", " Contract: ", $"{permission.Contract.ToJson()?.GetString()}"); + if (permission.Methods.IsWildcard) + ConsoleHelper.Info("", " Methods: ", "*"); + else + ConsoleHelper.Info("", " Methods: ", $"{string.Join(", ", permission.Methods)}"); + ConsoleHelper.Info(); + } + + ConsoleHelper.Info("", "-------------", "Methods", "-------------"); + ConsoleHelper.Info(); + foreach (var method in contract.Manifest.Abi.Methods) + { + ConsoleHelper.Info("", " Name: ", $"{method.Name}"); + ConsoleHelper.Info("", " Safe: ", $"{method.Safe}"); + ConsoleHelper.Info("", " Offset: ", $"{method.Offset}"); + ConsoleHelper.Info("", " Parameters: ", $"[{string.Join(", ", method.Parameters.Select(s => s.Type.ToString()))}]"); + ConsoleHelper.Info("", " ReturnType: ", $"{method.ReturnType}"); + ConsoleHelper.Info(); + } + + ConsoleHelper.Info("", "-------------", "Script", "-------------"); + ConsoleHelper.Info(); + ConsoleHelper.Info($" {Convert.ToBase64String(contract.Nef.Script.Span)}"); + ConsoleHelper.Info(); + ConsoleHelper.Info("", "--------------------------------"); + } + } } } diff --git a/src/Neo.CLI/neo.ico b/src/Neo.CLI/neo.ico index 60786c424d8ec4c41a72a023d1aead2a8995a515..403aa7f3764f3dd49f9edd8e93302bf24cc35fcf 100644 GIT binary patch literal 105486 zcmeI52V4}#7su!BfI~#V4i>O$u%Tdy4QyZuHZU3!do*fdi-w3%0Y$|wh)A(uLm@^i z(TENHQH;GCjTNN`SimTX1@8ZQd$-3y5Dw&klid$rX7_e?_RV{5W@lz+b{P{fDWgTi zYBT+Ej5%Z7%}u`DSYO2E;x}7c#dcT5f~$y_rKNm(M+3$#491zY72C!*e~yTmn8>$1 z%P?lPLd1;mJH(#USK-x>_>mm5&#~tGsGrZWVdl#pf z>z>{nw(5G^oXF?N(_i&)Z#ZzgepAn0R{jTOj`}X4N_fcfkV*FS<~<2={-ch*$N0ZP zt~T_KpXYblA=v7`uJhg9=QXcjSho2%|MAOi)mT6Lvh~$6y{-m(Mo-?{Wx$r*kDs~B z+OuldaPhkzFSukp>UjU+wpNEDrrina{GIDXnUQz>UU~h64DFgE(mC?#`~t(a_xp~l z(6aLd?~Cb;Q+uA7FX|b0>OzwVwcb{)GlMl*{QDPahZngI53u`XNZK1&AL~u6MzV>M zM&AB$ba)yG|`LI?x z&!s0W9sfGwUF91Gj0VrJ8+)2Lo%LEjeS+!Rm;SOSS^YKX-_7yvX;bIrr2`LKx_VZ5 zf9s5=Xvfxre=K%ieWTKtM()=mpH!cHV~nkN%V#OayE&{8?eO^DZ#M=8OCGi#+2zk( z<-0xEH1=i7s&~?tdQ9KZ*TgNc{j1-itXto;TlU!P@xYbSH&~gQoirO7@H%BvYVuaI zo>AYj;DWn|Y1NYB?3=!K29Dl6 zNq1~}{X3%feUrS#MeBH_``qktJGh#o(UzBnkyEVFQd*taR4dJJs>8zxp%1o4{@l3j zoWNg`-`>A=ym2{+<>ft3UyQGQbh%0UI&<_JwUXv)ez0H9zVd z7&yxFV#UM;9&?)BdpSJG-D%hxy^#}}guf|sq=$cU#nCM$y*Oq+-rS*+w?&IEX81$I z!ghO|7d8q1ynXqOW#a6=I`U>w$f5yp)^l0tVeh~#djgki`*%yzTkn5N8f9&@{LS&H z&w4+b6uI+Sz1Bg`$8Kq|aKp&CH*SYWuUu>WC0nu&m%nPfvED+nx&ITbU7lp0E{#q* z(7@+m(!5=<@d*xfkNVt<+Pu7li{qY~NmeX199P(4yrK5q`3-8g`pz;LwqvgN(hvw! z{p&Up4f>@#C>QZXr)4KA+pzgxhi$8QxJ<9Nl~JGd;ICIM{88O~Wsk6VNg2i&Gp96} ze*d7CaeL1@;@`haefL?l&Q*_g4Xxz%e0uuOZ%z;Tsn-16HSC=CroE7@pXE2pF`U)B zf55|XRwIv}BF&wiJnp^v(U{BI$Bz@WyPV#o@BUpcLw_?E_da;^i&K-~X^*c-s$9S3 zIx@z$qGYM;$++Qg!`injJH%kr zXD_~f#2PsoIn`gA(Q@t^uO7cIbRPYL`Q8{;KcwzSvoY}_1Pg!9KL8@dfNakXqb%Dm5oV+&@E zxw7fUZ<$k{F@K~61e&E@j*c41oF~-1agr-yKYTXvIQ(p0By%8{cX6 z`1B6&wm4IE{#rlxt8MPyrS4IWfku;Rl;37%4>_yfp5S>AI-1|v!M<86w*2(=#PI_S zZDZOQJSbxq)5dr5TbHC!PUeQTb2{|edVj>-35N`A(@k9i`ld{1A7Co!Z*y|)Pd6(6 zym#u0?~&ogShA>B7Q63P`zCa#q3!c8X8vzmzpDd&GIblBqPw>DpKNPtrI9U^Inl>l z(*KuZ(E}HZViS?meO#7Bg>{YzAKnAo+uo%AwBhL>>uuL0J$wJfdYW3XfhP^!d|FCs zk3A=BX4A&^eLK0iH9CA)|AB=`;-kMK(l1_%X>6_+q%U^WpJrt}XZf*bH{6mdb+f6r zZTp0XcQ-=*a*S!kqV}nRQ2|F}U{&k(88929zEP2I;DA3Nc`X!w?}+gs+1JHf8CSZNT@QgX?p zqs4ewe@wtkr?duh?q00e&1QOE*OfJ78F#N84`~PIdT06FN`vHK4+eC3WXW8f?+BW1 z;&#Nv>C`&WrLU^lSokEw`L;0JYS#DqD0q5|{eo6w>~%-CxODN%E?LTsOYIEZ8jdmb zXck$ue8-mtbBsE5^OU;0kl2j8d+2J&qN^{FZ>|sYtg-lqZ=ZG8p72YGOVGxFi9z-Y z-Xd>R+E@FI&YkX``zAilsB>ceOs5?+^laA*6#I4?a^a2rf-g73g&kTr&}c_lQ#R;q z+JI4>uMvT6M~liUME#qcd$ptg7kak)oiheJXgtSg&iyT2tLxc@42v01rc8nx0~(o4EX9u;?fh%MvTMF*sFEq`pEa!=J&cf!_U^}_>-XYdp8`79A}K#DDrrB zHgaj?()aydSM$I7_L0Y>F0oaETF1Fvsc&d})84<<&ZM^kl13$+USKYsd*pll1nJw) z_fBu#tlP$h9_6D~+wOQi`%08+t+Qq%-WSiFakp2HG~vPZ zDZ?Gcf7OF3786^pn^9p=?a2++-8cCmZ_8fjnMmM_Uo3>U81|_{V}|ce|b+= zNzTZDK+zfL`xIek|pE$Q$*c0l~K>CL(2rhVJYBQ^4`U;j;aT6xdoQlF;D zqpu%r5p33Q@b!qYmz-}5h^`UY*5u}abwi%%{4FjUnsIcH_2frYzL?ZPvVT%Lotkx@ z9bKuYw&9K#aADKX=^es?uH4Zxe7YradgSzV3C9*W{???-PWO~*r^gN47QTM4^onfv z`Q%xF`_9^hz5l+(`7Pg{d{+NNzpZ8tjc|gHC=Q@ZoV_w;?Vl-eNMGtm0G`Y=<&yk8DF_bM{YiOFeJfwL+}ZU|sJ*-Gf;z18BKt6TZFic`;2h(Zg8_3F{L`>w7d=QYN<8~uRh z54DekMbLnt0YL+T1_TWV8W1!fXh6__paDSxf(8T)2pSMHAZS3)fS>_E1A+zw4U|+3 ztbN3oe;kvndzdMq_iiRyxr-a*llh~t_Q`0#`!-{Ku}mBg!^*?gB9Qocneao52OC%3+&zxyalP?2p9)HFhwZw z`HeqH2(>{2t7A~U$1=TuIMxJqo((R7G>`#g3UadlJJ?&M;61{}U<>HuwTBt{>|x@) zd$mCWrBBAdc*X+anGUE4`%VN$Kq^qRId6Lk^Rhqh2NY7da0@I(nP7!bx@>pp({V{l z@jB#lB5c~6fKw&ya2ET&A@Bt$rb_*>cMU=A3_{K32>@7uJ zZ;j9sw*Cja$*0W=)BdWyK=p4;Ah+$>I2>F$39vWr6vNj$r$pt4yX=0j{yh4OQ6m@JujQ9 z?$?CvX%@28BdjYHo|EHg&=J^;2322a3yplY+i zT-UVyRegclk_o^McH01z;W;j z6h=KxTkX&L0fmLu*J#a{v^8Um!DmGXO%utotcm05aT4^$Re_yHfZgCMpKko|#>T87kTfpvVKvsmj z%=V1!9&Ap}*a~W!qByU(>VLd_^AoDw*H~Qkhpo?n?9bSW!j1*KhBnz>)mNymF&ZrO z+Qk~J$kyLnjP|EKnu6M*IL^~H`}2K^*I|1vuQ1jdeFO zLfJ2r|CwWlRPWb$t!FRS`@q%}U~`?Fk;-hX_6pkntQ}+GqDHX4a@<&6_NM*$F4xs| zfMPmOuz#NRS1s2^=eJxhCbO!2S;7AQv45eK>uMXKm<|-|&)J_Z*N>x&pUv0TQI8XE z+*nM8DWc1kV*68nOcK}$#)7&)Z?&5B^&&El#xGNf?9Z3$|G>^Zpr04&>ln|W6H|} zMaI&AsDk}9pj0i2Qn0@k8A}7A3ij84Qne^b!TwrgEDeY%*k1!m)uJc``)iT0G$5*A ze+?*Ai=q_luSLevfT)7~HK0^2ic+w@78y$eq6+rcfKs(6O2PhGWGoGcD%f8GO4Xt$ z1^a7}u{0p6V1ErLRg0n&?5{<}(txOf{WYLeEs9dGzZMxw1ELD{*ML&BC`!TpT4XE@ zh$`4$14`ARCH16zs1>#?pYOg8en1R4s~9u)h`=O9P?`_Sb+? zwJ1u#{#s-#4Tvh(Ujs_jq9_IXYmu=uAgW-04JcKMq7>|}MaI&AsDk}9pj0i2Qn0@k z8A}7A3ij84Qne^bt+YSBP3ZMZieKhDe@o<3D}>oK@QK-<_X7&4otJ<`n>+hhGXy64p0{wtbxGjnF3HFc6@!QjUTk0`2yvWgJ2ZujMb4|GF2(g4q-O5AhFjrY+H9LvPO7_vHoP>>ABmjz!a93Ale&a=_SSetZS5*PR< zgRknq?lr;pAOcW7Dc$1)UnrOkNOz>eR%30ZZlEnD=wG!V~Ck(TbjAH)NpuJB(!$m~CkWwz_%S(&w3 z)+Wr&C+WV0cCG|egg*~~5BvsFKxwWkP@fPt77=sji^f&ocvQ zs}H+>a?ga+vG<3LnfZb-VzCt-x5&feQ@27k!gs?C)K=}ywO?~LN9astOgW{?y zkpHEEV_*U>13GB435$j`!1X)h**Wg1i^O#~XL5aES>KL>k_E z1A+zw4G0<#G$3d|(14%;K?8yY1PurpC;|=0v~hWDlU3^ZMp?GsOGH_=QzR_Q32qXm zdcu1qVX7xYV_WqEM%z+ljPJSa%oC!y?aUKkG#sxyAx*K(pAf0o=1;&TcRWs@U39p7 zTf}YCZ}M$s!>wm-OS5fD^4K=Yw%;}Dwp13)6bs3(kdOO?wiWU#x6S1WQEn^r!*BEY z;_E1Deu+SciMx4!v7L40Kk9Gv*z}bbttavJ28m^Tlbr z7QIK}bFc)AU4001tissOzy&l0dfvMkTN$eTs!)toq%_mqXba#1&H(U_@m&x%mxF(gP%WgD=5rhZ^gWL3b3awnFGHGn-eEls1Oj_d z4v1IpDw%o^>nhTWcVi%pmBAno0_eRExy@(#Q2Kd2P?!d;f_b0?kOGkx{GzxQ@^7S% z%CT~w2UrUp0Cnf{sgr(Q7a2(R3vd*SN4}_qP{$iSAu7WBfijHVmqvM--koO+7J%!Z zAoE%ClYU+g6ut+EU@PbcjDdLd9yDgS{+q0xVU5k!P!kXr1n=A2{9Up&&68^grUM#l z|FLtl3YvaZUA#fsZ-FJCEhq!u5RoqUr7hClhKUA%6<}pPS%`GfytL7P=9CoX`)&#& z{k$$Hf24vaFcs7TI$p>hNWU0q_68Y1mQUzifOkP|D6RF|?^9mdKc?P97wDAGR_X*p2<4wk_5ldn_0 zj{)1j2v8eHDeqI7RhKr{K)Q8+v>=p_^pjt|0++!G&8uzgAa^noK|D{+IaqdP4d&SN{?0FZjQ@ z4%+X34^e~i1R zfKZJ0`Y{?qSCk8`TO8?E)dh{GxdZ6kwH<%~-l1J&`2*K0?)3Az;NSCj8Zyy)e+Un3NI7A0`MTC^rketU$b)8vmi1o{w3lcf!Vl^`Iwo zQ6Bk&#-$a?f_P~B&$ocaLgX}#@nd8!>~m=x+TXwfG)8&((e>-q$Xn!Bh>st~`U}?S z{pqg(<;lWMLqX#sSx6@OzQio}Kt1}VWnnIelk`C2|H^{Szzf_1>W+CVXxef+kKT`c z3oHj6;Qt2n9UgxT)}QDejO)-iU&?0{fg{)f@*4A+TRQTykI(ZPaZLwc40(#BexMxl zEU&AXL6(W&7@)db2FOpkayypFeELSo9xxnGnXf}WSyI|hcwaYt_lFIWz(dHMrM`RJb&^9T5{LWg{NLeNJ?D?}h@K+u4o0YL+WqyhEc zV(`XBer%-t4GkHJmt){H4&07N`KxgbkM z6?!2Bg%mFW?xhR}&9O<_6qLl!Tp<@PFDEGE~z7zBT(l#PdEy#TVs59^OIb?oPK)Ly}6-0iTS4lRY^2!ek0JSi0n*64k zLht7g=EX6{{^O8_D(Jsp-Y58v;6DZP9Qj#-{|Npg_)me_jmq|ymfycFLjKmk z0PuYooJ&ZJKE^ZDI~Ujd*!ClhE4c=!FW^g1UC~#^Xbd^G@Xu4!6DeOu;d&n{KkrA> zA4g-3FN0Np-WN(X5h=!;{r5Rhz9h~0V8mZo^7HASkkUfqz>a`%;4@GTP#+oRV>wHc z|6dWGCgfL53-yED1Dn7oK;u`aPn91Fn17*F&OkhxmY+`xrGsp86RZbz@GG*3nDeg! zwtsLw**FQj2mG}(9a37TzmNK|X8=o30f_w`s3=#BRh(lCsPB{JWt{}{en(BqpFRFF zxaJ@rrMVvYS#S{`f=?6jk${jR5p^XvS06Gw<&-B3nIV-&=eS<+%0fP+uBi? z4k{z4ADz-N9vlLc78>vSF>;g4H1>|}cgsP0K;- z6xX8nAX8eXjL%OxDBUEp7Z?akfiiv?Po{~b8XkaCxj^?&8c&XEl1-`s(i`QKe*npr z-M?s?{4N1(2K_*7KzdNhtqGa)ic{tK60BDSL%?s~9-y)@4jcnC=C&@NJjLC!JkKNc z0(*B}lBvJHS0^*i(+WUe-cRJkg#yaBQ#fx zisItqHW80;v5dE+EAWG zMO}vOk5mVsx>OIa3_Ji-M|_U!_rx{no#OO7^f}l827$UjO7GvNcZ@GrdH-;0cwcUK z-%_TN#QdC2%VTF5%kLUg6W2Tlk^tzr=O!fPH}8H{Jy30@2J>+_(dJ-@G2k@qOC` zygupqAFvcSfcn6Y{0|}LgA^K9rLju6j~mF>^<%iP72^?i4^S3}-255q`VsjrU)M*T zT#j$yP};b>RtV)!ey_jaOb&&}NBksQKOgxI_80X35zdywse=Eh?SFJ{oC_L(EPWOg z%yUqznm^@3|8#GnF{5|EuV5&kK1$Iq;kZ}<+wwSH-TPnmdn4Vmsn6IAP`!ofXMJx>G78KCpP_$BvIyn0-K4yw!13$A4Nw^UyCe&Z-3$d^fU*lu z<}L${p?;b=z!7W#)DQTfIvAhk4~4ugHX)8)z`*{8+^{>SLtwz0@aX z4UAXck)KcT6vi?G^$bOyts&wc0BBzFX%GOq11bkZ?*GHp3Yh=$lG8UDGEhG&@)WM6 z52^s_bLIPAS;abe#UkwgkOt)a2l#)SrijsWF>{%lasnQmMTRx!dK&0+*LlMAa=7An z>dlY<>dK&Q9*OKdb!E7@%49LhtIDXK!UR}?g7i}~?9BNE^M8OkG1`5!6vnq;tWl@; zxu=Mm{OJ+J~50N0=4h4w@n zY0m8>#6f)my#YOMxeVyJ0AC)xNBk5YwSD>aFpcqk2xtz#XwYay2-9yP7Bxa!a2Ob_ zUa67vKh;-)0o5639+rdbcIson&X-)~iK2DDcyHR;pA5fj0+7Eo1$OfdF>%a|k z1=WEr;Lgt}Zq?t6YRb11$J0HM>Uxa<*)#|Y1Ju?cebavKzG_fKH5N7274=oFe#xgz zMb6cC8Kb$mg|U3`lR|fj>rkJ2eizi3n9N4TQlv5#$yKRTVxVf4Il%rLQC7uVagq&3 zG~!6Zd9nx~lQF7?8H3tD-FjH1x{7vFH10Qh7#lwqbrY(bzjrw_6n`9(wA z8$03NNb{2_1Fnu$194Max`;~^98dm0J~bNb1W$2(5YDImV49yr-;L`E4DcL6)JDSf zJuBzD;rKNm7SLD>$^#iVe>2XfbE!^|4qkwrxF=h*)fN4S`}`pVyKsE=a)LkqI?lNa zRsxzIRt4uv+Ujuq-iA1zBggY&**foi%o6961!BNz)`wrCVyv2WTF>$PIOdPvB{iYj zy!4;j`MH=)xl2Rm2OwVVolljJhTN7Mu1_|+38)=R^D+C4n}~Qfbs{c)iUSws|rK-6hz|~I`{v14>Df> literal 21317 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 diff --git a/src/Neo.GUI/Neo.GUI.csproj b/src/Neo.GUI/Neo.GUI.csproj index 7a7193ea30..3921bb12b1 100644 --- a/src/Neo.GUI/Neo.GUI.csproj +++ b/src/Neo.GUI/Neo.GUI.csproj @@ -9,8 +9,13 @@ Neo true Neo.GUI + neo.ico + + + + DeveloperToolsForm.cs diff --git a/src/Neo.GUI/neo.ico b/src/Neo.GUI/neo.ico new file mode 100644 index 0000000000000000000000000000000000000000..141d11d686a2a1fe3bb2d9dbd81d5b477c99ef32 GIT binary patch literal 370070 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 literal 0 HcmV?d00001 From d5b102a5ba9532a11e4a6fc72c088694e3834e5f Mon Sep 17 00:00:00 2001 From: Ricardo Prado <38396062+lock9@users.noreply.github.com> Date: Wed, 6 Dec 2023 22:47:08 -0300 Subject: [PATCH 3/3] Update README.md --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 4c80cc59c2..8f64dcc854 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,6 @@ Neo Modules · Neo DevPack - · - Neo Node

@@ -128,7 +126,6 @@ An overview of the project folders can be seen below. Code references are provided for all platform building blocks. That includes the base library, the VM, a command line application and the compiler. * [neo:](https://github.com/neo-project/neo/) Neo core library, contains base classes, including ledger, p2p and IO modules. -* [neo-node:](https://github.com/neo-project/neo-node/) Executable version of the Neo library, exposing features using a command line application or GUI. * [neo-modules:](https://github.com/neo-project/neo-modules/) Neo modules include additional tools and plugins to be used with Neo. * [neo-devpack-dotnet:](https://github.com/neo-project/neo-devpack-dotnet/) These are the official tools used to convert a C# smart-contract into a *neo executable file*.