Browse Source

Add: New Account Explorer

Ugochukwu Mmaduekwe 7 years ago
parent
commit
ef294a4327
4 changed files with 933 additions and 1078 deletions
  1. 4 1
      src/core.utils/UDataSources.pas
  2. 194 493
      src/gui/UFRMAccountExplorer.lfm
  3. 733 582
      src/gui/UFRMAccountExplorer.pas
  4. 2 2
      src/gui/UUserInterface.pas

+ 4 - 1
src/core.utils/UDataSources.pas

@@ -380,7 +380,8 @@ begin
     TDataColumn.From('State'),
     TDataColumn.From('Price'),
     TDataColumn.From('PriceDecimal'),
-    TDataColumn.From('LockedUntil')
+    TDataColumn.From('LockedUntil'),
+    TDataColumn.From('NumberOfOperations')
     );
 end;
 
@@ -412,6 +413,8 @@ begin
     Result := TAccountComp.FormatMoneyDecimal(AItem.accountInfo.price)
   else if ABindingName = 'LockedUntil' then
     Result := AItem.accountInfo.locked_until_block
+  else if ABindingName = 'NumberOfOperations' then
+    Result := AItem.n_operation
   else
     raise Exception.Create(Format('Field not found "%s"', [ABindingName]));
 end;

+ 194 - 493
src/gui/UFRMAccountExplorer.lfm

@@ -1,528 +1,229 @@
 object FRMAccountExplorer: TFRMAccountExplorer
-  Left = 207
-  Height = 451
-  Top = 94
-  Width = 868
-  ActiveControl = cbMyPrivateKeys
-  Caption = 'Accounts Explorer'
-  ClientHeight = 451
-  ClientWidth = 868
-  FormStyle = fsMDIChild
-  Menu = meAccountExplorerMenu
+  Left = -7
+  Height = 459
+  Top = 2
+  Width = 926
+  ActiveControl = chkExploreMyAccounts
+  Caption = 'Account Explorer'
+  ClientHeight = 459
+  ClientWidth = 926
   OnCreate = FormCreate
-  OnDestroy = FormDestroy
+  OnResize = FormResize
   Position = poOwnerFormCenter
-  LCLVersion = '1.8.2.0'
   Visible = False
-  object Splitter1: TSplitter
-    Left = 380
-    Height = 365
-    Top = 66
-    Width = 5
-  end
-  object pnlMyAccountsTop: TPanel
+  object PairSplitter1: TPairSplitter
     Left = 0
-    Height = 66
+    Height = 459
     Top = 0
-    Width = 868
-    Align = alTop
-    BevelOuter = bvNone
-    ClientHeight = 66
-    ClientWidth = 868
-    TabOrder = 0
-    object Label18: TLabel
-      Left = 11
-      Height = 15
-      Top = 40
-      Width = 69
-      Caption = 'Find account'
-      ParentColor = False
-    end
-    object cbMyPrivateKeys: TComboBox
-      Left = 308
-      Height = 23
-      Top = 5
-      Width = 411
-      ItemHeight = 15
-      OnChange = cbMyPrivateKeysChange
-      Style = csDropDownList
-      TabOrder = 0
-    end
-    object cbExploreMyAccounts: TCheckBox
-      Left = 11
-      Height = 19
-      Top = 9
-      Width = 255
-      Caption = 'Explore accounts with one of my Wallet Keys'
-      OnChange = cbExploreMyAccountsChange
-      TabOrder = 1
-    end
-    object ebFindAccountNumber: TEdit
-      Left = 95
-      Height = 23
-      Top = 33
-      Width = 83
-      OnChange = ebFindAccountNumberChange
-      OnExit = ebFindAccountNumberExit
-      TabOrder = 3
-    end
-    object bbChangeKeyName: TBitBtn
-      Left = 733
-      Height = 25
-      Top = 5
-      Width = 126
-      Caption = 'Change Key name'
-      OnClick = bbChangeKeyNameClick
-      TabOrder = 2
-    end
-    object cbFilterAccounts: TCheckBox
-      Left = 308
-      Height = 19
-      Top = 35
-      Width = 157
-      Caption = 'Filter accounts by balance'
-      OnChange = cbFilterAccountsChange
-      TabOrder = 4
-    end
-    object ebFilterAccountByBalanceMin: TEdit
-      Left = 472
-      Height = 23
-      Hint = 'Min balance'
-      Top = 33
-      Width = 83
-      OnExit = ebFilterAccountByBalanceMinExit
-      OnKeyPress = ebFilterAccountByBalanceMinKeyPress
-      TabOrder = 5
-    end
-    object ebFilterAccountByBalanceMax: TEdit
-      Left = 568
-      Height = 23
-      Hint = 'Max balance'
-      Top = 33
-      Width = 83
-      OnExit = ebFilterAccountByBalanceMinExit
-      OnKeyPress = ebFilterAccountByBalanceMinKeyPress
-      TabOrder = 6
-    end
-    object sbSearchAccount: TSpeedButton
-      Left = 184
-      Height = 23
-      Top = 33
-      Width = 24
-      Glyph.Data = {
-        36030000424D3803000000000000360000002800000010000000100000000100
-        18000000000000000000120B0000120B00000000000000000000FF00FF4A667C
-        BE9596FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-        FFFF00FFFF00FFFF00FF6B9CC31E89E84B7AA3C89693FF00FFFF00FFFF00FFFF
-        00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF4BB4FE51B5FF
-        2089E94B7AA2C69592FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-        FFFF00FFFF00FFFF00FFFF00FF51B7FE51B3FF1D87E64E7AA0CA9792FF00FFFF
-        00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-        51B7FE4EB2FF1F89E64E7BA2B99497FF00FFFF00FFFF00FFFF00FFFF00FFFF00
-        FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF52B8FE4BB1FF2787D95F6A76FF
-        00FFB0857FC09F94C09F96BC988EFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-        FF00FFFF00FF55BDFFB5D6EDBF9D92BB9B8CE7DAC2FFFFE3FFFFE5FDFADAD8C3
-        B3B58D85FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFCEA795FD
-        EEBEFFFFD8FFFFDAFFFFDBFFFFE6FFFFFBEADDDCAE837FFF00FFFF00FFFF00FF
-        FF00FFFF00FFFF00FFFF00FFC1A091FBDCA8FEF7D0FFFFDBFFFFE3FFFFF8FFFF
-        FDFFFFFDC6A99CFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC1A091FEE3ACF1
-        C491FCF2CAFFFFDDFFFFE4FFFFF7FFFFF7FFFFE9EEE5CBB9948CFF00FFFF00FF
-        FF00FFFF00FFFF00FFC2A191FFE6AEEEB581F7DCAEFEFDD8FFFFDFFFFFE3FFFF
-        E4FFFFE0F3ECD2BB968EFF00FFFF00FFFF00FFFF00FFFF00FFBC978CFBE7B7F4
-        C791F2C994F8E5B9FEFCD8FFFFDDFFFFDCFFFFE0E2D2BAB68E86FF00FFFF00FF
-        FF00FFFF00FFFF00FFFF00FFD9C3A9FFFEE5F7DCB8F2C994F5D4A5FAE8BDFDF4
-        C9FDFBD6B69089FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB58D85E8
-        DEDDFFFEF2F9D8A3F4C48CF9D49FFDEAB8D0B49FB89086FF00FFFF00FFFF00FF
-        FF00FFFF00FFFF00FFFF00FFFF00FFAD827FC9AA9EEFE0B7EFDFB2E7CEACB890
-        86B89086FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-        00FFFF00FFBA968ABB988CB79188FF00FFFF00FFFF00FFFF00FF
-      }
-      OnClick = sbSearchAccountClick
-    end
-  end
-  object pnlAccounts: TPanel
-    Left = 0
-    Height = 365
-    Top = 66
-    Width = 380
-    Align = alLeft
-    BevelOuter = bvNone
-    ClientHeight = 365
-    ClientWidth = 380
-    TabOrder = 1
-    object dgAccounts: TDrawGrid
+    Width = 926
+    Align = alClient
+    Position = 500
+    object PairSplitterSide1: TPairSplitterSide
+      Cursor = crArrow
       Left = 0
-      Height = 331
+      Height = 459
       Top = 0
-      Width = 380
-      Align = alClient
-      ExtendedSelect = False
-      TabOrder = 0
-      TitleFont.Color = clWindowText
-      TitleFont.Height = -11
-      TitleFont.Name = 'Tahoma'
-      OnClick = dgAccountsClick
-    end
-    object pnlAccountsInfo: TPanel
-      Left = 0
-      Height = 34
-      Top = 331
-      Width = 380
-      Align = alBottom
-      BevelOuter = bvNone
-      ClientHeight = 34
-      ClientWidth = 380
-      TabOrder = 1
-      object Label17: TLabel
-        Left = 5
-        Height = 15
-        Top = 10
-        Width = 53
-        Caption = 'Accounts:'
-        ParentColor = False
-      end
-      object Label19: TLabel
-        Left = 136
-        Height = 15
-        Top = 10
-        Width = 44
-        Caption = 'Balance:'
-        ParentColor = False
-      end
-      object lblAccountsCount: TLabel
-        Left = 60
-        Height = 15
-        Top = 10
-        Width = 18
-        Caption = '000'
-        ParentColor = False
-      end
-      object lblAccountsBalance: TLabel
-        Left = 200
-        Height = 15
-        Top = 10
-        Width = 18
-        Caption = '000'
-        ParentColor = False
-      end
-      object bbAccountsRefresh: TBitBtn
-        Left = 302
-        Height = 25
-        Top = 6
-        Width = 75
-        Anchors = [akTop, akRight]
-        Caption = 'Refresh'
-        Glyph.Data = {
-          36030000424D3603000000000000360000002800000010000000100000000100
-          18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF
-          C2A6A4C2A6A4C2A6A4C2A6A4C2A6A4C2A6A4C2A6A4C2A6A4C2A6A4C2A6A4C2A6
-          A4C2A6A4FF00FFFF00FFFF00FFFF00FFC2A6A4FEFCFBFEFCFBFEFCFBFEFCFBFE
-          FCFBFEFCFBFEFCFBFEFCFBFEFCFBFEFCFBC2A6A4FF00FFFF00FFFF00FFFF00FF
-          C2A6A4FEFCFBFEFCFBFEFCFBFEFCFBD8EBD6018A02018A02D8EBD6FEFCFBFEFC
-          FBC2A6A4FF00FFFF00FFFF00FFFF00FFC2A6A4FEFBF7FEFBF7018A02D8EAD201
-          8A02D8EAD2D8EAD2018A02FEFBF7FEFBF7C2A6A4FF00FFFF00FFFF00FFFF00FF
-          C2A6A4FEF9F4FEF9F4018A02018A02D8E8D0FEF9F4FEF9F4D8E8D0FEF9F4FEF9
-          F4C2A6A4FF00FFFF00FFFF00FFFF00FFC2A6A4FEF7F0FEF7F0018A02018A0201
-          8A02FEF7F0FEF7F0FEF7F0FEF7F0FEF7F0C2A6A4FF00FFFF00FFFF00FFFF00FF
-          C2A6A4FEF5ECFEF5ECFEF5ECFEF5ECFEF5EC018A02018A02018A02FEF5ECFEF5
-          ECC2A6A4FF00FFFF00FFFF00FFFF00FFC2A6A4FEF3E9FEF3E9D8E3C7FEF3E9FE
-          F3E9D8E3C7018A02018A02FEF3E9FEF3E9C2A6A4FF00FFFF00FFFF00FFFF00FF
-          C2A6A4FFF1E5FFF1E5018A02D9E2C3D9E2C3018A02D9E2C3018A02FFF1E5FFF1
-          E5C2A6A4FF00FFFF00FFFF00FFFF00FFC2A6A4FFF0E2FFF0E2D9E1C1018A0201
-          8A02D9E1C1DDCFC2DDCFC2DDCFC2DDCFC2C2A6A4FF00FFFF00FFFF00FFFF00FF
-          C2A6A4FFEEDEFFEEDEFFEEDEFFEEDEFFEEDEFFEEDEC5B5A9C3B4A8C2B3A7C1B2
-          A6C2A6A4FF00FFFF00FFFF00FFFF00FFC2A6A4FFECDAFFECDAFFECDAFFECDAFF
-          ECDAFFECDAB0A296B0A296B0A296B0A296C2A6A4FF00FFFF00FFFF00FFFF00FF
-          C2A6A4FFEAD7FFEAD7FFEAD7FFEAD7FFEAD7C9B9ACFBF8F4FBF8F4E6DAD9C2A6
-          A4FF00FFFF00FFFF00FFFF00FFFF00FFC2A6A4FFE8D3FFE8D3FFE8D3FFE8D3FF
-          E8D3C9B9ACFBF8F4DFCEC7C2A6A4FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-          C2A6A4FFE6D0FFE6D0FFE6D0FFE6D0FFE6D0C9B9ACDFCEC7C2A6A4FF00FFFF00
-          FFFF00FFFF00FFFF00FFFF00FFFF00FFC2A6A4C2A6A4C2A6A4C2A6A4C2A6A4C2
-          A6A4C2A6A4C2A6A4FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-        }
-        OnClick = bbAccountsRefreshClick
+      Width = 500
+      ClientWidth = 500
+      ClientHeight = 459
+      object GroupBox1: TGroupBox
+        Left = 8
+        Height = 89
+        Top = 8
+        Width = 484
+        Anchors = [akTop, akLeft, akRight]
+        Caption = 'Overview'
+        ClientHeight = 69
+        ClientWidth = 480
         TabOrder = 0
