浏览代码

GUI: Wizard refactoring
- new workflow (Ugo's changes)
- model encapsulation (fee, signer, payload)
- other minor edits

Herman Schoenfeld 7 年之前
父节点
当前提交
3299d21df0
共有 83 个文件被更改,包括 3741 次插入399 次删除
  1. 27 11
      src/gui/UCTRLWallet.pas
  2. 29 28
      src/gui/wizards/UWIZChangeAccountPrivateKey.pas
  3. 10 8
      src/gui/wizards/UWIZChangeAccountPrivateKey_Confirmation.pas
  4. 10 10
      src/gui/wizards/UWIZChangeAccountPrivateKey_Transaction.pas
  5. 5 5
      src/gui/wizards/UWIZChangeAccountPrivateKey_TransactionPayload.pas
  6. 86 77
      src/gui/wizards/UWIZModels.pas
  7. 48 42
      src/gui/wizards/UWIZSendPASC.pas
  8. 1 1
      src/gui/wizards/UWIZSendPASC_ConfirmSender.lfm
  9. 1 1
      src/gui/wizards/UWIZSendPASC_ConfirmSender.pas
  10. 11 7
      src/gui/wizards/UWIZSendPASC_Confirmation.pas
  11. 1 0
      src/gui/wizards/UWIZSendPASC_EnterQuantity.lfm
  12. 6 6
      src/gui/wizards/UWIZSendPASC_EnterQuantity.pas
  13. 10 10
      src/gui/wizards/UWIZSendPASC_Transaction.pas
  14. 5 5
      src/gui/wizards/UWIZSendPASC_TransactionPayload.pas
  15. 28 28
      src/gui/wizards/UWIZTransferAccount.pas
  16. 5 5
      src/gui/wizards/UWIZTransferAccount_Confirmation.pas
  17. 12 12
      src/gui/wizards/UWIZTransferAccount_Transaction.pas
  18. 5 5
      src/gui/wizards/UWIZTransferAccount_TransactionPayload.pas
  19. 455 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey.pas
  20. 48 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Confirmation.lfm
  21. 144 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Confirmation.pas
  22. 0 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Start.lfm
  23. 1 1
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Start.pas
  24. 106 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Transaction.lfm
  25. 210 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Transaction.pas
  26. 97 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_TransactionPayload.lfm
  27. 84 0
      src/gui/wizards/operations/UWIZChangeAccountPrivateKey_TransactionPayload.pas
  28. 4 4
      src/gui/wizards/operations/UWIZEnlistAccountForSale.pas
  29. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_Confirmation.lfm
  30. 1 1
      src/gui/wizards/operations/UWIZEnlistAccountForSale_Confirmation.pas
  31. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_List.lfm
  32. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_List.pas
  33. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_PrivateSaleConfig.lfm
  34. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_PrivateSaleConfig.pas
  35. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_Start.lfm
  36. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_Start.pas
  37. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_Transaction.lfm
  38. 2 2
      src/gui/wizards/operations/UWIZEnlistAccountForSale_Transaction.pas
  39. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_TransactionPayload.lfm
  40. 0 0
      src/gui/wizards/operations/UWIZEnlistAccountForSale_TransactionPayload.pas
  41. 0 0
      src/gui/wizards/operations/UWIZFeeOverride.lfm
  42. 3 3
      src/gui/wizards/operations/UWIZFeeOverride.pas
  43. 1 0
      src/gui/wizards/operations/UWIZPayloadContentOverride.lfm
  44. 1 1
      src/gui/wizards/operations/UWIZPayloadContentOverride.pas
  45. 0 0
      src/gui/wizards/operations/UWIZPayloadOverride.lfm
  46. 5 5
      src/gui/wizards/operations/UWIZPayloadOverride.pas
  47. 0 0
      src/gui/wizards/operations/UWIZPayloadPasswordOverride.lfm
  48. 1 1
      src/gui/wizards/operations/UWIZPayloadPasswordOverride.pas
  49. 1 1
      src/gui/wizards/operations/UWIZSelectSignerOverride.lfm
  50. 8 8
      src/gui/wizards/operations/UWIZSelectSignerOverride.pas
  51. 431 0
      src/gui/wizards/operations/UWIZSendPASC.pas
  52. 3 3
      src/gui/wizards/operations/UWIZSendPASC_ConfirmSender.lfm
  53. 12 12
      src/gui/wizards/operations/UWIZSendPASC_ConfirmSender.pas
  54. 63 0
      src/gui/wizards/operations/UWIZSendPASC_Confirmation.lfm
  55. 144 0
      src/gui/wizards/operations/UWIZSendPASC_Confirmation.pas
  56. 62 0
      src/gui/wizards/operations/UWIZSendPASC_EnterQuantity.lfm
  57. 138 0
      src/gui/wizards/operations/UWIZSendPASC_EnterQuantity.pas
  58. 0 0
      src/gui/wizards/operations/UWIZSendPASC_EnterRecipient.lfm
  59. 2 2
      src/gui/wizards/operations/UWIZSendPASC_EnterRecipient.pas
  60. 0 0
      src/gui/wizards/operations/UWIZSendPASC_FeeOverride.lfm
  61. 451 0
      src/gui/wizards/operations/UWIZTransferAccount.pas
  62. 48 0
      src/gui/wizards/operations/UWIZTransferAccount_Confirmation.lfm
  63. 137 0
      src/gui/wizards/operations/UWIZTransferAccount_Confirmation.pas
  64. 0 0
      src/gui/wizards/operations/UWIZTransferAccount_Start.lfm
  65. 1 1
      src/gui/wizards/operations/UWIZTransferAccount_Start.pas
  66. 93 0
      src/gui/wizards/operations/UWIZTransferAccount_Transaction.lfm
  67. 148 0
      src/gui/wizards/operations/UWIZTransferAccount_Transaction.pas
  68. 98 0
      src/gui/wizards/operations/UWIZTransferAccount_TransactionPayload.lfm
  69. 84 0
      src/gui/wizards/operations/UWIZTransferAccount_TransactionPayload.pas
  70. 0 0
      src/gui/wizards/wallet/UWIZAddKey.pas
  71. 0 0
      src/gui/wizards/wallet/UWIZAddKey_EnterName.lfm
  72. 0 0
      src/gui/wizards/wallet/UWIZAddKey_EnterName.pas
  73. 0 0
      src/gui/wizards/wallet/UWIZAddKey_GenerateOrImport.lfm
  74. 0 0
      src/gui/wizards/wallet/UWIZAddKey_GenerateOrImport.pas
  75. 0 0
      src/gui/wizards/wallet/UWIZAddKey_ImportPrivKey.lfm
  76. 0 0
      src/gui/wizards/wallet/UWIZAddKey_ImportPrivKey.pas
  77. 0 0
      src/gui/wizards/wallet/UWIZAddKey_ImportPubKey.lfm
  78. 0 0
      src/gui/wizards/wallet/UWIZAddKey_ImportPubKey.pas
  79. 34 0
      src/gui/wizards/wallet/UWIZAddKey_SelectEncryption.lfm
  80. 81 0
      src/gui/wizards/wallet/UWIZAddKey_SelectEncryption.pas
  81. 66 0
      src/gui/wizards/wallet/UWIZAddKey_Start.lfm
  82. 55 0
      src/gui/wizards/wallet/UWIZAddKey_Start.pas
  83. 118 93
      src/pascalcoin_wallet.lpi

+ 27 - 11
src/gui/UCTRLWallet.pas

@@ -609,20 +609,36 @@ end;
 
 
 procedure TCTRLWallet.OnPrepareAccountPopupMenu(Sender: TObject;
 procedure TCTRLWallet.OnPrepareAccountPopupMenu(Sender: TObject;
   constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
   constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
+var
+  accNo: cardinal;
+  account: TAccount;
 begin
 begin
   miSep1.Visible := ASelection.RowCount = 1;
   miSep1.Visible := ASelection.RowCount = 1;
   miAccountInfo.Visible := ASelection.RowCount = 1;
   miAccountInfo.Visible := ASelection.RowCount = 1;
+  miSendPASC.Caption :=
+    IIF(ASelection.RowCount = 1, 'Send PASC', 'Send All PASC');
   miTransferAccounts.Caption :=
   miTransferAccounts.Caption :=
-    IIF(ASelection.RowCount = 1, 'Transfer Account', 'Transfer Accounts');
+    IIF(ASelection.RowCount = 1, 'Transfer Account', 'Transfer All Account');
   miChangeAccountsPrivateKey.Caption :=
   miChangeAccountsPrivateKey.Caption :=
-    IIF(ASelection.RowCount = 1, 'Change Account Private Key',
-    'Change Accounts Private Key');
+    IIF(ASelection.RowCount = 1, 'Change Account Private Key', 'Change All Account Private Key');
   miEnlistAccountsForSale.Caption :=
   miEnlistAccountsForSale.Caption :=
     IIF(ASelection.RowCount = 1, 'Enlist Account For Sale',
     IIF(ASelection.RowCount = 1, 'Enlist Account For Sale',
-    'Enlist Accounts For Sale');
+    'Enlist All Account For Sale');
   miDelistAccountsFromSale.Caption :=
   miDelistAccountsFromSale.Caption :=
     IIF(ASelection.RowCount = 1, 'Delist Account From Sale',
     IIF(ASelection.RowCount = 1, 'Delist Account From Sale',
-    'Delist Accounts From Sale');
+    'Delist All Account From Sale');
+  if ASelection.RowCount = 1 then
+  begin
+    if not TAccountComp.AccountTxtNumberToAccountNumber(
+      FAccountsGrid.Rows[ASelection.Row].Account, accNo) then
+    begin
+      raise Exception.Create('Error Parsing Account Number From Grid');
+    end;
+    account := TNode.Node.Operations.SafeBoxTransaction.Account(accNo);
+    miEnlistAccountsForSale.Visible :=
+      IIF(TAccountComp.IsAccountForSale(account.accountInfo), False, True);
+    miDelistAccountsFromSale.Visible := not miEnlistAccountsForSale.Visible;
+  end;
   APopupMenu := mnuAccountsPopup;
   APopupMenu := mnuAccountsPopup;
 end;
 end;
 
 
@@ -647,8 +663,8 @@ begin
     TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,
     TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,
     GetAccNoWithoutChecksum);
     GetAccNoWithoutChecksum);
 
 
-  model.SendPASCModel.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
-  model.SendPASCModel.SelectedIndex := 0;
+  model.SendPASC.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
+  model.SendPASC.SelectedIndex := 0;
   wiz.Start(model);
   wiz.Start(model);
 end;
 end;
 
 
@@ -666,8 +682,8 @@ begin
     TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,
     TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,
     GetAccNoWithoutChecksum);
     GetAccNoWithoutChecksum);
 
 
-  model.TransferAccountModel.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
-  model.TransferAccountModel.SelectedIndex := 0;
+  model.TransferAccount.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
+  model.TransferAccount.SelectedIndex := 0;
   wiz.Start(model);
   wiz.Start(model);
 end;
 end;
 
 
@@ -685,8 +701,8 @@ begin
     TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,
     TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,
     GetAccNoWithoutChecksum);
     GetAccNoWithoutChecksum);
 
 
-  model.ChangeAccountPrivateKeyModel.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
-  model.ChangeAccountPrivateKeyModel.SelectedIndex := 0;
+  model.ChangeAccountPrivateKey.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
+  model.ChangeAccountPrivateKey.SelectedIndex := 0;
   wiz.Start(model);
   wiz.Start(model);
 end;
 end;
 
 

+ 29 - 28
src/gui/wizards/UWIZChangeAccountPrivateKey.pas

@@ -47,7 +47,8 @@ uses
 
 
 { TWIZChangeAccountPrivateKeyWizard }
 { TWIZChangeAccountPrivateKeyWizard }
 
 
-function TWIZChangeAccountPrivateKeyWizard.UpdatePayload(const SenderAccount: TAccount; var errors: string): boolean;
+function TWIZChangeAccountPrivateKeyWizard.UpdatePayload(const SenderAccount: TAccount;
+  var errors: string): boolean;
 var
 var
   valid: boolean;
   valid: boolean;
   payload_encrypted, payload_u: string;
   payload_encrypted, payload_u: string;
@@ -56,9 +57,9 @@ var
 begin
 begin
   valid := False;
   valid := False;
   payload_encrypted := '';
   payload_encrypted := '';
-  Model.PayloadModel.EncodedPayload := '';
+  Model.ChangeAccountPrivateKey.EncodedPayload := '';
   errors := 'Unknown error';
   errors := 'Unknown error';
-  payload_u := Model.PayloadModel.Payload;
+  payload_u := Model.Payload.Content;
 
 
   try
   try
     if (payload_u = '') then
     if (payload_u = '') then
@@ -66,9 +67,9 @@ begin
       valid := True;
       valid := True;
       Exit;
       Exit;
     end;
     end;
-    case Model.PayloadModel.PayloadEncryptionMode of
+    case Model.Payload.Mode of
 
 
-      akaEncryptWithOldEC:
+      akaEncryptWithSender:
       begin
       begin
         // Use sender
         // Use sender
         errors := 'Error encrypting';
         errors := 'Error encrypting';
@@ -77,11 +78,11 @@ begin
         valid := payload_encrypted <> '';
         valid := payload_encrypted <> '';
       end;
       end;
 
 
-      akaEncryptWithEC:
+      akaEncryptWithReceiver:
       begin
       begin
         errors := 'Error encrypting';
         errors := 'Error encrypting';
 
 
-        public_key := Model.ChangeAccountPrivateKeyModel.NewWalletKey.AccountKey;
+        public_key := Model.ChangeAccountPrivateKey.NewWalletKey.AccountKey;
         if public_key.EC_OpenSSL_NID <>
         if public_key.EC_OpenSSL_NID <>
           CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then
           CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then
         begin
         begin
@@ -99,7 +100,7 @@ begin
       akaEncryptWithPassword:
       akaEncryptWithPassword:
       begin
       begin
         payload_encrypted := TAESComp.EVP_Encrypt_AES256(
         payload_encrypted := TAESComp.EVP_Encrypt_AES256(
-          payload_u, Model.PayloadModel.EncryptionPassword);
+          payload_u, Model.Payload.Password);
         valid := payload_encrypted <> '';
         valid := payload_encrypted <> '';
       end;
       end;
 
 
@@ -126,7 +127,7 @@ begin
       end;
       end;
 
 
     end;
     end;
-    Model.PayloadModel.EncodedPayload := payload_encrypted;
+    Model.ChangeAccountPrivateKey.EncodedPayload := payload_encrypted;
     Result := valid;
     Result := valid;
   end;
   end;
 
 
@@ -150,7 +151,7 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  if Length(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) = 0 then
+  if Length(Model.ChangeAccountPrivateKey.SelectedAccounts) = 0 then
   begin
   begin
     errors := 'No sender account';
     errors := 'No sender account';
     Exit;
     Exit;
@@ -158,9 +159,9 @@ begin
   else
   else
   begin
   begin
 
 
-    for iAcc := Low(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) to High(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) do
+    for iAcc := Low(Model.ChangeAccountPrivateKey.SelectedAccounts) to High(Model.ChangeAccountPrivateKey.SelectedAccounts) do
     begin
     begin
-      sender_account := Model.ChangeAccountPrivateKeyModel.SelectedAccounts[iAcc];
+      sender_account := Model.ChangeAccountPrivateKey.SelectedAccounts[iAcc];
       iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
       iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
       if (iWallet < 0) then
       if (iWallet < 0) then
       begin
       begin
@@ -188,7 +189,7 @@ begin
     end;
     end;
   end;
   end;
 
 
-  Result := UpdateOpChangeKey(Model.ChangeAccountPrivateKeyModel.SelectedAccounts[0], signer_account,
+  Result := UpdateOpChangeKey(Model.ChangeAccountPrivateKey.SelectedAccounts[0], signer_account,
     publicKey, errors);
     publicKey, errors);
   UpdatePayload(sender_account, e);
   UpdatePayload(sender_account, e);
 end;
 end;
@@ -200,12 +201,12 @@ begin
   Result := False;
   Result := False;
   errors := '';
   errors := '';
   try
   try
-    NewPublicKey := Model.ChangeAccountPrivateKeyModel.NewWalletKey.AccountKey;
+    NewPublicKey := Model.ChangeAccountPrivateKey.NewWalletKey.AccountKey;
 
 
     if TNode.Node.Bank.SafeBox.CurrentProtocol >= 1 then
     if TNode.Node.Bank.SafeBox.CurrentProtocol >= 1 then
     begin
     begin
       // Signer:
       // Signer:
-      SignerAccount := Model.SignerModel.SignerAccount;
+      SignerAccount := Model.Signer.SignerAccount;
       if (TAccountComp.IsAccountLocked(SignerAccount.accountInfo,
       if (TAccountComp.IsAccountLocked(SignerAccount.accountInfo,
         TNode.Node.Bank.BlocksCount)) then
         TNode.Node.Bank.BlocksCount)) then
       begin
       begin
@@ -269,11 +270,11 @@ begin
     _signer_n_ops := 0;
     _signer_n_ops := 0;
     operationstxt := '';
     operationstxt := '';
     operation_to_string := '';
     operation_to_string := '';
-    for iAcc := Low(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) to High(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) do
+    for iAcc := Low(Model.ChangeAccountPrivateKey.SelectedAccounts) to High(Model.ChangeAccountPrivateKey.SelectedAccounts) do
     begin
     begin
       loop_start:
       loop_start:
         op := nil;
         op := nil;
-      account := Model.ChangeAccountPrivateKeyModel.SelectedAccounts[iAcc];
+      account := Model.ChangeAccountPrivateKey.SelectedAccounts[iAcc];
       if not UpdatePayload(account, errors) then
       if not UpdatePayload(account, errors) then
       begin
       begin
         raise Exception.Create('Error encoding payload of sender account ' +
         raise Exception.Create('Error encoding payload of sender account ' +
@@ -288,8 +289,8 @@ begin
       wk := TWallet.Keys.Key[i];
       wk := TWallet.Keys.Key[i];
       dooperation := True;
       dooperation := True;
       // Default fee
       // Default fee
-      if account.balance > uint64(Model.FeeModel.DefaultFee) then
-        _fee := Model.FeeModel.DefaultFee
+      if account.balance > uint64(Model.Fee.DefaultFee) then
+        _fee := Model.Fee.DefaultFee
       else
       else
         _fee := account.balance;
         _fee := account.balance;
 
 
@@ -300,11 +301,11 @@ begin
       if _V2 then
       if _V2 then
       begin
       begin
         // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
         // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
-        if (iAcc < Length(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) - 1) and
+        if (iAcc < Length(Model.ChangeAccountPrivateKey.SelectedAccounts) - 1) and
           (account.account = signerAccount.account) then
           (account.account = signerAccount.account) then
         begin
         begin
-          TArrayTool<TAccount>.Swap(Model.ChangeAccountPrivateKeyModel.SelectedAccounts, iAcc,
-            Length(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) - 1); // ensure signer account processed last
+          TArrayTool<TAccount>.Swap(Model.ChangeAccountPrivateKey.SelectedAccounts, iAcc,
+            Length(Model.ChangeAccountPrivateKey.SelectedAccounts) - 1); // ensure signer account processed last
           // TArrayTool_internal<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1);
           // TArrayTool_internal<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1);
           goto loop_start; // TODO: remove ugly hack with refactoring!
           goto loop_start; // TODO: remove ugly hack with refactoring!
         end;
         end;
@@ -313,13 +314,13 @@ begin
         if uint64(_totalSignerFee) >= signerAccount.balance then
         if uint64(_totalSignerFee) >= signerAccount.balance then
           _fee := 0
           _fee := 0
         else if signerAccount.balance - uint64(_totalSignerFee) >
         else if signerAccount.balance - uint64(_totalSignerFee) >
-          uint64(Model.FeeModel.DefaultFee) then
-          _fee := Model.FeeModel.DefaultFee
+          uint64(Model.Fee.DefaultFee) then
+          _fee := Model.Fee.DefaultFee
         else
         else
           _fee := signerAccount.balance - uint64(_totalSignerFee);
           _fee := signerAccount.balance - uint64(_totalSignerFee);
         op := TOpChangeKeySigned.Create(signerAccount.account,
         op := TOpChangeKeySigned.Create(signerAccount.account,
           signerAccount.n_operation + _signer_n_ops + 1, account.account,
           signerAccount.n_operation + _signer_n_ops + 1, account.account,
-          wk.PrivateKey, _newOwnerPublicKey, _fee, Model.PayloadModel.EncodedPayload);
+          wk.PrivateKey, _newOwnerPublicKey, _fee, Model.ChangeAccountPrivateKey.EncodedPayload);
         Inc(_signer_n_ops);
         Inc(_signer_n_ops);
         Inc(_totalSignerFee, _fee);
         Inc(_totalSignerFee, _fee);
       end
       end
@@ -327,7 +328,7 @@ begin
       begin
       begin
         op := TOpChangeKey.Create(account.account, account.n_operation +
         op := TOpChangeKey.Create(account.account, account.n_operation +
           1, account.account, wk.PrivateKey, _newOwnerPublicKey, _fee,
           1, account.account, wk.PrivateKey, _newOwnerPublicKey, _fee,
-          Model.PayloadModel.EncodedPayload);
+          Model.ChangeAccountPrivateKey.EncodedPayload);
       end;
       end;
       Inc(_totalfee, _fee);
       Inc(_totalfee, _fee);
       operationstxt :=
       operationstxt :=
@@ -347,11 +348,11 @@ begin
     if (ops.OperationsCount = 0) then
     if (ops.OperationsCount = 0) then
       raise Exception.Create('No valid operation to execute');
       raise Exception.Create('No valid operation to execute');
 
 
-    if (Length(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) > 1) then
+    if (Length(Model.ChangeAccountPrivateKey.SelectedAccounts) > 1) then
     begin
     begin
       auxs := '';
       auxs := '';
       if Application.MessageBox(
       if Application.MessageBox(
-        PChar('Execute ' + IntToStr(Length(Model.ChangeAccountPrivateKeyModel.SelectedAccounts)) +
+        PChar('Execute ' + IntToStr(Length(Model.ChangeAccountPrivateKey.SelectedAccounts)) +
         ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
         ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
         auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
         auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
         #10 + #10 + 'Note: This operation will be transmitted to the network!'),
         #10 + #10 + 'Note: This operation will be transmitted to the network!'),

+ 10 - 8
src/gui/wizards/UWIZChangeAccountPrivateKey_Confirmation.pas

@@ -92,7 +92,7 @@ begin
   Data.Model := Model;
   Data.Model := Model;
   FSendersGrid.DataSource := Data;
   FSendersGrid.DataSource := Data;
   paGrid.AddControlDockCenter(FSendersGrid);
   paGrid.AddControlDockCenter(FSendersGrid);
-  lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.SignerModel.SignerAccount.account);
+  lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.Signer.SignerAccount.account);
 end;
 end;
 
 
 { TAccountSenderDataSource }
 { TAccountSenderDataSource }
@@ -106,7 +106,8 @@ begin
     );
     );
 end;
 end;
 
 
-function TAccountSenderDataSource.GetItemField(constref AItem: TAccount; const ABindingName: ansistring): variant;
+function TAccountSenderDataSource.GetItemField(constref AItem: TAccount;
+  const ABindingName: ansistring): variant;
 var
 var
   index: integer;
   index: integer;
 begin
 begin
@@ -114,15 +115,16 @@ begin
     Result := TAccountComp.AccountNumberToAccountTxtNumber(AItem.account)
     Result := TAccountComp.AccountNumberToAccountTxtNumber(AItem.account)
   else if ABindingName = 'NewPrivateKey' then
   else if ABindingName = 'NewPrivateKey' then
   begin
   begin
-    Result := IIF(Model.ChangeAccountPrivateKeyModel.NewWalletKey.Name = '',
-      TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(Model.ChangeAccountPrivateKeyModel.NewWalletKey.AccountKey)), Model.ChangeAccountPrivateKeyModel.NewWalletKey.Name);
-    if not Assigned(Model.ChangeAccountPrivateKeyModel.NewWalletKey.PrivateKey) then
+    Result := IIF(Model.ChangeAccountPrivateKey.NewWalletKey.Name = '',
+      TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(
+      Model.ChangeAccountPrivateKey.NewWalletKey.AccountKey)), Model.ChangeAccountPrivateKey.NewWalletKey.Name);
+    if not Assigned(Model.ChangeAccountPrivateKey.NewWalletKey.PrivateKey) then
     begin
     begin
       Result := Result + '(*)';
       Result := Result + '(*)';
     end;
     end;
   end
   end
   else if ABindingName = 'Fee' then
   else if ABindingName = 'Fee' then
-    Result := TAccountComp.FormatMoney(Model.FeeModel.DefaultFee)
+    Result := TAccountComp.FormatMoney(Model.Fee.DefaultFee)
   else
   else
     raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
     raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
 end;
 end;
@@ -132,9 +134,9 @@ procedure TAccountSenderDataSource.FetchAll(const AContainer: TList<TAccount>);
 var
 var
   i: integer;
   i: integer;
 begin
 begin
-  for i := Low(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) to High(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) do
+  for i := Low(Model.ChangeAccountPrivateKey.SelectedAccounts) to High(Model.ChangeAccountPrivateKey.SelectedAccounts) do
   begin
   begin
-    AContainer.Add(Model.ChangeAccountPrivateKeyModel.SelectedAccounts[i]);
+    AContainer.Add(Model.ChangeAccountPrivateKey.SelectedAccounts[i]);
   end;
   end;
 end;
 end;
 
 

+ 10 - 10
src/gui/wizards/UWIZChangeAccountPrivateKey_Transaction.pas

