Browse Source

Refactor: remove UI-tier / processing-tier code overlap

Herman Schoenfeld 7 years ago
parent
commit
4630395887
35 changed files with 1043 additions and 939 deletions
  1. 3 154
      src/core.utils/UCoreObjects.pas
  2. 26 668
      src/core.utils/UCoreUtils.pas
  3. 16 16
      src/core.utils/UDataSources.pas
  4. 7 7
      src/gui-classic/UGridUtils.pas
  5. 1 0
      src/gui/UCTRLBanner.lfm
  6. 4 2
      src/gui/UCTRLBanner.pas
  7. 2 1
      src/gui/UCTRLSyncronization.lfm
  8. 2 2
      src/gui/UCTRLSyncronization.pas
  9. 1 0
      src/gui/UCTRLWallet.lfm
  10. 21 12
      src/gui/UCTRLWallet.pas
  11. 1 1
      src/gui/UCellRenderers.pas
  12. 17 13
      src/gui/UFRMExecuteOperations.lfm
  13. 54 7
      src/gui/UFRMExecuteOperations.pas
  14. 3 3
      src/gui/wizards/operations/UWIZChangeKey.pas
  15. 2 2
      src/gui/wizards/operations/UWIZChangeKey_EnterKey.pas
  16. 2 2
      src/gui/wizards/operations/UWIZChangeKey_SelectKey.pas
  17. 3 2
      src/gui/wizards/operations/UWIZChangeKey_SelectOption.pas
  18. 4 3
      src/gui/wizards/operations/UWIZEnlistAccountForSale.pas
  19. 3 2
      src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterLockingBlock.pas
  20. 3 2
      src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterPublicKey.pas
  21. 3 2
      src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterSaleAmount.pas
  22. 2 2
      src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterSeller.pas
  23. 2 2
      src/gui/wizards/operations/UWIZEnlistAccountForSale_SelectOption.pas
  24. 825 0
      src/gui/wizards/operations/UWIZOperation.pas
  25. 7 7
      src/gui/wizards/operations/UWIZOperationConfirmation.pas
  26. 3 2
      src/gui/wizards/operations/UWIZOperationFee_Custom.pas
  27. 2 2
      src/gui/wizards/operations/UWIZOperationPayload_Content.pas
  28. 7 7
      src/gui/wizards/operations/UWIZOperationPayload_Encryption.pas
  29. 2 2
      src/gui/wizards/operations/UWIZOperationPayload_Password.pas
  30. 4 4
      src/gui/wizards/operations/UWIZOperationSelected.pas
  31. 2 2
      src/gui/wizards/operations/UWIZOperationSigner_Select.pas
  32. 3 3
      src/gui/wizards/operations/UWIZSendPASC.pas
  33. 3 2
      src/gui/wizards/operations/UWIZSendPASC_EnterQuantity.pas
  34. 2 2
      src/gui/wizards/operations/UWIZSendPASC_EnterRecipient.pas
  35. 1 1
      src/pascalcoin_wallet.lpi

+ 3 - 154
src/core.utils/UCoreObjects.pas

@@ -28,145 +28,9 @@ type
     TotalPASA : Cardinal;
     TotalPASA : Cardinal;
   end;
   end;
 
 
-  { TExecuteOperationsModel }
+  { TBlockSummary }
 
 
-  TExecuteOperationsModel = class(TComponent)
-    public
-      type
-
-      { TExecuteOperationType }
-
-      TExecuteOperationType = (omtAccount, omtSendPasc, omtChangeKey, omtTransferAccount, omtChangeAccountPrivateKey, omtAddKey, omtEnlistAccountForSale);
-
-      { TPayloadEncryptionMode }
-
-      TPayloadEncryptionMode = (akaEncryptWithSender, akaEncryptWithReceiver, akaEncryptWithPassword, akaNotEncrypt);
-
-      { TOperationSigningMode }
-
-      TOperationSigningMode = (akaPrimary, akaSecondary);
-
-      { TChangeKeyMode }
-
-      TChangeKeyMode = (akaTransferAccountOwnership, akaChangeAccountPrivateKey);
-
-      { TSendPASCMode }
-
-      TSendPASCMode = (akaAllBalance, akaSpecifiedAmount);
-
-      { TAccountSaleMode }
-      TAccountSaleMode = (akaPublicSale, akaPrivateSale);
-
-      { TOperationExecuteResultHandler }
-
-      TOperationExecuteResultHandler =
-      procedure(const ASourceAccount: TAccount; AOpType: TExecuteOperationType; const AOpText: ansistring; Result: boolean; const Message: ansistring) of object;
-
-
-      { TAccountModel }
-
-      TAccountModel = class(TComponent)
-      public
-        SelectedAccounts: TArray<TAccount>;
-      end;
-
-      { TSendPASCModel }
-
-      TSendPASCModel = class(TComponent)
-      public
-        SingleAmountToSend: int64;
-        DestinationAccount: TAccount;
-        SendPASCMode: TSendPASCMode;
-      end;
-
-      { TChangeKeyModel }
-
-      TChangeKeyModel = class(TComponent)
-      public
-        ChangeKeyMode: TChangeKeyMode;
-      end;
-
-      { TTransferAccountModel }
-
-      TTransferAccountModel = class(TComponent)
-      public
-        AccountKey: TAccountKey;
-      end;
-
-      { TChangeAccountPrivateKeyModel }
-
-      TChangeAccountPrivateKeyModel = class(TComponent)
-      public
-        SelectedIndex: integer;
-        NewWalletKey: TWalletKey;
-      end;
-
-      { TWIZEnlistAccountForSaleModel }
-      TEnlistAccountForSaleModel = class(TComponent)
-      public
-        SalePrice: int64;
-        NewOwnerPublicKey: TAccountKey;
-        LockedUntilBlock: cardinal;
-        SellerAccount: TAccount;
-        AccountSaleMode: TAccountSaleMode;
-      end;
-
-      { TFeeModel }
-
-      TFeeModel = class(TComponent)
-      public
-        DefaultFee, SingleOperationFee: int64;
-      end;
-
-      { TSignerModel }
-
-      TSignerModel = class(TComponent)
-      public
-        OperationSigningMode: TOperationSigningMode;
-        SignerAccount: TAccount;
-        SignerCandidates: TArray<TAccount>;
-        SelectedIndex: integer;
-      end;
-
-      { TPayloadModel }
-
-      TPayloadModel = class(TComponent)
-      public
-        HasPayload: boolean;
-        Content, Password: string;
-        PayloadEncryptionMode: TPayloadEncryptionMode;
-        EncodedBytes: TRawBytes;
-      end;
-
-    private
-      FExecuteOperationType: TExecuteOperationType;
-      FAccount: TAccountModel;
-      FSendPASC: TSendPASCModel;
-      FChangeKey: TChangeKeyModel;
-      FTransferAccount: TTransferAccountModel;
-      FChangeAccountPrivateKey: TChangeAccountPrivateKeyModel;
-      FEnlistAccountForSale: TEnlistAccountForSaleModel;
-      FFee: TFeeModel;
-      FSigner: TSignerModel;
-      FPayload: TPayloadModel;
-    public
-      constructor Create(AOwner: TComponent; AType: TExecuteOperationType); overload;
-      property ExecuteOperationType: TExecuteOperationType read FExecuteOperationType;
-      property Account: TAccountModel read FAccount;
-      property SendPASC: TSendPASCModel read FSendPASC;
-      property ChangeKey: TChangeKeyModel read FChangeKey;
-      property TransferAccount: TTransferAccountModel read FTransferAccount;
-      property ChangeAccountPrivateKey: TChangeAccountPrivateKeyModel read FChangeAccountPrivateKey;
-      property EnlistAccountForSale: TEnlistAccountForSaleModel read FEnlistAccountForSale;
-      property Fee: TFeeModel read FFee;
-      property Signer: TSignerModel read FSigner;
-      property Payload: TPayloadModel read FPayload;
-    end;
-
-
-  { TBlockChainData }
-
-  TBlockChainData = record
+  TBlockSummary = record
     Block: cardinal;
     Block: cardinal;
     Timestamp: cardinal;
     Timestamp: cardinal;
     BlockProtocolVersion,
     BlockProtocolVersion,
@@ -196,7 +60,7 @@ const
     TotalPASA : 0;
     TotalPASA : 0;
   );
   );
 
 
