Browse Source

more work on the SendPASC Wizard.

Ugochukwu Mmaduekwe 7 years ago
parent
commit
5a3a082446

+ 392 - 23
src/gui/wizards/UWIZSendPASC.pas

@@ -14,41 +14,402 @@ unit UWIZSendPASC;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, Forms, UWizard, UAccounts;
+  Classes, SysUtils, Forms, Dialogs, UCrypto, UWizard, UAccounts, LCLType;
 
 
 type
 type
 
 
   { TWIZSendPASCModel }
   { TWIZSendPASCModel }
+  TWIZPayloadEncryptionMode = (akaEncryptWithOldEC, akaEncryptWithEC,
+    akaEncryptWithPassword, akaNotEncrypt);
 
 
   TWIZSendPASCModel = class(TComponent)
   TWIZSendPASCModel = class(TComponent)
-    public
-      SelectedIndex: Integer;
-      SelectedAccounts: TArray<TAccount>;
-      SignerAccount, DestinationAccount: TAccount;
-      AmountToSend: String;
-      DefaultFee: Int64;
+  public
+    SelectedIndex: integer;
+    DefaultFee: int64;
+    AmountToSend, Payload, EncryptionPassword: string;
+    EncodedPayload: TRawBytes;
+    SignerAccount, DestinationAccount: TAccount;
+    SelectedAccounts: TArray<TAccount>;
+    PayloadEncryptionMode: TWIZPayloadEncryptionMode;
   end;
   end;
 
 
   { TWIZSendPASCWizard }
   { TWIZSendPASCWizard }
 
 
   TWIZSendPASCWizard = class(TWizard<TWIZSendPASCModel>)
   TWIZSendPASCWizard = class(TWizard<TWIZSendPASCModel>)