@@ -64,7 +64,7 @@ begin
   begin
   begin
     lblBalance.Font.Color := clGreen;
     lblBalance.Font.Color := clGreen;
     lblBalance.Caption := Format('%s PASC',
     lblBalance.Caption := Format('%s PASC',
-      [TAccountComp.FormatMoney(Model.ChangeAccountPrivateKeyModel.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
+      [TAccountComp.FormatMoney(Model.ChangeAccountPrivateKey.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
   end;
   end;
 end;
 end;
 
 
@@ -138,9 +138,9 @@ begin
   try
   try
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Add('Select Signer Account');
     cbSignerAccount.Items.Add('Select Signer Account');
-    for i := Low(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) to High(Model.ChangeAccountPrivateKeyModel.SelectedAccounts) do
+    for i := Low(Model.ChangeAccountPrivateKey.SelectedAccounts) to High(Model.ChangeAccountPrivateKey.SelectedAccounts) do
     begin
     begin
-      acc := Model.ChangeAccountPrivateKeyModel.SelectedAccounts[i];
+      acc := Model.ChangeAccountPrivateKey.SelectedAccounts[i];
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       totalBalance := totalBalance + acc.balance;
       totalBalance := totalBalance + acc.balance;
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
@@ -149,9 +149,9 @@ begin
     cbSignerAccount.Items.EndUpdate;
     cbSignerAccount.Items.EndUpdate;
   end;
   end;
   UpdateWalletKeys();
   UpdateWalletKeys();
-  cbSignerAccount.ItemIndex := Model.ChangeAccountPrivateKeyModel.SelectedIndex;
+  cbSignerAccount.ItemIndex := Model.ChangeAccountPrivateKey.SelectedIndex;
   cbSignerAccountChange(Self);
   cbSignerAccountChange(Self);
-  cbNewPrivateKey.ItemIndex := Model.ChangeAccountPrivateKeyModel.PrivateKeySelectedIndex;
+  cbNewPrivateKey.ItemIndex := Model.ChangeAccountPrivateKey.PrivateKeySelectedIndex;
   cbNewPrivateKeyChange(Self);
   cbNewPrivateKeyChange(Self);
   lblTotalBalanceValue.Caption :=
   lblTotalBalanceValue.Caption :=
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
@@ -161,10 +161,10 @@ end;
 
 
 procedure TWIZChangeAccountPrivateKey_Transaction.OnNext;
 procedure TWIZChangeAccountPrivateKey_Transaction.OnNext;
 begin
 begin
-  Model.ChangeAccountPrivateKeyModel.SelectedIndex := cbSignerAccount.ItemIndex;
-  Model.ChangeAccountPrivateKeyModel.PrivateKeySelectedIndex := cbNewPrivateKey.ItemIndex;
-  Model.SignerModel.SignerAccount := Model.ChangeAccountPrivateKeyModel.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
-  Model.ChangeAccountPrivateKeyModel.NewWalletKey := TWallet.Keys.Key[PtrInt(cbNewPrivateKey.Items.Objects[cbNewPrivateKey.ItemIndex])];
+  Model.ChangeAccountPrivateKey.SelectedIndex := cbSignerAccount.ItemIndex;
+  Model.ChangeAccountPrivateKey.PrivateKeySelectedIndex := cbNewPrivateKey.ItemIndex;
+  Model.Signer.SignerAccount := Model.ChangeAccountPrivateKey.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
+  Model.ChangeAccountPrivateKey.NewWalletKey := TWallet.Keys.Key[PtrInt(cbNewPrivateKey.Items.Objects[cbNewPrivateKey.ItemIndex])];
 
 
   UpdatePath(ptReplaceAllNext, [TWIZChangeAccountPrivateKey_TransactionPayload, TWIZChangeAccountPrivateKey_Confirmation]);
   UpdatePath(ptReplaceAllNext, [TWIZChangeAccountPrivateKey_TransactionPayload, TWIZChangeAccountPrivateKey_Confirmation]);
 end;
 end;
@@ -187,7 +187,7 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.FeeModel.DefaultFee) then
+  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.Fee.DefaultFee) then
   begin
   begin
     message := 'Invalid fee value "' + edtOpFee.Text + '"';
     message := 'Invalid fee value "' + edtOpFee.Text + '"';
     Result := False;
     Result := False;

+ 5 - 5
src/gui/wizards/UWIZChangeAccountPrivateKey_TransactionPayload.pas

@@ -48,25 +48,25 @@ uses
 
 
 procedure TWIZChangeAccountPrivateKey_TransactionPayload.OnNext;
 procedure TWIZChangeAccountPrivateKey_TransactionPayload.OnNext;
 begin
 begin
-  Model.PayloadModel.Payload := mmoPayload.Lines.Text;
+  Model.Payload.Content := mmoPayload.Lines.Text;
   if rbEncryptedWithOldEC.Checked then
   if rbEncryptedWithOldEC.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithOldEC;
+    Model.Payload.Mode := akaEncryptWithSender;
   end
   end
   else
   else
   if rbEncryptedWithEC.Checked then
   if rbEncryptedWithEC.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithEC;
+    Model.Payload.Mode := akaEncryptWithReceiver;
   end
   end
   else
   else
   if rbEncryptedWithPassword.Checked then
   if rbEncryptedWithPassword.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithPassword;
+    Model.Payload.Mode := akaEncryptWithPassword;
   end
   end
   else
   else
   if rbNotEncrypted.Checked then
   if rbNotEncrypted.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaNotEncrypt;
+    Model.Payload.Mode := akaNotEncrypt;
   end;
   end;
 end;
 end;
 
 

+ 86 - 77
src/gui/wizards/UWIZModels.pas

@@ -7,7 +7,8 @@ unit UWIZModels;
 
 
 interface
 interface
 
 
-uses Classes, SysUtils, UWizard, UAccounts, UBlockChain, UWallet, UBaseTypes, Generics.Defaults;
+uses Classes, SysUtils, UWizard, UAccounts, UBlockChain, UWallet,
+  UBaseTypes, Generics.Defaults;
 
 
 type
 type
 
 
@@ -18,111 +19,119 @@ type
   { TFRMAddKeyModel }
   { TFRMAddKeyModel }
 
 
   TWIZAddKeyModel = class(TComponent)
   TWIZAddKeyModel = class(TComponent)
-    public
-      Name : String;
-      KeyText : String;
-      Password : String;
-      EncryptionTypeNID : word;
-      Action : TWIZAddKeyAction;
+  public
+    Name: string;
+    KeyText: string;
+    Password: string;
+    EncryptionTypeNID: word;
+    Action: TWIZAddKeyAction;
   end;
   end;
 
 
   { TWIZOperationsModel }
   { TWIZOperationsModel }
 
 
-  TWIZOperationsModel = class (TComponent)
-    public type
+  TWIZOperationsModel = class(TComponent)
+  public type
+
+    { TModelType }
 
 
-       { TModelType }
+    TModelType = (omtSendPasc, omtTransferAccount, omtChangeAccountPrivateKey, omtAddKey);
 
 
-       TModelType = (omtSendPasc, omtTransferAccount, omtChangeAccountPrivateKey, omtAddKey);
+    { TPayloadEncryptionMode }
 
 
-       { TPayloadEncryptionMode }
+    TPayloadEncryptionMode = (akaEncryptWithSender, akaEncryptWithReceiver, akaEncryptWithPassword, akaNotEncrypt);
 
 
-       TPayloadEncryptionMode = (akaEncryptWithOldEC, akaEncryptWithEC, akaEncryptWithPassword, akaNotEncrypt);
+    { TOperationSigningMode }
 
 
-       { TSendPASCModel }
+    TOperationSigningMode = (akaPrimary, akaSecondary);
 
 
-       TSendPASCModel = class(TComponent)
-       public
-         SelectedIndex: integer;
-         AmountToSend : string;
-         DestinationAccount: TAccount;
-         SelectedAccounts: TArray<TAccount>;
-       end;
+    { TSendPASCModel }
 
 
-       { TTransferAccountModel }
+    TSendPASCModel = class(TComponent)
+    public
+      SelectedIndex: integer;
+      SingleAmountToSend: int64;
+      DestinationAccount: TAccount;
+      SelectedAccounts: TArray<TAccount>;
+    end;
 
 
-       TTransferAccountModel = class(TComponent)
-       public
-         NewPublicKey: string;
-         SelectedIndex: integer;
-         AccountKey: TAccountKey;
-         SelectedAccounts: TArray<TAccount>;
-       end;
+    { TTransferAccountModel }
 
 
-       { TChangeAccountPrivateKeyModel }
+    TTransferAccountModel = class(TComponent)
+    public
+      NewPublicKey : string;
+      SelectedIndex: integer;
+      AccountKey: TAccountKey;
+      SelectedAccounts: TArray<TAccount>;
+    end;
 
 
-       TChangeAccountPrivateKeyModel = class(TComponent)
-       public
-         NewPublicKey: string;
-         SelectedIndex, PrivateKeySelectedIndex: integer;
-         NewWalletKey: TWalletKey;
-         SelectedAccounts: TArray<TAccount>;
-       end;
+    { TChangeAccountPrivateKeyModel }
 
 
-       { TFeeModel }
+    TChangeAccountPrivateKeyModel = class(TComponent)
+    public
+      NewPublicKey : string;
+      SelectedIndex, PrivateKeySelectedIndex: integer;
+      NewWalletKey: TWalletKey;
+      EncodedPayload: TRawBytes;
+      SelectedAccounts: TArray<TAccount>;
+    end;
 
 
-       TFeeModel = class(TComponent)
-       public
-         DefaultFee: int64;
-       end;
+    { TFeeModel }
 
 
-       { TSignerModel }
+    TFeeModel = class(TComponent)
+    public
+      DefaultFee, SingleOperationFee: int64;
+    end;
 
 
-       TSignerModel = class(TComponent)
-       public
-         SignerAccount: TAccount;
-       end;
+    { TSignerModel }
 
 
-       { TPayloadModel }
+    TSignerModel = class(TComponent)
+    public
+      OperationSigningMode: TOperationSigningMode;
+      SignerAccount: TAccount;
+    end;
 
 
-       TPayloadModel = class(TComponent)
-       public
-         Payload, EncryptionPassword : string;
-         PayloadEncryptionMode: TPayloadEncryptionMode;
-         EncodedPayload: TRawBytes;
-       end;
+    { TPayloadModel }
 
 
-    private
-      FModelType : TModelType;
-      FSendModel : TSendPASCModel;
-      FTransferAccountModel : TTransferAccountModel;
-      FChangeAccountPrivateKeyModel : TChangeAccountPrivateKeyModel;
-      FFeeModel : TFeeModel;
-      FSignerModel : TSignerModel;
-      FPayloadModel : TPayloadModel;
+    TPayloadModel = class(TComponent)
     public
     public
-      constructor Create(AOwner : TComponent; AType : TModelType);  overload;
-      property ModelType : TModelType read FModelType;
-      property SendPASCModel : TSendPASCModel read FSendModel;
-      property TransferAccountModel : TTransferAccountModel read FTransferAccountModel;
-      property ChangeAccountPrivateKeyModel : TChangeAccountPrivateKeyModel read FChangeAccountPrivateKeyModel;
-      property FeeModel : TFeeModel read FFeeModel;
-      property SignerModel : TSignerModel read FSignerModel;
-      property PayloadModel : TPayloadModel read FPayloadModel;
+      HasPayload: boolean;
+      Content, Password : string;
+      Mode: TPayloadEncryptionMode;
+      EncodedBytes: TRawBytes;
+    end;
+
+  private
+    FModelType: TModelType;
+    FSendPASC : TSendPASCModel;
+    FTransferAccount : TTransferAccountModel;
+    FChangeAccountPrivateKey : TChangeAccountPrivateKeyModel;
+    FFee : TFeeModel;
+    FSigner : TSignerModel;
+    FPayload : TPayloadModel;
+  public
+    constructor Create(AOwner: TComponent; AType: TModelType); overload;
+    property ModelType: TModelType read FModelType;
+    property SendPASC: TSendPASCModel read FSendPASC;
+    property TransferAccount: TTransferAccountModel read FTransferAccount;
+    property ChangeAccountPrivateKey : TChangeAccountPrivateKeyModel read FChangeAccountPrivateKey;
+    property Fee : TFeeModel read FFee;
+    property Signer : TSignerModel read FSigner;
+    property Payload : TPayloadModel read FPayload;
   end;
   end;
 
 
 implementation
 implementation
 
 
-constructor TWIZOperationsModel.Create(AOwner : TComponent; AType : TWIZOperationsModel.TModelType);
+constructor TWIZOperationsModel.Create(AOwner: TComponent; AType: TWIZOperationsModel.TModelType);
 begin
 begin
   inherited Create(AOwner);
   inherited Create(AOwner);
   FModelType := AType;
   FModelType := AType;
-  FSendModel := TSendPASCModel.Create(Self);
-  FTransferAccountModel := TTransferAccountModel.Create(Self);
-  FChangeAccountPrivateKeyModel := TChangeAccountPrivateKeyModel.Create(Self);
-  FFeeModel := TFeeModel.Create(Self);
-  FSignerModel := TSignerModel.Create(Self);
+  FSendPASC := TSendPASCModel.Create(Self);
+  FTransferAccount := TTransferAccountModel.Create(Self);
+  FChangeAccountPrivateKey := TChangeAccountPrivateKeyModel.Create(Self);
+  FChangeAccountPrivateKey := TChangeAccountPrivateKeyModel.Create(Self);
+  FFee := TFeeModel.Create(Self);
+  FSigner := TSignerModel.Create(Self);
+  FPayload := TPayloadModel.Create(Self);
 end;
 end;
 
 
 end.
 end.
-

+ 48 - 42
src/gui/wizards/UWIZSendPASC.pas

@@ -22,9 +22,11 @@ type
 
 
   TWIZSendPASCWizard = class(TWizard<TWIZOperationsModel>)
   TWIZSendPASCWizard = class(TWizard<TWIZOperationsModel>)
   private
   private
-    function UpdatePayload(const SenderAccount: TAccount; var errors: string): boolean;
+    function UpdatePayload(const SenderAccount: TAccount;
+      var errors: string): boolean;
     function UpdateOperationOptions(var errors: string): boolean;
     function UpdateOperationOptions(var errors: string): boolean;
-    function UpdateOpTransaction(const SenderAccount: TAccount; var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
+    function UpdateOpTransaction(const SenderAccount: TAccount;
+      var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
     procedure SendPASC();
     procedure SendPASC();
   public
   public
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
@@ -44,7 +46,7 @@ uses
   UWallet,
   UWallet,
   UECIES,
   UECIES,
   UAES,
   UAES,
-  UWIZSendPASC_Start,
+  UWIZSendPASC_ConfirmSender,
   UWIZSendPASC_Confirmation;
   UWIZSendPASC_Confirmation;
 
 
 { TWIZSendPASCWizard }
 { TWIZSendPASCWizard }
@@ -65,7 +67,7 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  if Length(Model.SendPASCModel.SelectedAccounts) = 0 then
+  if Length(Model.SendPASC.SelectedAccounts) = 0 then
   begin
   begin
     errors := 'No sender account';
     errors := 'No sender account';
     Exit;
     Exit;
@@ -73,13 +75,15 @@ begin
   else
   else
   begin
   begin
 
 
-    for iAcc := Low(Model.SendPASCModel.SelectedAccounts) to High(Model.SendPASCModel.SelectedAccounts) do
+    for iAcc := Low(Model.SendPASC.SelectedAccounts) to High(Model.SendPASC.SelectedAccounts) do
     begin
     begin
-      sender_account := Model.SendPASCModel.SelectedAccounts[iAcc];
+      sender_account := Model.SendPASC.SelectedAccounts[iAcc];
       iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
       iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
       if (iWallet < 0) then
       if (iWallet < 0) then
       begin
       begin
-        errors := 'Private key of account ' + TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) + ' not found in wallet';
+        errors := 'Private key of account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
+          ' not found in wallet';
         Exit;
         Exit;
       end;
       end;
       wk := TWallet.Keys.Key[iWallet];
       wk := TWallet.Keys.Key[iWallet];
@@ -93,33 +97,31 @@ begin
         else
         else
         begin
         begin
           errors := 'Only public key of account ' +
           errors := 'Only public key of account ' +
-            TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) + ' found in wallet. You cannot operate with this account';
+            TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
+            ' found in wallet. You cannot operate with this account';
         end;
         end;
         Exit;
         Exit;
       end;
       end;
     end;
     end;
   end;
   end;
 
 
-  Result := UpdateOpTransaction(Model.SendPASCModel.SelectedAccounts[0], dest_account, amount, errors);
+  Result := UpdateOpTransaction(Model.SendPASC.SelectedAccounts[0], dest_account, amount, errors);
   UpdatePayload(sender_account, e);
   UpdatePayload(sender_account, e);
 end;
 end;
 
 
-function TWIZSendPASCWizard.UpdateOpTransaction(const SenderAccount: TAccount; var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
+function TWIZSendPASCWizard.UpdateOpTransaction(const SenderAccount: TAccount;
+  var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
 var
 var
   c: cardinal;
   c: cardinal;
 begin
 begin
   Result := False;
   Result := False;
   errors := '';
   errors := '';
 
 
-  DestAccount := Model.SendPASCModel.DestinationAccount;
+  DestAccount := Model.SendPASC.DestinationAccount;
 
 
-  if Length(Model.SendPASCModel.SelectedAccounts) = 1 then
+  if Length(Model.SendPASC.SelectedAccounts) = 1 then
   begin
   begin
-    if not TAccountComp.TxtToMoney(Model.SendPASCModel.AmountToSend, amount) then
-    begin
-      errors := 'Invalid amount (' + Model.SendPASCModel.AmountToSend + ')';
-      Exit;
-    end;
+    amount := Model.SendPASC.SingleAmountToSend;
   end
   end
   else
   else
   begin
   begin
@@ -132,9 +134,9 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  if (Length(Model.SendPASCModel.SelectedAccounts) = 1) then
+  if (Length(Model.SendPASC.SelectedAccounts) = 1) then
   begin
   begin
-    if (SenderAccount.balance < (amount + Model.FeeModel.DefaultFee)) then
+    if (SenderAccount.balance < (amount + Model.Fee.SingleOperationFee)) then
     begin
     begin
       errors := 'Insufficient funds';
       errors := 'Insufficient funds';
       Exit;
       Exit;
@@ -168,10 +170,10 @@ begin
     _signer_n_ops := 0;
     _signer_n_ops := 0;
     operationstxt := '';
     operationstxt := '';
     operation_to_string := '';
     operation_to_string := '';
-    for iAcc := Low(Model.SendPASCModel.SelectedAccounts) to High(Model.SendPASCModel.SelectedAccounts) do
+    for iAcc := Low(Model.SendPASC.SelectedAccounts) to High(Model.SendPASC.SelectedAccounts) do
     begin
     begin
       op := nil;
       op := nil;
-      account := Model.SendPASCModel.SelectedAccounts[iAcc];
+      account := Model.SendPASC.SelectedAccounts[iAcc];
       if not UpdatePayload(account, errors) then
       if not UpdatePayload(account, errors) then
       begin
       begin
         raise Exception.Create('Error encoding payload of sender account ' +
         raise Exception.Create('Error encoding payload of sender account ' +
@@ -186,21 +188,21 @@ begin
       wk := TWallet.Keys.Key[i];
       wk := TWallet.Keys.Key[i];
       dooperation := True;
       dooperation := True;
       // Default fee
       // Default fee
-      if account.balance > uint64(Model.FeeModel.DefaultFee) then
-        _fee := Model.FeeModel.DefaultFee
+      if account.balance > uint64(Model.Fee.SingleOperationFee) then
+        _fee := Model.Fee.SingleOperationFee
       else
       else
         _fee := account.balance;
         _fee := account.balance;
 
 
       if not UpdateOpTransaction(account, destAccount, _amount, errors) then
       if not UpdateOpTransaction(account, destAccount, _amount, errors) then
         raise Exception.Create(errors);
         raise Exception.Create(errors);
-      if Length(Model.SendPASCModel.SelectedAccounts) > 1 then
+      if Length(Model.SendPASC.SelectedAccounts) > 1 then
       begin
       begin
         if account.balance > 0 then
         if account.balance > 0 then
         begin
         begin
-          if account.balance > Model.FeeModel.DefaultFee then
+          if account.balance > Model.Fee.SingleOperationFee then
           begin
           begin
-            _amount := account.balance - Model.FeeModel.DefaultFee;
-            _fee := Model.FeeModel.DefaultFee;
+            _amount := account.balance - Model.Fee.SingleOperationFee;
+            _fee := Model.Fee.SingleOperationFee;
           end
           end
           else
           else
           begin
           begin
@@ -218,11 +220,12 @@ begin
       begin
       begin
         op := TOpTransaction.CreateTransaction(
         op := TOpTransaction.CreateTransaction(
           account.account, account.n_operation + 1, destAccount.account,
           account.account, account.n_operation + 1, destAccount.account,
-          wk.PrivateKey, _amount, _fee, Model.PayloadModel.EncodedPayload);
+          wk.PrivateKey, _amount, _fee, Model.Payload.EncodedBytes);
         Inc(_totalamount, _amount);
         Inc(_totalamount, _amount);
         Inc(_totalfee, _fee);
         Inc(_totalfee, _fee);
       end;
       end;
-      operationstxt := 'Transaction to ' + TAccountComp.AccountNumberToAccountTxtNumber(destAccount.account);
+      operationstxt := 'Transaction to ' + TAccountComp.AccountNumberToAccountTxtNumber(
+        destAccount.account);
 
 
       if Assigned(op) and (dooperation) then
       if Assigned(op) and (dooperation) then
       begin
       begin
@@ -237,11 +240,12 @@ begin
     if (ops.OperationsCount = 0) then
     if (ops.OperationsCount = 0) then
       raise Exception.Create('No valid operation to execute');
       raise Exception.Create('No valid operation to execute');
 
 
-    if (Length(Model.SendPASCModel.SelectedAccounts) > 1) then
+    if (Length(Model.SendPASC.SelectedAccounts) > 1) then
     begin
     begin
-      auxs := 'Total amount that dest will receive: ' + TAccountComp.FormatMoney(_totalamount) + #10;
+      auxs := 'Total amount that dest will receive: ' + TAccountComp.FormatMoney(
+        _totalamount) + #10;
       if Application.MessageBox(
       if Application.MessageBox(
-        PChar('Execute ' + IntToStr(Length(Model.SendPASCModel.SelectedAccounts)) +
+        PChar('Execute ' + IntToStr(Length(Model.SendPASC.SelectedAccounts)) +
         ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
         ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
         auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
         auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
         #10 + #10 + 'Note: This operation will be transmitted to the network!'),
         #10 + #10 + 'Note: This operation will be transmitted to the network!'),
@@ -312,7 +316,8 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TWIZSendPASCWizard.UpdatePayload(const SenderAccount: TAccount; var errors: string): boolean;
+function TWIZSendPASCWizard.UpdatePayload(const SenderAccount: TAccount;
+  var errors: string): boolean;
 var
 var
   valid: boolean;
   valid: boolean;
   payload_encrypted, payload_u: string;
   payload_encrypted, payload_u: string;
@@ -320,9 +325,9 @@ var
 begin
 begin
   valid := False;
   valid := False;
   payload_encrypted := '';
   payload_encrypted := '';
-  Model.PayloadModel.EncodedPayload := '';
+  Model.Payload.EncodedBytes := '';
   errors := 'Unknown error';
   errors := 'Unknown error';
-  payload_u := Model.PayloadModel.Payload;
+  payload_u := Model.Payload.Content;
 
 
   try
   try
     if (payload_u = '') then
     if (payload_u = '') then
@@ -330,9 +335,9 @@ begin
       valid := True;
       valid := True;
       Exit;
       Exit;
     end;
     end;
-    case Model.PayloadModel.PayloadEncryptionMode of
+    case Model.Payload.Mode of
 
 
-      akaEncryptWithOldEC:
+      akaEncryptWithSender:
       begin
       begin
         // Use sender
         // Use sender
         errors := 'Error encrypting';
         errors := 'Error encrypting';
@@ -341,18 +346,19 @@ begin
         valid := payload_encrypted <> '';
         valid := payload_encrypted <> '';
       end;
       end;
 
 
-      akaEncryptWithEC:
+      akaEncryptWithReceiver:
       begin
       begin
         // With dest public key
         // With dest public key
         errors := 'Error encrypting';
         errors := 'Error encrypting';
-        account := Model.SendPASCModel.DestinationAccount;
+        account := Model.SendPASC.DestinationAccount;
         payload_encrypted := ECIESEncrypt(account.accountInfo.accountKey, payload_u);
         payload_encrypted := ECIESEncrypt(account.accountInfo.accountKey, payload_u);
         valid := payload_encrypted <> '';
         valid := payload_encrypted <> '';
       end;
       end;
 
 
       akaEncryptWithPassword:
       akaEncryptWithPassword:
       begin
       begin
-        payload_encrypted := TAESComp.EVP_Encrypt_AES256(payload_u, Model.PayloadModel.EncryptionPassword);
+        payload_encrypted := TAESComp.EVP_Encrypt_AES256(
+          payload_u, Model.Payload.Password);
         valid := payload_encrypted <> '';
         valid := payload_encrypted <> '';
       end;
       end;
 
 
@@ -379,7 +385,7 @@ begin
       end;
       end;
 
 
     end;
     end;
-    Model.PayloadModel.EncodedPayload := payload_encrypted;
+    Model.Payload.EncodedBytes := payload_encrypted;
     Result := valid;
     Result := valid;
   end;
   end;
 
 
@@ -387,7 +393,7 @@ end;
 
 
 constructor TWIZSendPASCWizard.Create(AOwner: TComponent);
 constructor TWIZSendPASCWizard.Create(AOwner: TComponent);
 begin
 begin
-  inherited Create(AOwner, [TWIZSendPASC_Start, TWIZSendPASC_Confirmation]);
+  inherited Create(AOwner, [TWIZSendPASC_ConfirmSender, TWIZSendPASC_Confirmation]);
   TitleText := 'Send PASC';
   TitleText := 'Send PASC';
   FinishText := 'Send PASC';
   FinishText := 'Send PASC';
 end;
 end;

+ 1 - 1
src/gui/wizards/UWIZSendPASC_ConfirmSender.lfm

@@ -6,7 +6,7 @@ object WIZSendPASC_ConfirmSender: TWIZSendPASC_ConfirmSender
   Caption = 'WIZSendPASC_ConfirmSender'
   Caption = 'WIZSendPASC_ConfirmSender'
   ClientHeight = 261
   ClientHeight = 261
   ClientWidth = 429
   ClientWidth = 429
-  LCLVersion = '1.8.1.0'
+  LCLVersion = '1.8.2.0'
   Visible = False
   Visible = False
   object gpSender: TGroupBox
   object gpSender: TGroupBox
     Left = 4
     Left = 4

+ 1 - 1
src/gui/wizards/UWIZSendPASC_ConfirmSender.pas

@@ -87,7 +87,7 @@ begin
     Filters:=SORTABLE_NUMERIC_FILTER;
     Filters:=SORTABLE_NUMERIC_FILTER;
   end;
   end;
   data := TAccountSenderDataSource.Create(FSendersGrid);
   data := TAccountSenderDataSource.Create(FSendersGrid);
-  data.Model := Model.SendPASCModel;
+  data.Model := Model.SendPASC;
   FSendersGrid.DataSource := data;
   FSendersGrid.DataSource := data;
   paGrid.AddControlDockCenter(FSendersGrid);
   paGrid.AddControlDockCenter(FSendersGrid);
 end;
 end;

+ 11 - 7
src/gui/wizards/UWIZSendPASC_Confirmation.pas

@@ -3,10 +3,14 @@ unit UWIZSendPASC_Confirmation;
 {$mode delphi}
 {$mode delphi}
 {$modeswitch nestedprocvars}
 {$modeswitch nestedprocvars}
 
 
-{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+{ Copyright (c) 2018 Sphere 10 Software (http://www.sphere10.com/)
 
 
   Distributed under the MIT software license, see the accompanying file LICENSE
   Distributed under the MIT software license, see the accompanying file LICENSE
   or visit http://www.opensource.org/licenses/mit-license.php.
   or visit http://www.opensource.org/licenses/mit-license.php.
+
+  Acknowledgements:
+  Ugochukwu Mmaduekwe - main developer
+  Herman Schoenfeld - designer
 }
 }
 
 
 interface
 interface
@@ -93,8 +97,8 @@ begin
    data.Model := Model;
    data.Model := Model;
    FSendersGrid.DataSource := data;
    FSendersGrid.DataSource := data;
    paGrid.AddControlDockCenter(FSendersGrid);
    paGrid.AddControlDockCenter(FSendersGrid);
-   lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.SignerModel.SignerAccount.account);
-   lblDestAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.SendPASCModel.DestinationAccount.account);
+   lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.Signer.SignerAccount.account);
+   lblDestAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.SendPASC.DestinationAccount.account);
 end;
 end;
 
 
 { TAccountSenderDataSource }
 { TAccountSenderDataSource }
@@ -118,9 +122,9 @@ begin
    else if ABindingName = 'Balance' then
    else if ABindingName = 'Balance' then
      Result := TAccountComp.FormatMoney(AItem.Balance)
      Result := TAccountComp.FormatMoney(AItem.Balance)
    else if ABindingName = 'AmountToSend' then
    else if ABindingName = 'AmountToSend' then
-     Result := Model.SendPASCModel.AmountToSend
+     Result := TAccountComp.FormatMoney(Model.SendPASC.SingleAmountToSend)
      else if ABindingName = 'Fee' then
      else if ABindingName = 'Fee' then
-     Result := TAccountComp.FormatMoney(Model.FeeModel.DefaultFee)
+     Result := TAccountComp.FormatMoney(Model.Fee.SingleOperationFee)
    else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
    else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
 end;
 end;
 
 
@@ -129,9 +133,9 @@ procedure TAccountSenderDataSource.FetchAll(const AContainer : TList<TAccount>);
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
-  for i := Low(Model.SendPASCModel.SelectedAccounts) to High(Model.SendPASCModel.SelectedAccounts) do
+  for i := Low(Model.SendPASC.SelectedAccounts) to High(Model.SendPASC.SelectedAccounts) do
   begin
   begin
-    AContainer.Add( Model.SendPASCModel.SelectedAccounts[i] );
+    AContainer.Add( Model.SendPASC.SelectedAccounts[i] );
   end;
   end;
 end;
 end;
 
 

+ 1 - 0
src/gui/wizards/UWIZSendPASC_EnterQuantity.lfm

@@ -7,6 +7,7 @@ object WIZSendPASC_EnterQuantity: TWIZSendPASC_EnterQuantity
   Caption = 'WIZSendPASC_EnterQuantity'
   Caption = 'WIZSendPASC_EnterQuantity'
   ClientHeight = 253
   ClientHeight = 253
   ClientWidth = 429
   ClientWidth = 429
+  LCLVersion = '1.8.2.0'
   Visible = False
   Visible = False
   object gbQuantity: TGroupBox
   object gbQuantity: TGroupBox
     Left = 16
     Left = 16

+ 6 - 6
src/gui/wizards/UWIZSendPASC_EnterQuantity.pas

@@ -66,7 +66,7 @@ begin
     edtAmt.Enabled := True;
     edtAmt.Enabled := True;
   end;
   end;
 
 
-  Model.SendPASCModel.HasPayload := IIF(chkAttachPayload.Checked, True, False);
+  Model.Payload.HasPayload := IIF(chkAttachPayload.Checked, True, False);
 
 
 end;
 end;
 
 
@@ -89,14 +89,14 @@ procedure TWIZSendPASC_EnterQuantity.OnNext;
 var
 var
   amount: Int64;
   amount: Int64;
 begin
 begin
-  Model.SendPASCModel.HasPayload := chkAttachPayload.Checked;
+  Model.Payload.HasPayload := chkAttachPayload.Checked;
   if chkallfunds.Checked then
   if chkallfunds.Checked then
   begin
   begin
-    Model.SendPASCModel.SingleAmountToSend := 0; // all balance
+    Model.SendPASC.SingleAmountToSend := 0; // all balance
   end
   end
   else
   else
   begin
   begin
-    TAccountComp.TxtToMoney(edtAmt.Text, Model.SendPASCModel.SingleAmountToSend);
+    TAccountComp.TxtToMoney(edtAmt.Text, Model.SendPASC.SingleAmountToSend);
   end;
   end;
 
 
   if chkChooseFee.Checked then
   if chkChooseFee.Checked then
@@ -105,8 +105,8 @@ begin
   end
   end
   else
   else
   begin
   begin
-    Model.SendPASCModel.SingleOperationFee := TSettings.DefaultFee;
-    if Model.SendPASCModel.HasPayload then
+    Model.Fee.SingleOperationFee := TSettings.DefaultFee;
+    if Model.Payload.HasPayload then
     begin
     begin
       UpdatePath(ptReplaceAllNext, [TWIZPayloadOverride, TWIZSendPASC_Confirmation]);
       UpdatePath(ptReplaceAllNext, [TWIZPayloadOverride, TWIZSendPASC_Confirmation]);
     end
     end

+ 10 - 10
src/gui/wizards/UWIZSendPASC_Transaction.pas

@@ -63,7 +63,7 @@ begin
   begin
   begin
     lblBalance.Font.Color := clGreen;
     lblBalance.Font.Color := clGreen;
     lblBalance.Caption := Format('%s PASC',
     lblBalance.Caption := Format('%s PASC',
-      [TAccountComp.FormatMoney(Model.SendPASCModel.SelectedAccounts[PtrInt(
+      [TAccountComp.FormatMoney(Model.SendPASC.SelectedAccounts[PtrInt(
       cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
       cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
   end;
   end;
 end;
 end;
@@ -109,9 +109,9 @@ begin
   try
   try
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Add('Select Signer Account');
     cbSignerAccount.Items.Add('Select Signer Account');
-    for i := 0 to High(Model.SendPASCModel.SelectedAccounts) do
+    for i := 0 to High(Model.SendPASC.SelectedAccounts) do
     begin
     begin
-      acc := Model.SendPASCModel.SelectedAccounts[i];
+      acc := Model.SendPASC.SelectedAccounts[i];
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       totalBalance := totalBalance + acc.balance;
       totalBalance := totalBalance + acc.balance;
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
@@ -119,12 +119,12 @@ begin
   finally
   finally
     cbSignerAccount.Items.EndUpdate;
     cbSignerAccount.Items.EndUpdate;
   end;
   end;
-  cbSignerAccount.ItemIndex := Model.SendPASCModel.SelectedIndex;
+  cbSignerAccount.ItemIndex := Model.SendPASC.SelectedIndex;
   cbSignerAccountChange(Self);
   cbSignerAccountChange(Self);
   lblTotalBalanceValue.Caption :=
   lblTotalBalanceValue.Caption :=
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
 
 
-  if Length(Model.SendPASCModel.SelectedAccounts) > 1 then
+  if Length(Model.SendPASC.SelectedAccounts) > 1 then
   begin
   begin
     edtAmt.Text := 'ALL BALANCE';
     edtAmt.Text := 'ALL BALANCE';
     edtAmt.Enabled := False;
     edtAmt.Enabled := False;
@@ -170,10 +170,10 @@ procedure TWIZSendPASC_Transaction.OnNext;
   end;
   end;
 
 
 begin
 begin
-  Model.SendPASCModel.SelectedIndex := cbSignerAccount.ItemIndex;
-  Model.SignerModel.SignerAccount := Model.SendPASCModel.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
-  Model.SendPASCModel.DestinationAccount := GetAccounts(GetAccNoWithoutChecksum(edtDestAcc.Text));
-  Model.SendPASCModel.AmountToSend := edtAmt.Text;
+  Model.SendPASC.SelectedIndex := cbSignerAccount.ItemIndex;
+  Model.SignerModel.SignerAccount := Model.SendPASC.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
+  Model.SendPASC.DestinationAccount := GetAccounts(GetAccNoWithoutChecksum(edtDestAcc.Text));
+  Model.SendPASC.AmountToSend := edtAmt.Text;
   UpdatePath(ptReplaceAllNext, [TWIZSendPASC_TransactionPayload, TWIZSendPASC_Confirmation]);
   UpdatePath(ptReplaceAllNext, [TWIZSendPASC_TransactionPayload, TWIZSendPASC_Confirmation]);
 end;
 end;
 
 
@@ -192,7 +192,7 @@ var
   amount, opfee: int64;
   amount, opfee: int64;
   i: integer;
   i: integer;
 begin
 begin
-  Accounts := Model.SendPASCModel.SelectedAccounts;
+  Accounts := Model.SendPASC.SelectedAccounts;
   Result := True;
   Result := True;
   if cbSignerAccount.ItemIndex < 1 then
   if cbSignerAccount.ItemIndex < 1 then
   begin
   begin

+ 5 - 5
src/gui/wizards/UWIZSendPASC_TransactionPayload.pas

@@ -48,25 +48,25 @@ uses
 
 
 procedure TWIZSendPASC_TransactionPayload.OnNext;
 procedure TWIZSendPASC_TransactionPayload.OnNext;
 begin
 begin
-  Model.PayloadModel.Payload := mmoPayload.Lines.Text;
+  Model.Payload.Payload := mmoPayload.Lines.Text;
   if rbEncryptedWithOldEC.Checked then
   if rbEncryptedWithOldEC.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithOldEC;
+    Model.Payload.PayloadEncryptionMode := akaEncryptWithOldEC;
   end
   end
   else
   else
   if rbEncryptedWithEC.Checked then
   if rbEncryptedWithEC.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithEC;
+    Model.Payload.PayloadEncryptionMode := akaEncryptWithEC;
   end
   end
   else
   else
   if rbEncryptedWithPassword.Checked then
   if rbEncryptedWithPassword.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithPassword;
+    Model.Payload.PayloadEncryptionMode := akaEncryptWithPassword;
   end
   end
   else
   else
   if rbNotEncrypted.Checked then
   if rbNotEncrypted.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaNotEncrypt;
+    Model.Payload.PayloadEncryptionMode := akaNotEncrypt;
   end;
   end;
 end;
 end;
 
 

+ 28 - 28
src/gui/wizards/UWIZTransferAccount.pas

@@ -55,9 +55,9 @@ var
 begin
 begin
   valid := False;
   valid := False;
   payload_encrypted := '';
   payload_encrypted := '';
-  Model.PayloadModel.EncodedPayload := '';
+  Model.Payload.EncodedBytes := '';
   errors := 'Unknown error';
   errors := 'Unknown error';
-  payload_u := Model.PayloadModel.Payload;
+  payload_u := Model.Payload.Content;
 
 
   try
   try
     if (payload_u = '') then
     if (payload_u = '') then
@@ -65,9 +65,9 @@ begin
       valid := True;
       valid := True;
       Exit;
       Exit;
     end;
     end;
-    case Model.PayloadModel.PayloadEncryptionMode of
+    case Model.Payload.Mode of
 
 
-      akaEncryptWithOldEC:
+      akaEncryptWithSender:
       begin
       begin
         // Use sender
         // Use sender
         errors := 'Error encrypting';
         errors := 'Error encrypting';
@@ -76,14 +76,14 @@ begin
         valid := payload_encrypted <> '';
         valid := payload_encrypted <> '';
       end;
       end;
 
 
-      akaEncryptWithEC:
+      akaEncryptWithReceiver:
       begin
       begin
         errors := 'Public key: ' + 'Error encrypting';
         errors := 'Public key: ' + 'Error encrypting';
 
 
-        if Model.TransferAccountModel.AccountKey.EC_OpenSSL_NID <>
+        if Model.TransferAccount.AccountKey.EC_OpenSSL_NID <>
           CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then
           CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then
         begin
         begin
-          payload_encrypted := ECIESEncrypt(Model.TransferAccountModel.AccountKey, payload_u);
+          payload_encrypted := ECIESEncrypt(Model.TransferAccount.AccountKey, payload_u);
           valid := payload_encrypted <> '';
           valid := payload_encrypted <> '';
         end
         end
         else
         else
@@ -97,7 +97,7 @@ begin
       akaEncryptWithPassword:
       akaEncryptWithPassword:
       begin
       begin
         payload_encrypted := TAESComp.EVP_Encrypt_AES256(
         payload_encrypted := TAESComp.EVP_Encrypt_AES256(
-          payload_u, Model.PayloadModel.EncryptionPassword);
+          payload_u, Model.Payload.Password);
         valid := payload_encrypted <> '';
         valid := payload_encrypted <> '';
       end;
       end;
 
 
@@ -124,7 +124,7 @@ begin
       end;
       end;
 
 
     end;
     end;
-    Model.PayloadModel.EncodedPayload := payload_encrypted;
+    Model.Payload.EncodedBytes := payload_encrypted;
     Result := valid;
     Result := valid;
   end;
   end;
 
 
@@ -147,7 +147,7 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  if Length(Model.TransferAccountModel.SelectedAccounts) = 0 then
+  if Length(Model.TransferAccount.SelectedAccounts) = 0 then
   begin
   begin
     errors := 'No sender account';
     errors := 'No sender account';
     Exit;
     Exit;
@@ -155,9 +155,9 @@ begin
   else
   else
   begin
   begin
 
 
-    for iAcc := Low(Model.TransferAccountModel.SelectedAccounts) to High(Model.TransferAccountModel.SelectedAccounts) do
+    for iAcc := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
     begin
     begin
-      sender_account := Model.TransferAccountModel.SelectedAccounts[iAcc];
+      sender_account := Model.TransferAccount.SelectedAccounts[iAcc];
       iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
       iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
       if (iWallet < 0) then
       if (iWallet < 0) then
       begin
       begin
@@ -185,7 +185,7 @@ begin
     end;
     end;
   end;
   end;
 
 
-  Result := UpdateOpChangeKey(Model.TransferAccountModel.SelectedAccounts[0], signer_account,
+  Result := UpdateOpChangeKey(Model.TransferAccount.SelectedAccounts[0], signer_account,
     publicKey, errors);
     publicKey, errors);
   UpdatePayload(sender_account, e);
   UpdatePayload(sender_account, e);
 end;
 end;
@@ -197,7 +197,7 @@ begin
   Result := False;
   Result := False;
   errors := '';
   errors := '';
   try
   try
-    if not TAccountComp.AccountKeyFromImport(Model.TransferAccountModel.NewPublicKey,
+    if not TAccountComp.AccountKeyFromImport(Model.TransferAccount.NewPublicKey,
       NewPublicKey, errors) then
       NewPublicKey, errors) then
     begin
     begin
       Exit;
       Exit;
@@ -206,7 +206,7 @@ begin
     if TNode.Node.Bank.SafeBox.CurrentProtocol >= 1 then
     if TNode.Node.Bank.SafeBox.CurrentProtocol >= 1 then
     begin
     begin
       // Signer:
       // Signer:
-      SignerAccount := Model.SignerModel.SignerAccount;
+      SignerAccount := Model.Signer.SignerAccount;
       if (TAccountComp.IsAccountLocked(SignerAccount.accountInfo,
       if (TAccountComp.IsAccountLocked(SignerAccount.accountInfo,
         TNode.Node.Bank.BlocksCount)) then
         TNode.Node.Bank.BlocksCount)) then
       begin
       begin
@@ -270,11 +270,11 @@ begin
     _signer_n_ops := 0;
     _signer_n_ops := 0;
     operationstxt := '';
     operationstxt := '';
     operation_to_string := '';
     operation_to_string := '';
-    for iAcc := Low(Model.TransferAccountModel.SelectedAccounts) to High(Model.TransferAccountModel.SelectedAccounts) do
+    for iAcc := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
     begin
     begin
       loop_start:
       loop_start:
         op := nil;
         op := nil;
-      account := Model.TransferAccountModel.SelectedAccounts[iAcc];
+      account := Model.TransferAccount.SelectedAccounts[iAcc];
       if not UpdatePayload(account, errors) then
       if not UpdatePayload(account, errors) then
       begin
       begin
         raise Exception.Create('Error encoding payload of sender account ' +
         raise Exception.Create('Error encoding payload of sender account ' +
@@ -289,8 +289,8 @@ begin
       wk := TWallet.Keys.Key[i];
       wk := TWallet.Keys.Key[i];
       dooperation := True;
       dooperation := True;
       // Default fee
       // Default fee
-      if account.balance > uint64(Model.FeeModel.DefaultFee) then
-        _fee := Model.FeeModel.DefaultFee
+      if account.balance > uint64(Model.Fee.DefaultFee) then
+        _fee := Model.Fee.DefaultFee
       else
       else
         _fee := account.balance;
         _fee := account.balance;
 
 
@@ -301,11 +301,11 @@ begin
       if _V2 then
       if _V2 then
       begin
       begin
         // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
         // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
-        if (iAcc < Length(Model.TransferAccountModel.SelectedAccounts) - 1) and
+        if (iAcc < Length(Model.TransferAccount.SelectedAccounts) - 1) and
           (account.account = signerAccount.account) then
           (account.account = signerAccount.account) then
         begin
         begin
-          TArrayTool<TAccount>.Swap(Model.TransferAccountModel.SelectedAccounts, iAcc,
-            Length(Model.TransferAccountModel.SelectedAccounts) - 1); // ensure signer account processed last
+          TArrayTool<TAccount>.Swap(Model.TransferAccount.SelectedAccounts, iAcc,
+            Length(Model.TransferAccount.SelectedAccounts) - 1); // ensure signer account processed last
           // TArrayTool_internal<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1);
           // TArrayTool_internal<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1);
           goto loop_start; // TODO: remove ugly hack with refactoring!
           goto loop_start; // TODO: remove ugly hack with refactoring!
         end;
         end;
@@ -314,20 +314,20 @@ begin
         if uint64(_totalSignerFee) >= signerAccount.balance then
         if uint64(_totalSignerFee) >= signerAccount.balance then
           _fee := 0
           _fee := 0
         else if signerAccount.balance - uint64(_totalSignerFee) >
         else if signerAccount.balance - uint64(_totalSignerFee) >
-          uint64(Model.FeeModel.DefaultFee) then
-          _fee := Model.FeeModel.DefaultFee
+          uint64(Model.Fee.DefaultFee) then
+          _fee := Model.Fee.DefaultFee
         else
         else
           _fee := signerAccount.balance - uint64(_totalSignerFee);
           _fee := signerAccount.balance - uint64(_totalSignerFee);
         op := TOpChangeKeySigned.Create(signerAccount.account,
         op := TOpChangeKeySigned.Create(signerAccount.account,
           signerAccount.n_operation + _signer_n_ops + 1, account.account,
           signerAccount.n_operation + _signer_n_ops + 1, account.account,
-          wk.PrivateKey, _newOwnerPublicKey, _fee, Model.PayloadModel.EncodedPayload);
+          wk.PrivateKey, _newOwnerPublicKey, _fee, Model.Payload.EncodedBytes);
         Inc(_signer_n_ops);
         Inc(_signer_n_ops);
         Inc(_totalSignerFee, _fee);
         Inc(_totalSignerFee, _fee);
       end
       end
       else
       else
       begin
       begin
         op := TOpChangeKey.Create(account.account, account.n_operation +
         op := TOpChangeKey.Create(account.account, account.n_operation +
-          1, account.account, wk.PrivateKey, _newOwnerPublicKey, _fee, Model.PayloadModel.EncodedPayload);
+          1, account.account, wk.PrivateKey, _newOwnerPublicKey, _fee, Model.Payload.EncodedBytes);
       end;
       end;
       Inc(_totalfee, _fee);
       Inc(_totalfee, _fee);
       operationstxt :=
       operationstxt :=
@@ -347,11 +347,11 @@ begin
     if (ops.OperationsCount = 0) then
     if (ops.OperationsCount = 0) then
       raise Exception.Create('No valid operation to execute');
       raise Exception.Create('No valid operation to execute');
 
 
-    if (Length(Model.TransferAccountModel.SelectedAccounts) > 1) then
+    if (Length(Model.TransferAccount.SelectedAccounts) > 1) then
     begin
     begin
       auxs := '';
       auxs := '';
       if Application.MessageBox(
       if Application.MessageBox(
-        PChar('Execute ' + IntToStr(Length(Model.TransferAccountModel.SelectedAccounts)) +
+        PChar('Execute ' + IntToStr(Length(Model.TransferAccount.SelectedAccounts)) +
         ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
         ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
         auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
         auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
         #10 + #10 + 'Note: This operation will be transmitted to the network!'),
         #10 + #10 + 'Note: This operation will be transmitted to the network!'),

+ 5 - 5
src/gui/wizards/UWIZTransferAccount_Confirmation.pas

@@ -91,7 +91,7 @@ begin
    data.Model := Model;
    data.Model := Model;
    FSendersGrid.DataSource := data;
    FSendersGrid.DataSource := data;
    paGrid.AddControlDockCenter(FSendersGrid);
    paGrid.AddControlDockCenter(FSendersGrid);
-   lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.SignerModel.SignerAccount.account);
+   lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.Signer.SignerAccount.account);
 end;
 end;
 
 
 { TAccountSenderDataSource }
 { TAccountSenderDataSource }
@@ -115,9 +115,9 @@ begin
    else if ABindingName = 'CurrentPublicKey' then
    else if ABindingName = 'CurrentPublicKey' then
      Result := TAccountComp.AccountPublicKeyExport(AItem.accountInfo.accountKey)
      Result := TAccountComp.AccountPublicKeyExport(AItem.accountInfo.accountKey)
    else if ABindingName = 'NewPublicKey' then
    else if ABindingName = 'NewPublicKey' then
-     Result := Model.TransferAccountModel.NewPublicKey
+     Result := Model.TransferAccount.NewPublicKey
      else if ABindingName = 'Fee' then
      else if ABindingName = 'Fee' then
-     Result := TAccountComp.FormatMoney(Model.FeeModel.DefaultFee)
+     Result := TAccountComp.FormatMoney(Model.Fee.DefaultFee)
    else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
    else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
 end;
 end;
 
 
@@ -126,9 +126,9 @@ procedure TAccountSenderDataSource.FetchAll(const AContainer : TList<TAccount>);
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
-  for i := Low(Model.TransferAccountModel.SelectedAccounts) to High(Model.TransferAccountModel.SelectedAccounts) do
+  for i := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
   begin
   begin
-    AContainer.Add( Model.TransferAccountModel.SelectedAccounts[i] );
+    AContainer.Add( Model.TransferAccount.SelectedAccounts[i] );
   end;
   end;
 end;
 end;
 
 

+ 12 - 12
src/gui/wizards/UWIZTransferAccount_Transaction.pas

@@ -61,7 +61,7 @@ begin
   else
   else
   begin
   begin
     lblBalance.Font.Color := clGreen;
     lblBalance.Font.Color := clGreen;
-    lblBalance.Caption := Format('%s PASC', [TAccountComp.FormatMoney(Model.TransferAccountModel.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
+    lblBalance.Caption := Format('%s PASC', [TAccountComp.FormatMoney(Model.TransferAccount.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
   end;
   end;
 end;
 end;
 
 
@@ -83,9 +83,9 @@ begin
   try
   try
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Add('Select Signer Account');
     cbSignerAccount.Items.Add('Select Signer Account');
-    for i := Low(Model.TransferAccountModel.SelectedAccounts) to High(Model.TransferAccountModel.SelectedAccounts) do
+    for i := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
     begin
     begin
-      acc := Model.TransferAccountModel.SelectedAccounts[i];
+      acc := Model.TransferAccount.SelectedAccounts[i];
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       totalBalance := totalBalance + acc.balance;
       totalBalance := totalBalance + acc.balance;
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
@@ -93,7 +93,7 @@ begin
   finally
   finally
     cbSignerAccount.Items.EndUpdate;
     cbSignerAccount.Items.EndUpdate;
   end;
   end;
-  cbSignerAccount.ItemIndex := Model.TransferAccountModel.SelectedIndex;
+  cbSignerAccount.ItemIndex := Model.TransferAccount.SelectedIndex;
   cbSignerAccountChange(Self);
   cbSignerAccountChange(Self);
   lblTotalBalanceValue.Caption :=
   lblTotalBalanceValue.Caption :=
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
@@ -103,10 +103,10 @@ end;
 
 
 procedure TWIZTransferAccount_Transaction.OnNext;
 procedure TWIZTransferAccount_Transaction.OnNext;
 begin
 begin
-  Model.TransferAccountModel.SelectedIndex := cbSignerAccount.ItemIndex;
-  Model.SignerModel.SignerAccount := Model.TransferAccountModel.SelectedAccounts[PtrInt(
+  Model.TransferAccount.SelectedIndex := cbSignerAccount.ItemIndex;
+  Model.Signer.SignerAccount := Model.TransferAccount.SelectedAccounts[PtrInt(
     cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
     cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
-  Model.TransferAccountModel.NewPublicKey := Trim(edtPublicKey.Text);
+  Model.TransferAccount.NewPublicKey := Trim(edtPublicKey.Text);
 
 
   UpdatePath(ptReplaceAllNext, [TWIZTransferAccount_TransactionPayload,
   UpdatePath(ptReplaceAllNext, [TWIZTransferAccount_TransactionPayload,
     TWIZTransferAccount_Confirmation]);
     TWIZTransferAccount_Confirmation]);
@@ -124,7 +124,7 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.FeeModel.DefaultFee) then
+  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.Fee.DefaultFee) then
   begin
   begin
     message := 'Invalid fee value "' + edtOpFee.Text + '"';
     message := 'Invalid fee value "' + edtOpFee.Text + '"';
     Result := False;
     Result := False;
@@ -132,11 +132,11 @@ begin
   end;
   end;
 
 
   Result := TAccountComp.AccountKeyFromImport(edtPublicKey.Text,
   Result := TAccountComp.AccountKeyFromImport(edtPublicKey.Text,
-    Model.TransferAccountModel.AccountKey, message);
-  for i := Low(Model.TransferAccountModel.SelectedAccounts) to High(Model.TransferAccountModel.SelectedAccounts) do
+    Model.TransferAccount.AccountKey, message);
+  for i := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
   begin
   begin
-    if TAccountComp.EqualAccountKeys(Model.TransferAccountModel.SelectedAccounts[i].accountInfo.accountKey,
-      Model.TransferAccountModel.AccountKey) then
+    if TAccountComp.EqualAccountKeys(Model.TransferAccount.SelectedAccounts[i].accountInfo.accountKey,
+      Model.TransferAccount.AccountKey) then
     begin
     begin
       Result := False;
       Result := False;
       message := 'new public key is same as selected account public key';
       message := 'new public key is same as selected account public key';

+ 5 - 5
src/gui/wizards/UWIZTransferAccount_TransactionPayload.pas

@@ -48,25 +48,25 @@ uses
 
 
 procedure TWIZTransferAccount_TransactionPayload.OnNext;
 procedure TWIZTransferAccount_TransactionPayload.OnNext;
 begin
 begin
-  Model.PayloadModel.Payload := mmoPayload.Lines.Text;
+  Model.Payload.Content := mmoPayload.Lines.Text;
   if rbEncryptedWithOldEC.Checked then
   if rbEncryptedWithOldEC.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithOldEC;
+    Model.Payload.Mode := akaEncryptWithSender;
   end
   end
   else
   else
   if rbEncryptedWithEC.Checked then
   if rbEncryptedWithEC.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithEC;
+    Model.Payload.Mode := akaEncryptWithReceiver;
   end
   end
   else
   else
   if rbEncryptedWithPassword.Checked then
   if rbEncryptedWithPassword.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaEncryptWithPassword;
+    Model.Payload.Mode := akaEncryptWithPassword;
   end
   end
   else
   else
   if rbNotEncrypted.Checked then
   if rbNotEncrypted.Checked then
   begin
   begin
-    Model.PayloadModel.PayloadEncryptionMode := akaNotEncrypt;
+    Model.Payload.Mode := akaNotEncrypt;
   end;
   end;
 end;
 end;
 
 

+ 455 - 0
src/gui/wizards/operations/UWIZChangeAccountPrivateKey.pas

@@ -0,0 +1,455 @@
+unit UWIZChangeAccountPrivateKey;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+
+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UWallet, UCommon, UWizard,
+  UAccounts, LCLType, UWIZModels;
+
+type
+
+  { TWIZChangeAccountPrivateKeyWizard }
+
+  TWIZChangeAccountPrivateKeyWizard = class(TWizard<TWIZOperationsModel>)
+  private
+    function UpdatePayload(const SenderAccount: TAccount; var errors: string): boolean;
+    function UpdateOperationOptions(var errors: string): boolean;
+    function UpdateOpChangeKey(const TargetAccount: TAccount; var SignerAccount: TAccount; var NewPublicKey: TAccountKey; var errors: ansistring): boolean;
+    procedure ChangeAccountPrivateKey();
+  public
+    constructor Create(AOwner: TComponent); override;
+    function DetermineHasNext: boolean; override;
+    function DetermineHasPrevious: boolean; override;
+    function FinishRequested(out message: ansistring): boolean; override;
+    function CancelRequested(out message: ansistring): boolean; override;
+  end;
+
+implementation
+
+uses
+  UBlockChain,
+  UOpTransaction,
+  UNode,
+  UConst,
+  UECIES,
+  UAES,
+  UWIZChangeAccountPrivateKey_Start,
+  UWIZChangeAccountPrivateKey_Confirmation;
+
+{ TWIZChangeAccountPrivateKeyWizard }
+
+function TWIZChangeAccountPrivateKeyWizard.UpdatePayload(const SenderAccount: TAccount;
+  var errors: string): boolean;
+var
+  valid: boolean;
+  payload_encrypted, payload_u: string;
+  account: TAccount;
+  public_key: TAccountKey;
+begin
+  valid := False;
+  payload_encrypted := '';
+  Model.ChangeAccountPrivateKey.EncodedPayload := '';
+  errors := 'Unknown error';
+  payload_u := Model.Payload.Content;
+
+  try
+    if (payload_u = '') then
+    begin
+      valid := True;
+      Exit;
+    end;
+    case Model.Payload.Mode 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 := 'Error encrypting';
+
+        public_key := Model.ChangeAccountPrivateKey.NewWalletKey.AccountKey;
+        if public_key.EC_OpenSSL_NID <>
+          CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then
+        begin
+          payload_encrypted := ECIESEncrypt(public_key, payload_u);
+          valid := payload_encrypted <> '';
+        end
+        else
+        begin
+          valid := False;
+          errors := 'Selected private key is not valid to encode';
+          exit;
+        end;
+      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
+      begin
+        raise Exception.Create('Invalid Encryption Selection');
+      end;
+    end;
+
+  finally
+    if valid then
+    begin
+      if length(payload_encrypted) > CT_MaxPayloadSize then
+      begin
+        valid := False;
+        errors := 'Payload size is bigger than ' + IntToStr(CT_MaxPayloadSize) +
+          ' (' + IntToStr(length(payload_encrypted)) + ')';
+      end;
+
+    end;
+    Model.ChangeAccountPrivateKey.EncodedPayload := payload_encrypted;
+    Result := valid;
+  end;
+
+end;
+
+function TWIZChangeAccountPrivateKeyWizard.UpdateOperationOptions(
+  var errors: string): boolean;
+var
+  iAcc, iWallet: integer;
+  sender_account, signer_account: TAccount;
+  publicKey: TAccountKey;
+  wk: TWalletKey;
+  e: string;
+  amount: int64;
+begin
+  Result := False;
+  errors := '';
+  if not Assigned(TWallet.Keys) then
+  begin
+    errors := 'No wallet keys';
+    Exit;
+  end;
+
+  if Length(Model.ChangeAccountPrivateKey.SelectedAccounts) = 0 then
+  begin
+    errors := 'No sender account';
+    Exit;
+  end
+  else
+  begin
+
+    for iAcc := Low(Model.ChangeAccountPrivateKey.SelectedAccounts) to High(Model.ChangeAccountPrivateKey.SelectedAccounts) do
+    begin
+      sender_account := Model.ChangeAccountPrivateKey.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
+        begin
+          // TODO: handle unlocking of encrypted wallet here
+          errors := 'Wallet is password protected. Need password';
+        end
+        else
+        begin
+          errors := 'Only public key of account ' +
+            TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
+            ' found in wallet. You cannot operate with this account';
+        end;
+        Exit;
+      end;
+    end;
+  end;
+
+  Result := UpdateOpChangeKey(Model.ChangeAccountPrivateKey.SelectedAccounts[0], signer_account,
+    publicKey, errors);
+  UpdatePayload(sender_account, e);
+end;
+
+function TWIZChangeAccountPrivateKeyWizard.UpdateOpChangeKey(
+  const TargetAccount: TAccount; var SignerAccount: TAccount;
+  var NewPublicKey: TAccountKey; var errors: ansistring): boolean;
+begin
+  Result := False;
+  errors := '';
+  try
+    NewPublicKey := Model.ChangeAccountPrivateKey.NewWalletKey.AccountKey;
+
+    if TNode.Node.Bank.SafeBox.CurrentProtocol >= 1 then
+    begin
+      // Signer:
+      SignerAccount := Model.Signer.SignerAccount;
+      if (TAccountComp.IsAccountLocked(SignerAccount.accountInfo,
+        TNode.Node.Bank.BlocksCount)) then
+      begin
+        errors := 'Signer account ' + TAccountComp.AccountNumberToAccountTxtNumber(
+          SignerAccount.account) + ' is locked until block ' + IntToStr(
+          SignerAccount.accountInfo.locked_until_block);
+        exit;
+      end;
+      if (not TAccountComp.EqualAccountKeys(
+        SignerAccount.accountInfo.accountKey, TargetAccount.accountInfo.accountKey)) then
+      begin
+        errors := 'Signer account ' + TAccountComp.AccountNumberToAccountTxtNumber(
+          SignerAccount.account) + ' is not owner of account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(TargetAccount.account);
+        exit;
+      end;
+    end
+    else
+    begin
+      SignerAccount := TargetAccount;
+    end;
+
+    if (TAccountComp.EqualAccountKeys(TargetAccount.accountInfo.accountKey,
+      NewPublicKey)) then
+    begin
+      errors := 'New public key is the same public key';
+      exit;
+    end;
+
+  finally
+    Result := errors = '';
+  end;
+end;
+
+procedure TWIZChangeAccountPrivateKeyWizard.ChangeAccountPrivateKey();
+var
+  _V2, dooperation: boolean;
+  iAcc, i: integer;
+  _totalamount, _totalfee, _totalSignerFee, _amount, _fee: int64;
+  _signer_n_ops: cardinal;
+  operationstxt, operation_to_string, errors, auxs: string;
+  wk: TWalletKey;
+  ops: TOperationsHashTree;
+  op: TPCOperation;
+  account, signerAccount: 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.ChangeAccountPrivateKey.SelectedAccounts) to High(Model.ChangeAccountPrivateKey.SelectedAccounts) do
+    begin
+      loop_start:
+        op := nil;
+      account := Model.ChangeAccountPrivateKey.SelectedAccounts[iAcc];
+      if not UpdatePayload(account, errors) then
+      begin
+        raise Exception.Create('Error encoding payload of sender account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(account.account) + ': ' + errors);
+      end;
+      i := TWallet.Keys.IndexOfAccountKey(account.accountInfo.accountKey);
+      if i < 0 then
+      begin
+        raise Exception.Create('Sender account private key not found in Wallet');
+      end;
+
+      wk := TWallet.Keys.Key[i];
+      dooperation := True;
+      // Default fee
+      if account.balance > uint64(Model.ChangeAccountPrivateKey.Fee.DefaultFee) then
+        _fee := Model.ChangeAccountPrivateKey.Fee.DefaultFee
+      else
+        _fee := account.balance;
+
+      if not UpdateOpChangeKey(account, signerAccount, _newOwnerPublicKey, errors) then
+      begin
+        raise Exception.Create(errors);
+      end;
+      if _V2 then
+      begin
+        // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
+        if (iAcc < Length(Model.ChangeAccountPrivateKey.SelectedAccounts) - 1) and
+          (account.account = signerAccount.account) then
+        begin
+          TArrayTool<TAccount>.Swap(Model.ChangeAccountPrivateKey.SelectedAccounts, iAcc,
+            Length(Model.ChangeAccountPrivateKey.SelectedAccounts) - 1); // ensure signer account processed last
+          // TArrayTool_internal<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1);
+          goto loop_start; // TODO: remove ugly hack with refactoring!
+        end;
+
+        // Maintain correct signer fee distribution
+        if uint64(_totalSignerFee) >= signerAccount.balance then
+          _fee := 0
+        else if signerAccount.balance - uint64(_totalSignerFee) >
+          uint64(Model.ChangeAccountPrivateKey.Fee.DefaultFee) then
+          _fee := Model.ChangeAccountPrivateKey.Fee.DefaultFee
+        else
+          _fee := signerAccount.balance - uint64(_totalSignerFee);
+        op := TOpChangeKeySigned.Create(signerAccount.account,
+          signerAccount.n_operation + _signer_n_ops + 1, account.account,
+          wk.PrivateKey, _newOwnerPublicKey, _fee, Model.ChangeAccountPrivateKey.EncodedPayload);
+        Inc(_signer_n_ops);
+        Inc(_totalSignerFee, _fee);
+      end
+      else
+      begin
+        op := TOpChangeKey.Create(account.account, account.n_operation +
+          1, account.account, wk.PrivateKey, _newOwnerPublicKey, _fee,
+          Model.ChangeAccountPrivateKey.EncodedPayload);
+      end;
+      Inc(_totalfee, _fee);
+      operationstxt :=
+        'Change private key to ' + TAccountComp.GetECInfoTxt(
+        _newOwnerPublicKey.EC_OpenSSL_NID);
+
+      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.ChangeAccountPrivateKey.SelectedAccounts) > 1) then
+    begin
+      auxs := '';
+      if Application.MessageBox(
+        PChar('Execute ' + IntToStr(Length(Model.ChangeAccountPrivateKey.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
+      begin
+        Exit;
+      end;
+    end
+    else
+    begin
+      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
+      begin
+        Exit;
+      end;
+    end;
+    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
+      begin
+
+        ShowMessage(operationstxt);
+      end
+      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
+    begin
+      raise Exception.Create(errors);
+    end;
+
+
+  finally
+    ops.Free;
+  end;
+
+end;
+
+constructor TWIZChangeAccountPrivateKeyWizard.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner, [TWIZChangeAccountPrivateKey_Start,
+    TWIZChangeAccountPrivateKey_Confirmation]);
+  TitleText := 'Change Key';
+  FinishText := 'Change Key';
+end;
+
+function TWIZChangeAccountPrivateKeyWizard.DetermineHasNext: boolean;
+begin
+  Result := not (CurrentScreen is TWIZChangeAccountPrivateKey_Confirmation);
+end;
+
+function TWIZChangeAccountPrivateKeyWizard.DetermineHasPrevious: boolean;
+begin
+  Result := inherited DetermineHasPrevious;
+end;
+
+function TWIZChangeAccountPrivateKeyWizard.FinishRequested(
+  out message: ansistring): boolean;
+begin
+  // Execute the Change Account Private Key Action here
+  try
+    Result := True;
+    ChangeAccountPrivateKey();
+  except
+    On E: Exception do
+    begin
+      Result := False;
+      message := E.ToString;
+    end;
+  end;
+end;
+
+function TWIZChangeAccountPrivateKeyWizard.CancelRequested(
+  out message: ansistring): boolean;
+begin
+  Result := True;
+end;
+
+end.

+ 48 - 0
src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Confirmation.lfm

@@ -0,0 +1,48 @@
+object WIZChangeAccountPrivateKey_Confirmation: TWIZChangeAccountPrivateKey_Confirmation
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  Caption = 'WIZChangeAccountPrivateKey_Confirmation'
+  ClientHeight = 253
+  ClientWidth = 429
+  LCLVersion = '1.8.2.0'
+  Visible = False
+  object GroupBox1: TGroupBox
+    Left = 10
+    Height = 232
+    Top = 8
+    Width = 408
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    Caption = 'Confirm Transfer Transaction'
+    ClientHeight = 212
+    ClientWidth = 404
+    TabOrder = 0
+    object paGrid: TPanel
+      Left = 8
+      Height = 152
+      Top = 48
+      Width = 382
+      Anchors = [akTop, akLeft, akRight, akBottom]
+      BevelOuter = bvNone
+      Caption = 'GRID PANEL'
+      TabOrder = 0
+    end
+    object Label1: TLabel
+      Left = 8
+      Height = 15
+      Top = 16
+      Width = 84
+      Caption = 'Signer Account:'
+      ParentColor = False
+    end
+    object lblSgnAcc: TLabel
+      Left = 112
+      Height = 15
+      Top = 16
+      Width = 53
+      Caption = 'lblSgnAcc'
+      ParentColor = False
+    end
+  end
+end

+ 144 - 0
src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Confirmation.pas

@@ -0,0 +1,144 @@
+unit UWIZChangeAccountPrivateKey_Confirmation;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  ExtCtrls, UVisualGrid, UCellRenderers, UCommon.Data, UWizard,
+  UWIZChangeAccountPrivateKey, UWIZModels;
+
+type
+
+  { TWIZChangeAccountPrivateKey_Confirmation }
+
+  TWIZChangeAccountPrivateKey_Confirmation = class(TWizardForm<TWIZOperationsModel>)
+    GroupBox1: TGroupBox;
+    Label1: TLabel;
+    lblSgnAcc: TLabel;
+    paGrid: TPanel;
+  private
+    FSendersGrid: TVisualGrid;
+  public
+    procedure OnPresent; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses UAccounts, UCrypto, UDataSources, UCommon, UCommon.UI, Generics.Collections;
+
+type
+
+  { TAccountSenderDataSource }
+
+  TAccountSenderDataSource = class(TAccountsDataSourceBase)
+  private
+    FModel: TWIZOperationsModel.TChangeAccountPrivateKeyModel;
+  protected
+    function GetColumns: TDataColumns; override;
+  public
+    property Model: TWIZOperationsModel.TChangeAccountPrivateKeyModel read FModel write FModel;
+    procedure FetchAll(const AContainer: TList<TAccount>); override;
+    function GetItemField(constref AItem: TAccount;
+      const ABindingName: ansistring): variant; override;
+  end;
+
+{ TWIZChangeAccountPrivateKey_Confirmation }
+
+procedure TWIZChangeAccountPrivateKey_Confirmation.OnPresent;
+var
+  Data: TAccountSenderDataSource;
+begin
+  FSendersGrid := TVisualGrid.Create(Self);
+  FSendersGrid.CanSearch := False;
+  FSendersGrid.SortMode := smMultiColumn;
+  FSendersGrid.FetchDataInThread := False;
+  FSendersGrid.AutoPageSize := True;
+  FSendersGrid.SelectionType := stNone;
+  FSendersGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone,
+    vgoAutoHidePaging];
+  with FSendersGrid.AddColumn('Account') do
+  begin
+    Binding := 'Account';
+    Filters := SORTABLE_NUMERIC_FILTER;
+    Width := 100;
+    HeaderFontStyles := [fsBold];
+    DataFontStyles := [fsBold];
+  end;
+  with FSendersGrid.AddColumn('New Private Key Name') do
+  begin
+    Binding := 'NewPrivateKey';
+    Filters := SORTABLE_TEXT_FILTER;
+    Width := 100;
+  end;
+  with FSendersGrid.AddColumn('Fee') do
+  begin
+    Filters := SORTABLE_TEXT_FILTER;
+    Width := 100;
+  end;
+
+  Data := TAccountSenderDataSource.Create(FSendersGrid);
+  Data.Model := Model.ChangeAccountPrivateKey;
+  FSendersGrid.DataSource := Data;
+  paGrid.AddControlDockCenter(FSendersGrid);
+  lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.Signer.SignerAccount.account);
+end;
+
+{ TAccountSenderDataSource }
+
+function TAccountSenderDataSource.GetColumns: TDataColumns;
+begin
+  Result := TDataColumns.Create(
+    TDataColumn.From('Account'),
+    TDataColumn.From('NewPrivateKey'),
+    TDataColumn.From('Fee')
+    );
+end;
+
+function TAccountSenderDataSource.GetItemField(constref AItem: TAccount;
+  const ABindingName: ansistring): variant;
+var
+  index: integer;
+begin
+  if ABindingName = 'Account' then
+    Result := TAccountComp.AccountNumberToAccountTxtNumber(AItem.account)
+  else if ABindingName = 'NewPrivateKey' then
+  begin
+    Result := IIF(Model.NewWalletKey.Name = '',
+      TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(
+      Model.NewWalletKey.AccountKey)), Model.NewWalletKey.Name);
+    if not Assigned(Model.NewWalletKey.PrivateKey) then
+    begin
+      Result := Result + '(*)';
+    end;
+  end
+  else if ABindingName = 'Fee' then
+    Result := TAccountComp.FormatMoney(Model.Fee.DefaultFee)
+  else
+    raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
+end;
+
+
+procedure TAccountSenderDataSource.FetchAll(const AContainer: TList<TAccount>);
+var
+  i: integer;
+begin
+  for i := Low(Model.SelectedAccounts) to High(Model.SelectedAccounts) do
+  begin
+    AContainer.Add(Model.SelectedAccounts[i]);
+  end;
+end;
+
+
+end.

+ 0 - 0
src/gui/wizards/UWIZChangeAccountPrivateKey_Start.lfm → src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Start.lfm


+ 1 - 1
src/gui/wizards/UWIZChangeAccountPrivateKey_Start.pas → src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Start.pas

@@ -97,7 +97,7 @@ begin
     Filters := SORTABLE_NUMERIC_FILTER;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
   end;
   Data := TAccountSenderDataSource.Create(FSendersGrid);
   Data := TAccountSenderDataSource.Create(FSendersGrid);
-  Data.Model := Model.ChangeAccountPrivateKeyModel;
+  Data.Model := Model.ChangeAccountPrivateKey;
   FSendersGrid.DataSource := Data;
   FSendersGrid.DataSource := Data;
   paGrid.AddControlDockCenter(FSendersGrid);
   paGrid.AddControlDockCenter(FSendersGrid);
 end;
 end;

+ 106 - 0
src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Transaction.lfm

@@ -0,0 +1,106 @@
+object WIZChangeAccountPrivateKey_Transaction: TWIZChangeAccountPrivateKey_Transaction
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  ActiveControl = cbSignerAccount
+  Caption = 'WIZChangeAccountPrivateKey_Transaction'
+  ClientHeight = 253
+  ClientWidth = 429
+  LCLVersion = '1.8.2.0'
+  Visible = False
+  object gbTransaction: TGroupBox
+    Left = 24
+    Height = 192
+    Top = 40
+    Width = 384
+    Caption = 'Transaction Details'
+    ClientHeight = 172
+    ClientWidth = 380
+    TabOrder = 0
+    object cbSignerAccount: TComboBox
+      Left = 8
+      Height = 23
+      Top = 8
+      Width = 168
+      ItemHeight = 15
+      Items.Strings = (
+        ''
+      )
+      OnChange = cbSignerAccountChange
+      TabOrder = 0
+      Text = 'Select Signer Account'
+    end
+    object lblBalance: TLabel
+      Left = 200
+      Height = 15
+      Top = 12
+      Width = 151
+      Caption = 'Please Select Signer Account'
+      Font.Color = clRed
+      ParentColor = False
+      ParentFont = False
+    end
+    object lblprivatekey: TLabel
+      Left = 8
+      Height = 15
+      Top = 48
+      Width = 85
+      Caption = 'New Private Key'
+      ParentColor = False
+    end
+    object edtOpFee: TEdit
+      Left = 8
+      Height = 23
+      Top = 144
+      Width = 360
+      TabOrder = 1
+    end
+    object lblOpFee: TLabel
+      Left = 8
+      Height = 15
+      Top = 112
+      Width = 74
+      Caption = 'Operation Fee'
+      ParentColor = False
+    end
+    object cbNewPrivateKey: TComboBox
+      Left = 8
+      Height = 23
+      Top = 74
+      Width = 168
+      ItemHeight = 15
+      OnChange = cbNewPrivateKeyChange
+      TabOrder = 2
+      Text = 'Select Private Key'
+    end
+    object lblKeyName: TLabel
+      Left = 200
+      Height = 15
+      Top = 78
+      Width = 128
+      Caption = 'Please Select Private Key'
+      Font.Color = clRed
+      ParentColor = False
+      ParentFont = False
+    end
+  end
+  object lblTotalBalances: TLabel
+    Left = 24
+    Height = 15
+    Top = 16
+    Width = 176
+    Caption = 'Selected Accounts Total Balance: '
+    ParentColor = False
+  end
+  object lblTotalBalanceValue: TLabel
+    Left = 208
+    Height = 15
+    Top = 16
+    Width = 70
+    Caption = 'Total Balance'
+    Font.Color = clGreen
+    ParentColor = False
+    ParentFont = False
+  end
+end

+ 210 - 0
src/gui/wizards/operations/UWIZChangeAccountPrivateKey_Transaction.pas

@@ -0,0 +1,210 @@
+unit UWIZChangeAccountPrivateKey_Transaction;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
+  UFRMAccountSelect, UNode, UWizard, UWIZChangeAccountPrivateKey,
+  UWIZChangeAccountPrivateKey_TransactionPayload,
+  UWIZChangeAccountPrivateKey_Confirmation, UWIZModels;
+
+type
+
+  { TWIZChangeAccountPrivateKey_Transaction }
+
+  TWIZChangeAccountPrivateKey_Transaction = class(TWizardForm<TWIZOperationsModel>)
+    cbSignerAccount: TComboBox;
+    cbNewPrivateKey: TComboBox;
+    edtOpFee: TEdit;
+    gbTransaction: TGroupBox;
+    lblKeyName: TLabel;
+    lblOpFee: TLabel;
+    lblprivatekey: TLabel;
+    lblTotalBalanceValue: TLabel;
+    lblTotalBalances: TLabel;
+    lblBalance: TLabel;
+    procedure cbNewPrivateKeyChange(Sender: TObject);
+    procedure cbSignerAccountChange(Sender: TObject);
+  private
+    procedure UpdateWalletKeys();
+  public
+    procedure OnPresent; override;
+    procedure OnNext; override;
+    function Validate(out message: ansistring): boolean; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses
+  UAccounts, UCrypto, UUserInterface, USettings;
+
+{ TWIZChangeAccountPrivateKey_Transaction }
+
+procedure TWIZChangeAccountPrivateKey_Transaction.cbSignerAccountChange(Sender: TObject);
+begin
+  if cbSignerAccount.ItemIndex < 1 then
+  begin
+    lblBalance.Font.Color := clRed;
+    lblBalance.Caption := 'Please Select Signer Account';
+  end
+  else
+  begin
+    lblBalance.Font.Color := clGreen;
+    lblBalance.Caption := Format('%s PASC',
+      [TAccountComp.FormatMoney(Model.ChangeAccountPrivateKey.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
+  end;
+end;
+
+procedure TWIZChangeAccountPrivateKey_Transaction.cbNewPrivateKeyChange(
+  Sender: TObject);
+var
+  i: integer;
+  wk: TWalletKey;
+begin
+  if cbNewPrivateKey.ItemIndex < 1 then
+  begin
+    lblKeyName.Font.Color := clRed;
+    lblKeyName.Caption := 'Please Select Private Key';
+  end
+  else
+  begin
+    lblKeyName.Font.Color := clGreen;
+    i := PtrInt(cbNewPrivateKey.Items.Objects[cbNewPrivateKey.ItemIndex]);
+    wk := TWallet.Keys.Key[i];
+    lblKeyName.Caption := Format('%s ',
+      [IIF(wk.Name = '', TCrypto.ToHexaString(
+      TAccountComp.AccountKey2RawString(wk.AccountKey)), wk.Name)]);
+  end;
+end;
+
+procedure TWIZChangeAccountPrivateKey_Transaction.UpdateWalletKeys();
+var
+  i: integer;
+  wk: TWalletKey;
+  s: string;
+begin
+  cbNewPrivateKey.items.BeginUpdate;
+  try
+    cbNewPrivateKey.Items.Clear;
+    cbNewPrivateKey.Items.Add('Select Private Key');
+    if not Assigned(TWallet.Keys) then
+    begin
+      Exit;
+    end;
+    for i := 0 to TWallet.Keys.Count - 1 do
+    begin
+      wk := TWallet.Keys.Key[i];
+      s := IIF(wk.Name = '', TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(wk.AccountKey)), wk.Name);
+      if not Assigned(wk.PrivateKey) then
+      begin
+        s := s + '(*)';
+      end;
+      cbNewPrivateKey.Items.AddObject(s, TObject(i));
+    end;
+    cbNewPrivateKey.Sorted := True;
+  finally
+    cbNewPrivateKey.Items.EndUpdate;
+  end;
+end;
+
+procedure TWIZChangeAccountPrivateKey_Transaction.OnPresent;
+
+  function GetAccNoWithChecksum(AAccountNumber: cardinal): string;
+  begin
+    Result := TAccountComp.AccountNumberToAccountTxtNumber(AAccountNumber);
+  end;
+
+var
+  acc: TAccount;
+  accNumberwithChecksum: string;
+  totalBalance: int64;
+  i: integer;
+begin
+  cbSignerAccount.Items.BeginUpdate;
+  totalBalance := 0;
+  try
+    cbSignerAccount.Items.Clear;
+    cbSignerAccount.Items.Add('Select Signer Account');
+    for i := Low(Model.ChangeAccountPrivateKey.SelectedAccounts) to High(Model.ChangeAccountPrivateKey.SelectedAccounts) do
+    begin
+      acc := Model.ChangeAccountPrivateKey.SelectedAccounts[i];
+      accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
+      totalBalance := totalBalance + acc.balance;
+      cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
+    end;
+  finally
+    cbSignerAccount.Items.EndUpdate;
+  end;
+  UpdateWalletKeys();
+  cbSignerAccount.ItemIndex := Model.ChangeAccountPrivateKey.SelectedIndex;
+  cbSignerAccountChange(Self);
+  cbNewPrivateKey.ItemIndex := Model.ChangeAccountPrivateKey.PrivateKeySelectedIndex;
+  cbNewPrivateKeyChange(Self);
+  lblTotalBalanceValue.Caption :=
+    Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
+
+  edtOpFee.Text := TAccountComp.FormatMoney(TSettings.Fee.DefaultFee);
+end;
+
+procedure TWIZChangeAccountPrivateKey_Transaction.OnNext;
+begin
+  Model.ChangeAccountPrivateKey.SelectedIndex := cbSignerAccount.ItemIndex;
+  Model.ChangeAccountPrivateKey.PrivateKeySelectedIndex := cbNewPrivateKey.ItemIndex;
+  Model.Signer.SignerAccount := Model.ChangeAccountPrivateKey.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
+  Model.ChangeAccountPrivateKey.NewWalletKey := TWallet.Keys.Key[PtrInt(cbNewPrivateKey.Items.Objects[cbNewPrivateKey.ItemIndex])];
+
+  UpdatePath(ptReplaceAllNext, [TWIZChangeAccountPrivateKey_TransactionPayload, TWIZChangeAccountPrivateKey_Confirmation]);
+end;
+
+function TWIZChangeAccountPrivateKey_Transaction.Validate(out message: ansistring): boolean;
+var
+  i: integer;
+begin
+  if cbSignerAccount.ItemIndex < 1 then
+  begin
+    message := 'A signer account must be selected';
+    Result := False;
+    Exit;
+  end;
+
+  if cbNewPrivateKey.ItemIndex < 1 then
+  begin
+    message := 'A private key must be selected';
+    Result := False;
+    Exit;
+  end;
+
+  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.ChangeAccountPrivateKey.Fee.DefaultFee) then
+  begin
+    message := 'Invalid fee value "' + edtOpFee.Text + '"';
+    Result := False;
+    Exit;
+  end;
+
+  //Result := TAccountComp.AccountKeyFromImport(edtPublicKey.Text,
+  //  Model.AccountKey, message);
+  //for i := Low(Model.SelectedAccounts) to High(Model.SelectedAccounts) do
+  //begin
+  //  if TAccountComp.EqualAccountKeys(Model.SelectedAccounts[i].accountInfo.accountKey,
+  //    Model.AccountKey) then
+  //  begin
+  //    Result := False;
+  //    message := 'new public key is same as selected account public key';
+  //  end;
+  //end;
+end;
+
+end.

+ 97 - 0
src/gui/wizards/operations/UWIZChangeAccountPrivateKey_TransactionPayload.lfm

@@ -0,0 +1,97 @@
+object WIZChangeAccountPrivateKey_TransactionPayload: TWIZChangeAccountPrivateKey_TransactionPayload
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  ActiveControl = mmoPayload
+  Caption = 'Form1'
+  ClientHeight = 253
+  ClientWidth = 429
+  Visible = False
+  object grpPayload: TGroupBox
+    Left = 8
+    Height = 244
+    Top = 2
+    Width = 416
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    Caption = 'Transaction Payload'
+    ClientHeight = 224
+    ClientWidth = 412
+    TabOrder = 0
+    object paPayload: TPanel
+      Left = 8
+      Height = 214
+      Top = 2
+      Width = 396
+      Anchors = [akTop, akLeft, akRight, akBottom]
+      BevelOuter = bvNone
+      ClientHeight = 214
+      ClientWidth = 396
+      TabOrder = 0
+      object mmoPayload: TMemo
+        Left = 0
+        Height = 70
+        Top = 136
+        Width = 386
+        TabOrder = 0
+      end
+      object Label1: TLabel
+        Left = 0
+        Height = 15
+        Top = 118
+        Width = 69
+        Caption = 'Payload Data'
+        ParentColor = False
+      end
+      object rbEncryptedWithOldEC: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 0
+        Width = 176
+        Caption = 'Encrypted with old public key'
+        TabOrder = 1
+      end
+      object rbEncryptedWithEC: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 24
+        Width = 181
+        Caption = 'Encrypted with new public key'
+        Checked = True
+        TabOrder = 2
+        TabStop = True
+      end
+      object rbEncryptedWithPassword: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 48
+        Width = 152
+        Caption = 'Encrypted with password'
+        TabOrder = 3
+      end
+      object lblPassword: TLabel
+        Left = 3
+        Height = 15
+        Top = 73
+        Width = 53
+        Caption = 'Password:'
+        ParentColor = False
+      end
+      object rbNotEncrypted: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 94
+        Width = 181
+        Caption = 'Don''t encrypt (public payload)'
+        TabOrder = 4
+      end
+      object edtPassword: TEdit
+        Left = 64
+        Height = 23
+        Top = 70
+        Width = 160
+        TabOrder = 5
+      end
+    end
+  end
+end

+ 84 - 0
src/gui/wizards/operations/UWIZChangeAccountPrivateKey_TransactionPayload.pas

@@ -0,0 +1,84 @@
+unit UWIZChangeAccountPrivateKey_TransactionPayload;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  ExtCtrls, Buttons, UCommon, UCommon.Collections,
+  UWizard, UWIZChangeAccountPrivateKey, UWIZModels;
+
+type
+
+  { TWIZChangeAccountPrivateKey_TransactionPayload }
+
+  TWIZChangeAccountPrivateKey_TransactionPayload = class(TWizardForm<TWIZOperationsModel>)
+    edtPassword: TEdit;
+    grpPayload: TGroupBox;
+    Label1: TLabel;
+    lblPassword: TLabel;
+    mmoPayload: TMemo;
+    paPayload: TPanel;
+    rbEncryptedWithOldEC: TRadioButton;
+    rbEncryptedWithEC: TRadioButton;
+    rbEncryptedWithPassword: TRadioButton;
+    rbNotEncrypted: TRadioButton;
+  public
+    procedure OnNext; override;
+    function Validate(out message: ansistring): boolean; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses
+  UAccounts, UUserInterface;
+
+{ TWIZChangeAccountPrivateKey_TransactionPayload }
+
+procedure TWIZChangeAccountPrivateKey_TransactionPayload.OnNext;
+begin
+  Model.Payload.Content := mmoPayload.Lines.Text;
+  if rbEncryptedWithOldEC.Checked then
+  begin
+    Model.Payload.Mode := akaEncryptWithSender;
+  end
+  else
+  if rbEncryptedWithEC.Checked then
+  begin
+    Model.Payload.Mode := akaEncryptWithReceiver;
+  end
+  else
+  if rbEncryptedWithPassword.Checked then
+  begin
+    Model.Payload.Mode := akaEncryptWithPassword;
+  end
+  else
+  if rbNotEncrypted.Checked then
+  begin
+    Model.Payload.Mode := akaNotEncrypt;
+  end;
+end;
+
+function TWIZChangeAccountPrivateKey_TransactionPayload.Validate(out message: ansistring): boolean;
+begin
+  if (not rbNotEncrypted.Checked) and (not rbEncryptedWithEC.Checked) and
+    (not rbEncryptedWithOldEC.Checked) and (not rbEncryptedWithPassword.Checked) then
+  begin
+    message := 'you must select an encryption option for payload';
+    Result := False;
+    Exit;
+  end;
+end;
+
+end.

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

@@ -313,8 +313,8 @@ begin
       wk := TWallet.Keys.Key[i];
       wk := TWallet.Keys.Key[i];
       dooperation := True;
       dooperation := True;
       // Default fee
       // Default fee
-      if account.balance > uint64(Model.DefaultFee) then
-        _fee := Model.DefaultFee
+      if account.balance > uint64(Model.Fee.DefaultFee) then
+        _fee := Model.Fee.DefaultFee
       else
       else
         _fee := account.balance;
         _fee := account.balance;
 
 
@@ -324,8 +324,8 @@ begin
         raise Exception.Create(errors);
         raise Exception.Create(errors);
       end;
       end;
       // Special fee account:
       // Special fee account:
-      if signerAccount.balance > Model.DefaultFee then
-        _fee := Model.DefaultFee
+      if signerAccount.balance > Model.Fee.DefaultFee then
+        _fee := Model.Fee.DefaultFee
       else
       else
         _fee := signerAccount.balance;
         _fee := signerAccount.balance;
       if Model.AccountSaleMode = akaPublicSale then
       if Model.AccountSaleMode = akaPublicSale then

+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_Confirmation.lfm → src/gui/wizards/operations/UWIZEnlistAccountForSale_Confirmation.lfm


+ 1 - 1
src/gui/wizards/UWIZEnlistAccountForSale_Confirmation.pas → src/gui/wizards/operations/UWIZEnlistAccountForSale_Confirmation.pas

@@ -122,7 +122,7 @@ begin
    //else if ABindingName = 'NewPublicKey' then
    //else if ABindingName = 'NewPublicKey' then
    //  Result := Model.NewPublicKey
    //  Result := Model.NewPublicKey
      else if ABindingName = 'Fee' then
      else if ABindingName = 'Fee' then
-     Result := TAccountComp.FormatMoney(Model.DefaultFee)
+     Result := TAccountComp.FormatMoney(Model.Fee.DefaultFee)
    else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
    else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
 end;
 end;
 
 

+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_List.lfm → src/gui/wizards/operations/UWIZEnlistAccountForSale_List.lfm


+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_List.pas → src/gui/wizards/operations/UWIZEnlistAccountForSale_List.pas


+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_PrivateSaleConfig.lfm → src/gui/wizards/operations/UWIZEnlistAccountForSale_PrivateSaleConfig.lfm


+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_PrivateSaleConfig.pas → src/gui/wizards/operations/UWIZEnlistAccountForSale_PrivateSaleConfig.pas


+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_Start.lfm → src/gui/wizards/operations/UWIZEnlistAccountForSale_Start.lfm


+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_Start.pas → src/gui/wizards/operations/UWIZEnlistAccountForSale_Start.pas


+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_Transaction.lfm → src/gui/wizards/operations/UWIZEnlistAccountForSale_Transaction.lfm


+ 2 - 2
src/gui/wizards/UWIZEnlistAccountForSale_Transaction.pas → src/gui/wizards/operations/UWIZEnlistAccountForSale_Transaction.pas

@@ -126,7 +126,7 @@ begin
   cbSignerAccountChange(Self);
   cbSignerAccountChange(Self);
   lblTotalBalanceValue.Caption :=
   lblTotalBalanceValue.Caption :=
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
     Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
-  edtOpFee.Text := TAccountComp.FormatMoney(TSettings.DefaultFee);
+  edtOpFee.Text := TAccountComp.FormatMoney(TSettings.Fee.DefaultFee);
   edtSalePrice.Text := TAccountComp.FormatMoney(0);
   edtSalePrice.Text := TAccountComp.FormatMoney(0);
 end;
 end;
 
 
@@ -187,7 +187,7 @@ begin
 
 
   Model.SellerAccount := TNode.Node.Operations.SafeBoxTransaction.account(c);
   Model.SellerAccount := TNode.Node.Operations.SafeBoxTransaction.account(c);
 
 
-  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.DefaultFee) then
+  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.Fee.DefaultFee) then
   begin
   begin
     message := 'Invalid fee value "' + edtOpFee.Text + '"';
     message := 'Invalid fee value "' + edtOpFee.Text + '"';
     Result := False;
     Result := False;

+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_TransactionPayload.lfm → src/gui/wizards/operations/UWIZEnlistAccountForSale_TransactionPayload.lfm


+ 0 - 0
src/gui/wizards/UWIZEnlistAccountForSale_TransactionPayload.pas → src/gui/wizards/operations/UWIZEnlistAccountForSale_TransactionPayload.pas


+ 0 - 0
src/gui/wizards/generic wizards/UWIZFeeOverride.lfm → src/gui/wizards/operations/UWIZFeeOverride.lfm


+ 3 - 3
src/gui/wizards/generic wizards/UWIZFeeOverride.pas → src/gui/wizards/operations/UWIZFeeOverride.pas

@@ -58,7 +58,7 @@ var
 begin
 begin
   TAccountComp.TxtToMoney(Trim(fseFee.ValueToStr(fseFee.Value)), opfee);
   TAccountComp.TxtToMoney(Trim(fseFee.ValueToStr(fseFee.Value)), opfee);
   lblTotalFeeValue.Caption := Format('%s PASC', [TAccountComp.FormatMoney(opfee *
   lblTotalFeeValue.Caption := Format('%s PASC', [TAccountComp.FormatMoney(opfee *
-    Length(Model.SendPASCModel.SelectedAccounts))]);
+    Length(Model.SendPASC.SelectedAccounts))]);
 end;
 end;
 
 
 procedure TWIZFeeOverride.fseFeeChange(Sender: TObject);
 procedure TWIZFeeOverride.fseFeeChange(Sender: TObject);
@@ -74,8 +74,8 @@ end;
 procedure TWIZFeeOverride.OnNext;
 procedure TWIZFeeOverride.OnNext;
 begin
 begin
   TAccountComp.TxtToMoney(Trim(fseFee.ValueToStr(fseFee.Value)),
   TAccountComp.TxtToMoney(Trim(fseFee.ValueToStr(fseFee.Value)),
-    Model.SendPASCModel.SingleOperationFee);
-  if Model.SendPASCModel.HasPayload then
+    Model.Fee.SingleOperationFee);
+  if Model.Payload.HasPayload then
   begin
   begin
     UpdatePath(ptReplaceAllNext, [TWIZPayloadOverride,
     UpdatePath(ptReplaceAllNext, [TWIZPayloadOverride,
       TWIZSendPASC_Confirmation]);
       TWIZSendPASC_Confirmation]);

+ 1 - 0
src/gui/wizards/generic wizards/UWIZPayloadContentOverride.lfm → src/gui/wizards/operations/UWIZPayloadContentOverride.lfm

@@ -7,6 +7,7 @@ object WIZPayloadContentOverride: TWIZPayloadContentOverride
   Caption = 'Form1'
   Caption = 'Form1'
   ClientHeight = 253
   ClientHeight = 253
   ClientWidth = 429
   ClientWidth = 429
+  LCLVersion = '1.8.2.0'
   Visible = False
   Visible = False
   object grpPayload: TGroupBox
   object grpPayload: TGroupBox
     Left = 8
     Left = 8

+ 1 - 1
src/gui/wizards/generic wizards/UWIZPayloadContentOverride.pas → src/gui/wizards/operations/UWIZPayloadContentOverride.pas

@@ -45,7 +45,7 @@ uses
 
 
 procedure TWIZPayloadContentOverride.OnNext;
 procedure TWIZPayloadContentOverride.OnNext;
 begin
 begin
-  Model.SendPASCModel.PayloadContent := mmoPayload.Lines.Text;
+  Model.Payload.Content := mmoPayload.Lines.Text;
    UpdatePath(ptReplaceAllNext, [TWIZSelectSignerOverride,
    UpdatePath(ptReplaceAllNext, [TWIZSelectSignerOverride,
       TWIZSendPASC_Confirmation]);
       TWIZSendPASC_Confirmation]);
 end;
 end;

+ 0 - 0
src/gui/wizards/generic wizards/UWIZPayloadOverride.lfm → src/gui/wizards/operations/UWIZPayloadOverride.lfm


+ 5 - 5
src/gui/wizards/generic wizards/UWIZPayloadOverride.pas → src/gui/wizards/operations/UWIZPayloadOverride.pas

@@ -55,24 +55,24 @@ procedure TWIZPayloadOverride.OnNext;
 begin
 begin
   if rbEncryptedWithRecipient.Checked then
   if rbEncryptedWithRecipient.Checked then
   begin
   begin
-    Model.SendPASCModel.PayloadEncryptionMode := akaEncryptWithSender;
+    Model.Payload.Mode := akaEncryptWithSender;
   end
   end
   else
   else
   if rbEncryptedWithSender.Checked then
   if rbEncryptedWithSender.Checked then
   begin
   begin
-    Model.SendPASCModel.PayloadEncryptionMode := akaEncryptWithReceiver;
+    Model.Payload.Mode := akaEncryptWithReceiver;
   end
   end
   else
   else
   if rbEncryptedWithPassword.Checked then
   if rbEncryptedWithPassword.Checked then
   begin
   begin
-    Model.SendPASCModel.PayloadEncryptionMode := akaEncryptWithPassword;
+    Model.Payload.Mode := akaEncryptWithPassword;
   end
   end
   else
   else
   if rbNotEncrypted.Checked then
   if rbNotEncrypted.Checked then
   begin
   begin
-    Model.SendPASCModel.PayloadEncryptionMode := akaNotEncrypt;
+    Model.Payload.Mode := akaNotEncrypt;
   end;
   end;
-  case Model.SendPASCModel.PayloadEncryptionMode of
+  case Model.Payload.Mode of
     akaEncryptWithPassword:
     akaEncryptWithPassword:
     begin
     begin
       UpdatePath(ptReplaceAllNext, [TWIZPayloadPasswordOverride,
       UpdatePath(ptReplaceAllNext, [TWIZPayloadPasswordOverride,

+ 0 - 0
src/gui/wizards/generic wizards/UWIZPayloadPasswordOverride.lfm → src/gui/wizards/operations/UWIZPayloadPasswordOverride.lfm


+ 1 - 1
src/gui/wizards/generic wizards/UWIZPayloadPasswordOverride.pas → src/gui/wizards/operations/UWIZPayloadPasswordOverride.pas

@@ -47,7 +47,7 @@ uses
 
 
 procedure TWIZPayloadPasswordOverride.OnNext;
 procedure TWIZPayloadPasswordOverride.OnNext;
 begin
 begin
-  Model.SendPASCModel.EncryptionPassword := edtPassword.Text;
+  Model.Payload.Password := edtPassword.Text;
   UpdatePath(ptReplaceAllNext, [TWIZSelectSignerOverride,
   UpdatePath(ptReplaceAllNext, [TWIZSelectSignerOverride,
     TWIZSendPASC_Confirmation]);
     TWIZSendPASC_Confirmation]);
 end;
 end;

+ 1 - 1
src/gui/wizards/generic wizards/UWIZSelectSignerOverride.lfm → src/gui/wizards/operations/UWIZSelectSignerOverride.lfm

@@ -7,7 +7,7 @@ object WIZSelectSignerOverride: TWIZSelectSignerOverride
   Caption = 'WIZSelectSignerOverride'
   Caption = 'WIZSelectSignerOverride'
   ClientHeight = 253
   ClientHeight = 253
   ClientWidth = 429
   ClientWidth = 429
-  LCLVersion = '1.8.1.0'
+  LCLVersion = '1.8.2.0'
   Visible = False
   Visible = False
   object gbTransaction: TGroupBox
   object gbTransaction: TGroupBox
     Left = 16
     Left = 16

+ 8 - 8
src/gui/wizards/generic wizards/UWIZSelectSignerOverride.pas → src/gui/wizards/operations/UWIZSelectSignerOverride.pas

@@ -62,7 +62,7 @@ begin
   begin
   begin
     lblBalance.Font.Color := clGreen;
     lblBalance.Font.Color := clGreen;
     lblBalance.Caption := Format('%s PASC',
     lblBalance.Caption := Format('%s PASC',
-      [TAccountComp.FormatMoney(Model.SendPASCModel.SelectedAccounts[PtrInt(
+      [TAccountComp.FormatMoney(Model.SendPASC.SelectedAccounts[PtrInt(
       cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
       cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
   end;
   end;
 end;
 end;
@@ -83,31 +83,31 @@ begin
   try
   try
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Clear;
     cbSignerAccount.Items.Add('Select Signer Account');
     cbSignerAccount.Items.Add('Select Signer Account');
-    for i := Low(Model.SendPASCModel.SelectedAccounts) to High(Model.SendPASCModel.SelectedAccounts) do
+    for i := Low(Model.SendPASC.SelectedAccounts) to High(Model.SendPASC.SelectedAccounts) do
     begin
     begin
-      acc := Model.SendPASCModel.SelectedAccounts[i];
+      acc := Model.SendPASC.SelectedAccounts[i];
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
       cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
     end;
     end;
   finally
   finally
     cbSignerAccount.Items.EndUpdate;
     cbSignerAccount.Items.EndUpdate;
   end;
   end;
-  cbSignerAccount.ItemIndex := Model.SendPASCModel.SelectedIndex;
+  cbSignerAccount.ItemIndex := Model.SendPASC.SelectedIndex;
   cbSignerAccountChange(Self);
   cbSignerAccountChange(Self);
 end;
 end;
 
 
 procedure TWIZSelectSignerOverride.OnNext;
 procedure TWIZSelectSignerOverride.OnNext;
 begin
 begin
-  Model.SendPASCModel.SelectedIndex := cbSignerAccount.ItemIndex;
-  Model.SendPASCModel.SignerAccount := Model.SendPASCModel.SelectedAccounts[PtrInt(
+  Model.SendPASC.SelectedIndex := cbSignerAccount.ItemIndex;
+  Model.Signer.SignerAccount := Model.SendPASC.SelectedAccounts[PtrInt(
     cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
     cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
   if rbPrimary.Checked then
   if rbPrimary.Checked then
   begin
   begin
-    Model.SendPASCModel.OperationSigningMode := akaPrimary;
+    Model.Signer.OperationSigningMode := akaPrimary;
   end
   end
   else if rbSecondary.Checked then
   else if rbSecondary.Checked then
   begin
   begin
-    Model.SendPASCModel.OperationSigningMode := akaSecondary;
+    Model.Signer.OperationSigningMode := akaSecondary;
   end;
   end;
 end;
 end;
 
 

+ 431 - 0
src/gui/wizards/operations/UWIZSendPASC.pas

@@ -0,0 +1,431 @@
+unit UWIZSendPASC;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+
+  Acknowledgements:
+    Herman Schoenfeld <[email protected]>: added grid-based layout
+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UWizard, UAccounts, LCLType, UWIZModels;
+
+type
+
+  { TWIZSendPASCWizard }
+
+  TWIZSendPASCWizard = class(TWizard<TWIZOperationsModel>)
+  private
+    function UpdatePayload(const SenderAccount: TAccount;
+      var errors: string): boolean;
+    function UpdateOperationOptions(var errors: string): boolean;
+    function UpdateOpTransaction(const SenderAccount: TAccount;
+      var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
+    procedure SendPASC();
+  public
+    constructor Create(AOwner: TComponent); override;
+    function DetermineHasNext: boolean; override;
+    function DetermineHasPrevious: boolean; override;
+    function FinishRequested(out message: ansistring): boolean; override;
+    function CancelRequested(out message: ansistring): boolean; override;
+  end;
+
+implementation
+
+uses
+  UBlockChain,
+  UOpTransaction,
+  UNode,
+  UConst,
+  UWallet,
+  UECIES,
+  UAES,
+  UWIZSendPASC_ConfirmSender,
+  UWIZSendPASC_Confirmation;
+
+{ TWIZSendPASCWizard }
+
+function TWIZSendPASCWizard.UpdateOperationOptions(var errors: string): boolean;
+var
+  iAcc, iWallet: integer;
+  sender_account, dest_account: TAccount;
+  wk: TWalletKey;
+  e: string;
+  amount: int64;
+begin
+  Result := False;
+  errors := '';
+  if not Assigned(TWallet.Keys) then
+  begin
+    errors := 'No wallet keys';
+    Exit;
+  end;
+
+  if Length(Model.SendPASC.SelectedAccounts) = 0 then
+  begin
+    errors := 'No sender account';
+    Exit;
+  end
+  else
+  begin
+
+    for iAcc := Low(Model.SendPASC.SelectedAccounts) to High(Model.SendPASC.SelectedAccounts) do
+    begin
+      sender_account := Model.SendPASC.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
+        begin
+          // TODO: handle unlocking of encrypted wallet here
+          errors := 'Wallet is password protected. Need password';
+        end
+        else
+        begin
+          errors := 'Only public key of account ' +
+            TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
+            ' found in wallet. You cannot operate with this account';
+        end;
+        Exit;
+      end;
+    end;
+  end;
+
+  Result := UpdateOpTransaction(Model.SendPASC.SelectedAccounts[0], dest_account, amount, errors);
+  UpdatePayload(sender_account, e);
+end;
+
+function TWIZSendPASCWizard.UpdateOpTransaction(const SenderAccount: TAccount;
+  var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
+var
+  c: cardinal;
+begin
+  Result := False;
+  errors := '';
+
+  DestAccount := Model.SendPASC.DestinationAccount;
+
+  if Length(Model.SendPASC.SelectedAccounts) = 1 then
+  begin
+    amount := Model.SendPASC.SingleAmountToSend;
+  end
+  else
+  begin
+    amount := 0; // ALL BALANCE
+  end;
+
+  if DestAccount.account = SenderAccount.account then
+  begin
+    errors := 'Sender and dest account are the same';
+    Exit;
+  end;
+
+  if (Length(Model.SendPASC.SelectedAccounts) = 1) then
+  begin
+    if (SenderAccount.balance < (amount + Model.Fee.SingleOperationFee)) then
+    begin
+      errors := 'Insufficient funds';
+      Exit;
+    end;
+  end;
+  Result := True;
+end;
+
+procedure TWIZSendPASCWizard.SendPASC();
+var
+  _V2, dooperation: boolean;
+  iAcc, i: integer;
+  _totalamount, _totalfee, _totalSignerFee, _amount, _fee: int64;
+  _signer_n_ops: cardinal;
+  operationstxt, operation_to_string, errors, auxs: string;
+  wk: TWalletKey;
+  ops: TOperationsHashTree;
+  op: TPCOperation;
+  account, destAccount: TAccount;
+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.SendPASC.SelectedAccounts) to High(Model.SendPASC.SelectedAccounts) do
+    begin
+      op := nil;
+      account := Model.SendPASC.SelectedAccounts[iAcc];
+      if not UpdatePayload(account, errors) then
+      begin
+        raise Exception.Create('Error encoding payload of sender account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(account.account) + ': ' + errors);
+      end;
+      i := TWallet.Keys.IndexOfAccountKey(account.accountInfo.accountKey);
+      if i < 0 then
+      begin
+        raise Exception.Create('Sender account private key not found in Wallet');
+      end;
+
+      wk := TWallet.Keys.Key[i];
+      dooperation := True;
+      // Default fee
+      if account.balance > uint64(Model.Fee.SingleOperationFee) then
+        _fee := Model.Fee.SingleOperationFee
+      else
+        _fee := account.balance;
+
+      if not UpdateOpTransaction(account, destAccount, _amount, errors) then
+        raise Exception.Create(errors);
+      if Length(Model.SendPASC.SelectedAccounts) > 1 then
+      begin
+        if account.balance > 0 then
+        begin
+          if account.balance > Model.Fee.SingleOperationFee then
+          begin
+            _amount := account.balance - Model.Fee.SingleOperationFee;
+            _fee := Model.Fee.SingleOperationFee;
+          end
+          else
+          begin
+            _amount := account.balance;
+            _fee := 0;
+          end;
+        end
+        else
+          dooperation := False;
+      end
+      else
+      begin
+      end;
+      if dooperation then
+      begin
+        op := TOpTransaction.CreateTransaction(
+          account.account, account.n_operation + 1, destAccount.account,
+          wk.PrivateKey, _amount, _fee, Model.Payload.EncodedBytes);
+        Inc(_totalamount, _amount);
+        Inc(_totalfee, _fee);
+      end;
+      operationstxt := 'Transaction to ' + TAccountComp.AccountNumberToAccountTxtNumber(
+        destAccount.account);
+
+      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.SendPASC.SelectedAccounts) > 1) then
+    begin
+      auxs := 'Total amount that dest will receive: ' + TAccountComp.FormatMoney(
+        _totalamount) + #10;
+      if Application.MessageBox(
+        PChar('Execute ' + IntToStr(Length(Model.SendPASC.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
+      begin
+        Exit;
+      end;
+    end
+    else
+    begin
+      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
+      begin
+        Exit;
+      end;
+    end;
+    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
+      begin
+        //  with TFRMMemoText.Create(Self) do
+        //    try
+        //      InitData(Application.Title, operationstxt);
+        //      ShowModal;
+        //    finally
+        //      Free;
+        //    end;
+        ShowMessage(operationstxt);
+      end
+      else
+      begin
+        Application.MessageBox(
+          PChar('Successfully executed ' + IntToStr(i) + ' operations!' +
+          #10 + #10 + operation_to_string),
+          PChar(Application.Title), MB_OK + MB_ICONINFORMATION);
+      end;
+      // ModalResult := mrOk;
+    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);
+      //with TFRMMemoText.Create(Self) do
+      //  try
+      //    InitData(Application.Title, operationstxt);
+      //    ShowModal;
+      //  finally
+      //    Free;
+      //  end;
+      //ModalResult := mrOk;
+      ShowMessage(operationstxt);
+    end
+    else
+    begin
+      raise Exception.Create(errors);
+    end;
+
+  finally
+    ops.Free;
+  end;
+end;
+
+function TWIZSendPASCWizard.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.Mode of
+
+      akaEncryptWithSender:
+      begin
+        // Use sender
+        errors := 'Error encrypting';
+        account := SenderAccount;
+        payload_encrypted := ECIESEncrypt(account.accountInfo.accountKey, payload_u);
+        valid := payload_encrypted <> '';
+      end;
+
+      akaEncryptWithReceiver:
+      begin
+        // With dest public key
+        errors := 'Error encrypting';
+        account := Model.SendPASC.DestinationAccount;
+        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
+      begin
+        raise Exception.Create('Invalid Encryption Selection');
+      end;
+    end;
+
+  finally
+    if valid then
+    begin
+      if length(payload_encrypted) > CT_MaxPayloadSize then
+      begin
+        valid := False;
+        errors := 'Payload size is bigger than ' + IntToStr(CT_MaxPayloadSize) +
+          ' (' + IntToStr(length(payload_encrypted)) + ')';
+      end;
+
+    end;
+    Model.Payload.EncodedBytes := payload_encrypted;
+    Result := valid;
+  end;
+
+end;
+
+constructor TWIZSendPASCWizard.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner, [TWIZSendPASC_ConfirmSender, TWIZSendPASC_Confirmation]);
+  TitleText := 'Send PASC';
+  FinishText := 'Send PASC';
+end;
+
+function TWIZSendPASCWizard.DetermineHasNext: boolean;
+begin
+  Result := not (CurrentScreen is TWIZSendPASC_Confirmation);
+end;
+
+function TWIZSendPASCWizard.DetermineHasPrevious: boolean;
+begin
+  Result := inherited DetermineHasPrevious;
+end;
+
+function TWIZSendPASCWizard.FinishRequested(out message: ansistring): boolean;
+begin
+  // Execute the PASC Sending here
+  try
+    Result := True;
+    SendPASC();
+  except
+    On E: Exception do
+    begin
+      Result := False;
+      message := E.ToString;
+    end;
+  end;
+end;
+
+function TWIZSendPASCWizard.CancelRequested(out message: ansistring): boolean;
+begin
+  Result := True;
+end;
+
+end.

+ 3 - 3
src/gui/wizards/UWIZSendPASC_Start.lfm → src/gui/wizards/operations/UWIZSendPASC_ConfirmSender.lfm

@@ -1,12 +1,12 @@
-object WIZSendPASC_Start: TWIZSendPASC_Start
+object WIZSendPASC_ConfirmSender: TWIZSendPASC_ConfirmSender
   Left = 0
   Left = 0
   Height = 261
   Height = 261
   Top = 0
   Top = 0
   Width = 429
   Width = 429
-  Caption = 'WIZSendPASC_Start'
+  Caption = 'WIZSendPASC_ConfirmSender'
   ClientHeight = 261
   ClientHeight = 261
   ClientWidth = 429
   ClientWidth = 429
-  LCLVersion = '1.8.2.0'
+  LCLVersion = '1.8.1.0'
   Visible = False
   Visible = False
   object gpSender: TGroupBox
   object gpSender: TGroupBox
     Left = 4
     Left = 4

+ 12 - 12
src/gui/wizards/UWIZSendPASC_Start.pas → src/gui/wizards/operations/UWIZSendPASC_ConfirmSender.pas

@@ -1,15 +1,15 @@
-unit UWIZSendPASC_Start;
+unit UWIZSendPASC_ConfirmSender;
 
 
 {$mode delphi}
 {$mode delphi}
 
 
-{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+{ Copyright (c) 2018 Sphere 10 Software (http://www.sphere10.com/)
 
 
   Distributed under the MIT software license, see the accompanying file LICENSE
   Distributed under the MIT software license, see the accompanying file LICENSE
   or visit http://www.opensource.org/licenses/mit-license.php.
   or visit http://www.opensource.org/licenses/mit-license.php.
 
 
   Acknowledgements:
   Acknowledgements:
-    Herman Schoenfeld <[email protected]>: added grid-based layout
-
+  Ugochukwu Mmaduekwe - main developer
+  Herman Schoenfeld - designer
 }
 }
 
 
 interface
 interface
@@ -17,13 +17,13 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, UVisualGrid, UCommon.Data, UCellRenderers,
   ExtCtrls, UVisualGrid, UCommon.Data, UCellRenderers,
-  UWizard, UWIZSendPASC, UWIZSendPASC_Transaction, UWIZSendPASC_Confirmation, UWIZModels;
+  UWizard, UWIZSendPASC, UWIZSendPASC_EnterRecipient, UWIZSendPASC_Confirmation, UWIZModels;
 
 
 type
 type
 
 
-  { TWIZSendPASC_Start }
+  { TWIZSendPASC_ConfirmSender }
 
 
-  TWIZSendPASC_Start = class(TWizardForm<TWIZOperationsModel>)
+  TWIZSendPASC_ConfirmSender = class(TWizardForm<TWIZOperationsModel>)
     gpSender: TGroupBox;
     gpSender: TGroupBox;
     paGrid: TPanel;
     paGrid: TPanel;
   private
   private
@@ -53,9 +53,9 @@ type
       procedure FetchAll(const AContainer : TList<TAccount>); override;
       procedure FetchAll(const AContainer : TList<TAccount>); override;
   end;
   end;
 
 
-{ TWIZSendPASC_Start }
+{ TWIZSendPASC_ConfirmSender }
 
 
-procedure TWIZSendPASC_Start.OnPresent;
+procedure TWIZSendPASC_ConfirmSender.OnPresent;
 var
 var
   data : TAccountSenderDataSource;
   data : TAccountSenderDataSource;
 begin
 begin
@@ -87,14 +87,14 @@ begin
     Filters:=SORTABLE_NUMERIC_FILTER;
     Filters:=SORTABLE_NUMERIC_FILTER;
   end;
   end;
   data := TAccountSenderDataSource.Create(FSendersGrid);
   data := TAccountSenderDataSource.Create(FSendersGrid);
-  data.Model := Model.SendPASCModel;
+  data.Model := Model.SendPASC;
   FSendersGrid.DataSource := data;
   FSendersGrid.DataSource := data;
   paGrid.AddControlDockCenter(FSendersGrid);
   paGrid.AddControlDockCenter(FSendersGrid);
 end;
 end;
 
 
-procedure TWIZSendPASC_Start.OnNext;
+procedure TWIZSendPASC_ConfirmSender.OnNext;
 begin
 begin
-  UpdatePath(ptReplaceAllNext, [TWIZSendPASC_Transaction, TWIZSendPASC_Confirmation]);
+  UpdatePath(ptReplaceAllNext, [TWIZSendPASC_EnterRecipient, TWIZSendPASC_Confirmation]);
 end;
 end;
 
 
 { TAccountSenderDataSource }
 { TAccountSenderDataSource }

+ 63 - 0
src/gui/wizards/operations/UWIZSendPASC_Confirmation.lfm

@@ -0,0 +1,63 @@
+object WIZSendPASC_Confirmation: TWIZSendPASC_Confirmation
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  Caption = 'WIZSendPASC_Confirmation'
+  ClientHeight = 253
+  ClientWidth = 429
+  Visible = False
+  object GroupBox1: TGroupBox
+    Left = 10
+    Height = 232
+    Top = 8
+    Width = 408
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    Caption = 'Confirm Transaction'
+    ClientHeight = 212
+    ClientWidth = 404
+    TabOrder = 0
+    object paGrid: TPanel
+      Left = 8
+      Height = 152
+      Top = 48
+      Width = 382
+      Anchors = [akTop, akLeft, akRight, akBottom]
+      BevelOuter = bvNone
+      Caption = 'GRID PANEL'
+      TabOrder = 0
+    end
+    object Label1: TLabel
+      Left = 8
+      Height = 15
+      Top = 2
+      Width = 84
+      Caption = 'Signer Account:'
+      ParentColor = False
+    end
+    object lblSgnAcc: TLabel
+      Left = 112
+      Height = 15
+      Top = 2
+      Width = 53
+      Caption = 'lblSgnAcc'
+      ParentColor = False
+    end
+    object Label2: TLabel
+      Left = 8
+      Height = 15
+      Top = 24
+      Width = 111
+      Caption = 'Destination Account:'
+      ParentColor = False
+    end
+    object lblDestAcc: TLabel
+      Left = 128
+      Height = 15
+      Top = 24
+      Width = 56
+      Caption = 'lblDestAcc'
+      ParentColor = False
+    end
+  end
+end

+ 144 - 0
src/gui/wizards/operations/UWIZSendPASC_Confirmation.pas

@@ -0,0 +1,144 @@
+unit UWIZSendPASC_Confirmation;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ 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, StdCtrls,
+  ExtCtrls, UVisualGrid, UCellRenderers, UCommon.Data, UWizard, UWIZSendPASC, UWIZModels;
+
+type
+
+  { TWIZSendPASC_Confirmation }
+
+  TWIZSendPASC_Confirmation = class(TWizardForm<TWIZOperationsModel>)
+    GroupBox1: TGroupBox;
+    Label1: TLabel;
+    Label2: TLabel;
+    lblDestAcc: TLabel;
+    lblSgnAcc: TLabel;
+    paGrid: TPanel;
+  private
+    FSendersGrid : TVisualGrid;
+  public
+    procedure OnPresent; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses UAccounts, UDataSources, UCommon, UCommon.UI, Generics.Collections;
+
+type
+
+  { TAccountSenderDataSource }
+
+  TAccountSenderDataSource = class(TAccountsDataSourceBase)
+    private
+      FModel : TWIZOperationsModel.TSendPASCModel;
+    protected
+      function GetColumns : TDataColumns; override;
+    public
+      property Model : TWIZOperationsModel.TSendPASCModel read FModel write FModel;
+      procedure FetchAll(const AContainer : TList<TAccount>); override;
+      function GetItemField(constref AItem: TAccount; const ABindingName : AnsiString) : Variant; override;
+  end;
+
+{ TWIZSendPASC_Confirmation }
+
+procedure TWIZSendPASC_Confirmation.OnPresent;
+var
+  data : TAccountSenderDataSource;
+begin
+  FSendersGrid := TVisualGrid.Create(Self);
+  FSendersGrid.CanSearch:= False;
+  FSendersGrid.SortMode := smMultiColumn;
+  FSendersGrid.FetchDataInThread := False;
+  FSendersGrid.AutoPageSize := True;
+  FSendersGrid.SelectionType := stNone;
+  FSendersGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone, vgoAutoHidePaging];
+  with FSendersGrid.AddColumn('Sender') do begin
+    Binding := 'SenderAccount';
+    Filters := SORTABLE_NUMERIC_FILTER;
+    Width := 100;
+    HeaderFontStyles := [fsBold];
+    DataFontStyles := [fsBold];
+  end;
+  with FSendersGrid.AddColumn('Balance') do begin
+    Filters := SORTABLE_NUMERIC_FILTER;
+    Width := 100;
+    Renderer := TCellRenderers.PASC;
+  end;
+  with FSendersGrid.AddColumn('Amount To Send') do begin
+    Binding := 'AmountToSend';
+    Filters := SORTABLE_TEXT_FILTER;
+    Width := 100;
+  end;
+  with FSendersGrid.AddColumn('Fee') do begin
+    Filters := SORTABLE_TEXT_FILTER;
+    Width := 100;
+  end;
+
+   data := TAccountSenderDataSource.Create(FSendersGrid);
+   data.Model := Model.SendPASC;
+   FSendersGrid.DataSource := data;
+   paGrid.AddControlDockCenter(FSendersGrid);
+   lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.Signer.SignerAccount.account);
+   lblDestAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.SendPASC.DestinationAccount.account);
+end;
+
+{ TAccountSenderDataSource }
+
+function TAccountSenderDataSource.GetColumns : TDataColumns;
+begin
+  Result := TDataColumns.Create(
+    TDataColumn.From('SenderAccount'),
+    TDataColumn.From('Balance'),
+    TDataColumn.From('AmountToSend'),
+    TDataColumn.From('Fee')
+  );
+end;
+
+function TAccountSenderDataSource.GetItemField(constref AItem: TAccount; const ABindingName : AnsiString) : Variant;
+var
+  index : Integer;
+begin
+   if ABindingName = 'SenderAccount' then
+     Result := TAccountComp.AccountNumberToAccountTxtNumber(AItem.account)
+   else if ABindingName = 'Balance' then
+     Result := TAccountComp.FormatMoney(AItem.Balance)
+   else if ABindingName = 'AmountToSend' then
+     Result := TAccountComp.FormatMoney(Model.SingleAmountToSend)
+     else if ABindingName = 'Fee' then
+     Result := TAccountComp.FormatMoney(Model.SingleOperationFee)
+   else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
+end;
+
+
+procedure TAccountSenderDataSource.FetchAll(const AContainer : TList<TAccount>);
+var
+  i: Integer;
+begin
+  for i := Low(Model.SelectedAccounts) to High(Model.SelectedAccounts) do
+  begin
+    AContainer.Add( Model.SelectedAccounts[i] );
+  end;
+end;
+
+
+end.
+

+ 62 - 0
src/gui/wizards/operations/UWIZSendPASC_EnterQuantity.lfm

@@ -0,0 +1,62 @@
+object WIZSendPASC_EnterQuantity: TWIZSendPASC_EnterQuantity
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  ActiveControl = edtAmt
+  Caption = 'WIZSendPASC_EnterQuantity'
+  ClientHeight = 253
+  ClientWidth = 429
+  Visible = False
+  object gbQuantity: TGroupBox
+    Left = 16
+    Height = 232
+    Top = 8
+    Width = 400
+    Caption = 'Transaction Quantity'
+    ClientHeight = 212
+    ClientWidth = 396
+    TabOrder = 0
+    object edtAmt: TEdit
+      Left = 8
+      Height = 23
+      Top = 40
+      Width = 160
+      TabOrder = 0
+    end
+    object lblQuantityNotice: TLabel
+      Left = 8
+      Height = 15
+      Top = 7
+      Width = 217
+      Caption = 'Please enter the quantity of PASC to send'
+      ParentColor = False
+    end
+    object chkallfunds: TCheckBox
+      Left = 184
+      Height = 19
+      Top = 42
+      Width = 166
+      Caption = 'Send all funds in account(s)'
+      OnChange = chkallfundsChange
+      TabOrder = 1
+    end
+    object chkChooseFee: TCheckBox
+      Left = 8
+      Height = 19
+      Top = 80
+      Width = 226
+      Caption = 'Let me choose fee''s for this transaction'
+      TabOrder = 2
+    end
+    object chkAttachPayload: TCheckBox
+      Left = 8
+      Height = 19
+      Top = 110
+      Width = 303
+      Caption = 'I want to attach a message payload to this transaction'
+      OnChange = chkAttachPayloadChange
+      TabOrder = 3
+    end
+  end
+end

+ 138 - 0
src/gui/wizards/operations/UWIZSendPASC_EnterQuantity.pas

@@ -0,0 +1,138 @@
+unit UWIZSendPASC_EnterQuantity;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ 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, StdCtrls,
+  ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
+  UFRMAccountSelect, UNode, UWizard, UWIZSendPASC, UWIZFeeOverride, UWIZPayloadOverride, UWIZSelectSignerOverride,
+  UWIZSendPASC_Confirmation, UWIZModels;
+
+type
+
+  { TWIZSendPASC_EnterQuantity }
+
+  TWIZSendPASC_EnterQuantity = class(TWizardForm<TWIZOperationsModel>)
+    chkChooseFee: TCheckBox;
+    chkAttachPayload: TCheckBox;
+    chkallfunds: TCheckBox;
+    edtAmt: TEdit;
+    gbQuantity: TGroupBox;
+    lblQuantityNotice: TLabel;
+    procedure chkAttachPayloadChange(Sender: TObject);
+    procedure UpdateUI();
+    procedure chkallfundsChange(Sender: TObject);
+
+
+  public
+    procedure OnPresent; override;
+    procedure OnNext; override;
+    function Validate(out message: ansistring): boolean; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses
+  UAccounts, UUserInterface, USettings;
+
+{ TWIZSendPASC_EnterQuantity }
+
+procedure TWIZSendPASC_EnterQuantity.UpdateUI();
+begin
+  if chkallfunds.Checked then
+  begin
+    edtAmt.Text := 'ALL BALANCE';
+    edtAmt.Enabled := False;
+  end
+  else
+  begin
+    edtAmt.Text := TAccountComp.FormatMoney(0);
+    edtAmt.Enabled := True;
+  end;
+
+  Model.Payload.HasPayload := IIF(chkAttachPayload.Checked, True, False);
+
+end;
+
+procedure TWIZSendPASC_EnterQuantity.chkallfundsChange(Sender: TObject);
+begin
+  UpdateUI();
+end;
+
+procedure TWIZSendPASC_EnterQuantity.OnPresent;
+begin
+  edtAmt.Text := TAccountComp.FormatMoney(0);
+end;
+
+procedure TWIZSendPASC_EnterQuantity.chkAttachPayloadChange(Sender: TObject);
+begin
+  UpdateUI();
+end;
+
+procedure TWIZSendPASC_EnterQuantity.OnNext;
+var
+  amount: Int64;
+begin
+  Model.Payload.HasPayload := chkAttachPayload.Checked;
+  if chkallfunds.Checked then
+  begin
+    Model.SendPASC.SingleAmountToSend := 0; // all balance
+  end
+  else
+  begin
+    TAccountComp.TxtToMoney(edtAmt.Text, Model.SendPASC.SingleAmountToSend);
+  end;
+
+  if chkChooseFee.Checked then
+  begin
+    UpdatePath(ptReplaceAllNext, [TWIZFeeOverride, TWIZSendPASC_Confirmation]);
+  end
+  else
+  begin
+    Model.Fee.SingleOperationFee := TSettings.Fee.DefaultFee;
+    if Model.Payload.HasPayload then
+    begin
+      UpdatePath(ptReplaceAllNext, [TWIZPayloadOverride, TWIZSendPASC_Confirmation]);
+    end
+    else
+    begin
+      UpdatePath(ptReplaceAllNext, [TWIZSelectSignerOverride, TWIZSendPASC_Confirmation]);
+    end;
+  end;
+
+end;
+
+function TWIZSendPASC_EnterQuantity.Validate(out message: ansistring): boolean;
+var
+  amount: int64;
+begin
+  Result := True;
+  if not chkallfunds.Checked then
+  begin
+    if not TAccountComp.TxtToMoney(edtAmt.Text, amount) then
+    begin
+      message := 'Invalid amount (' + edtAmt.Text + ')';
+      Result := False;
+      Exit;
+    end;
+  end;
+
+end;
+
+end.

+ 0 - 0
src/gui/wizards/UWIZSendPASC_EnterRecipient.lfm → src/gui/wizards/operations/UWIZSendPASC_EnterRecipient.lfm


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

@@ -120,7 +120,7 @@ var
   aa: TAccount;
   aa: TAccount;
 begin
 begin
   TAccountComp.AccountTxtNumberToAccountNumber(edtDestAcc.Text, c);
   TAccountComp.AccountTxtNumberToAccountNumber(edtDestAcc.Text, c);
-  Model.SendPASCModel.DestinationAccount := TNode.Node.Operations.SafeBoxTransaction.account(c);
+  Model.SendPASC.DestinationAccount := TNode.Node.Operations.SafeBoxTransaction.account(c);
   UpdatePath(ptReplaceAllNext, [TWIZSendPASC_EnterQuantity,
   UpdatePath(ptReplaceAllNext, [TWIZSendPASC_EnterQuantity,
     TWIZSendPASC_Confirmation]);
     TWIZSendPASC_Confirmation]);
 end;
 end;
@@ -154,7 +154,7 @@ begin
   end;
   end;
 
 
   AccountNumbersWithChecksum :=
   AccountNumbersWithChecksum :=
-    TListTool<TAccount, string>.Transform(Model.SendPASCModel.SelectedAccounts, GetAccNoWithCheckSum);
+    TListTool<TAccount, string>.Transform(Model.SendPASC.SelectedAccounts, GetAccNoWithCheckSum);
 
 
   if TArrayTool<string>.Contains(AccountNumbersWithChecksum, edtDestAcc.Text) then
   if TArrayTool<string>.Contains(AccountNumbersWithChecksum, edtDestAcc.Text) then
   begin
   begin

+ 0 - 0
src/gui/wizards/UWIZSendPASC_FeeOverride.lfm → src/gui/wizards/operations/UWIZSendPASC_FeeOverride.lfm


+ 451 - 0
src/gui/wizards/operations/UWIZTransferAccount.pas

@@ -0,0 +1,451 @@
+unit UWIZTransferAccount;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+
+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UCommon, UWizard, UAccounts, LCLType, UWIZModels;
+
+type
+
+  { TWIZTransferAccountWizard }
+
+  TWIZTransferAccountWizard = class(TWizard<TWIZOperationsModel>)
+  private
+    function UpdatePayload(const SenderAccount: TAccount; var errors: string): boolean;
+    function UpdateOperationOptions(var errors: string): boolean;
+    function UpdateOpChangeKey(const TargetAccount: TAccount; var SignerAccount: TAccount; var NewPublicKey: TAccountKey; var errors: ansistring): boolean;
+    procedure TransferAccountOwnership();
+  public
+    constructor Create(AOwner: TComponent); override;
+    function DetermineHasNext: boolean; override;
+    function DetermineHasPrevious: boolean; override;
+    function FinishRequested(out message: ansistring): boolean; override;
+    function CancelRequested(out message: ansistring): boolean; override;
+  end;
+
+implementation
+
+uses
+  UBlockChain,
+  UOpTransaction,
+  UNode,
+  UConst,
+  UWallet,
+  UECIES,
+  UAES,
+  UWIZTransferAccount_Start,
+  UWIZTransferAccount_Confirmation;
+
+{ TWIZTransferAccountWizard }
+
+function TWIZTransferAccountWizard.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.Mode 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';
+
+        if Model.TransferAccount.AccountKey.EC_OpenSSL_NID <>
+          CT_Account_NUL.accountInfo.accountKey.EC_OpenSSL_NID then
+        begin
+          payload_encrypted := ECIESEncrypt(Model.TransferAccount.AccountKey, payload_u);
+          valid := payload_encrypted <> '';
+        end
+        else
+        begin
+          valid := False;
+          errors := 'Selected private key is not valid to encode';
+          exit;
+        end;
+      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
+      begin
+        raise Exception.Create('Invalid Encryption Selection');
+      end;
+    end;
+
+  finally
+    if valid then
+    begin
+      if length(payload_encrypted) > CT_MaxPayloadSize then
+      begin
+        valid := False;
+        errors := 'Payload size is bigger than ' + IntToStr(CT_MaxPayloadSize) +
+          ' (' + IntToStr(length(payload_encrypted)) + ')';
+      end;
+
+    end;
+    Model.Payload.EncodedBytes := payload_encrypted;
+    Result := valid;
+  end;
+
+end;
+
+function TWIZTransferAccountWizard.UpdateOperationOptions(var errors: string): boolean;
+var
+  iAcc, iWallet: integer;
+  sender_account, signer_account: TAccount;
+  publicKey: TAccountKey;
+  wk: TWalletKey;
+  e: string;
+  amount: int64;
+begin
+  Result := False;
+  errors := '';
+  if not Assigned(TWallet.Keys) then
+  begin
+    errors := 'No wallet keys';
+    Exit;
+  end;
+
+  if Length(Model.TransferAccount.SelectedAccounts) = 0 then
+  begin
+    errors := 'No sender account';
+    Exit;
+  end
+  else
+  begin
+
+    for iAcc := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
+    begin
+      sender_account := Model.TransferAccount.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
+        begin
+          // TODO: handle unlocking of encrypted wallet here
+          errors := 'Wallet is password protected. Need password';
+        end
+        else
+        begin
+          errors := 'Only public key of account ' +
+            TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
+            ' found in wallet. You cannot operate with this account';
+        end;
+        Exit;
+      end;
+    end;
+  end;
+
+  Result := UpdateOpChangeKey(Model.TransferAccount.SelectedAccounts[0], signer_account,
+    publicKey, errors);
+  UpdatePayload(sender_account, e);
+end;
+
+function TWIZTransferAccountWizard.UpdateOpChangeKey(const TargetAccount: TAccount;
+  var SignerAccount: TAccount; var NewPublicKey: TAccountKey;
+  var errors: ansistring): boolean;
+begin
+  Result := False;
+  errors := '';
+  try
+    if not TAccountComp.AccountKeyFromImport(Model.TransferAccount.NewPublicKey,
+      NewPublicKey, errors) then
+    begin
+      Exit;
+    end;
+
+    if TNode.Node.Bank.SafeBox.CurrentProtocol >= 1 then
+    begin
+      // Signer:
+      SignerAccount := Model.Signer.SignerAccount;
+      if (TAccountComp.IsAccountLocked(SignerAccount.accountInfo,
+        TNode.Node.Bank.BlocksCount)) then
+      begin
+        errors := 'Signer account ' + TAccountComp.AccountNumberToAccountTxtNumber(
+          SignerAccount.account) + ' is locked until block ' + IntToStr(
+          SignerAccount.accountInfo.locked_until_block);
+        exit;
+      end;
+      if (not TAccountComp.EqualAccountKeys(
+        SignerAccount.accountInfo.accountKey, TargetAccount.accountInfo.accountKey)) then
+      begin
+        errors := 'Signer account ' + TAccountComp.AccountNumberToAccountTxtNumber(
+          SignerAccount.account) + ' is not owner of account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(TargetAccount.account);
+        exit;
+      end;
+    end
+    else
+    begin
+      SignerAccount := TargetAccount;
+    end;
+
+    if (TAccountComp.EqualAccountKeys(TargetAccount.accountInfo.accountKey,
+      NewPublicKey)) then
+    begin
+      errors := 'New public key is the same public key';
+      exit;
+    end;
+
+  finally
+    Result := errors = '';
+  end;
+end;
+
+procedure TWIZTransferAccountWizard.TransferAccountOwnership();
+var
+  _V2, dooperation: boolean;
+  iAcc, i: integer;
+  _totalamount, _totalfee, _totalSignerFee, _amount, _fee: int64;
+  _signer_n_ops: cardinal;
+  operationstxt, operation_to_string, errors, auxs: string;
+  wk: TWalletKey;
+  ops: TOperationsHashTree;
+  op: TPCOperation;
+  account, signerAccount: 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.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
+    begin
+      loop_start:
+        op := nil;
+      account := Model.TransferAccount.SelectedAccounts[iAcc];
+      if not UpdatePayload(account, errors) then
+      begin
+        raise Exception.Create('Error encoding payload of sender account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(account.account) + ': ' + errors);
+      end;
+      i := TWallet.Keys.IndexOfAccountKey(account.accountInfo.accountKey);
+      if i < 0 then
+      begin
+        raise Exception.Create('Sender account private key not found in Wallet');
+      end;
+
+      wk := TWallet.Keys.Key[i];
+      dooperation := True;
+      // Default fee
+      if account.balance > uint64(Model.TransferAccount.Fee.DefaultFee) then
+        _fee := Model.TransferAccount.Fee.DefaultFee
+      else
+        _fee := account.balance;
+
+      if not UpdateOpChangeKey(account, signerAccount, _newOwnerPublicKey, errors) then
+      begin
+        raise Exception.Create(errors);
+      end;
+      if _V2 then
+      begin
+        // must ensure is Signer account last if included in sender accounts (not necessarily ordered enumeration)
+        if (iAcc < Length(Model.TransferAccount.SelectedAccounts) - 1) and
+          (account.account = signerAccount.account) then
+        begin
+          TArrayTool<TAccount>.Swap(Model.TransferAccount.SelectedAccounts, iAcc,
+            Length(Model.TransferAccount.SelectedAccounts) - 1); // ensure signer account processed last
+          // TArrayTool_internal<Cardinal>.Swap(_senderAccounts, iAcc, Length(_senderAccounts) - 1);
+          goto loop_start; // TODO: remove ugly hack with refactoring!
+        end;
+
+        // Maintain correct signer fee distribution
+        if uint64(_totalSignerFee) >= signerAccount.balance then
+          _fee := 0
+        else if signerAccount.balance - uint64(_totalSignerFee) >
+          uint64(Model.TransferAccount.Fee.DefaultFee) then
+          _fee := Model.TransferAccount.Fee.DefaultFee
+        else
+          _fee := signerAccount.balance - uint64(_totalSignerFee);
+        op := TOpChangeKeySigned.Create(signerAccount.account,
+          signerAccount.n_operation + _signer_n_ops + 1, account.account,
+          wk.PrivateKey, _newOwnerPublicKey, _fee, Model.Payload.EncodedBytes);
+        Inc(_signer_n_ops);
+        Inc(_totalSignerFee, _fee);
+      end
+      else
+      begin
+        op := TOpChangeKey.Create(account.account, account.n_operation +
+          1, account.account, wk.PrivateKey, _newOwnerPublicKey, _fee, Model.Payload.EncodedBytes);
+      end;
+      Inc(_totalfee, _fee);
+      operationstxt :=
+        'Change private key to ' + TAccountComp.GetECInfoTxt(
+        _newOwnerPublicKey.EC_OpenSSL_NID);
+
+      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.TransferAccount.SelectedAccounts) > 1) then
+    begin
+      auxs := '';
+      if Application.MessageBox(
+        PChar('Execute ' + IntToStr(Length(Model.TransferAccount.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
+      begin
+        Exit;
+      end;
+    end
+    else
+    begin
+      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
+      begin
+        Exit;
+      end;
+    end;
+    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
+      begin
+
+        ShowMessage(operationstxt);
+      end
+      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
+    begin
+      raise Exception.Create(errors);
+    end;
+
+
+  finally
+    ops.Free;
+  end;
+
+end;
+
+constructor TWIZTransferAccountWizard.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner, [TWIZTransferAccount_Start,
+    TWIZTransferAccount_Confirmation]);
+  TitleText := 'Transfer Account';
+  FinishText := 'Transfer Account';
+end;
+
+function TWIZTransferAccountWizard.DetermineHasNext: boolean;
+begin
+  Result := not (CurrentScreen is TWIZTransferAccount_Confirmation);
+end;
+
+function TWIZTransferAccountWizard.DetermineHasPrevious: boolean;
+begin
+  Result := inherited DetermineHasPrevious;
+end;
+
+function TWIZTransferAccountWizard.FinishRequested(out message: ansistring): boolean;
+begin
+  // Execute the Transfer Account Action here
+  try
+    Result := True;
+    TransferAccountOwnership();
+  except
+    On E: Exception do
+    begin
+      Result := False;
+      message := E.ToString;
+    end;
+  end;
+end;
+
+function TWIZTransferAccountWizard.CancelRequested(out message: ansistring): boolean;
+begin
+  Result := True;
+end;
+
+end.

+ 48 - 0
src/gui/wizards/operations/UWIZTransferAccount_Confirmation.lfm

@@ -0,0 +1,48 @@
+object WIZTransferAccount_Confirmation: TWIZTransferAccount_Confirmation
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  Caption = 'WIZTransferAccount_Confirmation'
+  ClientHeight = 253
+  ClientWidth = 429
+  LCLVersion = '1.8.2.0'
+  Visible = False
+  object GroupBox1: TGroupBox
+    Left = 10
+    Height = 232
+    Top = 8
+    Width = 408
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    Caption = 'Confirm Transfer Transaction'
+    ClientHeight = 212
+    ClientWidth = 404
+    TabOrder = 0
+    object paGrid: TPanel
+      Left = 8
+      Height = 152
+      Top = 48
+      Width = 382
+      Anchors = [akTop, akLeft, akRight, akBottom]
+      BevelOuter = bvNone
+      Caption = 'GRID PANEL'
+      TabOrder = 0
+    end
+    object Label1: TLabel
+      Left = 8
+      Height = 15
+      Top = 16
+      Width = 84
+      Caption = 'Signer Account:'
+      ParentColor = False
+    end
+    object lblSgnAcc: TLabel
+      Left = 112
+      Height = 15
+      Top = 16
+      Width = 53
+      Caption = 'lblSgnAcc'
+      ParentColor = False
+    end
+  end
+end

+ 137 - 0
src/gui/wizards/operations/UWIZTransferAccount_Confirmation.pas

@@ -0,0 +1,137 @@
+unit UWIZTransferAccount_Confirmation;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  ExtCtrls, UVisualGrid, UCellRenderers, UCommon.Data, UWizard, UWIZTransferAccount, UWIZModels;
+
+type
+
+  { TWIZTransferAccount_Confirmation }
+
+  TWIZTransferAccount_Confirmation = class(TWizardForm<TWIZOperationsModel>)
+    GroupBox1: TGroupBox;
+    Label1: TLabel;
+    lblSgnAcc: TLabel;
+    paGrid: TPanel;
+  private
+    FSendersGrid : TVisualGrid;
+  public
+    procedure OnPresent; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses UAccounts, UDataSources, UCommon, UCommon.UI, Generics.Collections;
+
+type
+
+  { TAccountSenderDataSource }
+
+  TAccountSenderDataSource = class(TAccountsDataSourceBase)
+    private
+      FModel : TWIZOperationsModel.TTransferAccountModel;
+    protected
+      function GetColumns : TDataColumns; override;
+    public
+      property Model : TWIZOperationsModel.TTransferAccountModel read FModel write FModel;
+      procedure FetchAll(const AContainer : TList<TAccount>); override;
+      function GetItemField(constref AItem: TAccount; const ABindingName : AnsiString) : Variant; override;
+  end;
+
+{ TWIZTransferAccount_Confirmation }
+
+procedure TWIZTransferAccount_Confirmation.OnPresent;
+var
+  data : TAccountSenderDataSource;
+begin
+  FSendersGrid := TVisualGrid.Create(Self);
+  FSendersGrid.CanSearch:= False;
+  FSendersGrid.SortMode := smMultiColumn;
+  FSendersGrid.FetchDataInThread := False;
+  FSendersGrid.AutoPageSize := True;
+  FSendersGrid.SelectionType := stNone;
+  FSendersGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone, vgoAutoHidePaging];
+  with FSendersGrid.AddColumn('Account') do begin
+    Binding := 'Account';
+    Filters := SORTABLE_NUMERIC_FILTER;
+    Width := 100;
+    HeaderFontStyles := [fsBold];
+    DataFontStyles := [fsBold];
+  end;
+  with FSendersGrid.AddColumn('Current Public Key') do begin
+    Binding := 'CurrentPublicKey';
+    Filters := SORTABLE_TEXT_FILTER;
+    Width := 100;
+  end;
+   with FSendersGrid.AddColumn('New Public Key') do begin
+    Binding := 'NewPublicKey';
+    Filters := SORTABLE_TEXT_FILTER;
+    Width := 100;
+  end;
+  with FSendersGrid.AddColumn('Fee') do begin
+    Filters := SORTABLE_TEXT_FILTER;
+    Width := 100;
+  end;
+
+   data := TAccountSenderDataSource.Create(FSendersGrid);
+   data.Model := Model.TransferAccount;
+   FSendersGrid.DataSource := data;
+   paGrid.AddControlDockCenter(FSendersGrid);
+   lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.Signer.SignerAccount.account);
+end;
+
+{ TAccountSenderDataSource }
+
+function TAccountSenderDataSource.GetColumns : TDataColumns;
+begin
+  Result := TDataColumns.Create(
+    TDataColumn.From('Account'),
+    TDataColumn.From('CurrentPublicKey'),
+    TDataColumn.From('NewPublicKey'),
+    TDataColumn.From('Fee')
+  );
+end;
+
+function TAccountSenderDataSource.GetItemField(constref AItem: TAccount; const ABindingName : AnsiString) : Variant;
+var
+  index : Integer;
+begin
+   if ABindingName = 'Account' then
+     Result := TAccountComp.AccountNumberToAccountTxtNumber(AItem.account)
+   else if ABindingName = 'CurrentPublicKey' then
+     Result := TAccountComp.AccountPublicKeyExport(AItem.accountInfo.accountKey)
+   else if ABindingName = 'NewPublicKey' then
+     Result := Model.NewPublicKey
+     else if ABindingName = 'Fee' then
+     Result := TAccountComp.FormatMoney(Model.Fee.DefaultFee)
+   else raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
+end;
+
+
+procedure TAccountSenderDataSource.FetchAll(const AContainer : TList<TAccount>);
+var
+  i: Integer;
+begin
+  for i := Low(Model.SelectedAccounts) to High(Model.SelectedAccounts) do
+  begin
+    AContainer.Add( Model.SelectedAccounts[i] );
+  end;
+end;
+
+
+end.
+

+ 0 - 0
src/gui/wizards/UWIZTransferAccount_Start.lfm → src/gui/wizards/operations/UWIZTransferAccount_Start.lfm


+ 1 - 1
src/gui/wizards/UWIZTransferAccount_Start.pas → src/gui/wizards/operations/UWIZTransferAccount_Start.pas

@@ -97,7 +97,7 @@ begin
     Filters := SORTABLE_NUMERIC_FILTER;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
   end;
   Data := TAccountSenderDataSource.Create(FSendersGrid);
   Data := TAccountSenderDataSource.Create(FSendersGrid);
-  Data.Model := Model.TransferAccountModel;
+  Data.Model := Model.TransferAccount;
   FSendersGrid.DataSource := Data;
   FSendersGrid.DataSource := Data;
   paGrid.AddControlDockCenter(FSendersGrid);
   paGrid.AddControlDockCenter(FSendersGrid);
 end;
 end;

+ 93 - 0
src/gui/wizards/operations/UWIZTransferAccount_Transaction.lfm

@@ -0,0 +1,93 @@
+object WIZTransferAccount_Transaction: TWIZTransferAccount_Transaction
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  ActiveControl = cbSignerAccount
+  Caption = 'WIZTransferAccount_Transaction'
+  ClientHeight = 253
+  ClientWidth = 429
+  LCLVersion = '1.8.2.0'
+  Visible = False
+  object gbTransaction: TGroupBox
+    Left = 24
+    Height = 192
+    Top = 40
+    Width = 384
+    Caption = 'Transfer Transaction Details'
+    ClientHeight = 172
+    ClientWidth = 380
+    TabOrder = 0
+    object cbSignerAccount: TComboBox
+      Left = 8
+      Height = 23
+      Top = 8
+      Width = 168
+      ItemHeight = 15
+      Items.Strings = (
+        ''
+      )
+      OnChange = cbSignerAccountChange
+      TabOrder = 0
+      Text = 'Select Signer Account'
+    end
+    object lblBalance: TLabel
+      Left = 200
+      Height = 15
+      Top = 12
+      Width = 151
+      Caption = 'Please Select Signer Account'
+      Font.Color = clRed
+      ParentColor = False
+      ParentFont = False
+    end
+    object lblpublickey: TLabel
+      Left = 8
+      Height = 15
+      Top = 48
+      Width = 120
+      Caption = 'New Owner Public Key'
+      ParentColor = False
+    end
+    object edtPublicKey: TEdit
+      Left = 8
+      Height = 23
+      Top = 74
+      Width = 360
+      TabOrder = 1
+    end
+    object edtOpFee: TEdit
+      Left = 8
+      Height = 23
+      Top = 144
+      Width = 360
+      TabOrder = 2
+    end
+    object lblOpFee: TLabel
+      Left = 8
+      Height = 15
+      Top = 112
+      Width = 74
+      Caption = 'Operation Fee'
+      ParentColor = False
+    end
+  end
+  object lblTotalBalances: TLabel
+    Left = 24
+    Height = 15
+    Top = 16
+    Width = 176
+    Caption = 'Selected Accounts Total Balance: '
+    ParentColor = False
+  end
+  object lblTotalBalanceValue: TLabel
+    Left = 208
+    Height = 15
+    Top = 16
+    Width = 70
+    Caption = 'Total Balance'
+    Font.Color = clGreen
+    ParentColor = False
+    ParentFont = False
+  end
+end

+ 148 - 0
src/gui/wizards/operations/UWIZTransferAccount_Transaction.pas

@@ -0,0 +1,148 @@
+unit UWIZTransferAccount_Transaction;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
+  UFRMAccountSelect, UNode, UWizard, UWIZTransferAccount,
+  UWIZTransferAccount_TransactionPayload,
+  UWIZTransferAccount_Confirmation, UWIZModels;
+
+type
+
+  { TWIZTransferAccount_Transaction }
+
+  TWIZTransferAccount_Transaction = class(TWizardForm<TWIZOperationsModel>)
+    cbSignerAccount: TComboBox;
+    edtOpFee: TEdit;
+    edtPublicKey: TEdit;
+    gbTransaction: TGroupBox;
+    lblOpFee: TLabel;
+    lblpublickey: TLabel;
+    lblTotalBalanceValue: TLabel;
+    lblTotalBalances: TLabel;
+    lblBalance: TLabel;
+    procedure cbSignerAccountChange(Sender: TObject);
+
+
+  public
+    procedure OnPresent; override;
+    procedure OnNext; override;
+    function Validate(out message: ansistring): boolean; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses
+  UAccounts, UUserInterface, USettings;
+
+{ TWIZTransferAccount_Transaction }
+
+procedure TWIZTransferAccount_Transaction.cbSignerAccountChange(Sender: TObject);
+begin
+  if cbSignerAccount.ItemIndex < 1 then
+  begin
+    lblBalance.Font.Color := clRed;
+    lblBalance.Caption := 'Please Select Signer Account';
+  end
+  else
+  begin
+    lblBalance.Font.Color := clGreen;
+    lblBalance.Caption := Format('%s PASC', [TAccountComp.FormatMoney(Model.TransferAccount.SelectedAccounts[PtrInt(cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])].Balance)]);
+  end;
+end;
+
+procedure TWIZTransferAccount_Transaction.OnPresent;
+
+  function GetAccNoWithChecksum(AAccountNumber: cardinal): string;
+  begin
+    Result := TAccountComp.AccountNumberToAccountTxtNumber(AAccountNumber);
+  end;
+
+var
+  acc: TAccount;
+  accNumberwithChecksum: string;
+  totalBalance: int64;
+  i: integer;
+begin
+  cbSignerAccount.Items.BeginUpdate;
+  totalBalance := 0;
+  try
+    cbSignerAccount.Items.Clear;
+    cbSignerAccount.Items.Add('Select Signer Account');
+    for i := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
+    begin
+      acc := Model.TransferAccount.SelectedAccounts[i];
+      accNumberwithChecksum := GetAccNoWithChecksum(acc.account);
+      totalBalance := totalBalance + acc.balance;
+      cbSignerAccount.Items.AddObject(accNumberwithChecksum, TObject(i));
+    end;
+  finally
+    cbSignerAccount.Items.EndUpdate;
+  end;
+  cbSignerAccount.ItemIndex := Model.TransferAccount.SelectedIndex;
+  cbSignerAccountChange(Self);
+  lblTotalBalanceValue.Caption :=
+    Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
+
+  edtOpFee.Text := TAccountComp.FormatMoney(TSettings.Fee.DefaultFee);
+end;
+
+procedure TWIZTransferAccount_Transaction.OnNext;
+begin
+  Model.TransferAccount.SelectedIndex := cbSignerAccount.ItemIndex;
+  Model.Signer.SignerAccount := Model.TransferAccount.SelectedAccounts[PtrInt(
+    cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
+  Model.TransferAccount.NewPublicKey := Trim(edtPublicKey.Text);
+
+  UpdatePath(ptReplaceAllNext, [TWIZTransferAccount_TransactionPayload,
+    TWIZTransferAccount_Confirmation]);
+end;
+
+function TWIZTransferAccount_Transaction.Validate(out message: ansistring): boolean;
+var
+  i: integer;
+begin
+  Result := True;
+  if cbSignerAccount.ItemIndex < 1 then
+  begin
+    message := 'A signer account must be selected';
+    Result := False;
+    Exit;
+  end;
+
+  if not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.TransferAccount.Fee.DefaultFee) then
+  begin
+    message := 'Invalid fee value "' + edtOpFee.Text + '"';
+    Result := False;
+    Exit;
+  end;
+
+  Result := TAccountComp.AccountKeyFromImport(edtPublicKey.Text,
+    Model.TransferAccount.AccountKey, message);
+  for i := Low(Model.TransferAccount.SelectedAccounts) to High(Model.TransferAccount.SelectedAccounts) do
+  begin
+    if TAccountComp.EqualAccountKeys(Model.TransferAccount.SelectedAccounts[i].accountInfo.accountKey,
+      Model.TransferAccount.AccountKey) then
+    begin
+      Result := False;
+      message := 'new public key is same as selected account public key';
+      Exit;
+    end;
+  end;
+end;
+
+end.

+ 98 - 0
src/gui/wizards/operations/UWIZTransferAccount_TransactionPayload.lfm

@@ -0,0 +1,98 @@
+object WIZTransferAccount_TransactionPayload: TWIZTransferAccount_TransactionPayload
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  ActiveControl = mmoPayload
+  Caption = 'Form1'
+  ClientHeight = 253
+  ClientWidth = 429
+  LCLVersion = '1.8.1.0'
+  Visible = False
+  object grpPayload: TGroupBox
+    Left = 8
+    Height = 244
+    Top = 2
+    Width = 416
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    Caption = 'Transfer Transaction Payload'
+    ClientHeight = 224
+    ClientWidth = 412
+    TabOrder = 0
+    object paPayload: TPanel
+      Left = 8
+      Height = 214
+      Top = 2
+      Width = 396
+      Anchors = [akTop, akLeft, akRight, akBottom]
+      BevelOuter = bvNone
+      ClientHeight = 214
+      ClientWidth = 396
+      TabOrder = 0
+      object mmoPayload: TMemo
+        Left = 0
+        Height = 70
+        Top = 136
+        Width = 386
+        TabOrder = 0
+      end
+      object Label1: TLabel
+        Left = 0
+        Height = 15
+        Top = 118
+        Width = 69
+        Caption = 'Payload Data'
+        ParentColor = False
+      end
+      object rbEncryptedWithOldEC: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 0
+        Width = 176
+        Caption = 'Encrypted with old public key'
+        TabOrder = 1
+      end
+      object rbEncryptedWithEC: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 24
+        Width = 181
+        Caption = 'Encrypted with new public key'
+        Checked = True
+        TabOrder = 2
+        TabStop = True
+      end
+      object rbEncryptedWithPassword: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 48
+        Width = 152
+        Caption = 'Encrypted with password'
+        TabOrder = 3
+      end
+      object lblPassword: TLabel
+        Left = 3
+        Height = 15
+        Top = 73
+        Width = 53
+        Caption = 'Password:'
+        ParentColor = False
+      end
+      object rbNotEncrypted: TRadioButton
+        Left = 3
+        Height = 19
+        Top = 94
+        Width = 181
+        Caption = 'Don''t encrypt (public payload)'
+        TabOrder = 4
+      end
+      object edtPassword: TEdit
+        Left = 64
+        Height = 23
+        Top = 70
+        Width = 160
+        TabOrder = 5
+      end
+    end
+  end
+end

+ 84 - 0
src/gui/wizards/operations/UWIZTransferAccount_TransactionPayload.pas

@@ -0,0 +1,84 @@
+unit UWIZTransferAccount_TransactionPayload;
+
+{$mode delphi}
+{$modeswitch nestedprocvars}
+
+{ Copyright (c) 2018 by Ugochukwu Mmaduekwe
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  ExtCtrls, Buttons, UCommon, UCommon.Collections,
+  UWizard, UWIZTransferAccount, UWIZModels;
+
+type
+
+  { TWIZTransferAccount_TransactionPayload }
+
+  TWIZTransferAccount_TransactionPayload = class(TWizardForm<TWIZOperationsModel>)
+    edtPassword: TEdit;
+    grpPayload: TGroupBox;
+    Label1: TLabel;
+    lblPassword: TLabel;
+    mmoPayload: TMemo;
+    paPayload: TPanel;
+    rbEncryptedWithOldEC: TRadioButton;
+    rbEncryptedWithEC: TRadioButton;
+    rbEncryptedWithPassword: TRadioButton;
+    rbNotEncrypted: TRadioButton;
+  public
+    procedure OnNext; override;
+    function Validate(out message: ansistring): boolean; override;
+  end;
+
+
+implementation
+
+{$R *.lfm}
+
+uses
+  UAccounts, UUserInterface;
+
+{ TWIZTransferAccount_TransactionPayload }
+
+procedure TWIZTransferAccount_TransactionPayload.OnNext;
+begin
+  Model.Payload.Content := mmoPayload.Lines.Text;
+  if rbEncryptedWithOldEC.Checked then
+  begin
+    Model.Payload.Mode := akaEncryptWithSender;
+  end
+  else
+  if rbEncryptedWithEC.Checked then
+  begin
+    Model.Payload.Mode := akaEncryptWithReceiver;
+  end
+  else
+  if rbEncryptedWithPassword.Checked then
+  begin
+    Model.Payload.Mode := akaEncryptWithPassword;
+  end
+  else
+  if rbNotEncrypted.Checked then
+  begin
+    Model.Payload.Mode := akaNotEncrypt;
+  end;
+end;
+
+function TWIZTransferAccount_TransactionPayload.Validate(out message: ansistring): boolean;
+begin
+  if (not rbNotEncrypted.Checked) and (not rbEncryptedWithEC.Checked) and
+    (not rbEncryptedWithOldEC.Checked) and (not rbEncryptedWithPassword.Checked) then
+  begin
+    message := 'you must select an encryption option for payload';
+    Result := False;
+    Exit;
+  end;
+end;
+
+end.

+ 0 - 0
src/gui/wizards/UWIZAddKey.pas → src/gui/wizards/wallet/UWIZAddKey.pas


+ 0 - 0
src/gui/wizards/UWIZAddKey_EnterName.lfm → src/gui/wizards/wallet/UWIZAddKey_EnterName.lfm


+ 0 - 0
src/gui/wizards/UWIZAddKey_EnterName.pas → src/gui/wizards/wallet/UWIZAddKey_EnterName.pas


+ 0 - 0
src/gui/wizards/UWIZAddKey_GenerateOrImport.lfm → src/gui/wizards/wallet/UWIZAddKey_GenerateOrImport.lfm


+ 0 - 0
src/gui/wizards/UWIZAddKey_GenerateOrImport.pas → src/gui/wizards/wallet/UWIZAddKey_GenerateOrImport.pas


+ 0 - 0
src/gui/wizards/UWIZAddKey_ImportPrivKey.lfm → src/gui/wizards/wallet/UWIZAddKey_ImportPrivKey.lfm


+ 0 - 0
src/gui/wizards/UWIZAddKey_ImportPrivKey.pas → src/gui/wizards/wallet/UWIZAddKey_ImportPrivKey.pas


+ 0 - 0
src/gui/wizards/UWIZAddKey_ImportPubKey.lfm → src/gui/wizards/wallet/UWIZAddKey_ImportPubKey.lfm


+ 0 - 0
src/gui/wizards/UWIZAddKey_ImportPubKey.pas → src/gui/wizards/wallet/UWIZAddKey_ImportPubKey.pas


+ 34 - 0
src/gui/wizards/wallet/UWIZAddKey_SelectEncryption.lfm

@@ -0,0 +1,34 @@
+object WIZAddKey_SelectEncryption: TWIZAddKey_SelectEncryption
+  Left = -1207
+  Height = 240
+  Top = 90
+  Width = 320
+  Caption = 'WIZAddKey_SelectEncryption'
+  ClientHeight = 240
+  ClientWidth = 320
+  OnCreate = FormCreate
+  LCLVersion = '1.8.2.0'
+  Visible = False
+  object rgKeyType: TRadioGroup
+    Left = 24
+    Height = 209
+    Top = 16
+    Width = 278
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    AutoFill = True
+    Caption = 'Select the type of encryption:'
+    ChildSizing.LeftRightSpacing = 6
+    ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
+    ChildSizing.EnlargeVertical = crsHomogenousChildResize
+    ChildSizing.ShrinkHorizontal = crsScaleChilds
+    ChildSizing.ShrinkVertical = crsScaleChilds
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 1
+    ClientHeight = 189
+    ClientWidth = 274
+    Items.Strings = (
+      'asdf'
+    )
+    TabOrder = 0
+  end
+end

+ 81 - 0
src/gui/wizards/wallet/UWIZAddKey_SelectEncryption.pas

@@ -0,0 +1,81 @@
+unit UWIZAddKey_SelectEncryption;
+
+{$mode delphi}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, UWizard, UWIZAddKey, UWIZModels;
+
+type
+
+  { TWIZAddKey_SelectEncryption }
+
+  TWIZAddKey_SelectEncryption = class(TWizardForm<TWIZAddKeyModel>)
+    rgKeyType: TRadioGroup;
+    procedure FormCreate(Sender: TObject);
+    class function GetOptionText(const EC_OpenSSL_NID: Word): AnsiString;
+  public
+    procedure OnNext; override;
+    function Validate(out message : AnsiString) : boolean; override;
+  end;
+
+implementation
+
+{$R *.lfm}
+
+uses UAccounts, UConst, UMemory;
+
+{ TWIZAddKey_SelectEncryption }
+
+procedure TWIZAddKey_SelectEncryption.FormCreate(Sender: TObject);
+var
+  i : Integer;
+  GC : TDisposables;
+  availableEncryptionTypes : TList;
+  name, desc : UTF8String;
+begin
+  rgKeyType.Items.Clear;
+  availableEncryptionTypes := GC.AddObject( TList.Create ) as TList;
+  TAccountComp.ValidsEC_OpenSSL_NID(availableEncryptionTypes);
+  for i := 0 to availableEncryptionTypes.Count - 1 do begin
+    rgKeyType.Items.AddObject(GetOptionText(PtrInt(availableEncryptionTypes[i])),availableEncryptionTypes[i]);
+  end;
+end;
+
+procedure TWIZAddKey_SelectEncryption.OnNext;
+begin
+  Self.Model.EncryptionTypeNID := PtrInt(rgKeyType.Items.Objects[rgKeyType.ItemIndex]);
+end;
+
+function TWIZAddKey_SelectEncryption.Validate(out message : AnsiString) : boolean;
+begin
+  Result := true;
+  if rgKeyType.ItemIndex < 0 then begin
+    message := 'A type of encryption must be selected';
+    Result := false;
+  end;
+end;
+
+
+class function TWIZAddKey_SelectEncryption.GetOptionText(const EC_OpenSSL_NID: Word): AnsiString;
+begin
+  case EC_OpenSSL_NID of
+    CT_NID_secp256k1 : begin
+      Result := 'SECP256K1 - Cryptocurrency Standard (same as Bitcoin)';
+    end;
+    CT_NID_secp384r1 : begin
+      Result := 'SECP384R1 - Stronger, different algorithm (larger key) ';
+    end;
+    CT_NID_sect283k1 : Begin
+      Result := 'SECP283K1 - Even stronger (larger key)';
+    End;
+    CT_NID_secp521r1 : begin
+      Result := 'SECP521R1 - Quantum-resistant (largest key)';
+    end
+    else Result := '(Unknown ID:'+inttostr(EC_OpenSSL_NID)+')';
+  end;
+end;
+
+end.
+

+ 66 - 0
src/gui/wizards/wallet/UWIZAddKey_Start.lfm

@@ -0,0 +1,66 @@
+object WIZAddKey_Start: TWIZAddKey_Start
+  Left = 26
+  Height = 300
+  Top = 27
+  Width = 437
+  Caption = 'Add Key'
+  ClientHeight = 300
+  ClientWidth = 437
+  LCLVersion = '1.8.2.0'
+  Visible = False
+  object rbPrivateKey: TRadioButton
+    Left = 32
+    Height = 19
+    Top = 56
+    Width = 84
+    Caption = 'Private Key'
+    Checked = True
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 1
+    TabStop = True
+  end
+  object rbPublicKey: TRadioButton
+    Left = 32
+    Height = 19
+    Top = 168
+    Width = 144
+    Caption = 'Watch-only Public Key'
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 0
+  end
+  object Label1: TLabel
+    Left = 32
+    Height = 32
+    Top = 16
+    Width = 370
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'What type of key would you like to add into your wallet?'
+    ParentColor = False
+    WordWrap = True
+  end
+  object Label2: TLabel
+    Left = 52
+    Height = 64
+    Top = 80
+    Width = 352
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'Adding a private key allows you to send operations from accounts bound to this key. Please ensure your wallet is adequately protected if using this option since sensitive information is stored on your machine.'
+    ParentColor = False
+    WordWrap = True
+  end
+  object Label3: TLabel
+    Left = 48
+    Height = 66
+    Top = 192
+    Width = 350
+    Anchors = [akTop, akLeft, akRight]
+    AutoSize = False
+    Caption = 'A watch-only key allows you to track accounts that are bound to this key but without the ability to authorize new operations. There is no sensitive information kept on your machine when using this option.'
+    ParentColor = False
+    WordWrap = True
+  end
+end

+ 55 - 0
src/gui/wizards/wallet/UWIZAddKey_Start.pas

@@ -0,0 +1,55 @@
+unit UWIZAddKey_Start;
+
+{$mode delphi}
+
+{ Copyright (c) 2018 by Herman Schoenfeld
+
+  Distributed under the MIT software license, see the accompanying file LICENSE
+  or visit http://www.opensource.org/licenses/mit-license.php.
+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  UWizard, UWIZAddKey, UWIZModels;
+
+type
+
+  { TWIZAddKey_Start }
+
+  TWIZAddKey_Start = class(TWizardForm<TWIZAddKeyModel>)
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    rbPrivateKey: TRadioButton;
+    rbPublicKey: TRadioButton;
+  private
+    { private declarations }
+  public
+    { public declarations }
+    procedure OnNext; override;
+  end;
+
+implementation
+
+{$R *.lfm}
+
+uses
+   UWIZAddKey_GenerateOrImport, UWIZAddKey_ImportPrivKey, UWIZAddKey_ImportPubKey, UWIZAddKey_EnterName;
+
+{ TWIZAddKey_Start }
+
+
+procedure TWIZAddKey_Start.OnNext;
+begin
+  if rbPublicKey.Checked = true then begin
+    Model.Action := akaImportPublicKey;
+    UpdatePath(ptReplaceAllNext, [TWIZAddKey_ImportPubKey, TWIZAddKey_EnterName]);
+  end else begin
+    UpdatePath(ptReplaceAllNext, [TWIZAddKey_GenerateOrImport, TWIZAddKey_ImportPrivKey]);//, TWIZAddKey_ImportPrivKey, TWIZAddKey_Finish]);
+  end;
+end;
+
+end.
+

+ 118 - 93
src/pascalcoin_wallet.lpi

@@ -33,7 +33,7 @@
         <PackageName Value="LCL"/>
         <PackageName Value="LCL"/>
       </Item1>
       </Item1>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="89">
+    <Units Count="101">
       <Unit0>
       <Unit0>
         <Filename Value="pascalcoin_wallet.dpr"/>
         <Filename Value="pascalcoin_wallet.dpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -273,236 +273,261 @@
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit46>
       </Unit46>
       <Unit47>
       <Unit47>
-        <Filename Value="gui\wizards\UWIZAddKey_Start.pas"/>
+        <Filename Value="gui\UFRMWalletKeys.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZAddKey_Start"/>
+        <ComponentName Value="FRMWalletKeys"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit47>
       </Unit47>
       <Unit48>
       <Unit48>
-        <Filename Value="gui\wizards\UWIZAddKey_GenerateOrImport.pas"/>
+        <Filename Value="core\USettings.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZAddKey_GenerateOrImport"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit48>
       </Unit48>
       <Unit49>
       <Unit49>
-        <Filename Value="gui\wizards\UWIZAddKey_ImportPubKey.pas"/>
+        <Filename Value="gui\UCTRLWallet.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZAddKey_ImportPubKey"/>
+        <ComponentName Value="CTRLWallet"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit49>
       </Unit49>
       <Unit50>
       <Unit50>
-        <Filename Value="gui\wizards\UWIZAddKey_ImportPrivKey.pas"/>
+        <Filename Value="libraries\sphere10\UCommon.Collections.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZAddKey_ImportPrivKey"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit50>
       </Unit50>
       <Unit51>
       <Unit51>
-        <Filename Value="gui\wizards\UWIZAddKey_EnterName.pas"/>
+        <Filename Value="libraries\sphere10\UCommon.Data.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZAddKey_EnterName"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit51>
       </Unit51>
       <Unit52>
       <Unit52>
-        <Filename Value="gui\UFRMWalletKeys.pas"/>
+        <Filename Value="libraries\sphere10\UCommon.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="FRMWalletKeys"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit52>
       </Unit52>
       <Unit53>
       <Unit53>
-        <Filename Value="gui\wizards\UWIZAddKey.pas"/>
+        <Filename Value="libraries\sphere10\UCommon.UI.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit53>
       </Unit53>
       <Unit54>
       <Unit54>
-        <Filename Value="core\USettings.pas"/>
+        <Filename Value="libraries\sphere10\UVisualGrid.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit54>
       </Unit54>
       <Unit55>
       <Unit55>
-        <Filename Value="gui\wizards\UWIZAddKey_SelectEncryption.pas"/>
+        <Filename Value="libraries\sphere10\UWizard.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZAddKey_SelectEncryption"/>
+        <ComponentName Value="WizardHostForm"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
       </Unit55>
       </Unit55>
       <Unit56>
       <Unit56>
-        <Filename Value="gui\UCTRLWallet.pas"/>
+        <Filename Value="config.inc"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="CTRLWallet"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit56>
       </Unit56>
       <Unit57>
       <Unit57>
-        <Filename Value="libraries\sphere10\UCommon.Collections.pas"/>
+        <Filename Value="libraries\sphere10\UMemory.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit57>
       </Unit57>
       <Unit58>
       <Unit58>
-        <Filename Value="libraries\sphere10\UCommon.Data.pas"/>
+        <Filename Value="gui\UCellRenderers.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit58>
       </Unit58>
       <Unit59>
       <Unit59>
-        <Filename Value="libraries\sphere10\UCommon.pas"/>
+        <Filename Value="libraries\generics.collections\inc\generics.dictionaries.inc"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit59>
       </Unit59>
       <Unit60>
       <Unit60>
-        <Filename Value="libraries\sphere10\UCommon.UI.pas"/>
+        <Filename Value="libraries\pascalcoin\UAppParams.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit60>
       </Unit60>
       <Unit61>
       <Unit61>
-        <Filename Value="libraries\sphere10\UVisualGrid.pas"/>
+        <Filename Value="libraries\pascalcoin\UFolderHelper.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit61>
       </Unit61>
       <Unit62>
       <Unit62>
-        <Filename Value="libraries\sphere10\UWizard.pas"/>
+        <Filename Value="libraries\pascalcoin\UGridUtils.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WizardHostForm"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit62>
       </Unit62>
       <Unit63>
       <Unit63>
-        <Filename Value="config.inc"/>
+        <Filename Value="libraries\pascalcoin\UJSONFunctions.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit63>
       </Unit63>
       <Unit64>
       <Unit64>
-        <Filename Value="gui\wizards\UWIZSendPASC.pas"/>
+        <Filename Value="core.utils\UCoreUtils.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit64>
       </Unit64>
       <Unit65>
       <Unit65>
-        <Filename Value="gui\wizards\UWIZSendPASC_Confirmation.pas"/>
+        <Filename Value="core.utils\UDataSources.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZSendPASC_Confirmation"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit65>
       </Unit65>
       <Unit66>
       <Unit66>
-        <Filename Value="gui\wizards\UWIZSendPASC_Start.pas"/>
+        <Filename Value="gui\wizards\UWIZModels.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZSendPASC_Start"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit66>
       </Unit66>
       <Unit67>
       <Unit67>
-        <Filename Value="gui\wizards\UWIZSendPASC_Transaction.pas"/>
+        <Filename Value="gui\wizards\wallet\UWIZAddKey.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZSendPASC_Transaction"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit67>
       </Unit67>
       <Unit68>
       <Unit68>
-        <Filename Value="libraries\sphere10\UMemory.pas"/>
+        <Filename Value="gui\wizards\wallet\UWIZAddKey_EnterName.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit68>
       </Unit68>
       <Unit69>
       <Unit69>
-        <Filename Value="gui\UCellRenderers.pas"/>
+        <Filename Value="gui\wizards\wallet\UWIZAddKey_GenerateOrImport.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit69>
       </Unit69>
       <Unit70>
       <Unit70>
-        <Filename Value="libraries\generics.collections\inc\generics.dictionaries.inc"/>
+        <Filename Value="gui\wizards\wallet\UWIZAddKey_ImportPrivKey.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit70>
       </Unit70>
       <Unit71>
       <Unit71>
-        <Filename Value="libraries\pascalcoin\UAppParams.pas"/>
+        <Filename Value="gui\wizards\wallet\UWIZAddKey_ImportPubKey.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit71>
       </Unit71>
       <Unit72>
       <Unit72>
-        <Filename Value="libraries\pascalcoin\UFolderHelper.pas"/>
+        <Filename Value="gui\wizards\wallet\UWIZAddKey_SelectEncryption.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit72>
       </Unit72>
       <Unit73>
       <Unit73>
-        <Filename Value="libraries\pascalcoin\UGridUtils.pas"/>
+        <Filename Value="gui\wizards\wallet\UWIZAddKey_Start.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit73>
       </Unit73>
       <Unit74>
       <Unit74>
-        <Filename Value="libraries\pascalcoin\UJSONFunctions.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZChangeAccountPrivateKey.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit74>
       </Unit74>
       <Unit75>
       <Unit75>
-        <Filename Value="core.utils\UCoreUtils.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZChangeAccountPrivateKey_Confirmation.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit75>
       </Unit75>
       <Unit76>
       <Unit76>
-        <Filename Value="core.utils\UDataSources.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZChangeAccountPrivateKey_Start.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit76>
       </Unit76>
       <Unit77>
       <Unit77>
-        <Filename Value="gui\wizards\UWIZSendPASC_TransactionPayload.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZChangeAccountPrivateKey_Transaction.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZSendPASC_TransactionPayload"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit77>
       </Unit77>
       <Unit78>
       <Unit78>
-        <Filename Value="gui\wizards\UWIZTransferAccount.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZChangeAccountPrivateKey_TransactionPayload.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit78>
       </Unit78>
       <Unit79>
       <Unit79>
-        <Filename Value="gui\wizards\UWIZTransferAccount_Start.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZEnlistAccountForSale.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZTransferAccount_Start"/>
-        <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit79>
       </Unit79>
       <Unit80>
       <Unit80>
-        <Filename Value="gui\wizards\UWIZTransferAccount_Transaction.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZEnlistAccountForSale_Confirmation.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZTransferAccount_Transaction"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit80>
       </Unit80>
       <Unit81>
       <Unit81>
-        <Filename Value="gui\wizards\UWIZTransferAccount_Confirmation.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZEnlistAccountForSale_List.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZTransferAccount_Confirmation"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit81>
       </Unit81>
       <Unit82>
       <Unit82>
-        <Filename Value="gui\wizards\UWIZTransferAccount_TransactionPayload.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZEnlistAccountForSale_PrivateSaleConfig.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZTransferAccount_TransactionPayload"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit82>
       </Unit82>
       <Unit83>
       <Unit83>
-        <Filename Value="gui\wizards\UWIZChangeAccountPrivateKey.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZEnlistAccountForSale_Start.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit83>
       </Unit83>
       <Unit84>
       <Unit84>
-        <Filename Value="gui\wizards\UWIZChangeAccountPrivateKey_Confirmation.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZEnlistAccountForSale_Transaction.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZChangeAccountPrivateKey_Confirmation"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit84>
       </Unit84>
       <Unit85>
       <Unit85>
-        <Filename Value="gui\wizards\UWIZChangeAccountPrivateKey_Start.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZEnlistAccountForSale_TransactionPayload.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZChangeAccountPrivateKey_Start"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit85>
       </Unit85>
       <Unit86>
       <Unit86>
-        <Filename Value="gui\wizards\UWIZChangeAccountPrivateKey_Transaction.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZFeeOverride.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZChangeAccountPrivateKey_Transaction"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit86>
       </Unit86>
       <Unit87>
       <Unit87>
-        <Filename Value="gui\wizards\UWIZChangeAccountPrivateKey_TransactionPayload.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZPayloadContentOverride.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-        <ComponentName Value="WIZChangeAccountPrivateKey_TransactionPayload"/>
         <HasResources Value="True"/>
         <HasResources Value="True"/>
-        <ResourceBaseClass Value="Form"/>
       </Unit87>
       </Unit87>
       <Unit88>
       <Unit88>
-        <Filename Value="gui\wizards\UWIZModels.pas"/>
+        <Filename Value="gui\wizards\operations\UWIZPayloadOverride.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
       </Unit88>
       </Unit88>
+      <Unit89>
+        <Filename Value="gui\wizards\operations\UWIZPayloadPasswordOverride.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit89>
+      <Unit90>
+        <Filename Value="gui\wizards\operations\UWIZSelectSignerOverride.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZSelectSignerOverride"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit90>
+      <Unit91>
+        <Filename Value="gui\wizards\operations\UWIZSendPASC.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit91>
+      <Unit92>
+        <Filename Value="gui\wizards\operations\UWIZSendPASC_Confirmation.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit92>
+      <Unit93>
+        <Filename Value="gui\wizards\operations\UWIZSendPASC_ConfirmSender.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit93>
+      <Unit94>
+        <Filename Value="gui\wizards\operations\UWIZSendPASC_EnterQuantity.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit94>
+      <Unit95>
+        <Filename Value="gui\wizards\operations\UWIZSendPASC_EnterRecipient.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit95>
+      <Unit96>
+        <Filename Value="gui\wizards\operations\UWIZTransferAccount.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit96>
+      <Unit97>
+        <Filename Value="gui\wizards\operations\UWIZTransferAccount_Confirmation.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit97>
+      <Unit98>
+        <Filename Value="gui\wizards\operations\UWIZTransferAccount_Start.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit98>
+      <Unit99>
+        <Filename Value="gui\wizards\operations\UWIZTransferAccount_Transaction.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit99>
+      <Unit100>
+        <Filename Value="gui\wizards\operations\UWIZTransferAccount_TransactionPayload.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit100>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>
@@ -513,7 +538,7 @@
     </Target>
     </Target>
     <SearchPaths>
     <SearchPaths>
       <IncludeFiles Value="$(ProjOutDir);libraries\generics.collections\inc"/>
       <IncludeFiles Value="$(ProjOutDir);libraries\generics.collections\inc"/>
-      <OtherUnitFiles Value="core;gui;gui\wizards;libraries\synapse;libraries\sphere10;libraries\generics.collections;libraries\pascalcoin;core.utils"/>
+      <OtherUnitFiles Value="core;gui;gui\wizards;libraries\synapse;libraries\sphere10;libraries\generics.collections;libraries\pascalcoin;core.utils;gui\wizards\wallet;gui\wizards\operations"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     </SearchPaths>
     <Parsing>
     <Parsing>