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;
   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;
     Timestamp: cardinal;
     BlockProtocolVersion,
@@ -196,7 +60,7 @@ const
     TotalPASA : 0;
   );
 
-  CT_TBlockChainData_NUL: TBlockChainData = (
+  CT_BlockSummary_NUL: TBlockSummary = (
     Block: 0;
     Timestamp: 0;
     BlockProtocolVersion: 0;
@@ -223,20 +87,5 @@ const
 
 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.
 

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

@@ -62,22 +62,7 @@ type
   TCoreTool = class
   public
     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 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;
 
   { TOrderedAccountKeysListHelper }
@@ -135,186 +120,37 @@ uses
   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
-  LAuxs, LOperationsTxt: string;
-  i: integer;
+  i, PoorSenderCount: integer;
+  Fee, maxSignerFee, minSignerFee: int64;
+  acc: TAccount;
 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
-    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;
 
-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;
 
-class function TOperationsManager.GetOperationShortText(const OpType, OpSubType: DWord): ansistring;
+class function TCoreTool.GetOperationShortText(const OpType, OpSubType: DWord): ansistring;
 begin
   case OpType of
     CT_PseudoOp_Reward: case OpSubType of
@@ -359,487 +195,6 @@ begin
   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 }
 
@@ -847,10 +202,13 @@ function TNodeHelper.HasBestKnownBlockchainTip: boolean;
 var
   LReady: boolean;
   LMsg: ansistring;
+  LDestBlock : Cardinal;
 begin
   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;
+  end;
 end;
 
 { TOrderedAccountKeysListHelper }

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

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

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

@@ -122,7 +122,7 @@ Type
     Property OperationsResume : TOperationsResumeList read FOperationsResume;
   End;
 
-  TBlockChainData = Record
+  TBlockSummary = Record
     Block : Cardinal;
     Timestamp : Cardinal;
     BlockProtocolVersion,
@@ -145,7 +145,7 @@ Type
     TimeAverage25 : Real;
     TimeAverage10 : Real;
   End;
-  TBlockChainDataArray = Array of TBlockChainData;
+  TBlockSummaryArray = Array of TBlockSummary;
 
   { TBlockChainGrid }
 
@@ -153,7 +153,7 @@ Type
 
   TBlockChainGrid = Class(TComponent)
   private
-    FBlockChainDataArray : TBlockChainDataArray;
+    FBlockChainDataArray : TBlockSummaryArray;
     FBlockStart: Int64;
     FHashRateAs: TShowHashRateAs;
     FMaxBlocks: Integer;
@@ -193,7 +193,7 @@ Type
   End;
 
 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
@@ -1063,7 +1063,7 @@ end;
 procedure TBlockChainGrid.OnGridDrawCell(Sender: TObject; ACol, ARow: Longint;
   Rect: TRect; State: TGridDrawState);
 Var s : String;
-  bcd : TBlockChainData;
+  bcd : TBlockSummary;
   deviation : Real;
   hr_base : Int64;
 begin
@@ -1275,7 +1275,7 @@ end;
 procedure TBlockChainGrid.UpdateBlockChainGrid;
 Var nstart,nend : Cardinal;
   opc : TPCOperationsComp;
-  bcd : TBlockChainData;
+  bcd : TBlockSummary;
   i : Integer;
   opb : TOperationBlock;
   bn : TBigNum;
@@ -1310,7 +1310,7 @@ begin
       opc.bank := Node.Bank;
       while (nstart<=nend) do begin
         i := length(FBlockChainDataArray) - (nend-nstart+1);
-        bcd := CT_TBlockChainData_NUL;
+        bcd := CT_TBlockSummary_NUL;
         opb := Node.Bank.SafeBox.Block(nend).blockchainInfo;
         bcd.Block:=opb.block;
         bcd.Timestamp := opb.timestamp;

+ 1 - 0
src/gui/UCTRLBanner.lfm

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

+ 4 - 2
src/gui/UCTRLBanner.pas

@@ -2,12 +2,14 @@ unit UCTRLBanner;
 
 {$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
   or visit http://www.opensource.org/licenses/mit-license.php.
-}
 
+  Acknowledgements:
+  - Herman Schoenfeld: unit creator, implementation
+}
 
 interface
 