-    public
-      constructor Create(AOwner: TComponent); override;
-      function DetermineHasNext : boolean; override;
-      function DetermineHasPrevious : boolean;  override;
-      function FinishRequested(out message : AnsiString) : boolean; override;
-      function CancelRequested(out message : AnsiString) : boolean; override;
+  private
+    function UpdatePayload(const SenderAccount: TAccount;
+      var errors: string): boolean;
+    function UpdateOperationOptions(var errors: string): boolean;
+    function UpdateOpTransaction(const SenderAccount: TAccount;
+      var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
+    procedure SendPASC();
+  public
+    constructor Create(AOwner: TComponent); override;
+    function DetermineHasNext: boolean; override;
+    function DetermineHasPrevious: boolean; override;
+    function FinishRequested(out message: ansistring): boolean; override;
+    function CancelRequested(out message: ansistring): boolean; override;
   end;
   end;
 
 
 implementation
 implementation
 
 
 uses
 uses
-  UCrypto,
+  UBlockChain,
+  UOpTransaction,
+  UNode,
+  UConst,
   UWallet,
   UWallet,
+  UECIES,
+  UAES,
   UWIZSendPASC_Start,
   UWIZSendPASC_Start,
   UWIZSendPASC_Transaction,
   UWIZSendPASC_Transaction,
   UWIZSendPASC_Confirmation;
   UWIZSendPASC_Confirmation;
-  //UWIZSendPASC_Completion;
+
+{ TWIZSendPASCWizard }
+
+function TWIZSendPASCWizard.UpdateOperationOptions(var errors: string): boolean;
+var
+  iAcc, iWallet: integer;
+  sender_account, dest_account: TAccount;
+  wk: TWalletKey;
+  e: string;
+  amount: int64;
+begin
+  Result := False;
+  errors := '';
+  if not Assigned(TWallet.Keys) then
+  begin
+    errors := 'No wallet keys';
+    Exit;
+  end;
+
+  if Length(Model.SelectedAccounts) = 0 then
+  begin
+    errors := 'No sender account';
+    Exit;
+  end
+  else
+  begin
+
+    for iAcc := Low(Model.SelectedAccounts) to High(Model.SelectedAccounts) do
+    begin
+      sender_account := Model.SelectedAccounts[iAcc];
+      iWallet := TWallet.Keys.IndexOfAccountKey(sender_account.accountInfo.accountKey);
+      if (iWallet < 0) then
+      begin
+        errors := 'Private key of account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
+          ' not found in wallet';
+        Exit;
+      end;
+      wk := TWallet.Keys.Key[iWallet];
+      if not assigned(wk.PrivateKey) then
+      begin
+        if wk.CryptedKey <> '' then
+        begin
+          // TODO: handle unlocking of encrypted wallet here
+          errors := 'Wallet is password protected. Need password';
+        end
+        else
+        begin
+          errors := 'Only public key of account ' +
+            TAccountComp.AccountNumberToAccountTxtNumber(sender_account.account) +
+            ' found in wallet. You cannot operate with this account';
+        end;
+        Exit;
+      end;
+    end;
+  end;
+
+  Result := UpdateOpTransaction(Model.SelectedAccounts[0], dest_account, amount, errors);
+  UpdatePayload(sender_account, e);
+end;
+
+function TWIZSendPASCWizard.UpdateOpTransaction(const SenderAccount: TAccount;
+  var DestAccount: TAccount; var amount: int64; var errors: string): boolean;
+var
+  c: cardinal;
+begin
+  Result := False;
+  errors := '';
+
+  DestAccount := Model.DestinationAccount;
+
+  if Length(Model.SelectedAccounts) = 1 then
+  begin
+    if not TAccountComp.TxtToMoney(Model.AmountToSend, amount) then
+    begin
+      errors := 'Invalid amount (' + Model.AmountToSend + ')';
+      Exit;
+    end;
+  end
+  else
+  begin
+    amount := 0; // ALL BALANCE
+  end;
+
+  if DestAccount.account = SenderAccount.account then
+  begin
+    errors := 'Sender and dest account are the same';
+    Exit;
+  end;
+
+  if (Length(Model.SelectedAccounts) = 1) then
+  begin
+    if (SenderAccount.balance < (amount + Model.DefaultFee)) then
+    begin
+      errors := 'Insufficient funds';
+      Exit;
+    end;
+  end;
+  Result := True;
+end;
+
+procedure TWIZSendPASCWizard.SendPASC();
+var
+  _V2, dooperation: boolean;
+  iAcc, i: integer;
+  _totalamount, _totalfee, _totalSignerFee, _amount, _fee: int64;
+  _signer_n_ops: cardinal;
+  operationstxt, operation_to_string, errors, auxs: string;
+  wk: TWalletKey;
+  ops: TOperationsHashTree;
+  op: TPCOperation;
+  account, destAccount: TAccount;
+begin
+  if not Assigned(TWallet.Keys) then
+    raise Exception.Create('No wallet keys');
+  if not UpdateOperationOptions(errors) then
+    raise Exception.Create(errors);
+  ops := TOperationsHashTree.Create;
+  try
+    _V2 := TNode.Node.Bank.SafeBox.CurrentProtocol >= CT_PROTOCOL_2;
+    _totalamount := 0;
+    _totalfee := 0;
+    _totalSignerFee := 0;
+    _signer_n_ops := 0;
+    operationstxt := '';
+    operation_to_string := '';
+    for iAcc := Low(Model.SelectedAccounts) to High(Model.SelectedAccounts) do
+    begin
+      op := nil;
+      account := Model.SelectedAccounts[iAcc];
+      if not UpdatePayload(account, errors) then
+      begin
+        raise Exception.Create('Error encoding payload of sender account ' +
+          TAccountComp.AccountNumberToAccountTxtNumber(account.account) + ': ' + errors);
+      end;
+      i := TWallet.Keys.IndexOfAccountKey(account.accountInfo.accountKey);
+      if i < 0 then
+      begin
+        raise Exception.Create('Sender account private key not found in Wallet');
+      end;
+
+      wk := TWallet.Keys.Key[i];
+      dooperation := True;
+      // Default fee
+      if account.balance > uint64(Model.DefaultFee) then
+        _fee := Model.DefaultFee
+      else
+        _fee := account.balance;
+
+      if not UpdateOpTransaction(account, destAccount, _amount, errors) then
+        raise Exception.Create(errors);
+      if Length(Model.SelectedAccounts) > 1 then
+      begin
+        if account.balance > 0 then
+        begin
+          if account.balance > Model.DefaultFee then
+          begin
+            _amount := account.balance - Model.DefaultFee;
+            _fee := Model.DefaultFee;
+          end
+          else
+          begin
+            _amount := account.balance;
+            _fee := 0;
+          end;
+        end
+        else
+          dooperation := False;
+      end
+      else
+      begin
+      end;
+      if dooperation then
+      begin
+        op := TOpTransaction.CreateTransaction(
+          account.account, account.n_operation + 1, destAccount.account,
+          wk.PrivateKey, _amount, _fee, Model.EncodedPayload);
+        Inc(_totalamount, _amount);
+        Inc(_totalfee, _fee);
+      end;
+      operationstxt := 'Transaction to ' + TAccountComp.AccountNumberToAccountTxtNumber(
+        destAccount.account);
+
+      if Assigned(op) and (dooperation) then
+      begin
+        ops.AddOperationToHashTree(op);
+        if operation_to_string <> '' then
+          operation_to_string := operation_to_string + #10;
+        operation_to_string := operation_to_string + op.ToString;
+      end;
+      FreeAndNil(op);
+    end;
+
+    if (ops.OperationsCount = 0) then
+      raise Exception.Create('No valid operation to execute');
+
+    if (Length(Model.SelectedAccounts) > 1) then
+    begin
+      auxs := 'Total amount that dest will receive: ' + TAccountComp.FormatMoney(
+        _totalamount) + #10;
+      if Application.MessageBox(
+        PChar('Execute ' + IntToStr(Length(Model.SelectedAccounts)) +
+        ' operations?' + #10 + 'Operation: ' + operationstxt + #10 +
+        auxs + 'Total fee: ' + TAccountComp.FormatMoney(_totalfee) +
+        #10 + #10 + 'Note: This operation will be transmitted to the network!'),
+        PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
+        idYes then
+      begin
+        Exit;
+      end;
+    end
+    else
+    begin
+      if Application.MessageBox(PChar('Execute this operation:' +
+        #10 + #10 + operation_to_string + #10 + #10 +
+        'Note: This operation will be transmitted to the network!'),
+        PChar(Application.Title), MB_YESNO + MB_ICONINFORMATION + MB_DEFBUTTON2) <>
+        idYes then
+      begin
+        Exit;
+      end;
+    end;
+    i := TNode.Node.AddOperations(nil, ops, nil, errors);
+    if (i = ops.OperationsCount) then
+    begin
+      operationstxt := 'Successfully executed ' + IntToStr(i) +
+        ' operations!' + #10 + #10 + operation_to_string;
+      if i > 1 then
+      begin
+        //  with TFRMMemoText.Create(Self) do
+        //    try
+        //      InitData(Application.Title, operationstxt);
+        //      ShowModal;
+        //    finally
+        //      Free;
+        //    end;
+        ShowMessage(operationstxt);
+      end
+      else
+      begin
+        Application.MessageBox(
+          PChar('Successfully executed ' + IntToStr(i) + ' operations!' +
+          #10 + #10 + operation_to_string),
+          PChar(Application.Title), MB_OK + MB_ICONINFORMATION);
+      end;
+      // ModalResult := mrOk;
+    end
+    else if (i > 0) then
+    begin
+      operationstxt := 'One or more of your operations has not been executed:' +
+        #10 + 'Errors:' + #10 + errors + #10 + #10 +
+        'Total successfully executed operations: ' + IntToStr(i);
+      //with TFRMMemoText.Create(Self) do
+      //  try
+      //    InitData(Application.Title, operationstxt);
+      //    ShowModal;
+      //  finally
+      //    Free;
+      //  end;
+      //ModalResult := mrOk;
+      ShowMessage(operationstxt);
+    end
+    else
+    begin
+      raise Exception.Create(errors);
+    end;
+
+  finally
+    ops.Free;
+  end;
+end;
+
+function TWIZSendPASCWizard.UpdatePayload(const SenderAccount: TAccount;
+  var errors: string): boolean;
+var
+  valid: boolean;
+  payload_encrypted, payload_u: string;
+  account: TAccount;
+begin
+  valid := False;
+  payload_encrypted := '';
+  Model.EncodedPayload := '';
+  errors := 'Unknown error';
+  payload_u := Model.Payload;
+
+  try
+    if (payload_u = '') then
+    begin
+      valid := True;
+      Exit;
+    end;
+    case Model.PayloadEncryptionMode of
+
+      akaEncryptWithOldEC:
+      begin
+        // Use sender
+        errors := 'Error encrypting';
+        account := SenderAccount;
+        payload_encrypted := ECIESEncrypt(account.accountInfo.accountKey, payload_u);
+        valid := payload_encrypted <> '';
+      end;
+
+      akaEncryptWithEC:
+      begin
+        // With dest public key
+        errors := 'Error encrypting';
+        account := Model.DestinationAccount;
+        payload_encrypted := ECIESEncrypt(account.accountInfo.accountKey, payload_u);
+        valid := payload_encrypted <> '';
+      end;
+
+      akaEncryptWithPassword:
+      begin
+        payload_encrypted := TAESComp.EVP_Encrypt_AES256(
+          payload_u, Model.EncryptionPassword);
+        valid := payload_encrypted <> '';
+      end;
+
+      akaNotEncrypt:
+      begin
+        payload_encrypted := payload_u;
+        valid := True;
+      end
+
+      else
+      begin
+        raise Exception.Create('Invalid Encryption Selection');
+      end;
+    end;
+
+  finally
+    if valid then
+    begin
+      if length(payload_encrypted) > CT_MaxPayloadSize then
+      begin
+        valid := False;
+        errors := 'Payload size is bigger than ' + IntToStr(CT_MaxPayloadSize) +
+          ' (' + IntToStr(length(payload_encrypted)) + ')';
+      end;
+
+    end;
+    Model.EncodedPayload := payload_encrypted;
+    Result := valid;
+  end;
+
+end;
 
 
 constructor TWIZSendPASCWizard.Create(AOwner: TComponent);
 constructor TWIZSendPASCWizard.Create(AOwner: TComponent);
 begin
 begin
@@ -57,26 +418,34 @@ begin
   FinishText := 'Send PASC';
   FinishText := 'Send PASC';
 end;
 end;
 
 
-function TWIZSendPASCWizard.DetermineHasNext : boolean;
+function TWIZSendPASCWizard.DetermineHasNext: boolean;
 begin
 begin
-  Result := NOT (CurrentScreen is TWIZSendPASC_Confirmation);
+  Result := not (CurrentScreen is TWIZSendPASC_Confirmation);
 end;
 end;
 
 
-function TWIZSendPASCWizard.DetermineHasPrevious : boolean;
+function TWIZSendPASCWizard.DetermineHasPrevious: boolean;
 begin
 begin
   Result := inherited DetermineHasPrevious;
   Result := inherited DetermineHasPrevious;
 end;
 end;
 
 
-function TWIZSendPASCWizard.FinishRequested(out message : AnsiString) : boolean;
+function TWIZSendPASCWizard.FinishRequested(out message: ansistring): boolean;
 begin
 begin
   // Execute the PASC Sending here
   // Execute the PASC Sending here
-    raise ENotImplemented.Create('Operation Not Yet Implemented');
+  try
+    Result := True;
+    SendPASC();
+  except
+    On E: Exception do
+    begin
+      Result := False;
+      message := E.ToString;
+    end;
+  end;
 end;
 end;
 
 
-function TWIZSendPASCWizard.CancelRequested(out message : AnsiString) : boolean;
+function TWIZSendPASCWizard.CancelRequested(out message: ansistring): boolean;
 begin
 begin
-  Result := true;
+  Result := True;
 end;
 end;
 
 
 end.
 end.
-

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

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

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

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

+ 14 - 12
src/gui/wizards/UWIZSendPASC_Transaction.pas

@@ -14,7 +14,8 @@ interface
 uses
 uses
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
   ExtCtrls, Buttons, UCommon, UCommon.Collections, UWallet,
-  UFRMAccountSelect, UNode, UWizard, UWIZSendPASC, UWIZSendPASC_Confirmation;
+  UFRMAccountSelect, UNode, UWizard, UWIZSendPASC, UWIZSendPASC_TransactionPayload,
+  UWIZSendPASC_Confirmation;
 
 
 type
 type
 
 
@@ -36,6 +37,7 @@ type
     procedure btnSearchClick(Sender: TObject);
     procedure btnSearchClick(Sender: TObject);
     procedure cbSignerAccountChange(Sender: TObject);
     procedure cbSignerAccountChange(Sender: TObject);
 
 
+
   public
   public
     procedure OnPresent; override;
     procedure OnPresent; override;
     procedure OnNext; override;
     procedure OnNext; override;
@@ -175,6 +177,8 @@ begin
     cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
     cbSignerAccount.Items.Objects[cbSignerAccount.ItemIndex])];
   Model.DestinationAccount := GetAccounts(GetAccNoWithoutChecksum(edtDestAcc.Text));
   Model.DestinationAccount := GetAccounts(GetAccNoWithoutChecksum(edtDestAcc.Text));
   Model.AmountToSend := edtAmt.Text;
   Model.AmountToSend := edtAmt.Text;
+  UpdatePath(ptReplaceAllNext, [TWIZSendPASC_TransactionPayload,
+    TWIZSendPASC_Confirmation]);
 end;
 end;
 
 
 function TWIZSendPASC_Transaction.Validate(out message: ansistring): boolean;
 function TWIZSendPASC_Transaction.Validate(out message: ansistring): boolean;
@@ -188,7 +192,6 @@ var
   AccountNumbersWithChecksum: TArray<string>;
   AccountNumbersWithChecksum: TArray<string>;
   Accounts: TArray<TAccount>;
   Accounts: TArray<TAccount>;
   c: cardinal;
   c: cardinal;
-  DestAccount: TAccount;
   amount, opfee: int64;
   amount, opfee: int64;
   i: integer;
   i: integer;
 begin
 begin
@@ -216,7 +219,6 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  DestAccount := TNode.Node.Operations.SafeBoxTransaction.account(c);
   if Length(Accounts) = 1 then
   if Length(Accounts) = 1 then
   begin
   begin
     if not TAccountComp.TxtToMoney(edtAmt.Text, amount) then
     if not TAccountComp.TxtToMoney(edtAmt.Text, amount) then
@@ -244,15 +246,15 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
-  //for i := Low(Accounts) to High(Accounts) do
-  //begin
-  //  if (Accounts[i].balance < (amount + opfee)) then
-  //  begin
-  //    message := 'Insufficient funds';
-  //    Result := False;
-  //    Exit;
-  //  end;
-  //end;
+  if Length(Accounts) = 1 then
+  begin
+    if (Accounts[0].balance < (amount + Model.DefaultFee)) then
+    begin
+      message := 'Insufficient funds';
+      Result := False;
+      Exit;
+    end;
+  end;
 
 
 end;
 end;
 
 

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

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

+ 84 - 0
src/gui/wizards/UWIZSendPASC_TransactionPayload.pas

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

+ 12 - 1
src/pascalcoin_wallet.lpi

@@ -33,7 +33,7 @@
         <PackageName Value="LCL"/>
         <PackageName Value="LCL"/>
       </Item1>
       </Item1>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="74">
+    <Units Count="76">
       <Unit0>
       <Unit0>
         <Filename Value="pascalcoin_wallet.dpr"/>
         <Filename Value="pascalcoin_wallet.dpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -416,6 +416,17 @@
         <Filename Value="core\UCore.pas"/>
         <Filename Value="core\UCore.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit73>
       </Unit73>
+      <Unit74>
+        <Filename Value="gui\wizards\UWIZSendPASC_TransactionPayload.lfm"/>
+        <IsPartOfProject Value="True"/>
+      </Unit74>
+      <Unit75>
+        <Filename Value="gui\wizards\UWIZSendPASC_TransactionPayload.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="WIZSendPASC_TransactionPayload"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit75>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>