From 5d45cb113fdcedf46d3bc129095e135e4996f5d7 Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Wed, 12 Jul 2017 22:30:57 +0900 Subject: [PATCH] Create model binders for the RPC controller --- Stratis.Bitcoin.IntegrationTests/Program.cs | 2 +- .../WalletTests.cs | 15 +++++ .../ModelBinders/DestinationModelBinder.cs | 65 +++++++++++++++++++ .../RPC/ModelBinders/MoneyModelBinder.cs | 43 ++++++++++++ Stratis.Bitcoin/RPC/WebHostExtensions.cs | 6 ++ 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 Stratis.Bitcoin/RPC/ModelBinders/DestinationModelBinder.cs create mode 100644 Stratis.Bitcoin/RPC/ModelBinders/MoneyModelBinder.cs diff --git a/Stratis.Bitcoin.IntegrationTests/Program.cs b/Stratis.Bitcoin.IntegrationTests/Program.cs index 82a2095ee3f..79b05d84008 100644 --- a/Stratis.Bitcoin.IntegrationTests/Program.cs +++ b/Stratis.Bitcoin.IntegrationTests/Program.cs @@ -8,7 +8,7 @@ class Program { public static void Main(string[] args) { - new WalletTests().CanMineBlocks(); + new WalletTests().CanSendToAddress(); } } } diff --git a/Stratis.Bitcoin.IntegrationTests/WalletTests.cs b/Stratis.Bitcoin.IntegrationTests/WalletTests.cs index 5ff2522f535..9c4b3ccbdd8 100644 --- a/Stratis.Bitcoin.IntegrationTests/WalletTests.cs +++ b/Stratis.Bitcoin.IntegrationTests/WalletTests.cs @@ -90,6 +90,21 @@ public void CanMineBlocks() } } + [Fact] + public void CanSendToAddress() + { + using(NodeBuilder builder = NodeBuilder.Create()) + { + var stratisNodeSync = builder.CreateStratisNode(); + builder.StartAll(); + var rpc = stratisNodeSync.CreateRPCClient(); + rpc.SendCommand(NBitcoin.RPC.RPCOperations.generate, 101); + var address = new Key().PubKey.GetAddress(rpc.Network); + var tx = rpc.SendToAddress(address, Money.Coins(1.0m)); + Assert.NotNull(tx); + } + } + [Fact] public void WalletCanReorg() { diff --git a/Stratis.Bitcoin/RPC/ModelBinders/DestinationModelBinder.cs b/Stratis.Bitcoin/RPC/ModelBinders/DestinationModelBinder.cs new file mode 100644 index 00000000000..4dbd0c3b7e8 --- /dev/null +++ b/Stratis.Bitcoin/RPC/ModelBinders/DestinationModelBinder.cs @@ -0,0 +1,65 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding; +using NBitcoin; +using System.Reflection; +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Internal; + +namespace Stratis.Bitcoin.RPC.ModelBinders +{ + public class DestinationModelBinder : IModelBinder, IModelBinderProvider + { + public DestinationModelBinder() + { + + } + + #region IModelBinder Members + + public Task BindModelAsync(ModelBindingContext bindingContext) + { + if(!SupportType(bindingContext.ModelType)) + { + return TaskCache.CompletedTask; + } + + ValueProviderResult val = bindingContext.ValueProvider.GetValue( + bindingContext.ModelName); + if(val == null) + { + return TaskCache.CompletedTask; + } + + string key = val.FirstValue as string; + if(key == null) + { + return TaskCache.CompletedTask; + } + + var network = (Network)bindingContext.HttpContext.RequestServices.GetService(typeof(Network)); + //TODO: Use var data = Network.Parse(key, network); when NBitcoin is updated to latest version + var data = BitcoinAddress.Create(key, network); + if(!bindingContext.ModelType.IsInstanceOfType(data)) + { + throw new FormatException("Invalid destination type"); + } + bindingContext.Result = ModelBindingResult.Success(data); + return TaskCache.CompletedTask; + } + + private static bool SupportType(Type type) + { + return (typeof(Base58Data).GetTypeInfo().IsAssignableFrom(type) || + typeof(IDestination).GetTypeInfo().IsAssignableFrom(type)); + } + + public IModelBinder GetBinder(ModelBinderProviderContext context) + { + if(SupportType(context.Metadata.ModelType)) + return this; + return null; + } + + #endregion + } +} diff --git a/Stratis.Bitcoin/RPC/ModelBinders/MoneyModelBinder.cs b/Stratis.Bitcoin/RPC/ModelBinders/MoneyModelBinder.cs new file mode 100644 index 00000000000..5db2b8dee9b --- /dev/null +++ b/Stratis.Bitcoin/RPC/ModelBinders/MoneyModelBinder.cs @@ -0,0 +1,43 @@ +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using NBitcoin; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Stratis.Bitcoin.RPC.ModelBinders +{ + public class MoneyModelBinder : IModelBinder, IModelBinderProvider + { + public Task BindModelAsync(ModelBindingContext bindingContext) + { + if(bindingContext.ModelType != typeof(Money)) + { + return TaskCache.CompletedTask; + } + + ValueProviderResult val = bindingContext.ValueProvider.GetValue( + bindingContext.ModelName); + if(val == null) + { + return TaskCache.CompletedTask; + } + + string key = val.FirstValue as string; + if(key == null) + { + return TaskCache.CompletedTask; + } + return Task.FromResult(Money.Parse(key)); + } + + public IModelBinder GetBinder(ModelBinderProviderContext context) + { + if(context.Metadata.ModelType == typeof(Money)) + return this; + return null; + } + } +} diff --git a/Stratis.Bitcoin/RPC/WebHostExtensions.cs b/Stratis.Bitcoin/RPC/WebHostExtensions.cs index 675d4e0d46d..30e90cf8ba8 100644 --- a/Stratis.Bitcoin/RPC/WebHostExtensions.cs +++ b/Stratis.Bitcoin/RPC/WebHostExtensions.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Stratis.Bitcoin.Miner; +using Stratis.Bitcoin.RPC.ModelBinders; using Stratis.Bitcoin.Wallet; using System; using System.Collections.Generic; @@ -15,6 +16,11 @@ public static IWebHostBuilder ForFullNode(this IWebHostBuilder hostBuilder, Full { hostBuilder.ConfigureServices(s => { + s.AddMvcCore(o => + { + o.ModelBinderProviders.Insert(0, new DestinationModelBinder()); + o.ModelBinderProviders.Insert(0, new MoneyModelBinder()); + }); s.AddSingleton(fullNode); s.AddSingleton(fullNode as Builder.IFullNode); s.AddSingleton(fullNode.Network);