+ 2 - 1
src/gui/UCTRLSyncronization.lfm

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

+ 2 - 2
src/gui/UCTRLSyncronization.pas

@@ -2,13 +2,13 @@ unit UCTRLSyncronization;
 
 {$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
   or visit http://www.opensource.org/licenses/mit-license.php.
 
   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

+ 1 - 0
src/gui/UCTRLWallet.lfm

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

+ 21 - 12
src/gui/UCTRLWallet.pas

@@ -1,14 +1,22 @@
 unit UCTRLWallet;
 
 {$mode delphi}
-
 {$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
 
 uses
   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;
 
 type
@@ -95,7 +103,7 @@ implementation
 
 uses
   UUserInterface, UCellRenderers, UBlockChain, UWallet, UCrypto,
-  UCommon, UMemory, Generics.Defaults, UCommon.Data, UCommon.Collections;
+  UCommon, UMemory, Generics.Defaults, UCommon.Data, UCommon.Collections, UWIZOperation;
 
 {$R *.lfm}
 
@@ -112,6 +120,7 @@ begin
   FNodeNotifyEvents.OnBlocksChanged := OnNodeBlocksChanged;
   FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
   TWallet.Keys.OnChanged.Add(OnPrivateKeysChanged);
+  TWallet.Keys.AccountsKeyList.ClearAccountKeyChanges;   // XXXXX CLEAR BUFFER on start
 
   // fields
   FAccountsDataSource := TMyAccountsDataSource.Create(Self);
@@ -505,8 +514,8 @@ end;
 
 procedure TCTRLWallet.OnUserAccountsChanged;
 begin
-//  if NOT TUserInterface.Node.HasBestKnownBlockchainTip then
-//    exit; // node syncing
+  if NOT TUserInterface.Node.HasBestKnownBlockchainTip then
+    exit; // node syncing
 
   RefreshTotals;
   FAccountsGrid.RefreshGrid;
@@ -547,7 +556,7 @@ begin
     ophash := FOperationsGrid.Rows[row].OPHASH;
     if TPCOperation.IsValidOperationHash(ophash) then begin
       TUserInterface.ShowOperationInfoDialog(self, ophash);
-      FOperationsGrid.ClearSelection(true);
+      FOperationsGrid.ClearSelection;
     end;
   end;
 end;
@@ -612,7 +621,7 @@ procedure TCTRLWallet.miSendPASCClick(Sender: TObject);
 var
   Scoped: TDisposables;
   wiz: TWIZSendPASCWizard;
-  model: TExecuteOperationsModel;
+  model: TWIZOperationsModel;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
 
   function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
@@ -622,7 +631,7 @@ var
 
 begin
   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);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   wiz.Start(model);
@@ -632,7 +641,7 @@ procedure TCTRLWallet.miChangeKeyClick(Sender: TObject);
 var
   Scoped: TDisposables;
   wiz: TWIZChangeKeyWizard;
-  model: TExecuteOperationsModel;
+  model: TWIZOperationsModel;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
 
   function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
@@ -642,7 +651,7 @@ var
 
 begin
   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);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   wiz.Start(model);
@@ -652,7 +661,7 @@ procedure TCTRLWallet.miEnlistAccountsForSaleClick(Sender: TObject);
 var
   Scoped: TDisposables;
   wiz: TWIZEnlistAccountForSaleWizard;
-  model: TExecuteOperationsModel;
+  model: TWIZOperationsModel;
   AccountNumbersWithoutChecksum: TArray<cardinal>;
 
    function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
