1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942 |
- unit UFRMWallet;
- {$IFDEF FPC}
- {$MODE Delphi}
- {$ENDIF}
- { Copyright (c) 2016 by Albert Molina
- Distributed under the MIT software license, see the accompanying file LICENSE
- or visit http://www.opensource.org/licenses/mit-license.php.
- This unit is a part of Pascal Coin, a P2P crypto currency without need of
- historical operations.
- If you like it, consider a donation using BitCoin:
- 16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
- }
- interface
- {$I ../config.inc}
- uses
- {$IFnDEF FPC}
- pngimage, Windows, AppEvnts, ShlObj,
- {$ELSE}
- LCLIntf, LCLType, LMessages,
- {$ENDIF}
- Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, ExtCtrls, ComCtrls, UWallet, StdCtrls,
- ULog, Grids, UAppParams,
- UBlockChain, UNode, UGridUtils, UAccounts, Menus, ImgList,
- UNetProtocol, UCrypto, Buttons, UPoolMining, URPC, UFRMAccountSelect,
- UConst;
- Const
- CM_PC_WalletKeysChanged = WM_USER + 1;
- CM_PC_NetConnectionUpdated = WM_USER + 2;
- type
- TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);
- { TFRMWallet }
- TFRMWallet = class(TForm)
- pnlTop: TPanel;
- Image1: TImage;
- sbSearchAccount: TSpeedButton;
- StatusBar: TStatusBar;
- PageControl: TPageControl;
- tsMyAccounts: TTabSheet;
- tsOperations: TTabSheet;
- TrayIcon: TTrayIcon;
- TimerUpdateStatus: TTimer;
- tsLogs: TTabSheet;
- pnlTopLogs: TPanel;
- cbShowDebugLogs: TCheckBox;
- memoLogs: TMemo;
- pnlMyAccountsTop: TPanel;
- dgAccounts: TDrawGrid;
- cbMyPrivateKeys: TComboBox;
- Splitter1: TSplitter;
- MainMenu: TMainMenu;
- miProject: TMenuItem;
- miOptions: TMenuItem;
- miPrivatekeys: TMenuItem;
- miN1: TMenuItem;
- miAbout: TMenuItem;
- miAboutPascalCoin: TMenuItem;
- miNewOperation: TMenuItem;
- Panel1: TPanel;
- Label2: TLabel;
- ebFilterOperationsStartBlock: TEdit;
- ebFilterOperationsEndBlock: TEdit;
- tsNodeStats: TTabSheet;
- memoNetConnections: TMemo;
- memoNetServers: TMemo;
- memoNetBlackLists: TMemo;
- Label3: TLabel;
- Label6: TLabel;
- Label7: TLabel;
- lblCurrentBlockCaption: TLabel;
- lblCurrentBlock: TLabel;
- lblCurrentBlockTimeCaption: TLabel;
- lblCurrentBlockTime: TLabel;
- lblOperationsPendingCaption: TLabel;
- lblOperationsPending: TLabel;
- lblMiningStatusCaption: TLabel;
- lblMinersClients: TLabel;
- lblCurrentDifficultyCaption: TLabel;
- lblCurrentDifficulty: TLabel;
- lblTimeAverage: TLabel;
- Label4: TLabel;
- tsBlockChain: TTabSheet;
- Panel2: TPanel;
- Label9: TLabel;
- ebBlockChainBlockStart: TEdit;
- ebBlockChainBlockEnd: TEdit;
- Label8: TLabel;
- lblNodeStatus: TLabel;
- tsPendingOperations: TTabSheet;
- dgPendingOperations: TDrawGrid;
- pnlPendingOperations: TPanel;
- Label10: TLabel;
- cbExploreMyAccounts: TCheckBox;
- N1: TMenuItem;
- MiClose: TMenuItem;
- MiDecodePayload: TMenuItem;
- ImageListIcons: TImageList;
- ApplicationEvents: {$IFDEF FPC}TApplicationProperties{$ELSE}TApplicationEvents{$ENDIF};
- Label5: TLabel;
- lblCurrentAccounts: TLabel;
- lblTimeAverageAux: TLabel;
- tsMessages: TTabSheet;
- lbNetConnections: TListBox;
- bbSendAMessage: TButton;
- Label11: TLabel;
- memoMessages: TMemo;
- memoMessageToSend: TMemo;
- Label12: TLabel;
- Label13: TLabel;
- Label14: TLabel;
- Label16: TLabel;
- lblBlocksFound: TLabel;
- pnlAccounts: TPanel;
- pnlAccountsInfo: TPanel;
- Label17: TLabel;
- Label19: TLabel;
- lblAccountsCount: TLabel;
- lblAccountsBalance: TLabel;
- lblReceivedMessages: TLabel;
- lblBuild: TLabel;
- ebFindAccountNumber: TEdit;
- Label18: TLabel;
- IPnodes1: TMenuItem;
- bbChangeKeyName: TBitBtn;
- pcAccountsOptions: TPageControl;
- tsAccountOperations: TTabSheet;
- dgAccountOperations: TDrawGrid;
- tsMultiSelectAccounts: TTabSheet;
- dgSelectedAccounts: TDrawGrid;
- pnlSelectedAccountsTop: TPanel;
- pnlSelectedAccountsBottom: TPanel;
- pnlSelectedAccountsLeft: TPanel;
- sbSelectedAccountsAdd: TSpeedButton;
- sbSelectedAccountsAddAll: TSpeedButton;
- sbSelectedAccountsDel: TSpeedButton;
- sbSelectedAccountsDelAll: TSpeedButton;
- Label20: TLabel;
- lblSelectedAccountsCount: TLabel;
- Label22: TLabel;
- lblSelectedAccountsBalance: TLabel;
- bbSelectedAccountsOperation: TBitBtn;
- Label15: TLabel;
- MiOperations: TMenuItem;
- MiAddaccounttoSelected: TMenuItem;
- MiRemoveaccountfromselected: TMenuItem;
- N2: TMenuItem;
- MiMultiaccountoperation: TMenuItem;
- N3: TMenuItem;
- MiFindnextaccountwithhighbalance: TMenuItem;
- MiFindpreviousaccountwithhighbalance: TMenuItem;
- MiFindaccount: TMenuItem;
- cbFilterAccounts: TCheckBox;
- ebFilterAccountByBalanceMin: TEdit;
- ebFilterAccountByBalanceMax: TEdit;
- bbAccountsRefresh: TBitBtn;
- dgBlockChainExplorer: TDrawGrid;
- dgOperationsExplorer: TDrawGrid;
- MiFindOperationbyOpHash: TMenuItem;
- MiAccountInformation: TMenuItem;
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure sbSearchAccountClick(Sender: TObject);
- procedure TimerUpdateStatusTimer(Sender: TObject);
- procedure cbMyPrivateKeysChange(Sender: TObject);
- procedure dgAccountsClick(Sender: TObject);
- procedure miOptionsClick(Sender: TObject);
- procedure miAboutPascalCoinClick(Sender: TObject);
- procedure miNewOperationClick(Sender: TObject);
- procedure miPrivatekeysClick(Sender: TObject);
- procedure dgAccountsColumnMoved(Sender: TObject; FromIndex,
- ToIndex: Integer);
- procedure dgAccountsFixedCellClick(Sender: TObject; ACol, ARow: Integer);
- procedure PageControlChange(Sender: TObject);
- procedure ebFilterOperationsAccountExit(Sender: TObject);
- procedure ebFilterOperationsAccountKeyPress(Sender: TObject; var Key: Char);
- procedure ebBlockChainBlockStartExit(Sender: TObject);
- procedure ebBlockChainBlockStartKeyPress(Sender: TObject; var Key: Char);
- procedure cbExploreMyAccountsClick(Sender: TObject);
- procedure MiCloseClick(Sender: TObject);
- procedure MiDecodePayloadClick(Sender: TObject);
- procedure TrayIconDblClick(Sender: TObject);
- procedure ApplicationEventsMinimize(Sender: TObject);
- procedure bbSendAMessageClick(Sender: TObject);
- procedure lblReceivedMessagesClick(Sender: TObject);
- procedure ebFindAccountNumberChange(Sender: TObject);
- procedure ebFindAccountNumberExit(Sender: TObject);
- procedure IPnodes1Click(Sender: TObject);
- procedure bbChangeKeyNameClick(Sender: TObject);
- procedure sbSelectedAccountsAddClick(Sender: TObject);
- procedure sbSelectedAccountsAddAllClick(Sender: TObject);
- procedure sbSelectedAccountsDelClick(Sender: TObject);
- procedure sbSelectedAccountsDelAllClick(Sender: TObject);
- procedure bbSelectedAccountsOperationClick(Sender: TObject);
- procedure MiAddaccounttoSelectedClick(Sender: TObject);
- procedure MiRemoveaccountfromselectedClick(Sender: TObject);
- procedure MiMultiaccountoperationClick(Sender: TObject);
- procedure MiFindnextaccountwithhighbalanceClick(Sender: TObject);
- procedure MiFindpreviousaccountwithhighbalanceClick(Sender: TObject);
- procedure MiFindaccountClick(Sender: TObject);
- procedure bbAccountsRefreshClick(Sender: TObject);
- procedure ebFilterAccountByBalanceMinExit(Sender: TObject);
- procedure ebFilterAccountByBalanceMinKeyPress(Sender: TObject;
- var Key: Char);
- procedure cbFilterAccountsClick(Sender: TObject);
- procedure MiFindOperationbyOpHashClick(Sender: TObject);
- procedure MiAccountInformationClick(Sender: TObject);
- private
- FLastNodesCacheUpdatedTS : TDateTime;
- FBackgroundPanel : TPanel;
- FMinersBlocksFound: Integer;
- procedure SetMinersBlocksFound(const Value: Integer);
- Procedure CheckIsReady;
- Procedure FinishedLoadingApp;
- Procedure FillAccountInformation(Const Strings : TStrings; Const AccountNumber : Cardinal);
- Procedure FillOperationInformation(Const Strings : TStrings; Const OperationResume : TOperationResume);
- protected
- { Private declarations }
- FNode : TNode;
- FIsActivated : Boolean;
- FWalletKeys : TWalletKeysExt;
- FLog : TLog;
- FAppParams : TAppParams;
- FNodeNotifyEvents : TNodeNotifyEvents;
- FAccountsGrid : TAccountsGrid;
- FSelectedAccountsGrid : TAccountsGrid;
- FOperationsAccountGrid : TOperationsGrid;
- FPendingOperationsGrid : TOperationsGrid;
- FOrderedAccountsKeyList : TOrderedAccountKeysList;
- FOperationsExplorerGrid : TOperationsGrid;
- FBlockChainGrid : TBlockChainGrid;
- FMinerPrivateKeyType : TMinerPrivateKey;
- FUpdating : Boolean;
- FMessagesUnreadCount : Integer;
- FMinAccountBalance : Int64;
- FMaxAccountBalance : Int64;
- FPoolMiningServer : TPoolMiningServer;
- FRPCServer : TRPCServer;
- FMustProcessWalletChanged : Boolean;
- FMustProcessNetConnectionUpdated : Boolean;
- Procedure OnNewAccount(Sender : TObject);
- Procedure OnReceivedHelloMessage(Sender : TObject);
- Procedure OnNetStatisticsChanged(Sender : TObject);
- procedure OnNewLog(logtype : TLogType; Time : TDateTime; ThreadID : TThreadID; Const sender, logtext : AnsiString);
- procedure OnWalletChanged(Sender : TObject);
- procedure OnNetConnectionsUpdated(Sender : TObject);
- procedure OnNetNodeServersUpdated(Sender : TObject);
- procedure OnNetBlackListUpdated(Sender : TObject);
- Procedure OnNodeMessageEvent(NetConnection : TNetConnection; MessageData : TRawBytes);
- Procedure OnSelectedAccountsGridUpdated(Sender : TObject);
- Procedure OnMiningServerNewBlockFound(Sender : TObject);
- Procedure UpdateConnectionStatus;
- Procedure UpdateAccounts(RefreshData : Boolean);
- Procedure UpdateBlockChainState;
- Procedure UpdatePrivateKeys;
- Procedure UpdateOperations;
- Procedure LoadAppParams;
- Procedure SaveAppParams;
- Procedure UpdateConfigChanged;
- Procedure UpdateNodeStatus;
- Procedure UpdateAvailableConnections;
- procedure Activate; override;
- Function ForceMining : Boolean; virtual;
- Function GetAccountKeyForMiner : TAccountKey;
- Procedure DoUpdateAccounts;
- Function DoUpdateAccountsFilter : Boolean;
- procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
- procedure CM_NetConnectionUpdated(var Msg: TMessage); message CM_PC_NetConnectionUpdated;
- public
- { Public declarations }
- Property WalletKeys : TWalletKeysExt read FWalletKeys;
- Property MinersBlocksFound : Integer read FMinersBlocksFound write SetMinersBlocksFound;
- end;
- var
- FRMWallet: TFRMWallet;
- implementation
- {$IFnDEF FPC}
- {$R *.dfm}
- {$ELSE}
- {$R *.lfm}
- {$ENDIF}
- Uses UFolderHelper, UOpenSSL, UOpenSSLdef, UTime, UFileStorage,
- UThread, UOpTransaction, UECIES, UFRMPascalCoinWalletConfig,
- UFRMAbout, UFRMOperation, UFRMWalletKeys, UFRMPayloadDecoder, UFRMNodesIp, UFRMMemoText, USettings, UCommon;
- Type
- TThreadActivate = Class(TPCThread)
- protected
- procedure BCExecute; override;
- End;
- { TThreadActivate }
- procedure TThreadActivate.BCExecute;
- begin
- // Read Operations saved from disk
- TNode.Node.InitSafeboxAndOperations; // New Build 2.1.4 to load pending operations buffer
- TNode.Node.AutoDiscoverNodes(CT_Discover_IPs);
- TNode.Node.NetServer.Active := true;
- Synchronize( FRMWallet.DoUpdateAccounts );
- Synchronize( FRMWallet.FinishedLoadingApp );
- end;
- { TFRMWallet }
- procedure TFRMWallet.Activate;
- Var ips : AnsiString;
- nsarr : TNodeServerAddressArray;
- begin
- inherited;
- if FIsActivated then exit;
- FIsActivated := true;
- try
- // Check OpenSSL dll
- 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');
- TCrypto.InitCrypto;
- // Read Wallet
- Try
- FWalletKeys.WalletFileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'WalletKeys.dat';
- Except
- On E:Exception do begin
- E.Message := 'Cannot open your wallet... Perhaps another instance of Pascal Coin is active!'+#10+#10+E.Message;
- Raise;
- end;
- End;
- ips := FAppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].GetAsString('');
- TNode.DecodeIpStringToNodeServerAddressArray(ips,nsarr);
- TNetData.NetData.DiscoverFixedServersOnly(nsarr);
- setlength(nsarr,0);
- // Creating Node:
- FNode := TNode.Node;
- FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
- FNode.PeerCache := FAppParams.ParamByName[CT_PARAM_PeerCache].GetAsString('')+';'+CT_Discover_IPs;
- // Create RPC server
- FRPCServer := TRPCServer.Create;
- FRPCServer.WalletKeys := WalletKeys;
- FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
- FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
- WalletKeys.SafeBox := FNode.Bank.SafeBox;
- // Check Database
- FNode.Bank.StorageClass := TFileStorage;
- TFileStorage(FNode.Bank.Storage).DatabaseFolder := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'Data';
- TFileStorage(FNode.Bank.Storage).Initialize;
- // Init Grid
- //FAccountsGrid.Node := FNode;
- FSelectedAccountsGrid.Node := FNode;
- FWalletKeys.OnChanged.Add( OnWalletChanged );
- FAccountsGrid.Node := FNode;
- FOperationsAccountGrid.Node := FNode;
- // Reading database
- TThreadActivate.Create(false).FreeOnTerminate := true;
- FNodeNotifyEvents.Node := FNode;
- // Init
- TNetData.NetData.OnReceivedHelloMessage := OnReceivedHelloMessage;
- TNetData.NetData.OnStatisticsChanged := OnNetStatisticsChanged;
- TNetData.NetData.OnNetConnectionsUpdated := onNetConnectionsUpdated;
- TNetData.NetData.OnNodeServersUpdated := OnNetNodeServersUpdated;
- TNetData.NetData.OnBlackListUpdated := OnNetBlackListUpdated;
- //
- TimerUpdateStatus.Interval := 1000;
- TimerUpdateStatus.Enabled := true;
- UpdateConfigChanged;
- Except
- On E:Exception do begin
- E.Message := 'An error occurred during initialization. Application cannot continue:'+#10+#10+E.Message+#10+#10+'Application will close...';
- Application.MessageBox(PChar(E.Message),PChar(Application.Title),MB_ICONERROR+MB_OK);
- Halt;
- end;
- end;
- UpdatePrivateKeys;
- UpdateAccounts(false);
- if FAppParams.ParamByName[CT_PARAM_FirstTime].GetAsBoolean(true) then begin
- FAppParams.ParamByName[CT_PARAM_FirstTime].SetAsBoolean(false);
- miAboutPascalCoinClick(Nil);
- end;
- end;
- procedure TFRMWallet.ApplicationEventsMinimize(Sender: TObject);
- begin
- {$IFnDEF FPC}
- Hide();
- WindowState := wsMinimized;
- TimerUpdateStatus.Enabled := false;
- { Show the animated tray icon and also a hint balloon. }
- TrayIcon.Visible := True;
- TrayIcon.ShowBalloonHint;
- {$ENDIF}
- end;
- procedure TFRMWallet.bbAccountsRefreshClick(Sender: TObject);
- begin
- UpdateAccounts(true);
- end;
- procedure TFRMWallet.bbChangeKeyNameClick(Sender: TObject);
- var i : Integer;
- name : String;
- begin
- if (cbMyPrivateKeys.ItemIndex<0) then exit;
- i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
- if (i<0) Or (i>=FWalletKeys.Count) then raise Exception.Create('Must select a Key');
- name := FWalletKeys.Key[i].Name;
- if InputQuery('Change Key name','Input new name',name) then begin
- FWalletKeys.SetName(i,name);
- end;
- UpdatePrivateKeys;
- end;
- procedure TFRMWallet.bbSelectedAccountsOperationClick(Sender: TObject);
- var l : TOrderedCardinalList;
- begin
- CheckIsReady;
- if FSelectedAccountsGrid.AccountsCount<=0 then raise Exception.Create('Must select at least 1 account');
- With TFRMOperation.Create(Self) do
- Try
- l := FSelectedAccountsGrid.LockAccountsList;
- try
- SenderAccounts.CopyFrom(l);
- finally
- FSelectedAccountsGrid.UnlockAccountsList;
- end;
- DefaultFee := FAppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
- WalletKeys := FWalletKeys;
- ShowModal;
- Finally
- Free;
- End;
- end;
- procedure TFRMWallet.bbSendAMessageClick(Sender: TObject);
- Var basem,m : String;
- them, errors : AnsiString;
- i,n : Integer;
- nc : TNetConnection;
- begin
- CheckIsReady;
- if (lbNetConnections.SelCount<=0) Or (lbNetConnections.ItemIndex<0) then raise Exception.Create('Select at least one connection');
- if lbNetConnections.SelCount<=0 then n := 1
- else n := lbNetConnections.SelCount;
- basem := memoMessageToSend.Lines.Text;
- m := '';
- // Clear non valid characters:
- for i := 1 to length(basem) do begin
- if basem[i] in [#32..#127] then m := m + basem[i]
- else m:=m+'.';
- end;
- if trim(m)='' then raise Exception.Create('No message');
- if Application.MessageBox(PChaR('Send this message to '+inttostr(n)+' nodes?'+#10+
- 'NOTE: Sending unauthorized messages will be considered spam and you will be banned'+#10+
- #10+
- 'Message: '+#10+
- m),PChar(Application.Title),MB_ICONQUESTION+MB_YESNO+MB_DEFBUTTON1)<>IdYes then exit;
- them := m;
- if n>1 then begin
- for i := 0 to lbNetConnections.Items.Count - 1 do begin
- if lbNetConnections.Selected[i] then begin
- nc := TNetConnection(lbNetconnections.Items.Objects[i]);
- if TNetData.NetData.ConnectionExistsAndActive(nc) then begin
- FNode.SendNodeMessage(nc,m,errors);
- memoMessages.Lines.Add(DateTimeToStr(now)+' Sent to '+nc.ClientRemoteAddr+' > '+m);
- end;
- end;
- end;
- end else begin
- nc := TNetConnection(lbNetconnections.Items.Objects[lbNetconnections.ItemIndex]);
- if TNetData.NetData.ConnectionExistsAndActive(nc) then begin
- FNode.SendNodeMessage(nc,m,errors);
- memoMessages.Lines.Add(DateTimeToStr(now)+' Sent to '+nc.ClientRemoteAddr+' > '+m);
- end;
- end;
- Application.MessageBox(PChaR('Message sent to '+inttostr(n)+' nodes'+#10+
- 'Message: '+#10+m),PChar(Application.Title),MB_ICONINFORMATION+MB_OK);
- end;
- procedure TFRMWallet.cbExploreMyAccountsClick(Sender: TObject);
- begin
- cbMyPrivateKeys.Enabled := cbExploreMyAccounts.Checked;
- UpdateAccounts(true);
- UpdateOperations;
- end;
- procedure TFRMWallet.cbFilterAccountsClick(Sender: TObject);
- begin
- If not DoUpdateAccountsFilter then UpdateAccounts(true);
- end;
- procedure TFRMWallet.cbMyPrivateKeysChange(Sender: TObject);
- begin
- UpdateAccounts(true);
- end;
- procedure TFRMWallet.CheckIsReady;
- Var isready : AnsiString;
- begin
- if Not Assigned(FNode) then Abort;
- if Not FNode.IsReady(isready) then begin
- Raise Exception.Create('You cannot do this operation now:'+#10+#10+isready);
- end;
- end;
- procedure TFRMWallet.CM_NetConnectionUpdated(var Msg: TMessage);
- Const CT_BooleanToString : Array[Boolean] of String = ('False','True');
- Var i : integer;
- NC : TNetConnection;
- l : TList;
- sClientApp, sLastConnTime : String;
- strings, sNSC, sRS, sDisc : TStrings;
- hh,nn,ss,ms : Word;
- begin
- Try
- if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
- try
- strings := memoNetConnections.Lines;
- sNSC := TStringList.Create;
- sRS := TStringList.Create;
- sDisc := TStringList.Create;
- strings.BeginUpdate;
- Try
- for i := 0 to l.Count - 1 do begin
- NC := l[i];
- If NC.Client.BytesReceived>0 then begin
- sClientApp := '['+IntToStr(NC.NetProtocolVersion.protocol_version)+'-'+IntToStr(NC.NetProtocolVersion.protocol_available)+'] '+NC.ClientAppVersion;
- end else begin
- sClientApp := '(no data)';
- end;
- if NC.Connected then begin
- if NC.Client.LastCommunicationTime>1000 then begin
- DecodeTime(now - NC.Client.LastCommunicationTime,hh,nn,ss,ms);
- if (hh=0) and (nn=0) And (ss<10) then begin
- sLastConnTime := ' - Last comunication <10 sec.';
- end else begin
- sLastConnTime := Format(' - Last comunication %.2dm%.2ds',[(hh*60)+nn,ss]);
- end;
- end else begin
- sLastConnTime := '';
- end;
- if NC is TNetServerClient then begin
- sNSC.Add(Format('Client: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
- [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
- end else begin
- if NC.IsMyselfServer then sNSC.Add(Format('MySelf IP:%s Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
- [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]))
- else begin
- sRS.Add(Format('Remote Server: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
- [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
- end;
- end;
- end else begin
- if NC is TNetServerClient then begin
- sDisc.Add(Format('Disconnected client: IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
- end else if NC.IsMyselfServer then begin
- sDisc.Add(Format('Disconnected MySelf IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
- end else begin
- sDisc.Add(Format('Disconnected Remote Server: IP:%s %s - %s',[NC.ClientRemoteAddr,CT_BooleanToString[NC.Connected],sClientApp]));
- end;
- end;
- end;
- strings.Clear;
- strings.Add(Format('Connections Updated %s Clients:%d Servers:%d (valid servers:%d)',[DateTimeToStr(now),sNSC.Count,sRS.Count,TNetData.NetData.NetStatistics.ServersConnectionsWithResponse]));
- strings.AddStrings(sRS);
- strings.AddStrings(sNSC);
- if sDisc.Count>0 then begin
- strings.Add('');
- strings.Add('Disconnected connections: '+Inttostr(sDisc.Count));
- strings.AddStrings(sDisc);
- end;
- Finally
- strings.EndUpdate;
- sNSC.Free;
- sRS.Free;
- sDisc.Free;
- End;
- //CheckMining;
- finally
- TNetData.NetData.NetConnections.UnlockList;
- end;
- Finally
- FMustProcessNetConnectionUpdated := false;
- End;
- end;
- procedure TFRMWallet.CM_WalletChanged(var Msg: TMessage);
- begin
- UpdatePrivateKeys;
- FMustProcessWalletChanged := false;
- end;
- procedure TFRMWallet.dgAccountsClick(Sender: TObject);
- begin
- UpdateOperations;
- end;
- procedure TFRMWallet.dgAccountsColumnMoved(Sender: TObject; FromIndex, ToIndex: Integer);
- begin
- SaveAppParams;
- end;
- procedure TFRMWallet.dgAccountsFixedCellClick(Sender: TObject; ACol,
- ARow: Integer);
- begin
- SaveAppParams;
- end;
- procedure TFRMWallet.DoUpdateAccounts;
- begin
- UpdateAccounts(true);
- end;
- function TFRMWallet.DoUpdateAccountsFilter: Boolean;
- Var m,bmin,bmax:Int64;
- doupd : Boolean;
- begin
- if FUpdating then exit;
- FUpdating := true;
- Try
- 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;
- Finally
- FUpdating := false;
- End;
- if doupd then UpdateAccounts(true);
- Result := doupd;
- end;
- procedure TFRMWallet.ebBlockChainBlockStartExit(Sender: TObject);
- var bstart,bend : Int64;
- begin
- If FUpdating then exit;
- FUpdating := True;
- Try
- bstart := StrToInt64Def(ebBlockChainBlockStart.Text,-1);
- bend := StrToInt64Def(ebBlockChainBlockEnd.Text,-1);
- FBlockChainGrid.SetBlocks(bstart,bend);
- if FBlockChainGrid.BlockStart>=0 then ebBlockChainBlockStart.Text := Inttostr(FBlockChainGrid.BlockStart) else ebBlockChainBlockStart.Text := '';
- if FBlockChainGrid.BlockEnd>=0 then ebBlockChainBlockEnd.Text := Inttostr(FBlockChainGrid.BlockEnd) else ebBlockChainBlockEnd.Text := '';
- Finally
- FUpdating := false;
- End;
- end;
- procedure TFRMWallet.ebBlockChainBlockStartKeyPress(Sender: TObject;
- var Key: Char);
- begin
- if key=#13 then ebBlockChainBlockStartExit(Nil);
- end;
- procedure TFRMWallet.ebFilterAccountByBalanceMinExit(Sender: TObject);
- begin
- DoUpdateAccountsFilter;
- end;
- procedure TFRMWallet.ebFilterAccountByBalanceMinKeyPress(Sender: TObject;
- var Key: Char);
- begin
- if key=#13 then DoUpdateAccountsFilter;
- end;
- procedure TFRMWallet.ebFilterOperationsAccountExit(Sender: TObject);
- Var bstart,bend : Int64;
- begin
- If FUpdating then exit;
- FUpdating := True;
- Try
- bstart := StrToInt64Def(ebFilterOperationsStartBlock.Text,-1);
- if bstart>=0 then ebFilterOperationsStartBlock.Text := Inttostr(bstart) else ebFilterOperationsStartBlock.Text := '';
- bend := StrToInt64Def(ebFilterOperationsEndBlock.Text,-1);
- if bend>=0 then ebFilterOperationsEndBlock.Text := Inttostr(bend) else ebFilterOperationsEndBlock.Text := '';
- FOperationsExplorerGrid.SetBlocks(bstart,bend);
- Finally
- FUpdating := false;
- End;
- end;
- procedure TFRMWallet.ebFilterOperationsAccountKeyPress(Sender: TObject;
- var Key: Char);
- begin
- if key=#13 then ebFilterOperationsAccountExit(Nil);
- end;
- procedure TFRMWallet.ebFindAccountNumberChange(Sender: TObject);
- Var an : Cardinal;
- 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;
- end;
- procedure TFRMWallet.ebFindAccountNumberExit(Sender: TObject);
- begin
- ebFindAccountNumber.Text := '';
- end;
- procedure TFRMWallet.FinishedLoadingApp;
- begin
- FPoolMiningServer := TPoolMiningServer.Create;
- FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
- FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
- FPoolMiningServer.MinerPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
- FNode.Operations.AccountKey := GetAccountKeyForMiner;
- FPoolMiningServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
- FPoolMiningServer.OnMiningServerNewBlockFound := OnMiningServerNewBlockFound;
- If Assigned(FBackgroundPanel) then begin
- FreeAndNil(FBackgroundPanel);
- end;
- PageControl.Visible:=True;
- PageControl.Enabled:=True;
- end;
- procedure TFRMWallet.FillAccountInformation(const Strings: TStrings; Const AccountNumber: Cardinal);
- Var account : TAccount;
- s : String;
- begin
- if AccountNumber<0 then exit;
- account := FNode.Operations.SafeBoxTransaction.Account(AccountNumber);
- if account.name<>'' then s:='Name: '+account.name
- else s:='';
- Strings.Add(Format('Account: %s %s Type:%d',[TAccountComp.AccountNumberToAccountTxtNumber(AccountNumber),s,account.account_type]));
- Strings.Add('');
- Strings.Add(Format('Current balance: %s',[TAccountComp.FormatMoney(account.balance)]));
- Strings.Add('');
- Strings.Add(Format('Updated on block: %d (%d blocks ago)',[account.updated_block,FNode.Bank.BlocksCount-account.updated_block]));
- Strings.Add(Format('Public key type: %s',[TAccountComp.GetECInfoTxt(account.accountInfo.accountKey.EC_OpenSSL_NID)]));
- Strings.Add(Format('Base58 Public key: %s',[TAccountComp.AccountPublicKeyExport(account.accountInfo.accountKey)]));
- if TAccountComp.IsAccountForSale(account.accountInfo) then begin
- Strings.Add('');
- Strings.Add('** Account is for sale: **');
- Strings.Add(Format('Price: %s',[TAccountComp.FormatMoney(account.accountInfo.price)]));
- Strings.Add(Format('Seller account (where to pay): %s',[TAccountComp.AccountNumberToAccountTxtNumber(account.accountInfo.account_to_pay)]));
- if TAccountComp.IsAccountForSaleAcceptingTransactions(account.accountInfo) then begin
- Strings.Add('');
- Strings.Add('** Private sale **');
- Strings.Add(Format('New Base58 Public key: %s',[TAccountComp.AccountPublicKeyExport(account.accountInfo.new_publicKey)]));
- Strings.Add('');
- if TAccountComp.IsAccountLocked(account.accountInfo,FNode.Bank.BlocksCount) then begin
- Strings.Add(Format('PURCHASE IS SECURE UNTIL BLOCK %d (current %d, remains %d)',
- [account.accountInfo.locked_until_block,FNode.Bank.BlocksCount,account.accountInfo.locked_until_block-FNode.Bank.BlocksCount]));
- end else begin
- Strings.Add(Format('PURCHASE IS NOT SECURE (Expired on block %d, current %d)',
- [account.accountInfo.locked_until_block,FNode.Bank.BlocksCount]));
- end;
- end;
- end;
- end;
- procedure TFRMWallet.FillOperationInformation(const Strings: TStrings; Const OperationResume: TOperationResume);
- begin
- If (not OperationResume.valid) then exit;
- If OperationResume.Block<FNode.Bank.BlocksCount then
- if (OperationResume.NOpInsideBlock>=0) then begin
- Strings.Add(Format('Block: %d/%d',[OperationResume.Block,OperationResume.NOpInsideBlock]))
- end else begin
- Strings.Add(Format('Block: %d',[OperationResume.Block]))
- end
- else Strings.Add('** Pending operation not included on blockchain **');
- Strings.Add(Format('%s',[OperationResume.OperationTxt]));
- Strings.Add(Format('OpType:%d Subtype:%d',[OperationResume.OpType,OperationResume.OpSubtype]));
- Strings.Add(Format('Operation Hash (ophash): %s',[TCrypto.ToHexaString(OperationResume.OperationHash)]));
- If (OperationResume.OperationHash_OLD<>'') then begin
- Strings.Add(Format('Old Operation Hash (old_ophash): %s',[TCrypto.ToHexaString(OperationResume.OperationHash_OLD)]));
- end;
- if (OperationResume.OriginalPayload<>'') then begin
- Strings.Add(Format('Payload length:%d',[length(OperationResume.OriginalPayload)]));
- If OperationResume.PrintablePayload<>'' then begin
- Strings.Add(Format('Payload (human): %s',[OperationResume.PrintablePayload]));
- end;
- Strings.Add(Format('Payload (Hexadecimal): %s',[TCrypto.ToHexaString(OperationResume.OriginalPayload)]));
- end;
- If OperationResume.Balance>=0 then begin
- Strings.Add(Format('Final balance: %s',[TAccountComp.FormatMoney(OperationResume.Balance)]));
- end;
- end;
- function TFRMWallet.ForceMining: Boolean;
- begin
- Result := false;
- end;
- procedure TFRMWallet.FormCreate(Sender: TObject);
- Var i : Integer;
- begin
- FLastNodesCacheUpdatedTS := Now;
- FBackgroundPanel := Nil;
- FMustProcessWalletChanged := false;
- FMustProcessNetConnectionUpdated := false;
- FRPCServer := Nil;
- FNode := Nil;
- FPoolMiningServer := Nil;
- FMinAccountBalance := 0;
- FMaxAccountBalance := CT_MaxWalletAmount;
- FMessagesUnreadCount := 0;
- lblReceivedMessages.Visible := false;
- memoNetConnections.Lines.Clear;
- memoNetServers.Lines.Clear;
- memoNetBlackLists.Lines.Clear;
- memoMessages.Lines.Clear;
- memoMessageToSend.Lines.Clear;
- FUpdating := false;
- FOrderedAccountsKeyList := Nil;
- TimerUpdateStatus.Enabled := false;
- FIsActivated := false;
- FWalletKeys := TWalletKeysExt.Create(Self);
- for i := 0 to StatusBar.Panels.Count - 1 do begin
- StatusBar.Panels[i].Text := '';
- end;
- FLog := TLog.Create(Self);
- FLog.OnNewLog := OnNewLog;
- FLog.SaveTypes := [];
- If Not ForceDirectories(TFolderHelper.GetPascalCoinDataFolder) then raise Exception.Create('Cannot create dir: '+TFolderHelper.GetPascalCoinDataFolder);
- FAppParams := TAppParams.Create(self);
- FAppParams.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'AppParams.prm';
- FNodeNotifyEvents := TNodeNotifyEvents.Create(Self);
- FNodeNotifyEvents.OnBlocksChanged := OnNewAccount;
- FNodeNotifyEvents.OnNodeMessageEvent := OnNodeMessageEvent;
- FAccountsGrid := TAccountsGrid.Create(Self);
- FAccountsGrid.DrawGrid := dgAccounts;
- FAccountsGrid.AllowMultiSelect := True;
- FSelectedAccountsGrid := TAccountsGrid.Create(Self);
- FSelectedAccountsGrid.DrawGrid := dgSelectedAccounts;
- FSelectedAccountsGrid.OnUpdated := OnSelectedAccountsGridUpdated;
- FOperationsAccountGrid := TOperationsGrid.Create(Self);
- FOperationsAccountGrid.DrawGrid := dgAccountOperations;
- FOperationsAccountGrid.MustShowAlwaysAnAccount := true;
- FPendingOperationsGrid := TOperationsGrid.Create(Self);
- FPendingOperationsGrid.DrawGrid := dgPendingOperations;
- FPendingOperationsGrid.AccountNumber := -1; // all
- FPendingOperationsGrid.PendingOperations := true;
- FOperationsExplorerGrid := TOperationsGrid.Create(Self);
- FOperationsExplorerGrid.DrawGrid := dgOperationsExplorer;
- FOperationsExplorerGrid.AccountNumber := -1;
- FOperationsExplorerGrid.PendingOperations := False;
- FBlockChainGrid := TBlockChainGrid.Create(Self);
- FBlockChainGrid.DrawGrid := dgBlockChainExplorer;
- // FWalletKeys.OnChanged.Add( OnWalletChanged );
- LoadAppParams;
- UpdatePrivateKeys;
- UpdateBlockChainState;
- UpdateConnectionStatus;
- PageControl.ActivePage := tsMyAccounts;
- pcAccountsOptions.ActivePage := tsAccountOperations;
- ebFilterOperationsStartBlock.Text := '';
- ebFilterOperationsEndBlock.Text := '';
- cbExploreMyAccountsClick(nil);
- TrayIcon.Visible := true;
- TrayIcon.Hint := Self.Caption;
- TrayIcon.BalloonTitle := 'Restoring the window.';
- TrayIcon.BalloonHint :=
- 'Double click the system tray icon to restore Pascal Coin';
- TrayIcon.BalloonFlags := bfInfo;
- MinersBlocksFound := 0;
- lblBuild.Caption := 'Build: '+CT_ClientAppVersion;
- {$IFDEF TESTNET}
- Image1.visible := false;
- {$ENDIF}
- PageControl.Enabled := False;
- PageControl.Visible := False;
- FBackgroundPanel := TPanel.Create(Self);
- FBackgroundPanel.Parent:=Self;
- FBackgroundPanel.Align:=alClient;
- FBackgroundPanel.Font.Size:=15;
- end;
- procedure TFRMWallet.FormDestroy(Sender: TObject);
- Var i : Integer;
- step : String;
- begin
- TLog.NewLog(ltinfo,Classname,'Destroying form - START');
- Try
- FreeAndNil(FRPCServer);
- FreeAndNil(FPoolMiningServer);
- step := 'Saving params';
- SaveAppParams;
- FreeAndNil(FAppParams);
- //
- step := 'Assigning nil events';
- FLog.OnNewLog :=Nil;
- FNodeNotifyEvents.Node := Nil;
- FOperationsAccountGrid.Node := Nil;
- FOperationsExplorerGrid.Node := Nil;
- FPendingOperationsGrid.Node := Nil;
- FAccountsGrid.Node := Nil;
- FSelectedAccountsGrid.Node := Nil;
- TNetData.NetData.OnReceivedHelloMessage := Nil;
- TNetData.NetData.OnStatisticsChanged := Nil;
- TNetData.NetData.OnNetConnectionsUpdated := Nil;
- TNetData.NetData.OnNodeServersUpdated := Nil;
- TNetData.NetData.OnBlackListUpdated := Nil;
- //
- step := 'Destroying NodeNotifyEvents';
- FreeAndNil(FNodeNotifyEvents);
- //
- step := 'Assigning Nil to TNetData';
- TNetData.NetData.OnReceivedHelloMessage := Nil;
- TNetData.NetData.OnStatisticsChanged := Nil;
- step := 'Destroying grids operators';
- FreeAndNil(FOperationsAccountGrid);
- FreeAndNil(FOperationsExplorerGrid);
- FreeAndNil(FBlockChainGrid);
- step := 'Ordered Accounts Key list';
- FreeAndNil(FOrderedAccountsKeyList);
- step := 'Desactivating Node';
- TNode.Node.NetServer.Active := false;
- FNode := Nil;
- TNetData.NetData.Free;
- step := 'Processing messages 1';
- Application.ProcessMessages;
- step := 'Destroying Node';
- TNode.Node.Free;
- step := 'Destroying Wallet';
- FreeAndNil(FWalletKeys);
- step := 'Processing messages 2';
- Application.ProcessMessages;
- step := 'Destroying stringslist';
- Except
- On E:Exception do begin
- TLog.NewLog(lterror,Classname,'Error destroying Form step: '+step+' Errors ('+E.ClassName+'): ' +E.Message);
- end;
- End;
- TLog.NewLog(ltinfo,Classname,'Destroying form - END');
- FreeAndNil(FLog);
- Sleep(100);
- end;
- procedure TFRMWallet.sbSearchAccountClick(Sender: TObject);
- Var F : TFRMAccountSelect;
- begin
- F := TFRMAccountSelect.Create(Self);
- try
- F.Node := FNode;
- F.WalletKeys := FWalletKeys;
- F.ShowModal;
- finally
- F.Free;
- end;
- end;
- function TFRMWallet.GetAccountKeyForMiner: TAccountKey;
- Var PK : TECPrivateKey;
- i : Integer;
- PublicK : TECDSA_Public;
- begin
- Result := CT_TECDSA_Public_Nul;
- if Not Assigned(FWalletKeys) then exit;
- if Not Assigned(FAppParams) then exit;
- case FMinerPrivateKeyType of
- mpk_NewEachTime: PublicK := CT_TECDSA_Public_Nul;
- mpk_Selected: begin
- PublicK := TAccountComp.RawString2Accountkey(FAppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].GetAsString(''));
- end;
- else
- // Random
- PublicK := CT_TECDSA_Public_Nul;
- if FWalletKeys.Count>0 then PublicK := FWalletKeys.Key[Random(FWalletKeys.Count)].AccountKey;
- end;
- i := FWalletKeys.IndexOfAccountKey(PublicK);
- if i>=0 then begin
- if (FWalletKeys.Key[i].CryptedKey='') then i:=-1;
- end;
- if i<0 then begin
- PK := TECPrivateKey.Create;
- try
- PK.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
- FWalletKeys.AddPrivateKey('New for miner '+DateTimeToStr(Now), PK);
- PublicK := PK.PublicKey;
- finally
- PK.Free;
- end;
- end;
- Result := PublicK;
- end;
- procedure TFRMWallet.IPnodes1Click(Sender: TObject);
- Var FRM : TFRMNodesIp;
- begin
- FRM := TFRMNodesIp.Create(Self);
- Try
- FRM.AppParams := FAppParams;
- FRM.ShowModal;
- Finally
- FRM.Free;
- End;
- end;
- procedure TFRMWallet.lblReceivedMessagesClick(Sender: TObject);
- begin
- PageControl.ActivePage := tsMessages;
- end;
- procedure TFRMWallet.LoadAppParams;
- Var ms : TMemoryStream;
- s : AnsiString;
- fvi : TFileVersionInfo;
- begin
- ms := TMemoryStream.Create;
- Try
- s := FAppParams.ParamByName[CT_PARAM_GridAccountsStream].GetAsString('');
- ms.WriteBuffer(s[1],length(s));
- ms.Position := 0;
- // Disabled on V2: FAccountsGrid.LoadFromStream(ms);
- Finally
- ms.Free;
- End;
- If FAppParams.FindParam(CT_PARAM_MinerName)=Nil then begin
- // New configuration... assigning a new random value
- fvi := TFolderHelper.GetTFileVersionInfo(Application.ExeName);
- FAppParams.ParamByName[CT_PARAM_MinerName].SetAsString('New Node '+DateTimeToStr(Now)+' - '+
- fvi.InternalName+' Build:'+fvi.FileVersion);
- end;
- FBlockChainGrid.ShowTimeAverageColumns:={$IFDEF SHOW_AVERAGE_TIME_STATS}True;{$ELSE}False;{$ENDIF}
- UpdateConfigChanged;
- end;
- procedure TFRMWallet.miAboutPascalCoinClick(Sender: TObject);
- begin
- With TFRMAbout.Create(Self) do
- try
- showmodal;
- finally
- free;
- end;
- end;
- procedure TFRMWallet.MiAccountInformationClick(Sender: TObject);
- Var F : TFRMMemoText;
- accn : Int64;
- s,title : String;
- account : TAccount;
- strings : TStrings;
- i : Integer;
- opr : TOperationResume;
- begin
- accn := -1;
- title := '';
- strings := TStringList.Create;
- try
- opr := CT_TOperationResume_NUL;
- if PageControl.ActivePage=tsOperations then begin
- i := FOperationsExplorerGrid.DrawGrid.Row;
- if (i>0) and (i<=FOperationsExplorerGrid.OperationsResume.Count) then begin
- opr := FOperationsExplorerGrid.OperationsResume.OperationResume[i-1];
- end;
- end else if PageControl.ActivePage=tsPendingOperations then begin
- i := FPendingOperationsGrid.DrawGrid.Row;
- if (i>0) and (i<=FPendingOperationsGrid.OperationsResume.Count) then begin
- opr := FPendingOperationsGrid.OperationsResume.OperationResume[i-1];
- end;
- end else if PageControl.ActivePage=tsMyAccounts then begin
- accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
- if accn<0 then raise Exception.Create('Select an account');
- FillAccountInformation(strings,accn);
- title := 'Account '+TAccountComp.AccountNumberToAccountTxtNumber(accn)+' info';
- i := FOperationsAccountGrid.DrawGrid.Row;
- if (i>0) and (i<=FOperationsAccountGrid.OperationsResume.Count) then begin
- opr := FOperationsAccountGrid.OperationsResume.OperationResume[i-1];
- end;
- end;
- If (opr.valid) then begin
- if accn>=0 then strings.Add('')
- else title := 'Operation info';
- strings.Add('Operation info:');
- FillOperationInformation(strings,opr);
- end else if accn<0 then Raise Exception.Create('No info available');
- F := TFRMMemoText.Create(Self);
- Try
- F.Caption := title;
- F.Memo.Lines.Assign(strings);
- F.ShowModal;
- Finally
- F.Free;
- End;
- finally
- strings.free;
- end;
- end;
- procedure TFRMWallet.MiAddaccounttoSelectedClick(Sender: TObject);
- begin
- PageControl.ActivePage := tsMyAccounts;
- PageControlChange(Nil);
- pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
- sbSelectedAccountsAddClick(Sender);
- end;
- procedure TFRMWallet.MiCloseClick(Sender: TObject);
- begin
- Close;
- end;
- procedure TFRMWallet.MiDecodePayloadClick(Sender: TObject);
- begin
- if PageControl.ActivePage=tsOperations then begin
- FOperationsExplorerGrid.ShowModalDecoder(FWalletKeys,FAppParams);
- end else if PageControl.ActivePage=tsPendingOperations then begin
- FPendingOperationsGrid.ShowModalDecoder(FWalletKeys,FAppParams);
- end else if PageControl.ActivePage=tsMyAccounts then begin
- FOperationsAccountGrid.ShowModalDecoder(FWalletKeys,FAppParams);
- end;
- end;
- procedure TFRMWallet.MiFindaccountClick(Sender: TObject);
- begin
- PageControl.ActivePage := tsMyAccounts;
- PageControlChange(Nil);
- ebFindAccountNumber.SetFocus;
- end;
- procedure TFRMWallet.MiFindnextaccountwithhighbalanceClick(Sender: TObject);
- Var an : Cardinal;
- an64 : Int64;
- start : TAccount;
- begin
- PageControl.ActivePage := tsMyAccounts;
- PageControlChange(Nil);
- an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
- if an64<0 then an := 0
- else an := an64;
- If an>=FNode.Bank.SafeBox.AccountsCount then exit;
- start := FNode.Bank.SafeBox.Account(an);
- while (an<FNode.Bank.SafeBox.AccountsCount) do begin
- if FNode.Bank.SafeBox.Account(an).balance>start.balance then break
- else inc(an);
- end;
- if (an<FNode.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));
- end;
- procedure TFRMWallet.MiFindOperationbyOpHashClick(Sender: TObject);
- Var FRM : TFRMPayloadDecoder;
- oph : String;
- begin
- oph := '';
- if Not InputQuery('Search operation by OpHash','Insert Operation Hash value (OpHash)',oph) then exit;
- //
- FRM := TFRMPayloadDecoder.Create(Self);
- try
- FRM.Init(CT_TOperationResume_NUL,WalletKeys,FAppParams);
- FRM.DoFind(oph);
- FRM.ShowModal;
- finally
- FRM.Free;
- end;
- end;
- procedure TFRMWallet.MiFindpreviousaccountwithhighbalanceClick(Sender: TObject);
- Var an : Cardinal;
- an64 : Int64;
- start : TAccount;
- begin
- PageControl.ActivePage := tsMyAccounts;
- PageControlChange(Nil);
- an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
- if an64<0 then an := FNode.Bank.SafeBox.AccountsCount-1
- else an := an64;
- If an>=FNode.Bank.SafeBox.AccountsCount then exit;
- start := FNode.Bank.SafeBox.Account(an);
- while (an>0) do begin
- if FNode.Bank.SafeBox.Account(an).balance>start.balance then break
- else dec(an);
- end;
- if (FNode.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));
- end;
- procedure TFRMWallet.MiMultiaccountoperationClick(Sender: TObject);
- begin
- PageControl.ActivePage := tsMyAccounts;
- pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
- bbSelectedAccountsOperationClick(Sender);
- end;
- procedure TFRMWallet.miNewOperationClick(Sender: TObject);
- var l : TOrderedCardinalList;
- begin
- CheckIsReady;
- With TFRMOperation.Create(Self) do
- Try
- l := TOrderedCardinalList.Create;
- try
- If FAccountsGrid.SelectedAccounts(l)<1 then raise Exception.Create('No row selected');
- SenderAccounts.CopyFrom(l);
- finally
- l.Free;
- end;
- DefaultFee := FAppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
- WalletKeys := FWalletKeys;
- ShowModal;
- Finally
- Free;
- End;
- end;
- procedure TFRMWallet.miOptionsClick(Sender: TObject);
- begin
- With TFRMPascalCoinWalletConfig.Create(Self) do
- try
- AppParams := Self.FAppParams;
- WalletKeys := Self.FWalletKeys;
- if ShowModal=MrOk then begin
- SaveAppParams;
- UpdateConfigChanged;
- end;
- finally
- free;
- end;
- end;
- procedure TFRMWallet.miPrivatekeysClick(Sender: TObject);
- Var FRM : TFRMWalletKeys;
- begin
- FRM := TFRMWalletKeys.Create(Self);
- Try
- FRM.WalletKeys := FWalletKeys;
- FRM.ShowModal;
- UpdatePrivateKeys;
- Finally
- FRM.Free;
- End;
- end;
- procedure TFRMWallet.MiRemoveaccountfromselectedClick(Sender: TObject);
- begin
- PageControl.ActivePage := tsMyAccounts;
- PageControlChange(Nil);
- pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
- sbSelectedAccountsDelClick(Sender);
- end;
- procedure TFRMWallet.OnMiningServerNewBlockFound(Sender: TObject);
- begin
- FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
- end;
- procedure TFRMWallet.OnNetBlackListUpdated(Sender: TObject);
- Const CT_TRUE_FALSE : Array[Boolean] Of AnsiString = ('FALSE','TRUE');
- Var i,j,n : integer;
- P : PNodeServerAddress;
- l : TList;
- strings : TStrings;
- begin
- l := TNetData.NetData.NodeServersAddresses.LockList;
- try
- strings := memoNetBlackLists.Lines;
- strings.BeginUpdate;
- Try
- strings.Clear;
- strings.Add('BlackList Updated: '+DateTimeToStr(now)+' by TID:'+IntToHex(PtrInt(TThread.CurrentThread.ThreadID),8));
- j := 0; n:=0;
- for i := 0 to l.Count - 1 do begin
- P := l[i];
- if (P^.is_blacklisted) then begin
- inc(n);
- if Not P^.its_myself then begin
- inc(j);
- strings.Add(Format('Blacklist IP:%s:%d LastConnection:%s Reason: %s',
- [
- P^.ip,P^.port,
- DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection))),P^.BlackListText]));
- end;
- end;
- end;
- Strings.Add(Format('Total Blacklisted IPs: %d (Total %d)',[j,n]));
- Finally
- strings.EndUpdate;
- End;
- finally
- TNetData.NetData.NodeServersAddresses.UnlockList;
- end;
- end;
- procedure TFRMWallet.OnNetConnectionsUpdated(Sender: TObject);
- begin
- if FMustProcessNetConnectionUpdated then exit;
- FMustProcessNetConnectionUpdated := true;
- PostMessage(Self.Handle,CM_PC_NetConnectionUpdated,0,0);
- end;
- procedure TFRMWallet.OnNetNodeServersUpdated(Sender: TObject);
- Var i : integer;
- P : PNodeServerAddress;
- l : TList;
- strings : TStrings;
- s : String;
- begin
- l := TNetData.NetData.NodeServersAddresses.LockList;
- try
- strings := memoNetServers.Lines;
- strings.BeginUpdate;
- Try
- strings.Clear;
- strings.Add('NodeServers Updated: '+DateTimeToStr(now) +' Count: '+inttostr(l.Count));
- for i := 0 to l.Count - 1 do begin
- P := l[i];
- if Not (P^.is_blacklisted) then begin
- s := Format('Server IP:%s:%d',[P^.ip,P^.port]);
- if (P^.last_connection_by_me>0) then begin
- s := s + ' [Server] ';
- end;
- if Assigned(P.netConnection) then begin
- If P.last_connection>0 then s := s+ ' ** ACTIVE **'
- else s := s+' ** TRYING TO CONNECT **';
- end;
- if P.its_myself then begin
- s := s+' ** NOT VALID ** '+P.BlackListText;
- end;
- if P.last_connection>0 then begin
- s := s + ' Last connection: '+DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection)));
- end;
- if P.last_connection_by_server>0 then begin
- s := s + ' Last server connection: '+DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection_by_server)));
- end;
- if (P.last_attempt_to_connect>0) then begin
- s := s + ' Last attempt to connect: '+DateTimeToStr(P^.last_attempt_to_connect);
- end;
- if (P.total_failed_attemps_to_connect>0) then begin
- s := s + ' (Attempts: '+inttostr(P^.total_failed_attemps_to_connect)+')';
- end;
- strings.Add(s);
- end;
- end;
- Finally
- strings.EndUpdate;
- End;
- finally
- TNetData.NetData.NodeServersAddresses.UnlockList;
- end;
- end;
- procedure TFRMWallet.OnNetStatisticsChanged(Sender: TObject);
- Var NS : TNetStatistics;
- begin
- //CheckMining;
- if Assigned(FNode) then begin
- If FNode.NetServer.Active then begin
- StatusBar.Panels[0].Text := 'Active (Port '+Inttostr(FNode.NetServer.Port)+')';
- end else StatusBar.Panels[0].Text := 'Server stopped';
- NS := TNetData.NetData.NetStatistics;
- StatusBar.Panels[1].Text := Format('Connections:%d Clients:%d Servers:%d - Rcvd:%d Kb Send:%d Kb',
- [NS.ActiveConnections,NS.ClientsConnections,NS.ServersConnections,NS.BytesReceived DIV 1024,NS.BytesSend DIV 1024]);
- end else begin
- StatusBar.Panels[0].Text := '';
- StatusBar.Panels[1].Text := '';
- end;
- end;
- procedure TFRMWallet.OnNewAccount(Sender: TObject);
- begin
- Try
- UpdateAccounts(false);
- UpdateBlockChainState;
- Except
- On E:Exception do begin
- E.Message := 'Error at OnNewAccount '+E.Message;
- Raise;
- end;
- end;
- end;
- procedure TFRMWallet.OnNewLog(logtype: TLogType; Time : TDateTime; ThreadID : TThreadID; const sender,logtext: AnsiString);
- Var s : AnsiString;
- begin
- if (logtype=ltdebug) And (Not cbShowDebugLogs.Checked) then exit;
- if ThreadID=MainThreadID then s := ' MAIN:' else s:=' TID:';
- if MemoLogs.Lines.Count>300 then begin
- // Limit max lines in logs...
- memoLogs.Lines.BeginUpdate;
- try
- while memoLogs.Lines.Count>250 do memoLogs.Lines.Delete(0);
- finally
- memoLogs.Lines.EndUpdate;
- end;
- end;
- memoLogs.Lines.Add(formatDateTime('dd/mm/yyyy hh:nn:ss.zzz',Time)+s+IntToHex(PtrInt(ThreadID),8)+' ['+CT_LogType[Logtype]+'] <'+sender+'> '+logtext);
- //
- end;
- procedure TFRMWallet.OnNodeMessageEvent(NetConnection: TNetConnection; MessageData: TRawBytes);
- Var s : String;
- begin
- inc(FMessagesUnreadCount);
- if Assigned(NetConnection) then begin
- s := DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr;
- memoMessages.Lines.Add(DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr+' Length '+inttostr(Length(MessageData))+' bytes');
- memoMessages.Lines.Add('RECEIVED> '+MessageData);
- if FAppParams.ParamByName[CT_PARAM_ShowModalMessages].GetAsBoolean(false) then begin
- s := DateTimeToStr(now)+' Message from '+NetConnection.ClientRemoteAddr+#10+
- 'Length '+inttostr(length(MessageData))+' bytes'+#10+#10;
- if TCrypto.IsHumanReadable(MessageData) then begin
- s := s + MessageData;
- end else begin
- s := s +'Value in hexadecimal:'+#10+
- TCrypto.ToHexaString(MessageData);
- end;
- Application.MessageBox(PChar(s),PChar(Application.Title),MB_ICONINFORMATION+MB_OK);
- end;
- end else begin
- memoMessages.Lines.Add(DateTimeToStr(now)+' Internal message: '+MessageData);
- end;
- if FMessagesUnreadCount>1 then lblReceivedMessages.Caption := Format('You have received %d messages',[FMessagesUnreadCount])
- else lblReceivedMessages.Caption := 'You have received 1 message';
- lblReceivedMessages.Visible := true;
- end;
- procedure TFRMWallet.OnReceivedHelloMessage(Sender: TObject);
- Var nsarr : TNodeServerAddressArray;
- i : Integer;
- s : AnsiString;
- begin
- If (FLastNodesCacheUpdatedTS + EncodeTime(0,5,0,0) > Now) then exit; // Prevent continuous saving
- FLastNodesCacheUpdatedTS := Now;
- // Update node servers Peer Cache
- nsarr := TNetData.NetData.NodeServersAddresses.GetValidNodeServers(true,0);
- s := '';
- for i := low(nsarr) to High(nsarr) do begin
- if (s<>'') then s := s+';';
- s := s + nsarr[i].ip+':'+IntToStr( nsarr[i].port );
- end;
- FAppParams.ParamByName[CT_PARAM_PeerCache].SetAsString(s);
- TNode.Node.PeerCache := s;
- end;
- procedure TFRMWallet.OnSelectedAccountsGridUpdated(Sender: TObject);
- begin
- lblSelectedAccountsCount.Caption := Inttostr(FSelectedAccountsGrid.AccountsCount);
- lblSelectedAccountsBalance.Caption := TAccountComp.FormatMoney( FSelectedAccountsGrid.AccountsBalance );
- end;
- procedure TFRMWallet.OnWalletChanged(Sender: TObject);
- begin
- if FMustProcessWalletChanged then exit;
- FMustProcessWalletChanged := true;
- PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
- end;
- procedure TFRMWallet.PageControlChange(Sender: TObject);
- begin
- MiDecodePayload.Enabled := false;
- if PageControl.ActivePage=tsMyAccounts then begin
- //FAccountsGrid.Node := FNode;
- MiDecodePayload.Enabled := true;
- FSelectedAccountsGrid.Node := FNode;
- end else begin
- //FAccountsGrid.Node := Nil;
- FSelectedAccountsGrid.Node := Nil;
- end;
- if PageControl.ActivePage=tsPendingOperations then begin
- FPendingOperationsGrid.Node := FNode;
- MiDecodePayload.Enabled := true;
- end else FPendingOperationsGrid.Node := Nil;
- if PageControl.ActivePage=tsBlockChain then FBlockChainGrid.Node := FNode
- else FBlockChainGrid.Node := Nil;
- if PageControl.ActivePage=tsOperations then begin
- FOperationsExplorerGrid.Node := FNode;
- MiDecodePayload.Enabled := true;
- end else FOperationsExplorerGrid.Node := Nil;
- if PageControl.ActivePage=tsMessages then begin
- UpdateAvailableConnections;
- FMessagesUnreadCount := 0;
- lblReceivedMessages.Visible := false;
- end;
- end;
- procedure TFRMWallet.SaveAppParams;
- Var ms : TMemoryStream;
- s : AnsiString;
- begin
- ms := TMemoryStream.Create;
- Try
- FAccountsGrid.SaveToStream(ms);
- ms.Position := 0;
- setlength(s,ms.Size);
- ms.ReadBuffer(s[1],ms.Size);
- FAppParams.ParamByName[CT_PARAM_GridAccountsStream].SetAsString(s);
- Finally
- ms.Free;
- End;
- end;
- procedure TFRMWallet.sbSelectedAccountsAddAllClick(Sender: TObject);
- Var lsource,ltarget : TOrderedCardinalList;
- i : Integer;
- begin
- lsource := FAccountsGrid.LockAccountsList;
- Try
- ltarget := FSelectedAccountsGrid.LockAccountsList;
- Try
- for i := 0 to lsource.Count-1 do begin
- 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)]));
- ltarget.Add(lsource.Get(i));
- end;
- Finally
- FSelectedAccountsGrid.UnlockAccountsList;
- End;
- Finally
- FAccountsGrid.UnlockAccountsList;
- End;
- end;
- procedure TFRMWallet.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 FWalletKeys.IndexOfAccountKey(FNode.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 := FSelectedAccountsGrid.LockAccountsList;
- selected := TOrderedCardinalList.Create;
- Try
- FAccountsGrid.SelectedAccounts(selected);
- for i := 0 to selected.Count-1 do begin
- l.Add(selected.Get(i));
- end;
- Finally
- selected.Free;
- FSelectedAccountsGrid.UnlockAccountsList;
- End;
- end;
- procedure TFRMWallet.sbSelectedAccountsDelAllClick(Sender: TObject);
- Var l : TOrderedCardinalList;
- begin
- l := FSelectedAccountsGrid.LockAccountsList;
- try
- l.Clear;
- finally
- FSelectedAccountsGrid.UnlockAccountsList;
- end;
- end;
- procedure TFRMWallet.sbSelectedAccountsDelClick(Sender: TObject);
- Var an : Int64;
- l : TOrderedCardinalList;
- begin
- l := FSelectedAccountsGrid.LockAccountsList;
- try
- an := FSelectedAccountsGrid.AccountNumber(dgSelectedAccounts.Row);
- if an>=0 then l.Remove(an);
- finally
- FSelectedAccountsGrid.UnlockAccountsList;
- end;
- end;
- procedure TFRMWallet.SetMinersBlocksFound(const Value: Integer);
- begin
- FMinersBlocksFound := Value;
- lblBlocksFound.Caption := Inttostr(Value);
- if Value>0 then lblBlocksFound.Font.Color := clGreen
- else lblBlocksFound.Font.Color := clDkGray;
- end;
- procedure TFRMWallet.TimerUpdateStatusTimer(Sender: TObject);
- begin
- Try
- UpdateConnectionStatus;
- UpdateBlockChainState;
- UpdateNodeStatus;
- Except
- On E:Exception do begin
- E.Message := 'Exception at TimerUpdate '+E.ClassName+': '+E.Message;
- TLog.NewLog(lterror,ClassName,E.Message);
- end;
- End;
- end;
- procedure TFRMWallet.TrayIconDblClick(Sender: TObject);
- begin
- TrayIcon.Visible := False;
- TimerUpdateStatus.Enabled := true;
- Show();
- WindowState := wsNormal;
- Application.BringToFront();
- end;
- procedure TFRMWallet.UpdateAccounts(RefreshData : Boolean);
- Var accl : TOrderedCardinalList;
- l : TOrderedCardinalList;
- i,j,k : Integer;
- c : Cardinal;
- applyfilter : Boolean;
- acc : TAccount;
- 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 FWalletKeys.Count - 1 do begin
- j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[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 := FNode.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<FWalletKeys.Count) then begin
- j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[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 := FNode.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<FNode.Bank.SafeBox.AccountsCount) do begin
- acc := FNode.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(FNode.Bank.AccountsCount);
- end;
- bbChangeKeyName.Enabled := cbExploreMyAccounts.Checked;
- // Show Totals:
- lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
- UpdateOperations;
- end;
- procedure TFRMWallet.UpdateAvailableConnections;
- Var i : integer;
- NC : TNetConnection;
- l : TList;
- begin
- if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
- try
- lbNetConnections.Items.BeginUpdate;
- Try
- lbNetConnections.Items.Clear;
- for i := 0 to l.Count - 1 do begin
- NC := l[i];
- if NC.Connected then begin
- if NC is TNetServerClient then begin
- if Not NC.IsMyselfServer then begin
- lbNetConnections.Items.AddObject(Format('Client: IP:%s',[NC.ClientRemoteAddr]),NC);
- end;
- end else begin
- if Not NC.IsMyselfServer then begin
- lbNetConnections.Items.AddObject(Format('Server: IP:%s',[NC.ClientRemoteAddr]),NC);
- end;
- end;
- end;
- end;
- Finally
- lbNetConnections.Items.EndUpdate;
- End;
- finally
- TNetData.NetData.NetConnections.UnlockList;
- end;
- end;
- procedure TFRMWallet.UpdateBlockChainState;
- Var isMining : boolean;
- // hr : Int64;
- i,mc : Integer;
- s : String;
- mtl : TList;
- f, favg : real;
- begin
- UpdateNodeStatus;
- mc := 0;
- // hr := 0;
- if Assigned(FNode) then begin
- if FNode.Bank.BlocksCount>0 then begin
- lblCurrentBlock.Caption := Inttostr(FNode.Bank.BlocksCount)+' (0..'+Inttostr(FNode.Bank.BlocksCount-1)+')'; ;
- end else lblCurrentBlock.Caption := '(none)';
- lblCurrentAccounts.Caption := Inttostr(FNode.Bank.AccountsCount);
- lblCurrentBlockTime.Caption := UnixTimeToLocalElapsedTime(FNode.Bank.LastOperationBlock.timestamp);
- lblOperationsPending.Caption := Inttostr(FNode.Operations.Count);
- lblCurrentDifficulty.Caption := InttoHex(FNode.Operations.OperationBlock.compact_target,8);
- favg := FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage);
- f := (CT_NewLineSecondsAvg - favg) / CT_NewLineSecondsAvg;
- lblTimeAverage.Caption := 'Last '+Inttostr(CT_CalcNewTargetBlocksAverage)+': '+FormatFloat('0.0',favg)+' sec. (Optimal '+Inttostr(CT_NewLineSecondsAvg)+'s) Deviation '+FormatFloat('0.00%',f*100);
- if favg>=CT_NewLineSecondsAvg then begin
- lblTimeAverage.Font.Color := clNavy;
- end else begin
- lblTimeAverage.Font.Color := clOlive;
- end;
- lblTimeAverageAux.Caption := Format('Last %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec.',[
- CT_CalcNewTargetBlocksAverage * 2 ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage * 2)),
- ((CT_CalcNewTargetBlocksAverage * 3) DIV 2) ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage((CT_CalcNewTargetBlocksAverage * 3) DIV 2)),
- ((CT_CalcNewTargetBlocksAverage DIV 4)*3),FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(((CT_CalcNewTargetBlocksAverage DIV 4)*3))),
- CT_CalcNewTargetBlocksAverage DIV 2,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 2)),
- CT_CalcNewTargetBlocksAverage DIV 4,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 4))]);
- end else begin
- isMining := false;
- lblCurrentBlock.Caption := '';
- lblCurrentAccounts.Caption := '';
- lblCurrentBlockTime.Caption := '';
- lblOperationsPending.Caption := '';
- lblCurrentDifficulty.Caption := '';
- lblTimeAverage.Caption := '';
- lblTimeAverageAux.Caption := '';
- end;
- if (Assigned(FPoolMiningServer)) And (FPoolMiningServer.Active) then begin
- If FPoolMiningServer.ClientsCount>0 then begin
- lblMinersClients.Caption := IntToStr(FPoolMiningServer.ClientsCount)+' connected JSON-RPC clients';
- lblMinersClients.Font.Color := clNavy;
- end else begin
- lblMinersClients.Caption := 'No JSON-RPC clients';
- lblMinersClients.Font.Color := clDkGray;
- end;
- MinersBlocksFound := FPoolMiningServer.ClientsWins;
- end else begin
- MinersBlocksFound := 0;
- lblMinersClients.Caption := 'JSON-RPC server not active';
- lblMinersClients.Font.Color := clRed;
- end;
- end;
- procedure TFRMWallet.UpdateConfigChanged;
- Var wa : Boolean;
- i : Integer;
- begin
- tsLogs.TabVisible := FAppParams.ParamByName[CT_PARAM_ShowLogs].GetAsBoolean(false);
- if (Not tsLogs.TabVisible) then begin
- FLog.OnNewLog := Nil;
- if PageControl.ActivePage = tsLogs then PageControl.ActivePage := tsMyAccounts;
- end else FLog.OnNewLog := OnNewLog;
- if FAppParams.ParamByName[CT_PARAM_SaveLogFiles].GetAsBoolean(false) then begin
- if FAppParams.ParamByName[CT_PARAM_SaveDebugLogs].GetAsBoolean(false) then FLog.SaveTypes := CT_TLogTypes_ALL
- else FLog.SaveTypes := CT_TLogTypes_DEFAULT;
- FLog.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'PascalCointWallet.log';
- end else begin
- FLog.SaveTypes := [];
- FLog.FileName := '';
- end;
- if Assigned(FNode) then begin
- wa := FNode.NetServer.Active;
- FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
- FNode.NetServer.Active := wa;
- FNode.Operations.BlockPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
- FNode.NodeLogFilename := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'blocks.log';
- end;
- if Assigned(FPoolMiningServer) then begin
- if FPoolMiningServer.Port<>FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port) then begin
- FPoolMiningServer.Active := false;
- FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
- end;
- FPoolMiningServer.Active :=FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
- FPoolMiningServer.UpdateAccountAndPayload(GetAccountKeyForMiner,FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString(''));
- end;
- if Assigned(FRPCServer) then begin
- FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
- FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
- end;
- i := FAppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].GetAsInteger(Integer(mpk_Random));
- if (i>=Integer(Low(TMinerPrivatekey))) And (i<=Integer(High(TMinerPrivatekey))) then FMinerPrivateKeyType := TMinerPrivateKey(i)
- else FMinerPrivateKeyType := mpk_Random;
- end;
- procedure TFRMWallet.UpdateConnectionStatus;
- var errors : AnsiString;
- begin
- UpdateNodeStatus;
- OnNetStatisticsChanged(Nil);
- if Assigned(FNode) then begin
- if FNode.IsBlockChainValid(errors) then begin
- StatusBar.Panels[2].Text := Format('Last account time:%s',
- [FormatDateTime('dd/mm/yyyy hh:nn:ss',UnivDateTime2LocalDateTime(UnixToUnivDateTime( FNode.Bank.LastOperationBlock.timestamp )))]);
- end else begin
- StatusBar.Panels[2].Text := 'NO BLOCKCHAIN: '+errors;
- end;
- end else begin
- StatusBar.Panels[2].Text := '';
- end;
- end;
- procedure TFRMWallet.UpdateNodeStatus;
- Var status : AnsiString;
- begin
- If Not Assigned(FNode) then begin
- lblNodeStatus.Font.Color := clRed;
- lblNodeStatus.Caption := 'Initializing...';
- end else begin
- If FNode.IsReady(status) then begin
- if TNetData.NetData.NetStatistics.ActiveConnections>0 then begin
- lblNodeStatus.Font.Color := clGreen;
- if TNetData.NetData.IsDiscoveringServers then begin
- lblNodeStatus.Caption := 'Discovering servers';
- end else if TNetData.NetData.IsGettingNewBlockChainFromClient then begin
- lblNodeStatus.Caption := 'Obtaining new blockchain';
- end else begin
- lblNodeStatus.Caption := 'Running';
- end;
- end else begin
- lblNodeStatus.Font.Color := clRed;
- lblNodeStatus.Caption := 'Alone in the world...';
- end;
- end else begin
- lblNodeStatus.Font.Color := clRed;
- lblNodeStatus.Caption := status;
- end;
- end;
- If Assigned(FBackgroundPanel) then begin
- FBackgroundPanel.Font.Color:=lblNodeStatus.Font.Color;
- FBackgroundPanel.Caption:='Please wait until finished: '+lblNodeStatus.Caption;
- end;
- end;
- procedure TFRMWallet.UpdateOperations;
- Var accn : Int64;
- begin
- accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
- FOperationsAccountGrid.AccountNumber := accn;
- end;
- procedure TFRMWallet.UpdatePrivateKeys;
- Var i,last_i : Integer;
- wk : TWalletKey;
- s : AnsiString;
- begin
- If (Not Assigned(FOrderedAccountsKeyList)) And (Assigned(FNode)) Then begin
- FOrderedAccountsKeyList := TOrderedAccountKeysList.Create(FNode.Bank.SafeBox,false);
- end;
- 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 FWalletKeys.Count-1 do begin
- wk := FWalletKeys.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;
- end;
- initialization
- FRMWallet := Nil;
- end.
|