-      end
-    end
-  end
-  object pcAccountsOptions: TPageControl
-    Left = 385
-    Height = 365
-    Top = 66
-    Width = 483
-    ActivePage = tsMultiSelectAccounts
-    Align = alClient
-    TabIndex = 1
-    TabOrder = 2
-    object tsAccountOperations: TTabSheet
-      Caption = 'Operations of selected Account'
-      ClientHeight = 355
-      ClientWidth = 470
-      object dgAccountOperations: TDrawGrid
-        Left = 0
-        Height = 355
-        Top = 0
-        Width = 470
-        Align = alClient
-        ExtendedSelect = False
-        TabOrder = 0
-        TitleFont.Color = clWindowText
-        TitleFont.Height = -11
-        TitleFont.Name = 'Tahoma'
-        OnClick = dgAccountOperationsClick
-        OnDblClick = dgAccountOperationsClick
-      end
-    end
-    object tsMultiSelectAccounts: TTabSheet
-      Caption = 'Selected accounts for massive operations'
-      ClientHeight = 337
-      ClientWidth = 475
-      ImageIndex = 1
-      object dgSelectedAccounts: TDrawGrid
-        Left = 41
-        Height = 280
-        Top = 31
-        Width = 325
-        Align = alLeft
-        Anchors = [akTop, akLeft, akRight, akBottom]
-        ExtendedSelect = False
-        TabOrder = 0
-        TitleFont.Color = clWindowText
-        TitleFont.Height = -11
-        TitleFont.Name = 'Tahoma'
-      end
-      object pnlSelectedAccountsTop: TPanel
-        Left = 0
-        Height = 31
-        Top = 0
-        Width = 475
-        Align = alTop
-        BevelOuter = bvNone
-        ClientHeight = 31
-        ClientWidth = 475
-        Font.Color = clWindowText
-        Font.Height = -13
-        Font.Name = 'Tahoma'
-        Font.Style = [fsBold]
-        ParentFont = False
-        TabOrder = 1
-        object Label15: TLabel
-          Left = 41
-          Height = 16
-          Top = 4
-          Width = 361
-          Caption = 'Select multiple accounts to execute massive operations'
-          ParentColor = False
-        end
-      end
-      object pnlSelectedAccountsBottom: TPanel
-        Left = 0
-        Height = 26
-        Top = 311
-        Width = 475
-        Align = alBottom
-        BevelOuter = bvNone
-        ClientHeight = 26
-        ClientWidth = 475
-        TabOrder = 2
-        object Label20: TLabel
-          Left = 41
+        object Label1: TLabel
+          Left = 16
           Height = 15
-          Top = 6
-          Width = 53
-          Caption = 'Accounts:'
+          Top = 8
+          Width = 58
+          Caption = 'Total PASC'
+          Font.Style = [fsBold]
           ParentColor = False
+          ParentFont = False
         end
-        object lblSelectedAccountsCount: TLabel
-          Left = 96
+        object Label2: TLabel
+          Left = 16
           Height = 15
-          Top = 6
-          Width = 18
-          Caption = '000'
+          Top = 40
+          Width = 59
+          Caption = 'Total PASA'
+          Font.Style = [fsBold]
           ParentColor = False
+          ParentFont = False
         end
-        object Label22: TLabel
-          Left = 156
+        object lblTotalPASA: TLabel
+          Left = 360
           Height = 15
-          Top = 6
-          Width = 97
-          Caption = 'Accounts Balance:'
+          Top = 40
+          Width = 108
+          Alignment = taRightJustify
+          Anchors = [akTop, akRight]
+          AutoSize = False
+          Caption = '0'
+          Font.Style = [fsBold]
           ParentColor = False
+          ParentFont = False
         end
-        object lblSelectedAccountsBalance: TLabel
-          Left = 250
+        object lblTotalPASC: TLabel
+          Left = 360
           Height = 15
-          Top = 6
-          Width = 18
-          Caption = '000'
+          Top = 8
+          Width = 106
+          Alignment = taRightJustify
+          Anchors = [akTop, akRight]
+          AutoSize = False
+          Caption = '0'
+          Font.Style = [fsBold]
           ParentColor = False
+          ParentFont = False
         end
       end
-      object pnlSelectedAccountsLeft: TPanel
-        Left = 0
-        Height = 280
-        Top = 31
-        Width = 41
-        Align = alLeft
-        BevelOuter = bvNone
-        ClientHeight = 280
-        ClientWidth = 41
-        TabOrder = 3
-        object sbSelectedAccountsAdd: TSpeedButton
-          Left = 2
-          Height = 31
-          Top = 0
-          Width = 33
-          Caption = '>'
-          OnClick = sbSelectedAccountsAddClick
+      object gpAccounts: TGroupBox
+        Left = 8
+        Height = 344
+        Top = 104
+        Width = 484
+        Anchors = [akTop, akLeft, akRight, akBottom]
+        Caption = 'Accounts'
+        ClientHeight = 324
+        ClientWidth = 480
+        TabOrder = 1
+        object paAccounts: TPanel
+          Left = 8
+          Height = 240
+          Top = 80
+          Width = 460
+          Anchors = [akTop, akLeft, akRight, akBottom]
+          BorderSpacing.Around = 3
+          BevelOuter = bvNone
+          Caption = 'MY ACCOUNT PANEL'
+          ParentColor = False
+          TabOrder = 0
         end
-        object sbSelectedAccountsAddAll: TSpeedButton
-          Left = 2
-          Height = 31
-          Top = 37
-          Width = 33
-          Caption = '>>'
-          OnClick = sbSelectedAccountsAddAllClick
+        object chkExploreMyAccounts: TCheckBox
+          Left = 8
+          Height = 19
+          Top = 8
+          Width = 243
+          Caption = 'Explore Only Accounts With Keys In Wallet'
+          Checked = True
+          OnChange = chkExploreMyAccountsChange
+          State = cbChecked
+          TabOrder = 1
         end
-        object sbSelectedAccountsDel: TSpeedButton
-          Left = 2
-          Height = 31
-          Top = 74
-          Width = 33
-          Caption = '<'
-          OnClick = sbSelectedAccountsDelClick
+        object cbAccounts: TComboBox
+          Left = 8
+          Height = 23
+          Top = 40
+          Width = 336
+          ItemHeight = 15
+          ItemIndex = 0
+          Items.Strings = (
+            'Show All'
+            'Show non-zero balances'
+            'Get my first account!'
+          )
+          OnChange = cbAccountsChange
+          Style = csDropDownList
+          TabOrder = 2
+          Text = 'Show All'
         end
-        object sbSelectedAccountsDelAll: TSpeedButton
-          Left = 2
-          Height = 31
-          Top = 111
-          Width = 33
-          Caption = '<<'
-          OnClick = sbSelectedAccountsDelAllClick
+        object btnChangeKeyName: TBitBtn
+          Left = 352
+          Height = 30
+          Top = 36
+          Width = 116
+          Caption = 'Change Key Name'
+          OnClick = btnChangeKeyNameClick
+          TabOrder = 3
         end
       end
-      object bbSelectedAccountsOperation: TBitBtn
-        Left = 372
-        Height = 61
-        Top = 31
-        Width = 75
-        Anchors = [akTop, akRight]
-        Caption = 'Operations'
-        Glyph.Data = {
-          F6060000424DF606000000000000360000002800000018000000180000000100
-          180000000000C0060000120B0000120B00000000000000000000FF00FFFF00FF
-          FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
-          FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-          00FFFF00FFFF00FF019ACF019ACF019ACF019ACFFF00FFFF00FFFF00FFFF00FF
-          FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C8518FF00FFFF00FFFF00FFFF00
-          FFFF00FFFF00FFFF00FFFF00FF0D9FD18BD4EE6BD3F845C0ED28B0E0019ACF01
-          9ACF019ACF019ACFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF0C85180C8518
-          FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF069CD076C8E5A9E9FE6DD8
-          FF75DBFF77DCFF77DBFF63D1F930B3E3029BD0019ACF019ACF019ACF019ACFFF
-          00FF0C85181399220C8518FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF019ACF
-          34AFD9BCE9F86ED8FF6FD8FE70D8FE70D8FE71D8FF0C85180C85180C85180C85
-          180C85180C85180C85180C85181DAC31139A220C8518FF00FFFF00FFFF00FFFF
-          00FFFF00FF019ACF1FA9D68FD3EB97E4FF6FD9FE71D9FE71D9FE71D9FE0C8518
-          57E38851DD7E4AD77443D0693BC95E34C1522BBA4725B33C1EAE33149B230C85
-          18FF00FFFF00FFFF00FFFF00FF019ACF31B1DC49B7DEBDEEFB71DDFE77DEFE77
-          DEFE77DEFE0C85185EE89059E48953DE804CD87645D16C3DCA6035C2542DBB49
-          26B53F1FAF35149B250C8518FF00FFFF00FFFF00FF019ACF52C2E71DA7D5ADE2
-          F38FE8FF7CE2FE7CE3FE7CE3FE0C851861EB955FE9925AE58B54DF824DD97846
-          D26D3ECB6237C4562FBD4C27B64021B037159B250C8518FF00FFFF00FF019ACF
-          60CAEF1FA8D85EC1E1C2E6ED8ACEE08FCFE18ECFE10C851861EB9561EB955FEA
-          935CE58D56E0844FDB7A48D47040CD6538C65931BF4D1DA3320C8518FF00FFFF
-          00FFFF00FF019ACF65CFF53EB7E52CA9D4C5EFF8ACF3FEA5F2FFA5F2FF0C8518
-          61EB9561EB9561EB9561EB945CE68E57E18650DC7C49D57242CE6727AD410C85
-          18FF00FFFF00FFFF00FFFF00FF019ACF69D1F855C4F32A9CC673CBE7D6FEFDB1
-          FBFDB2FBFD0C85180C85180C85180C85180C85180C85180C85180C851852DD7F
-          32B6500C851898FAFF019ACFFF00FFFF00FFFF00FF019ACF77D5FC5CC8FB748E
-          A224A8D5B9E7F3D5F5F9D5F6F9D6F6FADCFAFBCDFDFCB9FCFCAFFAFCB0FAFCB1
-          FAFC0C85183ABE5C0C85189FFCFFA4FFFF43C1E2019ACFFF00FFFF00FF019ACF
-          8BDBFF5FCDFFB7898973C3DD18A2D218A2D216A2D215A1D21AA4D391D7EBEBFE
-          FDDBFDFCC5FBFBC2FBFB0C85180C851883E4F3B6FDFFBAFFFFB5FCFD019ACFFF
-          00FFFF00FF019ACF99E2FF67D3FFB88989FEF5ECFDF3EBF0EFEAE5EBE8D6E5E6
-          A4D2E025A6D34DB9DDE5F8FBF5FDFCEBFCFB0C8518C4FBFF9CE4F2DAFEFFD9FE
-          FFE3FFFFADE9F5019ACFFF00FF019ACF9FE9FF70DCFFB88989FEF3E9FFF2E6FE
-          F3E9FEF3E9FEF3E9FEF3E9D4E4E439ADD422A5D49DD8ECF1F9FBEEEFEFE9FDFF
-          CEEEF7F8FFFFF7FFFFFEFFFFE9F9FD019ACFFF00FF019ACFA7EFFF76E5FFB889
-          89FFF2E5FFF0E2FFF2E5FFF2E5FFF2E5FFF2E5FFF2E5EAEBE38EC9DA44B0D501
-          9ACF019ACF019ACF019ACF019ACF019ACF019ACF019ACF019ACFFF00FF019ACF
-          ABF6FF7EEDFFB88989FFF0E2FFEFDFFFF0E2FFF0E2FFF0E2FFF0E2FFF0E2FEEE
-          E0FBECDEFAEBDEF6E6D9B8898993F7FF019ACFFF00FFFF00FFFF00FFFF00FFFF
-          00FFFF00FF019ACFC7FFFF82F5FFB88989FFEEDFFFECDBFFEEDFFFEEDFFFEEDF
-          FFEEDFF9E8D9DECCC1D9CABDCFBDB4C8B3ACB88989B5FFFF019ACFFF00FFFF00
-          FFFF00FFFF00FFFF00FFFF00FF019ACFA4E0F0A0FDFFB88989FFECDBFFEBD8FF
-          ECDBFFECDBFFECDBFFECDBF5E2D2C4ABA7C2A8A5BBA39FC2AFA9B88989019ACF
-          FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF019ACFECFFFFB889
-          89FFEBD8FFEAD5FFEBD8FFEBD8FFEBD8FFEBD8FFEBD8D9C8C5FEFEFDFEF6EFDE
-          C9C0B88989FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-          FF00FF019ACFB88989FFE9D5FFE8D3FFE9D5FFE9D5FFE9D5FFE9D5FFE9D5C6AD
-          A9FEF8F2E8D4CACD9999FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
-          00FFFF00FFFF00FFFF00FFFF00FFB88989FFE7D1FFE7D0FFE7D1FFE7D1FFE7D1
-          FFE7D1E7CEBFD3BFB9E8D5CCCD9999FF00FFFF00FFFF00FFFF00FFFF00FFFF00
-          FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB88989FFE6CFFFE6CFFF
-          E6CFFFE6CFFFE6CFFFE6CFD5BBB2E0CCC5CD9999FF00FFFF00FFFF00FFFF00FF
-          FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB889
-          89B88989B88989B88989B88989B88989B88989B88989B88989FF00FFFF00FFFF
-          00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
-        }
-        Layout = blGlyphTop
-        OnClick = bbSelectedAccountsOperationClick
-        TabOrder = 4
+    end
+    object PairSplitterSide2: TPairSplitterSide
+      Cursor = crArrow
+      Left = 505
+      Height = 459
+      Top = 0
+      Width = 421
+      ClientWidth = 421
+      ClientHeight = 459
+      object gpRecentOps: TGroupBox
+        Left = 8
+        Height = 440
+        Top = 8
+        Width = 411
+        Anchors = [akTop, akLeft, akRight, akBottom]
+        Caption = 'Recent Operations'
+        ClientHeight = 420
+        ClientWidth = 407
+        TabOrder = 0
+        object paOperations: TPanel
+          Left = 8
+          Height = 400
+          Top = 16
+          Width = 395
+          Anchors = [akTop, akLeft, akRight, akBottom]
+          BorderSpacing.Around = 3
+          BevelOuter = bvNone
+          Caption = 'OPERATIONS PANEL'
+          ParentColor = False
+          TabOrder = 0
+        end
       end
     end
   end
-  object meAccountExplorerMenu: TMainMenu
-    left = 240
-    top = 16
-    object miTools: TMenuItem
-      Caption = 'Tools'
-      object miNewOperation: TMenuItem
-        Caption = 'New Operation'
-        OnClick = miNewOperationClick
-      end
-      object miDecodePayload: TMenuItem
-        Caption = 'Decode Payload'
-        OnClick = miDecodePayloadClick
-      end
-      object N1: TMenuItem
-        Caption = '-'
-      end
-      object miFindAccount: TMenuItem
-        Caption = 'Find account'
-        ShortCut = 16454
-      end
-      object miAccountInformation: TMenuItem
-        Caption = 'Account Information'
-        ShortCut = 112
-        OnClick = MiAccountInformationClick
-      end
-      object N2: TMenuItem
-        Caption = '-'
-      end
-      object miAddAccountToSelected: TMenuItem
-        Caption = 'Add account to selected'
-        ShortCut = 117
-        OnClick = miAddAccountToSelectedClick
-      end
-      object miRemoveAccountFromSelected: TMenuItem
-        Caption = 'Remove account from selected'
-        ShortCut = 118
-        OnClick = miRemoveAccountFromSelectedClick
-      end
-      object N3: TMenuItem
-        Caption = '-'
-      end
-      object miFindPreviousAccountWithHighBalance: TMenuItem
-        Caption = 'Find previous account with high balance'
-        ShortCut = 16498
-        OnClick = miFindPreviousAccountWithHighBalanceClick
+  object mnuAccountsPopup: TPopupMenu
+    left = 768
+    top = 64
+    object miSendPASC: TMenuItem
+      Caption = 'Send PASC'
+      OnClick = miSendPASCClick
+    end
+    object miChangeKey: TMenuItem
+      Caption = 'Change Key'
+      OnClick = miChangeKeyClick
+    end
+    object miAccountsMarket: TMenuItem
+      Caption = 'Account Market'
+      object miEnlistAccountsForSale: TMenuItem
+        Caption = 'Enlist Account(s) For Sale'
+        OnClick = miEnlistAccountsForSaleClick
       end
-      object miFindNextAccountWithHighBalance: TMenuItem
-        Caption = 'Find next account with high balance'
-        ShortCut = 114
-        OnClick = miFindNextAccountWithHighBalanceClick
+      object miDelistAccountsFromSale: TMenuItem
+        Caption = 'Delist Account(s) From Sale'
+        OnClick = miDelistAccountsFromSaleClick
       end
     end
+    object miSep1: TMenuItem
+      Caption = '-'
+    end
+    object miAccountInfo: TMenuItem
+      Caption = 'Account Info'
+      OnClick = miAccountInfoClick
+    end
+  end
+  object mnuOperationsPopup: TPopupMenu
+    left = 896
+    top = 64
+    object miCopyOphash: TMenuItem
+      Caption = 'Copy OPHASH'
+      OnClick = miCopyOphashClick
+    end
+    object miSep2: TMenuItem
+      Caption = '-'
+    end
+    object miOperationInfo: TMenuItem
+      Caption = 'Operation Info'
+      OnClick = miOperationInfoClick
+    end
+  end
+  object mnuFirstAccountPopup: TPopupMenu
+    left = 1024
+    top = 64
   end
 end

+ 733 - 582
src/gui/UFRMAccountExplorer.pas

@@ -2,720 +2,871 @@ unit UFRMAccountExplorer;
 
 {$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.
-
-  Acknowledgements:
-  - Albert Molina: portions of code copied from https://github.com/PascalCoin/PascalCoin/blob/master/Units/Forms/UFRMWallet.pas
-}
+{$modeswitch nestedprocvars}
 
 interface
 
-{$I ..\config.inc}
-
 uses
-  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
-  ExtCtrls, StdCtrls, Buttons, Grids, Menus, UCommon.UI,
-  UGridUtils, UNode, UAccounts, UBlockChain;
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus,
+  ExtCtrls, PairSplitter, Buttons, UVisualGrid, UCommon.UI, Generics.Collections,
+  UAccounts, UDataSources, UNode, UCoreObjects, UCoreUtils, UWIZSendPASC, UWIZChangeKey, UWIZEnlistAccountForSale;
 
 type
 
   { TFRMAccountExplorer }
 
+  TFRMAccountExplorerAccountsMode = (wamMyAccounts, wamAllAccounts);
+  TFRMAccountExplorerOperationsMode = (womSelectedAccounts, womAllAccounts);
+  TFRMAccountExplorerOperationsHistory = (woh7Days, woh30Days, wohFullHistory);
+
   TFRMAccountExplorer = class(TApplicationForm)
-    bbAccountsRefresh: TBitBtn;
-    bbAccountsRefresh1: TBitBtn;
-    bbAccountsRefresh2: TBitBtn;
-    bbChangeKeyName: TBitBtn;
-    bbChangeKeyName1: TBitBtn;
-    bbChangeKeyName2: TBitBtn;
-    bbSelectedAccountsOperation: TBitBtn;
-    bbSelectedAccountsOperation1: TBitBtn;
-    bbSelectedAccountsOperation2: TBitBtn;
-    cbExploreMyAccounts: TCheckBox;
-    cbExploreMyAccounts1: TCheckBox;
-    cbExploreMyAccounts2: TCheckBox;
-    cbFilterAccounts: TCheckBox;
-    cbFilterAccounts1: TCheckBox;
-    cbFilterAccounts2: TCheckBox;
-    cbMyPrivateKeys: TComboBox;
-    cbMyPrivateKeys1: TComboBox;
-    cbMyPrivateKeys2: TComboBox;
-    dgAccountOperations: TDrawGrid;
-    dgAccountOperations1: TDrawGrid;
-    dgAccountOperations2: TDrawGrid;
-    dgAccounts: TDrawGrid;
-    dgAccounts1: TDrawGrid;
-    dgAccounts2: TDrawGrid;
-    dgSelectedAccounts: TDrawGrid;
-    dgSelectedAccounts1: TDrawGrid;
-    dgSelectedAccounts2: TDrawGrid;
-    ebFilterAccountByBalanceMax: TEdit;
-    ebFilterAccountByBalanceMax1: TEdit;
-    ebFilterAccountByBalanceMax2: TEdit;
-    ebFilterAccountByBalanceMin: TEdit;
-    ebFilterAccountByBalanceMin1: TEdit;
-    ebFilterAccountByBalanceMin2: TEdit;
-    ebFindAccountNumber: TEdit;
-    ebFindAccountNumber1: TEdit;
-    ebFindAccountNumber2: TEdit;
-    Label15: TLabel;
-    Label16: TLabel;
-    Label17: TLabel;
-    Label18: TLabel;
-    Label19: TLabel;
-    Label20: TLabel;
-    Label21: TLabel;
-    Label22: TLabel;
-    Label23: TLabel;
-    Label24: TLabel;
-    Label25: TLabel;
-    Label26: TLabel;
-    Label27: TLabel;
-    Label28: TLabel;
-    Label29: TLabel;
-    Label30: TLabel;
-    Label31: TLabel;
-    Label32: TLabel;
-    lblAccountsBalance: TLabel;
-    lblAccountsBalance1: TLabel;
-    lblAccountsBalance2: TLabel;
-    lblAccountsCount: TLabel;
-    lblAccountsCount1: TLabel;
-    lblAccountsCount2: TLabel;
-    lblSelectedAccountsBalance: TLabel;
-    lblSelectedAccountsBalance1: TLabel;
-    lblSelectedAccountsBalance2: TLabel;
-    lblSelectedAccountsCount: TLabel;
-    lblSelectedAccountsCount1: TLabel;
-    lblSelectedAccountsCount2: TLabel;
-    meAccountExplorerMenu : TMainMenu;
-    miDecodePayload: TMenuItem;
-    miAccountInformation: TMenuItem;
-    miAddAccountToSelected: TMenuItem;
-    miFindAccount: TMenuItem;
-    miFindNextAccountWithHighBalance: TMenuItem;
-    miFindPreviousAccountWithHighBalance: TMenuItem;
-    miNewOperation: TMenuItem;
-    miRemoveAccountFromSelected: TMenuItem;
-    miTools: TMenuItem;
-    N1: TMenuItem;
-    N2: TMenuItem;
-    N3: TMenuItem;
-    pcAccountsOptions: TPageControl;
-    pcAccountsOptions1: TPageControl;
-    pcAccountsOptions2: TPageControl;
-    pnlAccounts: TPanel;
-    pnlAccounts1: TPanel;
-    pnlAccounts2: TPanel;
-    pnlAccountsInfo: TPanel;
-    pnlAccountsInfo1: TPanel;
-    pnlAccountsInfo2: TPanel;
-    pnlMyAccountsTop: TPanel;
-    pnlMyAccountsTop1: TPanel;
-    pnlMyAccountsTop2: TPanel;
-    pnlSelectedAccountsBottom: TPanel;
-    pnlSelectedAccountsBottom1: TPanel;
-    pnlSelectedAccountsBottom2: TPanel;
-    pnlSelectedAccountsLeft: TPanel;
-    pnlSelectedAccountsLeft1: TPanel;
-    pnlSelectedAccountsLeft2: TPanel;
-    pnlSelectedAccountsTop: TPanel;
-    pnlSelectedAccountsTop1: TPanel;
-    pnlSelectedAccountsTop2: TPanel;
-    sbSearchAccount: TSpeedButton;
-    sbSearchAccount1: TSpeedButton;
-    sbSearchAccount2: TSpeedButton;
-    sbSelectedAccountsAdd: TSpeedButton;
-    sbSelectedAccountsAdd1: TSpeedButton;
-    sbSelectedAccountsAdd2: TSpeedButton;
-    sbSelectedAccountsAddAll: TSpeedButton;
-    sbSelectedAccountsAddAll1: TSpeedButton;
-    sbSelectedAccountsAddAll2: TSpeedButton;
-    sbSelectedAccountsDel: TSpeedButton;
-    sbSelectedAccountsDel1: TSpeedButton;
-    sbSelectedAccountsDel2: TSpeedButton;
-    sbSelectedAccountsDelAll: TSpeedButton;
-    sbSelectedAccountsDelAll1: TSpeedButton;
-    sbSelectedAccountsDelAll2: TSpeedButton;
-    Splitter1: TSplitter;
-    Splitter2: TSplitter;
-    Splitter3: TSplitter;
-    tsAccountOperations: TTabSheet;
-    tsAccountOperations1: TTabSheet;
-    tsAccountOperations2: TTabSheet;
-    tsMultiSelectAccounts: TTabSheet;
-    tsMultiSelectAccounts1: TTabSheet;
-    tsMultiSelectAccounts2: TTabSheet;
-    tsMyAccounts: TTabSheet;
-    tsMyAccounts1: TTabSheet;
-    tsMyAccounts2: TTabSheet;
-    procedure bbAccountsRefreshClick(Sender: TObject);
-    procedure bbChangeKeyNameClick(Sender: TObject);
-    procedure bbSelectedAccountsOperationClick(Sender: TObject);
-    procedure cbExploreMyAccountsChange(Sender: TObject);
-    procedure cbFilterAccountsChange(Sender: TObject);
-    procedure cbMyPrivateKeysChange(Sender: TObject);
-    procedure dgAccountOperationsClick(Sender: TObject);
-    procedure dgAccountsClick(Sender: TObject);
-    procedure ebFilterAccountByBalanceMinExit(Sender: TObject);
-    procedure ebFilterAccountByBalanceMinKeyPress(Sender: TObject; var Key: char);
-    procedure ebFindAccountNumberChange(Sender: TObject);
-    procedure ebFindAccountNumberExit(Sender: TObject);
+    btnChangeKeyName: TBitBtn;
+    cbAccounts: TComboBox;
+    chkExploreMyAccounts: TCheckBox;
+    gpAccounts: TGroupBox;
+    gpRecentOps: TGroupBox;
+    GroupBox1: TGroupBox;
+    Label1: TLabel;
+    Label2: TLabel;
+    lblTotalPASA: TLabel;
+    lblTotalPASC: TLabel;
+    miCopyOphash: TMenuItem;
+    miOperationInfo: TMenuItem;
+    miSendPASC: TMenuItem;
+    miChangeKey: TMenuItem;
+    miAccountsMarket: TMenuItem;
+    miEnlistAccountsForSale: TMenuItem;
+    miDelistAccountsFromSale: TMenuItem;
+    miAccountInfo: TMenuItem;
+    miSep1: TMenuItem;
+    miSep2: TMenuItem;
+    PairSplitter1: TPairSplitter;
+    PairSplitterSide1: TPairSplitterSide;
+    PairSplitterSide2: TPairSplitterSide;
+    paAccounts: TPanel;
+    paOperations: TPanel;
+    mnuAccountsPopup: TPopupMenu;
+    mnuOperationsPopup: TPopupMenu;
+    mnuFirstAccountPopup: TPopupMenu;
+    procedure btnChangeKeyNameClick(Sender: TObject);
+    procedure cbAccountsChange(Sender: TObject);
+    procedure chkExploreMyAccountsChange(Sender: TObject);
+    procedure cmbDurationChange(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
-    procedure miAccountInformationClick(Sender: TObject);
-    procedure miAddAccountToSelectedClick(Sender: TObject);
-    procedure miDecodePayloadClick(Sender: TObject);
-    procedure miFindNextAccountWithHighBalanceClick(Sender: TObject);
-    procedure miFindPreviousAccountWithHighBalanceClick(Sender: TObject);
-    procedure miNewOperationClick(Sender: TObject);
-    procedure miRemoveAccountFromSelectedClick(Sender: TObject);
-    procedure sbSearchAccountClick(Sender: TObject);
-    function DoUpdateAccountsFilter: Boolean;
-    procedure sbSelectedAccountsAddAllClick(Sender: TObject);
-    procedure sbSelectedAccountsAddClick(Sender: TObject);
-    procedure sbSelectedAccountsDelAllClick(Sender: TObject);
-    procedure sbSelectedAccountsDelClick(Sender: TObject);
-    procedure RefreshAccountsGrid(RefreshData : Boolean);
-    procedure RefreshMyKeysCombo;
-    procedure OnAccountsSelectedGridUpdated(Sender: TObject);
+    procedure FormResize(Sender: TObject);
+    procedure miAccountInfoClick(Sender: TObject);
+    procedure miChangeKeyClick(Sender: TObject);
+    procedure miCopyOphashClick(Sender: TObject);
+    procedure miOperationInfoClick(Sender: TObject);
+    procedure miSendPASCClick(Sender: TObject);
+    procedure miEnlistAccountsForSaleClick(Sender: TObject);
+    procedure miDelistAccountsFromSaleClick(Sender: TObject);
   private
-    { private declarations }
-    FAccountsGrid : TAccountsGrid;
-    FAccountOperationsGrid : TOperationsGrid;
-    FAccountsSelectedGrid : TAccountsGrid;
-    FOrderedAccountsKeyList : TOrderedAccountKeysList;
-    FMinAccountBalance : Int64;
-    FMaxAccountBalance : Int64;
+    FNodeNotifyEvents: TNodeNotifyEvents;
+    FAccountsMode: TFRMAccountExplorerAccountsMode;
+    FOperationsMode: TFRMAccountExplorerOperationsMode;
+    FOperationsHistory: TFRMAccountExplorerOperationsHistory;
+    FAccountsGrid: TVisualGrid;
+    FOperationsGrid: TVisualGrid;
+    FAllAccountsDataSource: TAccountsDataSource;
+    FAccountsDataSource: TMyAccountsDataSource;
+    FOperationsDataSource: TAccountsOperationsDataSource;
+    procedure SetAccountsMode(AMode: TFRMAccountExplorerAccountsMode);
+    procedure SetOperationsMode(AMode: TFRMAccountExplorerOperationsMode);
+    procedure SetOperationsHistory(AHistory: TFRMAccountExplorerOperationsHistory);
+    procedure RefreshMyAccountsCombo;
+    procedure RefreshTotals;
+    procedure RefreshAccountsGrid;
+    procedure RefreshOperationsGrid;
+    function GetAccounts(const AccountNumbers: TArray<cardinal>): TArray<TAccount>;
+  protected
+    procedure ActivateFirstTime; override;
     procedure OnPrivateKeysChanged(Sender: TObject);
+    procedure OnUserAccountsChanged(Sender: TObject);
+    procedure OnNodeBlocksChanged(Sender: TObject);
+    procedure OnNodeNewOperation(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);
   public
-    { public declarations }
-    procedure OnSelectedAccountChanged;
-    procedure Refresh;
+    property AccountsMode: TFRMAccountExplorerAccountsMode read FAccountsMode write SetAccountsMode;
+    property OperationsMode: TFRMAccountExplorerOperationsMode read FOperationsMode write SetOperationsMode;
+    property OperationsHistory: TFRMAccountExplorerOperationsHistory read FOperationsHistory write SetOperationsHistory;
   end;
 
 implementation
 
-{$R *.lfm}
+uses
+  UUserInterface, UCellRenderers, UBlockChain, UWallet, UCrypto,
+  UCommon, UMemory, Generics.Defaults, UCommon.Data, UCommon.Collections;
 
-uses UFRMAccountSelect, UConst, USettings, UFRMOperation,
-     UWallet, UCrypto, UFRMMemoText, UUserInterface, UCommon;
+{$R *.lfm}
 
 { TFRMAccountExplorer }
 
-{%region Form life-cycle}
-
 procedure TFRMAccountExplorer.FormCreate(Sender: TObject);
-begin
-  FMinAccountBalance := 0;
-  FMaxAccountBalance := CT_MaxWalletAmount;
-  FOrderedAccountsKeyList := Nil;
-  FAccountsGrid := TAccountsGrid.Create(Self);
-  FAccountsGrid.DrawGrid := dgAccounts;
-  FAccountsGrid.Node := TUserInterface.Node;
-  FAccountsGrid.AllowMultiSelect := True;
-  FAccountsSelectedGrid := TAccountsGrid.Create(Self);
-  FAccountsSelectedGrid.DrawGrid :=dgSelectedAccounts;
-  FAccountsSelectedGrid.Node := TUserInterface.Node;
-  FAccountsSelectedGrid.OnUpdated := OnAccountsSelectedGridUpdated;
-  FAccountOperationsGrid := TOperationsGrid.Create(Self);
-  FAccountOperationsGrid.DrawGrid := dgAccountOperations;
-  FAccountOperationsGrid.Node := TUserInterface.Node;
-  FAccountOperationsGrid.MustShowAlwaysAnAccount := true;
-  pcAccountsOptions.ActivePage := tsAccountOperations;
-
-  // Get account list from SafeBox
-  FOrderedAccountsKeyList := TOrderedAccountKeysList.Create(TUserInterface.Node.Bank.SafeBox,false);
-
-  // Subscribe to wallet events
+var
+  cmbDuration: TComboBox;
+begin
+  // event registrations
+  FNodeNotifyEvents := TNodeNotifyEvents.Create(self);
+  FNodeNotifyEvents.WatchKeys := TWallet.Keys.AccountsKeyList;
+  FNodeNotifyEvents.OnKeyActivity := OnUserAccountsChanged;
+  FNodeNotifyEvents.OnBlocksChanged := OnNodeBlocksChanged;
+  FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
   TWallet.Keys.OnChanged.Add(OnPrivateKeysChanged);
-  Refresh;
-end;
-
-procedure TFRMAccountExplorer.FormDestroy(Sender: TObject);
-begin
-  // Unsubscribe from wallet events
-  TWallet.Keys.OnChanged.Remove(OnPrivateKeysChanged);
-
-  // Nullify fields
-  FAccountOperationsGrid.Node := Nil;
-  FAccountsGrid.Node := Nil;
-  FAccountsSelectedGrid.Node := Nil;
-  FAccountsGrid.Node := Nil;
 
-  // Note: grids themselves are collected with Self (TComponent dependency)
-end;
+  // fields
+  FAllAccountsDataSource := TAccountsDataSource.Create(Self);
+  FAllAccountsDataSource.IncludePending := True;
+  FAccountsDataSource := TMyAccountsDataSource.Create(Self);
+  FOperationsDataSource := TAccountsOperationsDataSource.Create(Self);
+  FOperationsDataSource.Accounts := nil;
+  FOperationsHistory := woh7Days;
+  FOperationsMode := womAllAccounts;
+  FAccountsMode := wamAllAccounts;
+
+  // grids
+  FAccountsGrid := TVisualGrid.Create(Self);
+  FAccountsGrid.SortMode := smMultiColumn;
+  FAccountsGrid.FetchDataInThread := False;
+  FAccountsGrid.AutoPageSize := True;
+  FAccountsGrid.DeselectionType := dtDefault;
+  FAccountsGrid.SelectionType := stMultiRow;
+  FAccountsGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone, vgoAutoHidePaging, vgoAutoHideSearchPanel];
+  with FAccountsGrid.AddColumn('Account') do
+  begin
+    Binding := 'AccountNumber';
+    SortBinding := 'AccountNumber';
+    DisplayBinding := 'Account';
+    Width := 100;
+    HeaderFontStyles := [fsBold];
+    DataFontStyles := [fsBold];
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FAccountsGrid.AddColumn('Name') do
+  begin
+    Width := 100;
+    HeaderAlignment := taCenter;
+    Filters := SORTABLE_TEXT_FILTER;
+  end;
+  with FAccountsGrid.AddColumn('Balance') do
+  begin
+    Binding := 'BalanceDecimal';
+    SortBinding := 'Balance';
+    DisplayBinding := 'Balance';
+    Width := 100;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
+    Renderer := TCellRenderers.PASC;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FAccountsGrid.AddColumn('N Op.') do
+  begin
+    Binding := 'NumberOfOperations';
+    Width := 50;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FAccountsGrid.AddColumn('Type') do
+  begin
+    Binding := 'Type';
+    Width := 50;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FAccountsGrid.AddColumn('Price') do
+  begin
+    Binding := 'Price';
+    Width := 100;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
+    Renderer := TCellRenderers.PASC_CheckPendingBalance;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
 
