Commit 3e8b0a9f authored by Jeremy Bokobza's avatar Jeremy Bokobza

Merged from master

parents 1c4eaa2a 2279ba4a
......@@ -167,12 +167,12 @@ Cannot check if the password is good or not. If the password is wrong it'll reco
## DELETE /wallet - Deletes the wallet
Works as expected.
## POST /wallet/account - Adds an account to the wallet
## POST /wallet/account - Gets an unused account from the wallet
This endpoint will get the first account containing no transaction or will create a new account.
### Parameters
```
{
"walletName": "myFirstWallet",
"accountName": "account one",
"walletName": "myFirstWallet",
"password": "123456",
"coinType": 105
}
......@@ -182,21 +182,20 @@ Works as expected.
"account one"
```
## POST /wallet/address - Adds an address to an account
### Parameters
```
{
"walletName": "myFirstWallet",
"accountName": "account one",
"coinType": 0
}
```
## GET /wallet/address - Gets an unused address
This endpoint will get the last address containing no transaction or will create a new address.
### Query parameters
`walletName` (required) - the name of the wallet in which this address is contained.
`coinType` (required) - the type of coin for which to get the address, e.g 0 for bitcoin, 105 for stratis.
`accountName` (required) - the name of the account in which this address is contained.
### Responses
```
"1HDypWxXWZC5KXK259EHMnrWaa2youy7Mj"
```
## GET /wallet/receive/[account1/account2] - Displays unused receive addresses of the specified wallet account
### Responses
```
......
......@@ -2,7 +2,7 @@
"variables": [],
"info": {
"name": "Wallet",
"_postman_id": "5eec0912-fcf0-50f5-05a2-0835fa13c670",
"_postman_id": "57013f2c-02dc-df32-41e9-6e4aaa14ad5e",
"description": "Requests relating to operations on the wallet",
"schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
},
......@@ -81,7 +81,7 @@
],
"body": {
"mode": "raw",
"raw": "{ \n\t\"password\": \"123456\",\n\t\"network\": \"Main\",\n\t\"folderPath\": \"Wallets\",\n\t\"name\": \"myFirstWalletRecovered\",\n\t\"mnemonic\": \"elbow scale error joke labor page beyond curve indicate exit brass laundry\"\n\t\n}"
"raw": "{ \n\t\"password\": \"123456\",\n\t\"network\": \"Main\",\n\t\"folderPath\": \"Wallets\",\n\t\"name\": \"myRecoveredWallet\",\n\t\"mnemonic\": \"elbow scale error joke labor page beyond curve indicate exit brass laundry\",\n\t\"creationDate\": \"2016-02-25 16:20:33\"\n}"
},
"description": ""
},
......@@ -206,29 +206,9 @@
"description": "Gets all the wallets files stored in the default folder"
},
"response": []
},
{
"name": "New account for non-existant wallet fails",
"request": {
"url": "http://localhost:5000/api/v1/wallet/account",
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json",
"description": ""
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"walletName\": \"myFirstWallet\",\n\t\"accountName\": \"account one\"\n}"
},
"description": ""
},
"response": []
},
},
{
"name": "Create new account for wallet",
"name": "Get unused account in wallet",
"request": {
"url": "http://localhost:5000/api/v1/wallet/account",
"method": "POST",
......@@ -241,17 +221,17 @@
],
"body": {
"mode": "raw",
"raw": "{\n\t\"walletName\": \"myFirstWallet\",\n\t\"accountName\": \"account one\",\n\t\"password\": \"123456\",\n\t\"coinType\": 105\n}"
"raw": "{\n\t\"walletName\": \"myFirstWallet\",\n\t\"password\": \"123456\",\n\t\"coinType\": 0\n}"
},
"description": ""
},
"response": []
},
{
"name": "Create new address for wallet",
"name": "Get unused address in wallet",
"request": {
"url": "http://localhost:5000/api/v1/wallet/address",
"method": "POST",
"url": "http://localhost:5000/api/v1/wallet/address?walletName=wallet1&accountName=account 0&coinType=0",
"method": "GET",
"header": [
{
"key": "Content-Type",
......@@ -261,7 +241,7 @@
],
"body": {
"mode": "raw",
"raw": "{\n\t\"walletName\": \"myFirstWallet\",\n\t\"accountName\": \"account one\",\n\t\"coinType\": 0\n}"
"raw": ""
},
"description": ""
},
......
......@@ -359,7 +359,7 @@ namespace Breeze.Wallet.Controllers
/// <returns>An account name.</returns>
[Route("account")]
[HttpPost]
public IActionResult CreateNewAccount([FromBody]CreateAccountModel request)
public IActionResult CreateNewAccount([FromBody]GetUnusedAccountModel request)
{
// checks the request is valid
if (!this.ModelState.IsValid)
......@@ -370,22 +370,22 @@ namespace Breeze.Wallet.Controllers
try
{
var result = this.walletManager.CreateNewAccount(request.WalletName, request.CoinType, request.AccountName, request.Password);
return this.Json(result);
var result = this.walletManager.GetUnusedAccount(request.WalletName, request.CoinType, request.Password);
return this.Json(result.Name);
}
catch (Exception e)
{
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
/// <summary>
/// Creates a new address for a wallet.
/// Gets an unused address.
/// </summary>
/// <returns>An address in Base58 format.</returns>
/// <returns>The last created and unused address or creates a new address (in Base58 format).</returns>
[Route("address")]
[HttpPost]
public IActionResult CreateNewAddress([FromBody]CreateAddressModel request)
[HttpGet]
public IActionResult GetUnusedAddress([FromQuery]GetUnusedAddressModel request)
{
// checks the request is valid
if (!this.ModelState.IsValid)
......@@ -395,8 +395,8 @@ namespace Breeze.Wallet.Controllers
}
try
{
var result = this.walletManager.CreateNewAddress(request.WalletName, request.CoinType, request.AccountName);
{
var result = this.walletManager.GetUnusedAddress(request.WalletName, request.CoinType, request.AccountName);
return this.Json(result);
}
catch (Exception e)
......
......@@ -44,33 +44,58 @@ namespace Breeze.Wallet
Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTime? creationTime = null);
/// <summary>
/// Deleted a wallet.
/// Deletes a wallet.
/// </summary>
/// <param name="walletFilePath">The location of the wallet file.</param>
void DeleteWallet(string walletFilePath);
/// <summary>
/// Creates a new account.
/// Gets an account that contains no transactions.
/// </summary>
/// <param name="walletName">The name of the wallet in which this account will be created.</param>
/// <param name="coinType">the type of coin for which to create an account.</param>
/// <param name="accountName">The name by which this account will be identified.</param>
/// <param name="walletName">The name of the wallet from which to get an account.</param>
/// <param name="coinType">The type of coin for which to get an account.</param>
/// <param name="password">The password used to decrypt the private key.</param>
/// <remarks>
/// According to BIP44, an account at index (i) can only be created when the account
/// at index (i - 1) contains transactions.
/// </remarks>
/// <returns>The name of the new account.</returns>
string CreateNewAccount(string walletName, CoinType coinType, string accountName, string password);
/// <returns>An unused account.</returns>
HdAccount GetUnusedAccount(string walletName, CoinType coinType, string password);
/// <summary>
/// Creates the new address.
/// Gets an account that contains no transactions.
/// </summary>
/// <param name="wallet">The wallet from which to get an account.</param>
/// <param name="coinType">The type of coin for which to get an account.</param>
/// <param name="password">The password used to decrypt the private key.</param>
/// <remarks>
/// According to BIP44, an account at index (i) can only be created when the account
/// at index (i - 1) contains transactions.
/// </remarks>
/// <returns>An unused account.</returns>
HdAccount GetUnusedAccount(Wallet wallet, CoinType coinType, string password);
/// <summary>
/// Creates a new account.
/// </summary>
/// <param name="walletName">The name of the wallet in which this address will be created.</param>
/// <param name="wallet">The wallet in which this account will be created.</param>
/// <param name="coinType">The type of coin for which to create an account.</param>
/// <param name="accountName">The name of the account in which this address will be created.</param>
/// <returns>The new address, in Base58 format.</returns>
string CreateNewAddress(string walletName, CoinType coinType, string accountName);
/// <param name="password">The password used to decrypt the private key.</param>
/// <remarks>
/// According to BIP44, an account at index (i) can only be created when the account
/// at index (i - 1) contains transactions.
/// </remarks>
/// <returns>The new account.</returns>
HdAccount CreateNewAccount(Wallet wallet, CoinType coinType, string password);
/// <summary>
/// Gets an address that contains no transaction.
/// </summary>
/// <param name="walletName">The name of the wallet in which this address is contained.</param>
/// <param name="coinType">The type of coin for which to get the address.</param>
/// <param name="accountName">The name of the account in which this address is contained.</param>
/// <returns>An unused address or a newly created address, in Base58 format.</returns>
string GetUnusedAddress(string walletName, CoinType coinType, string accountName);
WalletGeneralInfoModel GetGeneralInfo(string walletName);
......@@ -101,6 +126,6 @@ namespace Breeze.Wallet
/// <param name="transaction">The transaction.</param>
/// <param name="blockHeight">The height of the block this transaction came from. Null if it was not a transaction included in a block.</param>
/// <param name="blockTime">The block time.</param>
void ProcessTransaction(CoinType coinType, NBitcoin.Transaction transaction, int? blockHeight = null, uint? blockTime = null);
void ProcessTransaction(CoinType coinType, NBitcoin.Transaction transaction, int? blockHeight = null, uint? blockTime = null);
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Breeze.Wallet.Models
{
public class CreateAccountModel
{
/// <summary>
/// The name of the wallet in which to create the account.
/// </summary>
[Required]
public string WalletName { get; set; }
/// <summary>
/// The type of coin this account contains.
/// </summary>
[Required]
public CoinType CoinType { get; set; }
/// <summary>
/// The name of the account.
/// </summary>
[Required]
public string AccountName { get; set; }
/// <summary>
/// The password for this wallet.
/// </summary>
[Required]
public string Password { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Breeze.Wallet.Models
{
public class CreateAddressModel
{
/// <summary>
/// The name of the wallet in which to create the address.
/// </summary>
[Required]
public string WalletName { get; set; }
/// <summary>
/// The type of coin this account contains.
/// </summary>
[Required]
public CoinType CoinType { get; set; }
/// <summary>
/// The name of the account in which to create the address.
/// </summary>
[Required]
public string AccountName { get; set; }
}
}
......@@ -100,4 +100,45 @@ namespace Breeze.Wallet.Models
public string Hex { get; set; }
}
public class GetUnusedAddressModel
{
/// <summary>
/// The name of the wallet from which to get the address.
/// </summary>
[Required]
public string WalletName { get; set; }
/// <summary>
/// The type of coin this address is for.
/// </summary>
[Required]
public CoinType CoinType { get; set; }
/// <summary>
/// The name of the account for which to get the address.
/// </summary>
[Required]
public string AccountName { get; set; }
}
public class GetUnusedAccountModel
{
/// <summary>
/// The name of the wallet in which to create the account.
/// </summary>
[Required]
public string WalletName { get; set; }
/// <summary>
/// The type of coin this account contains.
/// </summary>
[Required]
public CoinType CoinType { get; set; }
/// <summary>
/// The password for this wallet.
/// </summary>
[Required]
public string Password { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Breeze.Wallet.JsonConverters;
using NBitcoin;
using NBitcoin.JsonConverters;
......@@ -80,6 +81,23 @@ namespace Breeze.Wallet
/// </summary>
[JsonProperty(PropertyName = "accounts")]
public IEnumerable<HdAccount> Accounts { get; set; }
/// <summary>
/// Gets the first account that contains no transaction.
/// </summary>
/// <returns>An unused account</returns>
public HdAccount GetFirstUnusedAccount()
{
var unusedAccounts = this.Accounts.Where(acc => !acc.ExternalAddresses.Any() && !acc.InternalAddresses.Any()).ToList();
if (!unusedAccounts.Any())
{
return null;
}
// gets the unused account with the lowest index
var index = unusedAccounts.Min(a => a.Index);
return unusedAccounts.Single(a => a.Index == index);
}
}
/// <summary>
......@@ -125,7 +143,6 @@ namespace Breeze.Wallet
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
/// <summary>
/// A path to the account as defined in BIP44.
/// </summary>
......@@ -156,6 +173,34 @@ namespace Breeze.Wallet
/// </summary>
[JsonProperty(PropertyName = "internalAddresses")]
public IEnumerable<HdAddress> InternalAddresses { get; set; }
/// <summary>
/// Gets the type of coin this account is for.
/// </summary>
/// <returns>A <see cref="CoinType"/>.</returns>
public CoinType GetCoinType()
{
string[] pathElements = this.HdPath.Split('/');
int coinType = int.Parse(pathElements[2].Replace("'", string.Empty));
return (CoinType)coinType;
}
/// <summary>
/// Gets the first receiving address that contains no transaction.
/// </summary>
/// <returns>An unused address</returns>
public HdAddress GetFirstUnusedExternalAddress()
{
var unusedAddresses = this.ExternalAddresses.Where(acc => !acc.Transactions.Any()).ToList();
if (!unusedAddresses.Any())
{
return null;
}
// gets the unused address with the lowest index
var index = unusedAddresses.Min(a => a.Index);
return unusedAddresses.Single(a => a.Index == index);
}
}
/// <summary>
......
This diff is collapsed.
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