Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
Breeze
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DeStream-public
Breeze
Commits
e125985c
Commit
e125985c
authored
May 08, 2017
by
Jeremy Bokobza
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace method CreatenewAccount by GetUnusedAccount
parent
8e626ee6
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
132 additions
and
110 deletions
+132
-110
ApiSpecification.md
Breeze.Documentation/ApiSpecification.md
+3
-3
Wallet.postman_collection.json
...Api.Tests/Postman requests/Wallet.postman_collection.json
+4
-24
WalletController.cs
Breeze/src/Breeze.Wallet/Controllers/WalletController.cs
+4
-4
IWalletManager.cs
Breeze/src/Breeze.Wallet/IWalletManager.cs
+32
-7
CreateAccountModel.cs
Breeze/src/Breeze.Wallet/Models/CreateAccountModel.cs
+0
-36
RequestModels.cs
Breeze/src/Breeze.Wallet/Models/RequestModels.cs
+21
-0
Wallet.cs
Breeze/src/Breeze.Wallet/Wallet.cs
+18
-1
WalletManager.cs
Breeze/src/Breeze.Wallet/WalletManager.cs
+50
-35
No files found.
Breeze.Documentation/ApiSpecification.md
View file @
e125985c
...
...
@@ -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",
"password": "123456",
"coinType": 105
}
...
...
Breeze/src/Breeze.Api.Tests/Postman requests/Wallet.postman_collection.json
View file @
e125985c
...
...
@@ -208,7 +208,7 @@
"response"
:
[]
},
{
"name"
:
"
New account for non-existant wallet fails
"
,
"name"
:
"
Get unused account in wallet
"
,
"request"
:
{
"url"
:
"http://localhost:5000/api/v1/wallet/account"
,
"method"
:
"POST"
,
...
...
@@ -221,27 +221,7 @@
],
"body"
:
{
"mode"
:
"raw"
,
"raw"
:
"{
\n\t\"
walletName
\"
:
\"
myFirstWallet
\"
,
\n\t\"
accountName
\"
:
\"
account one
\"\n
}"
},
"description"
:
""
},
"response"
:
[]
},
{
"name"
:
"Create new account for wallet"
,
"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\t\"
password
\"
:
\"
123456
\"
,
\n\t\"
coinType
\"
: 105
\n
}"
"raw"
:
"{
\n\t\"
walletName
\"
:
\"
myFirstWallet
\"
,
\n\t\"
password
\"
:
\"
123456
\"
,
\n\t\"
coinType
\"
: 0
\n
}"
},
"description"
:
""
},
...
...
@@ -250,7 +230,7 @@
{
"name"
:
"Get unused address in wallet"
,
"request"
:
{
"url"
:
"http://localhost:5000/api/v1/wallet/address?walletName=wallet1&accountName=account
one
&coinType=0"
,
"url"
:
"http://localhost:5000/api/v1/wallet/address?walletName=wallet1&accountName=account
0
&coinType=0"
,
"method"
:
"GET"
,
"header"
:
[
{
...
...
Breeze/src/Breeze.Wallet/Controllers/WalletController.cs
View file @
e125985c
...
...
@@ -355,7 +355,7 @@ namespace Breeze.Wallet.Controllers
/// <returns>An account name.</returns>
[
Route
(
"account"
)]
[
HttpPost
]
public
IActionResult
CreateNewAccount
([
FromBody
]
Create
AccountModel
request
)
public
IActionResult
CreateNewAccount
([
FromBody
]
GetUnused
AccountModel
request
)
{
// checks the request is valid
if
(!
this
.
ModelState
.
IsValid
)
...
...
@@ -366,8 +366,8 @@ namespace Breeze.Wallet.Controllers
try
{
var
result
=
this
.
walletManager
.
CreateNewAccount
(
request
.
WalletName
,
request
.
CoinType
,
request
.
AccountNam
e
,
request
.
Password
);
return
this
.
Json
(
result
);
var
result
=
this
.
walletManager
.
GetUnusedAccount
(
request
.
WalletName
,
request
.
CoinTyp
e
,
request
.
Password
);
return
this
.
Json
(
result
.
Name
);
}
catch
(
Exception
e
)
{
...
...
Breeze/src/Breeze.Wallet/IWalletManager.cs
View file @
e125985c
...
...
@@ -44,24 +44,49 @@ namespace Breeze.Wallet
Wallet
RecoverWallet
(
string
password
,
string
folderPath
,
string
name
,
string
network
,
string
mnemonic
,
string
passphrase
=
null
,
DateTimeOffset
?
creationTime
=
null
);
/// <summary>
/// Delete
d
a wallet.
/// Delete
s
a wallet.
/// </summary>
/// <param name="walletFilePath">The location of the wallet file.</param>
void
DeleteWallet
(
string
walletFilePath
);
/// <summary>
/// Gets an account that contains no transactions.
/// </summary>
/// <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>An unused account.</returns>
HdAccount
GetUnusedAccount
(
string
walletName
,
CoinType
coinType
,
string
password
);
/// <summary>
/// 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 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="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="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 n
ame of the n
ew account.</returns>
string
CreateNewAccount
(
string
walletName
,
CoinType
coinType
,
string
accountNam
e
,
string
password
);
/// <returns>The new account.</returns>
HdAccount
CreateNewAccount
(
Wallet
wallet
,
CoinType
coinTyp
e
,
string
password
);
/// <summary>
/// Gets an address that contains no transaction.
...
...
Breeze/src/Breeze.Wallet/Models/CreateAccountModel.cs
deleted
100644 → 0
View file @
8e626ee6
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
;
}
}
}
Breeze/src/Breeze.Wallet/Models/RequestModels.cs
View file @
e125985c
...
...
@@ -114,4 +114,25 @@ namespace Breeze.Wallet.Models
[
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
;
}
}
}
Breeze/src/Breeze.Wallet/Wallet.cs
View file @
e125985c
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>
...
...
Breeze/src/Breeze.Wallet/WalletManager.cs
View file @
e125985c
...
...
@@ -53,7 +53,6 @@ namespace Breeze.Wallet
ExtKey
extendedKey
=
mnemonic
.
DeriveExtKey
(
passphrase
);
// create a wallet file
Wallet
wallet
=
this
.
GenerateWalletFile
(
password
,
folderPath
,
name
,
WalletHelpers
.
GetNetwork
(
network
),
extendedKey
);
this
.
Load
(
wallet
);
...
...
@@ -92,7 +91,7 @@ namespace Breeze.Wallet
}
/// <inheritdoc />
public
string
CreateNewAccount
(
string
walletName
,
CoinType
coinType
,
string
accountNam
e
,
string
password
)
public
HdAccount
GetUnusedAccount
(
string
walletName
,
CoinType
coinTyp
e
,
string
password
)
{
Wallet
wallet
=
this
.
Wallets
.
SingleOrDefault
(
w
=>
w
.
Name
==
walletName
);
if
(
wallet
==
null
)
...
...
@@ -100,28 +99,44 @@ namespace Breeze.Wallet
throw
new
Exception
(
$"No wallet with name
{
walletName
}
could be found."
);
}
// get the accounts for this type of coin
var
accounts
=
wallet
.
AccountsRoot
.
Single
(
a
=>
a
.
CoinType
==
coinType
).
Accounts
.
ToList
();
int
newAccountIndex
=
0
;
return
this
.
GetUnusedAccount
(
wallet
,
coinType
,
password
);
}
// validate account creation
if
(
accounts
.
Any
())
/// <inheritdoc />
public
HdAccount
GetUnusedAccount
(
Wallet
wallet
,
CoinType
coinType
,
string
password
)
{
// get the accounts root for this type of coin
var
accountsRoot
=
wallet
.
AccountsRoot
.
Single
(
a
=>
a
.
CoinType
==
coinType
);
// check if an unused account exists
if
(
accountsRoot
.
Accounts
.
Any
())
{
// check account with same name doesn't already exists
if
(
accounts
.
Any
(
a
=>
a
.
Name
==
accountName
))
// gets an unused account
var
firstUnusedAccount
=
accountsRoot
.
GetFirstUnusedAccount
();
if
(
firstUnusedAccount
!=
null
)
{
throw
new
Exception
(
$"Account with name '
{
accountName
}
' already exists in '
{
walletName
}
'."
);
return
firstUnusedAccount
;
}
}
// check account at index i - 1 contains transactions.
int
lastAccountIndex
=
accounts
.
Max
(
a
=>
a
.
Index
);
HdAccount
previousAccount
=
accounts
.
Single
(
a
=>
a
.
Index
==
lastAccountIndex
);
if
(!
previousAccount
.
ExternalAddresses
.
Any
(
addresses
=>
addresses
.
Transactions
.
Any
())
&&
!
previousAccount
.
InternalAddresses
.
Any
(
addresses
=>
addresses
.
Transactions
.
Any
()))
{
throw
new
Exception
(
$"Cannot create new account '
{
accountName
}
' in '
{
walletName
}
' if the previous account '
{
previousAccount
.
Name
}
' has not been used."
)
;
// all accounts contain transactions, create a new one
var
newAccount
=
this
.
CreateNewAccount
(
wallet
,
coinType
,
password
);
// save the changes to the file
this
.
SaveToFile
(
wallet
);
return
newAccount
;
}
newAccountIndex
=
lastAccountIndex
+
1
;
/// <inheritdoc />
public
HdAccount
CreateNewAccount
(
Wallet
wallet
,
CoinType
coinType
,
string
password
)
{
// get the accounts for this type of coin
var
accounts
=
wallet
.
AccountsRoot
.
Single
(
a
=>
a
.
CoinType
==
coinType
).
Accounts
.
ToList
();
int
newAccountIndex
=
0
;
if
(
accounts
.
Any
())
{
newAccountIndex
=
accounts
.
Max
(
a
=>
a
.
Index
)
+
1
;
}
// get the extended pub key used to generate addresses for this account
...
...
@@ -132,21 +147,21 @@ namespace Breeze.Wallet
ExtKey
accountExtKey
=
seedExtKey
.
Derive
(
keyPath
);
ExtPubKey
accountExtPubKey
=
accountExtKey
.
Neuter
();
accounts
.
Add
(
new
HdAccount
var
newAccount
=
new
HdAccount
{
Index
=
newAccountIndex
,
ExtendedPubKey
=
accountExtPubKey
.
ToString
(
wallet
.
Network
),
ExternalAddresses
=
new
List
<
HdAddress
>(),
InternalAddresses
=
new
List
<
HdAddress
>(),
Name
=
accountName
,
Name
=
$"account
{
newAccountIndex
}
"
,
HdPath
=
accountHdPath
,
CreationTime
=
DateTimeOffset
.
Now
}
)
;
};
accounts
.
Add
(
newAccount
);
wallet
.
AccountsRoot
.
Single
(
a
=>
a
.
CoinType
==
coinType
).
Accounts
=
accounts
;
this
.
SaveToFile
(
wallet
);
return
accountName
;
return
newAccount
;
}
/// <inheritdoc />
...
...
@@ -303,7 +318,7 @@ namespace Breeze.Wallet
{
foreach
(
var
account
in
accountRoot
.
Accounts
)
{
foreach
(
var
address
in
account
.
ExternalAddresses
.
Where
(
a
=>
a
.
ScriptPubKey
==
script
))
foreach
(
var
address
in
account
.
ExternalAddresses
)
//
.Where(a => a.ScriptPubKey == script))
{
address
.
Transactions
=
address
.
Transactions
.
Concat
(
new
[]
{
...
...
@@ -483,9 +498,9 @@ namespace Breeze.Wallet
SelectMany
(
w
=>
w
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
)).
SelectMany
(
a
=>
a
.
Accounts
).
SelectMany
(
a
=>
a
.
ExternalAddresses
).
Select
(
s
=>
s
.
ScriptPubKey
));
//
Select(s => s.ScriptPubKey));
// uncomment the following for testing on a random address
//
Select(t => (new BitcoinPubKeyAddress(t.Address, Network.Main)).ScriptPubKey));
Select
(
t
=>
(
new
BitcoinPubKeyAddress
(
t
.
Address
,
Network
.
Main
)).
ScriptPubKey
));
}
/// <summary>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment