Skip to content

Commit

Permalink
Fixes #1
Browse files Browse the repository at this point in the history
  • Loading branch information
bscheiman committed Feb 2, 2015
1 parent b8f7cf5 commit 37baa69
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 154 deletions.
67 changes: 38 additions & 29 deletions BlockCypher.csproj
Expand Up @@ -2,15 +2,20 @@
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E203C0BC-F28E-463F-953D-A37D42B79397}</ProjectGuid>
<ProjectGuid>{52A9A7E6-6554-42DE-BFB9-AEEA3DCA9F30}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BlockCypher</RootNamespace>
<AssemblyName>BlockCypher</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<NuGetPackageImportStamp>4f485c66</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -29,43 +34,19 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="BouncyCastle.Crypto">
<HintPath>packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="bscheiman.Common, Version=1.0.47.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\bscheiman.Common.1.0.47\lib\net45\bscheiman.Common.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Build.Tasks.v4.0" />
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\Newtonsoft.Json.6.0.7\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="RestSharp">
<HintPath>packages\RestSharp.105.0.1\lib\net4\RestSharp.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Blockcypher.cs" />
<Compile Include="Endpoint.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="Helpers\Base58Helper.cs" />
<Compile Include="HookEvent.cs" />
<Compile Include="Objects\AddressInfo.cs" />
<Compile Include="Objects\Balance.cs" />
<Compile Include="Objects\BaseObject.cs" />
<Compile Include="Objects\Faucet.cs" />
<Compile Include="Objects\HookInfo.cs" />
<Compile Include="Objects\SatoshiConverter.cs" />
<Compile Include="Objects\Satoshi.cs" />
<Compile Include="Objects\SatoshiConverter.cs" />
<Compile Include="Objects\Transaction.cs" />
<Compile Include="Objects\TxInput.cs" />
<Compile Include="Objects\TxOutput.cs" />
Expand All @@ -74,9 +55,37 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="crypto">
<HintPath>packages\Portable.BouncyCastle.1.7.0.1\lib\portable-net4+sl5+wp8+win8+wpa81\crypto.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>packages\Microsoft.Bcl.Async.1.0.168\lib\portable-net45+win8+wpa81\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>packages\Microsoft.Bcl.Async.1.0.168\lib\portable-net45+win8+wpa81\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>packages\Newtonsoft.Json.6.0.8\lib\portable-net45+wp80+win8+wpa81+aspnetcore50\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Extensions">
<HintPath>packages\Microsoft.Net.Http.2.2.28\lib\portable-net45+win8\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives">
<HintPath>packages\Microsoft.Net.Http.2.2.28\lib\portable-net45+win8\System.Net.Http.Primitives.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
6 changes: 0 additions & 6 deletions BlockCypher.csproj.user

This file was deleted.

14 changes: 0 additions & 14 deletions BlockCypher.nuspec

This file was deleted.

10 changes: 5 additions & 5 deletions BlockCypher.sln
Expand Up @@ -3,18 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockCypher", "BlockCypher.csproj", "{E203C0BC-F28E-463F-953D-A37D42B79397}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockCypher", "BlockCypher.csproj", "{52A9A7E6-6554-42DE-BFB9-AEEA3DCA9F30}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E203C0BC-F28E-463F-953D-A37D42B79397}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E203C0BC-F28E-463F-953D-A37D42B79397}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E203C0BC-F28E-463F-953D-A37D42B79397}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E203C0BC-F28E-463F-953D-A37D42B79397}.Release|Any CPU.Build.0 = Release|Any CPU
{52A9A7E6-6554-42DE-BFB9-AEEA3DCA9F30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52A9A7E6-6554-42DE-BFB9-AEEA3DCA9F30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52A9A7E6-6554-42DE-BFB9-AEEA3DCA9F30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52A9A7E6-6554-42DE-BFB9-AEEA3DCA9F30}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Binary file modified BlockCypher.v12.suo
Binary file not shown.
135 changes: 62 additions & 73 deletions Blockcypher.cs
@@ -1,20 +1,21 @@
#region
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using BlockCypher.Helpers;
using BlockCypher.Objects;
using bscheiman.Common.Extensions;
using BlockCypher.Pcl;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using RestSharp;

#endregion

Expand Down Expand Up @@ -66,40 +67,51 @@ public class Blockcypher {
}

public Task<HookInfo> GenerateHook(string address, HookEvent hook, string url) {
string evt = "";

switch (hook) {
case HookEvent.ConfirmedTransaction:
evt = "confirmed-tx";
break;

case HookEvent.DoubleSpendTransaction:
evt = "double-spend-tx";
break;

case HookEvent.NewBlock:
evt = "new-block";
break;

case HookEvent.TransactionConfirmation:
evt = "tx-confirmation";
break;

case HookEvent.UnconfirmedTransaction:
evt = "unconfirmed-tx";
break;
}

return PostAsync<HookInfo>("hooks", new {
@event = hook.GetAttributeOfType<DescriptionAttribute>().Description,
@event = evt,
url,
address
});
}

public Task<AddressBalance> GetBalanceForAddress(string address) {
return GetAsync<AddressBalance>("addrs/{address}", null, new Parameter {
Name = "address",
Value = address,
Type = ParameterType.UrlSegment
});
return GetAsync<AddressBalance>(string.Format("addrs/{0}", address));
}