-  CT_TBlockChainData_NUL: TBlockChainData = (
+  CT_BlockSummary_NUL: TBlockSummary = (
     Block: 0;
     Block: 0;
     Timestamp: 0;
     Timestamp: 0;
     BlockProtocolVersion: 0;
     BlockProtocolVersion: 0;
@@ -223,20 +87,5 @@ const
 
 
 implementation
 implementation
 
 
-constructor TExecuteOperationsModel.Create(AOwner: TComponent; AType: TExecuteOperationsModel.TExecuteOperationType);
-begin
-  inherited Create(AOwner);
-  FExecuteOperationType := AType;
-  FAccount := TAccountModel.Create(Self);
-  FSendPASC := TSendPASCModel.Create(Self);
-  FChangeKey := TChangeKeyModel.Create(Self);
-  FTransferAccount := TTransferAccountModel.Create(Self);
-  FChangeAccountPrivateKey := TChangeAccountPrivateKeyModel.Create(Self);
-  FEnlistAccountForSale := TEnlistAccountForSaleModel.Create(Self);
-  FFee := TFeeModel.Create(Self);
-  FSigner := TSignerModel.Create(Self);
-  FPayload := TPayloadModel.Create(Self);
-end;
-
 end.
 end.
 
 

+ 26 - 668
src/core.utils/UCoreUtils.pas

@@ -62,22 +62,7 @@ type
   TCoreTool = class
   TCoreTool = class
   public
   public
     class function GetSignerCandidates(ANumOps: integer; ASingleOperationFee: int64; const ACandidates: array of TAccount): TArray<TAccount>; static;
     class function GetSignerCandidates(ANumOps: integer; ASingleOperationFee: int64; const ACandidates: array of TAccount): TArray<TAccount>; static;
-  end;
-
-  { TOperationsManager }
-
-  TOperationsManager = class
-  private
-    class function UpdatePayload(const ASenderPublicKey, ADestinationPublicKey: TAccountKey; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent: string; var AEncodedPayloadBytes: TRawBytes; const APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
-
-    class function SendPASCFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalAmount, ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean; static;
-    class function OthersFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean; static;
-  public
     class function GetOperationShortText(const OpType, OpSubType: DWord): ansistring; static; inline;
     class function GetOperationShortText(const OpType, OpSubType: DWord): ansistring; static; inline;
-    class function ExecuteOperations(const ANewOps: TExecuteOperationsModel; AHandler: TExecuteOperationsModel.TOperationExecuteResultHandler; var errors: ansistring): boolean; static;
-    class function ExecuteSendPASC(const ASelectedAccounts: TArray<TAccount>; const ADestinationAccount, ASignerAccount: TAccount; AAmount, AFee: int64; const ASendPASCMode: TExecuteOperationsModel.TSendPASCMode; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean; static;
-    class function ExecuteChangeKey(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount: TAccount; APublicKey: TAccountKey; AFee: int64; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean; static;
-    class function ExecuteEnlistAccountForSale(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount, ASellerAccount: TAccount; const APublicKey: TAccountKey; AFee, ASalePrice: int64; ALockedUntilBlock: UInt32; const AAccountSaleMode: TExecuteOperationsModel.TAccountSaleMode; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean; static;
   end;
   end;
 
 
   { TOrderedAccountKeysListHelper }
   { TOrderedAccountKeysListHelper }
@@ -135,186 +120,37 @@ uses
   UMemory, UConst, UWallet, UECIES, UAES;
   UMemory, UConst, UWallet, UECIES, UAES;
 
 
 
 
-{ TOperationsManager }
+{ TCoreTool }
 
 
-class function TOperationsManager.SendPASCFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalAmount, ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean;
+class function TCoreTool.GetSignerCandidates(ANumOps: integer; ASingleOperationFee: int64; const ACandidates: array of TAccount): TArray<TAccount>;
 var
 var
-  LAuxs, LOperationsTxt: string;
-  i: integer;
+  i, PoorSenderCount: integer;
+  Fee, maxSignerFee, minSignerFee: int64;
+  acc: TAccount;
 begin
 begin
-  LOperationsTxt := AOperationsTxt;
-  if (ANoOfOperations > 1) then
-  begin
-    LAuxs := 'Total amount that dest will receive: ' + TAccountComp.FormatMoney(
-      ATotalAmount) + #10;
-    if Application.MessageBox(
-      PChar('Execute ' + IntToStr(ANoOfOperations) +
-      ' operations?' + #10 + 'Operation: ' + LOperationsTxt + #10 +
-      LAuxs + 'Total fee: ' + TAccountComp.FormatMoney(ATotalFee) +
-      #10 + #10 + 'Note: This operation will be transmitted to the network!'),
-      PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
-      idYes then
-      Exit;
-  end
-  else
-  if Application.MessageBox(PChar('Execute this operation:' +
-    #10 + #10 + AOperationToString + #10 + #10 +
-    'Note: This operation will be transmitted to the network!'),
-    PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
-    idYes then
-    Exit;
-  Result := True;
-  i := TNode.Node.AddOperations(nil, AOperationsHashTree, nil, AErrorMessage);
-  if (i = AOperationsHashTree.OperationsCount) then
-  begin
-    LOperationsTxt := 'Successfully executed ' + IntToStr(i) +
-      ' operations!' + #10 + #10 + AOperationToString;
-    if i > 1 then
-      ShowMessage(LOperationsTxt)
-    else
-    begin
-      Application.MessageBox(
-        PChar('Successfully executed ' + IntToStr(i) + ' operations!' +
-        #10 + #10 + AOperationToString),
-        PChar(Application.Title), MB_OK + MB_ICONINFORMATION);
-    end;
-  end
-  else if (i > 0) then
+  //make deep copy of accounts!!! Very Important
+  Result := TArrayTool<TAccount>.Copy(ACandidates);
+  Fee := ASingleOperationFee;
+  PoorSenderCount := 0;
+  for i := Low(Result) to High(Result) do
   begin
   begin
-    LOperationsTxt := 'One or more of your operations has not been executed:' +
-      #10 + 'Errors:' + #10 + AErrorMessage + #10 + #10 +
-      'Total successfully executed operations: ' + IntToStr(i);
-    ShowMessage(LOperationsTxt);
-  end
-  else
-    Result := False;
-end;
-
-class function TOperationsManager.UpdatePayload(const ASenderPublicKey, ADestinationPublicKey: TAccountKey; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent: string; var AEncodedPayloadBytes: TRawBytes; const APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
-var
-  LValid: boolean;
-begin
-
-  if (APayloadContent = '') then
-    Exit(True);
-
-  LValid := False;
-  AErrorMessage := 'An Error Occured During Payload Encryption.';
-
-  try
-
-    case APayloadEncryptionMode of
-
-      akaEncryptWithSender:
-      begin
-        // Use sender public key
-        AEncodedPayloadBytes := ECIESEncrypt(ASenderPublicKey, APayloadContent);
-        LValid := AEncodedPayloadBytes <> '';
-      end;
-
-      akaEncryptWithReceiver:
-      begin
-        // With destination public key
-        AEncodedPayloadBytes := ECIESEncrypt(ADestinationPublicKey, APayloadContent);
-        LValid := AEncodedPayloadBytes <> '';
-      end;
-
-      akaEncryptWithPassword:
-      begin
-        // With defined password
-        if APayloadEncryptionPassword = '' then
-        begin
-          AErrorMessage := 'Payload Encryption Password Cannot Be Empty With The Chosen Option : "Encrypt With Password."';
-          Exit(False);
-        end;
-        AEncodedPayloadBytes := TAESComp.EVP_Encrypt_AES256(
-          APayloadContent, APayloadEncryptionPassword);
-        LValid := AEncodedPayloadBytes <> '';
-      end;
-
-      akaNotEncrypt:
-      begin
-        // no encryption
-        AEncodedPayloadBytes := APayloadContent;
-        LValid := True;
-      end
-
-      else
-      begin
-        AErrorMessage := 'Unknown Encryption Selected';
-        Exit(False);
-      end;
-    end;
-
-  finally
-    if LValid then
-      if Length(AEncodedPayloadBytes) > CT_MaxPayloadSize then
-      begin
-        LValid := False;
-        AErrorMessage := Format('Payload Size Is %d Which Is Bigger Than %d', [Length(AEncodedPayloadBytes), CT_MaxPayloadSize]);
-      end;
-    Result := LValid;
+    acc := Result[i];
+    if (acc.Balance < Fee) then
+      Inc(PoorSenderCount);
   end;
   end;
-end;
 
 
-class function TOperationsManager.OthersFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean;
-var
-  LAuxs, LOperationsTxt: string;
-  i: integer;
-begin
-  LOperationsTxt := AOperationsTxt;
-  if (ANoOfOperations > 1) then
-  begin
-    LAuxs := '';
-    if Application.MessageBox(
-      PChar('Execute ' + IntToStr(ANoOfOperations) +
-      ' operations?' + #10 + 'Operation: ' + LOperationsTxt + #10 +
-      LAuxs + 'Total fee: ' + TAccountComp.FormatMoney(ATotalFee) +
-      #10 + #10 + 'Note: This operation will be transmitted to the network!'),
-      PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
-      idYes then
-      Exit;
-  end
-  else
-  if Application.MessageBox(PChar('Execute this operation:' +
-    #10 + #10 + AOperationToString + #10 + #10 +
-    'Note: This operation will be transmitted to the network!'),
-    PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
-    idYes then
-    Exit;
-  Result := True;
-  i := TNode.Node.AddOperations(nil, AOperationsHashTree, nil, AErrorMessage);
-  if (i = AOperationsHashTree.OperationsCount) then
-  begin
-    LOperationsTxt := 'Successfully executed ' + IntToStr(i) +
-      ' operations!' + #10 + #10 + AOperationToString;
-    if i > 1 then
-      ShowMessage(LOperationsTxt)
-    else
-    begin
-      Application.MessageBox(
-        PChar('Successfully executed ' + IntToStr(i) + ' operations!' +
-        #10 + #10 + AOperationToString),
-        PChar(Application.Title), MB_OK + MB_ICONINFORMATION);
-    end;
-  end
-  else if (i > 0) then
-  begin
-    LOperationsTxt := 'One or more of your operations has not been executed:' +
-      #10 + 'Errors:' + #10 + AErrorMessage + #10 + #10 +
-      'Total successfully executed operations: ' + IntToStr(i);
-    ShowMessage(LOperationsTxt);
-  end
-  else
-    Result := False;
-end;
-
-class function TOperationsManager.ExecuteOperations(const ANewOps: TExecuteOperationsModel; AHandler: TExecuteOperationsModel.TOperationExecuteResultHandler; var errors: ansistring): boolean;
-begin
+  maxSignerFee := ANumOps * Fee;
+  minSignerFee := maxSignerFee - (PoorSenderCount * Fee);
 
 
+  for i := High(Result) downto Low(Result) do
+  begin
+    acc := Result[i];
+    if not (acc.Balance >= maxSignerFee) then
+      TArrayTool<TAccount>.RemoveAt(Result, i);
+  end;
 end;
 end;
 
 
-class function TOperationsManager.GetOperationShortText(const OpType, OpSubType: DWord): ansistring;
+class function TCoreTool.GetOperationShortText(const OpType, OpSubType: DWord): ansistring;
 begin
 begin
   case OpType of
   case OpType of
     CT_PseudoOp_Reward: case OpSubType of
     CT_PseudoOp_Reward: case OpSubType of
@@ -359,487 +195,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-class function TOperationsManager.ExecuteSendPASC(const ASelectedAccounts: TArray<TAccount>; const ADestinationAccount, ASignerAccount: TAccount; AAmount, AFee: int64; const ASendPASCMode: TExecuteOperationsModel.TSendPASCMode; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
-var
-  LWalletKey: TWalletKey;
-  LWalletKeys: TWalletKeys;
-  LNode: TNode;
-  LPCOperation: TPCOperation;
-  LOperationsHashTree: TOperationsHashTree;
-  LTotalAmount, LTotalSignerFee, LAmount, LFee: int64;
-  LDoOperation: boolean;
-  LOperationsTxt, LOperationToString: string;
-  LIdx, LAccountIdx, LNoOfOperations: integer;
-  LCurrentAccount: TAccount;
-  LPayloadEncodedBytes: TRawBytes;
-begin
-  if Length(ASelectedAccounts) = 0 then
-  begin
-    AErrorMessage := 'No Selected Account Found';
-    Exit(False);
-  end;
-
-  LWalletKeys := TWallet.Keys;
-  LNode := TNode.Node;
-
-  if not Assigned(LWalletKeys) then
-  begin
-    AErrorMessage := 'No Wallet Keys Found';
-    Exit(False);
-  end;
-
-  if not Assigned(LNode) then
-  begin
-    AErrorMessage := 'No Node Found';
-    Exit(False);
-  end;
-
-  LOperationsHashTree := TOperationsHashTree.Create;
-  try
-    LTotalAmount := 0;
-    LTotalSignerFee := 0;
-    LNoOfOperations := 0;
-    LOperationsTxt := '';
-    LOperationToString := '';
-    for LAccountIdx := Low(ASelectedAccounts) to High(ASelectedAccounts) do
-    begin
-      LPCOperation := nil; // reset LPCOperation to Nil
-      LCurrentAccount := ASelectedAccounts[LAccountIdx];
-
-      if LCurrentAccount.account = ADestinationAccount.account then
-      begin
-        AErrorMessage := Format('Sender "%s" And Destination "%s" Accounts Are The Same', [LCurrentAccount.AccountString, ADestinationAccount.AccountString]);
-        Exit(False);
-      end;
-
-      if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, ADestinationAccount.accountInfo.accountKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
-      begin
-        AErrorMessage := Format('Error Encoding Payload Of Selected Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
-        Exit(False);
-      end;
-
-      LIdx := LWalletKeys.IndexOfAccountKey(LCurrentAccount.accountInfo.accountKey);
-      if LIdx < 0 then
-      begin
-        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
-        Exit(False);
-      end;
-      LWalletKey := LWalletKeys.Key[LIdx];
-
-      if not Assigned(LWalletKey.PrivateKey) then
-      begin
-        if LWalletKey.HasPrivateKey then
-          AErrorMessage := 'Wallet is Password Protected. Please Unlock Before You Proceed.'
-        else
-          AErrorMessage := Format('Only Public Key of Account %s Was Found in Wallet. You Cannot Operate This Account', [LCurrentAccount.AccountString]);
-        Exit(False);
-      end;
-
-      LDoOperation := True;
-
-      if LCurrentAccount.balance > 0 then
-        case ASendPASCMode of
-          akaAllBalance:
-          begin
-            LAmount := LCurrentAccount.balance - AFee;
-            LFee := AFee;
-          end;
-
-          akaSpecifiedAmount:
-            if LCurrentAccount.balance >= UInt64(AAmount + AFee) then
-            begin
-              LAmount := AAmount;
-              LFee := AFee;
-            end
-            else
-            begin
-              AErrorMessage := Format('Insufficient Funds In "%s". %s < (%s + %s = %s)', [LCurrentAccount.AccountString, TAccountComp.FormatMoney(LCurrentAccount.balance), TAccountComp.FormatMoney(AAmount), TAccountComp.FormatMoney(AFee), TAccountComp.FormatMoney(AAmount + AFee)]);
-              Exit(False);
-            end;
-        end
-      else
-        LDoOperation := False;
-
-      if LDoOperation then
-      begin
-        LPCOperation := TOpTransaction.CreateTransaction(
-          LCurrentAccount.account, LCurrentAccount.n_operation + 1, ADestinationAccount.account, LWalletKey.PrivateKey, LAmount, LFee, LPayloadEncodedBytes);
-        try
-          LOperationsTxt := Format('Transaction To "%s"', [ADestinationAccount.AccountString]);
-
-          if Assigned(LPCOperation) then
-          begin
-            LOperationsHashTree.AddOperationToHashTree(LPCOperation);
-            Inc(LTotalAmount, LAmount);
-            Inc(LTotalSignerFee, LFee);
-            Inc(LNoOfOperations);
-            if LOperationToString <> '' then
-              LOperationToString := LOperationToString + #10;
-            LOperationToString := LOperationToString + LPCOperation.ToString;
-          end;
-        finally
-          FreeAndNil(LPCOperation);
-        end;
-      end;
-
-    end;
-    if (LOperationsHashTree.OperationsCount = 0) then
-    begin
-      AErrorMessage := 'No Valid Operation To Execute';
-      Exit(False);
-    end;
-
-    Exit(TOperationsManager.SendPASCFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalAmount, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
-  finally
-    LOperationsHashTree.Free;
-  end;
-
-end;
-
-class function TOperationsManager.ExecuteChangeKey(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount: TAccount; APublicKey: TAccountKey; AFee: int64; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
-var
-  LWalletKey: TWalletKey;
-  LWalletKeys: TWalletKeys;
-  LNode: TNode;
-  LPCOperation: TPCOperation;
-  LOperationsHashTree: TOperationsHashTree;
-  LTotalSignerFee, LFee: int64;
-  LIsV2: boolean;
-  LOperationsTxt, LOperationToString: string;
-  LIdx, LAccountIdx, LNoOfOperations: integer;
-  LCurrentAccount, LSignerAccount: TAccount;
-  LPayloadEncodedBytes: TRawBytes;
-label
-  loop_start;
-begin
-  if Length(ASelectedAccounts) = 0 then
-  begin
-    AErrorMessage := 'No Selected Account Found';
-    Exit(False);
-  end;
-
-  LWalletKeys := TWallet.Keys;
-  LNode := TNode.Node;
-
-  if not Assigned(LWalletKeys) then
-  begin
-    AErrorMessage := 'No Wallet Keys Found';
-    Exit(False);
-  end;
-
-  if not Assigned(LNode) then
-  begin
-    AErrorMessage := 'No Node Found';
-    Exit(False);
-  end;
-
-  LOperationsHashTree := TOperationsHashTree.Create;
-  try
-    LIsV2 := LNode.Bank.SafeBox.CurrentProtocol >= CT_PROTOCOL_2;
-    LTotalSignerFee := 0;
-    LNoOfOperations := 0;
-    LOperationsTxt := '';
-    LOperationToString := '';
-    for LAccountIdx := Low(ASelectedAccounts) to High(ASelectedAccounts) do
-    begin
-      loop_start:
-        LPCOperation := nil; // reset LPCOperation to Nil
-      LCurrentAccount := ASelectedAccounts[LAccountIdx];
-
-      if (TAccountComp.EqualAccountKeys(LCurrentAccount.accountInfo.accountKey,
-        APublicKey)) then
-      begin
-        AErrorMessage := 'New Key Is Same As Current Key';
-        Exit(False);
-      end;
-
-      if LNode.Bank.SafeBox.CurrentProtocol >= 1 then
-      begin
-        // Signer:
-        LSignerAccount := ASignerAccount;
-        if (TAccountComp.IsAccountLocked(LSignerAccount.accountInfo,
-          LNode.Bank.BlocksCount)) then
-        begin
-          AErrorMessage := Format('Signer Account "%s"  Is Locked Until Block %u', [LSignerAccount.AccountString, LSignerAccount.accountInfo.locked_until_block]);
-          Exit(False);
-        end;
-        if (not TAccountComp.EqualAccountKeys(
-          LSignerAccount.accountInfo.accountKey, LCurrentAccount.accountInfo.accountKey)) then
-        begin
-          AErrorMessage := Format('Signer Account %s Is Not The Owner Of Account %s', [LSignerAccount.AccountString, LCurrentAccount.AccountString]);
-          Exit(False);
-        end;
-      end
-      else
-        LSignerAccount := LCurrentAccount;
-
-      if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, APublicKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
-      begin
-        AErrorMessage := Format('Error Encoding Payload Of Selected Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
-        Exit(False);
-      end;
-
-      LIdx := LWalletKeys.IndexOfAccountKey(LCurrentAccount.accountInfo.accountKey);
-      if LIdx < 0 then
-      begin
-        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
-        Exit(False);
-      end;
-      LWalletKey := LWalletKeys.Key[LIdx];
-
-      if not Assigned(LWalletKey.PrivateKey) then
-      begin
-        if LWalletKey.HasPrivateKey then
-          AErrorMessage := 'Wallet Is Password Protected. Please Unlock Before You Proceed.'
-        else
-          AErrorMessage := Format('Only Public Key of Account %s Was Found In Wallet. You Cannot Operate This Account', [LCurrentAccount.AccountString]);
-        Exit(False);
-      end;
-
-      if LIsV2 then
-      begin
-        // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
-        if (LAccountIdx < Length(ASelectedAccounts) - 1) and
-          (LCurrentAccount.account = LSignerAccount.account) then
-        begin
-          TArrayTool<TAccount>.Swap(ASelectedAccounts, LAccountIdx,
-            Length(ASelectedAccounts) - 1); // ensure signer account processed last
-          goto loop_start; // TODO: remove ugly hack with refactoring!
-        end;
-
-        // Maintain correct signer fee distribution
-        if Uint64(LTotalSignerFee) >= LSignerAccount.balance then
-          LFee := 0
-        else if LSignerAccount.balance - uint64(LTotalSignerFee) >
-          UInt64(AFee) then
-          LFee := AFee
-        else
-          LFee := LSignerAccount.balance - UInt64(LTotalSignerFee);
-        LPCOperation := TOpChangeKeySigned.Create(LSignerAccount.account,
-          LSignerAccount.n_operation + LNoOfOperations + 1, LCurrentAccount.account,
-          LWalletKey.PrivateKey, APublicKey, LFee, LPayloadEncodedBytes);
-      end
-      else
-        LPCOperation := TOpChangeKey.Create(LCurrentAccount.account, LCurrentAccount.n_operation +
-          1, LCurrentAccount.account, LWalletKey.PrivateKey, APublicKey, LFee, LPayloadEncodedBytes);
-
-      try
-        LOperationsTxt := Format('Change Key To "%s"', [TAccountComp.GetECInfoTxt(APublicKey.EC_OpenSSL_NID)]);
-        if Assigned(LPCOperation) then
-        begin
-          LOperationsHashTree.AddOperationToHashTree(LPCOperation);
-          Inc(LNoOfOperations);
-          Inc(LTotalSignerFee, LFee);
-          if LOperationToString <> '' then
-            LOperationToString := LOperationToString + #10;
-          LOperationToString := LOperationToString + LPCOperation.ToString;
-        end;
-      finally
-        FreeAndNil(LPCOperation);
-      end;
-
-    end;
-
-    if (LOperationsHashTree.OperationsCount = 0) then
-    begin
-      AErrorMessage := 'No Valid Operation to Execute';
-      Exit(False);
-    end;
-
-    Exit(TOperationsManager.OthersFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
-  finally
-    LOperationsHashTree.Free;
-  end;
-
-end;
-
-class function TOperationsManager.ExecuteEnlistAccountForSale(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount, ASellerAccount: TAccount; const APublicKey: TAccountKey; AFee, ASalePrice: int64; ALockedUntilBlock: UInt32; const AAccountSaleMode: TExecuteOperationsModel.TAccountSaleMode; const APayloadEncryptionMode: TExecuteOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
-var
-  LWalletKey: TWalletKey;
-  LWalletKeys: TWalletKeys;
-  LNode: TNode;
-  LPCOperation: TPCOperation;
-  LOperationsHashTree: TOperationsHashTree;
-  LTotalSignerFee, LFee: int64;
-  LOperationsTxt, LOperationToString: string;
-  LIdx, LAccountIdx, LNoOfOperations: integer;
-  LCurrentAccount, LSignerAccount: TAccount;
-  LPayloadEncodedBytes: TRawBytes;
-begin
-  if Length(ASelectedAccounts) = 0 then
-  begin
-    AErrorMessage := 'No Selected Account Found';
-    Exit(False);
-  end;
-
-  LWalletKeys := TWallet.Keys;
-  LNode := TNode.Node;
-
-  if not Assigned(LWalletKeys) then
-  begin
-    AErrorMessage := 'No Wallet Keys Found';
-    Exit(False);
-  end;
-
-  if not Assigned(LNode) then
-  begin
-    AErrorMessage := 'No Node Found';
-    Exit(False);
-  end;
-
-  LOperationsHashTree := TOperationsHashTree.Create;
-  try
-    LTotalSignerFee := 0;
-    LNoOfOperations := 0;
-    LOperationsTxt := '';
-    LOperationToString := '';
-
-    for LAccountIdx := Low(ASelectedAccounts) to High(ASelectedAccounts) do
-    begin
-      LPCOperation := nil; // reset LPCOperation to Nil
-      LCurrentAccount := ASelectedAccounts[LAccountIdx];
-
-      if TAccountComp.IsAccountForSale(LCurrentAccount.accountInfo) then
-      begin
-        AErrorMessage := Format('Account "%s" Is Already Enlisted For Sale', [LCurrentAccount.AccountString]);
-        Exit(False);
-      end;
-
-      if (ASellerAccount.account = LCurrentAccount.account) then
-      begin
-        AErrorMessage := 'Seller Account Cannot Be Same As Account To Be Sold.';
-        Exit(False);
-      end;
-
-      if (LNode.Node.Bank.SafeBox.CurrentProtocol = CT_PROTOCOL_1) then
-      begin
-        AErrorMessage := 'This Operation Needs PROTOCOL 2 Active';
-        Exit(False);
-      end;
-
-      if AAccountSaleMode = akaPrivateSale then
-      begin
-
-        if TAccountComp.EqualAccountKeys(APublicKey,
-          LCurrentAccount.accountInfo.accountKey) then
-        begin
-          AErrorMessage := 'You Cannot Sell To An Account That You Want To Enlist For Sale.';
-          Exit(False);
-        end;
-
-        if ALockedUntilBlock = 0 then
-        begin
-          AErrorMessage := 'You Didn''t Insert a Locking Block.';
-          Exit(False);
-        end;
-      end;
-
-      if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, APublicKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
-      begin
-        AErrorMessage := Format('Error Encoding Payload Of Selected Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
-        Exit(False);
-      end;
-
-      LIdx := LWalletKeys.IndexOfAccountKey(LCurrentAccount.accountInfo.accountKey);
-      if LIdx < 0 then
-      begin
-        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
-        Exit(False);
-      end;
-      LWalletKey := LWalletKeys.Key[LIdx];
-
-      if not Assigned(LWalletKey.PrivateKey) then
-      begin
-        if LWalletKey.HasPrivateKey then
-          AErrorMessage := 'Wallet Is Password Protected. Please Unlock Before You Proceed.'
-        else
-          AErrorMessage := Format('Only Public Key Of Account %s Was Found In Wallet. You Cannot Operate This Account', [LCurrentAccount.AccountString]);
-        Exit(False);
-      end;
-
-      if ASignerAccount.balance > AFee then
-        LFee := AFee
-      else
-        LFee := ASignerAccount.balance;
-
-      case AAccountSaleMode of
-        akaPublicSale:
-
-          LPCOperation := TOpListAccountForSale.CreateListAccountForSale(
-            ASignerAccount.account, ASignerAccount.n_operation + 1 + LAccountIdx,
-            LCurrentAccount.account, ASalePrice, LFee, ASellerAccount.account,
-            APublicKey, 0, LWalletKey.PrivateKey, LPayloadEncodedBytes);
-
-        akaPrivateSale:
-
-          LPCOperation := TOpListAccountForSale.CreateListAccountForSale(
-            ASignerAccount.account, ASignerAccount.n_operation + 1 + LAccountIdx,
-            LCurrentAccount.account, ASalePrice, LFee, ASellerAccount.account,
-            APublicKey, ALockedUntilBlock, LWalletKey.PrivateKey, LPayloadEncodedBytes)
-
-        else
-          raise Exception.Create('Invalid Account Sale Type')
-      end;
-
-      try
-        LOperationsTxt := Format('Enlist Account For Sale At a Price Of "%s" PASC', [TAccountComp.FormatMoney(ASalePrice)]);
-        if Assigned(LPCOperation) then
-        begin
-          LOperationsHashTree.AddOperationToHashTree(LPCOperation);
-          Inc(LNoOfOperations);
-          Inc(LTotalSignerFee, LFee);
-          if LOperationToString <> '' then
-            LOperationToString := LOperationToString + #10;
-          LOperationToString := LOperationToString + LPCOperation.ToString;
-        end;
-      finally
-        FreeAndNil(LPCOperation);
-      end;
-
-    end;
-
-    if (LOperationsHashTree.OperationsCount = 0) then
-    begin
-      AErrorMessage := 'No Valid Operation to Execute';
-      Exit(False);
-    end;
-
-    Exit(TOperationsManager.OthersFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
-
-  finally
-    LOperationsHashTree.Free;
-  end;
-end;
-
-{ TCoreTool }
-
-class function TCoreTool.GetSignerCandidates(ANumOps: integer; ASingleOperationFee: int64; const ACandidates: array of TAccount): TArray<TAccount>;
-var
-  i, PoorSenderCount: integer;
-  Fee, maxSignerFee, minSignerFee: int64;
-  acc: TAccount;
-begin
-  //make deep copy of accounts!!! Very Important
-  Result := TArrayTool<TAccount>.Copy(ACandidates);
-  Fee := ASingleOperationFee;
-  PoorSenderCount := 0;
-  for i := Low(Result) to High(Result) do
-  begin
-    acc := Result[i];
-    if (acc.Balance < Fee) then
-      Inc(PoorSenderCount);
-  end;
-
-  maxSignerFee := ANumOps * Fee;
-  minSignerFee := maxSignerFee - (PoorSenderCount * Fee);
-
-  for i := High(Result) downto Low(Result) do
-  begin
-    acc := Result[i];
-    if not (acc.Balance >= maxSignerFee) then
-      TArrayTool<TAccount>.RemoveAt(Result, i);
-  end;
-end;
 
 
 { TNodeHelper }
 { TNodeHelper }
 
 
@@ -847,10 +202,13 @@ function TNodeHelper.HasBestKnownBlockchainTip: boolean;
 var
 var
   LReady: boolean;
   LReady: boolean;
   LMsg: ansistring;
   LMsg: ansistring;
+  LDestBlock : Cardinal;
 begin
 begin
   LReady := Self.Bank.IsReady(LMsg);
   LReady := Self.Bank.IsReady(LMsg);
-  if LReady and TNetData.NetData.IsGettingNewBlockChainFromClient then
+  if LReady and TNetData.NetData.IsGettingNewBlockChainFromClient then begin
+    LDestBlock := TNetData.NetData.MaxRemoteOperationBlock.block;
     Result := Self.Bank.BlocksCount = TNetData.NetData.MaxRemoteOperationBlock.block;
     Result := Self.Bank.BlocksCount = TNetData.NetData.MaxRemoteOperationBlock.block;
+  end;
 end;
 end;
 
 
 { TOrderedAccountKeysListHelper }
 { TOrderedAccountKeysListHelper }

+ 16 - 16
src/core.utils/UDataSources.pas

@@ -89,9 +89,9 @@ type
     procedure FetchAll(const AContainer: TList<TOperationResume>); override;
     procedure FetchAll(const AContainer: TList<TOperationResume>); override;
   end;
   end;
 
 
-  { TBlockChainDataSourceBase }
+  { TBlockSummarySourceBase }
 
 
-  TBlockChainDataSourceBase = class(TCustomDataSource<TBlockChainData>)
+  TBlockSummarySourceBase = class(TCustomDataSource<TBlockSummary>)
   public type
   public type
     TShowHashRateAs = (hr_Kilo, hr_Mega, hr_Giga, hr_Tera);
     TShowHashRateAs = (hr_Kilo, hr_Mega, hr_Giga, hr_Tera);
   private
   private
@@ -109,14 +109,14 @@ type
     property EndBlock: cardinal read FEnd write FEnd;
     property EndBlock: cardinal read FEnd write FEnd;
     property HashRateAs: TShowHashRateAs read FHashRateAs write FHashRateAs;
     property HashRateAs: TShowHashRateAs read FHashRateAs write FHashRateAs;
     property HashRateAverageBlocksCount: integer read FHashRateAverageBlocksCount write FHashRateAverageBlocksCount;
     property HashRateAverageBlocksCount: integer read FHashRateAverageBlocksCount write FHashRateAverageBlocksCount;
-    function GetItemField(constref AItem: TBlockChainData; const ABindingName: ansistring): variant; override;
+    function GetItemField(constref AItem: TBlockSummary; const ABindingName: ansistring): variant; override;
   end;
   end;
 
 
-  { TBlockChainDataSource }
+  { TBlockSummarySource }
 
 
-  TBlockChainDataSource = class(TBlockChainDataSourceBase)
+  TBlockSummarySource = class(TBlockSummarySourceBase)
   public
   public
-    procedure FetchAll(const AContainer: TList<TBlockChainData>); override;
+    procedure FetchAll(const AContainer: TList<TBlockSummary>); override;
   end;
   end;
 
 
 implementation
 implementation
@@ -504,14 +504,14 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ TBlockChainDataSourceBase }
+{ TBlockSummarySourceBase }
 
 
-function TBlockChainDataSourceBase.GetTimeSpan: TTimeSpan;
+function TBlockSummarySourceBase.GetTimeSpan: TTimeSpan;
 begin
 begin
   Result := TTimeSpan.FromSeconds(CT_NewLineSecondsAvg * (FEnd - FStart + 1));
   Result := TTimeSpan.FromSeconds(CT_NewLineSecondsAvg * (FEnd - FStart + 1));
 end;
 end;
 
 
-procedure TBlockChainDataSourceBase.SetTimeSpan(const ASpan: TTimeSpan);
+procedure TBlockSummarySourceBase.SetTimeSpan(const ASpan: TTimeSpan);
 var
 var
   LNode: TNode;
   LNode: TNode;
 begin
 begin
@@ -522,7 +522,7 @@ begin
   FStart := ClipValue(FEnd - (ASpan.TotalBlockCount + 1), 0, FEnd);
   FStart := ClipValue(FEnd - (ASpan.TotalBlockCount + 1), 0, FEnd);
 end;
 end;
 
 
-function TBlockChainDataSourceBase.GetColumns: TDataColumns;
+function TBlockSummarySourceBase.GetColumns: TDataColumns;
 var
 var
   LHashType: string;
   LHashType: string;
 begin
 begin
@@ -553,7 +553,7 @@ begin
   );
   );
 end;
 end;
 
 
-constructor TBlockChainDataSourceBase.Create(AOwner: TComponent);
+constructor TBlockSummarySourceBase.Create(AOwner: TComponent);
 var
 var
   LNode: TNode;
   LNode: TNode;
 begin
 begin
@@ -568,7 +568,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TBlockChainDataSourceBase.GetItemField(constref AItem: TBlockChainData; const ABindingName: ansistring): variant;
+function TBlockSummarySourceBase.GetItemField(constref AItem: TBlockSummary; const ABindingName: ansistring): variant;
 var
 var
   LHR_Base: int64;
   LHR_Base: int64;
   LHashType: string;
   LHashType: string;
@@ -633,13 +633,13 @@ begin
     raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
     raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
 end;
 end;
 
 
-{ TBlockChainDataSource }
+{ TBlockSummarySource }
 
 
-procedure TBlockChainDataSource.FetchAll(const AContainer: TList<TBlockChainData>);
+procedure TBlockSummarySource.FetchAll(const AContainer: TList<TBlockSummary>);
 var
 var
   LStart, LEnd, LIdx: cardinal;
   LStart, LEnd, LIdx: cardinal;
   LOperationComp: TPCOperationsComp;
   LOperationComp: TPCOperationsComp;
-  LBlockChainData: TBlockChainData;
+  LBlockChainData: TBlockSummary;
   LOperationBlock: TOperationBlock;
   LOperationBlock: TOperationBlock;
   LBigNum: TBigNum;
   LBigNum: TBigNum;
   LNode: TNode;
   LNode: TNode;
@@ -656,7 +656,7 @@ begin
     LOperationComp.bank := LNode.Bank;
     LOperationComp.bank := LNode.Bank;
 
 
     for LIdx := LEnd downto LStart do begin
     for LIdx := LEnd downto LStart do begin
-      LBlockChainData := CT_TBlockChainData_NUL;
+      LBlockChainData := CT_BlockSummary_NUL;
       LOperationBlock := LNode.Bank.SafeBox.Block(LIdx).blockchainInfo;
       LOperationBlock := LNode.Bank.SafeBox.Block(LIdx).blockchainInfo;
       LBlockChainData.Block := LOperationBlock.block;
       LBlockChainData.Block := LOperationBlock.block;
       LBlockChainData.Timestamp := LOperationBlock.timestamp;
       LBlockChainData.Timestamp := LOperationBlock.timestamp;

+ 7 - 7
src/gui-classic/UGridUtils.pas

@@ -122,7 +122,7 @@ Type
     Property OperationsResume : TOperationsResumeList read FOperationsResume;
     Property OperationsResume : TOperationsResumeList read FOperationsResume;
   End;
   End;
 
 
-  TBlockChainData = Record
+  TBlockSummary = Record
     Block : Cardinal;
     Block : Cardinal;
     Timestamp : Cardinal;
     Timestamp : Cardinal;
     BlockProtocolVersion,
     BlockProtocolVersion,
@@ -145,7 +145,7 @@ Type
     TimeAverage25 : Real;
     TimeAverage25 : Real;
     TimeAverage10 : Real;
     TimeAverage10 : Real;
   End;
   End;
-  TBlockChainDataArray = Array of TBlockChainData;
+  TBlockSummaryArray = Array of TBlockSummary;
 
 
   { TBlockChainGrid }
   { TBlockChainGrid }
 
 
@@ -153,7 +153,7 @@ Type
 
 
   TBlockChainGrid = Class(TComponent)
   TBlockChainGrid = Class(TComponent)
   private
   private
-    FBlockChainDataArray : TBlockChainDataArray;
+    FBlockChainDataArray : TBlockSummaryArray;
     FBlockStart: Int64;
     FBlockStart: Int64;
     FHashRateAs: TShowHashRateAs;
     FHashRateAs: TShowHashRateAs;
     FMaxBlocks: Integer;
     FMaxBlocks: Integer;
@@ -193,7 +193,7 @@ Type
   End;
   End;
 
 
 Const
 Const
-  CT_TBlockChainData_NUL : TBlockChainData = (Block:0;Timestamp:0;BlockProtocolVersion:0;BlockProtocolAvailable:0;OperationsCount:-1;Volume:-1;Reward:0;Fee:0;Target:0;HashRateTargetKhs:0;HashRateKhs:0;MinerPayload:'';PoW:'';SafeBoxHash:'';AccumulatedWork:0;TimeAverage200:0;TimeAverage150:0;TimeAverage100:0;TimeAverage75:0;TimeAverage50:0;TimeAverage25:0;TimeAverage10:0);
+  CT_TBlockSummary_NUL : TBlockSummary = (Block:0;Timestamp:0;BlockProtocolVersion:0;BlockProtocolAvailable:0;OperationsCount:-1;Volume:-1;Reward:0;Fee:0;Target:0;HashRateTargetKhs:0;HashRateKhs:0;MinerPayload:'';PoW:'';SafeBoxHash:'';AccumulatedWork:0;TimeAverage200:0;TimeAverage150:0;TimeAverage100:0;TimeAverage75:0;TimeAverage50:0;TimeAverage25:0;TimeAverage10:0);
 
 
 
 
 implementation
 implementation
@@ -1063,7 +1063,7 @@ end;
 procedure TBlockChainGrid.OnGridDrawCell(Sender: TObject; ACol, ARow: Longint;
 procedure TBlockChainGrid.OnGridDrawCell(Sender: TObject; ACol, ARow: Longint;
   Rect: TRect; State: TGridDrawState);
   Rect: TRect; State: TGridDrawState);
 Var s : String;
 Var s : String;
-  bcd : TBlockChainData;
+  bcd : TBlockSummary;
   deviation : Real;
   deviation : Real;
   hr_base : Int64;
   hr_base : Int64;
 begin
 begin
@@ -1275,7 +1275,7 @@ end;
 procedure TBlockChainGrid.UpdateBlockChainGrid;
 procedure TBlockChainGrid.UpdateBlockChainGrid;
 Var nstart,nend : Cardinal;
 Var nstart,nend : Cardinal;
   opc : TPCOperationsComp;
   opc : TPCOperationsComp;
-  bcd : TBlockChainData;
+  bcd : TBlockSummary;
   i : Integer;
   i : Integer;
   opb : TOperationBlock;
   opb : TOperationBlock;
   bn : TBigNum;
   bn : TBigNum;
@@ -1310,7 +1310,7 @@ begin
       opc.bank := Node.Bank;
       opc.bank := Node.Bank;
       while (nstart<=nend) do begin
       while (nstart<=nend) do begin
         i := length(FBlockChainDataArray) - (nend-nstart+1);
         i := length(FBlockChainDataArray) - (nend-nstart+1);
-        bcd := CT_TBlockChainData_NUL;
+        bcd := CT_TBlockSummary_NUL;
         opb := Node.Bank.SafeBox.Block(nend).blockchainInfo;
         opb := Node.Bank.SafeBox.Block(nend).blockchainInfo;
         bcd.Block:=opb.block;
         bcd.Block:=opb.block;
         bcd.Timestamp := opb.timestamp;
         bcd.Timestamp := opb.timestamp;

+ 1 - 0
src/gui/UCTRLBanner.lfm

@@ -12,6 +12,7 @@ object CTRLBanner: TCTRLBanner
   Constraints.MinHeight = 80
   Constraints.MinHeight = 80
   Constraints.MinWidth = 512
   Constraints.MinWidth = 512
   OnCreate = FormCreate
   OnCreate = FormCreate
+  LCLVersion = '1.8.2.0'
   Visible = False
   Visible = False
   object imBackground: TImage
   object imBackground: TImage
     Left = 0
     Left = 0

+ 4 - 2
src/gui/UCTRLBanner.pas

@@ -2,12 +2,14 @@ unit UCTRLBanner;
 
 
 {$mode delphi}
 {$mode delphi}
 
 
-{ Copyright (c) 2018 by Herman Schoenfeld
+{ Copyright (c) 2018 Sphere 10 Software
 
 
   Distributed under the MIT software license, see the accompanying file LICENSE
   Distributed under the MIT software license, see the accompanying file LICENSE
   or visit http://www.opensource.org/licenses/mit-license.php.
   or visit http://www.opensource.org/licenses/mit-license.php.
-}
 
 
+  Acknowledgements:
+  - Herman Schoenfeld: unit creator, implementation
+}
 
 
 interface
 interface
 
 

+ 2 - 1
src/gui/UCTRLSyncronization.lfm

@@ -8,7 +8,8 @@ object CTRLSyncronization: TCTRLSyncronization
   Caption = 'Synchronization'
   Caption = 'Synchronization'
   ClientHeight = 240
   ClientHeight = 240
   ClientWidth = 636
   ClientWidth = 636
-  LCLVersion = '1.6.4.0'
+  LCLVersion = '1.8.2.0'
+  Visible = False
   object Label8: TLabel
   object Label8: TLabel
     Left = 16
     Left = 16
     Height = 32
     Height = 32

+ 2 - 2
src/gui/UCTRLSyncronization.pas

@@ -2,13 +2,13 @@ unit UCTRLSyncronization;
 
 
 {$mode delphi}
 {$mode delphi}
 
 
-{ Copyright (c) 2018 by Herman Schoenfeld
+{ Copyright (c) 2018 Sphere 10 Software
 
 
   Distributed under the MIT software license, see the accompanying file LICENSE
   Distributed under the MIT software license, see the accompanying file LICENSE
   or visit http://www.opensource.org/licenses/mit-license.php.
   or visit http://www.opensource.org/licenses/mit-license.php.
 
 
   Acknowledgements:
   Acknowledgements:
-  - Albert Molina: portions of code copied from https://github.com/PascalCoin/PascalCoin/blob/master/Units/Forms/UFRMWallet.pas
+  - Herman Schoenfeld: unit creator, implementation
 }
 }
 
 
 interface
 interface

+ 1 - 0
src/gui/UCTRLWallet.lfm

@@ -10,6 +10,7 @@ object CTRLWallet: TCTRLWallet
   ClientWidth = 1151
   ClientWidth = 1151
   OnCreate = FormCreate
   OnCreate = FormCreate
   OnResize = FormResize
   OnResize = FormResize
+  LCLVersion = '1.8.2.0'
   Visible = False
   Visible = False
   object PairSplitter1: TPairSplitter
   object PairSplitter1: TPairSplitter
     Left = 0
     Left = 0

+ 21 - 12
src/gui/UCTRLWallet.pas

@@ -1,14 +1,22 @@
 unit UCTRLWallet;
 unit UCTRLWallet;
 
 
 {$mode delphi}
 {$mode delphi}
-
 {$modeswitch nestedprocvars}
 {$modeswitch nestedprocvars}
 
 
+{ Copyright (c) 2018 Sphere 10 Software
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+
+  Acknowledgements:
+  - Herman Schoenfeld: unit creator, implementation
+}
+
 interface
 interface
 
 
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus,
-  ExtCtrls, PairSplitter, Buttons, UVisualGrid, UCommon.UI, Generics.Collections,
+  ExtCtrls, PairSplitter, Buttons, UVisualGrid, UCommon.UI, Generics.Collections, ULog,
   UAccounts, UDataSources, UNode, UCoreObjects, UCoreUtils, UWIZSendPASC, UWIZChangeKey, UWIZEnlistAccountForSale;
   UAccounts, UDataSources, UNode, UCoreObjects, UCoreUtils, UWIZSendPASC, UWIZChangeKey, UWIZEnlistAccountForSale;
 
 
 type
 type
@@ -95,7 +103,7 @@ implementation
 
 
 uses
 uses
   UUserInterface, UCellRenderers, UBlockChain, UWallet, UCrypto,
   UUserInterface, UCellRenderers, UBlockChain, UWallet, UCrypto,
-  UCommon, UMemory, Generics.Defaults, UCommon.Data, UCommon.Collections;
+  UCommon, UMemory, Generics.Defaults, UCommon.Data, UCommon.Collections, UWIZOperation;
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
@@ -112,6 +120,7 @@ begin
   FNodeNotifyEvents.OnBlocksChanged := OnNodeBlocksChanged;
   FNodeNotifyEvents.OnBlocksChanged := OnNodeBlocksChanged;
   FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
   FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
   TWallet.Keys.OnChanged.Add(OnPrivateKeysChanged);
   TWallet.Keys.OnChanged.Add(OnPrivateKeysChanged);
+  TWallet.Keys.AccountsKeyList.ClearAccountKeyChanges;   // XXXXX CLEAR BUFFER on start
 
 
   // fields
   // fields
   FAccountsDataSource := TMyAccountsDataSource.Create(Self);
   FAccountsDataSource := TMyAccountsDataSource.Create(Self);
@@ -505,8 +514,8 @@ end;
 
 
 procedure TCTRLWallet.OnUserAccountsChanged;
 procedure TCTRLWallet.OnUserAccountsChanged;
 begin
 begin
-//  if NOT TUserInterface.Node.HasBestKnownBlockchainTip then
-//    exit; // node syncing
+  if NOT TUserInterface.Node.HasBestKnownBlockchainTip then
+    exit; // node syncing
 
 
   RefreshTotals;
   RefreshTotals;
   FAccountsGrid.RefreshGrid;
   FAccountsGrid.RefreshGrid;
@@ -547,7 +556,7 @@ begin
     ophash := FOperationsGrid.Rows[row].OPHASH;
     ophash := FOperationsGrid.Rows[row].OPHASH;
     if TPCOperation.IsValidOperationHash(ophash) then begin
     if TPCOperation.IsValidOperationHash(ophash) then begin
       TUserInterface.ShowOperationInfoDialog(self, ophash);
       TUserInterface.ShowOperationInfoDialog(self, ophash);
-      FOperationsGrid.ClearSelection(true);
+      FOperationsGrid.ClearSelection;
     end;
     end;
   end;
   end;
 end;
 end;
@@ -612,7 +621,7 @@ procedure TCTRLWallet.miSendPASCClick(Sender: TObject);
 var
 var
   Scoped: TDisposables;
   Scoped: TDisposables;
   wiz: TWIZSendPASCWizard;
   wiz: TWIZSendPASCWizard;
-  model: TExecuteOperationsModel;
+  model: TWIZOperationsModel;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
 
 
   function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
   function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
@@ -622,7 +631,7 @@ var
 
 
 begin
 begin
   wiz := Scoped.AddObject(TWIZSendPASCWizard.Create(nil)) as TWIZSendPASCWizard;
   wiz := Scoped.AddObject(TWIZSendPASCWizard.Create(nil)) as TWIZSendPASCWizard;
-  model := TExecuteOperationsModel.Create(wiz, omtSendPasc);
+  model := TWIZOperationsModel.Create(wiz, omtSendPasc);
   AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,GetAccNoWithoutChecksum);
   AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,GetAccNoWithoutChecksum);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   wiz.Start(model);
   wiz.Start(model);
@@ -632,7 +641,7 @@ procedure TCTRLWallet.miChangeKeyClick(Sender: TObject);
 var
 var
   Scoped: TDisposables;
   Scoped: TDisposables;
   wiz: TWIZChangeKeyWizard;
   wiz: TWIZChangeKeyWizard;
-  model: TExecuteOperationsModel;
+  model: TWIZOperationsModel;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
 
 
   function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
   function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
@@ -642,7 +651,7 @@ var
 
 
 begin
 begin
   wiz := Scoped.AddObject(TWIZChangeKeyWizard.Create(nil)) as TWIZChangeKeyWizard;
   wiz := Scoped.AddObject(TWIZChangeKeyWizard.Create(nil)) as TWIZChangeKeyWizard;
-  model := TExecuteOperationsModel.Create(wiz, omtChangeKey);
+  model := TWIZOperationsModel.Create(wiz, omtChangeKey);
   AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNoWithoutChecksum);
   AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNoWithoutChecksum);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   wiz.Start(model);
   wiz.Start(model);
@@ -652,7 +661,7 @@ procedure TCTRLWallet.miEnlistAccountsForSaleClick(Sender: TObject);
 var
 var
   Scoped: TDisposables;
   Scoped: TDisposables;
   wiz: TWIZEnlistAccountForSaleWizard;
   wiz: TWIZEnlistAccountForSaleWizard;
-  model: TExecuteOperationsModel;
+  model: TWIZOperationsModel;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
 
 
    function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
    function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
@@ -663,7 +672,7 @@ var
 
 
 begin
 begin
   wiz := Scoped.AddObject(TWIZEnlistAccountForSaleWizard.Create(nil)) as TWIZEnlistAccountForSaleWizard;
   wiz := Scoped.AddObject(TWIZEnlistAccountForSaleWizard.Create(nil)) as TWIZEnlistAccountForSaleWizard;
-  model := TExecuteOperationsModel.Create(wiz, omtEnlistAccountForSale);
+  model := TWIZOperationsModel.Create(wiz, omtEnlistAccountForSale);
   AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNoWithoutChecksum);
   AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNoWithoutChecksum);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   wiz.Start(model);
   wiz.Start(model);

+ 1 - 1
src/gui/UCellRenderers.pas

@@ -181,7 +181,7 @@ end;
 
 
 class function TCellRenderers.OperationShortText(const OpType, OpSubType : DWord) : AnsiString;
 class function TCellRenderers.OperationShortText(const OpType, OpSubType : DWord) : AnsiString;
 begin
 begin
-  Result := TOperationsManager.GetOperationShortText(OpType, OpSubType);
+  Result := TCoreTool.GetOperationShortText(OpType, OpSubType);
 end;
 end;
 
 
 class function TCellRenderers.AccountKeyShortText(const AText : AnsiString) : AnsiString;
 class function TCellRenderers.AccountKeyShortText(const AText : AnsiString) : AnsiString;

+ 17 - 13
src/gui/UFRMExecuteOperations.lfm

@@ -1,39 +1,43 @@
 object ExecuteOperations: TExecuteOperations
 object ExecuteOperations: TExecuteOperations
   Left = 0
   Left = 0
-  Height = 340
+  Height = 307
   Top = 0
   Top = 0
-  Width = 606
+  Width = 545
+  ActiveControl = btnClose
   Caption = 'Execute Operations'
   Caption = 'Execute Operations'
-  ClientHeight = 340
-  ClientWidth = 606
+  ClientHeight = 307
+  ClientWidth = 545
+  OnCreate = FormCreate
+  LCLVersion = '1.8.2.0'
   Visible = False
   Visible = False
   object GroupBox1: TGroupBox
   object GroupBox1: TGroupBox
     Left = 0
     Left = 0
-    Height = 293
+    Height = 260
     Top = 8
     Top = 8
-    Width = 606
+    Width = 545
     Anchors = [akTop, akLeft, akRight, akBottom]
     Anchors = [akTop, akLeft, akRight, akBottom]
     Caption = 'Executing Operations'
     Caption = 'Executing Operations'
-    ClientHeight = 273
-    ClientWidth = 602
+    ClientHeight = 240
+    ClientWidth = 541
     TabOrder = 0
     TabOrder = 0
-    object Panel1: TPanel
+    object paGrid: TPanel
       Left = 6
       Left = 6
-      Height = 253
+      Height = 220
       Top = 8
       Top = 8
-      Width = 588
+      Width = 527
       Anchors = [akTop, akLeft, akRight, akBottom]
       Anchors = [akTop, akLeft, akRight, akBottom]
       Caption = 'GRID PANEL'
       Caption = 'GRID PANEL'
       TabOrder = 0
       TabOrder = 0
     end
     end
   end
   end
   object btnClose: TButton
   object btnClose: TButton
-    Left = 490
+    Left = 429
     Height = 25
     Height = 25
-    Top = 309
+    Top = 276
     Width = 107
     Width = 107
     Anchors = [akRight, akBottom]
     Anchors = [akRight, akBottom]
     Caption = 'Close'
     Caption = 'Close'
+    OnClick = btnCloseClick
     TabOrder = 1
     TabOrder = 1
   end
   end
 end
 end

+ 54 - 7
src/gui/UFRMExecuteOperations.pas

@@ -2,32 +2,79 @@ unit UFRMExecuteOperations;
 
 
 {$mode delphi}
 {$mode delphi}
 
 
+{ Copyright (c) 2018 Sphere 10 Software (http://www.sphere10.com/)
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+
+  Acknowledgements:
+  Ugochukwu Mmaduekwe - main developer
+  Herman Schoenfeld - designer }
+
 interface
 interface
 
 
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
-  StdCtrls;
+  StdCtrls, UCommon, UCommon.Data, UCommon.Collections, UCommon.UI, UVisualGrid, UCoreObjects, UCoreUtils;
 
 
 type
 type
 
 
   { TExecuteOperations }
   { TExecuteOperations }
 
 
-  TExecuteOperations = class(TForm)
+  TExecuteOperations = class(TApplicationFormEx)
     btnClose: TButton;
     btnClose: TButton;
     GroupBox1: TGroupBox;
     GroupBox1: TGroupBox;
-    Panel1: TPanel;
+    paGrid: TPanel;
+    procedure btnCloseClick(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
   private
   private
-
+    FOperations : TWIZOperationsModel;
+  protected
+    procedure ActivateFirstTime; override;
+    procedure Execute;
+  private
+      FGrid : TVisualGrid;
   public
   public
 
 
   end;
   end;
 
 
-var
-  ExecuteOperations: TExecuteOperations;
-
 implementation
 implementation
 
 
+
+type
+
+
+  TExecuteOperationResultDataSource : class(TDataSource<
+
 {$R *.lfm}
 {$R *.lfm}
 
 
+{ TExecuteOperations }
+
+procedure TExecuteOperations.btnCloseClick(Sender: TObject);
+begin
+
+end;
+
+procedure TExecuteOperations.FormCreate(Sender: TObject);
+begin
+  FOperationsGrid := TVisualGrid.Create(Self);
+  FOperationsGrid.SortMode := smMultiColumn;
+  FOperationsGrid.FetchDataInThread := false;
+  FOperationsGrid.AutoPageSize := True;
+  FOperationsGrid.DeselectionType := dtDefault;
+  FOperationsGrid.SelectionType := stRow;
+end;
+
+procedure TExecuteOperations.ActivateFirstTime;
+begin
+
+end;
+
+
+procedure TExecuteOperations.Execute;
+begin
+
+end;
+
 end.
 end.
 
 

+ 3 - 3
src/gui/wizards/operations/UWIZChangeKey.pas

@@ -15,13 +15,13 @@ unit UWIZChangeKey;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon, UWizard, UAccounts, UCoreObjects, LCLType;
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon, UWizard, UAccounts, UCoreObjects, UWIZOperation, LCLType;
 
 
 type
 type
 
 
   { TWIZChangeKeyWizard }
   { TWIZChangeKeyWizard }
 
 
-  TWIZChangeKeyWizard = class(TWizard<TExecuteOperationsModel>)
+  TWIZChangeKeyWizard = class(TWizard<TWIZOperationsModel>)
   public
   public
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     function DetermineHasNext: boolean; override;
     function DetermineHasNext: boolean; override;
@@ -77,7 +77,7 @@ begin
 
 
   end;
   end;
 
 
-  Result := TOperationsManager.ExecuteChangeKey(Model.Account.SelectedAccounts, Model.Signer.SignerAccount, LPublicKey, Model.Fee.SingleOperationFee, Model.Payload.PayloadEncryptionMode, IIF(Model.Payload.HasPayload, Model.Payload.Content, ''), Model.Payload.Password, message);
+  Result := TWIZOperationsHelper.ExecuteChangeKey(Model.Account.SelectedAccounts, Model.Signer.SignerAccount, LPublicKey, Model.Fee.SingleOperationFee, Model.Payload.PayloadEncryptionMode, IIF(Model.Payload.HasPayload, Model.Payload.Content, ''), Model.Payload.Password, message);
 end;
 end;
 
 
 function TWIZChangeKeyWizard.CancelRequested(out message: ansistring): boolean;
 function TWIZChangeKeyWizard.CancelRequested(out message: ansistring): boolean;

+ 2 - 2
src/gui/wizards/operations/UWIZChangeKey_EnterKey.pas

@@ -19,13 +19,13 @@ uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   UFRMAccountSelect, UNode, UCoreObjects, UWizard,
   UFRMAccountSelect, UNode, UCoreObjects, UWizard,
-  UWIZOperationFee_Custom, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
+  UWIZOperation, UWIZOperationFee_Custom, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
 
 
 type
 type
 
 
   { TWIZChangeKey_EnterKey }
   { TWIZChangeKey_EnterKey }
 
 
-  TWIZChangeKey_EnterKey = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZChangeKey_EnterKey = class(TWizardForm<TWIZOperationsModel>)
     chkChooseFee: TCheckBox;
     chkChooseFee: TCheckBox;
     chkAttachPayload: TCheckBox;
     chkAttachPayload: TCheckBox;
     gbNewPublicKey: TGroupBox;
     gbNewPublicKey: TGroupBox;

+ 2 - 2
src/gui/wizards/operations/UWIZChangeKey_SelectKey.pas

@@ -19,13 +19,13 @@ uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   UFRMAccountSelect, UNode, UWizard, UCoreObjects,
   UFRMAccountSelect, UNode, UWizard, UCoreObjects,
-  UWIZOperationFee_Custom, UWIZOperationSigner_Select, UWIZOperationPayload_Encryption;
+  UWIZOperation, UWIZOperationFee_Custom, UWIZOperationSigner_Select, UWIZOperationPayload_Encryption;
 
 
 type
 type
 
 
   { TWIZChangeKey_SelectKey }
   { TWIZChangeKey_SelectKey }
 
 
-  TWIZChangeKey_SelectKey = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZChangeKey_SelectKey = class(TWizardForm<TWIZOperationsModel>)
     cbNewPrivateKey: TComboBox;
     cbNewPrivateKey: TComboBox;
     chkAttachPayload: TCheckBox;
     chkAttachPayload: TCheckBox;
     chkChooseFee: TCheckBox;
     chkChooseFee: TCheckBox;

+ 3 - 2
src/gui/wizards/operations/UWIZChangeKey_SelectOption.pas

@@ -17,13 +17,14 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
-  ExtCtrls, UCoreObjects, UWizard, UWIZChangeKey_EnterKey, UWIZChangeKey_SelectKey;
+  ExtCtrls, UCoreObjects,
+  UWizard, UWIZOperation, UWIZChangeKey_EnterKey, UWIZChangeKey_SelectKey;
 
 
 type
 type
 
 
   { TWIZChangeKey_SelectOption }
   { TWIZChangeKey_SelectOption }
 
 
-  TWIZChangeKey_SelectOption = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZChangeKey_SelectOption = class(TWizardForm<TWIZOperationsModel>)
     gbChangeKeyOptions: TGroupBox;
     gbChangeKeyOptions: TGroupBox;
     lblTransferAccountOwnership: TLabel;
     lblTransferAccountOwnership: TLabel;
     lblNote: TLabel;
     lblNote: TLabel;

+ 4 - 3
src/gui/wizards/operations/UWIZEnlistAccountForSale.pas

@@ -15,13 +15,14 @@ unit UWIZEnlistAccountForSale;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon, UWizard, UAccounts, UCoreObjects, LCLType;
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon,
+  UWizard, UWIZOperation, UAccounts, UCoreObjects, LCLType;
 
 
 type
 type
 
 
   { TWIZEnlistAccountForSaleWizard }
   { TWIZEnlistAccountForSaleWizard }
 
 
-  TWIZEnlistAccountForSaleWizard = class(TWizard<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSaleWizard = class(TWizard<TWIZOperationsModel>)
   public
   public
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     function DetermineHasNext: boolean; override;
     function DetermineHasNext: boolean; override;
@@ -81,7 +82,7 @@ begin
 
 
   end;
   end;
 
 
-  Result := TOperationsManager.ExecuteEnlistAccountForSale(Model.Account.SelectedAccounts, Model.Signer.SignerAccount, Model.EnlistAccountForSale.SellerAccount, LPublicKey, Model.Fee.SingleOperationFee, Model.EnlistAccountForSale.SalePrice, Model.EnlistAccountForSale.LockedUntilBlock, Model.EnlistAccountForSale.AccountSaleMode, Model.Payload.PayloadEncryptionMode, IIF(Model.Payload.HasPayload, Model.Payload.Content, ''), Model.Payload.Password, message);
+  Result := TWIZOperationsHelper.ExecuteEnlistAccountForSale(Model.Account.SelectedAccounts, Model.Signer.SignerAccount, Model.EnlistAccountForSale.SellerAccount, LPublicKey, Model.Fee.SingleOperationFee, Model.EnlistAccountForSale.SalePrice, Model.EnlistAccountForSale.LockedUntilBlock, Model.EnlistAccountForSale.AccountSaleMode, Model.Payload.PayloadEncryptionMode, IIF(Model.Payload.HasPayload, Model.Payload.Content, ''), Model.Payload.Password, message);
 end;
 end;
 
 
 function TWIZEnlistAccountForSaleWizard.CancelRequested(out message: ansistring): boolean;
 function TWIZEnlistAccountForSaleWizard.CancelRequested(out message: ansistring): boolean;

+ 3 - 2
src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterLockingBlock.pas

@@ -13,13 +13,14 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
-  ExtCtrls, Buttons, UWizard, UCoreObjects, UWIZEnlistAccountForSale_EnterSeller;
+  ExtCtrls, Buttons,
+  UWizard, UWIZOperation, UCoreObjects, UWIZEnlistAccountForSale_EnterSeller;
 
 
 type
 type
 
 
   { TWIZEnlistAccountForSale_EnterLockingBlock }
   { TWIZEnlistAccountForSale_EnterLockingBlock }
 
 
-  TWIZEnlistAccountForSale_EnterLockingBlock = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSale_EnterLockingBlock = class(TWizardForm<TWIZOperationsModel>)
     edtBlockLock: TEdit;
     edtBlockLock: TEdit;
     gbLockBlock: TGroupBox;
     gbLockBlock: TGroupBox;
     lblBlockLock: TLabel;
     lblBlockLock: TLabel;

+ 3 - 2
src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterPublicKey.pas

@@ -13,13 +13,14 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
-  ExtCtrls, Buttons, UCoreObjects, UWizard, UWIZEnlistAccountForSale_EnterLockingBlock;
+  ExtCtrls, Buttons, UCoreObjects,
+  UWizard, UWIZOperation, UWIZEnlistAccountForSale_EnterLockingBlock;
 
 
 type
 type
 
 
   { TWIZEnlistAccountForSale_EnterPublicKey }
   { TWIZEnlistAccountForSale_EnterPublicKey }
 
 
-  TWIZEnlistAccountForSale_EnterPublicKey = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSale_EnterPublicKey = class(TWizardForm<TWIZOperationsModel>)
     gbTransaction: TGroupBox;
     gbTransaction: TGroupBox;
     lblBlockLock: TLabel;
     lblBlockLock: TLabel;
     lblPublicKey: TLabel;
     lblPublicKey: TLabel;

+ 3 - 2
src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterSaleAmount.pas

@@ -18,13 +18,14 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet, UCoreObjects,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet, UCoreObjects,
-  UFRMAccountSelect, UNode, UWizard, UWIZOperationFee_Custom, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
+  UFRMAccountSelect, UNode,
+  UWizard, UWIZOperation, UWIZOperationFee_Custom, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
 
 
 type
 type
 
 
   { TWIZEnlistAccountForSale_EnterSaleAmount }
   { TWIZEnlistAccountForSale_EnterSaleAmount }
 
 
-  TWIZEnlistAccountForSale_EnterSaleAmount = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSale_EnterSaleAmount = class(TWizardForm<TWIZOperationsModel>)
     chkChooseFee: TCheckBox;
     chkChooseFee: TCheckBox;
     chkAttachPayload: TCheckBox;
     chkAttachPayload: TCheckBox;
     edtAmt: TEdit;
     edtAmt: TEdit;

+ 2 - 2
src/gui/wizards/operations/UWIZEnlistAccountForSale_EnterSeller.pas

@@ -18,13 +18,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
-  UFRMAccountSelect, UNode, UWizard, UCoreObjects;
+  UFRMAccountSelect, UNode, UWizard, UCoreObjects, UWIZOperation;
 
 
 type
 type
 
 
   { TWIZEnlistAccountForSale_EnterSeller }
   { TWIZEnlistAccountForSale_EnterSeller }
 
 
-  TWIZEnlistAccountForSale_EnterSeller = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSale_EnterSeller = class(TWizardForm<TWIZOperationsModel>)
     edtSellerAcc: TEdit;
     edtSellerAcc: TEdit;
     gbSeller: TGroupBox;
     gbSeller: TGroupBox;
     lblSellerAccount: TLabel;
     lblSellerAccount: TLabel;

+ 2 - 2
src/gui/wizards/operations/UWIZEnlistAccountForSale_SelectOption.pas

@@ -13,13 +13,13 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
-  ExtCtrls, UWizard, UCoreObjects, UWIZEnlistAccountForSale_EnterPublicKey;
+  ExtCtrls, UWizard, UCoreObjects, UWIZOperation, UWIZEnlistAccountForSale_EnterPublicKey;
 
 
 type
 type
 
 
   { TWIZEnlistAccountForSale_SelectOption }
   { TWIZEnlistAccountForSale_SelectOption }
 
 
-  TWIZEnlistAccountForSale_SelectOption = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSale_SelectOption = class(TWizardForm<TWIZOperationsModel>)
     grpEnlistAccountForSale: TGroupBox;
     grpEnlistAccountForSale: TGroupBox;
     Label1: TLabel;
     Label1: TLabel;
     Label2: TLabel;
     Label2: TLabel;

+ 825 - 0
src/gui/wizards/operations/UWIZOperation.pas

@@ -0,0 +1,825 @@
+unit UWIZOperation;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 Sphere 10 Software (http://www.sphere10.com/)
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+
+  Acknowledgements:
+  Ugochukwu Mmaduekwe - main developer
+  Herman Schoenfeld - designer
+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Dialogs, UBaseTypes, UCommon, UWizard, UAccounts, UBlockChain, UNode, UWallet, UCoreObjects, LCLType;
+
+type
+
+  { TWIZOperationsModel }
+
+  TWIZOperationsModel = class(TComponent)
+    public
+      type
+
+      { TExecuteOperationType }
+
+      TExecuteOperationType = (omtAccount, omtSendPasc, omtChangeKey, omtTransferAccount, omtChangeAccountPrivateKey, omtAddKey, omtEnlistAccountForSale);
+
+      { TPayloadEncryptionMode }
+
+      TPayloadEncryptionMode = (pemEncryptWithSender, pemEncryptWithReceiver, pemEncryptWithPassword, pemNotEncrypt);
+
+      { TOperationSigningMode }
+
+      TOperationSigningMode = (akaPrimary, akaSecondary);
+
+      { TChangeKeyMode }
+
+      TChangeKeyMode = (akaTransferAccountOwnership, akaChangeAccountPrivateKey);
+
+      { TSendPASCMode }
+
+      TSendPASCMode = (akaAllBalance, akaSpecifiedAmount);
+
+      { TAccountSaleMode }
+      TAccountSaleMode = (akaPublicSale, akaPrivateSale);
+
+      { TOperationExecuteResultHandler }
+
+      TOperationExecuteResultHandler =
+      procedure(const ASourceAccount: TAccount; AOpType: TExecuteOperationType; const AOpText: ansistring; Result: boolean; const Message: ansistring) of object;
+
+
+      { TAccountModel }
+
+      TAccountModel = class(TComponent)
+      public
+        SelectedAccounts: TArray<TAccount>;
+      end;
+
+      { TSendPASCModel }
+
+      TSendPASCModel = class(TComponent)
+      public
+        SingleAmountToSend: int64;
+        DestinationAccount: TAccount;
+        SendPASCMode: TSendPASCMode;
+      end;
+
+      { TChangeKeyModel }
+
+      TChangeKeyModel = class(TComponent)
+      public
+        ChangeKeyMode: TChangeKeyMode;
+      end;
+
+      { TTransferAccountModel }
+
+      TTransferAccountModel = class(TComponent)
+      public
+        AccountKey: TAccountKey;
+      end;
+
+      { TChangeAccountPrivateKeyModel }
+
+      TChangeAccountPrivateKeyModel = class(TComponent)
+      public
+        SelectedIndex: integer;
+        NewWalletKey: TWalletKey;
+      end;
+
+      { TWIZEnlistAccountForSaleModel }
+      TEnlistAccountForSaleModel = class(TComponent)
+      public
+        SalePrice: int64;
+        NewOwnerPublicKey: TAccountKey;
+        LockedUntilBlock: cardinal;
+        SellerAccount: TAccount;
+        AccountSaleMode: TAccountSaleMode;
+      end;
+
+      { TFeeModel }
+
+      TFeeModel = class(TComponent)
+      public
+        DefaultFee, SingleOperationFee: int64;
+      end;
+
+      { TSignerModel }
+
+      TSignerModel = class(TComponent)
+      public
+        OperationSigningMode: TOperationSigningMode;
+        SignerAccount: TAccount;
+        SignerCandidates: TArray<TAccount>;
+        SelectedIndex: integer;
+      end;
+
+      { TPayloadModel }
+
+      TPayloadModel = class(TComponent)
+      public
+        HasPayload: boolean;
+        Content, Password: string;
+        PayloadEncryptionMode: TPayloadEncryptionMode;
+        EncodedBytes: TRawBytes;
+      end;
+
+    private
+      FExecuteOperationType: TExecuteOperationType;
+      FAccount: TAccountModel;
+      FSendPASC: TSendPASCModel;
+      FChangeKey: TChangeKeyModel;
+      FTransferAccount: TTransferAccountModel;
+      FChangeAccountPrivateKey: TChangeAccountPrivateKeyModel;
+      FEnlistAccountForSale: TEnlistAccountForSaleModel;
+      FFee: TFeeModel;
+      FSigner: TSignerModel;
+      FPayload: TPayloadModel;
+    public
+      constructor Create(AOwner: TComponent; AType: TExecuteOperationType); overload;
+      property ExecuteOperationType: TExecuteOperationType read FExecuteOperationType;
+      property Account: TAccountModel read FAccount;
+      property SendPASC: TSendPASCModel read FSendPASC;
+      property ChangeKey: TChangeKeyModel read FChangeKey;
+      property TransferAccount: TTransferAccountModel read FTransferAccount;
+      property ChangeAccountPrivateKey: TChangeAccountPrivateKeyModel read FChangeAccountPrivateKey;
+      property EnlistAccountForSale: TEnlistAccountForSaleModel read FEnlistAccountForSale;
+      property Fee: TFeeModel read FFee;
+      property Signer: TSignerModel read FSigner;
+      property Payload: TPayloadModel read FPayload;
+  end;
+
+
+  { TWIZOperationsHelper }
+
+  TWIZOperationsHelper = class
+  private
+    class function UpdatePayload(const ASenderPublicKey, ADestinationPublicKey: TAccountKey; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent: string; var AEncodedPayloadBytes: TRawBytes; const APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
+    class function SendPASCFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalAmount, ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean; static;
+    class function OthersFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean; static;
+  public
+    class function ExecuteOperations(const ANewOps: TWIZOperationsModel; AHandler: TWIZOperationsModel.TOperationExecuteResultHandler; var errors: ansistring): boolean; static;
+    class function ExecuteSendPASC(const ASelectedAccounts: TArray<TAccount>; const ADestinationAccount, ASignerAccount: TAccount; AAmount, AFee: int64; const ASendPASCMode: TWIZOperationsModel.TSendPASCMode; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean; static;
+    class function ExecuteChangeKey(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount: TAccount; APublicKey: TAccountKey; AFee: int64; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean; static;
+    class function ExecuteEnlistAccountForSale(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount, ASellerAccount: TAccount; const APublicKey: TAccountKey; AFee, ASalePrice: int64; ALockedUntilBlock: UInt32; const AAccountSaleMode: TWIZOperationsModel.TAccountSaleMode; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean; static;
+  end;
+
+implementation
+
+uses
+  UCrypto, UECIES, UAES, UConst, UCoreUtils, UOpTransaction;
+
+{ TWIZOperationsModel }
+
+constructor TWIZOperationsModel.Create(AOwner: TComponent; AType: TWIZOperationsModel.TExecuteOperationType);
+begin
+  inherited Create(AOwner);
+  FExecuteOperationType := AType;
+  FAccount := TAccountModel.Create(Self);
+  FSendPASC := TSendPASCModel.Create(Self);
+  FChangeKey := TChangeKeyModel.Create(Self);
+  FTransferAccount := TTransferAccountModel.Create(Self);
+  FChangeAccountPrivateKey := TChangeAccountPrivateKeyModel.Create(Self);
+  FEnlistAccountForSale := TEnlistAccountForSaleModel.Create(Self);
+  FFee := TFeeModel.Create(Self);
+  FSigner := TSignerModel.Create(Self);
+  FPayload := TPayloadModel.Create(Self);
+end;
+
+{ TWIZOperationsHelper }
+
+class function TWIZOperationsHelper.SendPASCFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalAmount, ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean;
+var
+  LAuxs, LOperationsTxt: string;
+  i: integer;
+begin
+  LOperationsTxt := AOperationsTxt;
+  if (ANoOfOperations > 1) then
+  begin
+    LAuxs := 'Total amount that dest will receive: ' + TAccountComp.FormatMoney(
+      ATotalAmount) + #10;
+    if Application.MessageBox(
+      PChar('Execute ' + IntToStr(ANoOfOperations) +
+      ' operations?' + #10 + 'Operation: ' + LOperationsTxt + #10 +
+      LAuxs + 'Total fee: ' + TAccountComp.FormatMoney(ATotalFee) +
+      #10 + #10 + 'Note: This operation will be transmitted to the network!'),
+      PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
+      idYes then
+      Exit;
+  end
+  else
+  if Application.MessageBox(PChar('Execute this operation:' +
+    #10 + #10 + AOperationToString + #10 + #10 +
+    'Note: This operation will be transmitted to the network!'),
+    PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
+    idYes then
+    Exit;
+  Result := True;
+  i := TNode.Node.AddOperations(nil, AOperationsHashTree, nil, AErrorMessage);
+  if (i = AOperationsHashTree.OperationsCount) then
+  begin
+    LOperationsTxt := 'Successfully executed ' + IntToStr(i) +
+      ' operations!' + #10 + #10 + AOperationToString;
+    if i > 1 then
+      ShowMessage(LOperationsTxt)
+    else
+    begin
+      Application.MessageBox(
+        PChar('Successfully executed ' + IntToStr(i) + ' operations!' +
+        #10 + #10 + AOperationToString),
+        PChar(Application.Title), MB_OK + MB_ICONINFORMATION);
+    end;
+  end
+  else if (i > 0) then
+  begin
+    LOperationsTxt := 'One or more of your operations has not been executed:' +
+      #10 + 'Errors:' + #10 + AErrorMessage + #10 + #10 +
+      'Total successfully executed operations: ' + IntToStr(i);
+    ShowMessage(LOperationsTxt);
+  end
+  else
+    Result := False;
+end;
+
+class function TWIZOperationsHelper.UpdatePayload(const ASenderPublicKey, ADestinationPublicKey: TAccountKey; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent: string; var AEncodedPayloadBytes: TRawBytes; const APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
+var
+  LValid: boolean;
+begin
+
+  if (APayloadContent = '') then
+    Exit(True);
+
+  LValid := False;
+  AErrorMessage := 'An Error Occured During Payload Encryption.';
+
+  try
+
+    case APayloadEncryptionMode of
+
+      pemEncryptWithSender:
+      begin
+        // Use sender public key
+        AEncodedPayloadBytes := ECIESEncrypt(ASenderPublicKey, APayloadContent);
+        LValid := AEncodedPayloadBytes <> '';
+      end;
+
+      pemEncryptWithReceiver:
+      begin
+        // With destination public key
+        AEncodedPayloadBytes := ECIESEncrypt(ADestinationPublicKey, APayloadContent);
+        LValid := AEncodedPayloadBytes <> '';
+      end;
+
+      pemEncryptWithPassword:
+      begin
+        // With defined password
+        if APayloadEncryptionPassword = '' then
+        begin
+          AErrorMessage := 'Payload Encryption Password Cannot Be Empty With The Chosen Option : "Encrypt With Password."';
+          Exit(False);
+        end;
+        AEncodedPayloadBytes := TAESComp.EVP_Encrypt_AES256(
+          APayloadContent, APayloadEncryptionPassword);
+        LValid := AEncodedPayloadBytes <> '';
+      end;
+
+      pemNotEncrypt:
+      begin
+        // no encryption
+        AEncodedPayloadBytes := APayloadContent;
+        LValid := True;
+      end
+
+      else
+      begin
+        AErrorMessage := 'Unknown Encryption Selected';
+        Exit(False);
+      end;
+    end;
+
+  finally
+    if LValid then
+      if Length(AEncodedPayloadBytes) > CT_MaxPayloadSize then
+      begin
+        LValid := False;
+        AErrorMessage := Format('Payload Size Is %d Which Is Bigger Than %d', [Length(AEncodedPayloadBytes), CT_MaxPayloadSize]);
+      end;
+    Result := LValid;
+  end;
+end;
+
+class function TWIZOperationsHelper.OthersFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean;
+var
+  LAuxs, LOperationsTxt: string;
+  i: integer;
+begin
+  LOperationsTxt := AOperationsTxt;
+  if (ANoOfOperations > 1) then
+  begin
+    LAuxs := '';
+    if Application.MessageBox(
+      PChar('Execute ' + IntToStr(ANoOfOperations) +
+      ' operations?' + #10 + 'Operation: ' + LOperationsTxt + #10 +
+      LAuxs + 'Total fee: ' + TAccountComp.FormatMoney(ATotalFee) +
+      #10 + #10 + 'Note: This operation will be transmitted to the network!'),
+      PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
+      idYes then
+      Exit;
+  end
+  else
+  if Application.MessageBox(PChar('Execute this operation:' +
+    #10 + #10 + AOperationToString + #10 + #10 +
+    'Note: This operation will be transmitted to the network!'),
+    PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
+    idYes then
+    Exit;
+  Result := True;
+  i := TNode.Node.AddOperations(nil, AOperationsHashTree, nil, AErrorMessage);
+  if (i = AOperationsHashTree.OperationsCount) then
+  begin
+    LOperationsTxt := 'Successfully executed ' + IntToStr(i) +
+      ' operations!' + #10 + #10 + AOperationToString;
+    if i > 1 then
+      ShowMessage(LOperationsTxt)
+    else
+    begin
+      Application.MessageBox(
+        PChar('Successfully executed ' + IntToStr(i) + ' operations!' +
+        #10 + #10 + AOperationToString),
+        PChar(Application.Title), MB_OK + MB_ICONINFORMATION);
+    end;
+  end
+  else if (i > 0) then
+  begin
+    LOperationsTxt := 'One or more of your operations has not been executed:' +
+      #10 + 'Errors:' + #10 + AErrorMessage + #10 + #10 +
+      'Total successfully executed operations: ' + IntToStr(i);
+    ShowMessage(LOperationsTxt);
+  end
+  else
+    Result := False;
+end;
+
+class function TWIZOperationsHelper.ExecuteOperations(const ANewOps: TWIZOperationsModel; AHandler: TWIZOperationsModel.TOperationExecuteResultHandler; var errors: ansistring): boolean;
+begin
+
+end;
+
+class function TWIZOperationsHelper.ExecuteSendPASC(const ASelectedAccounts: TArray<TAccount>; const ADestinationAccount, ASignerAccount: TAccount; AAmount, AFee: int64; const ASendPASCMode: TWIZOperationsModel.TSendPASCMode; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
+var
+  LWalletKey: TWalletKey;
+  LWalletKeys: TWalletKeys;
+  LNode: TNode;
+  LPCOperation: TPCOperation;
+  LOperationsHashTree: TOperationsHashTree;
+  LTotalAmount, LTotalSignerFee, LAmount, LFee: int64;
+  LDoOperation: boolean;
+  LOperationsTxt, LOperationToString: string;
+  LIdx, LAccountIdx, LNoOfOperations: integer;
+  LCurrentAccount: TAccount;
+  LPayloadEncodedBytes: TRawBytes;
+begin
+  if Length(ASelectedAccounts) = 0 then
+  begin
+    AErrorMessage := 'No Selected Account Found';
+    Exit(False);
+  end;
+
+  LWalletKeys := TWallet.Keys;
+  LNode := TNode.Node;
+
+  if not Assigned(LWalletKeys) then
+  begin
+    AErrorMessage := 'No Wallet Keys Found';
+    Exit(False);
+  end;
+
+  if not Assigned(LNode) then
+  begin
+    AErrorMessage := 'No Node Found';
+    Exit(False);
+  end;
+
+  LOperationsHashTree := TOperationsHashTree.Create;
+  try
+    LTotalAmount := 0;
+    LTotalSignerFee := 0;
+    LNoOfOperations := 0;
+    LOperationsTxt := '';
+    LOperationToString := '';
+    for LAccountIdx := Low(ASelectedAccounts) to High(ASelectedAccounts) do
+    begin
+      LPCOperation := nil; // reset LPCOperation to Nil
+      LCurrentAccount := ASelectedAccounts[LAccountIdx];
+
+      if LCurrentAccount.account = ADestinationAccount.account then
+      begin
+        AErrorMessage := Format('Sender "%s" And Destination "%s" Accounts Are The Same', [LCurrentAccount.AccountString, ADestinationAccount.AccountString]);
+        Exit(False);
+      end;
+
+      if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, ADestinationAccount.accountInfo.accountKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
+      begin
+        AErrorMessage := Format('Error Encoding Payload Of Selected Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
+        Exit(False);
+      end;
+
+      LIdx := LWalletKeys.IndexOfAccountKey(LCurrentAccount.accountInfo.accountKey);
+      if LIdx < 0 then
+      begin
+        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
+        Exit(False);
+      end;
+      LWalletKey := LWalletKeys.Key[LIdx];
+
+      if not Assigned(LWalletKey.PrivateKey) then
+      begin
+        if LWalletKey.HasPrivateKey then
+          AErrorMessage := 'Wallet is Password Protected. Please Unlock Before You Proceed.'
+        else
+          AErrorMessage := Format('Only Public Key of Account %s Was Found in Wallet. You Cannot Operate This Account', [LCurrentAccount.AccountString]);
+        Exit(False);
+      end;
+
+      LDoOperation := True;
+
+      if LCurrentAccount.balance > 0 then
+        case ASendPASCMode of
+          akaAllBalance:
+          begin
+            LAmount := LCurrentAccount.balance - AFee;
+            LFee := AFee;
+          end;
+
+          akaSpecifiedAmount:
+            if LCurrentAccount.balance >= UInt64(AAmount + AFee) then
+            begin
+              LAmount := AAmount;
+              LFee := AFee;
+            end
+            else
+            begin
+              AErrorMessage := Format('Insufficient Funds In "%s". %s < (%s + %s = %s)', [LCurrentAccount.AccountString, TAccountComp.FormatMoney(LCurrentAccount.balance), TAccountComp.FormatMoney(AAmount), TAccountComp.FormatMoney(AFee), TAccountComp.FormatMoney(AAmount + AFee)]);
+              Exit(False);
+            end;
+        end
+      else
+        LDoOperation := False;
+
+      if LDoOperation then
+      begin
+        LPCOperation := TOpTransaction.CreateTransaction(
+          LCurrentAccount.account, LCurrentAccount.n_operation + 1, ADestinationAccount.account, LWalletKey.PrivateKey, LAmount, LFee, LPayloadEncodedBytes);
+        try
+          LOperationsTxt := Format('Transaction To "%s"', [ADestinationAccount.AccountString]);
+
+          if Assigned(LPCOperation) then
+          begin
+            LOperationsHashTree.AddOperationToHashTree(LPCOperation);
+            Inc(LTotalAmount, LAmount);
+            Inc(LTotalSignerFee, LFee);
+            Inc(LNoOfOperations);
+            if LOperationToString <> '' then
+              LOperationToString := LOperationToString + #10;
+            LOperationToString := LOperationToString + LPCOperation.ToString;
+          end;
+        finally
+          FreeAndNil(LPCOperation);
+        end;
+      end;
+
+    end;
+    if (LOperationsHashTree.OperationsCount = 0) then
+    begin
+      AErrorMessage := 'No Valid Operation To Execute';
+      Exit(False);
+    end;
+
+    Exit(TWIZOperationsHelper.SendPASCFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalAmount, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
+  finally
+    LOperationsHashTree.Free;
+  end;
+
+end;
+
+class function TWIZOperationsHelper.ExecuteChangeKey(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount: TAccount; APublicKey: TAccountKey; AFee: int64; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
+var
+  LWalletKey: TWalletKey;
+  LWalletKeys: TWalletKeys;
+  LNode: TNode;
+  LPCOperation: TPCOperation;
+  LOperationsHashTree: TOperationsHashTree;
+  LTotalSignerFee, LFee: int64;
+  LIsV2: boolean;
+  LOperationsTxt, LOperationToString: string;
+  LIdx, LAccountIdx, LNoOfOperations: integer;
+  LCurrentAccount, LSignerAccount: TAccount;
+  LPayloadEncodedBytes: TRawBytes;
+label
+  loop_start;
+begin
+  if Length(ASelectedAccounts) = 0 then
+  begin
+    AErrorMessage := 'No Selected Account Found';
+    Exit(False);
+  end;
+
+  LWalletKeys := TWallet.Keys;
+  LNode := TNode.Node;
+
+  if not Assigned(LWalletKeys) then
+  begin
+    AErrorMessage := 'No Wallet Keys Found';
+    Exit(False);
+  end;
+
+  if not Assigned(LNode) then
+  begin
+    AErrorMessage := 'No Node Found';
+    Exit(False);
+  end;
+
+  LOperationsHashTree := TOperationsHashTree.Create;
+  try
+    LIsV2 := LNode.Bank.SafeBox.CurrentProtocol >= CT_PROTOCOL_2;
+    LTotalSignerFee := 0;
+    LNoOfOperations := 0;
+    LOperationsTxt := '';
+    LOperationToString := '';
+    for LAccountIdx := Low(ASelectedAccounts) to High(ASelectedAccounts) do
+    begin
+      loop_start:
+        LPCOperation := nil; // reset LPCOperation to Nil
+      LCurrentAccount := ASelectedAccounts[LAccountIdx];
+
+      if (TAccountComp.EqualAccountKeys(LCurrentAccount.accountInfo.accountKey,
+        APublicKey)) then
+      begin
+        AErrorMessage := 'New Key Is Same As Current Key';
+        Exit(False);
+      end;
+
+      if LNode.Bank.SafeBox.CurrentProtocol >= 1 then
+      begin
+        // Signer:
+        LSignerAccount := ASignerAccount;
+        if (TAccountComp.IsAccountLocked(LSignerAccount.accountInfo,
+          LNode.Bank.BlocksCount)) then
+        begin
+          AErrorMessage := Format('Signer Account "%s"  Is Locked Until Block %u', [LSignerAccount.AccountString, LSignerAccount.accountInfo.locked_until_block]);
+          Exit(False);
+        end;
+        if (not TAccountComp.EqualAccountKeys(
+          LSignerAccount.accountInfo.accountKey, LCurrentAccount.accountInfo.accountKey)) then
+        begin
+          AErrorMessage := Format('Signer Account %s Is Not The Owner Of Account %s', [LSignerAccount.AccountString, LCurrentAccount.AccountString]);
+          Exit(False);
+        end;
+      end
+      else
+        LSignerAccount := LCurrentAccount;
+
+      if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, APublicKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
+      begin
+        AErrorMessage := Format('Error Encoding Payload Of Selected Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
+        Exit(False);
+      end;
+
+      LIdx := LWalletKeys.IndexOfAccountKey(LCurrentAccount.accountInfo.accountKey);
+      if LIdx < 0 then
+      begin
+        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
+        Exit(False);
+      end;
+      LWalletKey := LWalletKeys.Key[LIdx];
+
+      if not Assigned(LWalletKey.PrivateKey) then
+      begin
+        if LWalletKey.HasPrivateKey then
+          AErrorMessage := 'Wallet Is Password Protected. Please Unlock Before You Proceed.'
+        else
+          AErrorMessage := Format('Only Public Key of Account %s Was Found In Wallet. You Cannot Operate This Account', [LCurrentAccount.AccountString]);
+        Exit(False);
+      end;
+
+      if LIsV2 then
+      begin
+        // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
+        if (LAccountIdx < Length(ASelectedAccounts) - 1) and
+          (LCurrentAccount.account = LSignerAccount.account) then
+        begin
+          TArrayTool<TAccount>.Swap(ASelectedAccounts, LAccountIdx,
+            Length(ASelectedAccounts) - 1); // ensure signer account processed last
+          goto loop_start; // TODO: remove ugly hack with refactoring!
+        end;
+
+        // Maintain correct signer fee distribution
+        if Uint64(LTotalSignerFee) >= LSignerAccount.balance then
+          LFee := 0
+        else if LSignerAccount.balance - uint64(LTotalSignerFee) >
+          UInt64(AFee) then
+          LFee := AFee
+        else
+          LFee := LSignerAccount.balance - UInt64(LTotalSignerFee);
+        LPCOperation := TOpChangeKeySigned.Create(LSignerAccount.account,
+          LSignerAccount.n_operation + LNoOfOperations + 1, LCurrentAccount.account,
+          LWalletKey.PrivateKey, APublicKey, LFee, LPayloadEncodedBytes);
+      end
+      else
+        LPCOperation := TOpChangeKey.Create(LCurrentAccount.account, LCurrentAccount.n_operation +
+          1, LCurrentAccount.account, LWalletKey.PrivateKey, APublicKey, LFee, LPayloadEncodedBytes);
+
+      try
+        LOperationsTxt := Format('Change Key To "%s"', [TAccountComp.GetECInfoTxt(APublicKey.EC_OpenSSL_NID)]);
+        if Assigned(LPCOperation) then
+        begin
+          LOperationsHashTree.AddOperationToHashTree(LPCOperation);
+          Inc(LNoOfOperations);
+          Inc(LTotalSignerFee, LFee);
+          if LOperationToString <> '' then
+            LOperationToString := LOperationToString + #10;
+          LOperationToString := LOperationToString + LPCOperation.ToString;
+        end;
+      finally
+        FreeAndNil(LPCOperation);
+      end;
+
+    end;
+
+    if (LOperationsHashTree.OperationsCount = 0) then
+    begin
+      AErrorMessage := 'No Valid Operation to Execute';
+      Exit(False);
+    end;
+
+    Exit(TWIZOperationsHelper.OthersFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
+  finally
+    LOperationsHashTree.Free;
+  end;
+
+end;
+
+class function TWIZOperationsHelper.ExecuteEnlistAccountForSale(const ASelectedAccounts: TArray<TAccount>; const ASignerAccount, ASellerAccount: TAccount; const APublicKey: TAccountKey; AFee, ASalePrice: int64; ALockedUntilBlock: UInt32; const AAccountSaleMode: TWIZOperationsModel.TAccountSaleMode; const APayloadEncryptionMode: TWIZOperationsModel.TPayloadEncryptionMode; const APayloadContent, APayloadEncryptionPassword: string; var AErrorMessage: string): boolean;
+var
+  LWalletKey: TWalletKey;
+  LWalletKeys: TWalletKeys;
+  LNode: TNode;
+  LPCOperation: TPCOperation;
+  LOperationsHashTree: TOperationsHashTree;
+  LTotalSignerFee, LFee: int64;
+  LOperationsTxt, LOperationToString: string;
+  LIdx, LAccountIdx, LNoOfOperations: integer;
+  LCurrentAccount, LSignerAccount: TAccount;
+  LPayloadEncodedBytes: TRawBytes;
+begin
+  if Length(ASelectedAccounts) = 0 then
+  begin
+    AErrorMessage := 'No Selected Account Found';
+    Exit(False);
+  end;
+
+  LWalletKeys := TWallet.Keys;
+  LNode := TNode.Node;
+
+  if not Assigned(LWalletKeys) then
+  begin
+    AErrorMessage := 'No Wallet Keys Found';
+    Exit(False);
+  end;
+
+  if not Assigned(LNode) then
+  begin
+    AErrorMessage := 'No Node Found';
+    Exit(False);
+  end;
+
+  LOperationsHashTree := TOperationsHashTree.Create;
+  try
+    LTotalSignerFee := 0;
+    LNoOfOperations := 0;
+    LOperationsTxt := '';
+    LOperationToString := '';
+
+    for LAccountIdx := Low(ASelectedAccounts) to High(ASelectedAccounts) do
+    begin
+      LPCOperation := nil; // reset LPCOperation to Nil
+      LCurrentAccount := ASelectedAccounts[LAccountIdx];
+
+      if TAccountComp.IsAccountForSale(LCurrentAccount.accountInfo) then
+      begin
+        AErrorMessage := Format('Account "%s" Is Already Enlisted For Sale', [LCurrentAccount.AccountString]);
+        Exit(False);
+      end;
+
+      if (ASellerAccount.account = LCurrentAccount.account) then
+      begin
+        AErrorMessage := 'Seller Account Cannot Be Same As Account To Be Sold.';
+        Exit(False);
+      end;
+
+      if (LNode.Node.Bank.SafeBox.CurrentProtocol = CT_PROTOCOL_1) then
+      begin
+        AErrorMessage := 'This Operation Needs PROTOCOL 2 Active';
+        Exit(False);
+      end;
+
+      if AAccountSaleMode = akaPrivateSale then
+      begin
+
+        if TAccountComp.EqualAccountKeys(APublicKey,
+          LCurrentAccount.accountInfo.accountKey) then
+        begin
+          AErrorMessage := 'You Cannot Sell To An Account That You Want To Enlist For Sale.';
+          Exit(False);
+        end;
+
+        if ALockedUntilBlock = 0 then
+        begin
+          AErrorMessage := 'You Didn''t Insert a Locking Block.';
+          Exit(False);
+        end;
+      end;
+
+      if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, APublicKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
+      begin
+        AErrorMessage := Format('Error Encoding Payload Of Selected Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
+        Exit(False);
+      end;
+
+      LIdx := LWalletKeys.IndexOfAccountKey(LCurrentAccount.accountInfo.accountKey);
+      if LIdx < 0 then
+      begin
+        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
+        Exit(False);
+      end;
+      LWalletKey := LWalletKeys.Key[LIdx];
+
+      if not Assigned(LWalletKey.PrivateKey) then
+      begin
+        if LWalletKey.HasPrivateKey then
+          AErrorMessage := 'Wallet Is Password Protected. Please Unlock Before You Proceed.'
+        else
+          AErrorMessage := Format('Only Public Key Of Account %s Was Found In Wallet. You Cannot Operate This Account', [LCurrentAccount.AccountString]);
+        Exit(False);
+      end;
+
+      if ASignerAccount.balance > AFee then
+        LFee := AFee
+      else
+        LFee := ASignerAccount.balance;
+
+      case AAccountSaleMode of
+        akaPublicSale:
+
+          LPCOperation := TOpListAccountForSale.CreateListAccountForSale(
+            ASignerAccount.account, ASignerAccount.n_operation + 1 + LAccountIdx,
+            LCurrentAccount.account, ASalePrice, LFee, ASellerAccount.account,
+            APublicKey, 0, LWalletKey.PrivateKey, LPayloadEncodedBytes);
+
+        akaPrivateSale:
+
+          LPCOperation := TOpListAccountForSale.CreateListAccountForSale(
+            ASignerAccount.account, ASignerAccount.n_operation + 1 + LAccountIdx,
+            LCurrentAccount.account, ASalePrice, LFee, ASellerAccount.account,
+            APublicKey, ALockedUntilBlock, LWalletKey.PrivateKey, LPayloadEncodedBytes)
+
+        else
+          raise Exception.Create('Invalid Account Sale Type')
+      end;
+
+      try
+        LOperationsTxt := Format('Enlist Account For Sale At a Price Of "%s" PASC', [TAccountComp.FormatMoney(ASalePrice)]);
+        if Assigned(LPCOperation) then
+        begin
+          LOperationsHashTree.AddOperationToHashTree(LPCOperation);
+          Inc(LNoOfOperations);
+          Inc(LTotalSignerFee, LFee);
+          if LOperationToString <> '' then
+            LOperationToString := LOperationToString + #10;
+          LOperationToString := LOperationToString + LPCOperation.ToString;
+        end;
+      finally
+        FreeAndNil(LPCOperation);
+      end;
+
+    end;
+
+    if (LOperationsHashTree.OperationsCount = 0) then
+    begin
+      AErrorMessage := 'No Valid Operation to Execute';
+      Exit(False);
+    end;
+
+    Exit(TWIZOperationsHelper.OthersFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
+
+  finally
+    LOperationsHashTree.Free;
+  end;
+end;
+
+end.

+ 7 - 7
src/gui/wizards/operations/UWIZOperationConfirmation.pas

@@ -17,13 +17,13 @@ interface
 
 
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
-  ExtCtrls, UVisualGrid, UCellRenderers, UCommon.Data, UWizard, UCoreObjects;
+  ExtCtrls, UVisualGrid, UCellRenderers, UCommon.Data, UWizard, UWIZOperation, UCoreObjects;
 
 
 type
 type
 
 
   { TWIZOperationConfirmation }
   { TWIZOperationConfirmation }
 
 
-  TWIZOperationConfirmation = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationConfirmation = class(TWizardForm<TWIZOperationsModel>)
     GroupBox1: TGroupBox;
     GroupBox1: TGroupBox;
     lblSignerAccount: TLabel;
     lblSignerAccount: TLabel;
     lblBeneficiaryAccount: TLabel;
     lblBeneficiaryAccount: TLabel;
@@ -52,12 +52,12 @@ type
 
 
   TOperationConfirmationDataSource = class(TAccountsDataSourceBase)
   TOperationConfirmationDataSource = class(TAccountsDataSourceBase)
   private
   private
-    FModel: TExecuteOperationsModel;
+    FModel: TWIZOperationsModel;
 
 
   protected
   protected
     function GetColumns: TDataColumns; override;
     function GetColumns: TDataColumns; override;
   public
   public
-    property Model: TExecuteOperationsModel read FModel write FModel;
+    property Model: TWIZOperationsModel read FModel write FModel;
     procedure FetchAll(const AContainer: TList<TAccount>); override;
     procedure FetchAll(const AContainer: TList<TAccount>); override;
     function GetItemField(constref AItem: TAccount; const ABindingName: ansistring): variant; override;
     function GetItemField(constref AItem: TAccount; const ABindingName: ansistring): variant; override;
   end;
   end;
@@ -190,12 +190,12 @@ begin
       omtSendPasc:
       omtSendPasc:
       begin
       begin
         Result := IIF(Model.SendPASC.SendPASCMode = akaAllBalance, 'All Balance', Format('%s ', [TAccountComp.FormatMoney(Model.SendPASC.SingleAmountToSend)]));
         Result := IIF(Model.SendPASC.SendPASCMode = akaAllBalance, 'All Balance', Format('%s ', [TAccountComp.FormatMoney(Model.SendPASC.SingleAmountToSend)]));
-        Result := Format('%s %s', [TOperationsManager.GetOperationShortText(CT_Op_Transaction, CT_OpSubtype_TransactionSender), Result]);
+        Result := Format('%s %s', [TCoreTool.GetOperationShortText(CT_Op_Transaction, CT_OpSubtype_TransactionSender), Result]);
       end;
       end;
       omtChangeKey:
       omtChangeKey:
-        Result := Format('%s', [TOperationsManager.GetOperationShortText(CT_Op_ChangeKeySigned, CT_OpSubtype_ChangeKey)]);
+        Result := Format('%s', [TCoreTool.GetOperationShortText(CT_Op_ChangeKeySigned, CT_OpSubtype_ChangeKey)]);
       omtEnlistAccountForSale:
       omtEnlistAccountForSale:
-        Result := Format('%s', [TOperationsManager.GetOperationShortText(CT_Op_ListAccountForSale, IIF(Model.EnlistAccountForSale.AccountSaleMode = akaPrivateSale, CT_OpSubtype_ListAccountForPrivateSale, CT_OpSubtype_ListAccountForPublicSale))]);
+        Result := Format('%s', [TCoreTool.GetOperationShortText(CT_Op_ListAccountForSale, IIF(Model.EnlistAccountForSale.AccountSaleMode = akaPrivateSale, CT_OpSubtype_ListAccountForPrivateSale, CT_OpSubtype_ListAccountForPublicSale))]);
 
 
     end
     end
   else if ABindingName = 'Recipient' then
   else if ABindingName = 'Recipient' then

+ 3 - 2
src/gui/wizards/operations/UWIZOperationFee_Custom.pas

@@ -18,13 +18,14 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, Spin, UCommon, UCommon.Collections, UWallet, UCoreObjects,
   ExtCtrls, Buttons, Spin, UCommon, UCommon.Collections, UWallet, UCoreObjects,
-  UFRMAccountSelect, UNode, UWizard, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
+  UFRMAccountSelect, UNode,
+  UWizard, UWIZOperation, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
 
 
 type
 type
 
 
   { TWIZOperationFee_Custom }
   { TWIZOperationFee_Custom }
 
 
-  TWIZOperationFee_Custom = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationFee_Custom = class(TWizardForm<TWIZOperationsModel>)
     fseFee: TFloatSpinEdit;
     fseFee: TFloatSpinEdit;
     gbTransactionFee: TGroupBox;
     gbTransactionFee: TGroupBox;
     lblestimatedfee: TLabel;
     lblestimatedfee: TLabel;

+ 2 - 2
src/gui/wizards/operations/UWIZOperationPayload_Content.pas

@@ -18,13 +18,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections,
   ExtCtrls, Buttons, UCommon, UCommon.Collections,
-  UWizard, UWIZOperationSigner_Select, UCoreObjects;
+  UWizard, UWIZOperation, UWIZOperationSigner_Select, UCoreObjects;
 
 
 type
 type
 
 
   { TWIZOperationPayload_Content }
   { TWIZOperationPayload_Content }
 
 
-  TWIZOperationPayload_Content = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationPayload_Content = class(TWizardForm<TWIZOperationsModel>)
     grpPayload: TGroupBox;
     grpPayload: TGroupBox;
     Label1: TLabel;
     Label1: TLabel;
     mmoPayload: TMemo;
     mmoPayload: TMemo;

+ 7 - 7
src/gui/wizards/operations/UWIZOperationPayload_Encryption.pas

@@ -18,13 +18,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections,
   ExtCtrls, Buttons, UCommon, UCommon.Collections,
-  UWizard, UWIZOperationPayload_Content, UWIZOperationPayload_Password, UCoreObjects;
+  UWizard, UWIZOperation, UWIZOperationPayload_Content, UWIZOperationPayload_Password, UCoreObjects;
 
 
 type
 type
 
 
   { TWIZOperationPayload_Encryption }
   { TWIZOperationPayload_Encryption }
 
 
-  TWIZOperationPayload_Encryption = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationPayload_Encryption = class(TWizardForm<TWIZOperationsModel>)
     grpPayload: TGroupBox;
     grpPayload: TGroupBox;
     Label1: TLabel;
     Label1: TLabel;
     lblNoEncryption: TLabel;
     lblNoEncryption: TLabel;
@@ -55,25 +55,25 @@ procedure TWIZOperationPayload_Encryption.OnNext;
 begin
 begin
   if rbEncryptedWithRecipient.Checked then
   if rbEncryptedWithRecipient.Checked then
   begin
   begin
-    Model.Payload.PayloadEncryptionMode := akaEncryptWithSender;
+    Model.Payload.PayloadEncryptionMode := pemEncryptWithSender;
   end
   end
   else
   else
   if rbEncryptedWithSender.Checked then
   if rbEncryptedWithSender.Checked then
   begin
   begin
-    Model.Payload.PayloadEncryptionMode := akaEncryptWithReceiver;
+    Model.Payload.PayloadEncryptionMode := pemEncryptWithReceiver;
   end
   end
   else
   else
   if rbEncryptedWithPassword.Checked then
   if rbEncryptedWithPassword.Checked then
   begin
   begin
-    Model.Payload.PayloadEncryptionMode := akaEncryptWithPassword;
+    Model.Payload.PayloadEncryptionMode := pemEncryptWithPassword;
   end
   end
   else
   else
   if rbNotEncrypted.Checked then
   if rbNotEncrypted.Checked then
   begin
   begin
-    Model.Payload.PayloadEncryptionMode := akaNotEncrypt;
+    Model.Payload.PayloadEncryptionMode := pemNotEncrypt;
   end;
   end;
   case Model.Payload.PayloadEncryptionMode of
   case Model.Payload.PayloadEncryptionMode of
-    akaEncryptWithPassword:
+    pemEncryptWithPassword:
     begin
     begin
       UpdatePath(ptInject, [TWIZOperationPayload_Password]);
       UpdatePath(ptInject, [TWIZOperationPayload_Password]);
     end
     end

+ 2 - 2
src/gui/wizards/operations/UWIZOperationPayload_Password.pas

@@ -18,13 +18,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections,
   ExtCtrls, Buttons, UCommon, UCommon.Collections,
-  UWizard, UWIZOperationSigner_Select, UCoreObjects;
+  UWizard, UWIZOperation, UWIZOperationSigner_Select, UCoreObjects;
 
 
 type
 type
 
 
   { TWIZOperationPayload_Password }
   { TWIZOperationPayload_Password }
 
 
-  TWIZOperationPayload_Password = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationPayload_Password = class(TWizardForm<TWIZOperationsModel>)
     edtPassword: TEdit;
     edtPassword: TEdit;
     grpPayload: TGroupBox;
     grpPayload: TGroupBox;
     lblNote: TLabel;
     lblNote: TLabel;

+ 4 - 4
src/gui/wizards/operations/UWIZOperationSelected.pas

@@ -17,13 +17,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, UVisualGrid, UCommon.Data, UCellRenderers,
   ExtCtrls, UVisualGrid, UCommon.Data, UCellRenderers,
-  UWizard, UCoreObjects;
+  UWizard, UWIZOperation, UCoreObjects;
 
 
 type
 type
 
 
   { TWIZOperationSelected }
   { TWIZOperationSelected }
 
 
-  TWIZOperationSelected = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationSelected = class(TWizardForm<TWIZOperationsModel>)
     gpSelectedAccounts: TGroupBox;
     gpSelectedAccounts: TGroupBox;
     lblTotalBalances: TLabel;
     lblTotalBalances: TLabel;
     lblTotalBalanceValue: TLabel;
     lblTotalBalanceValue: TLabel;
@@ -49,9 +49,9 @@ type
 
 
   TOperationSelectedDataSource = class(TAccountsDataSourceBase)
   TOperationSelectedDataSource = class(TAccountsDataSourceBase)
   private
   private
-    FModel: TExecuteOperationsModel;
+    FModel: TWIZOperationsModel;
   public
   public
-    property Model: TExecuteOperationsModel read FModel write FModel;
+    property Model: TWIZOperationsModel read FModel write FModel;
     procedure FetchAll(const AContainer: TList<TAccount>); override;
     procedure FetchAll(const AContainer: TList<TAccount>); override;
   end;
   end;
 
 

+ 2 - 2
src/gui/wizards/operations/UWIZOperationSigner_Select.pas

@@ -18,13 +18,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
-  UFRMAccountSelect, UNode, UWizard, UCoreObjects;
+  UFRMAccountSelect, UNode, UWizard, UCoreObjects, UWIZOperation;
 
 
 type
 type
 
 
   { TWIZOperationSigner_Select }
   { TWIZOperationSigner_Select }
 
 
-  TWIZOperationSigner_Select = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationSigner_Select = class(TWizardForm<TWIZOperationsModel>)
     cbSignerAccount: TComboBox;
     cbSignerAccount: TComboBox;
     gbTransaction: TGroupBox;
     gbTransaction: TGroupBox;
     lblNote: TLabel;
     lblNote: TLabel;

+ 3 - 3
src/gui/wizards/operations/UWIZSendPASC.pas

@@ -15,13 +15,13 @@ unit UWIZSendPASC;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, Forms, Dialogs, UWizard, UCommon, UCoreObjects;
+  Classes, SysUtils, Forms, Dialogs, UWizard, UCommon, UCoreObjects, UWIZOperation;
 
 
 type
 type
 
 
   { TWIZSendPASCWizard }
   { TWIZSendPASCWizard }
 
 
-  TWIZSendPASCWizard = class(TWizard<TExecuteOperationsModel>)
+  TWIZSendPASCWizard = class(TWizard<TWIZOperationsModel>)
   public
   public
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     function DetermineHasNext: boolean; override;
     function DetermineHasNext: boolean; override;
@@ -68,7 +68,7 @@ end;
 function TWIZSendPASCWizard.FinishRequested(out message: ansistring): boolean;
 function TWIZSendPASCWizard.FinishRequested(out message: ansistring): boolean;
 begin
 begin
   // Execute the PASC Sending here
   // Execute the PASC Sending here
-  Result := TOperationsManager.ExecuteSendPASC(Model.Account.SelectedAccounts, Model.SendPASC.DestinationAccount, Model.Signer.SignerAccount, Model.SendPASC.SingleAmountToSend, Model.Fee.SingleOperationFee, Model.SendPASC.SendPASCMode, Model.Payload.PayloadEncryptionMode, IIF(Model.Payload.HasPayload, Model.Payload.Content, ''), Model.Payload.Password, message);
+  Result := TWIZOperationsHelper.ExecuteSendPASC(Model.Account.SelectedAccounts, Model.SendPASC.DestinationAccount, Model.Signer.SignerAccount, Model.SendPASC.SingleAmountToSend, Model.Fee.SingleOperationFee, Model.SendPASC.SendPASCMode, Model.Payload.PayloadEncryptionMode, IIF(Model.Payload.HasPayload, Model.Payload.Content, ''), Model.Payload.Password, message);
 end;
 end;
 
 
 function TWIZSendPASCWizard.CancelRequested(out message: ansistring): boolean;
 function TWIZSendPASCWizard.CancelRequested(out message: ansistring): boolean;

+ 3 - 2
src/gui/wizards/operations/UWIZSendPASC_EnterQuantity.pas

@@ -18,14 +18,15 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
-  UFRMAccountSelect, UNode, UWizard, UWIZSendPASC, UWIZOperationFee_Custom, UWIZOperationPayload_Encryption,
+  UFRMAccountSelect, UNode,
+  UWizard, UWIZOperation, UWIZSendPASC, UWIZOperationFee_Custom, UWIZOperationPayload_Encryption,
   UWIZOperationSigner_Select, UCoreObjects;
   UWIZOperationSigner_Select, UCoreObjects;
 
 
 type
 type
 
 
   { TWIZSendPASC_EnterQuantity }
   { TWIZSendPASC_EnterQuantity }
 
 
-  TWIZSendPASC_EnterQuantity = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZSendPASC_EnterQuantity = class(TWizardForm<TWIZOperationsModel>)
     chkChooseFee: TCheckBox;
     chkChooseFee: TCheckBox;
     chkAttachPayload: TCheckBox;
     chkAttachPayload: TCheckBox;
     chkallfunds: TCheckBox;
     chkallfunds: TCheckBox;

+ 2 - 2
src/gui/wizards/operations/UWIZSendPASC_EnterRecipient.pas

@@ -18,13 +18,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet, UCoreObjects,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet, UCoreObjects,
-  UFRMAccountSelect, UNode, UWizard, UWIZSendPASC, UWIZSendPASC_EnterQuantity, UCoreUtils;
+  UFRMAccountSelect, UNode, UWizard, UWIZOperation, UWIZSendPASC, UWIZSendPASC_EnterQuantity, UCoreUtils;
 
 
 type
 type
 
 
   { TWIZSendPASC_EnterRecipient }
   { TWIZSendPASC_EnterRecipient }
 
 
-  TWIZSendPASC_EnterRecipient = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZSendPASC_EnterRecipient = class(TWizardForm<TWIZOperationsModel>)
     edtDestAcc: TEdit;
     edtDestAcc: TEdit;
     gbRecipient: TGroupBox;
     gbRecipient: TGroupBox;
     lblDestAccNumber: TLabel;
     lblDestAccNumber: TLabel;

+ 1 - 1
src/pascalcoin_wallet.lpi

@@ -460,7 +460,7 @@
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit80>
       </Unit80>
       <Unit81>
       <Unit81>
-        <Filename Value="gui\wizards\operations\UWIZChangeKey.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZOperation.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit81>
       </Unit81>
       <Unit82>
       <Unit82>