Browse Source

Add: refactoring of enlist accounts for sale wizard.

Ugochukwu Mmaduekwe 7 years ago
parent
commit
28a8ac460d
2 changed files with 195 additions and 364 deletions
  1. 183 30
      src/core.utils/UCoreUtils.pas
  2. 12 334
      src/gui/wizards/operations/UWIZEnlistAccountForSale.pas

+ 183 - 30
src/core.utils/UCoreUtils.pas

@@ -70,13 +70,13 @@ type
     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 ChangeKeyFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; APublicKey: TAccountKey; 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: TExecuteOperationsModel; AHandler: TExecuteOperationsModel.TOperationExecuteResultHandler; var errors: ansistring): boolean; static;
     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 procedure ExecuteEnlistAccountForSale(); 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 }
@@ -255,7 +255,7 @@ begin
   end;
 end;
 
-class function TOperationsManager.ChangeKeyFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; APublicKey: TAccountKey; ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean;
+class function TOperationsManager.OthersFinalizeAndDisplayMessage(const AOperationsTxt, AOperationToString: string; ANoOfOperations: integer; ATotalFee: int64; AOperationsHashTree: TOperationsHashTree; var AErrorMessage: string): boolean;
 var
   LAuxs, LOperationsTxt: string;
   i: integer;
@@ -324,7 +324,7 @@ var
   LNode: TNode;
   LPCOperation: TPCOperation;
   LOperationsHashTree: TOperationsHashTree;
-  LTotalAmount, LTotalFee, LAmount, LFee: int64;
+  LTotalAmount, LTotalSignerFee, LAmount, LFee: int64;
   LDoOperation: boolean;
   LOperationsTxt, LOperationToString: string;
   LIdx, LAccountIdx, LNoOfOperations: integer;
@@ -333,7 +333,7 @@ var
 begin
   if Length(ASelectedAccounts) = 0 then
   begin
-    AErrorMessage := 'No Sender Account Found';
+    AErrorMessage := 'No Selected Account Found';
     Exit(False);
   end;
 
@@ -355,7 +355,7 @@ begin
   LOperationsHashTree := TOperationsHashTree.Create;
   try
     LTotalAmount := 0;
-    LTotalFee := 0;
+    LTotalSignerFee := 0;
     LNoOfOperations := 0;
     LOperationsTxt := '';
     LOperationToString := '';
@@ -372,14 +372,14 @@ begin
 
       if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, ADestinationAccount.accountInfo.accountKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
       begin
