Skip to content

Commit c0f947d

Browse files
committed
Add SendContractTransaction method. Add copy account adress command.
1 parent dbca481 commit c0f947d

File tree

6 files changed

+120
-53
lines changed

6 files changed

+120
-53
lines changed

src/Stratis.DevEx.Ethereum/Network.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,18 @@ public static async Task<TransactionReceipt> DeployContract(string rpcurl, strin
4949
return await web3.Eth.DeployContract.SendRequestAndWaitForReceiptAsync(abi, bytecode, account, gasDeploy, values: values);
5050
}
5151

52-
public static async Task<string> CallContractAsync(string rpcurl, string contractAddress, string abi, string functionName, string fromAddress = null, HexBigInteger gas = null, HexBigInteger value = null, params object[] functionInput)
52+
public static async Task<string> CallContractAsync(string rpcurl, string contractAddress, string abi, string functionName, HexBigInteger gas = null, HexBigInteger value = null, params object[] functionInput)
5353
{
5454
var func = new Web3(rpcurl).Eth.GetContract(abi, contractAddress).GetFunction(functionName);
5555
return await func.CallAsync(func.CreateCallInput(functionInput));
5656
}
57-
57+
58+
public static async Task<string> SendContractTransactionAsync(string rpcurl, string contractAddress, string abi, string functionName, string fromAddress = null, HexBigInteger gas = null, HexBigInteger value = null, params object[] functionInput)
59+
{
60+
var func = new Web3(rpcurl).Eth.GetContract(abi, contractAddress).GetFunction(functionName);
61+
return await func.SendTransactionAsync(func.CreateTransactionInput(fromAddress, functionInput));
62+
}
63+
5864
public static async Task<string> GetProtocolVersion(string rpcurl) => await new Web3(rpcurl).Eth.ProtocolVersion.SendRequestAsync();
5965

6066
public static async Task<BigInteger> GetChainIdAsync(string rpcurl) => await new Web3(rpcurl).Eth.ChainId.SendRequestAsync();

src/Stratis.VS.StratisEVM/UI/BlockchainExplorer/BlockchainExplorerToolWindowControl.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
<CommandBinding Command="{x:Static stratisui:BlockchainExplorerTree.NewDeployProfileCmd}" Executed="NewDeployProfileCmd_Executed" />
5656
<CommandBinding Command="{x:Static stratisui:BlockchainExplorerTree.DeleteDeployProfileCmd}" Executed="DeleteDeployProfileCmd_Executed" />
5757
<CommandBinding Command="{x:Static stratisui:BlockchainExplorerTree.EditDeployProfileCmd}" Executed="EditDeployProfileCmd_Executed" />
58+
<CommandBinding Command="{x:Static stratisui:BlockchainExplorerTree.CopyAccountAddressCmd}" Executed="CopyAccountAddressCmd_Executed" />
5859
<CommandBinding Command="{x:Static stratisui:BlockchainExplorerTree.NewAccountCmd}" Executed="NewAccountCmd_Executed" />
5960
<CommandBinding Command="{x:Static stratisui:BlockchainExplorerTree.DeleteAccountCmd}" Executed="DeleteAccountCmd_Executed" />
6061
<CommandBinding Command="{x:Static stratisui:BlockchainExplorerTree.EditContractCmd}" Executed="EditContractCmd_Executed" />

src/Stratis.VS.StratisEVM/UI/BlockchainExplorer/BlockchainExplorerToolWindowControl.xaml.cs

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,13 @@ private void DeleteAccountCmd_Executed(object sender, ExecutedRoutedEventArgs e)
810810
tree.Refresh();
811811
}
812812

813+
private void CopyAccountAddressCmd_Executed(object sender, ExecutedRoutedEventArgs e)
814+
{
815+
var item = GetSelectedItem(sender);
816+
var address = item.Name;
817+
Clipboard.SetText(address);
818+
}
819+
813820
private async void EditContractCmd_Executed(object sender, ExecutedRoutedEventArgs e)
814821
{
815822
try
@@ -823,9 +830,9 @@ private async void EditContractCmd_Executed(object sender, ExecutedRoutedEventAr
823830
Title = "Edit contract " + item.DisplayName,
824831
Content = _sp,
825832
PrimaryButtonText = "Save",
826-
PrimaryButtonIcon = new SymbolIcon(SymbolRegular.Save20),
833+
PrimaryButtonIcon = new SymbolIcon(SymbolRegular.Save16),
827834
SecondaryButtonText = "Run",
828-
SecondaryButtonIcon = new SymbolIcon(SymbolRegular.Run24),
835+
SecondaryButtonIcon = new SymbolIcon(SymbolRegular.Run16),
829836
CloseButtonText = "Cancel",
830837
};
831838
var sp = (StackPanel)(_sp).Children[0];
@@ -842,34 +849,16 @@ private async void EditContractCmd_Executed(object sender, ExecutedRoutedEventAr
842849
creator.Text = (string)item.Data["Creator"];
843850
transactionHash.Text = (string)item.Data["TransactionHash"];
844851
deployedOn.Text = (string)item.Data["DeployedOn"];
845-
abi.Text = (string)item.Data["Abi"];
846-
847-
848-
852+
abi.Text = (string)item.Data["Abi"];
849853
var r = await dw.ShowAsync();
850854
if (r == ContentDialogResult.None)
851855
{
852856
return;
853857
}
854858
else if (r == ContentDialogResult.Secondary)
855859
{
856-
#pragma warning disable CS4014
857-
ThreadHelper.JoinableTaskFactory.RunAsync(async delegate
858-
{
859-
var w = await StratisEVMPackage.Instance.ShowToolWindowAsync(typeof(RunSmartContractToolWindow), 0, true, StratisEVMPackage.Instance.DisposalToken);
860-
if (w != null && w.Frame != null)
861-
{
862-
RunSmartContractToolWindowControl.instance.RunContract(item);
863-
}
864-
else
865-
{
866-
VSUtil.ShowModalErrorDialogBox("Could not launch Run Smart Contract tool window.", "Edit Contract error");
867-
}
868-
});
860+
BlockchainExplorerTree.RunContractCmd.Execute(null, tree);
869861
return;
870-
871-
#pragma warning restore CS4014
872-
873862
}
874863
//item.Data["Label"] = label.Text;
875864
//item.Data["Abi"] = abi.Text;
@@ -911,7 +900,8 @@ private async void RunContractCmd_Executed(object sender, ExecutedRoutedEventArg
911900

912901
var transactCheckBox = (CheckBox)((_sp).Children[0]);
913902
var transactPanel = (StackPanel)((_sp).Children[1]);
914-
var runAddressTextBox = (Wpc.TextBox)((StackPanel)(transactPanel).Children[0]).Children[1];
903+
var fromAddressTextBox = (Wpc.TextBox)((StackPanel)(transactPanel).Children[0]).Children[1];
904+
fromAddressTextBox.Text = (string)item.Data["Address"];
915905
transactCheckBox.Checked += (s, ev) =>
916906
{
917907
transactPanel.IsEnabled = true;
@@ -922,7 +912,7 @@ private async void RunContractCmd_Executed(object sender, ExecutedRoutedEventArg
922912
};
923913
var formPanel = (StackPanel)(_sp).Children[2];
924914
var statusPanel = ((StackPanel)(_sp).Children[3]);
925-
await CreateRunContractFormAsync(formPanel, statusPanel, item.Data);
915+
await CreateRunContractFormAsync(formPanel, statusPanel, item.Data, transactCheckBox, fromAddressTextBox.Text);
926916
dw.ButtonClicked += (cd, args) => { };
927917
dw.Closing += (d, args) => { };
928918
await dw.ShowAsync();
@@ -986,7 +976,7 @@ private void ShowValidationSuccess(StackPanel successPanel, Wpc.TextBlock succes
986976

987977
private void HideValidationSuccess(StackPanel successPanel) => successPanel.Visibility = Visibility.Hidden;
988978

989-
private async Task CreateRunContractFormAsync(StackPanel form, StackPanel statusPanel, Dictionary<string, object> contractData)
979+
private async Task CreateRunContractFormAsync(StackPanel form, StackPanel statusPanel, Dictionary<string, object> contractData, CheckBox transactCheckBox, string fromAddress)
990980
{
991981
form.Children.Clear();
992982
var errors = (Wpc.TextBlock)((Grid)statusPanel.Children[0]).Children[0];
@@ -1026,6 +1016,8 @@ private async Task CreateRunContractFormAsync(StackPanel form, StackPanel status
10261016
ShowValidationErrors(errors, $"Could not retrieve balance for contract. {balr.FailureMessage}");
10271017
return;
10281018
}
1019+
1020+
10291021

10301022
foreach (var function in _abi.Functions)
10311023
{
@@ -1036,21 +1028,21 @@ private async Task CreateRunContractFormAsync(StackPanel form, StackPanel status
10361028
vsp.Children.Add(new Separator()
10371029
{
10381030
Margin = new Thickness(0, 8, 0, 8),
1039-
Background = System.Windows.Media.Brushes.LightGray,
10401031
Height = 1
10411032
});
10421033

10431034
var button = new Wpc.Button()
10441035
{
10451036
Name = function.Name + "_Button",
10461037
Content = function.Name,
1047-
Width=75.0,
1038+
Width=125.0,
10481039
Foreground = System.Windows.Media.Brushes.White,
10491040
Background = System.Windows.Media.Brushes.DodgerBlue,
10501041
Icon = new SymbolIcon(SymbolRegular.Play12),
10511042
VerticalAlignment = VerticalAlignment.Center,
1052-
HorizontalAlignment = HorizontalAlignment.Left,
1053-
FontSize =9.0
1043+
HorizontalAlignment = HorizontalAlignment.Right,
1044+
FontSize =11.0,
1045+
Margin = new Thickness(0,4,0,0)
10541046
};
10551047

10561048
if (function.InputParameters != null && function.InputParameters.Count() > 0)
@@ -1062,60 +1054,94 @@ private async Task CreateRunContractFormAsync(StackPanel form, StackPanel status
10621054
Orientation = Orientation.Horizontal,
10631055
VerticalAlignment = VerticalAlignment.Top,
10641056
HorizontalAlignment = HorizontalAlignment.Left,
1065-
Margin = new Thickness(4, 0, 0, 2)
1057+
Margin = new Thickness(4, 4, 0, 2)
10661058
};
10671059
var lbl = new Wpc.TextBlock { Width = 100, VerticalAlignment = VerticalAlignment.Bottom};
1068-
lbl.Inlines.Add(new Run() { Text = p.Name, FontSize=11.0 });
1069-
lbl.Inlines.Add(new Run() { Text = $" ({p.Type}): ", FontSize=11.0, FontStyle = FontStyles.Italic});
1060+
lbl.Inlines.Add(new Run() { Text = p.Name });
1061+
lbl.Inlines.Add(new Run() { Text = $" ({p.Type}): ", FontStyle = FontStyles.Italic, FontSize=9.0});
10701062
var tb = new Wpc.TextBox() { Name = $"Param{p.Name}TextBox", Width = 150, VerticalAlignment = VerticalAlignment.Bottom};
10711063
sp.Children.Add(lbl);
10721064
sp.Children.Add(tb);
10731065
vsp.Children.Add(sp);
10741066
}
1075-
1067+
10761068
button.Click += (s, e) =>
10771069
{
10781070
var paramVals = GetContractFunctionParams(vsp, function.InputParameters.ToDictionary(ip => ip.Name, ip => ip.Type));
10791071
if (paramVals.Length != function.InputParameters.Count())
10801072
{
10811073
ShowValidationErrors(errors, $"The {function.Name} function requires {function.InputParameters.Count()} parameters.");
1074+
VSUtil.LogToStratisEVMWindow($"\n========== Call contract {address} at {rpcurl} failed.==========\nThe {function.Name} function requires {function.InputParameters.Count()} parameters.");
10821075
return;
10831076
}
1084-
ShowProgressRing(progressring);
1085-
var r = ThreadHelper.JoinableTaskFactory.Run(() => ExecuteAsync(Network.CallContractAsync(rpcurl, address, abi, function.Name, functionInput: paramVals)));
1077+
1078+
ShowProgressRing(progressring);
1079+
Result<string> r;
1080+
1081+
if (transactCheckBox.IsChecked ?? false)
1082+
{
1083+
1084+
if (string.IsNullOrEmpty(fromAddress))
1085+
{
1086+
HideProgressRing(progressring);
1087+
ShowValidationErrors(errors, "Enter a valid from address to send the transaction from.");
1088+
return;
1089+
}
1090+
r = ThreadHelper.JoinableTaskFactory.Run(() => ExecuteAsync(Network.SendContractTransactionAsync(rpcurl, address, abi, function.Name, fromAddress, functionInput: paramVals)));
1091+
}
1092+
else
1093+
{
1094+
r = ThreadHelper.JoinableTaskFactory.Run(() => ExecuteAsync(Network.CallContractAsync(rpcurl, address, abi, function.Name, functionInput: paramVals)));
1095+
}
10861096
HideProgressRing(progressring);
1097+
string desc = (transactCheckBox.IsChecked == null || transactCheckBox.IsChecked == false) ? "call" : "transaction";
10871098
if (r.IsSuccess)
10881099
{
10891100
HideValidationErrors(errors);
1090-
ShowValidationSuccess(successPanel, successTextBlock, $"Call function {function.Name}({paramVals.Cast<string>().JoinWith(",")}) returned: {r.Value}");
1091-
VSUtil.LogToStratisEVMWindow($"[call] {address +":" + function.Name}({function.InputParameters.Select((p,i) =>p.Type + " " + p.Name + ":" +paramVals.ElementAt(i)).JoinWith(", ")}): {r.Value}");
1101+
ShowValidationSuccess(successPanel, successTextBlock, $"Function {function.Name}({paramVals.Select(v => v.ToString()).JoinWith(",")}) returned: {r.Value}");
1102+
VSUtil.LogToStratisEVMWindow($"\n========== Call contract {address} at {rpcurl} succeeded.==========\n[{desc}] {address +":" + function.Name}({function.InputParameters.Select((p,i) =>p.Type + " " + p.Name + ":" +paramVals.ElementAt(i)).JoinWith(", ")}): {r.Value}");
10921103
}
10931104
else
10941105
{
10951106
HideValidationSuccess(successPanel);
1096-
ShowValidationErrors(errors, $"Error calling function {function.Name}({paramVals.Cast<string>().JoinWith(",")}): {r.FailureMessage}");
1107+
ShowValidationErrors(errors, $"Error calling function {function.Name}({paramVals.Select(v => v.ToString()).JoinWith(",")}): {r.FailureMessage}");
1108+
VSUtil.LogToStratisEVMWindow($"\n========== Call contract {address} at {rpcurl} failed.==========\n[{desc}] {address + ":" + function.Name}({function.InputParameters.Select((p, i) => p.Type + " " + p.Name + ":" + paramVals.ElementAt(i)).JoinWith(", ")}): {r.FailureMessage}");
10971109
}
10981110
};
10991111
}
11001112
else
11011113
{
11021114
button.Click += (s, e) =>
1103-
{
1104-
1115+
{
11051116
ShowProgressRing(progressring);
1106-
var r = ThreadHelper.JoinableTaskFactory.Run(() => ExecuteAsync(Network.CallContractAsync(rpcurl, address, abi, function.Name)));
1117+
Result<string> r;
1118+
if (transactCheckBox.IsChecked ?? false)
1119+
{
1120+
if (string.IsNullOrEmpty(fromAddress))
1121+
{
1122+
HideProgressRing(progressring);
1123+
ShowValidationErrors(errors, "Enter a valid from address to send the transaction from.");
1124+
return;
1125+
}
1126+
r = ThreadHelper.JoinableTaskFactory.Run(() => ExecuteAsync(Network.SendContractTransactionAsync(rpcurl, address, abi, function.Name, fromAddress)));
1127+
}
1128+
else
1129+
{
1130+
r = ThreadHelper.JoinableTaskFactory.Run(() => ExecuteAsync(Network.CallContractAsync(rpcurl, address, abi, function.Name)));
1131+
}
11071132
HideProgressRing(progressring);
1133+
string desc = (transactCheckBox.IsChecked == null || transactCheckBox.IsChecked == false) ? "call" : "transaction";
11081134
if (r.IsSuccess)
11091135
{
1110-
HideValidationErrors(errors);
1111-
1112-
ShowValidationSuccess(successPanel, successTextBlock, $"Function {function.Name} result: {r.Value}");
1113-
VSUtil.LogToStratisEVMWindow($"[call] {function.Name}: {r.Value}");
1136+
HideValidationErrors(errors);
1137+
ShowValidationSuccess(successPanel, successTextBlock, $"Function {function.Name} returned: {r.Value}");
1138+
VSUtil.LogToStratisEVMWindow($"\n========== Call contract {address} at {rpcurl} succeeded.==========\n[{desc}] {address + ":" + function.Name}: {r.Value}");
11141139
}
11151140
else
11161141
{
11171142
HideValidationSuccess(successPanel);
1118-
ShowValidationErrors(errors, $"Error calling contract function: {r.FailureMessage}");
1143+
ShowValidationErrors(errors, $"Error calling function: {r.FailureMessage}");
1144+
VSUtil.LogToStratisEVMWindow($"\n========== Call contract {address} at {rpcurl} failed.==========\n[{desc}] {address + ":" + function.Name}: {r.FailureMessage}");
11191145
}
11201146

11211147
};
@@ -1128,7 +1154,6 @@ private async Task CreateRunContractFormAsync(StackPanel form, StackPanel status
11281154
private object[] GetContractFunctionParams(StackPanel form, Dictionary<string, string> paramTypes)
11291155
{
11301156
Dictionary<string, (string, string)> paramValues = new Dictionary<string, (string, string)>();
1131-
//List<object> paramValues = new List<object>();
11321157
foreach (var child in form.Children)
11331158
{
11341159
if (child is StackPanel sp && sp.Children.Count == 2 && sp.Children[0] is Wpc.TextBlock lbl && sp.Children[1] is Wpc.TextBox tb)
@@ -1151,6 +1176,8 @@ private object[] GetContractFunctionParams(StackPanel form, Dictionary<string, s
11511176
#region Fields
11521177
internal BlockchainExplorerToolWindow window;
11531178
internal static BlockchainExplorerToolWindowControl instance;
1154-
#endregion
1179+
#endregion
1180+
1181+
11551182
}
11561183
}

src/Stratis.VS.StratisEVM/UI/BlockchainExplorer/BlockchainExplorerTree.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public class BlockchainExplorerTree : TreeViewBase<BlockchainInfo>
4141

4242
public static RoutedCommand DeleteAccountCmd { get; } = new RoutedCommand();
4343

44+
public static RoutedCommand CopyAccountAddressCmd { get; } = new RoutedCommand();
45+
4446
public static RoutedCommand EditContractCmd { get; } = new RoutedCommand();
4547

4648
public static RoutedCommand NewContractCmd { get; } = new RoutedCommand();

0 commit comments

Comments
 (0)