-{%endregion}
+  FAccountsGrid.OnSelection := OnAccountsSelected;
+  FAccountsGrid.OnPreparePopupMenu := OnPrepareAccountPopupMenu;
+
+  FOperationsGrid := TVisualGrid.Create(Self);
+  FOperationsGrid.SortMode := smMultiColumn;
+  FOperationsGrid.FetchDataInThread := True;
+  FOperationsGrid.AutoPageSize := True;
+  FOperationsGrid.DeselectionType := dtDefault;
+  FOperationsGrid.SelectionType := stRow;
+  FOperationsGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone, vgoAutoHidePaging, vgoAutoHideSearchPanel];
+  with FOperationsGrid.AddColumn('Time') do
+  begin
+    SortBinding := 'UnixTime';
+    DisplayBinding := 'UnixTime';
+    Renderer := TCellRenderers.OperationTime;
+    Width := 130;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Block') do
+  begin
+    Binding := 'BlockLocation';
+    SortBinding := 'BlockLocationSortable';
+    AutoWidth := True;
+    Filters := SORTABLE_TEXT_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Account') do
+  begin
+    Binding := 'AccountNumber';
+    DisplayBinding := 'Account';
+    Width := 100;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Type') do
+  begin
+    Sanitizer := TCellRenderers.OperationTypeSanitizer;
+    Width := 150;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Amount') do
+  begin
+    Binding := 'AmountDecimal';
+    SortBinding := 'Amount';
+    DisplayBinding := 'Amount';
+    Width := 150;
+    HeaderAlignment := taRightJustify;
+    Renderer := TCellRenderers.PASC_CheckPendingBalance;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Fee') do
+  begin
+    Binding := 'FeeDecimal';
+    SortBinding := 'Fee';
+    DisplayBinding := 'Fee';
+    AutoWidth := True;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
+    Renderer := TCellRenderers.PASC_CheckPendingBalance;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Balance') do
+  begin
+    Binding := 'BalanceDecimal';
+    SortBinding := 'Balance';
+    DisplayBinding := 'Balance';
+    Width := 100;
+    HeaderAlignment := taRightJustify;
+    DataAlignment := taRightJustify;
+    Renderer := TCellRenderers.PASC_CheckPendingBalance;
+    Filters := SORTABLE_NUMERIC_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Payload') do
+  begin
+    AutoWidth := True;
+    Renderer := TCellRenderers.Payload;
+    Filters := SORTABLE_TEXT_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('OPHASH') do
+  begin
+    Width := 80;
+    Renderer := TCellRenderers.OPHASH;
+    Filters := SORTABLE_TEXT_FILTER;
+  end;
+  with FOperationsGrid.AddColumn('Description') do
+  begin
+    StretchedToFill := True;
+    Filters := SORTABLE_TEXT_FILTER;
+  end;
+  FOperationsGrid.OnSelection := OnOperationSelected;
+  FOperationsGrid.OnPreparePopupMenu := OnPrepareOperationsPopupMenu;
+  FOperationsGrid.Caption.Alignment := taCenter;
+  //FOperationsGrid.Caption.Text := 'All Account Operations';
+  FOperationsGrid.Caption.Text := '';
+  FOperationsGrid.Caption.Visible := True;
+
+  // key combo
+  RefreshMyAccountsCombo;
+
+  // duration combo
+  cmbDuration := TComboBox.Create(FOperationsGrid);
+  cmbDuration.ReadOnly := True;
+  cmbDuration.Items.BeginUpdate;
+  try
+    cmbDuration.AddItem('7 Days', TObject(woh7Days));
+    cmbDuration.AddItem('30 Days', TObject(woh30Days));
+    cmbDuration.AddItem('Maximum', TObject(wohFullHistory));
+  finally
+    cmbDuration.Items.EndUpdate;
+    cmbDuration.ItemIndex := 0;
+  end;
+  cmbDuration.OnChange := cmbDurationChange;
+  FOperationsGrid.WidgetControl := cmbDuration;
 
-{%region Form methods}
+  // Add datasources to grid
+  chkExploreMyAccountsChange(Self);
+  FOperationsGrid.DataSource := FOperationsDataSource;
 
-procedure TFRMAccountExplorer.Refresh;
-begin
-  RefreshAccountsGrid(true);
-  RefreshMyKeysCombo;
+  // Add grid to panels
+  paAccounts.AddControlDockCenter(FAccountsGrid);
+  paOperations.AddControlDockCenter(FOperationsGrid);
 end;
 
-{%endregion}
-
-{%region For auxillary methods}
-
-procedure TFRMAccountExplorer.RefreshAccountsGrid(RefreshData : Boolean);
-Var accl : TOrderedCardinalList;
-  l : TOrderedCardinalList;
-  i,j,k : Integer;
-  c  : Cardinal;
-  applyfilter : Boolean;
-  acc : TAccount;
+procedure TFRMAccountExplorer.FormDestroy(Sender: TObject);
 begin
-  If Not Assigned(FOrderedAccountsKeyList) Then exit;
-  if Not RefreshData then begin
-    dgAccounts.Invalidate;
-    exit;
-  end;
-  applyfilter := (cbFilterAccounts.Checked) and ((FMinAccountBalance>0) Or (FMaxAccountBalance<CT_MaxWalletAmount));
-  FAccountsGrid.ShowAllAccounts := (Not cbExploreMyAccounts.Checked) And (not applyfilter);
-  if Not FAccountsGrid.ShowAllAccounts then begin
-    accl := FAccountsGrid.LockAccountsList;
-    Try
-      accl.Clear;
-      if cbExploreMyAccounts.Checked then begin
-        if cbMyPrivateKeys.ItemIndex<0 then exit;
-        if cbMyPrivateKeys.ItemIndex=0 then begin
-          // All keys in the wallet
-          for i := 0 to TWallet.Keys.Count - 1 do begin
-            j := FOrderedAccountsKeyList.IndexOfAccountKey(TWallet.Keys[i].AccountKey);
-            if (j>=0) then begin
-              l := FOrderedAccountsKeyList.AccountKeyList[j];
-              for k := 0 to l.Count - 1 do begin
-                if applyfilter then begin
-                  acc := TUserInterface.Node.Bank.SafeBox.Account(l.Get(k));
-                  if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
-                end else accl.Add(l.Get(k));
-              end;
-            end;
-          end;
-        end else begin
-          i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
-          if (i>=0) And (i<TWallet.Keys.Count) then begin
-            j := FOrderedAccountsKeyList.IndexOfAccountKey(TWallet.Keys[i].AccountKey);
-            if (j>=0) then begin
-              l := FOrderedAccountsKeyList.AccountKeyList[j];
-              for k := 0 to l.Count - 1 do begin
-                if applyfilter then begin
-                  acc := TUserInterface.Node.Bank.SafeBox.Account(l.Get(k));
-                  if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
-                end else accl.Add(l.Get(k));
-              end;
-            end;
-          end;
-        end;
-      end else begin
-        // There is a filter... check every account...
-        c := 0;
-        while (c<TUserInterface.Node.Bank.SafeBox.AccountsCount) do begin
-          acc := TUserInterface.Node.Bank.SafeBox.Account(c);
-          if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
-          inc(c);
-        end;
-      end;
-    Finally
-      FAccountsGrid.UnlockAccountsList;
-    End;
-    lblAccountsCount.Caption := inttostr(accl.Count);
-  end else begin
-    lblAccountsCount.Caption := inttostr(TUserInterface.Node.Bank.AccountsCount);
-  end;
-  bbChangeKeyName.Enabled := cbExploreMyAccounts.Checked;
-  // Show Totals:
-  lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
-  OnSelectedAccountChanged;
+  TWallet.Keys.OnChanged.Add(OnPrivateKeysChanged);
 end;
 
-procedure TFRMAccountExplorer.RefreshMyKeysCombo;
-Var i,last_i : Integer;
-  wk : TWalletKey;
-  s : AnsiString;
+procedure TFRMAccountExplorer.FormResize(Sender: TObject);
 begin