public IEnumerable<Task<AddressBalance>> GetBalanceForAddresses(params string[] addresses) {
return addresses.Select(GetBalanceForAddress);
}

private static byte[] GetBytesFromBase58Key(string privateKey) {
var tmp = Base58Helper.DecodeWithCheckSum(privateKey);
var bytes = new byte[tmp.Length - 1];

Array.Copy(tmp, 1, bytes, 0, tmp.Length - 1);

return bytes;
}

public Task<UnsignedTransaction> Send(AddressInfo fromAddress, AddressInfo toAddress, Satoshi amount) {
return Send(fromAddress.Address, toAddress.Address, fromAddress.Private, fromAddress.Public, amount);
}

public async Task<UnsignedTransaction> Send(string fromAddress, string toAddress, string fromPrivate, string fromPublic,
Satoshi amount) {
Satoshi amount) {
var unsignedTx = await PostAsync<UnsignedTransaction>("txs/new", new Transaction {
Inputs = new[] {
new TxInput {
Expand Down Expand Up @@ -128,10 +140,19 @@ public class Blockcypher {
return await PostAsync<UnsignedTransaction>("txs/send", unsignedTx);
}

private static byte[] GetBytesFromBase58Key(string privateKey) {
var tmp = Base58Helper.DecodeWithCheckSum(privateKey);
var bytes = new byte[tmp.Length - 1];

Array.Copy(tmp, 1, bytes, 0, tmp.Length - 1);

return bytes;
}

private static void Sign(UnsignedTransaction unsignedTransaction, string privateKey, bool isHex, bool addPubKey,
bool forceCompressed = false) {
bool forceCompressed = false) {
bool compressed = false;
byte[] bytes = isHex ? privateKey.FromHexString() : GetBytesFromBase58Key(privateKey);
var bytes = isHex ? privateKey.FromHexString() : GetBytesFromBase58Key(privateKey);

if (bytes.Length == 33 && bytes[32] == 1) {
compressed = true;
Expand All @@ -153,7 +174,7 @@ public class Blockcypher {
var privKey = new ECPrivateKeyParameters(privKeyB, curve);
signer.Init(true, privKey);

foreach (var toSign in unsignedTransaction.ToSign) {
foreach (string toSign in unsignedTransaction.ToSign) {
if (addPubKey)
unsignedTransaction.PubKeys.Add(publicKey.ToHexString());

Expand All @@ -172,76 +193,44 @@ public class Blockcypher {

seq.Close();

var signedString = ms.ToArray().ToHexString();
string signedString = ms.ToArray().ToHexString();

unsignedTransaction.Signatures.Add(signedString);
}
}
}

#region Helpers
internal Task<T> DeleteAsync<T>(string url, params Parameter[] parameters) where T : new() {
var tcs = new TaskCompletionSource<T>();
var client = GetClient(url);

client.ExecuteAsync(GetRequest(url, Method.DELETE, null, parameters), response => tcs.SetResult(response.Content.FromJson<T>()));

return tcs.Task;
}
internal async Task<T> GetAsync<T>(string url) {
var client = GetClient();

internal Task<T> GetAsync<T>(string url, object obj = null, params Parameter[] parameters) {
var tcs = new TaskCompletionSource<T>();
var client = GetClient(url);
var response = await client.GetAsync(string.Format("{0}/{1}", BaseUrl, url));
response.EnsureSuccessStatusCode();

client.ExecuteAsync(GetRequest(url, Method.GET, obj, parameters), response => tcs.SetResult(response.Content.FromJson<T>()));
string content = await response.Content.ReadAsStringAsync();

return tcs.Task;
return content.FromJson<T>();
}

internal RestClient GetClient(string url) {
var client = new RestClient(BaseUrl) {
UserAgent = "Blockcypher.NET"
};
internal HttpClient GetClient() {
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

return client;
}

internal RestRequest GetRequest(string url, Method method, object obj, params Parameter[] parameters) {
var request = new RestRequest(url, method);

foreach (var p in parameters)
request.AddParameter(p);

if (!string.IsNullOrEmpty(UserToken)) {
request.AddParameter(new Parameter {
Name = "token",
Type = ParameterType.QueryString,
Value = UserToken
});
}

request.AddParameter("application/json", (obj ?? new {
}).ToJson(), ParameterType.RequestBody);

return request;
}

internal Task<T> PostAsync<T>(string url, object obj, params Parameter[] parameters) where T : new() {
var tcs = new TaskCompletionSource<T>();
var client = GetClient(url);

client.ExecuteAsync(GetRequest(url, Method.POST, obj, parameters), response => tcs.SetResult(response.Content.FromJson<T>()));

return tcs.Task;
}
internal async Task<T> PostAsync<T>(string url, object obj) where T : new() {
var client = GetClient();

internal Task<T> PutAsync<T>(string url, object obj, params Parameter[] parameters) where T : new() {
var tcs = new TaskCompletionSource<T>();
var client = GetClient(url);
var response =
await
client.PostAsync(string.Format("{0}/{1}", BaseUrl, url),
new StringContent((obj ?? new object()).ToJson(), Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();

client.ExecuteAsync(GetRequest(url, Method.PUT, obj, parameters), response => tcs.SetResult(response.Content.FromJson<T>()));
string content = await response.Content.ReadAsStringAsync();

return tcs.Task;
return content.FromJson<T>();
}
#endregion
}
Expand Down

0 comments on commit 37baa69

Please sign in to comment.