Commit 1dc3c9a7 authored by Pieterjan Vanhoof's avatar Pieterjan Vanhoof Committed by GitHub

Merge pull request #38 from bokobza/feature/history

Added getting the balance for the user's accounts
parents e4036778 bae6052a
...@@ -196,8 +196,6 @@ Works as expected. ...@@ -196,8 +196,6 @@ Works as expected.
"1HDypWxXWZC5KXK259EHMnrWaa2youy7Mj" "1HDypWxXWZC5KXK259EHMnrWaa2youy7Mj"
``` ```
## GET /wallet/mempool/?allow=[true/false] - Allows or disallows mempool syncing
Works as expected.
## GET /wallet/receive/[account1/account2] - Displays unused receive addresses of the specified wallet account ## GET /wallet/receive/[account1/account2] - Displays unused receive addresses of the specified wallet account
### Responses ### Responses
...@@ -216,38 +214,54 @@ Works as expected. ...@@ -216,38 +214,54 @@ Works as expected.
} }
``` ```
## GET /wallet/history/[account1/account2] - Displays the history of the specified wallet account ## GET /wallet/history - Displays the history of the specified wallet account
### Query parameters
`walletName` (required) - the name of the wallet.
`coinType` (required) - the type of coin, e.g 0 for bitcoin, 105 for stratis.
### Responses ### Responses
``` ```
{ {
"history": "transactions": [
[
{ {
"txid": "9a9949476b629b4075b31d8faad64dad352586a18df8f2810c5a7bb900478c60", "address": "1H2jbtknP6jRYx2riaXJf3H9Mb1JC6kcL2",
"amount": "0.1", "txId": "b800f9b24a9c49a375cddf4fc8c484722af0bec7d23ac65b782daf1b0089bb29",
"amount": -50360386,
"confirmed": true, "confirmed": true,
"timestamp": "2016.12.19. 23:15:05" // if confirmed it's the blocktime, utc "timestamp": "1337803568"
}, },
{ {
"txid": "9a9949476b629b4075b31d8faad64dad352586a18df8f2810c5a7bb900478c60", "address": "1H2jbtknP6jRYx2riaXJf3H9Mb1JC6kcL2",
"amount": "-0.1", "txId": "9c0560a34f88573a71ebf68a2540cb7215b55bc2ddee0af3cb1dc343f2f3e0da",
"confirmed": false, "amount": 53845026,
"timestamp": "2016.12.20. 1:15:36" // if unconfirmed it's the time our node first seen this transaction, utc "confirmed": true,
"timestamp": "1337605326"
} }
] ]
} }
``` ```
## GET /wallet/balance/[account1/account2] - Displays the balances of the specified wallet account ## GET /wallet/balance - Displays the balances of the specified wallet account
### Query parameters
`walletName` (required) - the name of the wallet.
`coinType` (required) - the type of coin, e.g 0 for bitcoin, 105 for stratis.
### Responses ### Responses
``` ```
{ {
"isSynced": true, "balances": [
"confirmed": "0.144", {
"unconfirmed": "-6.23" "accountName": "account one",
"accountHdPath": "m/44'/0'/0'",
"coinType": 0,
"amountConfirmed": 209268016,
"amountUnconfirmed": 0
}
]
} }
``` ```
If the synced is false, then the balances might not be accurate.
Confirmed balance is the (amount of unspent confirmed outputs - unconfirmed outgoing transactions). It cannot be negative. Confirmed balance is the (amount of unspent confirmed outputs - unconfirmed outgoing transactions). It cannot be negative.
Unconfirmed balance is the difference of unconfirmed incoming and outgoing transactions. It can be negative. Unconfirmed balance is the difference of unconfirmed incoming and outgoing transactions. It can be negative.
......
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
{ {
"name": "Get Wallet History", "name": "Get Wallet History",
"request": { "request": {
"url": "http://localhost:5000/api/v1/wallet/history?name=mywallet", "url": "http://localhost:5000/api/v1/wallet/history?walletname=wallet1&cointype=0",
"method": "GET", "method": "GET",
"header": [ "header": [
{ {
...@@ -130,7 +130,7 @@ ...@@ -130,7 +130,7 @@
{ {
"name": "Get wallet balance", "name": "Get wallet balance",
"request": { "request": {
"url": "http://localhost:5000/api/v1/wallet/balance?name=mywallet", "url": "http://localhost:5000/api/v1/wallet/balance?walletname=wallet1&cointype=0",
"method": "GET", "method": "GET",
"header": [ "header": [
{ {
......
...@@ -192,7 +192,7 @@ namespace Breeze.Wallet.Controllers ...@@ -192,7 +192,7 @@ namespace Breeze.Wallet.Controllers
try try
{ {
WalletHistoryModel model = new WalletHistoryModel {Transactions = new List<TransactionItem>()}; WalletHistoryModel model = new WalletHistoryModel { Transactions = new List<TransactionItem>() };
var accounts = this.walletManager.GetAccountsByCoinType(request.WalletName, request.CoinType).ToList(); var accounts = this.walletManager.GetAccountsByCoinType(request.WalletName, request.CoinType).ToList();
foreach (var address in accounts.SelectMany(a => a.ExternalAddresses).Concat(accounts.SelectMany(a => a.InternalAddresses))) foreach (var address in accounts.SelectMany(a => a.ExternalAddresses).Concat(accounts.SelectMany(a => a.InternalAddresses)))
...@@ -210,7 +210,8 @@ namespace Breeze.Wallet.Controllers ...@@ -210,7 +210,8 @@ namespace Breeze.Wallet.Controllers
} }
} }
return this.Json(model.Transactions.OrderByDescending(t => t.Timestamp)); model.Transactions = model.Transactions.OrderByDescending(t => t.Timestamp).ToList();
return this.Json(model);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -221,11 +222,11 @@ namespace Breeze.Wallet.Controllers ...@@ -221,11 +222,11 @@ namespace Breeze.Wallet.Controllers
/// <summary> /// <summary>
/// Gets the balance of a wallet. /// Gets the balance of a wallet.
/// </summary> /// </summary>
/// <param name="model">The name of the wallet.</param> /// <param name="request">The request parameters.</param>
/// <returns></returns> /// <returns></returns>
[Route("balance")] [Route("balance")]
[HttpGet] [HttpGet]
public IActionResult GetBalance([FromQuery] WalletName model) public IActionResult GetBalance([FromQuery] WalletBalanceRequest request)
{ {
// checks the request is valid // checks the request is valid
if (!this.ModelState.IsValid) if (!this.ModelState.IsValid)
...@@ -236,8 +237,26 @@ namespace Breeze.Wallet.Controllers ...@@ -236,8 +237,26 @@ namespace Breeze.Wallet.Controllers
try try
{ {
return this.Json(this.walletManager.GetBalance(model.Name)); WalletBalanceModel model = new WalletBalanceModel { AccountsBalances = new List<AccountBalance>() };
var accounts = this.walletManager.GetAccountsByCoinType(request.WalletName, request.CoinType).ToList();
foreach (var account in accounts)
{
var allTransactions = account.ExternalAddresses.SelectMany(a => a.Transactions)
.Concat(account.InternalAddresses.SelectMany(i => i.Transactions)).ToList();
AccountBalance balance = new AccountBalance
{
CoinType = request.CoinType,
Name = account.Name,
HdPath = account.HdPath,
AmountConfirmed = allTransactions.Where(t => t.Confirmed).Sum(t => t.Amount),
AmountUnconfirmed = allTransactions.Where(t => !t.Confirmed).Sum(t => t.Amount)
};
model.AccountsBalances.Add(balance);
}
return this.Json(model);
} }
catch (Exception e) catch (Exception e)
{ {
......
...@@ -74,8 +74,6 @@ namespace Breeze.Wallet ...@@ -74,8 +74,6 @@ namespace Breeze.Wallet
WalletGeneralInfoModel GetGeneralInfo(string walletName); WalletGeneralInfoModel GetGeneralInfo(string walletName);
WalletBalanceModel GetBalance(string walletName);
/// <summary> /// <summary>
/// Gets a list of accounts filtered by coin type. /// Gets a list of accounts filtered by coin type.
/// </summary> /// </summary>
......
...@@ -56,6 +56,15 @@ namespace Breeze.Wallet.Models ...@@ -56,6 +56,15 @@ namespace Breeze.Wallet.Models
public CoinType CoinType { get; set; } public CoinType CoinType { get; set; }
} }
public class WalletBalanceRequest
{
[Required(ErrorMessage = "The name of the wallet is missing.")]
public string WalletName { get; set; }
[Required(ErrorMessage = "The type of coin for which history is requested is missing.")]
public CoinType CoinType { get; set; }
}
public class WalletName public class WalletName
{ {
[Required(ErrorMessage = "The name of the wallet is missing.")] [Required(ErrorMessage = "The name of the wallet is missing.")]
......
...@@ -9,13 +9,25 @@ namespace Breeze.Wallet.Models ...@@ -9,13 +9,25 @@ namespace Breeze.Wallet.Models
{ {
public class WalletBalanceModel public class WalletBalanceModel
{ {
[JsonProperty(PropertyName = "isSynced")] [JsonProperty(PropertyName = "balances")]
public bool IsSynced { get; set; } public List<AccountBalance> AccountsBalances { get; set; }
}
public class AccountBalance
{
[JsonProperty(PropertyName = "accountName")]
public string Name { get; set; }
[JsonProperty(PropertyName = "accountHdPath")]
public string HdPath { get; set; }
[JsonProperty(PropertyName = "coinType")]
public CoinType CoinType { get; set; }
[JsonProperty(PropertyName = "confirmed")] [JsonProperty(PropertyName = "amountConfirmed")]
public Money Confirmed { get; set; } public Money AmountConfirmed { get; set; }
[JsonProperty(PropertyName = "unconfirmed")] [JsonProperty(PropertyName = "amountUnconfirmed")]
public Money Unconfirmed { get; set; } public Money AmountUnconfirmed { get; set; }
} }
} }
...@@ -125,6 +125,13 @@ namespace Breeze.Wallet ...@@ -125,6 +125,13 @@ namespace Breeze.Wallet
[JsonProperty(PropertyName = "name")] [JsonProperty(PropertyName = "name")]
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// A path to the account as defined in BIP44.
/// </summary>
[JsonProperty(PropertyName = "hdPath")]
public string HdPath { get; set; }
/// <summary> /// <summary>
/// An extended pub key used to generate addresses. /// An extended pub key used to generate addresses.
/// </summary> /// </summary>
......
...@@ -127,7 +127,8 @@ namespace Breeze.Wallet ...@@ -127,7 +127,8 @@ namespace Breeze.Wallet
// get the extended pub key used to generate addresses for this account // get the extended pub key used to generate addresses for this account
var privateKey = Key.Parse(wallet.EncryptedSeed, password, wallet.Network); var privateKey = Key.Parse(wallet.EncryptedSeed, password, wallet.Network);
var seedExtKey = new ExtKey(privateKey, wallet.ChainCode); var seedExtKey = new ExtKey(privateKey, wallet.ChainCode);
KeyPath keyPath = new KeyPath($"m/44'/{(int)coinType}'/{newAccountIndex}'"); var accountHdPath = $"m/44'/{(int) coinType}'/{newAccountIndex}'";
KeyPath keyPath = new KeyPath(accountHdPath);
ExtKey accountExtKey = seedExtKey.Derive(keyPath); ExtKey accountExtKey = seedExtKey.Derive(keyPath);
ExtPubKey accountExtPubKey = accountExtKey.Neuter(); ExtPubKey accountExtPubKey = accountExtKey.Neuter();
...@@ -138,6 +139,7 @@ namespace Breeze.Wallet ...@@ -138,6 +139,7 @@ namespace Breeze.Wallet
ExternalAddresses = new List<HdAddress>(), ExternalAddresses = new List<HdAddress>(),
InternalAddresses = new List<HdAddress>(), InternalAddresses = new List<HdAddress>(),
Name = accountName, Name = accountName,
HdPath = accountHdPath,
CreationTime = DateTimeOffset.Now CreationTime = DateTimeOffset.Now
}); });
...@@ -206,11 +208,6 @@ namespace Breeze.Wallet ...@@ -206,11 +208,6 @@ namespace Breeze.Wallet
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public WalletBalanceModel GetBalance(string walletName)
{
throw new System.NotImplementedException();
}
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<HdAccount> GetAccountsByCoinType(string walletName, CoinType coinType) public IEnumerable<HdAccount> GetAccountsByCoinType(string walletName, CoinType coinType)
{ {
......
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