Commit 1c4eaa2a authored by Jeremy Bokobza's avatar Jeremy Bokobza

Added method to find a block given a date

parent 1dc3c9a7
...@@ -22,7 +22,7 @@ namespace Breeze.Api.Tests ...@@ -22,7 +22,7 @@ namespace Breeze.Api.Tests
var mockWalletCreate = new Mock<IWalletManager>(); var mockWalletCreate = new Mock<IWalletManager>();
mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), null)).Returns(mnemonic); mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), null)).Returns(mnemonic);
var controller = new WalletController(mockWalletCreate.Object); var controller = new WalletController(mockWalletCreate.Object, new Mock<ITracker>().Object);
// Act // Act
var result = controller.Create(new WalletCreationRequest var result = controller.Create(new WalletCreationRequest
...@@ -50,9 +50,9 @@ namespace Breeze.Api.Tests ...@@ -50,9 +50,9 @@ namespace Breeze.Api.Tests
}; };
var mockWalletWrapper = new Mock<IWalletManager>(); var mockWalletWrapper = new Mock<IWalletManager>();
mockWalletWrapper.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), null, null)).Returns(wallet); mockWalletWrapper.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), null, It.IsAny<DateTime>())).Returns(wallet);
var controller = new WalletController(mockWalletWrapper.Object); var controller = new WalletController(mockWalletWrapper.Object, new Mock<ITracker>().Object);
// Act // Act
var result = controller.Recover(new WalletRecoveryRequest var result = controller.Recover(new WalletRecoveryRequest
...@@ -85,7 +85,7 @@ namespace Breeze.Api.Tests ...@@ -85,7 +85,7 @@ namespace Breeze.Api.Tests
var mockWalletWrapper = new Mock<IWalletManager>(); var mockWalletWrapper = new Mock<IWalletManager>();
mockWalletWrapper.Setup(w => w.LoadWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(wallet); mockWalletWrapper.Setup(w => w.LoadWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(wallet);
var controller = new WalletController(mockWalletWrapper.Object); var controller = new WalletController(mockWalletWrapper.Object, new Mock<ITracker>().Object);
// Act // Act
var result = controller.Load(new WalletLoadRequest var result = controller.Load(new WalletLoadRequest
...@@ -111,7 +111,7 @@ namespace Breeze.Api.Tests ...@@ -111,7 +111,7 @@ namespace Breeze.Api.Tests
var mockWalletWrapper = new Mock<IWalletManager>(); var mockWalletWrapper = new Mock<IWalletManager>();
mockWalletWrapper.Setup(wallet => wallet.LoadWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Throws<FileNotFoundException>(); mockWalletWrapper.Setup(wallet => wallet.LoadWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Throws<FileNotFoundException>();
var controller = new WalletController(mockWalletWrapper.Object); var controller = new WalletController(mockWalletWrapper.Object, new Mock<ITracker>().Object);
// Act // Act
var result = controller.Load(new WalletLoadRequest var result = controller.Load(new WalletLoadRequest
......
...@@ -39,5 +39,39 @@ namespace Breeze.Wallet ...@@ -39,5 +39,39 @@ namespace Breeze.Wallet
throw new Exception("No support for this coin."); throw new Exception("No support for this coin.");
} }
} }
/// <summary>
/// Gets the height of the first block created after this date.
/// </summary>
/// <param name="chain">The chain of blocks.</param>
/// <param name="date">The date.</param>
/// <returns>The height of the first block created after the date.</returns>
public static int GetHeightAtTime(this ConcurrentChain chain, DateTime date)
{
int blockSyncStart = 0;
int upperLimit = chain.Tip.Height;
int lowerLimit = 0;
bool found = false;
while (!found)
{
int check = lowerLimit + (upperLimit - lowerLimit) / 2;
if (chain.GetBlock(check).Header.BlockTime >= date)
{
upperLimit = check;
}
else if (chain.GetBlock(check).Header.BlockTime < date)
{
lowerLimit = check;
}
if (upperLimit - lowerLimit <= 1)
{
blockSyncStart = upperLimit;
found = true;
}
}
return blockSyncStart;
}
} }
} }
\ No newline at end of file
...@@ -14,14 +14,17 @@ namespace Breeze.Wallet.Controllers ...@@ -14,14 +14,17 @@ namespace Breeze.Wallet.Controllers
/// <summary> /// <summary>
/// Controller providing operations on a wallet. /// Controller providing operations on a wallet.
/// </summary> /// </summary>
[Route("api/v{version:apiVersion}/[controller]")] [Route("api/v{version:apiVersion}/[controller]")]
public class WalletController : Controller public class WalletController : Controller
{ {
private readonly IWalletManager walletManager; private readonly IWalletManager walletManager;
public WalletController(IWalletManager walletManager) private readonly ITracker tracker;
public WalletController(IWalletManager walletManager, ITracker tracker)
{ {
this.walletManager = walletManager; this.walletManager = walletManager;
this.tracker = tracker;
} }
/// <summary> /// <summary>
...@@ -60,7 +63,7 @@ namespace Breeze.Wallet.Controllers ...@@ -60,7 +63,7 @@ namespace Breeze.Wallet.Controllers
/// </summary> /// </summary>
/// <param name="request">The name of the wallet to load.</param> /// <param name="request">The name of the wallet to load.</param>
/// <returns></returns> /// <returns></returns>
[Route("load")] [Route("load")]
[HttpPost] [HttpPost]
public IActionResult Load([FromBody]WalletLoadRequest request) public IActionResult Load([FromBody]WalletLoadRequest request)
{ {
...@@ -120,9 +123,10 @@ namespace Breeze.Wallet.Controllers ...@@ -120,9 +123,10 @@ namespace Breeze.Wallet.Controllers
// get the wallet folder // get the wallet folder
DirectoryInfo walletFolder = GetWalletFolder(request.FolderPath); DirectoryInfo walletFolder = GetWalletFolder(request.FolderPath);
Wallet wallet = this.walletManager.RecoverWallet(request.Password, walletFolder.FullName, request.Name, request.Network, request.Mnemonic); Wallet wallet = this.walletManager.RecoverWallet(request.Password, walletFolder.FullName, request.Name, request.Network, request.Mnemonic, null, request.CreationDate);
// TODO give the tracker the date at which this wallet was originally created so that it can start syncing blocks for it // start syncing the wallet from the creation date
this.tracker.SyncFrom(request.CreationDate);
return this.Json(new WalletModel return this.Json(new WalletModel
{ {
...@@ -179,7 +183,7 @@ namespace Breeze.Wallet.Controllers ...@@ -179,7 +183,7 @@ namespace Breeze.Wallet.Controllers
/// </summary> /// </summary>
/// <param name="request">The request parameters.</param> /// <param name="request">The request parameters.</param>
/// <returns></returns> /// <returns></returns>
[Route("history")] [Route("history")]
[HttpGet] [HttpGet]
public IActionResult GetHistory([FromQuery] WalletHistoryRequest request) public IActionResult GetHistory([FromQuery] WalletHistoryRequest request)
{ {
...@@ -269,7 +273,7 @@ namespace Breeze.Wallet.Controllers ...@@ -269,7 +273,7 @@ namespace Breeze.Wallet.Controllers
/// </summary> /// </summary>
/// <param name="request">The transaction parameters.</param> /// <param name="request">The transaction parameters.</param>
/// <returns>All the details of the transaction, including the hex used to execute it.</returns> /// <returns>All the details of the transaction, including the hex used to execute it.</returns>
[Route("build-transaction")] [Route("build-transaction")]
[HttpPost] [HttpPost]
public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request) public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request)
{ {
...@@ -296,7 +300,7 @@ namespace Breeze.Wallet.Controllers ...@@ -296,7 +300,7 @@ namespace Breeze.Wallet.Controllers
/// </summary> /// </summary>
/// <param name="request">The hex representing the transaction.</param> /// <param name="request">The hex representing the transaction.</param>
/// <returns></returns> /// <returns></returns>
[Route("send-transaction")] [Route("send-transaction")]
[HttpPost] [HttpPost]
public IActionResult SendTransaction([FromBody] SendTransactionRequest request) public IActionResult SendTransaction([FromBody] SendTransactionRequest request)
{ {
......
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
using NBitcoin; using NBitcoin;
namespace Breeze.Wallet namespace Breeze.Wallet
...@@ -16,5 +17,12 @@ namespace Breeze.Wallet ...@@ -16,5 +17,12 @@ namespace Breeze.Wallet
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
Task WaitForChainDownloadAsync(); Task WaitForChainDownloadAsync();
/// <summary>
/// Synchronize the wallet starting from the date passed as a parameter.
/// </summary>
/// <param name="date">The date from which to start the sync process.</param>
/// <returns></returns>
void SyncFrom(DateTime date);
} }
} }
...@@ -39,9 +39,9 @@ namespace Breeze.Wallet ...@@ -39,9 +39,9 @@ namespace Breeze.Wallet
/// <param name="network">The network in which to creae this wallet</param> /// <param name="network">The network in which to creae this wallet</param>
/// <param name="mnemonic">The user's mnemonic for the wallet.</param> /// <param name="mnemonic">The user's mnemonic for the wallet.</param>
/// <param name="passphrase">The passphrase used in the seed.</param> /// <param name="passphrase">The passphrase used in the seed.</param>
/// <param name="creationTime">The time this wallet was created.</param> /// <param name="creationTime">The date and time this wallet was created.</param>
/// <returns>The recovered wallet.</returns> /// <returns>The recovered wallet.</returns>
Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTimeOffset? creationTime = null); Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTime? creationTime = null);
/// <summary> /// <summary>
/// Deleted a wallet. /// Deleted a wallet.
......
using System.Collections; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Breeze.Wallet.Models namespace Breeze.Wallet.Models
{ {
...@@ -45,6 +48,9 @@ namespace Breeze.Wallet.Models ...@@ -45,6 +48,9 @@ namespace Breeze.Wallet.Models
public string Name { get; set; } public string Name { get; set; }
public string Network { get; set; } public string Network { get; set; }
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime CreationDate { get; set; }
} }
public class WalletHistoryRequest public class WalletHistoryRequest
......
...@@ -84,6 +84,15 @@ namespace Breeze.Wallet ...@@ -84,6 +84,15 @@ namespace Breeze.Wallet
repeatEvery: TimeSpans.FiveSeconds); repeatEvery: TimeSpans.FiveSeconds);
} }
/// <inheritdoc />
public void SyncFrom(DateTime date)
{
int blockSyncStart = this.chain.GetHeightAtTime(date);
// start syncing blocks
this.blockNotification.SyncFrom(this.chain.GetBlock(blockSyncStart).HashBlock);
}
private bool BlocksSynced() private bool BlocksSynced()
{ {
return this.walletManager.Wallets.All(w => w.AccountsRoot.Single(a => a.CoinType == this.coinType).LastBlockSyncedHeight == this.chain.Tip.Height); return this.walletManager.Wallets.All(w => w.AccountsRoot.Single(a => a.CoinType == this.coinType).LastBlockSyncedHeight == this.chain.Tip.Height);
......
...@@ -73,7 +73,7 @@ namespace Breeze.Wallet ...@@ -73,7 +73,7 @@ namespace Breeze.Wallet
} }
/// <inheritdoc /> /// <inheritdoc />
public Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTimeOffset? creationTime = null) public Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTime? creationTime = null)
{ {
// for now the passphrase is set to be the password by default. // for now the passphrase is set to be the password by default.
if (passphrase == null) if (passphrase == null)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment