Prechádzať zdrojové kódy

First Commit of Transfer Account Wizard.

Ugochukwu Mmaduekwe 7 rokov pred
rodič
commit
a23f97e5bf

+ 206 - 161
src/gui/UCTRLWallet.pas

@@ -9,7 +9,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus,
   ExtCtrls, PairSplitter, Buttons, UVisualGrid, UCommon.UI, Generics.Collections,
-  UAccounts, UDataSources, UNode, UWIZSendPASC{, UWIZTransferAccount};
+  UAccounts, UDataSources, UNode, UWIZSendPASC, UWIZTransferAccount;
 
 type
 
@@ -66,20 +66,29 @@ type
     procedure SetOperationsMode(AMode: TCTRLWalletOperationsMode);
     procedure SetOperationsHistory(AHistory: TCTRLWalletOperationsHistory);
     procedure RefreshMyAccountsCombo;
+    function GetAccNoWithoutChecksum(constref ARow: variant): cardinal; inline;
+    function GetAccounts(const AccountNumbers: TArray<cardinal>): TArray<TAccount>;
   protected
     procedure ActivateFirstTime; override;
     procedure OnPrivateKeysChanged(Sender: TObject);
     procedure OnNodeBlocksChanged(Sender: TObject);
     procedure OnNodeNewOperation(Sender: TObject);
     procedure OnAccountsUpdated(Sender: TObject);