-  cbMyPrivateKeys.Enabled := cbExploreMyAccounts.Checked;
-  if (cbMyPrivateKeys.ItemIndex>=0) then last_i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex])
-  else last_i := -1;
-  cbMyPrivateKeys.items.BeginUpdate;
-  Try
-    cbMyPrivateKeys.Items.Clear;
-    For i:=0 to TWallet.Keys.Count-1 do begin
-      wk := TWallet.Keys.Key[i];
-      if assigned(FOrderedAccountsKeyList) then begin
-        FOrderedAccountsKeyList.AddAccountKey(wk.AccountKey);
-      end;
-      if (wk.Name='') then begin
-        s := 'Sha256='+TCrypto.ToHexaString( TCrypto.DoSha256( TAccountComp.AccountKey2RawString(wk.AccountKey) ) );
-      end else begin
-        s := wk.Name;
-      end;
-      if Not Assigned(wk.PrivateKey) then s := s + '(*)';
-      cbMyPrivateKeys.Items.AddObject(s,TObject(i));
-    end;
-    cbMyPrivateKeys.Sorted := true;
-    cbMyPrivateKeys.Sorted := false;
-    cbMyPrivateKeys.Items.InsertObject(0,'(All my private keys)',TObject(-1));
-  Finally
-    cbMyPrivateKeys.Items.EndUpdate;
-  End;
-  last_i := cbMyPrivateKeys.Items.IndexOfObject(TObject(last_i));
-  if last_i<0 then last_i := 0;
-  if cbMyPrivateKeys.Items.Count>last_i then cbMyPrivateKeys.ItemIndex := last_i
-  else if cbMyPrivateKeys.Items.Count>=0 then cbMyPrivateKeys.ItemIndex := 0;
+  // Left hand panel is 50% the size up until a max size of 450
+
 end;
 
-function TFRMAccountExplorer.DoUpdateAccountsFilter: Boolean;
-Var bmin,bmax:Int64;
-  doupd : Boolean;
+procedure TFRMAccountExplorer.ActivateFirstTime;
 begin
-  If Not TAccountComp.TxtToMoney(ebFilterAccountByBalanceMin.Text,bmin) then bmin := 0;
-  If not TAccountComp.TxtToMoney(ebFilterAccountByBalanceMax.Text,bmax) then bmax := CT_MaxWalletAmount;
-  if (bmax<bmin) or (bmax=0) then bmax := CT_MaxWalletAmount;
-  if bmin>bmax then bmin := 0;
-  doupd := (bmin<>FMinAccountBalance) Or (bmax<>FMaxAccountBalance);
-  FMinAccountBalance := bmin;
-  FMaxAccountBalance := bmax;
-  if bmin>0 then
-    ebFilterAccountByBalanceMin.Text:=TAccountComp.FormatMoney(bmin)
-  else ebFilterAccountByBalanceMin.Text := '';
-  if bmax<CT_MaxWalletAmount then
-    ebFilterAccountByBalanceMax.Text := TAccountComp.FormatMoney(bmax)
-  else ebFilterAccountByBalanceMax.Text := '';
-  if cbFilterAccounts.Checked then begin
-    ebFilterAccountByBalanceMin.ParentFont := true;
-    ebFilterAccountByBalanceMax.ParentFont := true;
-  end else begin
-    ebFilterAccountByBalanceMin.font.Color := clDkGray;
-    ebFilterAccountByBalanceMax.font.Color := clDkGray;
-  end;
-  if doupd then RefreshAccountsGrid(true);
-  Result := doupd;
-  //end;
+  RefreshTotals;
 end;
 
-{%endregion}
+procedure TFRMAccountExplorer.RefreshTotals;
 
-{%region Event Handlers: Blockchain }
+  function GetAllAccountsKey(): TArray<TAccountKey>;
+  var
+    LAccount: TAccount;
+    LAccounts: TList<TAccount>;
+    LAccountsKey: TList<TAccountKey>;
+    LGC: TDisposables;
+  begin
+    LAccounts := LGC.AddObject(TList<TAccount>.Create) as TList<TAccount>;
+    FAllAccountsDataSource.FetchAll(LAccounts);
+    LAccountsKey := LGC.AddObject(TList<TAccountKey>.Create) as TList<TAccountKey>;
+    for LAccount in LAccounts do
+      LAccountsKey.Add(LAccount.accountInfo.accountKey);
+    Result := LAccountsKey.ToArray;
+  end;
 
-procedure TFRMAccountExplorer.OnPrivateKeysChanged(Sender: TObject);
+var
+  LBalance: TBalanceSummary;
 begin
-  Refresh;
+  case FAccountsMode of
+    wamMyAccounts:
+    begin
+      LBalance := TWallet.Keys.AccountsKeyList.GetBalance(True);
+      lblTotalPASC.Caption := TAccountComp.FormatMoney(LBalance.TotalPASC);
+      lblTotalPASA.Caption := Format('%d', [LBalance.TotalPASA]);
+    end;
+    wamAllAccounts:
+    begin
+      LBalance := TNode.Node.Bank.SafeBox.GetBalance(GetAllAccountsKey, True);
+      lblTotalPASC.Caption := TAccountComp.FormatMoney(LBalance.TotalPASC);
+      lblTotalPASA.Caption := Format('%d', [LBalance.TotalPASA]);
+    end;
+  end;
 end;
 
-procedure TFRMAccountExplorer.OnSelectedAccountChanged;
-Var accn : Int64;
-begin
-  accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
-  FAccountOperationsGrid.AccountNumber := accn;
+procedure TFRMAccountExplorer.RefreshMyAccountsCombo;
+var
+  i: integer;
+  selectFirst, selectLast: boolean;
+  last_key: TAccountKey;
+  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;
+    end;
+  end
+  else
+  begin
+    selectFirst := True;
+    selectLast := False;
+  end;
+
+  // update combo items
+  cbAccounts.items.BeginUpdate;
+  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
+      // get i'th key
+      key := TWallet.Keys.Key[i];
+      // fix name
+      if (key.Name = '') then
+        str := 'Sha256=' + TCrypto.ToHexaString(TCrypto.DoSha256(
+          TAccountComp.AccountKey2RawString(key.AccountKey)))
+      else
+        str := key.Name;
+      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);
+  finally
+    cbAccounts.Items.EndUpdate;
+  end;
+  // re-select previous selection
+  if selectFirst then
+    cbAccounts.ItemIndex := 0
+  else if selectLast then
+    cbAccounts.ItemIndex := cbAccounts.Items.Count - 1
+  else
+    for i := 1 to cbAccounts.Items.Count - 2 do
+      if TAccountKeyEqualityComparer.AreEqual(TBox<TAccountKey>(cbAccounts.Items.Objects[i]).Value, last_key) then
+      begin
+        cbAccounts.ItemIndex := i;
+        exit;
+      end;
 end;
 
-{%endregion}
+procedure TFRMAccountExplorer.RefreshAccountsGrid;
 
-{%region Event Handlers: Combo Boxes}
+  function GetAccountKey(constref AAccount: TAccount): TAccountKey;
+  begin
+    Result := AAccount.accountInfo.accountKey;
+  end;
 
-procedure TFRMAccountExplorer.cbExploreMyAccountsChange(Sender: TObject);
-begin
-    RefreshAccountsGrid(true);
-    RefreshMyKeysCombo;
-    OnSelectedAccountChanged;
-end;
+  function GetAllAccounts(): TArray<TAccount>;
+  var
+    LAccounts: TList<TAccount>;
+    LGC: TDisposables;
+  begin
+    LAccounts := LGC.AddObject(TList<TAccount>.Create) as TList<TAccount>;
+    FAllAccountsDataSource.FetchAll(LAccounts);
+    Result := LAccounts.ToArray;
+  end;
 
-procedure TFRMAccountExplorer.cbFilterAccountsChange(Sender: TObject);
-begin
-  If not DoUpdateAccountsFilter then RefreshAccountsGrid(true);
-end;
+var
+  index: integer;
+  sel: TBox<TAccountKey>;
+begin
+
+  case Self.AccountsMode of
+    wamMyAccounts:
+    begin
+      cbAccounts.Enabled := True;
+      btnChangeKeyName.Enabled := True;
+      if cbAccounts.ItemIndex = cbAccounts.Items.Count - 1 then
+        exit; // not a key
+      index := cbAccounts.ItemIndex;
+      if index = 0 then
+      begin
+        gpAccounts.Caption := 'My Accounts';
+        FAccountsDataSource.FilterKeys := TWallet.Keys.AccountsKeyList.ToArray;
+      end
+      else
+      begin
+        sel := TBox<TAccountKey>(cbAccounts.Items.Objects[cbAccounts.ItemIndex]);
+        gpAccounts.Caption := Format('%s Accounts', [TWallet.Keys[TWallet.Keys.IndexOfAccountKey(sel.Value)].Name]);
+        FAccountsDataSource.FilterKeys := TArray<TAccountKey>.Create(sel.Value);
+      end;
+    end;
 
-procedure TFRMAccountExplorer.cbMyPrivateKeysChange(Sender: TObject);
-begin
-  RefreshAccountsGrid(true);
+    wamAllAccounts:
+    begin
+      cbAccounts.Enabled := False;
+      btnChangeKeyName.Enabled := False;
+      gpAccounts.Caption := 'All Accounts';
+      FAllAccountsDataSource.FilterKeys := TListTool<TAccount, TAccountKey>.Transform(GetAllAccounts, GetAccountKey);
+    end;
+  end;
+  RefreshTotals;
+  FAccountsGrid.RefreshGrid;
 end;
 
-{%endregion}
-
-{%region Event Handlers: Buttons}
+procedure TFRMAccountExplorer.RefreshOperationsGrid;
 
-procedure TFRMAccountExplorer.bbChangeKeyNameClick(Sender: TObject);
-var i : Integer;
-  nameString : String;
-begin
-  if (cbMyPrivateKeys.ItemIndex<0) then  exit;
-  i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
-  if (i<0) Or (i>=TWallet.Keys.Count) then raise Exception.Create('Must select a Key');
-  name := TWallet.Keys.Key[i].Name;
-  if InputQuery('Change Key name','Input new name',nameString) then begin
-    TWallet.Keys.SetName(i,name);
+  function GetAccNo(constref AAccount: TAccount): cardinal; overload;
+  begin
+    Result := AAccount.account;
   end;
-end;
 
-procedure TFRMAccountExplorer.bbAccountsRefreshClick(Sender: TObject);
-begin
-  RefreshAccountsGrid(true);
-end;
+  function GetAccNo(constref ARow: variant): cardinal; overload;
+  begin
+    Result := ARow.__KEY;
+  end;
 
-procedure TFRMAccountExplorer.sbSelectedAccountsAddAllClick(Sender: TObject);
-Var lsource,ltarget : TOrderedCardinalList;
-  i : Integer;
-begin
-  lsource := FAccountsGrid.LockAccountsList;
-  Try
-    ltarget := FAccountsSelectedGrid.LockAccountsList;
-    Try
-      for i := 0 to lsource.Count-1 do begin
-        if TWallet.Keys.IndexOfAccountKey(TUserInterface.Node.Bank.SafeBox.Account(lsource.Get(i)).accountInfo.accountKey)<0 then raise Exception.Create(Format('You cannot operate with account %d because private key not found in your wallet',[lsource.Get(i)]));
-        ltarget.Add(lsource.Get(i));
-      end;
-    Finally
-      FAccountsSelectedGrid.UnlockAccountsList;
-    End;
-  Finally
-    FAccountsGrid.UnlockAccountsList;
-  End;
-end;
+  function GetAllAccounts(): TArray<TAccount>;
+  var
+    LAccounts: TList<TAccount>;
+    LGC: TDisposables;
+  begin
+    LAccounts := LGC.AddObject(TList<TAccount>.Create) as TList<TAccount>;
+    FAllAccountsDataSource.FetchAll(LAccounts);
+    Result := LAccounts.ToArray;
+  end;
 
-procedure TFRMAccountExplorer.sbSelectedAccountsAddClick(Sender: TObject);
-Var l, selected : TOrderedCardinalList;
-  an : Int64;
-  i : Integer;
 begin
-  an := FAccountsGrid.AccountNumber(dgAccounts.Row);
-  if (an<0) then raise Exception.Create('No account selected');
-  if TWallet.Keys.IndexOfAccountKey(TUserInterface.Node.Bank.SafeBox.Account(an).accountInfo.accountkey)<0 then
-    raise Exception.Create(Format('You cannot add %s account because private key not found in your wallet.'#10+#10+'You''re not the owner!',
-      [TAccountComp.AccountNumberToAccountTxtNumber(an)]));
-  // Add
-  l := FAccountsSelectedGrid.LockAccountsList;
-  selected := TOrderedCardinalList.Create;
-  Try
-    FAccountsGrid.SelectedAccounts(selected);
-    for i := 0 to selected.Count-1 do begin
-      l.Add(selected.Get(i));
+  case FOperationsMode of
+    womAllAccounts:
+    begin
+      FOperationsGrid.Caption.Text := '';
+      FOperationsDataSource.Accounts := nil;
     end;
-  Finally
-    selected.Free;
-    FAccountsSelectedGrid.UnlockAccountsList;
-  End;
+    womSelectedAccounts:
+    begin
+      FOperationsGrid.Caption.Text := 'Selected Account Operations';
+      FOperationsDataSource.Accounts := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNo);
+    end
+    else
+      raise ENotSupportedException.Create(Format('AMode %d not supported', [integer(FOperationsMode)]));
+  end;
+  FOperationsGrid.RefreshGrid;
 end;
 
-procedure TFRMAccountExplorer.sbSelectedAccountsDelAllClick(Sender: TObject);
-Var l : TOrderedCardinalList;
+function TFRMAccountExplorer.GetAccounts(const AccountNumbers: TArray<cardinal>): TArray<TAccount>;
+var
+  acc: TAccount;
+  safeBox: TPCSafeBox;
+  keys: TOrderedAccountKeysList;
+  LContainer: Generics.Collections.TList<TAccount>;
+  i: integer;
 begin
-  l := FAccountsSelectedGrid.LockAccountsList;
+  LContainer := Generics.Collections.TList<TAccount>.Create();
+  keys := TWallet.keys.AccountsKeyList;
+  safeBox := TUserInterface.Node.Bank.safeBox;
+  safeBox.StartThreadSafe;
   try
-    l.Clear;
+    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
+          LContainer.Add(acc);
+      end;
+    finally
+      safeBox.EndThreadSave;
+    end;
+    Result := LContainer.ToArray;
   finally
-    FAccountsSelectedGrid.UnlockAccountsList;
+    LContainer.Free;
   end;
 end;
 
-procedure TFRMAccountExplorer.sbSelectedAccountsDelClick(Sender: TObject);
-Var an : Int64;
-  l : TOrderedCardinalList;
+procedure TFRMAccountExplorer.SetAccountsMode(AMode: TFRMAccountExplorerAccountsMode);
 begin
-  l := FAccountsSelectedGrid.LockAccountsList;
+  if FAccountsMode = AMode then
+    exit;
+
+  FUILock.Acquire;
   try
-    an := FAccountsSelectedGrid.AccountNumber(dgSelectedAccounts.Row);
-    if an>=0 then l.Remove(an);
+    FAccountsMode := AMode;
+    paAccounts.RemoveAllControls(False);
+    // reset account combo
+    cbAccounts.OnChange := nil; // disable event
+    cbAccounts.ItemIndex := 0;
+    cbAccounts.OnChange := cbAccountsChange; // re-enable event
+    // ensure on accounts panel
+    if FAccountsGrid.Parent <> paAccounts then
+    begin
+      paAccounts.RemoveAllControls(False);
+      paAccounts.AddControlDockCenter(FAccountsGrid);
+    end;
+    case AMode of
+
+      wamMyAccounts:
+        FAccountsGrid.DataSource := FAccountsDataSource;
+
+      wamAllAccounts:
+        FAccountsGrid.DataSource := FAllAccountsDataSource;
+    end;
+    // Refresh grid
+    FAccountsGrid.ClearSelection();
+    RefreshAccountsGrid;
   finally
-    FAccountsSelectedGrid.UnlockAccountsList;
+    FUILock.Release;
   end;
 end;
 
-procedure TFRMAccountExplorer.bbSelectedAccountsOperationClick(Sender: TObject);
-var l : TOrderedCardinalList;
+procedure TFRMAccountExplorer.SetOperationsMode(AMode: TFRMAccountExplorerOperationsMode);
 begin
-  TUserInterface.CheckNodeIsReady;
-  if FAccountsSelectedGrid.AccountsCount<=0 then raise Exception.Create('Must select at least 1 account');
+  if FOperationsMode = AMode then
+    exit;
+  FUILock.Acquire;
   try
-    l := FAccountsSelectedGrid.LockAccountsList;
-    TUserInterface.ShowNewOperationDialog(Self, l, TSettings.DefaultFee);
+    FOperationsMode := AMode;
+    RefreshOperationsGrid;
   finally
-    FAccountsSelectedGrid.UnlockAccountsList;
+    FUILock.Release;
   end;
 end;
 
-procedure TFRMAccountExplorer.sbSearchAccountClick(Sender: TObject);
-Var F : TFRMAccountSelect;
+procedure TFRMAccountExplorer.SetOperationsHistory(AHistory: TFRMAccountExplorerOperationsHistory);
 begin
-  F := TFRMAccountSelect.Create(Self);
-  try
-    F.Node := TUserInterface.Node;
-    F.WalletKeys := TWallet.Keys;
-    F.ShowModal;
-  finally
-    F.Free;
+  FOperationsHistory := AHistory;
+  case FOperationsHistory of
+    woh7Days: FOperationsDataSource.TimeSpan := TTimeSpan.FromDays(7);
+    woh30Days: FOperationsDataSource.TimeSpan := TTimeSpan.FromDays(30);
+    wohFullHistory: FOperationsDataSource.TimeSpan := TTimeSpan.FromDays(10 * 365);
   end;
+  FOperationsGrid.RefreshGrid;
 end;
 
-{%endregion}
-
-{%region Event Handlers: Text Boxes}
-
-procedure TFRMAccountExplorer.ebFilterAccountByBalanceMinExit(Sender: TObject);
+procedure TFRMAccountExplorer.OnPrivateKeysChanged(Sender: TObject);
 begin
-  DoUpdateAccountsFilter;
+  RefreshMyAccountsCombo;
 end;
 
-procedure TFRMAccountExplorer.ebFilterAccountByBalanceMinKeyPress(Sender: TObject; var Key: char);
+procedure TFRMAccountExplorer.OnUserAccountsChanged(Sender: TObject);
 begin
-  if key=#13 then DoUpdateAccountsFilter;
+  //  if NOT TUserInterface.Node.HasBestKnownBlockchainTip then
+  //    exit; // node syncing
+
+  RefreshTotals;
+  FAccountsGrid.RefreshGrid;
+  FOperationsGrid.RefreshGrid;
 end;
 
-procedure TFRMAccountExplorer.ebFindAccountNumberChange(Sender: TObject);
-Var an : Cardinal =0;
+procedure TFRMAccountExplorer.OnNodeBlocksChanged(Sender: TObject);
 begin
-  if Trim(ebFindAccountNumber.Text)='' then begin
-    ebFindAccountNumber.Color := clWindow;
-    ebFindAccountNumber.Font.Color := clDkGray;
-  end else if TAccountComp.AccountTxtNumberToAccountNumber(ebFindAccountNumber.Text,an) then begin
-    ebFindAccountNumber.Color := clWindow;
-    if FAccountsGrid.MoveRowToAccount(an) then begin
-      ebFindAccountNumber.Font.Color := clWindowText;
-    end else begin
-      ebFindAccountNumber.Font.Color := clRed;
-    end;
-  end else begin
-    // Invalid value
-    ebFindAccountNumber.Color := clRed;
-    ebFindAccountNumber.Font.Color := clWindowText;
-  end;
+  // TODO: play block sound chime
+  RefreshTotals;
+  FAccountsGrid.RefreshGrid;
+  FOperationsGrid.RefreshGrid;
 end;
 
-procedure TFRMAccountExplorer.ebFindAccountNumberExit(Sender: TObject);
+procedure TFRMAccountExplorer.OnNodeNewOperation(Sender: TObject);
 begin
-  ebFindAccountNumber.Text := '';
+  // TODO: play operation sound tick
+  RefreshTotals;
+  FAccountsGrid.RefreshGrid;
+  FOperationsGrid.RefreshGrid;
 end;
 
-{%endregion}
-
-{%region Event Handlers: Data Grid}
-
-procedure TFRMAccountExplorer.dgAccountOperationsClick(Sender: TObject);
+procedure TFRMAccountExplorer.OnAccountsSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
 begin
-  TUserInterface.ShowOperationInfoDialog(Self, FAccountOperationsGrid.SelectedOperation);
+  if ASelection.Page >= 0 then
+  begin
+    if OperationsMode <> womSelectedAccounts then
+      OperationsMode := womSelectedAccounts
+    else
+      RefreshOperationsGrid; // already viewing selected accounts, add to visible set
+  end
+  else
+    OperationsMode := womAllAccounts;
 end;
 
-procedure TFRMAccountExplorer.dgAccountsClick(Sender: TObject);
+procedure TFRMAccountExplorer.OnOperationSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
+var
+  row: longint;
+  v: variant;
+  ophash: ansistring;
 begin
-  OnSelectedAccountChanged;
+  if ASelection.Page < 0 then
+    exit;
+  row := ASelection.Row;
+  if (row >= 0) and (row < FOperationsGrid.RowCount) then
+  begin
+    v := FOperationsGrid.Rows[row];
+    ophash := FOperationsGrid.Rows[row].OPHASH;
+    if TPCOperation.IsValidOperationHash(ophash) then
+    begin
+      TUserInterface.ShowOperationInfoDialog(self, ophash);
+      FOperationsGrid.ClearSelection(True);
+    end;
+  end;
 end;
 
-procedure TFRMAccountExplorer.OnAccountsSelectedGridUpdated(Sender: TObject);
+procedure TFRMAccountExplorer.cbAccountsChange(Sender: TObject);
 begin
-  lblSelectedAccountsCount.Caption := Inttostr(FAccountsSelectedGrid.AccountsCount);
-  lblSelectedAccountsBalance.Caption := TAccountComp.FormatMoney( FAccountsSelectedGrid.AccountsBalance );
+  if cbAccounts.ItemIndex < 0 then
+    exit;
+  FAccountsGrid.ClearSelection();
+  RefreshAccountsGrid;
+  if FOperationsMode <> womAllAccounts then
+    RefreshOperationsGrid;
+end;
+
+procedure TFRMAccountExplorer.btnChangeKeyNameClick(Sender: TObject);
+var
+  LIdx, LCurrentIndex: integer;
+  LNewName: string;
+begin
+  if (cbAccounts.ItemIndex <= 0) then
+    ShowMessage('You Must Select a Valid Key');
+  LIdx := TWallet.Keys.IndexOfAccountKey(TBox<TAccountKey>(
+    cbAccounts.Items.Objects[cbAccounts.ItemIndex]).Value);
+
+  if (LIdx < 0) or (LIdx >= TWallet.Keys.Count) then
+    ShowMessage('You Must Select a Valid Key');
+
+  LCurrentIndex := cbAccounts.ItemIndex;
+  if InputQuery('Change Key Name', 'Input New Name', LNewName) then
+  begin
+    TWallet.Keys.SetName(LIdx, LNewName);
+    cbAccounts.ItemIndex := LCurrentIndex;
+    cbAccountsChange(Self);
+  end;
 end;
 