-        AErrorMessage := Format('Error Encoding Payload Of Sender Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
+        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('Sender Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
+        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
         Exit(False);
       end;
       LWalletKey := LWalletKeys.Key[LIdx];
@@ -423,14 +423,14 @@ begin
         LPCOperation := TOpTransaction.CreateTransaction(
           LCurrentAccount.account, LCurrentAccount.n_operation + 1, ADestinationAccount.account, LWalletKey.PrivateKey, LAmount, LFee, LPayloadEncodedBytes);
         try
-          Inc(LTotalAmount, LAmount);
-          Inc(LTotalFee, LFee);
-          Inc(LNoOfOperations);
           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;
@@ -447,7 +447,7 @@ begin
       Exit(False);
     end;
 
-    Exit(TOperationsManager.SendPASCFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalAmount, LTotalFee, LOperationsHashTree, AErrorMessage));
+    Exit(TOperationsManager.SendPASCFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalAmount, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
   finally
     LOperationsHashTree.Free;
   end;
@@ -464,7 +464,7 @@ var
   LTotalSignerFee, LFee: int64;
   LIsV2: boolean;
   LOperationsTxt, LOperationToString: string;
-  LIdx, LAccountIdx, LSignerNoOfOperations: integer;
+  LIdx, LAccountIdx, LNoOfOperations: integer;
   LCurrentAccount, LSignerAccount: TAccount;
   LPayloadEncodedBytes: TRawBytes;
 label
@@ -472,7 +472,7 @@ label
 begin
   if Length(ASelectedAccounts) = 0 then
   begin
-    AErrorMessage := 'No Sender Account Found';
+    AErrorMessage := 'No Selected Account Found';
     Exit(False);
   end;
 
@@ -495,7 +495,7 @@ begin
   try
     LIsV2 := LNode.Bank.SafeBox.CurrentProtocol >= CT_PROTOCOL_2;
     LTotalSignerFee := 0;
-    LSignerNoOfOperations := 0;
+    LNoOfOperations := 0;
     LOperationsTxt := '';
     LOperationToString := '';
     for LAccountIdx := Low(ASelectedAccounts) to High(ASelectedAccounts) do
@@ -504,6 +504,13 @@ begin
         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:
@@ -524,23 +531,16 @@ begin
       else
         LSignerAccount := LCurrentAccount;
 
-      if (TAccountComp.EqualAccountKeys(LCurrentAccount.accountInfo.accountKey,
-        APublicKey)) then
-      begin
-        AErrorMessage := 'New Key is Same as Current Key';
-        Exit(False);
-      end;
-
       if not UpdatePayload(LCurrentAccount.accountInfo.accountKey, APublicKey, APayloadEncryptionMode, APayloadContent, LPayloadEncodedBytes, APayloadEncryptionPassword, AErrorMessage) then
       begin
-        AErrorMessage := Format('Error Encoding Payload Of Sender Account "%s. ", Specific Error Is "%s"', [LCurrentAccount.AccountString, AErrorMessage]);
+        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('Sender Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
+        AErrorMessage := Format('Selected Account "%s" Private Key Not Found In Wallet', [LCurrentAccount.AccountString]);
         Exit(False);
       end;
       LWalletKey := LWalletKeys.Key[LIdx];
@@ -574,7 +574,7 @@ begin
         else
           LFee := LSignerAccount.balance - UInt64(LTotalSignerFee);
         LPCOperation := TOpChangeKeySigned.Create(LSignerAccount.account,
-          LsignerAccount.n_operation + LSignerNoOfOperations + 1, LCurrentAccount.account,
+          LSignerAccount.n_operation + LNoOfOperations + 1, LCurrentAccount.account,
           LWalletKey.PrivateKey, APublicKey, LFee, LPayloadEncodedBytes);
       end
       else
@@ -582,12 +582,12 @@ begin
           1, LCurrentAccount.account, LWalletKey.PrivateKey, APublicKey, LFee, LPayloadEncodedBytes);
 
       try
-        Inc(LSignerNoOfOperations);
-        Inc(LTotalSignerFee, LFee);
         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;
@@ -604,16 +604,169 @@ begin
       Exit(False);
     end;
 
-    Exit(TOperationsManager.ChangeKeyFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LSignerNoOfOperations, APublicKey, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
+    Exit(TOperationsManager.OthersFinalizeAndDisplayMessage(LOperationsTxt, LOperationToString, LNoOfOperations, LTotalSignerFee, LOperationsHashTree, AErrorMessage));
   finally
     LOperationsHashTree.Free;
   end;
 
 end;
 
-class procedure TOperationsManager.ExecuteEnlistAccountForSale();
+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 }

+ 12 - 334
src/gui/wizards/operations/UWIZEnlistAccountForSale.pas

@@ -22,11 +22,6 @@ type
   { TWIZEnlistAccountForSaleWizard }
 
   TWIZEnlistAccountForSaleWizard = class(TWizard<TExecuteOperationsModel>)
-  private
-    function UpdatePayload(const SenderAccount: TAccount; var errors: string): boolean;
-    function UpdateOperationOptions(var errors: string): boolean;
-    function UpdateOpListForSale(const TargetAccount: TAccount; var SalePrice: int64; var SellerAccount, SignerAccount: TAccount; var NewOwnerPublicKey: TAccountKey; var LockedUntilBlock: cardinal; var errors: ansistring): boolean;
-    procedure EnlistAccountForSale();
   public
     constructor Create(AOwner: TComponent); override;
     function DetermineHasNext: boolean; override;
@@ -38,13 +33,7 @@ type
 implementation
 
 uses
-  UBlockChain,
-  UOpTransaction,
-  UNode,
-  UConst,
-  UWallet,
-  UECIES,
-  UAES,
+  UCoreUtils,
   UWIZOperationSelected,
   UWIZEnlistAccountForSale_SelectOption,
   UWIZEnlistAccountForSale_EnterSeller,
@@ -53,319 +42,6 @@ uses
 
 { TWIZEnlistAccountForSaleWizard }
 
-function TWIZEnlistAccountForSaleWizard.UpdatePayload(const SenderAccount: TAccount; var errors: string): boolean;
-var
-  valid: boolean;
-  payload_encrypted, payload_u: string;
-  account: TAccount;
-begin
-  valid := False;
-  payload_encrypted := '';
-  Model.Payload.EncodedBytes := '';
-  errors := 'Unknown error';
-  payload_u := Model.Payload.Content;
-
-  try
-    if (payload_u = '') then
-    begin
-      valid := True;
-      Exit;
-    end;
-    case Model.Payload.PayloadEncryptionMode of
-
-      akaEncryptWithSender:
-      begin
-        // Use sender
-        errors := 'Error encrypting';
-        account := SenderAccount;
-        payload_encrypted := ECIESEncrypt(account.accountInfo.accountKey, payload_u);
-        valid := payload_encrypted <> '';
-      end;
-
-      akaEncryptWithReceiver:
-      begin
-        errors := 'Public key: ' + 'Error encrypting';
-
-        account := Model.Signer.SignerAccount;
-        payload_encrypted := ECIESEncrypt(account.accountInfo.accountKey, payload_u);
-        valid := payload_encrypted <> '';
-      end;
-
-      akaEncryptWithPassword:
-      begin
-        payload_encrypted := TAESComp.EVP_Encrypt_AES256(
-          payload_u, Model.Payload.Password);
-        valid := payload_encrypted <> '';
-      end;
-
-      akaNotEncrypt:
-      begin
-        payload_encrypted := payload_u;
-        valid := True;
-      end
-
-      else
-        raise Exception.Create('Invalid Encryption Selection');
-    end;
-
-  finally
-    if valid then
-      if length(payload_encrypted) > CT_MaxPayloadSize then
-      begin
-        valid := False;
-        errors := 'Payload size is bigger than ' + IntToStr(CT_MaxPayloadSize) +
-          ' (' + IntToStr(length(payload_encrypted)) + ')';
-      end;
-    Model.Payload.EncodedBytes := payload_encrypted;
-    Result := valid;
-  end;
-
-end;
-
-function TWIZEnlistAccountForSaleWizard.UpdateOperationOptions(var errors: string): boolean;
-var
-  iAcc, iWallet: integer;
-  sender_account, signer_account, seller_account: TAccount;
-  publicKey: TAccountKey;
-  wk: TWalletKey;
-  e: string;
-  salePrice: int64;
-  auxC: cardinal;
-begin
-  Result := False;
-  errors := '';
-  if not Assigned(TWallet.Keys) then
-  begin
-    errors := 'No wallet keys';
-    Exit;
-  end;
-
-  if Length(Model.Account.SelectedAccounts) = 0 then
-  begin
-    errors := 'No sender account';
-    Exit;
-  end
-  else
-    for iAcc := Low(Model.Account.SelectedAccounts) to High(Model.Account.SelectedAccounts) do
-    begin
-      sender_account := Model.Account.SelectedAccounts[iAcc];
-      iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
-      if (iWallet < 0) then
-      begin
-        errors := 'Private key of account ' +
-          TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
-          ' not found in wallet';
-        Exit;
-      end;
-      wk := TWallet.Keys.Key[iWallet];
-      if not assigned(wk.PrivateKey) then
-      begin
-        if wk.CryptedKey <> '' then
-          errors := 'Wallet is password protected. Need password'// TODO: handle unlocking of encrypted wallet here
-
-        else
-          errors := 'Only public key of account ' +
-            TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
-            ' found in wallet. You cannot operate with this account';
-        Exit;
-      end;
-    end;
-
-  Result := UpdateOpListForSale(Model.Account.SelectedAccounts[0], salePrice,
-    seller_account, signer_account, publicKey, auxC, errors);
-  UpdatePayload(sender_account, e);
-end;
-
-function TWIZEnlistAccountForSaleWizard.UpdateOpListForSale(const TargetAccount: TAccount; var SalePrice: int64; var SellerAccount, SignerAccount: TAccount; var NewOwnerPublicKey: TAccountKey; var LockedUntilBlock: cardinal; var errors: ansistring): boolean;
-begin
-  Result := False;
-  SalePrice := 0;
-  SellerAccount := CT_Account_NUL;
-  NewOwnerPublicKey := CT_TECDSA_Public_Nul;
-  LockedUntilBlock := 0;
-  errors := '';
-  try
-    if TAccountComp.IsAccountForSale(TargetAccount.accountInfo) then
-    begin
-      errors := 'Account ' + TAccountComp.AccountNumberToAccountTxtNumber(
-        TargetAccount.account) + ' is already enlisted for sale';
-      Exit;
-    end;
-    salePrice := Model.EnlistAccountForSale.SalePrice;
-
-    SignerAccount := Model.Signer.SignerAccount;
-
-    if (Model.EnlistAccountForSale.SellerAccount.account = TargetAccount.account) then
-    begin
-      errors := 'Seller account cannot be same account';
-      exit;
-    end;
-
-    SellerAccount := Model.EnlistAccountForSale.SellerAccount;
-    if Model.EnlistAccountForSale.AccountSaleMode = akaPrivateSale then
-    begin
-
-      NewOwnerPublicKey := Model.EnlistAccountForSale.NewOwnerPublicKey;
-
-      if TAccountComp.EqualAccountKeys(NewOwnerPublicKey,
-        TargetAccount.accountInfo.accountKey) then
-      begin
-        errors := 'New public key for private sale is the same public key';
-        Exit;
-      end;
-      LockedUntilBlock := Model.EnlistAccountForSale.LockedUntilBlock;
-      if LockedUntilBlock = 0 then
-      begin
-        errors := 'Insert locking block';
-        exit;
-      end;
-    end;
-    if (TNode.Node.Bank.SafeBox.CurrentProtocol = CT_PROTOCOL_1) then
-    begin
-      errors := 'This operation needs PROTOCOL 2 active';
-      exit;
-    end;
-  finally
-    Result := errors = '';
-  end;
-end;
-
-procedure TWIZEnlistAccountForSaleWizard.EnlistAccountForSale();
-var
-  _V2, dooperation: boolean;
-  iAcc, i: integer;
-  _totalamount, _totalfee, _totalSignerFee, _amount, _fee, _salePrice: int64;
-  _signer_n_ops, _lockedUntil: cardinal;
-  operationstxt, operation_to_string, errors, auxs: string;
-  wk: TWalletKey;
-  ops: TOperationsHashTree;
-  op: TPCOperation;
-  account, signerAccount, destAccount: TAccount;
-  _newOwnerPublicKey: TECDSA_Public;
-label
-  loop_start;
-begin
-  if not Assigned(TWallet.Keys) then
-    raise Exception.Create('No wallet keys');
-  if not UpdateOperationOptions(errors) then
-    raise Exception.Create(errors);
-  ops := TOperationsHashTree.Create;
-
-  try
-    _V2 := TNode.Node.Bank.SafeBox.CurrentProtocol >= CT_PROTOCOL_2;
-    _totalamount := 0;
-    _totalfee := 0;
-    _totalSignerFee := 0;
-    _signer_n_ops := 0;
-    operationstxt := '';
-    operation_to_string := '';
-    for iAcc := Low(Model.Account.SelectedAccounts) to High(Model.Account.SelectedAccounts) do
-    begin
-      loop_start:
-        op := nil;
-      account := Model.Account.SelectedAccounts[iAcc];
-      if not UpdatePayload(account, errors) then
-        raise Exception.Create('Error encoding payload of sender account ' +
-          TAccountComp.AccountNumberToAccountTxtNumber(account.account) + ': ' + errors);
-      i := TWallet.Keys.IndexOfAccountKey(account.accountInfo.accountKey);
-      if i < 0 then
-        raise Exception.Create('Sender account private key not found in Wallet');
-
-      wk := TWallet.Keys.Key[i];
-      dooperation := True;
-      // Default fee
-      if account.balance > uint64(Model.Fee.DefaultFee) then
-        _fee := Model.Fee.DefaultFee
-      else
-        _fee := account.balance;
-
-      if not UpdateOpListForSale(account, _salePrice, destAccount,
-        signerAccount, _newOwnerPublicKey, _lockedUntil, errors) then
-        raise Exception.Create(errors);
-      // Special fee account:
-      if signerAccount.balance > Model.Fee.DefaultFee then
-        _fee := Model.Fee.DefaultFee
-      else
-        _fee := signerAccount.balance;
-      if Model.EnlistAccountForSale.AccountSaleMode = akaPublicSale then
-        op := TOpListAccountForSale.CreateListAccountForSale(
-          signerAccount.account, signerAccount.n_operation + 1 + iAcc,
-          account.account, _salePrice, _fee, destAccount.account,
-          CT_TECDSA_Public_Nul, 0, wk.PrivateKey, Model.Payload.EncodedBytes)
-      else if Model.EnlistAccountForSale.AccountSaleMode = akaPrivateSale then
-        op := TOpListAccountForSale.CreateListAccountForSale(
-          signerAccount.account, signerAccount.n_operation + 1 + iAcc,
-          account.account, _salePrice, _fee, destAccount.account,
-          _newOwnerPublicKey, _lockedUntil, wk.PrivateKey, Model.Payload.EncodedBytes)
-      else
-        raise Exception.Create('Invalid Sale type');
-
-      if Assigned(op) and (dooperation) then
-      begin
-        ops.AddOperationToHashTree(op);
-        if operation_to_string <> '' then
-          operation_to_string := operation_to_string + #10;
-        operation_to_string := operation_to_string + op.ToString;
-      end;
-      FreeAndNil(op);
-    end;
-
-    if (ops.OperationsCount = 0) then
-      raise Exception.Create('No valid operation to execute');
-
-    if (Length(Model.Account.SelectedAccounts) > 1) then
-    begin
-      auxs := '';
-      if Application.MessageBox(
-        PChar('Execute ' + IntToStr(Length(Model.Account.SelectedAccounts)) +
-        ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
-        auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
-        #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 + operation_to_string + #10 + #10 +
-      'Note: This operation will be transmitted to the network!'),
-      PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
-      idYes then
-      Exit;
-    i := TNode.Node.AddOperations(nil, ops, nil, errors);
-    if (i = ops.OperationsCount) then
-    begin
-      operationstxt := 'Successfully executed ' + IntToStr(i) +
-        ' operations!' + #10 + #10 + operation_to_string;
-      if i > 1 then
-        ShowMessage(operationstxt)
-      else
-      begin
-        Application.MessageBox(
-          PChar('Successfully executed ' + IntToStr(i) + ' operations!' +
-          #10 + #10 + operation_to_string),
-          PChar(Application.Title), MB_OK + MB_ICONINFORMATION);
-      end;
-
-    end
-    else if (i > 0) then
-    begin
-      operationstxt := 'One or more of your operations has not been executed:' +
-        #10 + 'Errors:' + #10 + errors + #10 + #10 +
-        'Total successfully executed operations: ' + IntToStr(i);
-
-      ShowMessage(operationstxt);
-    end
-    else
-      raise Exception.Create(errors);
-
-
-  finally
-    ops.Free;
-  end;
-
-end;
-
 constructor TWIZEnlistAccountForSaleWizard.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner,
@@ -392,18 +68,20 @@ begin
 end;
 
 function TWIZEnlistAccountForSaleWizard.FinishRequested(out message: ansistring): boolean;
+var
+  LPublicKey: TAccountKey;
 begin
   // Execute the Enlist Account For Sale Action here
-  try
-    Result := True;
-    EnlistAccountForSale();
-  except
-    On E: Exception do
-    begin
-      Result := False;
-      message := E.ToString;
-    end;
+   case Model.EnlistAccountForSale.AccountSaleMode of
+    akaPublicSale:
+      LPublicKey := CT_TECDSA_Public_Nul;
+
+    akaPrivateSale:
+      LPublicKey := Model.EnlistAccountForSale.NewOwnerPublicKey;
+
   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);
 end;
 
 function TWIZEnlistAccountForSaleWizard.CancelRequested(out message: ansistring): boolean;