-    procedure OnAccountsSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
-    procedure OnOperationSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
-    procedure OnPrepareAccountPopupMenu(Sender: TObject; constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
-    procedure OnPrepareOperationsPopupMenu(Sender: TObject; constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
+    procedure OnAccountsSelected(Sender: TObject;
+      constref ASelection: TVisualGridSelection);
+    procedure OnOperationSelected(Sender: TObject;
+      constref ASelection: TVisualGridSelection);
+    procedure OnPrepareAccountPopupMenu(Sender: TObject;
+      constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
+    procedure OnPrepareOperationsPopupMenu(Sender: TObject;
+      constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
   public
-    property AccountsMode: TCTRLWalletAccountsMode read FAccountsMode write SetAccountsMode;
-    property OperationsMode: TCTRLWalletOperationsMode read FOperationsMode write SetOperationsMode;
-    property OperationsHistory: TCTRLWalletOperationsHistory read FOperationsHistory write SetOperationsHistory;
+    property AccountsMode: TCTRLWalletAccountsMode
+      read FAccountsMode write SetAccountsMode;
+    property OperationsMode: TCTRLWalletOperationsMode
+      read FOperationsMode write SetOperationsMode;
+    property OperationsHistory: TCTRLWalletOperationsHistory
+      read FOperationsHistory write SetOperationsHistory;
   end;
 
 implementation
@@ -115,30 +124,34 @@ begin
   FAccountsGrid.AutoPageSize := True;
   FAccountsGrid.SelectionType := stMultiRow;
   FAccountsGrid.DeselectionType := dtDefault;
-  FAccountsGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone, vgoAutoHidePaging];
-  with FAccountsGrid.AddColumn('Account') do begin
+  FAccountsGrid.Options := [vgoColAutoFill, vgoColSizing,
+    vgoSortDirectionAllowNone, vgoAutoHidePaging];
+  with FAccountsGrid.AddColumn('Account') do
+  begin
     Binding := 'AccountNumber';
     SortBinding := 'AccountNumber';
     DisplayBinding := 'Account';
     Width := 100;
     HeaderFontStyles := [fsBold];
     DataFontStyles := [fsBold];
-    Filters:=SORTABLE_NUMERIC_FILTER;
+    Filters := SORTABLE_NUMERIC_FILTER;
   end;
-  with FAccountsGrid.AddColumn('Name') do begin
-    StretchedToFill := true;
+  with FAccountsGrid.AddColumn('Name') do
+  begin
+    StretchedToFill := True;
     HeaderAlignment := taCenter;
-    Filters:=SORTABLE_TEXT_FILTER;
+    Filters := SORTABLE_TEXT_FILTER;
   end;
-  with FAccountsGrid.AddColumn('Balance') do begin
+  with FAccountsGrid.AddColumn('Balance') do
+  begin
     Binding := 'BalanceDecimal';
     SortBinding := 'Balance';
     DisplayBinding := 'Balance';
     Width := 100;
-    HeaderAlignment:=taRightJustify;
-    DataAlignment:=taRightJustify;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
     Renderer := TCellRenderers.PASC;
-    Filters:=SORTABLE_NUMERIC_FILTER;
+    Filters := SORTABLE_NUMERIC_FILTER;
   end;
 
   FAccountsGrid.OnSelection := OnAccountsSelected;
@@ -151,32 +164,38 @@ begin
   FOperationsGrid.AutoPageSize := True;
   FOperationsGrid.SelectionType := stRow;
   FOperationsGrid.DeselectionType := dtDefault;
-  FOperationsGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone, vgoAutoHidePaging];
-  with FOperationsGrid.AddColumn('Time') do begin
+  FOperationsGrid.Options := [vgoColAutoFill, vgoColSizing,
+    vgoSortDirectionAllowNone, vgoAutoHidePaging];
+  with FOperationsGrid.AddColumn('Time') do
+  begin
     SortBinding := 'UnixTime';
     DisplayBinding := 'UnixTime';
-    Renderer:=TCellRenderers.OperationTime;
+    Renderer := TCellRenderers.OperationTime;
     Width := 130;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Block') do begin
+  with FOperationsGrid.AddColumn('Block') do
+  begin
     Binding := 'BlockLocation';
     SortBinding := 'BlockLocationSortable';
-    AutoWidth := true;
+    AutoWidth := True;
     Filters := SORTABLE_TEXT_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Account') do begin
+  with FOperationsGrid.AddColumn('Account') do
+  begin
     Binding := 'AccountNumber';
     DisplayBinding := 'Account';
     Width := 100;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Type') do begin
+  with FOperationsGrid.AddColumn('Type') do
+  begin
     Sanitizer := TCellRenderers.OperationTypeSanitizer;
     Width := 150;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Amount') do begin
+  with FOperationsGrid.AddColumn('Amount') do
+  begin
     Binding := 'AmountDecimal';
     SortBinding := 'Amount';
     DisplayBinding := 'Amount';
@@ -185,38 +204,43 @@ begin
     Renderer := TCellRenderers.PASC;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Fee') do begin
+  with FOperationsGrid.AddColumn('Fee') do
+  begin
     Binding := 'FeeDecimal';
     SortBinding := 'Fee';
     DisplayBinding := 'Fee';
-    AutoWidth := true;
-    HeaderAlignment:=taRightJustify;
-    DataAlignment:=taRightJustify;
+    AutoWidth := True;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
     Renderer := TCellRenderers.PASC;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Balance') do begin
+  with FOperationsGrid.AddColumn('Balance') do
+  begin
     Binding := 'BalanceDecimal';
     SortBinding := 'Balance';
     DisplayBinding := 'Balance';
     Width := 100;
-    HeaderAlignment:=taRightJustify;
-    DataAlignment:=taRightJustify;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
     Renderer := TCellRenderers.PASC;
     Filters := SORTABLE_NUMERIC_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Payload') do begin
-    AutoWidth := true;
+  with FOperationsGrid.AddColumn('Payload') do
+  begin
+    AutoWidth := True;
     Renderer := TCellRenderers.Payload;
     Filters := SORTABLE_TEXT_FILTER;
   end;
-  with FOperationsGrid.AddColumn('OPHASH') do begin
+  with FOperationsGrid.AddColumn('OPHASH') do
+  begin
     Width := 80;
     Renderer := TCellRenderers.OPHASH;
     Filters := SORTABLE_TEXT_FILTER;
   end;
-  with FOperationsGrid.AddColumn('Description') do begin
-    StretchedToFill := true;
+  with FOperationsGrid.AddColumn('Description') do
+  begin
+    StretchedToFill := True;
     Filters := SORTABLE_TEXT_FILTER;
   end;
   FOperationsGrid.OnSelection := OnOperationSelected;
@@ -230,7 +254,7 @@ begin
 
   // duration combo
   cmbDuration := TComboBox.Create(FOperationsGrid);
-  cmbDuration.ReadOnly:= true;
+  cmbDuration.ReadOnly := True;
   cmbDuration.Items.BeginUpdate;
   try
     cmbDuration.AddItem('30 Days', TObject(woh30Days));
@@ -269,71 +293,134 @@ end;
 
 procedure TCTRLWallet.RefreshMyAccountsCombo;
 var
-  i : Integer;
-  selectFirst, selectLast : boolean;
+  i: integer;
+  selectFirst, selectLast: boolean;
   last_key: TAccountKey;
-  key : TWalletKey;
-  str : AnsiString;
+  key: TWalletKey;
+  str: ansistring;
 begin
   // determine current selection
-  if cbAccounts.ItemIndex >= 1 then begin
-    if cbAccounts.ItemIndex < cbAccounts.Items.Count - 1 then begin
-      last_key := TBox<TAccountKey>(cbAccounts.Items.Objects[cbAccounts.ItemIndex]).Value;
-      selectFirst := false;
-      selectLast := false;
-    end else begin
-      selectFirst := false;
-      selectLast := true;
+  if cbAccounts.ItemIndex >= 1 then
+  begin
+    if cbAccounts.ItemIndex < cbAccounts.Items.Count - 1 then
+    begin
+      last_key := TBox<TAccountKey>(
+        cbAccounts.Items.Objects[cbAccounts.ItemIndex]).Value;
+      selectFirst := False;
+      selectLast := False;
+    end
+    else
+    begin
+      selectFirst := False;
+      selectLast := True;
     end;
-  end else begin
-    selectFirst := true;
-    selectLast := false;
+  end
+  else
+  begin
+    selectFirst := True;
+    selectLast := False;
   end;
 
   // update combo items
   cbAccounts.items.BeginUpdate;
-  Try
+  try
     // free existing items
     for i := 0 to cbAccounts.Items.Count - 1 do
       cbAccounts.Items.Objects[i].Free;
     cbAccounts.Items.Clear;
     // add new items
-    For i:=0 to TWallet.Keys.Count-1 do begin
+    for i := 0 to TWallet.Keys.Count - 1 do
+    begin
       // get i'th key
       key := TWallet.Keys.Key[i];
       // fix name
-      if (key.Name='') then begin
-        str := 'Sha256=' + TCrypto.ToHexaString( TCrypto.DoSha256( TAccountComp.AccountKey2RawString( key.AccountKey ) ) );
-      end else begin
+      if (key.Name = '') then
+      begin
+        str := 'Sha256=' + TCrypto.ToHexaString(TCrypto.DoSha256(
+          TAccountComp.AccountKey2RawString(key.AccountKey)));
+      end
+      else
+      begin
         str := key.Name;
       end;
-      if Not Assigned(key.PrivateKey) then str := str + '(*)';
+      if not Assigned(key.PrivateKey) then
+        str := str + '(*)';
       cbAccounts.Items.AddObject(str, TBox<TAccountKey>.Create(key.AccountKey));
     end;
-    cbAccounts.Items.InsertObject(0,'Show All', TBox<TAccountKey>.Create);
-    cbAccounts.Items.AddObject('Get An Account',TBox<TAccountKey>.Create);
-  Finally
+    cbAccounts.Items.InsertObject(0, 'Show All', TBox<TAccountKey>.Create);
+    cbAccounts.Items.AddObject('Get An Account', TBox<TAccountKey>.Create);
+  finally
     cbAccounts.Items.EndUpdate;
-  End;
+  end;
   // re-select previous selection
   if selectFirst then
     cbAccounts.ItemIndex := 0
   else if selectLast then
     cbAccounts.ItemIndex := cbAccounts.Items.Count - 1
-  else begin
-    for i := 1 to cbAccounts.Items.Count - 2 do begin
-       if TAccountKeyEqualityComparer.AreEqual(TBox<TAccountKey>( cbAccounts.Items.Objects[i] ).Value, last_key) then begin
-         cbAccounts.ItemIndex := i;
-         exit;
-       end;
+  else
+  begin
+    for i := 1 to cbAccounts.Items.Count - 2 do
+    begin
+      if TAccountKeyEqualityComparer.AreEqual(TBox<TAccountKey>(
+        cbAccounts.Items.Objects[i]).Value, last_key) then
+      begin
+        cbAccounts.ItemIndex := i;
+        exit;
+      end;
     end;
   end;
 end;
 
+function TCTRLWallet.GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
+begin
+  Result := ARow.__KEY;
+end;
+
+//function GetAccNoWithCheckSum(constref ARow: variant): string;
+//begin
+//  Result := ARow.Account;
+//end;
+
+function TCTRLWallet.GetAccounts(const AccountNumbers: TArray<cardinal>): TArray<TAccount>;
+var
+  acc: TAccount;
+  safeBox: TPCSafeBox;
+  keys: TOrderedAccountKeysList;
+  LContainer: Generics.Collections.TList<TAccount>;
+  i: integer;
+begin
+  LContainer := Generics.Collections.TList<TAccount>.Create();
+  keys := TWallet.keys.AccountsKeyList;
+  safeBox := TUserInterface.Node.Bank.safeBox;
+  safeBox.StartThreadSafe;
+  try
+    LContainer.Clear;
+    try
+      // load selected user accounts
+      for i := Low(AccountNumbers) to High(AccountNumbers) do
+      begin
+        acc := safeBox.Account(AccountNumbers[i]);
+        if keys.IndexOfAccountKey(acc.accountInfo.accountKey) >= 0 then
+        begin
+          LContainer.Add(acc);
+        end;
+      end;
+    finally
+      safeBox.EndThreadSave;
+    end;
+    Result := LContainer.ToArray;
+  finally
+    LContainer.Free;
+  end;
+
+end;
+
 procedure TCTRLWallet.SetAccountsMode(AMode: TCTRLWalletAccountsMode);
-var sel1 : TVisualGridSelection; sel2 : TRect;
+var
+  sel1: TVisualGridSelection;
+  sel2: TRect;
 begin
-  FAccountsMode:= AMode;
+  FAccountsMode := AMode;
   paAccounts.RemoveAllControls(False);
   case AMode of
     wamMyAccounts:
@@ -441,11 +528,10 @@ begin
         selectedAccounts.Add(acc);
     end;
     FOperationsDataSource.Accounts := selectedAccounts.ToArray;
-    FOperationsGrid.Caption.Text:= IIF(
-       ASelection.RowCount = 1,
-       Format('Account: %s', [TAccountComp.AccountNumberToAccountTxtNumber( selectedAccounts[0] )]),
-       'Selected Accounts'
-    ) ;
+    FOperationsGrid.Caption.Text :=
+      IIF(ASelection.RowCount = 1, Format('Account: %s',
+      [TAccountComp.AccountNumberToAccountTxtNumber(selectedAccounts[0])]),
+      'Selected Accounts');
     FOperationsGrid.RefreshGrid;
   end
   else
@@ -454,7 +540,8 @@ begin
   end;
 end;
 
-procedure TCTRLWallet.OnOperationSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
+procedure TCTRLWallet.OnOperationSelected(Sender: TObject;
+  constref ASelection: TVisualGridSelection);
 var
   row: longint;
   v: variant;
@@ -472,17 +559,21 @@ end;
 
 procedure TCTRLWallet.cbAccountsChange(Sender: TObject);
 var
-  index : Integer;
-  sel : TBox<TAccountKey>;
+  index: integer;
+  sel: TBox<TAccountKey>;
 begin
   index := cbAccounts.ItemIndex;
-  if cbAccounts.ItemIndex < 0 then exit;
+  if cbAccounts.ItemIndex < 0 then
+    exit;
   if index = 0 then
     FAccountsDataSource.FilterKeys := TWallet.Keys.AccountsKeyList.ToArray
-  else if index = cbAccounts.Items.Count - 1 then begin
-    AccountsMode:= wamFirstAccount;
+  else if index = cbAccounts.Items.Count - 1 then
+  begin
+    AccountsMode := wamFirstAccount;
     exit;
-  end else begin
+  end
+  else
+  begin
     sel := TBox<TAccountKey>(cbAccounts.Items.Objects[cbAccounts.ItemIndex]);
     FAccountsDataSource.FilterKeys := TArray<TAccountKey>.Create(sel.Value);
   end;
@@ -506,7 +597,8 @@ begin
   end;
 end;
 
-procedure TCTRLWallet.OnPrepareAccountPopupMenu(Sender: TObject; constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
+procedure TCTRLWallet.OnPrepareAccountPopupMenu(Sender: TObject;
+  constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
 begin
   miSep1.Visible := ASelection.RowCount = 1;
   miAccountInfo.Visible := ASelection.RowCount = 1;
@@ -523,56 +615,6 @@ begin
 end;
 
 procedure TCTRLWallet.miSendPASCClick(Sender: TObject);
-
-  function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
-  begin
-    if not TAccountComp.AccountTxtNumberToAccountNumber(ARow.Account, Result) then
-    begin
-      raise Exception.Create(
-        'Internal Error: Unable to parse account number from table row');
-    end;
-  end;
-
-  function GetAccNoWithCheckSum(constref ARow: variant): string;
-  begin
-    Result := ARow.Account;
-  end;
-
-  function GetAccounts(AccountNumbers: TArray<cardinal>): TArray<TAccount>;
-  var
-    acc: TAccount;
-    safeBox: TPCSafeBox;
-    keys: TOrderedAccountKeysList;
-    LContainer: Generics.Collections.TList<TAccount>;
-    i: integer;
-  begin
-    LContainer := Generics.Collections.TList<TAccount>.Create();
-    keys := TWallet.keys.AccountsKeyList;
-    safeBox := TUserInterface.Node.Bank.safeBox;
-    safeBox.StartThreadSafe;
-    try
-      LContainer.Clear;
-      try
-
-        // load selected user accounts
-        for i := 0 to High(AccountNumbers) do
-        begin
-          acc := safeBox.Account(AccountNumbers[i]);
-          if keys.IndexOfAccountKey(acc.accountInfo.accountKey) >= 0 then
-          begin
-            LContainer.Add(acc);
-          end;
-        end;
-      finally
-        safeBox.EndThreadSave;
-      end;
-      Result := LContainer.ToArray;
-    finally
-      LContainer.Free;
-    end;
-
-  end;
-
 var
   Scoped: TDisposables;
   wiz: TWIZSendPASCWizard;
@@ -592,37 +634,40 @@ begin
 end;
 
 procedure TCTRLWallet.miTransferAccountsClick(Sender: TObject);
-//var
-//  Scoped: TDisposables;
-//  wiz: TWIZTransferAccountWizard;
-//  model: TWIZTransferAccountModel;
-//  auxC: cardinal;
+var
+  Scoped: TDisposables;
+  wiz: TWIZTransferAccountWizard;
+  model: TWIZTransferAccountModel;
+  AccountNumbersWithoutChecksum: TArray<cardinal>;
 begin
-  //wiz := Scoped.AddObject(TWIZTransferAccountWizard.Create(nil)) as
-  //  TWIZTransferAccountWizard;
-  //model := Scoped.AddObject(TWIZTransferAccountModel.Create(nil)) as
-  //  TWIZTransferAccountModel;
-  //
-  //if not TAccountComp.AccountTxtNumberToAccountNumber(
-  //  FAccountsGrid.SelectedRows[0].Account, auxC) then
-  //begin
-  //  raise Exception.Create(
-  //    'Internal Error: Unable to parse account number from input');
-  //end;
-  //
-  //model.SelectedAccount := TNode.Node.Operations.SafeBoxTransaction.Account(auxC);
-  //wiz.Start(model);
+  wiz := Scoped.AddObject(TWIZTransferAccountWizard.Create(nil)) as
+    TWIZTransferAccountWizard;
+  model := Scoped.AddObject(TWIZTransferAccountModel.Create(nil)) as
+    TWIZTransferAccountModel;
+
+  AccountNumbersWithoutChecksum :=
+    TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows,
+    GetAccNoWithoutChecksum);
+
+  model.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
+  model.SelectedIndex := 0;
+  wiz.Start(model);
 end;
 
-procedure TCTRLWallet.OnPrepareOperationsPopupMenu(Sender: TObject; constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
+procedure TCTRLWallet.OnPrepareOperationsPopupMenu(Sender: TObject;
+  constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
 begin
-  if (ASelection.RowCount <> 1) OR ((ASelection.RowCount = 1) and (FOperationsGrid.SelectedRows[0].__KEY <> Variant(nil))) then begin
-    miSep2.Visible := true;
-    miOperationInfo.Visible := true;
+  if (ASelection.RowCount <> 1) or ((ASelection.RowCount = 1) and
+    (FOperationsGrid.SelectedRows[0].__KEY <> variant(nil))) then
+  begin
+    miSep2.Visible := True;
+    miOperationInfo.Visible := True;
     APopupMenu := mnuOperationsPopup;
-  end else begin
-    miSep2.Visible := false;
-    miOperationInfo.Visible := false;
+  end
+  else
+  begin
+    miSep2.Visible := False;
+    miOperationInfo.Visible := False;
     APopupMenu := nil; // is empty, so dont show
   end;
 end;

+ 0 - 1
src/gui/wizards/UWIZSendPASC.pas

@@ -62,7 +62,6 @@ uses
   UECIES,
   UAES,
   UWIZSendPASC_Start,
-  UWIZSendPASC_Transaction,
   UWIZSendPASC_Confirmation;
 
 { TWIZSendPASCWizard }

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

@@ -6,7 +6,6 @@ object WIZSendPASC_Confirmation: TWIZSendPASC_Confirmation
   Caption = 'WIZSendPASC_Confirmation'
   ClientHeight = 253
   ClientWidth = 429
-  LCLVersion = '1.8.1.0'
   Visible = False
   object GroupBox1: TGroupBox
     Left = 10

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

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

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

@@ -7,7 +7,6 @@ object WIZSendPASC_Transaction: TWIZSendPASC_Transaction
   Caption = 'WIZSendPASC_Transaction'
   ClientHeight = 253
   ClientWidth = 429
-  LCLVersion = '1.8.1.0'
   Visible = False
   object gbTransaction: TGroupBox
     Left = 22

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

@@ -7,6 +7,7 @@ object WIZSendPASC_TransactionPayload: TWIZSendPASC_TransactionPayload
   Caption = 'Form1'
   ClientHeight = 253
   ClientWidth = 429
+  LCLVersion = '1.8.1.0'
   Visible = False
   object grpPayload: TGroupBox
     Left = 8

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

@@ -14,7 +14,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections,
-  UWizard, UWIZSendPASC, UWIZSendPASC_Confirmation;
+  UWizard, UWIZSendPASC;
 
 type
 

+ 102 - 0
src/gui/wizards/UWIZTransferAccount.pas

@@ -0,0 +1,102 @@
+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, UWizard, UAccounts, LCLType;
+
+type
+
+  { TWIZTransferAccountModel }
+  TWIZPayloadEncryptionMode = (akaEncryptWithOldEC, akaEncryptWithEC,
+    akaEncryptWithPassword, akaNotEncrypt);
+
+  TWIZTransferAccountModel = class(TComponent)
+  public
+    DefaultFee: int64;
+    NewPublicKey, Payload, EncryptionPassword: string;
+    SelectedIndex: integer;
+    AccountKey: TAccountKey;
+    EncodedPayload: TRawBytes;
+    SignerAccount: TAccount;
+    SelectedAccounts, SortedAccounts: TArray<TAccount>;
+    PayloadEncryptionMode: TWIZPayloadEncryptionMode;
+  end;
+
+  { TWIZTransferAccountWizard }
+
+  TWIZTransferAccountWizard = class(TWizard<TWIZTransferAccountModel>)
+    // private
+    //procedure TransferAccount();
+  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 }
+
+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
+  raise ENotImplemented.Create('Not yet implemented.');
+  //try
+  //  Result := True;
+  //  // TransferAccount();
+  //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.

+ 47 - 0
src/gui/wizards/UWIZTransferAccount_Confirmation.lfm

@@ -0,0 +1,47 @@
+object WIZTransferAccount_Confirmation: TWIZTransferAccount_Confirmation
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  Caption = 'WIZTransferAccount_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 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/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;
+
+type
+
+  { TWIZTransferAccount_Confirmation }
+
+  TWIZTransferAccount_Confirmation = class(TWizardForm<TWIZTransferAccountModel>)
+    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 : TWIZTransferAccountModel;
+    protected
+      function GetColumns : TDataColumns; override;
+    public
+      property Model : TWIZTransferAccountModel 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;
+   FSendersGrid.DataSource := data;
+   paGrid.AddControlDockCenter(FSendersGrid);
+   lblSgnAcc.Caption := TAccountComp.AccountNumberToAccountTxtNumber(Model.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.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.SortedAccounts) to High(Model.SortedAccounts) do
+  begin
+    AContainer.Add( Model.SortedAccounts[i] );
+  end;
+end;
+
+
+end.
+

+ 31 - 0
src/gui/wizards/UWIZTransferAccount_Start.lfm

@@ -0,0 +1,31 @@
+object WIZTransferAccount_Start: TWIZTransferAccount_Start
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  Caption = 'WIZTransferAccount_Start'
+  ClientHeight = 253
+  ClientWidth = 429
+  Visible = False
+  object grpTransferAccount: TGroupBox
+    Left = 6
+    Height = 248
+    Top = 0
+    Width = 416
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    Caption = 'Transfer Accounts'
+    ClientHeight = 228
+    ClientWidth = 412
+    TabOrder = 0
+    object paGrid: TPanel
+      Left = 6
+      Height = 200
+      Top = 24
+      Width = 402
+      Anchors = [akTop, akLeft, akRight, akBottom]
+      BevelOuter = bvNone
+      Caption = 'GRID PANEL'
+      TabOrder = 0
+    end
+  end
+end

+ 110 - 0
src/gui/wizards/UWIZTransferAccount_Start.pas

@@ -0,0 +1,110 @@
+unit UWIZTransferAccount_Start;
+
+{$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, UCommon.Data, UCellRenderers,
+  UWizard, UWIZTransferAccount, UWIZTransferAccount_Transaction, UWIZSendPASC_Confirmation;
+
+type
+
+  { TWIZTransferAccount_Start }
+
+  TWIZTransferAccount_Start = class(TWizardForm<TWIZTransferAccountModel>)
+    grpTransferAccount: TGroupBox;
+    paGrid: TPanel;
+  private
+    FSendersGrid: TVisualGrid;
+  public
+    procedure OnPresent; override;
+    procedure OnNext; override;
+  end;
+
+
+
+implementation
+
+{$R *.lfm}
+
+uses UAccounts, USettings, UDataSources, UCommon, UCommon.UI, Generics.Collections;
+
+type
+
+  { TAccountSenderDataSource }
+
+  TAccountSenderDataSource = class(TAccountsDataSourceBase)
+  private
+    FModel: TWIZTransferAccountModel;
+  public
+    property Model: TWIZTransferAccountModel read FModel write FModel;
+    procedure FetchAll(const AContainer: TList<TAccount>); override;
+  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;
+
+{ TWIZTransferAccount_Start }
+
+procedure TWIZTransferAccount_Start.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
+    StretchedToFill := True;
+    Binding := 'AccountNumber';
+    SortBinding := 'AccountNumber';
+    DisplayBinding := 'Account';
+    Width := 100;
+    HeaderFontStyles := [fsBold];
+    DataFontStyles := [fsBold];
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FSendersGrid.AddColumn('Balance') do
+  begin
+    Binding := 'BalanceDecimal';
+    SortBinding := 'Balance';
+    DisplayBinding := 'Balance';
+    Width := 100;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
+    Renderer := TCellRenderers.PASC;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  Data := TAccountSenderDataSource.Create(FSendersGrid);
+  Data.Model := Model;
+  FSendersGrid.DataSource := Data;
+  paGrid.AddControlDockCenter(FSendersGrid);
+end;
+
+procedure TWIZTransferAccount_Start.OnNext;
+begin
+   UpdatePath(ptReplaceAllNext, [TWIZTransferAccount_Transaction, TWIZSendPASC_Confirmation]);
+end;
+
+end.

+ 92 - 0
src/gui/wizards/UWIZTransferAccount_Transaction.lfm

@@ -0,0 +1,92 @@
+object WIZTransferAccount_Transaction: TWIZTransferAccount_Transaction
+  Left = 0
+  Height = 253
+  Top = 0
+  Width = 429
+  ActiveControl = cbSignerAccount
+  Caption = 'WIZTransferAccount_Transaction'
+  ClientHeight = 253
+  ClientWidth = 429
+  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

+ 151 - 0
src/gui/wizards/UWIZTransferAccount_Transaction.pas

@@ -0,0 +1,151 @@
+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;
+
+type
+
+  { TWIZTransferAccount_Transaction }
+
+  TWIZTransferAccount_Transaction = class(TWizardForm<TWIZTransferAccountModel>)
+    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.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.SelectedAccounts) to High(Model.SelectedAccounts) do
+    begin
+      acc := Model.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.SelectedIndex;
+  cbSignerAccountChange(Self);
+  lblTotalBalanceValue.Caption :=
+    Format('%s PASC', [TAccountComp.FormatMoney(totalBalance)]);
+
+  edtOpFee.Text := TAccountComp.FormatMoney(TSettings.DefaultFee);
+end;
+
+procedure TWIZTransferAccount_Transaction.OnNext;
+begin
+  Model.SelectedIndex := cbSignerAccount.ItemIndex;
+  Model.SignerAccount := Model.SelectedAccounts[PtrInt(
+    cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
+  Model.NewPublicKey := Trim(edtPublicKey.Text);
+  // make a deep copy
+  Model.SortedAccounts := Copy(Model.SelectedAccounts);
+  // must ensure that Signer account is last in the new array according version 2 protocol
+  TArrayTool<TAccount>.MoveItem(Model.SortedAccounts,
+    TArrayTool<TAccount>.IndexOf(Model.SortedAccounts, Model.SignerAccount),
+    High(Model.SortedAccounts));
+  UpdatePath(ptReplaceAllNext, [TWIZTransferAccount_TransactionPayload,
+    TWIZTransferAccount_Confirmation]);
+end;
+
+function TWIZTransferAccount_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 not TAccountComp.TxtToMoney(Trim(edtOpFee.Text), Model.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.

+ 98 - 0
src/gui/wizards/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 = 227
+        Caption = 'Encrypted with dest account 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/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;
+
+type
+
+  { TWIZTransferAccount_TransactionPayload }
+
+  TWIZTransferAccount_TransactionPayload = class(TWizardForm<TWIZTransferAccountModel>)
+    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 := mmoPayload.Lines.Text;
+  if rbEncryptedWithOldEC.Checked then
+  begin
+    Model.PayloadEncryptionMode := akaEncryptWithOldEC;
+  end
+  else
+  if rbEncryptedWithEC.Checked then
+  begin
+    Model.PayloadEncryptionMode := akaEncryptWithEC;
+  end
+  else
+  if rbEncryptedWithPassword.Checked then
+  begin
+    Model.PayloadEncryptionMode := akaEncryptWithPassword;
+  end
+  else
+  if rbNotEncrypted.Checked then
+  begin
+    Model.PayloadEncryptionMode := 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.

+ 33 - 1
src/pascalcoin_wallet.lpi

@@ -33,7 +33,7 @@
         <PackageName Value="LCL"/>
       </Item1>
     </RequiredPackages>
-    <Units Count="78">
+    <Units Count="83">
       <Unit0>
         <Filename Value="pascalcoin_wallet.dpr"/>
         <IsPartOfProject Value="True"/>
@@ -435,6 +435,38 @@
         <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
       </Unit77>
+      <Unit78>
+        <Filename Value="gui\wizards\UWIZTransferAccount.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit78>
+      <Unit79>
+        <Filename Value="gui\wizards\UWIZTransferAccount_Start.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZTransferAccount_Start"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit79>
+      <Unit80>
+        <Filename Value="gui\wizards\UWIZTransferAccount_Transaction.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZTransferAccount_Transaction"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit80>
+      <Unit81>
+        <Filename Value="gui\wizards\UWIZTransferAccount_Confirmation.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZTransferAccount_Confirmation"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit81>
+      <Unit82>
+        <Filename Value="gui\wizards\UWIZTransferAccount_TransactionPayload.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZTransferAccount_TransactionPayload"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit82>
     </Units>
   </ProjectOptions>
   <CompilerOptions>