UFRMWallet.pas 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942
  1. unit UFRMWallet;
  2. {$IFDEF FPC}
  3. {$MODE Delphi}
  4. {$ENDIF}
  5. { Copyright (c) 2016 by Albert Molina
  6. Distributed under the MIT software license, see the accompanying file LICENSE
  7. or visit http://www.opensource.org/licenses/mit-license.php.
  8. This unit is a part of Pascal Coin, a P2P crypto currency without need of
  9. historical operations.
  10. If you like it, consider a donation using BitCoin:
  11. 16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
  12. }
  13. interface
  14. {$I ../config.inc}
  15. uses
  16. {$IFnDEF FPC}
  17. pngimage, Windows, AppEvnts, ShlObj,
  18. {$ELSE}
  19. LCLIntf, LCLType, LMessages,
  20. {$ENDIF}
  21. Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  22. Dialogs, ExtCtrls, ComCtrls, UWallet, StdCtrls,
  23. ULog, Grids, UAppParams,
  24. UBlockChain, UNode, UGridUtils, UAccounts, Menus, ImgList,
  25. UNetProtocol, UCrypto, Buttons, UPoolMining, URPC, UFRMAccountSelect,
  26. UConst;
  27. Const
  28. CM_PC_WalletKeysChanged = WM_USER + 1;
  29. CM_PC_NetConnectionUpdated = WM_USER + 2;
  30. type
  31. TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);
  32. { TFRMWallet }
  33. TFRMWallet = class(TForm)
  34. pnlTop: TPanel;
  35. Image1: TImage;
  36. sbSearchAccount: TSpeedButton;
  37. StatusBar: TStatusBar;
  38. PageControl: TPageControl;
  39. tsMyAccounts: TTabSheet;
  40. tsOperations: TTabSheet;
  41. TrayIcon: TTrayIcon;
  42. TimerUpdateStatus: TTimer;
  43. tsLogs: TTabSheet;
  44. pnlTopLogs: TPanel;
  45. cbShowDebugLogs: TCheckBox;
  46. memoLogs: TMemo;
  47. pnlMyAccountsTop: TPanel;
  48. dgAccounts: TDrawGrid;
  49. cbMyPrivateKeys: TComboBox;
  50. Splitter1: TSplitter;
  51. MainMenu: TMainMenu;
  52. miProject: TMenuItem;
  53. miOptions: TMenuItem;
  54. miPrivatekeys: TMenuItem;
  55. miN1: TMenuItem;
  56. miAbout: TMenuItem;
  57. miAboutPascalCoin: TMenuItem;
  58. miNewOperation: TMenuItem;
  59. Panel1: TPanel;
  60. Label2: TLabel;
  61. ebFilterOperationsStartBlock: TEdit;
  62. ebFilterOperationsEndBlock: TEdit;
  63. tsNodeStats: TTabSheet;
  64. memoNetConnections: TMemo;
  65. memoNetServers: TMemo;
  66. memoNetBlackLists: TMemo;
  67. Label3: TLabel;
  68. Label6: TLabel;
  69. Label7: TLabel;
  70. lblCurrentBlockCaption: TLabel;
  71. lblCurrentBlock: TLabel;
  72. lblCurrentBlockTimeCaption: TLabel;
  73. lblCurrentBlockTime: TLabel;
  74. lblOperationsPendingCaption: TLabel;
  75. lblOperationsPending: TLabel;
  76. lblMiningStatusCaption: TLabel;
  77. lblMinersClients: TLabel;
  78. lblCurrentDifficultyCaption: TLabel;
  79. lblCurrentDifficulty: TLabel;
  80. lblTimeAverage: TLabel;
  81. Label4: TLabel;
  82. tsBlockChain: TTabSheet;
  83. Panel2: TPanel;
  84. Label9: TLabel;
  85. ebBlockChainBlockStart: TEdit;
  86. ebBlockChainBlockEnd: TEdit;
  87. Label8: TLabel;
  88. lblNodeStatus: TLabel;
  89. tsPendingOperations: TTabSheet;
  90. dgPendingOperations: TDrawGrid;
  91. pnlPendingOperations: TPanel;
  92. Label10: TLabel;
  93. cbExploreMyAccounts: TCheckBox;
  94. N1: TMenuItem;
  95. MiClose: TMenuItem;
  96. MiDecodePayload: TMenuItem;
  97. ImageListIcons: TImageList;
  98. ApplicationEvents: {$IFDEF FPC}TApplicationProperties{$ELSE}TApplicationEvents{$ENDIF};
  99. Label5: TLabel;
  100. lblCurrentAccounts: TLabel;
  101. lblTimeAverageAux: TLabel;
  102. tsMessages: TTabSheet;
  103. lbNetConnections: TListBox;
  104. bbSendAMessage: TButton;
  105. Label11: TLabel;
  106. memoMessages: TMemo;
  107. memoMessageToSend: TMemo;
  108. Label12: TLabel;
  109. Label13: TLabel;
  110. Label14: TLabel;
  111. Label16: TLabel;
  112. lblBlocksFound: TLabel;
  113. pnlAccounts: TPanel;
  114. pnlAccountsInfo: TPanel;
  115. Label17: TLabel;
  116. Label19: TLabel;
  117. lblAccountsCount: TLabel;
  118. lblAccountsBalance: TLabel;
  119. lblReceivedMessages: TLabel;
  120. lblBuild: TLabel;
  121. ebFindAccountNumber: TEdit;
  122. Label18: TLabel;
  123. IPnodes1: TMenuItem;
  124. bbChangeKeyName: TBitBtn;
  125. pcAccountsOptions: TPageControl;
  126. tsAccountOperations: TTabSheet;
  127. dgAccountOperations: TDrawGrid;
  128. tsMultiSelectAccounts: TTabSheet;
  129. dgSelectedAccounts: TDrawGrid;
  130. pnlSelectedAccountsTop: TPanel;
  131. pnlSelectedAccountsBottom: TPanel;
  132. pnlSelectedAccountsLeft: TPanel;
  133. sbSelectedAccountsAdd: TSpeedButton;
  134. sbSelectedAccountsAddAll: TSpeedButton;
  135. sbSelectedAccountsDel: TSpeedButton;
  136. sbSelectedAccountsDelAll: TSpeedButton;
  137. Label20: TLabel;
  138. lblSelectedAccountsCount: TLabel;
  139. Label22: TLabel;
  140. lblSelectedAccountsBalance: TLabel;
  141. bbSelectedAccountsOperation: TBitBtn;
  142. Label15: TLabel;
  143. MiOperations: TMenuItem;
  144. MiAddaccounttoSelected: TMenuItem;
  145. MiRemoveaccountfromselected: TMenuItem;
  146. N2: TMenuItem;
  147. MiMultiaccountoperation: TMenuItem;
  148. N3: TMenuItem;
  149. MiFindnextaccountwithhighbalance: TMenuItem;
  150. MiFindpreviousaccountwithhighbalance: TMenuItem;
  151. MiFindaccount: TMenuItem;
  152. cbFilterAccounts: TCheckBox;
  153. ebFilterAccountByBalanceMin: TEdit;
  154. ebFilterAccountByBalanceMax: TEdit;
  155. bbAccountsRefresh: TBitBtn;
  156. dgBlockChainExplorer: TDrawGrid;
  157. dgOperationsExplorer: TDrawGrid;
  158. MiFindOperationbyOpHash: TMenuItem;
  159. MiAccountInformation: TMenuItem;
  160. procedure FormCreate(Sender: TObject);
  161. procedure FormDestroy(Sender: TObject);
  162. procedure sbSearchAccountClick(Sender: TObject);
  163. procedure TimerUpdateStatusTimer(Sender: TObject);
  164. procedure cbMyPrivateKeysChange(Sender: TObject);
  165. procedure dgAccountsClick(Sender: TObject);
  166. procedure miOptionsClick(Sender: TObject);
  167. procedure miAboutPascalCoinClick(Sender: TObject);
  168. procedure miNewOperationClick(Sender: TObject);
  169. procedure miPrivatekeysClick(Sender: TObject);
  170. procedure dgAccountsColumnMoved(Sender: TObject; FromIndex,
  171. ToIndex: Integer);
  172. procedure dgAccountsFixedCellClick(Sender: TObject; ACol, ARow: Integer);
  173. procedure PageControlChange(Sender: TObject);
  174. procedure ebFilterOperationsAccountExit(Sender: TObject);
  175. procedure ebFilterOperationsAccountKeyPress(Sender: TObject; var Key: Char);
  176. procedure ebBlockChainBlockStartExit(Sender: TObject);
  177. procedure ebBlockChainBlockStartKeyPress(Sender: TObject; var Key: Char);
  178. procedure cbExploreMyAccountsClick(Sender: TObject);
  179. procedure MiCloseClick(Sender: TObject);
  180. procedure MiDecodePayloadClick(Sender: TObject);
  181. procedure TrayIconDblClick(Sender: TObject);
  182. procedure ApplicationEventsMinimize(Sender: TObject);
  183. procedure bbSendAMessageClick(Sender: TObject);
  184. procedure lblReceivedMessagesClick(Sender: TObject);
  185. procedure ebFindAccountNumberChange(Sender: TObject);
  186. procedure ebFindAccountNumberExit(Sender: TObject);
  187. procedure IPnodes1Click(Sender: TObject);
  188. procedure bbChangeKeyNameClick(Sender: TObject);
  189. procedure sbSelectedAccountsAddClick(Sender: TObject);
  190. procedure sbSelectedAccountsAddAllClick(Sender: TObject);
  191. procedure sbSelectedAccountsDelClick(Sender: TObject);
  192. procedure sbSelectedAccountsDelAllClick(Sender: TObject);
  193. procedure bbSelectedAccountsOperationClick(Sender: TObject);
  194. procedure MiAddaccounttoSelectedClick(Sender: TObject);
  195. procedure MiRemoveaccountfromselectedClick(Sender: TObject);
  196. procedure MiMultiaccountoperationClick(Sender: TObject);
  197. procedure MiFindnextaccountwithhighbalanceClick(Sender: TObject);
  198. procedure MiFindpreviousaccountwithhighbalanceClick(Sender: TObject);
  199. procedure MiFindaccountClick(Sender: TObject);
  200. procedure bbAccountsRefreshClick(Sender: TObject);
  201. procedure ebFilterAccountByBalanceMinExit(Sender: TObject);
  202. procedure ebFilterAccountByBalanceMinKeyPress(Sender: TObject;
  203. var Key: Char);
  204. procedure cbFilterAccountsClick(Sender: TObject);
  205. procedure MiFindOperationbyOpHashClick(Sender: TObject);
  206. procedure MiAccountInformationClick(Sender: TObject);
  207. private
  208. FLastNodesCacheUpdatedTS : TDateTime;
  209. FBackgroundPanel : TPanel;
  210. FMinersBlocksFound: Integer;
  211. procedure SetMinersBlocksFound(const Value: Integer);
  212. Procedure CheckIsReady;
  213. Procedure FinishedLoadingApp;
  214. Procedure FillAccountInformation(Const Strings : TStrings; Const AccountNumber : Cardinal);
  215. Procedure FillOperationInformation(Const Strings : TStrings; Const OperationResume : TOperationResume);
  216. protected
  217. { Private declarations }
  218. FNode : TNode;
  219. FIsActivated : Boolean;
  220. FWalletKeys : TWalletKeysExt;
  221. FLog : TLog;
  222. FAppParams : TAppParams;
  223. FNodeNotifyEvents : TNodeNotifyEvents;
  224. FAccountsGrid : TAccountsGrid;
  225. FSelectedAccountsGrid : TAccountsGrid;
  226. FOperationsAccountGrid : TOperationsGrid;
  227. FPendingOperationsGrid : TOperationsGrid;
  228. FOrderedAccountsKeyList : TOrderedAccountKeysList;
  229. FOperationsExplorerGrid : TOperationsGrid;
  230. FBlockChainGrid : TBlockChainGrid;
  231. FMinerPrivateKeyType : TMinerPrivateKey;
  232. FUpdating : Boolean;
  233. FMessagesUnreadCount : Integer;
  234. FMinAccountBalance : Int64;
  235. FMaxAccountBalance : Int64;
  236. FPoolMiningServer : TPoolMiningServer;
  237. FRPCServer : TRPCServer;
  238. FMustProcessWalletChanged : Boolean;
  239. FMustProcessNetConnectionUpdated : Boolean;
  240. Procedure OnNewAccount(Sender : TObject);
  241. Procedure OnReceivedHelloMessage(Sender : TObject);
  242. Procedure OnNetStatisticsChanged(Sender : TObject);
  243. procedure OnNewLog(logtype : TLogType; Time : TDateTime; ThreadID : TThreadID; Const sender, logtext : AnsiString);
  244. procedure OnWalletChanged(Sender : TObject);
  245. procedure OnNetConnectionsUpdated(Sender : TObject);
  246. procedure OnNetNodeServersUpdated(Sender : TObject);
  247. procedure OnNetBlackListUpdated(Sender : TObject);
  248. Procedure OnNodeMessageEvent(NetConnection : TNetConnection; MessageData : TRawBytes);
  249. Procedure OnSelectedAccountsGridUpdated(Sender : TObject);
  250. Procedure OnMiningServerNewBlockFound(Sender : TObject);
  251. Procedure UpdateConnectionStatus;
  252. Procedure UpdateAccounts(RefreshData : Boolean);
  253. Procedure UpdateBlockChainState;
  254. Procedure UpdatePrivateKeys;
  255. Procedure UpdateOperations;
  256. Procedure LoadAppParams;
  257. Procedure SaveAppParams;
  258. Procedure UpdateConfigChanged;
  259. Procedure UpdateNodeStatus;
  260. Procedure UpdateAvailableConnections;
  261. procedure Activate; override;
  262. Function ForceMining : Boolean; virtual;
  263. Function GetAccountKeyForMiner : TAccountKey;
  264. Procedure DoUpdateAccounts;
  265. Function DoUpdateAccountsFilter : Boolean;
  266. procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
  267. procedure CM_NetConnectionUpdated(var Msg: TMessage); message CM_PC_NetConnectionUpdated;
  268. public
  269. { Public declarations }
  270. Property WalletKeys : TWalletKeysExt read FWalletKeys;
  271. Property MinersBlocksFound : Integer read FMinersBlocksFound write SetMinersBlocksFound;
  272. end;
  273. var
  274. FRMWallet: TFRMWallet;
  275. implementation
  276. {$IFnDEF FPC}
  277. {$R *.dfm}
  278. {$ELSE}
  279. {$R *.lfm}
  280. {$ENDIF}
  281. Uses UFolderHelper, UOpenSSL, UOpenSSLdef, UTime, UFileStorage,
  282. UThread, UOpTransaction, UECIES, UFRMPascalCoinWalletConfig,
  283. UFRMAbout, UFRMOperation, UFRMWalletKeys, UFRMPayloadDecoder, UFRMNodesIp, UFRMMemoText, USettings, UCommon;
  284. Type
  285. TThreadActivate = Class(TPCThread)
  286. protected
  287. procedure BCExecute; override;
  288. End;
  289. { TThreadActivate }
  290. procedure TThreadActivate.BCExecute;
  291. begin
  292. // Read Operations saved from disk
  293. TNode.Node.InitSafeboxAndOperations; // New Build 2.1.4 to load pending operations buffer
  294. TNode.Node.AutoDiscoverNodes(CT_Discover_IPs);
  295. TNode.Node.NetServer.Active := true;
  296. Synchronize( FRMWallet.DoUpdateAccounts );
  297. Synchronize( FRMWallet.FinishedLoadingApp );
  298. end;
  299. { TFRMWallet }
  300. procedure TFRMWallet.Activate;
  301. Var ips : AnsiString;
  302. nsarr : TNodeServerAddressArray;
  303. begin
  304. inherited;
  305. if FIsActivated then exit;
  306. FIsActivated := true;
  307. try
  308. // Check OpenSSL dll
  309. if Not LoadSSLCrypt then raise Exception.Create('Cannot load '+SSL_C_LIB+#10+'To use this software make sure this file is available on you system or reinstall the application');
  310. TCrypto.InitCrypto;
  311. // Read Wallet
  312. Try
  313. FWalletKeys.WalletFileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'WalletKeys.dat';
  314. Except
  315. On E:Exception do begin
  316. E.Message := 'Cannot open your wallet... Perhaps another instance of Pascal Coin is active!'+#10+#10+E.Message;
  317. Raise;
  318. end;
  319. End;
  320. ips := FAppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].GetAsString('');
  321. TNode.DecodeIpStringToNodeServerAddressArray(ips,nsarr);
  322. TNetData.NetData.DiscoverFixedServersOnly(nsarr);
  323. setlength(nsarr,0);
  324. // Creating Node:
  325. FNode := TNode.Node;
  326. FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
  327. FNode.PeerCache := FAppParams.ParamByName[CT_PARAM_PeerCache].GetAsString('')+';'+CT_Discover_IPs;
  328. // Create RPC server
  329. FRPCServer := TRPCServer.Create;
  330. FRPCServer.WalletKeys := WalletKeys;
  331. FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
  332. FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
  333. WalletKeys.SafeBox := FNode.Bank.SafeBox;
  334. // Check Database
  335. FNode.Bank.StorageClass := TFileStorage;
  336. TFileStorage(FNode.Bank.Storage).DatabaseFolder := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'Data';
  337. TFileStorage(FNode.Bank.Storage).Initialize;
  338. // Init Grid
  339. //FAccountsGrid.Node := FNode;
  340. FSelectedAccountsGrid.Node := FNode;
  341. FWalletKeys.OnChanged.Add( OnWalletChanged );
  342. FAccountsGrid.Node := FNode;
  343. FOperationsAccountGrid.Node := FNode;
  344. // Reading database
  345. TThreadActivate.Create(false).FreeOnTerminate := true;
  346. FNodeNotifyEvents.Node := FNode;
  347. // Init
  348. TNetData.NetData.OnReceivedHelloMessage := OnReceivedHelloMessage;
  349. TNetData.NetData.OnStatisticsChanged := OnNetStatisticsChanged;
  350. TNetData.NetData.OnNetConnectionsUpdated := onNetConnectionsUpdated;
  351. TNetData.NetData.OnNodeServersUpdated := OnNetNodeServersUpdated;
  352. TNetData.NetData.OnBlackListUpdated := OnNetBlackListUpdated;
  353. //
  354. TimerUpdateStatus.Interval := 1000;
  355. TimerUpdateStatus.Enabled := true;
  356. UpdateConfigChanged;
  357. Except
  358. On E:Exception do begin
  359. E.Message := 'An error occurred during initialization. Application cannot continue:'+#10+#10+E.Message+#10+#10+'Application will close...';
  360. Application.MessageBox(PChar(E.Message),PChar(Application.Title),MB_ICONERROR+MB_OK);
  361. Halt;
  362. end;
  363. end;
  364. UpdatePrivateKeys;
  365. UpdateAccounts(false);
  366. if FAppParams.ParamByName[CT_PARAM_FirstTime].GetAsBoolean(true) then begin
  367. FAppParams.ParamByName[CT_PARAM_FirstTime].SetAsBoolean(false);
  368. miAboutPascalCoinClick(Nil);
  369. end;
  370. end;
  371. procedure TFRMWallet.ApplicationEventsMinimize(Sender: TObject);
  372. begin
  373. {$IFnDEF FPC}
  374. Hide();
  375. WindowState := wsMinimized;
  376. TimerUpdateStatus.Enabled := false;
  377. { Show the animated tray icon and also a hint balloon. }
  378. TrayIcon.Visible := True;
  379. TrayIcon.ShowBalloonHint;
  380. {$ENDIF}
  381. end;
  382. procedure TFRMWallet.bbAccountsRefreshClick(Sender: TObject);
  383. begin
  384. UpdateAccounts(true);
  385. end;
  386. procedure TFRMWallet.bbChangeKeyNameClick(Sender: TObject);
  387. var i : Integer;
  388. name : String;
  389. begin
  390. if (cbMyPrivateKeys.ItemIndex<0) then exit;
  391. i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
  392. if (i<0) Or (i>=FWalletKeys.Count) then raise Exception.Create('Must select a Key');
  393. name := FWalletKeys.Key[i].Name;
  394. if InputQuery('Change Key name','Input new name',name) then begin
  395. FWalletKeys.SetName(i,name);
  396. end;
  397. UpdatePrivateKeys;
  398. end;
  399. procedure TFRMWallet.bbSelectedAccountsOperationClick(Sender: TObject);
  400. var l : TOrderedCardinalList;
  401. begin
  402. CheckIsReady;
  403. if FSelectedAccountsGrid.AccountsCount<=0 then raise Exception.Create('Must select at least 1 account');
  404. With TFRMOperation.Create(Self) do
  405. Try
  406. l := FSelectedAccountsGrid.LockAccountsList;
  407. try
  408. SenderAccounts.CopyFrom(l);
  409. finally
  410. FSelectedAccountsGrid.UnlockAccountsList;
  411. end;
  412. DefaultFee := FAppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
  413. WalletKeys := FWalletKeys;
  414. ShowModal;
  415. Finally
  416. Free;
  417. End;
  418. end;
  419. procedure TFRMWallet.bbSendAMessageClick(Sender: TObject);
  420. Var basem,m : String;
  421. them, errors : AnsiString;
  422. i,n : Integer;
  423. nc : TNetConnection;
  424. begin
  425. CheckIsReady;
  426. if (lbNetConnections.SelCount<=0) Or (lbNetConnections.ItemIndex<0) then raise Exception.Create('Select at least one connection');
  427. if lbNetConnections.SelCount<=0 then n := 1
  428. else n := lbNetConnections.SelCount;
  429. basem := memoMessageToSend.Lines.Text;
  430. m := '';
  431. // Clear non valid characters:
  432. for i := 1 to length(basem) do begin
  433. if basem[i] in [#32..#127] then m := m + basem[i]
  434. else m:=m+'.';
  435. end;
  436. if trim(m)='' then raise Exception.Create('No message');
  437. if Application.MessageBox(PChaR('Send this message to '+inttostr(n)+' nodes?'+#10+
  438. 'NOTE: Sending unauthorized messages will be considered spam and you will be banned'+#10+
  439. #10+
  440. 'Message: '+#10+
  441. m),PChar(Application.Title),MB_ICONQUESTION+MB_YESNO+MB_DEFBUTTON1)<>IdYes then exit;
  442. them := m;
  443. if n>1 then begin
  444. for i := 0 to lbNetConnections.Items.Count - 1 do begin
  445. if lbNetConnections.Selected[i] then begin
  446. nc := TNetConnection(lbNetconnections.Items.Objects[i]);
  447. if TNetData.NetData.ConnectionExistsAndActive(nc) then begin
  448. FNode.SendNodeMessage(nc,m,errors);
  449. memoMessages.Lines.Add(DateTimeToStr(now)+' Sent to '+nc.ClientRemoteAddr+' > '+m);
  450. end;
  451. end;
  452. end;
  453. end else begin
  454. nc := TNetConnection(lbNetconnections.Items.Objects[lbNetconnections.ItemIndex]);
  455. if TNetData.NetData.ConnectionExistsAndActive(nc) then begin
  456. FNode.SendNodeMessage(nc,m,errors);
  457. memoMessages.Lines.Add(DateTimeToStr(now)+' Sent to '+nc.ClientRemoteAddr+' > '+m);
  458. end;
  459. end;
  460. Application.MessageBox(PChaR('Message sent to '+inttostr(n)+' nodes'+#10+
  461. 'Message: '+#10+m),PChar(Application.Title),MB_ICONINFORMATION+MB_OK);
  462. end;
  463. procedure TFRMWallet.cbExploreMyAccountsClick(Sender: TObject);
  464. begin
  465. cbMyPrivateKeys.Enabled := cbExploreMyAccounts.Checked;
  466. UpdateAccounts(true);
  467. UpdateOperations;
  468. end;
  469. procedure TFRMWallet.cbFilterAccountsClick(Sender: TObject);
  470. begin
  471. If not DoUpdateAccountsFilter then UpdateAccounts(true);
  472. end;
  473. procedure TFRMWallet.cbMyPrivateKeysChange(Sender: TObject);
  474. begin
  475. UpdateAccounts(true);
  476. end;
  477. procedure TFRMWallet.CheckIsReady;
  478. Var isready : AnsiString;
  479. begin
  480. if Not Assigned(FNode) then Abort;
  481. if Not FNode.IsReady(isready) then begin
  482. Raise Exception.Create('You cannot do this operation now:'+#10+#10+isready);
  483. end;
  484. end;
  485. procedure TFRMWallet.CM_NetConnectionUpdated(var Msg: TMessage);
  486. Const CT_BooleanToString : Array[Boolean] of String = ('False','True');
  487. Var i : integer;
  488. NC : TNetConnection;
  489. l : TList;
  490. sClientApp, sLastConnTime : String;
  491. strings, sNSC, sRS, sDisc : TStrings;
  492. hh,nn,ss,ms : Word;
  493. begin
  494. Try
  495. if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
  496. try
  497. strings := memoNetConnections.Lines;
  498. sNSC := TStringList.Create;
  499. sRS := TStringList.Create;
  500. sDisc := TStringList.Create;
  501. strings.BeginUpdate;
  502. Try
  503. for i := 0 to l.Count - 1 do begin
  504. NC := l[i];
  505. If NC.Client.BytesReceived>0 then begin
  506. sClientApp := '['+IntToStr(NC.NetProtocolVersion.protocol_version)+'-'+IntToStr(NC.NetProtocolVersion.protocol_available)+'] '+NC.ClientAppVersion;
  507. end else begin
  508. sClientApp := '(no data)';
  509. end;
  510. if NC.Connected then begin
  511. if NC.Client.LastCommunicationTime>1000 then begin
  512. DecodeTime(now - NC.Client.LastCommunicationTime,hh,nn,ss,ms);
  513. if (hh=0) and (nn=0) And (ss<10) then begin
  514. sLastConnTime := ' - Last comunication <10 sec.';
  515. end else begin
  516. sLastConnTime := Format(' - Last comunication %.2dm%.2ds',[(hh*60)+nn,ss]);
  517. end;
  518. end else begin
  519. sLastConnTime := '';
  520. end;
  521. if NC is TNetServerClient then begin
  522. sNSC.Add(Format('Client: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
  523. [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
  524. end else begin
  525. if NC.IsMyselfServer then sNSC.Add(Format('MySelf IP:%s Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
  526. [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]))
  527. else begin
  528. sRS.Add(Format('Remote Server: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
  529. [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
  530. end;
  531. end;
  532. end else begin
  533. if NC is TNetServerClient then begin
  534. sDisc.Add(Format('Disconnected client: IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
  535. end else if NC.IsMyselfServer then begin
  536. sDisc.Add(Format('Disconnected MySelf IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
  537. end else begin
  538. sDisc.Add(Format('Disconnected Remote Server: IP:%s %s - %s',[NC.ClientRemoteAddr,CT_BooleanToString[NC.Connected],sClientApp]));
  539. end;
  540. end;
  541. end;
  542. strings.Clear;
  543. strings.Add(Format('Connections Updated %s Clients:%d Servers:%d (valid servers:%d)',[DateTimeToStr(now),sNSC.Count,sRS.Count,TNetData.NetData.NetStatistics.ServersConnectionsWithResponse]));
  544. strings.AddStrings(sRS);
  545. strings.AddStrings(sNSC);
  546. if sDisc.Count>0 then begin
  547. strings.Add('');
  548. strings.Add('Disconnected connections: '+Inttostr(sDisc.Count));
  549. strings.AddStrings(sDisc);
  550. end;
  551. Finally
  552. strings.EndUpdate;
  553. sNSC.Free;
  554. sRS.Free;
  555. sDisc.Free;
  556. End;
  557. //CheckMining;
  558. finally
  559. TNetData.NetData.NetConnections.UnlockList;
  560. end;
  561. Finally
  562. FMustProcessNetConnectionUpdated := false;
  563. End;
  564. end;
  565. procedure TFRMWallet.CM_WalletChanged(var Msg: TMessage);
  566. begin
  567. UpdatePrivateKeys;
  568. FMustProcessWalletChanged := false;
  569. end;
  570. procedure TFRMWallet.dgAccountsClick(Sender: TObject);
  571. begin
  572. UpdateOperations;
  573. end;
  574. procedure TFRMWallet.dgAccountsColumnMoved(Sender: TObject; FromIndex, ToIndex: Integer);
  575. begin
  576. SaveAppParams;
  577. end;
  578. procedure TFRMWallet.dgAccountsFixedCellClick(Sender: TObject; ACol,
  579. ARow: Integer);
  580. begin
  581. SaveAppParams;
  582. end;
  583. procedure TFRMWallet.DoUpdateAccounts;
  584. begin
  585. UpdateAccounts(true);
  586. end;
  587. function TFRMWallet.DoUpdateAccountsFilter: Boolean;
  588. Var m,bmin,bmax:Int64;
  589. doupd : Boolean;
  590. begin
  591. if FUpdating then exit;
  592. FUpdating := true;
  593. Try
  594. If Not TAccountComp.TxtToMoney(ebFilterAccountByBalanceMin.Text,bmin) then bmin := 0;
  595. If not TAccountComp.TxtToMoney(ebFilterAccountByBalanceMax.Text,bmax) then bmax := CT_MaxWalletAmount;
  596. if (bmax<bmin) or (bmax=0) then bmax := CT_MaxWalletAmount;
  597. if bmin>bmax then bmin := 0;
  598. doupd := (bmin<>FMinAccountBalance) Or (bmax<>FMaxAccountBalance);
  599. FMinAccountBalance := bmin;
  600. FMaxAccountBalance := bmax;
  601. if bmin>0 then
  602. ebFilterAccountByBalanceMin.Text:=TAccountComp.FormatMoney(bmin)
  603. else ebFilterAccountByBalanceMin.Text := '';
  604. if bmax<CT_MaxWalletAmount then
  605. ebFilterAccountByBalanceMax.Text := TAccountComp.FormatMoney(bmax)
  606. else ebFilterAccountByBalanceMax.Text := '';
  607. if cbFilterAccounts.Checked then begin
  608. ebFilterAccountByBalanceMin.ParentFont := true;
  609. ebFilterAccountByBalanceMax.ParentFont := true;
  610. end else begin
  611. ebFilterAccountByBalanceMin.font.Color := clDkGray;
  612. ebFilterAccountByBalanceMax.font.Color := clDkGray;
  613. end;
  614. Finally
  615. FUpdating := false;
  616. End;
  617. if doupd then UpdateAccounts(true);
  618. Result := doupd;
  619. end;
  620. procedure TFRMWallet.ebBlockChainBlockStartExit(Sender: TObject);
  621. var bstart,bend : Int64;
  622. begin
  623. If FUpdating then exit;
  624. FUpdating := True;
  625. Try
  626. bstart := StrToInt64Def(ebBlockChainBlockStart.Text,-1);
  627. bend := StrToInt64Def(ebBlockChainBlockEnd.Text,-1);
  628. FBlockChainGrid.SetBlocks(bstart,bend);
  629. if FBlockChainGrid.BlockStart>=0 then ebBlockChainBlockStart.Text := Inttostr(FBlockChainGrid.BlockStart) else ebBlockChainBlockStart.Text := '';
  630. if FBlockChainGrid.BlockEnd>=0 then ebBlockChainBlockEnd.Text := Inttostr(FBlockChainGrid.BlockEnd) else ebBlockChainBlockEnd.Text := '';
  631. Finally
  632. FUpdating := false;
  633. End;
  634. end;
  635. procedure TFRMWallet.ebBlockChainBlockStartKeyPress(Sender: TObject;
  636. var Key: Char);
  637. begin
  638. if key=#13 then ebBlockChainBlockStartExit(Nil);
  639. end;
  640. procedure TFRMWallet.ebFilterAccountByBalanceMinExit(Sender: TObject);
  641. begin
  642. DoUpdateAccountsFilter;
  643. end;
  644. procedure TFRMWallet.ebFilterAccountByBalanceMinKeyPress(Sender: TObject;
  645. var Key: Char);
  646. begin
  647. if key=#13 then DoUpdateAccountsFilter;
  648. end;
  649. procedure TFRMWallet.ebFilterOperationsAccountExit(Sender: TObject);
  650. Var bstart,bend : Int64;
  651. begin
  652. If FUpdating then exit;
  653. FUpdating := True;
  654. Try
  655. bstart := StrToInt64Def(ebFilterOperationsStartBlock.Text,-1);
  656. if bstart>=0 then ebFilterOperationsStartBlock.Text := Inttostr(bstart) else ebFilterOperationsStartBlock.Text := '';
  657. bend := StrToInt64Def(ebFilterOperationsEndBlock.Text,-1);
  658. if bend>=0 then ebFilterOperationsEndBlock.Text := Inttostr(bend) else ebFilterOperationsEndBlock.Text := '';
  659. FOperationsExplorerGrid.SetBlocks(bstart,bend);
  660. Finally
  661. FUpdating := false;
  662. End;
  663. end;
  664. procedure TFRMWallet.ebFilterOperationsAccountKeyPress(Sender: TObject;
  665. var Key: Char);
  666. begin
  667. if key=#13 then ebFilterOperationsAccountExit(Nil);
  668. end;
  669. procedure TFRMWallet.ebFindAccountNumberChange(Sender: TObject);
  670. Var an : Cardinal;
  671. begin
  672. if Trim(ebFindAccountNumber.Text)='' then begin
  673. ebFindAccountNumber.Color := clWindow;
  674. ebFindAccountNumber.Font.Color := clDkGray;
  675. end else if TAccountComp.AccountTxtNumberToAccountNumber(ebFindAccountNumber.Text,an) then begin
  676. ebFindAccountNumber.Color := clWindow;
  677. if FAccountsGrid.MoveRowToAccount(an) then begin
  678. ebFindAccountNumber.Font.Color := clWindowText;
  679. end else begin
  680. ebFindAccountNumber.Font.Color := clRed;
  681. end;
  682. end else begin
  683. // Invalid value
  684. ebFindAccountNumber.Color := clRed;
  685. ebFindAccountNumber.Font.Color := clWindowText;
  686. end;
  687. end;
  688. procedure TFRMWallet.ebFindAccountNumberExit(Sender: TObject);
  689. begin
  690. ebFindAccountNumber.Text := '';
  691. end;
  692. procedure TFRMWallet.FinishedLoadingApp;
  693. begin
  694. FPoolMiningServer := TPoolMiningServer.Create;
  695. FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
  696. FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
  697. FPoolMiningServer.MinerPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
  698. FNode.Operations.AccountKey := GetAccountKeyForMiner;
  699. FPoolMiningServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
  700. FPoolMiningServer.OnMiningServerNewBlockFound := OnMiningServerNewBlockFound;
  701. If Assigned(FBackgroundPanel) then begin
  702. FreeAndNil(FBackgroundPanel);
  703. end;
  704. PageControl.Visible:=True;
  705. PageControl.Enabled:=True;
  706. end;
  707. procedure TFRMWallet.FillAccountInformation(const Strings: TStrings; Const AccountNumber: Cardinal);
  708. Var account : TAccount;
  709. s : String;
  710. begin
  711. if AccountNumber<0 then exit;
  712. account := FNode.Operations.SafeBoxTransaction.Account(AccountNumber);
  713. if account.name<>'' then s:='Name: '+account.name
  714. else s:='';
  715. Strings.Add(Format('Account: %s %s Type:%d',[TAccountComp.AccountNumberToAccountTxtNumber(AccountNumber),s,account.account_type]));
  716. Strings.Add('');
  717. Strings.Add(Format('Current balance: %s',[TAccountComp.FormatMoney(account.balance)]));
  718. Strings.Add('');
  719. Strings.Add(Format('Updated on block: %d (%d blocks ago)',[account.updated_block,FNode.Bank.BlocksCount-account.updated_block]));
  720. Strings.Add(Format('Public key type: %s',[TAccountComp.GetECInfoTxt(account.accountInfo.accountKey.EC_OpenSSL_NID)]));
  721. Strings.Add(Format('Base58 Public key: %s',[TAccountComp.AccountPublicKeyExport(account.accountInfo.accountKey)]));
  722. if TAccountComp.IsAccountForSale(account.accountInfo) then begin
  723. Strings.Add('');
  724. Strings.Add('** Account is for sale: **');
  725. Strings.Add(Format('Price: %s',[TAccountComp.FormatMoney(account.accountInfo.price)]));
  726. Strings.Add(Format('Seller account (where to pay): %s',[TAccountComp.AccountNumberToAccountTxtNumber(account.accountInfo.account_to_pay)]));
  727. if TAccountComp.IsAccountForSaleAcceptingTransactions(account.accountInfo) then begin
  728. Strings.Add('');
  729. Strings.Add('** Private sale **');
  730. Strings.Add(Format('New Base58 Public key: %s',[TAccountComp.AccountPublicKeyExport(account.accountInfo.new_publicKey)]));
  731. Strings.Add('');
  732. if TAccountComp.IsAccountLocked(account.accountInfo,FNode.Bank.BlocksCount) then begin
  733. Strings.Add(Format('PURCHASE IS SECURE UNTIL BLOCK %d (current %d, remains %d)',
  734. [account.accountInfo.locked_until_block,FNode.Bank.BlocksCount,account.accountInfo.locked_until_block-FNode.Bank.BlocksCount]));
  735. end else begin
  736. Strings.Add(Format('PURCHASE IS NOT SECURE (Expired on block %d, current %d)',
  737. [account.accountInfo.locked_until_block,FNode.Bank.BlocksCount]));
  738. end;
  739. end;
  740. end;
  741. end;
  742. procedure TFRMWallet.FillOperationInformation(const Strings: TStrings; Const OperationResume: TOperationResume);
  743. begin
  744. If (not OperationResume.valid) then exit;
  745. If OperationResume.Block<FNode.Bank.BlocksCount then
  746. if (OperationResume.NOpInsideBlock>=0) then begin
  747. Strings.Add(Format('Block: %d/%d',[OperationResume.Block,OperationResume.NOpInsideBlock]))
  748. end else begin
  749. Strings.Add(Format('Block: %d',[OperationResume.Block]))
  750. end
  751. else Strings.Add('** Pending operation not included on blockchain **');
  752. Strings.Add(Format('%s',[OperationResume.OperationTxt]));
  753. Strings.Add(Format('OpType:%d Subtype:%d',[OperationResume.OpType,OperationResume.OpSubtype]));
  754. Strings.Add(Format('Operation Hash (ophash): %s',[TCrypto.ToHexaString(OperationResume.OperationHash)]));
  755. If (OperationResume.OperationHash_OLD<>'') then begin
  756. Strings.Add(Format('Old Operation Hash (old_ophash): %s',[TCrypto.ToHexaString(OperationResume.OperationHash_OLD)]));
  757. end;
  758. if (OperationResume.OriginalPayload<>'') then begin
  759. Strings.Add(Format('Payload length:%d',[length(OperationResume.OriginalPayload)]));
  760. If OperationResume.PrintablePayload<>'' then begin
  761. Strings.Add(Format('Payload (human): %s',[OperationResume.PrintablePayload]));
  762. end;
  763. Strings.Add(Format('Payload (Hexadecimal): %s',[TCrypto.ToHexaString(OperationResume.OriginalPayload)]));
  764. end;
  765. If OperationResume.Balance>=0 then begin
  766. Strings.Add(Format('Final balance: %s',[TAccountComp.FormatMoney(OperationResume.Balance)]));
  767. end;
  768. end;
  769. function TFRMWallet.ForceMining: Boolean;
  770. begin
  771. Result := false;
  772. end;
  773. procedure TFRMWallet.FormCreate(Sender: TObject);
  774. Var i : Integer;
  775. begin
  776. FLastNodesCacheUpdatedTS := Now;
  777. FBackgroundPanel := Nil;
  778. FMustProcessWalletChanged := false;
  779. FMustProcessNetConnectionUpdated := false;
  780. FRPCServer := Nil;
  781. FNode := Nil;
  782. FPoolMiningServer := Nil;
  783. FMinAccountBalance := 0;
  784. FMaxAccountBalance := CT_MaxWalletAmount;
  785. FMessagesUnreadCount := 0;
  786. lblReceivedMessages.Visible := false;
  787. memoNetConnections.Lines.Clear;
  788. memoNetServers.Lines.Clear;
  789. memoNetBlackLists.Lines.Clear;
  790. memoMessages.Lines.Clear;
  791. memoMessageToSend.Lines.Clear;
  792. FUpdating := false;
  793. FOrderedAccountsKeyList := Nil;
  794. TimerUpdateStatus.Enabled := false;
  795. FIsActivated := false;
  796. FWalletKeys := TWalletKeysExt.Create(Self);
  797. for i := 0 to StatusBar.Panels.Count - 1 do begin
  798. StatusBar.Panels[i].Text := '';
  799. end;
  800. FLog := TLog.Create(Self);
  801. FLog.OnNewLog := OnNewLog;
  802. FLog.SaveTypes := [];
  803. If Not ForceDirectories(TFolderHelper.GetPascalCoinDataFolder) then raise Exception.Create('Cannot create dir: '+TFolderHelper.GetPascalCoinDataFolder);
  804. FAppParams := TAppParams.Create(self);
  805. FAppParams.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'AppParams.prm';
  806. FNodeNotifyEvents := TNodeNotifyEvents.Create(Self);
  807. FNodeNotifyEvents.OnBlocksChanged := OnNewAccount;
  808. FNodeNotifyEvents.OnNodeMessageEvent := OnNodeMessageEvent;
  809. FAccountsGrid := TAccountsGrid.Create(Self);
  810. FAccountsGrid.DrawGrid := dgAccounts;
  811. FAccountsGrid.AllowMultiSelect := True;
  812. FSelectedAccountsGrid := TAccountsGrid.Create(Self);
  813. FSelectedAccountsGrid.DrawGrid := dgSelectedAccounts;
  814. FSelectedAccountsGrid.OnUpdated := OnSelectedAccountsGridUpdated;
  815. FOperationsAccountGrid := TOperationsGrid.Create(Self);
  816. FOperationsAccountGrid.DrawGrid := dgAccountOperations;
  817. FOperationsAccountGrid.MustShowAlwaysAnAccount := true;
  818. FPendingOperationsGrid := TOperationsGrid.Create(Self);
  819. FPendingOperationsGrid.DrawGrid := dgPendingOperations;
  820. FPendingOperationsGrid.AccountNumber := -1; // all
  821. FPendingOperationsGrid.PendingOperations := true;
  822. FOperationsExplorerGrid := TOperationsGrid.Create(Self);
  823. FOperationsExplorerGrid.DrawGrid := dgOperationsExplorer;
  824. FOperationsExplorerGrid.AccountNumber := -1;
  825. FOperationsExplorerGrid.PendingOperations := False;
  826. FBlockChainGrid := TBlockChainGrid.Create(Self);
  827. FBlockChainGrid.DrawGrid := dgBlockChainExplorer;
  828. // FWalletKeys.OnChanged.Add( OnWalletChanged );
  829. LoadAppParams;
  830. UpdatePrivateKeys;
  831. UpdateBlockChainState;
  832. UpdateConnectionStatus;
  833. PageControl.ActivePage := tsMyAccounts;
  834. pcAccountsOptions.ActivePage := tsAccountOperations;
  835. ebFilterOperationsStartBlock.Text := '';
  836. ebFilterOperationsEndBlock.Text := '';
  837. cbExploreMyAccountsClick(nil);
  838. TrayIcon.Visible := true;
  839. TrayIcon.Hint := Self.Caption;
  840. TrayIcon.BalloonTitle := 'Restoring the window.';
  841. TrayIcon.BalloonHint :=
  842. 'Double click the system tray icon to restore Pascal Coin';
  843. TrayIcon.BalloonFlags := bfInfo;
  844. MinersBlocksFound := 0;
  845. lblBuild.Caption := 'Build: '+CT_ClientAppVersion;
  846. {$IFDEF TESTNET}
  847. Image1.visible := false;
  848. {$ENDIF}
  849. PageControl.Enabled := False;
  850. PageControl.Visible := False;
  851. FBackgroundPanel := TPanel.Create(Self);
  852. FBackgroundPanel.Parent:=Self;
  853. FBackgroundPanel.Align:=alClient;
  854. FBackgroundPanel.Font.Size:=15;
  855. end;
  856. procedure TFRMWallet.FormDestroy(Sender: TObject);
  857. Var i : Integer;
  858. step : String;
  859. begin
  860. TLog.NewLog(ltinfo,Classname,'Destroying form - START');
  861. Try
  862. FreeAndNil(FRPCServer);
  863. FreeAndNil(FPoolMiningServer);
  864. step := 'Saving params';
  865. SaveAppParams;
  866. FreeAndNil(FAppParams);
  867. //
  868. step := 'Assigning nil events';
  869. FLog.OnNewLog :=Nil;
  870. FNodeNotifyEvents.Node := Nil;
  871. FOperationsAccountGrid.Node := Nil;
  872. FOperationsExplorerGrid.Node := Nil;
  873. FPendingOperationsGrid.Node := Nil;
  874. FAccountsGrid.Node := Nil;
  875. FSelectedAccountsGrid.Node := Nil;
  876. TNetData.NetData.OnReceivedHelloMessage := Nil;
  877. TNetData.NetData.OnStatisticsChanged := Nil;
  878. TNetData.NetData.OnNetConnectionsUpdated := Nil;
  879. TNetData.NetData.OnNodeServersUpdated := Nil;
  880. TNetData.NetData.OnBlackListUpdated := Nil;
  881. //
  882. step := 'Destroying NodeNotifyEvents';
  883. FreeAndNil(FNodeNotifyEvents);
  884. //
  885. step := 'Assigning Nil to TNetData';
  886. TNetData.NetData.OnReceivedHelloMessage := Nil;
  887. TNetData.NetData.OnStatisticsChanged := Nil;
  888. step := 'Destroying grids operators';
  889. FreeAndNil(FOperationsAccountGrid);
  890. FreeAndNil(FOperationsExplorerGrid);
  891. FreeAndNil(FBlockChainGrid);
  892. step := 'Ordered Accounts Key list';
  893. FreeAndNil(FOrderedAccountsKeyList);
  894. step := 'Desactivating Node';
  895. TNode.Node.NetServer.Active := false;
  896. FNode := Nil;
  897. TNetData.NetData.Free;
  898. step := 'Processing messages 1';
  899. Application.ProcessMessages;
  900. step := 'Destroying Node';
  901. TNode.Node.Free;
  902. step := 'Destroying Wallet';
  903. FreeAndNil(FWalletKeys);
  904. step := 'Processing messages 2';
  905. Application.ProcessMessages;
  906. step := 'Destroying stringslist';
  907. Except
  908. On E:Exception do begin
  909. TLog.NewLog(lterror,Classname,'Error destroying Form step: '+step+' Errors ('+E.ClassName+'): ' +E.Message);
  910. end;
  911. End;
  912. TLog.NewLog(ltinfo,Classname,'Destroying form - END');
  913. FreeAndNil(FLog);
  914. Sleep(100);
  915. end;
  916. procedure TFRMWallet.sbSearchAccountClick(Sender: TObject);
  917. Var F : TFRMAccountSelect;
  918. begin
  919. F := TFRMAccountSelect.Create(Self);
  920. try
  921. F.Node := FNode;
  922. F.WalletKeys := FWalletKeys;
  923. F.ShowModal;
  924. finally
  925. F.Free;
  926. end;
  927. end;
  928. function TFRMWallet.GetAccountKeyForMiner: TAccountKey;
  929. Var PK : TECPrivateKey;
  930. i : Integer;
  931. PublicK : TECDSA_Public;
  932. begin
  933. Result := CT_TECDSA_Public_Nul;
  934. if Not Assigned(FWalletKeys) then exit;
  935. if Not Assigned(FAppParams) then exit;
  936. case FMinerPrivateKeyType of
  937. mpk_NewEachTime: PublicK := CT_TECDSA_Public_Nul;
  938. mpk_Selected: begin
  939. PublicK := TAccountComp.RawString2Accountkey(FAppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].GetAsString(''));
  940. end;
  941. else
  942. // Random
  943. PublicK := CT_TECDSA_Public_Nul;
  944. if FWalletKeys.Count>0 then PublicK := FWalletKeys.Key[Random(FWalletKeys.Count)].AccountKey;
  945. end;
  946. i := FWalletKeys.IndexOfAccountKey(PublicK);
  947. if i>=0 then begin
  948. if (FWalletKeys.Key[i].CryptedKey='') then i:=-1;
  949. end;
  950. if i<0 then begin
  951. PK := TECPrivateKey.Create;
  952. try
  953. PK.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
  954. FWalletKeys.AddPrivateKey('New for miner '+DateTimeToStr(Now), PK);
  955. PublicK := PK.PublicKey;
  956. finally
  957. PK.Free;
  958. end;
  959. end;
  960. Result := PublicK;
  961. end;
  962. procedure TFRMWallet.IPnodes1Click(Sender: TObject);
  963. Var FRM : TFRMNodesIp;
  964. begin
  965. FRM := TFRMNodesIp.Create(Self);
  966. Try
  967. FRM.AppParams := FAppParams;
  968. FRM.ShowModal;
  969. Finally
  970. FRM.Free;
  971. End;
  972. end;
  973. procedure TFRMWallet.lblReceivedMessagesClick(Sender: TObject);
  974. begin
  975. PageControl.ActivePage := tsMessages;
  976. end;
  977. procedure TFRMWallet.LoadAppParams;
  978. Var ms : TMemoryStream;
  979. s : AnsiString;
  980. fvi : TFileVersionInfo;
  981. begin
  982. ms := TMemoryStream.Create;
  983. Try
  984. s := FAppParams.ParamByName[CT_PARAM_GridAccountsStream].GetAsString('');
  985. ms.WriteBuffer(s[1],length(s));
  986. ms.Position := 0;
  987. // Disabled on V2: FAccountsGrid.LoadFromStream(ms);
  988. Finally
  989. ms.Free;
  990. End;
  991. If FAppParams.FindParam(CT_PARAM_MinerName)=Nil then begin
  992. // New configuration... assigning a new random value
  993. fvi := TFolderHelper.GetTFileVersionInfo(Application.ExeName);
  994. FAppParams.ParamByName[CT_PARAM_MinerName].SetAsString('New Node '+DateTimeToStr(Now)+' - '+
  995. fvi.InternalName+' Build:'+fvi.FileVersion);
  996. end;
  997. FBlockChainGrid.ShowTimeAverageColumns:={$IFDEF SHOW_AVERAGE_TIME_STATS}True;{$ELSE}False;{$ENDIF}
  998. UpdateConfigChanged;
  999. end;
  1000. procedure TFRMWallet.miAboutPascalCoinClick(Sender: TObject);
  1001. begin
  1002. With TFRMAbout.Create(Self) do
  1003. try
  1004. showmodal;
  1005. finally
  1006. free;
  1007. end;
  1008. end;
  1009. procedure TFRMWallet.MiAccountInformationClick(Sender: TObject);
  1010. Var F : TFRMMemoText;
  1011. accn : Int64;
  1012. s,title : String;
  1013. account : TAccount;
  1014. strings : TStrings;
  1015. i : Integer;
  1016. opr : TOperationResume;
  1017. begin
  1018. accn := -1;
  1019. title := '';
  1020. strings := TStringList.Create;
  1021. try
  1022. opr := CT_TOperationResume_NUL;
  1023. if PageControl.ActivePage=tsOperations then begin
  1024. i := FOperationsExplorerGrid.DrawGrid.Row;
  1025. if (i>0) and (i<=FOperationsExplorerGrid.OperationsResume.Count) then begin
  1026. opr := FOperationsExplorerGrid.OperationsResume.OperationResume[i-1];
  1027. end;
  1028. end else if PageControl.ActivePage=tsPendingOperations then begin
  1029. i := FPendingOperationsGrid.DrawGrid.Row;
  1030. if (i>0) and (i<=FPendingOperationsGrid.OperationsResume.Count) then begin
  1031. opr := FPendingOperationsGrid.OperationsResume.OperationResume[i-1];
  1032. end;
  1033. end else if PageControl.ActivePage=tsMyAccounts then begin
  1034. accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1035. if accn<0 then raise Exception.Create('Select an account');
  1036. FillAccountInformation(strings,accn);
  1037. title := 'Account '+TAccountComp.AccountNumberToAccountTxtNumber(accn)+' info';
  1038. i := FOperationsAccountGrid.DrawGrid.Row;
  1039. if (i>0) and (i<=FOperationsAccountGrid.OperationsResume.Count) then begin
  1040. opr := FOperationsAccountGrid.OperationsResume.OperationResume[i-1];
  1041. end;
  1042. end;
  1043. If (opr.valid) then begin
  1044. if accn>=0 then strings.Add('')
  1045. else title := 'Operation info';
  1046. strings.Add('Operation info:');
  1047. FillOperationInformation(strings,opr);
  1048. end else if accn<0 then Raise Exception.Create('No info available');
  1049. F := TFRMMemoText.Create(Self);
  1050. Try
  1051. F.Caption := title;
  1052. F.Memo.Lines.Assign(strings);
  1053. F.ShowModal;
  1054. Finally
  1055. F.Free;
  1056. End;
  1057. finally
  1058. strings.free;
  1059. end;
  1060. end;
  1061. procedure TFRMWallet.MiAddaccounttoSelectedClick(Sender: TObject);
  1062. begin
  1063. PageControl.ActivePage := tsMyAccounts;
  1064. PageControlChange(Nil);
  1065. pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
  1066. sbSelectedAccountsAddClick(Sender);
  1067. end;
  1068. procedure TFRMWallet.MiCloseClick(Sender: TObject);
  1069. begin
  1070. Close;
  1071. end;
  1072. procedure TFRMWallet.MiDecodePayloadClick(Sender: TObject);
  1073. begin
  1074. if PageControl.ActivePage=tsOperations then begin
  1075. FOperationsExplorerGrid.ShowModalDecoder(FWalletKeys,FAppParams);
  1076. end else if PageControl.ActivePage=tsPendingOperations then begin
  1077. FPendingOperationsGrid.ShowModalDecoder(FWalletKeys,FAppParams);
  1078. end else if PageControl.ActivePage=tsMyAccounts then begin
  1079. FOperationsAccountGrid.ShowModalDecoder(FWalletKeys,FAppParams);
  1080. end;
  1081. end;
  1082. procedure TFRMWallet.MiFindaccountClick(Sender: TObject);
  1083. begin
  1084. PageControl.ActivePage := tsMyAccounts;
  1085. PageControlChange(Nil);
  1086. ebFindAccountNumber.SetFocus;
  1087. end;
  1088. procedure TFRMWallet.MiFindnextaccountwithhighbalanceClick(Sender: TObject);
  1089. Var an : Cardinal;
  1090. an64 : Int64;
  1091. start : TAccount;
  1092. begin
  1093. PageControl.ActivePage := tsMyAccounts;
  1094. PageControlChange(Nil);
  1095. an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1096. if an64<0 then an := 0
  1097. else an := an64;
  1098. If an>=FNode.Bank.SafeBox.AccountsCount then exit;
  1099. start := FNode.Bank.SafeBox.Account(an);
  1100. while (an<FNode.Bank.SafeBox.AccountsCount) do begin
  1101. if FNode.Bank.SafeBox.Account(an).balance>start.balance then break
  1102. else inc(an);
  1103. end;
  1104. if (an<FNode.Bank.SafeBox.AccountsCount) then FAccountsGrid.MoveRowToAccount(an)
  1105. else raise Exception.Create('Not found any account higher than '+TAccountComp.AccountNumberToAccountTxtNumber(start.account)+' with balance higher than '+
  1106. TAccountComp.FormatMoney(start.balance));
  1107. end;
  1108. procedure TFRMWallet.MiFindOperationbyOpHashClick(Sender: TObject);
  1109. Var FRM : TFRMPayloadDecoder;
  1110. oph : String;
  1111. begin
  1112. oph := '';
  1113. if Not InputQuery('Search operation by OpHash','Insert Operation Hash value (OpHash)',oph) then exit;
  1114. //
  1115. FRM := TFRMPayloadDecoder.Create(Self);
  1116. try
  1117. FRM.Init(CT_TOperationResume_NUL,WalletKeys,FAppParams);
  1118. FRM.DoFind(oph);
  1119. FRM.ShowModal;
  1120. finally
  1121. FRM.Free;
  1122. end;
  1123. end;
  1124. procedure TFRMWallet.MiFindpreviousaccountwithhighbalanceClick(Sender: TObject);
  1125. Var an : Cardinal;
  1126. an64 : Int64;
  1127. start : TAccount;
  1128. begin
  1129. PageControl.ActivePage := tsMyAccounts;
  1130. PageControlChange(Nil);
  1131. an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1132. if an64<0 then an := FNode.Bank.SafeBox.AccountsCount-1
  1133. else an := an64;
  1134. If an>=FNode.Bank.SafeBox.AccountsCount then exit;
  1135. start := FNode.Bank.SafeBox.Account(an);
  1136. while (an>0) do begin
  1137. if FNode.Bank.SafeBox.Account(an).balance>start.balance then break
  1138. else dec(an);
  1139. end;
  1140. if (FNode.Bank.SafeBox.Account(an).balance>start.balance) then FAccountsGrid.MoveRowToAccount(an)
  1141. else raise Exception.Create('Not found any account lower than '+TAccountComp.AccountNumberToAccountTxtNumber(start.account)+' with balance higher than '+
  1142. TAccountComp.FormatMoney(start.balance));
  1143. end;
  1144. procedure TFRMWallet.MiMultiaccountoperationClick(Sender: TObject);
  1145. begin
  1146. PageControl.ActivePage := tsMyAccounts;
  1147. pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
  1148. bbSelectedAccountsOperationClick(Sender);
  1149. end;
  1150. procedure TFRMWallet.miNewOperationClick(Sender: TObject);
  1151. var l : TOrderedCardinalList;
  1152. begin
  1153. CheckIsReady;
  1154. With TFRMOperation.Create(Self) do
  1155. Try
  1156. l := TOrderedCardinalList.Create;
  1157. try
  1158. If FAccountsGrid.SelectedAccounts(l)<1 then raise Exception.Create('No row selected');
  1159. SenderAccounts.CopyFrom(l);
  1160. finally
  1161. l.Free;
  1162. end;
  1163. DefaultFee := FAppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
  1164. WalletKeys := FWalletKeys;
  1165. ShowModal;
  1166. Finally
  1167. Free;
  1168. End;
  1169. end;
  1170. procedure TFRMWallet.miOptionsClick(Sender: TObject);
  1171. begin
  1172. With TFRMPascalCoinWalletConfig.Create(Self) do
  1173. try
  1174. AppParams := Self.FAppParams;
  1175. WalletKeys := Self.FWalletKeys;
  1176. if ShowModal=MrOk then begin
  1177. SaveAppParams;
  1178. UpdateConfigChanged;
  1179. end;
  1180. finally
  1181. free;
  1182. end;
  1183. end;
  1184. procedure TFRMWallet.miPrivatekeysClick(Sender: TObject);
  1185. Var FRM : TFRMWalletKeys;
  1186. begin
  1187. FRM := TFRMWalletKeys.Create(Self);
  1188. Try
  1189. FRM.WalletKeys := FWalletKeys;
  1190. FRM.ShowModal;
  1191. UpdatePrivateKeys;
  1192. Finally
  1193. FRM.Free;
  1194. End;
  1195. end;
  1196. procedure TFRMWallet.MiRemoveaccountfromselectedClick(Sender: TObject);
  1197. begin
  1198. PageControl.ActivePage := tsMyAccounts;
  1199. PageControlChange(Nil);
  1200. pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
  1201. sbSelectedAccountsDelClick(Sender);
  1202. end;
  1203. procedure TFRMWallet.OnMiningServerNewBlockFound(Sender: TObject);
  1204. begin
  1205. FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
  1206. end;
  1207. procedure TFRMWallet.OnNetBlackListUpdated(Sender: TObject);
  1208. Const CT_TRUE_FALSE : Array[Boolean] Of AnsiString = ('FALSE','TRUE');
  1209. Var i,j,n : integer;
  1210. P : PNodeServerAddress;
  1211. l : TList;
  1212. strings : TStrings;
  1213. begin
  1214. l := TNetData.NetData.NodeServersAddresses.LockList;
  1215. try
  1216. strings := memoNetBlackLists.Lines;
  1217. strings.BeginUpdate;
  1218. Try
  1219. strings.Clear;
  1220. strings.Add('BlackList Updated: '+DateTimeToStr(now)+' by TID:'+IntToHex(PtrInt(TThread.CurrentThread.ThreadID),8));
  1221. j := 0; n:=0;
  1222. for i := 0 to l.Count - 1 do begin
  1223. P := l[i];
  1224. if (P^.is_blacklisted) then begin
  1225. inc(n);
  1226. if Not P^.its_myself then begin
  1227. inc(j);
  1228. strings.Add(Format('Blacklist IP:%s:%d LastConnection:%s Reason: %s',
  1229. [
  1230. P^.ip,P^.port,
  1231. DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection))),P^.BlackListText]));
  1232. end;
  1233. end;
  1234. end;
  1235. Strings.Add(Format('Total Blacklisted IPs: %d (Total %d)',[j,n]));
  1236. Finally
  1237. strings.EndUpdate;
  1238. End;
  1239. finally
  1240. TNetData.NetData.NodeServersAddresses.UnlockList;
  1241. end;
  1242. end;
  1243. procedure TFRMWallet.OnNetConnectionsUpdated(Sender: TObject);
  1244. begin
  1245. if FMustProcessNetConnectionUpdated then exit;
  1246. FMustProcessNetConnectionUpdated := true;
  1247. PostMessage(Self.Handle,CM_PC_NetConnectionUpdated,0,0);
  1248. end;
  1249. procedure TFRMWallet.OnNetNodeServersUpdated(Sender: TObject);
  1250. Var i : integer;
  1251. P : PNodeServerAddress;
  1252. l : TList;
  1253. strings : TStrings;
  1254. s : String;
  1255. begin
  1256. l := TNetData.NetData.NodeServersAddresses.LockList;
  1257. try
  1258. strings := memoNetServers.Lines;
  1259. strings.BeginUpdate;
  1260. Try
  1261. strings.Clear;
  1262. strings.Add('NodeServers Updated: '+DateTimeToStr(now) +' Count: '+inttostr(l.Count));
  1263. for i := 0 to l.Count - 1 do begin
  1264. P := l[i];
  1265. if Not (P^.is_blacklisted) then begin
  1266. s := Format('Server IP:%s:%d',[P^.ip,P^.port]);
  1267. if (P^.last_connection_by_me>0) then begin
  1268. s := s + ' [Server] ';
  1269. end;
  1270. if Assigned(P.netConnection) then begin
  1271. If P.last_connection>0 then s := s+ ' ** ACTIVE **'
  1272. else s := s+' ** TRYING TO CONNECT **';
  1273. end;
  1274. if P.its_myself then begin
  1275. s := s+' ** NOT VALID ** '+P.BlackListText;
  1276. end;
  1277. if P.last_connection>0 then begin
  1278. s := s + ' Last connection: '+DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection)));
  1279. end;
  1280. if P.last_connection_by_server>0 then begin
  1281. s := s + ' Last server connection: '+DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection_by_server)));
  1282. end;
  1283. if (P.last_attempt_to_connect>0) then begin
  1284. s := s + ' Last attempt to connect: '+DateTimeToStr(P^.last_attempt_to_connect);
  1285. end;
  1286. if (P.total_failed_attemps_to_connect>0) then begin
  1287. s := s + ' (Attempts: '+inttostr(P^.total_failed_attemps_to_connect)+')';
  1288. end;
  1289. strings.Add(s);
  1290. end;
  1291. end;
  1292. Finally
  1293. strings.EndUpdate;
  1294. End;
  1295. finally
  1296. TNetData.NetData.NodeServersAddresses.UnlockList;
  1297. end;
  1298. end;
  1299. procedure TFRMWallet.OnNetStatisticsChanged(Sender: TObject);
  1300. Var NS : TNetStatistics;
  1301. begin
  1302. //CheckMining;
  1303. if Assigned(FNode) then begin
  1304. If FNode.NetServer.Active then begin
  1305. StatusBar.Panels[0].Text := 'Active (Port '+Inttostr(FNode.NetServer.Port)+')';
  1306. end else StatusBar.Panels[0].Text := 'Server stopped';
  1307. NS := TNetData.NetData.NetStatistics;
  1308. StatusBar.Panels[1].Text := Format('Connections:%d Clients:%d Servers:%d - Rcvd:%d Kb Send:%d Kb',
  1309. [NS.ActiveConnections,NS.ClientsConnections,NS.ServersConnections,NS.BytesReceived DIV 1024,NS.BytesSend DIV 1024]);
  1310. end else begin
  1311. StatusBar.Panels[0].Text := '';
  1312. StatusBar.Panels[1].Text := '';
  1313. end;
  1314. end;
  1315. procedure TFRMWallet.OnNewAccount(Sender: TObject);
  1316. begin
  1317. Try
  1318. UpdateAccounts(false);
  1319. UpdateBlockChainState;
  1320. Except
  1321. On E:Exception do begin
  1322. E.Message := 'Error at OnNewAccount '+E.Message;
  1323. Raise;
  1324. end;
  1325. end;
  1326. end;
  1327. procedure TFRMWallet.OnNewLog(logtype: TLogType; Time : TDateTime; ThreadID : TThreadID; const sender,logtext: AnsiString);
  1328. Var s : AnsiString;
  1329. begin
  1330. if (logtype=ltdebug) And (Not cbShowDebugLogs.Checked) then exit;
  1331. if ThreadID=MainThreadID then s := ' MAIN:' else s:=' TID:';
  1332. if MemoLogs.Lines.Count>300 then begin
  1333. // Limit max lines in logs...
  1334. memoLogs.Lines.BeginUpdate;
  1335. try
  1336. while memoLogs.Lines.Count>250 do memoLogs.Lines.Delete(0);
  1337. finally
  1338. memoLogs.Lines.EndUpdate;
  1339. end;
  1340. end;
  1341. memoLogs.Lines.Add(formatDateTime('dd/mm/yyyy hh:nn:ss.zzz',Time)+s+IntToHex(PtrInt(ThreadID),8)+' ['+CT_LogType[Logtype]+'] <'+sender+'> '+logtext);
  1342. //
  1343. end;
  1344. procedure TFRMWallet.OnNodeMessageEvent(NetConnection: TNetConnection; MessageData: TRawBytes);
  1345. Var s : String;
  1346. begin
  1347. inc(FMessagesUnreadCount);
  1348. if Assigned(NetConnection) then begin
  1349. s := DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr;
  1350. memoMessages.Lines.Add(DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr+' Length '+inttostr(Length(MessageData))+' bytes');
  1351. memoMessages.Lines.Add('RECEIVED> '+MessageData);
  1352. if FAppParams.ParamByName[CT_PARAM_ShowModalMessages].GetAsBoolean(false) then begin
  1353. s := DateTimeToStr(now)+' Message from '+NetConnection.ClientRemoteAddr+#10+
  1354. 'Length '+inttostr(length(MessageData))+' bytes'+#10+#10;
  1355. if TCrypto.IsHumanReadable(MessageData) then begin
  1356. s := s + MessageData;
  1357. end else begin
  1358. s := s +'Value in hexadecimal:'+#10+
  1359. TCrypto.ToHexaString(MessageData);
  1360. end;
  1361. Application.MessageBox(PChar(s),PChar(Application.Title),MB_ICONINFORMATION+MB_OK);
  1362. end;
  1363. end else begin
  1364. memoMessages.Lines.Add(DateTimeToStr(now)+' Internal message: '+MessageData);
  1365. end;
  1366. if FMessagesUnreadCount>1 then lblReceivedMessages.Caption := Format('You have received %d messages',[FMessagesUnreadCount])
  1367. else lblReceivedMessages.Caption := 'You have received 1 message';
  1368. lblReceivedMessages.Visible := true;
  1369. end;
  1370. procedure TFRMWallet.OnReceivedHelloMessage(Sender: TObject);
  1371. Var nsarr : TNodeServerAddressArray;
  1372. i : Integer;
  1373. s : AnsiString;
  1374. begin
  1375. If (FLastNodesCacheUpdatedTS + EncodeTime(0,5,0,0) > Now) then exit; // Prevent continuous saving
  1376. FLastNodesCacheUpdatedTS := Now;
  1377. // Update node servers Peer Cache
  1378. nsarr := TNetData.NetData.NodeServersAddresses.GetValidNodeServers(true,0);
  1379. s := '';
  1380. for i := low(nsarr) to High(nsarr) do begin
  1381. if (s<>'') then s := s+';';
  1382. s := s + nsarr[i].ip+':'+IntToStr( nsarr[i].port );
  1383. end;
  1384. FAppParams.ParamByName[CT_PARAM_PeerCache].SetAsString(s);
  1385. TNode.Node.PeerCache := s;
  1386. end;
  1387. procedure TFRMWallet.OnSelectedAccountsGridUpdated(Sender: TObject);
  1388. begin
  1389. lblSelectedAccountsCount.Caption := Inttostr(FSelectedAccountsGrid.AccountsCount);
  1390. lblSelectedAccountsBalance.Caption := TAccountComp.FormatMoney( FSelectedAccountsGrid.AccountsBalance );
  1391. end;
  1392. procedure TFRMWallet.OnWalletChanged(Sender: TObject);
  1393. begin
  1394. if FMustProcessWalletChanged then exit;
  1395. FMustProcessWalletChanged := true;
  1396. PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
  1397. end;
  1398. procedure TFRMWallet.PageControlChange(Sender: TObject);
  1399. begin
  1400. MiDecodePayload.Enabled := false;
  1401. if PageControl.ActivePage=tsMyAccounts then begin
  1402. //FAccountsGrid.Node := FNode;
  1403. MiDecodePayload.Enabled := true;
  1404. FSelectedAccountsGrid.Node := FNode;
  1405. end else begin
  1406. //FAccountsGrid.Node := Nil;
  1407. FSelectedAccountsGrid.Node := Nil;
  1408. end;
  1409. if PageControl.ActivePage=tsPendingOperations then begin
  1410. FPendingOperationsGrid.Node := FNode;
  1411. MiDecodePayload.Enabled := true;
  1412. end else FPendingOperationsGrid.Node := Nil;
  1413. if PageControl.ActivePage=tsBlockChain then FBlockChainGrid.Node := FNode
  1414. else FBlockChainGrid.Node := Nil;
  1415. if PageControl.ActivePage=tsOperations then begin
  1416. FOperationsExplorerGrid.Node := FNode;
  1417. MiDecodePayload.Enabled := true;
  1418. end else FOperationsExplorerGrid.Node := Nil;
  1419. if PageControl.ActivePage=tsMessages then begin
  1420. UpdateAvailableConnections;
  1421. FMessagesUnreadCount := 0;
  1422. lblReceivedMessages.Visible := false;
  1423. end;
  1424. end;
  1425. procedure TFRMWallet.SaveAppParams;
  1426. Var ms : TMemoryStream;
  1427. s : AnsiString;
  1428. begin
  1429. ms := TMemoryStream.Create;
  1430. Try
  1431. FAccountsGrid.SaveToStream(ms);
  1432. ms.Position := 0;
  1433. setlength(s,ms.Size);
  1434. ms.ReadBuffer(s[1],ms.Size);
  1435. FAppParams.ParamByName[CT_PARAM_GridAccountsStream].SetAsString(s);
  1436. Finally
  1437. ms.Free;
  1438. End;
  1439. end;
  1440. procedure TFRMWallet.sbSelectedAccountsAddAllClick(Sender: TObject);
  1441. Var lsource,ltarget : TOrderedCardinalList;
  1442. i : Integer;
  1443. begin
  1444. lsource := FAccountsGrid.LockAccountsList;
  1445. Try
  1446. ltarget := FSelectedAccountsGrid.LockAccountsList;
  1447. Try
  1448. for i := 0 to lsource.Count-1 do begin
  1449. if FWalletKeys.IndexOfAccountKey(FNode.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)]));
  1450. ltarget.Add(lsource.Get(i));
  1451. end;
  1452. Finally
  1453. FSelectedAccountsGrid.UnlockAccountsList;
  1454. End;
  1455. Finally
  1456. FAccountsGrid.UnlockAccountsList;
  1457. End;
  1458. end;
  1459. procedure TFRMWallet.sbSelectedAccountsAddClick(Sender: TObject);
  1460. Var l, selected : TOrderedCardinalList;
  1461. an : Int64;
  1462. i : Integer;
  1463. begin
  1464. an := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1465. if (an<0) then raise Exception.Create('No account selected');
  1466. if FWalletKeys.IndexOfAccountKey(FNode.Bank.SafeBox.Account(an).accountInfo.accountkey)<0 then
  1467. raise Exception.Create(Format('You cannot add %s account because private key not found in your wallet.'#10+#10+'You''re not the owner!',
  1468. [TAccountComp.AccountNumberToAccountTxtNumber(an)]));
  1469. // Add
  1470. l := FSelectedAccountsGrid.LockAccountsList;
  1471. selected := TOrderedCardinalList.Create;
  1472. Try
  1473. FAccountsGrid.SelectedAccounts(selected);
  1474. for i := 0 to selected.Count-1 do begin
  1475. l.Add(selected.Get(i));
  1476. end;
  1477. Finally
  1478. selected.Free;
  1479. FSelectedAccountsGrid.UnlockAccountsList;
  1480. End;
  1481. end;
  1482. procedure TFRMWallet.sbSelectedAccountsDelAllClick(Sender: TObject);
  1483. Var l : TOrderedCardinalList;
  1484. begin
  1485. l := FSelectedAccountsGrid.LockAccountsList;
  1486. try
  1487. l.Clear;
  1488. finally
  1489. FSelectedAccountsGrid.UnlockAccountsList;
  1490. end;
  1491. end;
  1492. procedure TFRMWallet.sbSelectedAccountsDelClick(Sender: TObject);
  1493. Var an : Int64;
  1494. l : TOrderedCardinalList;
  1495. begin
  1496. l := FSelectedAccountsGrid.LockAccountsList;
  1497. try
  1498. an := FSelectedAccountsGrid.AccountNumber(dgSelectedAccounts.Row);
  1499. if an>=0 then l.Remove(an);
  1500. finally
  1501. FSelectedAccountsGrid.UnlockAccountsList;
  1502. end;
  1503. end;
  1504. procedure TFRMWallet.SetMinersBlocksFound(const Value: Integer);
  1505. begin
  1506. FMinersBlocksFound := Value;
  1507. lblBlocksFound.Caption := Inttostr(Value);
  1508. if Value>0 then lblBlocksFound.Font.Color := clGreen
  1509. else lblBlocksFound.Font.Color := clDkGray;
  1510. end;
  1511. procedure TFRMWallet.TimerUpdateStatusTimer(Sender: TObject);
  1512. begin
  1513. Try
  1514. UpdateConnectionStatus;
  1515. UpdateBlockChainState;
  1516. UpdateNodeStatus;
  1517. Except
  1518. On E:Exception do begin
  1519. E.Message := 'Exception at TimerUpdate '+E.ClassName+': '+E.Message;
  1520. TLog.NewLog(lterror,ClassName,E.Message);
  1521. end;
  1522. End;
  1523. end;
  1524. procedure TFRMWallet.TrayIconDblClick(Sender: TObject);
  1525. begin
  1526. TrayIcon.Visible := False;
  1527. TimerUpdateStatus.Enabled := true;
  1528. Show();
  1529. WindowState := wsNormal;
  1530. Application.BringToFront();
  1531. end;
  1532. procedure TFRMWallet.UpdateAccounts(RefreshData : Boolean);
  1533. Var accl : TOrderedCardinalList;
  1534. l : TOrderedCardinalList;
  1535. i,j,k : Integer;
  1536. c : Cardinal;
  1537. applyfilter : Boolean;
  1538. acc : TAccount;
  1539. begin
  1540. If Not Assigned(FOrderedAccountsKeyList) Then exit;
  1541. if Not RefreshData then begin
  1542. dgAccounts.Invalidate;
  1543. exit;
  1544. end;
  1545. applyfilter := (cbFilterAccounts.Checked) and ((FMinAccountBalance>0) Or (FMaxAccountBalance<CT_MaxWalletAmount));
  1546. FAccountsGrid.ShowAllAccounts := (Not cbExploreMyAccounts.Checked) And (not applyfilter);
  1547. if Not FAccountsGrid.ShowAllAccounts then begin
  1548. accl := FAccountsGrid.LockAccountsList;
  1549. Try
  1550. accl.Clear;
  1551. if cbExploreMyAccounts.Checked then begin
  1552. if cbMyPrivateKeys.ItemIndex<0 then exit;
  1553. if cbMyPrivateKeys.ItemIndex=0 then begin
  1554. // All keys in the wallet
  1555. for i := 0 to FWalletKeys.Count - 1 do begin
  1556. j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[i].AccountKey);
  1557. if (j>=0) then begin
  1558. l := FOrderedAccountsKeyList.AccountKeyList[j];
  1559. for k := 0 to l.Count - 1 do begin
  1560. if applyfilter then begin
  1561. acc := FNode.Bank.SafeBox.Account(l.Get(k));
  1562. if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
  1563. end else accl.Add(l.Get(k));
  1564. end;
  1565. end;
  1566. end;
  1567. end else begin
  1568. i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
  1569. if (i>=0) And (i<FWalletKeys.Count) then begin
  1570. j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[i].AccountKey);
  1571. if (j>=0) then begin
  1572. l := FOrderedAccountsKeyList.AccountKeyList[j];
  1573. for k := 0 to l.Count - 1 do begin
  1574. if applyfilter then begin
  1575. acc := FNode.Bank.SafeBox.Account(l.Get(k));
  1576. if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
  1577. end else accl.Add(l.Get(k));
  1578. end;
  1579. end;
  1580. end;
  1581. end;
  1582. end else begin
  1583. // There is a filter... check every account...
  1584. c := 0;
  1585. while (c<FNode.Bank.SafeBox.AccountsCount) do begin
  1586. acc := FNode.Bank.SafeBox.Account(c);
  1587. if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
  1588. inc(c);
  1589. end;
  1590. end;
  1591. Finally
  1592. FAccountsGrid.UnlockAccountsList;
  1593. End;
  1594. lblAccountsCount.Caption := inttostr(accl.Count);
  1595. end else begin
  1596. lblAccountsCount.Caption := inttostr(FNode.Bank.AccountsCount);
  1597. end;
  1598. bbChangeKeyName.Enabled := cbExploreMyAccounts.Checked;
  1599. // Show Totals:
  1600. lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
  1601. UpdateOperations;
  1602. end;
  1603. procedure TFRMWallet.UpdateAvailableConnections;
  1604. Var i : integer;
  1605. NC : TNetConnection;
  1606. l : TList;
  1607. begin
  1608. if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
  1609. try
  1610. lbNetConnections.Items.BeginUpdate;
  1611. Try
  1612. lbNetConnections.Items.Clear;
  1613. for i := 0 to l.Count - 1 do begin
  1614. NC := l[i];
  1615. if NC.Connected then begin
  1616. if NC is TNetServerClient then begin
  1617. if Not NC.IsMyselfServer then begin
  1618. lbNetConnections.Items.AddObject(Format('Client: IP:%s',[NC.ClientRemoteAddr]),NC);
  1619. end;
  1620. end else begin
  1621. if Not NC.IsMyselfServer then begin
  1622. lbNetConnections.Items.AddObject(Format('Server: IP:%s',[NC.ClientRemoteAddr]),NC);
  1623. end;
  1624. end;
  1625. end;
  1626. end;
  1627. Finally
  1628. lbNetConnections.Items.EndUpdate;
  1629. End;
  1630. finally
  1631. TNetData.NetData.NetConnections.UnlockList;
  1632. end;
  1633. end;
  1634. procedure TFRMWallet.UpdateBlockChainState;
  1635. Var isMining : boolean;
  1636. // hr : Int64;
  1637. i,mc : Integer;
  1638. s : String;
  1639. mtl : TList;
  1640. f, favg : real;
  1641. begin
  1642. UpdateNodeStatus;
  1643. mc := 0;
  1644. // hr := 0;
  1645. if Assigned(FNode) then begin
  1646. if FNode.Bank.BlocksCount>0 then begin
  1647. lblCurrentBlock.Caption := Inttostr(FNode.Bank.BlocksCount)+' (0..'+Inttostr(FNode.Bank.BlocksCount-1)+')'; ;
  1648. end else lblCurrentBlock.Caption := '(none)';
  1649. lblCurrentAccounts.Caption := Inttostr(FNode.Bank.AccountsCount);
  1650. lblCurrentBlockTime.Caption := UnixTimeToLocalElapsedTime(FNode.Bank.LastOperationBlock.timestamp);
  1651. lblOperationsPending.Caption := Inttostr(FNode.Operations.Count);
  1652. lblCurrentDifficulty.Caption := InttoHex(FNode.Operations.OperationBlock.compact_target,8);
  1653. favg := FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage);
  1654. f := (CT_NewLineSecondsAvg - favg) / CT_NewLineSecondsAvg;
  1655. lblTimeAverage.Caption := 'Last '+Inttostr(CT_CalcNewTargetBlocksAverage)+': '+FormatFloat('0.0',favg)+' sec. (Optimal '+Inttostr(CT_NewLineSecondsAvg)+'s) Deviation '+FormatFloat('0.00%',f*100);
  1656. if favg>=CT_NewLineSecondsAvg then begin
  1657. lblTimeAverage.Font.Color := clNavy;
  1658. end else begin
  1659. lblTimeAverage.Font.Color := clOlive;
  1660. end;
  1661. lblTimeAverageAux.Caption := Format('Last %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec.',[
  1662. CT_CalcNewTargetBlocksAverage * 2 ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage * 2)),
  1663. ((CT_CalcNewTargetBlocksAverage * 3) DIV 2) ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage((CT_CalcNewTargetBlocksAverage * 3) DIV 2)),
  1664. ((CT_CalcNewTargetBlocksAverage DIV 4)*3),FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(((CT_CalcNewTargetBlocksAverage DIV 4)*3))),
  1665. CT_CalcNewTargetBlocksAverage DIV 2,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 2)),
  1666. CT_CalcNewTargetBlocksAverage DIV 4,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 4))]);
  1667. end else begin
  1668. isMining := false;
  1669. lblCurrentBlock.Caption := '';
  1670. lblCurrentAccounts.Caption := '';
  1671. lblCurrentBlockTime.Caption := '';
  1672. lblOperationsPending.Caption := '';
  1673. lblCurrentDifficulty.Caption := '';
  1674. lblTimeAverage.Caption := '';
  1675. lblTimeAverageAux.Caption := '';
  1676. end;
  1677. if (Assigned(FPoolMiningServer)) And (FPoolMiningServer.Active) then begin
  1678. If FPoolMiningServer.ClientsCount>0 then begin
  1679. lblMinersClients.Caption := IntToStr(FPoolMiningServer.ClientsCount)+' connected JSON-RPC clients';
  1680. lblMinersClients.Font.Color := clNavy;
  1681. end else begin
  1682. lblMinersClients.Caption := 'No JSON-RPC clients';
  1683. lblMinersClients.Font.Color := clDkGray;
  1684. end;
  1685. MinersBlocksFound := FPoolMiningServer.ClientsWins;
  1686. end else begin
  1687. MinersBlocksFound := 0;
  1688. lblMinersClients.Caption := 'JSON-RPC server not active';
  1689. lblMinersClients.Font.Color := clRed;
  1690. end;
  1691. end;
  1692. procedure TFRMWallet.UpdateConfigChanged;
  1693. Var wa : Boolean;
  1694. i : Integer;
  1695. begin
  1696. tsLogs.TabVisible := FAppParams.ParamByName[CT_PARAM_ShowLogs].GetAsBoolean(false);
  1697. if (Not tsLogs.TabVisible) then begin
  1698. FLog.OnNewLog := Nil;
  1699. if PageControl.ActivePage = tsLogs then PageControl.ActivePage := tsMyAccounts;
  1700. end else FLog.OnNewLog := OnNewLog;
  1701. if FAppParams.ParamByName[CT_PARAM_SaveLogFiles].GetAsBoolean(false) then begin
  1702. if FAppParams.ParamByName[CT_PARAM_SaveDebugLogs].GetAsBoolean(false) then FLog.SaveTypes := CT_TLogTypes_ALL
  1703. else FLog.SaveTypes := CT_TLogTypes_DEFAULT;
  1704. FLog.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'PascalCointWallet.log';
  1705. end else begin
  1706. FLog.SaveTypes := [];
  1707. FLog.FileName := '';
  1708. end;
  1709. if Assigned(FNode) then begin
  1710. wa := FNode.NetServer.Active;
  1711. FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
  1712. FNode.NetServer.Active := wa;
  1713. FNode.Operations.BlockPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
  1714. FNode.NodeLogFilename := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'blocks.log';
  1715. end;
  1716. if Assigned(FPoolMiningServer) then begin
  1717. if FPoolMiningServer.Port<>FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port) then begin
  1718. FPoolMiningServer.Active := false;
  1719. FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
  1720. end;
  1721. FPoolMiningServer.Active :=FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
  1722. FPoolMiningServer.UpdateAccountAndPayload(GetAccountKeyForMiner,FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString(''));
  1723. end;
  1724. if Assigned(FRPCServer) then begin
  1725. FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
  1726. FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
  1727. end;
  1728. i := FAppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].GetAsInteger(Integer(mpk_Random));
  1729. if (i>=Integer(Low(TMinerPrivatekey))) And (i<=Integer(High(TMinerPrivatekey))) then FMinerPrivateKeyType := TMinerPrivateKey(i)
  1730. else FMinerPrivateKeyType := mpk_Random;
  1731. end;
  1732. procedure TFRMWallet.UpdateConnectionStatus;
  1733. var errors : AnsiString;
  1734. begin
  1735. UpdateNodeStatus;
  1736. OnNetStatisticsChanged(Nil);
  1737. if Assigned(FNode) then begin
  1738. if FNode.IsBlockChainValid(errors) then begin
  1739. StatusBar.Panels[2].Text := Format('Last account time:%s',
  1740. [FormatDateTime('dd/mm/yyyy hh:nn:ss',UnivDateTime2LocalDateTime(UnixToUnivDateTime( FNode.Bank.LastOperationBlock.timestamp )))]);
  1741. end else begin
  1742. StatusBar.Panels[2].Text := 'NO BLOCKCHAIN: '+errors;
  1743. end;
  1744. end else begin
  1745. StatusBar.Panels[2].Text := '';
  1746. end;
  1747. end;
  1748. procedure TFRMWallet.UpdateNodeStatus;
  1749. Var status : AnsiString;
  1750. begin
  1751. If Not Assigned(FNode) then begin
  1752. lblNodeStatus.Font.Color := clRed;
  1753. lblNodeStatus.Caption := 'Initializing...';
  1754. end else begin
  1755. If FNode.IsReady(status) then begin
  1756. if TNetData.NetData.NetStatistics.ActiveConnections>0 then begin
  1757. lblNodeStatus.Font.Color := clGreen;
  1758. if TNetData.NetData.IsDiscoveringServers then begin
  1759. lblNodeStatus.Caption := 'Discovering servers';
  1760. end else if TNetData.NetData.IsGettingNewBlockChainFromClient then begin
  1761. lblNodeStatus.Caption := 'Obtaining new blockchain';
  1762. end else begin
  1763. lblNodeStatus.Caption := 'Running';
  1764. end;
  1765. end else begin
  1766. lblNodeStatus.Font.Color := clRed;
  1767. lblNodeStatus.Caption := 'Alone in the world...';
  1768. end;
  1769. end else begin
  1770. lblNodeStatus.Font.Color := clRed;
  1771. lblNodeStatus.Caption := status;
  1772. end;
  1773. end;
  1774. If Assigned(FBackgroundPanel) then begin
  1775. FBackgroundPanel.Font.Color:=lblNodeStatus.Font.Color;
  1776. FBackgroundPanel.Caption:='Please wait until finished: '+lblNodeStatus.Caption;
  1777. end;
  1778. end;
  1779. procedure TFRMWallet.UpdateOperations;
  1780. Var accn : Int64;
  1781. begin
  1782. accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1783. FOperationsAccountGrid.AccountNumber := accn;
  1784. end;
  1785. procedure TFRMWallet.UpdatePrivateKeys;
  1786. Var i,last_i : Integer;
  1787. wk : TWalletKey;
  1788. s : AnsiString;
  1789. begin
  1790. If (Not Assigned(FOrderedAccountsKeyList)) And (Assigned(FNode)) Then begin
  1791. FOrderedAccountsKeyList := TOrderedAccountKeysList.Create(FNode.Bank.SafeBox,false);
  1792. end;
  1793. if (cbMyPrivateKeys.ItemIndex>=0) then last_i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex])
  1794. else last_i := -1;
  1795. cbMyPrivateKeys.items.BeginUpdate;
  1796. Try
  1797. cbMyPrivateKeys.Items.Clear;
  1798. For i:=0 to FWalletKeys.Count-1 do begin
  1799. wk := FWalletKeys.Key[i];
  1800. if assigned(FOrderedAccountsKeyList) then begin
  1801. FOrderedAccountsKeyList.AddAccountKey(wk.AccountKey);
  1802. end;
  1803. if (wk.Name='') then begin
  1804. s := 'Sha256='+TCrypto.ToHexaString( TCrypto.DoSha256( TAccountComp.AccountKey2RawString(wk.AccountKey) ) );
  1805. end else begin
  1806. s := wk.Name;
  1807. end;
  1808. if Not Assigned(wk.PrivateKey) then s := s + '(*)';
  1809. cbMyPrivateKeys.Items.AddObject(s,TObject(i));
  1810. end;
  1811. cbMyPrivateKeys.Sorted := true;
  1812. cbMyPrivateKeys.Sorted := false;
  1813. cbMyPrivateKeys.Items.InsertObject(0,'(All my private keys)',TObject(-1));
  1814. Finally
  1815. cbMyPrivateKeys.Items.EndUpdate;
  1816. End;
  1817. last_i := cbMyPrivateKeys.Items.IndexOfObject(TObject(last_i));
  1818. if last_i<0 then last_i := 0;
  1819. if cbMyPrivateKeys.Items.Count>last_i then cbMyPrivateKeys.ItemIndex := last_i
  1820. else if cbMyPrivateKeys.Items.Count>=0 then cbMyPrivateKeys.ItemIndex := 0;
  1821. end;
  1822. initialization
  1823. FRMWallet := Nil;
  1824. end.