-{%endregion}
-
-{%region Events Handlers: Menu Items}
+procedure TFRMAccountExplorer.chkExploreMyAccountsChange(Sender: TObject);
+begin
+  if chkExploreMyAccounts.Checked then
+  begin
+    FAccountsMode := wamMyAccounts;
+    FAccountsGrid.DataSource := FAccountsDataSource;
+  end
+  else
+  begin
+    FAccountsMode := wamAllAccounts;
+    FAccountsGrid.DataSource := FAllAccountsDataSource;
+  end;
+  RefreshAccountsGrid;
+end;
 
-procedure TFRMAccountExplorer.miNewOperationClick(Sender: TObject);
-var targetAccounts : TOrderedCardinalList;
+procedure TFRMAccountExplorer.cmbDurationChange(Sender: TObject);
+var
+  cmbDuration: TComboBox;
 begin
-  targetAccounts := TOrderedCardinalList.Create;
-  try
-    If FAccountsGrid.SelectedAccounts(targetAccounts) = 0
-      then raise Exception.Create('No row selected');
+  cmbDuration := Sender as TComboBox;
+  if not Assigned(cmbDuration) then
+    exit;
 
-    TUserInterface.ShowNewOperationDialog(Self, targetAccounts, TSettings.DefaultFee);
-  finally
-     targetAccounts.Free;
+  case cmbDuration.ItemIndex of
+    0: OperationsHistory := woh7Days;
+    1: OperationsHistory := woh30Days;
+    2: OperationsHistory := wohFullHistory;
   end;
 end;
 
-procedure TFRMAccountExplorer.miFindPreviousAccountWithHighBalanceClick(Sender: TObject);
-Var an  : Cardinal;
-  an64 : Int64;
-  start : TAccount;
-begin
-    an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
-    if an64<0 then an := TUserInterface.Node.Bank.SafeBox.AccountsCount-1
-    else an := an64;
-    If an>= TUserInterface.Node.Bank.SafeBox.AccountsCount then exit;
-    start := TUserInterface.Node.Bank.SafeBox.Account(an);
-    while (an>0)  do begin
-      if TUserInterface.Node.Bank.SafeBox.Account(an).balance>start.balance then break
-      else dec(an);
-    end;
-    if (TUserInterface.Node.Bank.SafeBox.Account(an).balance>start.balance) then FAccountsGrid.MoveRowToAccount(an)
-    else raise Exception.Create('Not found any account lower than '+TAccountComp.AccountNumberToAccountTxtNumber(start.account)+' with balance higher than '+
-      TAccountComp.FormatMoney(start.balance));
+procedure TFRMAccountExplorer.OnPrepareAccountPopupMenu(Sender: TObject; constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
+var
+  accNo: cardinal;
+  account: TAccount;
+begin
+  miSep1.Visible := ASelection.RowCount = 1;
+  miAccountInfo.Visible := ASelection.RowCount = 1;
+  miSendPASC.Visible := IIF(FAccountsMode = wamMyAccounts, True, False);
+  miChangeKey.Visible := IIF(FAccountsMode = wamMyAccounts, True, False);
+  miAccountsMarket.Visible := IIF(FAccountsMode = wamMyAccounts, True, False);
+  miSendPASC.Caption := IIF(ASelection.RowCount = 1, 'Send PASC', 'Send All PASC');
+  miChangeKey.Caption := IIF(ASelection.RowCount = 1, 'Change Key', 'Change All Key');
+  miEnlistAccountsForSale.Caption := IIF(ASelection.RowCount = 1, 'Enlist Account For Sale', 'Enlist All Account For Sale');
+  miDelistAccountsFromSale.Caption := IIF(ASelection.RowCount = 1, 'Delist Account From Sale', 'Delist All Account From Sale');
+  if ASelection.RowCount = 1 then
+  begin
+    if not TAccountComp.AccountTxtNumberToAccountNumber(FAccountsGrid.Rows[ASelection.Row].Account, accNo) then
+      raise Exception.Create('Error Parsing Account Number From Grid');
+    account := TNode.Node.Operations.SafeBoxTransaction.Account(accNo);
+    miEnlistAccountsForSale.Visible := IIF(TAccountComp.IsAccountForSale(account.accountInfo), False, True);
+    miDelistAccountsFromSale.Visible := not miEnlistAccountsForSale.Visible;
+  end;
+  APopupMenu := mnuAccountsPopup;
 end;
 
-procedure TFRMAccountExplorer.miFindNextAccountWithHighBalanceClick(Sender: TObject);
-Var an  : Cardinal;
-  an64 : Int64;
-  start : TAccount;
+procedure TFRMAccountExplorer.miAccountInfoClick(Sender: TObject);
 begin
-  an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
-  if an64<0 then an := 0
-  else an := an64;
-  If an>=TUserInterface.Node.Bank.SafeBox.AccountsCount then exit;
-  start := TUserInterface.Node.Bank.SafeBox.Account(an);
-  while (an<TUserInterface.Node.Bank.SafeBox.AccountsCount)  do begin
-    if TUserInterface.Node.Bank.SafeBox.Account(an).balance>start.balance then break
-    else inc(an);
-  end;
-  if (an<TUserInterface.Node.Bank.SafeBox.AccountsCount) then FAccountsGrid.MoveRowToAccount(an)
-  else raise Exception.Create('Not found any account higher than '+TAccountComp.AccountNumberToAccountTxtNumber(start.account)+' with balance higher than '+
-    TAccountComp.FormatMoney(start.balance));
+  if FAccountsGrid.Selection.RowCount <> 1 then
+    exit;
+  TUserInterface.ShowAccountInfoDialog(Self, FAccountsGrid.SelectedRows[0].__KEY);
 end;
 
-procedure TFRMAccountExplorer.miAccountInformationClick(Sender: TObject);
-Var F : TFRMMemoText;
-  accn : Int64 =-1;
-  acc : TAccount;
-  i : Integer;
-  opr : TOperationResume;
+procedure TFRMAccountExplorer.miSendPASCClick(Sender: TObject);
+var
+  Scoped: TDisposables;
+  wiz: TWIZSendPASCWizard;
+  model: TExecuteOperationsModel;
+  AccountNumbersWithoutChecksum: TArray<cardinal>;
+
+  function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
+  begin
+    Result := ARow.__KEY;
+  end;
+
 begin
-  accn := -1;
-  opr := CT_TOperationResume_NUL;
-  accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
-  if accn<0 then
-    raise Exception.Create('Select an account');
+  wiz := Scoped.AddObject(TWIZSendPASCWizard.Create(nil)) as TWIZSendPASCWizard;
+  model := TExecuteOperationsModel.Create(wiz, omtSendPasc);
+  AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNoWithoutChecksum);
+  model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
+  wiz.Start(model);
+end;
+
+procedure TFRMAccountExplorer.miChangeKeyClick(Sender: TObject);
+var
+  Scoped: TDisposables;
+  wiz: TWIZChangeKeyWizard;
+  model: TExecuteOperationsModel;
+  AccountNumbersWithoutChecksum: TArray<cardinal>;
 
-  if accn >= TUserInterface.Node.Bank.AccountsCount then
-    raise Exception.Create('Account not found');
+  function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
+  begin
+    Result := ARow.__KEY;
+  end;
+
+begin
+  wiz := Scoped.AddObject(TWIZChangeKeyWizard.Create(nil)) as TWIZChangeKeyWizard;
+  model := TExecuteOperationsModel.Create(wiz, omtChangeKey);
+  AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNoWithoutChecksum);
+  model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
+  wiz.Start(model);
+end;
 
-  acc := TUserInterface.Node.Operations.SafeBoxTransaction.Account(accn);
+procedure TFRMAccountExplorer.miEnlistAccountsForSaleClick(Sender: TObject);
+var
+  Scoped: TDisposables;
+  wiz: TWIZEnlistAccountForSaleWizard;
+  model: TExecuteOperationsModel;
+  AccountNumbersWithoutChecksum: TArray<cardinal>;
 
-  i := FAccountOperationsGrid.DrawGrid.Row;
-  if (i>0) and (i<=FAccountOperationsGrid.OperationsResume.Count) then begin
-    opr := FAccountOperationsGrid.OperationsResume.OperationResume[i-1];
+  function GetAccNoWithoutChecksum(constref ARow: variant): cardinal;
+  begin
+    Result := ARow.__KEY;
   end;
 
-  If opr.valid then
-    TUserInterface.ShowAccountOperationInfoDialog(Self, acc, opr)
-  else
-    TUserInterface.ShowAccountInfoDialog(Self, acc);
+begin
+  wiz := Scoped.AddObject(TWIZEnlistAccountForSaleWizard.Create(nil)) as TWIZEnlistAccountForSaleWizard;
+  model := TExecuteOperationsModel.Create(wiz, omtEnlistAccountForSale);
+  AccountNumbersWithoutChecksum := TListTool<variant, cardinal>.Transform(FAccountsGrid.SelectedRows, GetAccNoWithoutChecksum);
+  model.Account.SelectedAccounts := GetAccounts(AccountNumbersWithoutChecksum);
+  wiz.Start(model);
 end;
 
-procedure TFRMAccountExplorer.miAddAccountToSelectedClick(Sender: TObject);
+procedure TFRMAccountExplorer.miDelistAccountsFromSaleClick(Sender: TObject);
 begin
-   // in memory for not exit program - Application.Exit - auto free mem not need control free manual for this send Self!
-  pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
-  sbSelectedAccountsAddClick(Sender);
+  raise ENotImplemented.Create('not yet implemented.');
 end;
 
-procedure TFRMAccountExplorer.miDecodePayloadClick(Sender: TObject);
+procedure TFRMAccountExplorer.OnPrepareOperationsPopupMenu(Sender: TObject; constref ASelection: TVisualGridSelection; out APopupMenu: TPopupMenu);
 begin
-  TUserInterface.ShowOperationInfoDialog(Self, FAccountOperationsGrid.SelectedOperation.OperationHash);
+  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;
+    APopupMenu := nil; // is empty, so dont show
+  end;
 end;
 
-procedure TFRMAccountExplorer.miRemoveAccountFromSelectedClick(Sender: TObject);
+procedure TFRMAccountExplorer.miCopyOphashClick(Sender: TObject);
 begin
-  Self.pcAccountsOptions.ActivePage := Self.tsMultiSelectAccounts;
-  Self.sbSelectedAccountsDelClick(Sender);
+  raise ENotImplemented.Create('Not Implemented');
 end;
 
-{%endregion}
+procedure TFRMAccountExplorer.miOperationInfoClick(Sender: TObject);
+begin
+  if FOperationsGrid.Selection.RowCount = 0 then
+    exit;
+  TUserInterface.ShowOperationInfoDialog(Self, FOperationsGrid.SelectedRows[0].__KEY);
+end;
 
 end.
-

+ 2 - 2
src/gui/UUserInterface.pas

@@ -866,7 +866,7 @@ begin
   FUILock.Acquire;
   Try
     if Assigned(FAccountExplorer) then
-      FAccountExplorer.RefreshAccountsGrid(true);
+     // FAccountExplorer.RefreshAccountsGrid(true);
   finally
     FUILock.Release;
   end;
@@ -878,7 +878,7 @@ begin
   try
     try
       if Assigned(FAccountExplorer) then
-        FAccountExplorer.RefreshAccountsGrid(false);
+       // FAccountExplorer.RefreshAccountsGrid(false);
       FMainForm.SyncControl.UpdateBlockChainState;
     except
       On E:Exception do begin