@@ -663,7 +672,7 @@ var
 
 begin
   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);
   model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
   wiz.Start(model);

+ 1 - 1
src/gui/UCellRenderers.pas

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

+ 17 - 13
src/gui/UFRMExecuteOperations.lfm

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

+ 54 - 7
src/gui/UFRMExecuteOperations.pas

@@ -2,32 +2,79 @@ unit UFRMExecuteOperations;
 
 {$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, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
-  StdCtrls;
+  StdCtrls, UCommon, UCommon.Data, UCommon.Collections, UCommon.UI, UVisualGrid, UCoreObjects, UCoreUtils;
 
 type
 
   { TExecuteOperations }
 
-  TExecuteOperations = class(TForm)
+  TExecuteOperations = class(TApplicationFormEx)
     btnClose: TButton;
     GroupBox1: TGroupBox;
-    Panel1: TPanel;
+    paGrid: TPanel;
+    procedure btnCloseClick(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
   private
-
+    FOperations : TWIZOperationsModel;
+  protected
+    procedure ActivateFirstTime; override;
+    procedure Execute;
+  private
+      FGrid : TVisualGrid;
   public
 
   end;
 
-var
-  ExecuteOperations: TExecuteOperations;
-
 implementation
 
+
+type
+
+
+  TExecuteOperationResultDataSource : class(TDataSource<
+
 {$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.
 

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

@@ -15,13 +15,13 @@ unit UWIZChangeKey;
 interface
 
 uses
-  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon, UWizard, UAccounts, UCoreObjects, LCLType;
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon, UWizard, UAccounts, UCoreObjects, UWIZOperation, LCLType;
 
 type
 
   { TWIZChangeKeyWizard }
 
-  TWIZChangeKeyWizard = class(TWizard<TExecuteOperationsModel>)
+  TWIZChangeKeyWizard = class(TWizard<TWIZOperationsModel>)
   public
     constructor Create(AOwner: TComponent); override;
     function DetermineHasNext: boolean; override;
@@ -77,7 +77,7 @@ begin
 
   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;
 
 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,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   UFRMAccountSelect, UNode, UCoreObjects, UWizard,
-  UWIZOperationFee_Custom, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
+  UWIZOperation, UWIZOperationFee_Custom, UWIZOperationPayload_Encryption, UWIZOperationSigner_Select;
 
 type
 
   { TWIZChangeKey_EnterKey }
 
-  TWIZChangeKey_EnterKey = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZChangeKey_EnterKey = class(TWizardForm<TWIZOperationsModel>)
     chkChooseFee: TCheckBox;
     chkAttachPayload: TCheckBox;
     gbNewPublicKey: TGroupBox;

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

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

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

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

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

@@ -15,13 +15,14 @@ unit UWIZEnlistAccountForSale;
 interface
 
 uses
-  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon, UWizard, UAccounts, UCoreObjects, LCLType;
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon,
+  UWizard, UWIZOperation, UAccounts, UCoreObjects, LCLType;
 
 type
 
   { TWIZEnlistAccountForSaleWizard }
 
-  TWIZEnlistAccountForSaleWizard = class(TWizard<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSaleWizard = class(TWizard<TWIZOperationsModel>)
   public
     constructor Create(AOwner: TComponent); override;
     function DetermineHasNext: boolean; override;
@@ -81,7 +82,7 @@ begin
 
   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;
 
 function TWIZEnlistAccountForSaleWizard.CancelRequested(out message: ansistring): boolean;

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

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

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

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

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

@@ -18,13 +18,14 @@ interface
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   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
 
   { TWIZEnlistAccountForSale_EnterSaleAmount }
 
-  TWIZEnlistAccountForSale_EnterSaleAmount = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSale_EnterSaleAmount = class(TWizardForm<TWIZOperationsModel>)
     chkChooseFee: TCheckBox;
     chkAttachPayload: TCheckBox;
     edtAmt: TEdit;

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

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

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

@@ -13,13 +13,13 @@ interface
 
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
-  ExtCtrls, UWizard, UCoreObjects, UWIZEnlistAccountForSale_EnterPublicKey;
+  ExtCtrls, UWizard, UCoreObjects, UWIZOperation, UWIZEnlistAccountForSale_EnterPublicKey;
 
 type
 
   { TWIZEnlistAccountForSale_SelectOption }
 
-  TWIZEnlistAccountForSale_SelectOption = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZEnlistAccountForSale_SelectOption = class(TWizardForm<TWIZOperationsModel>)
     grpEnlistAccountForSale: TGroupBox;
     Label1: 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
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
-  ExtCtrls, UVisualGrid, UCellRenderers, UCommon.Data, UWizard, UCoreObjects;
+  ExtCtrls, UVisualGrid, UCellRenderers, UCommon.Data, UWizard, UWIZOperation, UCoreObjects;
 
 type
 
   { TWIZOperationConfirmation }
 
-  TWIZOperationConfirmation = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZOperationConfirmation = class(TWizardForm<TWIZOperationsModel>)
     GroupBox1: TGroupBox;
     lblSignerAccount: TLabel;
     lblBeneficiaryAccount: TLabel;
@@ -52,12 +52,12 @@ type
 
   TOperationConfirmationDataSource = class(TAccountsDataSourceBase)
   private
-    FModel: TExecuteOperationsModel;
+    FModel: TWIZOperationsModel;
 
   protected
     function GetColumns: TDataColumns; override;
   public
-    property Model: TExecuteOperationsModel read FModel write FModel;
+    property Model: TWIZOperationsModel read FModel write FModel;
     procedure FetchAll(const AContainer: TList<TAccount>); override;
     function GetItemField(constref AItem: TAccount; const ABindingName: ansistring): variant; override;
   end;
@@ -190,12 +190,12 @@ begin
       omtSendPasc:
       begin
         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;
       omtChangeKey:
-        Result := Format('%s', [TOperationsManager.GetOperationShortText(CT_Op_ChangeKeySigned, CT_OpSubtype_ChangeKey)]);
+        Result := Format('%s', [TCoreTool.GetOperationShortText(CT_Op_ChangeKeySigned, CT_OpSubtype_ChangeKey)]);
       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
   else if ABindingName = 'Recipient' then

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -15,13 +15,13 @@ unit UWIZSendPASC;
 interface
 
 uses
-  Classes, SysUtils, Forms, Dialogs, UWizard, UCommon, UCoreObjects;
+  Classes, SysUtils, Forms, Dialogs, UWizard, UCommon, UCoreObjects, UWIZOperation;
 
 type
 
   { TWIZSendPASCWizard }
 
-  TWIZSendPASCWizard = class(TWizard<TExecuteOperationsModel>)
+  TWIZSendPASCWizard = class(TWizard<TWIZOperationsModel>)
   public
     constructor Create(AOwner: TComponent); override;
     function DetermineHasNext: boolean; override;
@@ -68,7 +68,7 @@ end;
 function TWIZSendPASCWizard.FinishRequested(out message: ansistring): boolean;
 begin
   // 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;
 
 function TWIZSendPASCWizard.CancelRequested(out message: ansistring): boolean;

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

@@ -18,14 +18,15 @@ interface
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   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;
 
 type
 
   { TWIZSendPASC_EnterQuantity }
 
-  TWIZSendPASC_EnterQuantity = class(TWizardForm<TExecuteOperationsModel>)
+  TWIZSendPASC_EnterQuantity = class(TWizardForm<TWIZOperationsModel>)
     chkChooseFee: TCheckBox;
     chkAttachPayload: TCheckBox;
     chkallfunds: TCheckBox;

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

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

+ 1 - 1
src/pascalcoin_wallet.lpi

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