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
a17f8ca6
Commit
a17f8ca6
authored
Apr 27, 2017
by
Jeremy Bokobza
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added Tracker object whose role is to figure out from where in the chain do we need to sync blocks.
parent
a48af926
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
322 additions
and
126 deletions
+322
-126
ChainExtensions.cs
Breeze/src/Breeze.Wallet/ChainExtensions.cs
+43
-0
WalletController.cs
Breeze/src/Breeze.Wallet/Controllers/WalletController.cs
+4
-15
ITracker.cs
Breeze/src/Breeze.Wallet/ITracker.cs
+20
-0
IWalletManager.cs
Breeze/src/Breeze.Wallet/IWalletManager.cs
+16
-1
BlockObserver.cs
Breeze/src/Breeze.Wallet/Notifications/BlockObserver.cs
+15
-16
TransactionObserver.cs
...ze/src/Breeze.Wallet/Notifications/TransactionObserver.cs
+15
-13
Tracker.cs
Breeze/src/Breeze.Wallet/Tracker.cs
+93
-0
Wallet.cs
Breeze/src/Breeze.Wallet/Wallet.cs
+19
-0
WalletFeature.cs
Breeze/src/Breeze.Wallet/WalletFeature.cs
+14
-15
WalletManager.cs
Breeze/src/Breeze.Wallet/WalletManager.cs
+83
-14
ITrackerWrapper.cs
Breeze/src/Breeze.Wallet/Wrappers/ITrackerWrapper.cs
+0
-13
TrackerWrapper.cs
Breeze/src/Breeze.Wallet/Wrappers/TrackerWrapper.cs
+0
-39
No files found.
Breeze/src/Breeze.Wallet/ChainExtensions.cs
0 → 100644
View file @
a17f8ca6
using
System
;
using
System.Collections.Generic
;
using
System.Text
;
using
NBitcoin
;
namespace
Breeze.Wallet
{
public
static
class
ChainExtensions
{
/// <summary>
/// Determines whether the chain is downloaded and up to date.
/// </summary>
/// <param name="chain">The chain.</param>
public
static
bool
IsDownloaded
(
this
ConcurrentChain
chain
)
{
return
chain
.
Tip
.
Header
.
BlockTime
.
ToUnixTimeSeconds
()
>
(
DateTimeOffset
.
Now
.
ToUnixTimeSeconds
()
-
TimeSpan
.
FromHours
(
1
).
TotalSeconds
);
}
/// <summary>
/// Gets the type of the coin this chain relates to.
/// Obviously this method and how we figure out what coin we're on needs to be revisited.
/// </summary>
/// <param name="chain">The chain.</param>
/// <returns></returns>
/// <exception cref="System.Exception">No support for this coin.</exception>
public
static
CoinType
GetCoinType
(
this
ConcurrentChain
chain
)
{
uint256
genesis
=
chain
.
Genesis
.
Header
.
GetHash
();
switch
(
genesis
.
ToString
())
{
case
"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
:
return
CoinType
.
Bitcoin
;
case
"b0e511e965aeb40614ca65a1b79bd6e4e7ef299fa23e575a64b079691e9d4690"
:
return
CoinType
.
Stratis
;
case
"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
:
return
CoinType
.
Testnet
;
default
:
throw
new
Exception
(
"No support for this coin."
);
}
}
}
}
Breeze/src/Breeze.Wallet/Controllers/WalletController.cs
View file @
a17f8ca6
...
@@ -2,12 +2,10 @@
...
@@ -2,12 +2,10 @@
using
System.IO
;
using
System.IO
;
using
System.Linq
;
using
System.Linq
;
using
System.Net
;
using
System.Net
;
using
System.Runtime.InteropServices
;
using
System.Security
;
using
System.Security
;
using
Breeze.Wallet.Errors
;
using
Breeze.Wallet.Errors
;
using
Microsoft.AspNetCore.Mvc
;
using
Microsoft.AspNetCore.Mvc
;
using
Breeze.Wallet.Models
;
using
Breeze.Wallet.Models
;
using
Breeze.Wallet.Wrappers
;
using
NBitcoin
;
using
NBitcoin
;
namespace
Breeze.Wallet.Controllers
namespace
Breeze.Wallet.Controllers
...
@@ -122,6 +120,9 @@ namespace Breeze.Wallet.Controllers
...
@@ -122,6 +120,9 @@ namespace Breeze.Wallet.Controllers
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
);
// TODO give the tracker the date at which this wallet was originally created so that it can start syncing blocks for it
return
this
.
Json
(
new
WalletModel
return
this
.
Json
(
new
WalletModel
{
{
Network
=
wallet
.
Network
.
Name
,
Network
=
wallet
.
Network
.
Name
,
...
@@ -372,23 +373,11 @@ namespace Breeze.Wallet.Controllers
...
@@ -372,23 +373,11 @@ namespace Breeze.Wallet.Controllers
{
{
if
(
string
.
IsNullOrEmpty
(
folderPath
))
if
(
string
.
IsNullOrEmpty
(
folderPath
))
{
{
folderPath
=
GetDefaultWalletFolderPath
();
folderPath
=
WalletManager
.
GetDefaultWalletFolderPath
();
}
}
return
Directory
.
CreateDirectory
(
folderPath
);
return
Directory
.
CreateDirectory
(
folderPath
);
}
}
/// <summary>
/// Gets the path of the default folder in which the wallets will be stored.
/// </summary>
/// <returns>The folder path for Windows, Linux or OSX systems.</returns>
private
static
string
GetDefaultWalletFolderPath
()
{
if
(
RuntimeInformation
.
IsOSPlatform
(
OSPlatform
.
Windows
))
{
return
$@"
{
Environment
.
GetEnvironmentVariable
(
"AppData"
)}
\Breeze"
;
}
return
$"
{
Environment
.
GetEnvironmentVariable
(
"HOME"
)}
/.breeze"
;
}
}
}
}
}
Breeze/src/Breeze.Wallet/ITracker.cs
0 → 100644
View file @
a17f8ca6
using
System.Threading.Tasks
;
using
NBitcoin
;
namespace
Breeze.Wallet
{
public
interface
ITracker
{
/// <summary>
/// Initializes the tracker.
/// </summary>
/// <returns></returns>
Task
Initialize
();
/// <summary>
/// Waits for the chain to download.
/// </summary>
/// <returns></returns>
Task
WaitForChainDownloadAsync
();
}
}
Breeze/src/Breeze.Wallet/IWalletManager.cs
View file @
a17f8ca6
...
@@ -66,7 +66,7 @@ namespace Breeze.Wallet
...
@@ -66,7 +66,7 @@ namespace Breeze.Wallet
/// Creates the new address.
/// Creates the new address.
/// </summary>
/// </summary>
/// <param name="walletName">The name of the wallet in which this address will be created.</param>
/// <param name="walletName">The name of the wallet in which this address will be created.</param>
/// <param name="coinType">
t
he type of coin for which to create an account.</param>
/// <param name="coinType">
T
he 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>
/// <param name="accountName">The name of the account in which this address will be created.</param>
/// <returns>The new address, in Base58 format.</returns>
/// <returns>The new address, in Base58 format.</returns>
string
CreateNewAddress
(
string
walletName
,
CoinType
coinType
,
string
accountName
);
string
CreateNewAddress
(
string
walletName
,
CoinType
coinType
,
string
accountName
);
...
@@ -80,5 +80,20 @@ namespace Breeze.Wallet
...
@@ -80,5 +80,20 @@ namespace Breeze.Wallet
WalletBuildTransactionModel
BuildTransaction
(
string
password
,
string
address
,
Money
amount
,
string
feeType
,
bool
allowUnconfirmed
);
WalletBuildTransactionModel
BuildTransaction
(
string
password
,
string
address
,
Money
amount
,
string
feeType
,
bool
allowUnconfirmed
);
bool
SendTransaction
(
string
transactionHex
);
bool
SendTransaction
(
string
transactionHex
);
/// <summary>
/// Processes a block received from the network.
/// </summary>
/// <param name="coinType">The type of coin this block relates to.</param>
/// <param name="height">The height of the block in the blockchain.</param>
/// <param name="block">The block.</param>
void
ProcessBlock
(
CoinType
coinType
,
int
height
,
Block
block
);
/// <summary>
/// Processes a transaction received from the network.
/// </summary>
/// <param name="coinType">The type of coin this transaction relates to.</param>
/// <param name="transaction">The transaction.</param>
void
ProcessTransaction
(
CoinType
coinType
,
NBitcoin
.
Transaction
transaction
);
}
}
}
}
Breeze/src/Breeze.Wallet/Notifications/BlockObserver.cs
View file @
a17f8ca6
using
NBitcoin
;
using
NBitcoin
;
using
Stratis.Bitcoin
;
using
Stratis.Bitcoin
;
using
Breeze.Wallet.Wrappers
;
using
Stratis.Bitcoin.Builder
;
namespace
Breeze.Wallet.Notifications
namespace
Breeze.Wallet.Notifications
{
{
...
@@ -9,27 +7,28 @@ namespace Breeze.Wallet.Notifications
...
@@ -9,27 +7,28 @@ namespace Breeze.Wallet.Notifications
/// Observer that receives notifications about the arrival of new <see cref="Block"/>s.
/// Observer that receives notifications about the arrival of new <see cref="Block"/>s.
/// </summary>
/// </summary>
public
class
BlockObserver
:
SignalObserver
<
Block
>
public
class
BlockObserver
:
SignalObserver
<
Block
>
{
{
private
readonly
ConcurrentChain
chain
;
private
readonly
ConcurrentChain
chain
;
private
readonly
CoinType
coinType
;
private
readonly
IWalletManager
walletManager
;
private
readonly
ITrackerWrapper
trackerWrapper
;
public
BlockObserver
(
ConcurrentChain
chain
,
CoinType
coinType
,
IWalletManager
walletManager
)
{
this
.
chain
=
chain
;
this
.
coinType
=
coinType
;
this
.
walletManager
=
walletManager
;
}
public
BlockObserver
(
ConcurrentChain
chain
,
ITrackerWrapper
trackerWrapper
)
{
this
.
chain
=
chain
;
this
.
trackerWrapper
=
trackerWrapper
;
}
/// <summary>
/// <summary>
/// Manages what happens when a new block is received.
/// Manages what happens when a new block is received.
/// </summary>
/// </summary>
/// <param name="block">The new block</param>
/// <param name="block">The new block</param>
protected
override
void
OnNextCore
(
Block
block
)
protected
override
void
OnNextCore
(
Block
block
)
{
{
var
hash
=
block
.
Header
.
GetHash
();
var
hash
=
block
.
Header
.
GetHash
();
var
height
=
this
.
chain
.
GetBlock
(
hash
).
Height
;
var
height
=
this
.
chain
.
GetBlock
(
hash
).
Height
;
this
.
trackerWrapper
.
NotifyAboutBlock
(
height
,
block
);
this
.
walletManager
.
ProcessBlock
(
this
.
coinType
,
height
,
block
);
}
}
}
}
}
}
Breeze/src/Breeze.Wallet/Notifications/TransactionObserver.cs
View file @
a17f8ca6
using
NBitcoin
;
using
NBitcoin
;
using
Stratis.Bitcoin
;
using
Stratis.Bitcoin
;
using
Breeze.Wallet.Wrappers
;
namespace
Breeze.Wallet.Notifications
namespace
Breeze.Wallet.Notifications
{
{
...
@@ -8,21 +7,24 @@ namespace Breeze.Wallet.Notifications
...
@@ -8,21 +7,24 @@ namespace Breeze.Wallet.Notifications
/// Observer that receives notifications about the arrival of new <see cref="Transaction"/>s.
/// Observer that receives notifications about the arrival of new <see cref="Transaction"/>s.
/// </summary>
/// </summary>
public
class
TransactionObserver
:
SignalObserver
<
Transaction
>
public
class
TransactionObserver
:
SignalObserver
<
Transaction
>
{
{
private
readonly
ITrackerWrapper
trackerWrapper
;
private
readonly
CoinType
coinType
;
private
readonly
IWalletManager
walletManager
;
public
TransactionObserver
(
CoinType
coinType
,
IWalletManager
walletManager
)
{
this
.
coinType
=
coinType
;
this
.
walletManager
=
walletManager
;
}
public
TransactionObserver
(
ITrackerWrapper
trackerWrapper
)
{
this
.
trackerWrapper
=
trackerWrapper
;
}
/// <summary>
/// <summary>
/// Manages what happens when a new transaction is received.
/// Manages what happens when a new transaction is received.
/// </summary>
/// </summary>
/// <param name="transaction">The new transaction</param>
/// <param name="transaction">The new transaction</param>
protected
override
void
OnNextCore
(
Transaction
transaction
)
protected
override
void
OnNextCore
(
Transaction
transaction
)
{
{
this
.
trackerWrapper
.
NotifyAboutTransaction
(
transaction
);
this
.
walletManager
.
ProcessTransaction
(
this
.
coinType
,
transaction
);
}
}
}
}
}
}
Breeze/src/Breeze.Wallet/Tracker.cs
0 → 100644
View file @
a17f8ca6
using
System
;
using
System.Collections.Generic
;
using
System.Collections.ObjectModel
;
using
System.Linq
;
using
System.Reactive.Linq
;
using
System.Text
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Breeze.Wallet.Notifications
;
using
NBitcoin
;
using
Stratis.Bitcoin
;
using
Stratis.Bitcoin.Notifications
;
using
Stratis.Bitcoin.Utilities
;
namespace
Breeze.Wallet
{
public
class
Tracker
:
ITracker
{
private
readonly
WalletManager
walletManager
;
private
readonly
ConcurrentChain
chain
;
private
readonly
Signals
signals
;
private
readonly
BlockNotification
blockNotification
;
private
readonly
CoinType
coinType
;
public
Tracker
(
IWalletManager
walletManager
,
ConcurrentChain
chain
,
Signals
signals
,
BlockNotification
blockNotification
)
{
this
.
walletManager
=
walletManager
as
WalletManager
;
this
.
chain
=
chain
;
this
.
signals
=
signals
;
this
.
blockNotification
=
blockNotification
;
this
.
coinType
=
chain
.
GetCoinType
();
}
/// <inheritdoc />
public
async
Task
Initialize
()
{
// get the chain headers. This needs to be up-to-date before we really do anything
await
this
.
WaitForChainDownloadAsync
();
// subscribe to receiving blocks and transactions
BlockSubscriber
sub
=
new
BlockSubscriber
(
this
.
signals
.
Blocks
,
new
BlockObserver
(
this
.
chain
,
this
.
coinType
,
this
.
walletManager
));
sub
.
Subscribe
();
TransactionSubscriber
txSub
=
new
TransactionSubscriber
(
this
.
signals
.
Transactions
,
new
TransactionObserver
(
this
.
coinType
,
this
.
walletManager
));
txSub
.
Subscribe
();
// start syncing blocks
this
.
blockNotification
.
SyncFrom
(
this
.
chain
.
GetBlock
(
this
.
FindBestHeightForSyncing
()).
HashBlock
);
}
private
int
FindBestHeightForSyncing
()
{
// if there are no wallets, get blocks from now
if
(!
this
.
walletManager
.
Wallets
.
Any
())
{
return
this
.
chain
.
Tip
.
Height
;
}
// sync the accounts with new blocks, starting from the most out of date
int
?
syncFromHeight
=
this
.
walletManager
.
Wallets
.
Min
(
w
=>
w
.
AccountsRoot
.
Single
(
a
=>
a
.
CoinType
==
this
.
coinType
).
LastBlockSyncedHeight
);
if
(
syncFromHeight
==
null
)
{
return
this
.
chain
.
Tip
.
Height
;
}
return
Math
.
Min
(
syncFromHeight
.
Value
,
this
.
chain
.
Tip
.
Height
);
}
/// <inheritdoc />
public
Task
WaitForChainDownloadAsync
()
{
// make sure the chain is downloaded
CancellationTokenSource
cancellationTokenSource
=
new
CancellationTokenSource
();
return
AsyncLoop
.
Run
(
"WalletFeature.DownloadChain"
,
token
=>
{
// wait until the chain is downloaded. We wait until a block is from an hour ago.
if
(
this
.
chain
.
IsDownloaded
())
{
cancellationTokenSource
.
Cancel
();
}
return
Task
.
CompletedTask
;
},
cancellationTokenSource
.
Token
,
repeatEvery
:
TimeSpans
.
FiveSeconds
);
}
private
bool
BlocksSynced
()
{
return
this
.
walletManager
.
Wallets
.
All
(
w
=>
w
.
AccountsRoot
.
Single
(
a
=>
a
.
CoinType
==
this
.
coinType
).
LastBlockSyncedHeight
==
this
.
chain
.
Tip
.
Height
);
}
}
}
Breeze/src/Breeze.Wallet/Wallet.cs
View file @
a17f8ca6
...
@@ -69,6 +69,12 @@ namespace Breeze.Wallet
...
@@ -69,6 +69,12 @@ namespace Breeze.Wallet
[
JsonProperty
(
PropertyName
=
"coinType"
)]
[
JsonProperty
(
PropertyName
=
"coinType"
)]
public
CoinType
CoinType
{
get
;
set
;
}
public
CoinType
CoinType
{
get
;
set
;
}
/// <summary>
/// The height of the last block that was synced.
/// </summary>
[
JsonProperty
(
PropertyName
=
"lastBlockSyncedHeight"
,
NullValueHandling
=
NullValueHandling
.
Ignore
)]
public
int
?
LastBlockSyncedHeight
{
get
;
set
;
}
/// <summary>
/// <summary>
/// The accounts used in the wallet.
/// The accounts used in the wallet.
/// </summary>
/// </summary>
...
@@ -79,9 +85,22 @@ namespace Breeze.Wallet
...
@@ -79,9 +85,22 @@ namespace Breeze.Wallet
/// <summary>
/// <summary>
/// The type of coin, as specified in BIP44.
/// The type of coin, as specified in BIP44.
/// </summary>
/// </summary>
/// <remarks>For more, see https://github.com/satoshilabs/slips/blob/master/slip-0044.md</remarks>
public
enum
CoinType
public
enum
CoinType
{
{
/// <summary>
/// Bitcoin
/// </summary>
Bitcoin
=
0
,
Bitcoin
=
0
,
/// <summary>
/// Testnet (all coins)
/// </summary>
Testnet
=
1
,
/// <summary>
/// Stratis
/// </summary>
Stratis
=
105
Stratis
=
105
}
}
...
...
Breeze/src/Breeze.Wallet/WalletFeature.cs
View file @
a17f8ca6
using
Stratis.Bitcoin.Builder.Feature
;
using
Stratis.Bitcoin.Builder.Feature
;
using
Breeze.Wallet.Controllers
;
using
Breeze.Wallet.Controllers
;
using
Breeze.Wallet.Notifications
;
using
Breeze.Wallet.Wrappers
;
using
Microsoft.Extensions.DependencyInjection
;
using
Microsoft.Extensions.DependencyInjection
;
using
NBitcoin
;
using
NBitcoin
;
using
Stratis.Bitcoin
;
using
Stratis.Bitcoin
;
...
@@ -11,23 +9,24 @@ namespace Breeze.Wallet
...
@@ -11,23 +9,24 @@ namespace Breeze.Wallet
{
{
public
class
WalletFeature
:
FullNodeFeature
public
class
WalletFeature
:
FullNodeFeature
{
{
private
readonly
ITrackerWrapper
trackerWrapper
;
private
readonly
ITracker
tracker
;
private
readonly
Signals
signals
;
private
readonly
IWalletManager
walletManager
;
private
readonly
ConcurrentChain
chain
;
public
WalletFeature
(
ITracker
tracker
,
IWalletManager
walletManager
)
public
WalletFeature
(
ITrackerWrapper
trackerWrapper
,
Signals
signals
,
ConcurrentChain
chain
)
{
{
this
.
trackerWrapper
=
trackerWrapper
;
this
.
tracker
=
tracker
;
this
.
signals
=
signals
;
this
.
walletManager
=
walletManager
;
this
.
chain
=
chain
;
}
}
public
override
void
Start
()
public
override
void
Start
()
{
this
.
tracker
.
Initialize
();
}
public
override
void
Stop
()
{
{
BlockSubscriber
sub
=
new
BlockSubscriber
(
signals
.
Blocks
,
new
BlockObserver
(
chain
,
trackerWrapper
));
this
.
walletManager
.
Dispose
();
sub
.
Subscribe
();
base
.
Stop
();
TransactionSubscriber
txSub
=
new
TransactionSubscriber
(
signals
.
Transactions
,
new
TransactionObserver
(
trackerWrapper
));
txSub
.
Subscribe
();
}
}
}
}
...
@@ -41,7 +40,7 @@ namespace Breeze.Wallet
...
@@ -41,7 +40,7 @@ namespace Breeze.Wallet
.
AddFeature
<
WalletFeature
>()
.
AddFeature
<
WalletFeature
>()
.
FeatureServices
(
services
=>
.
FeatureServices
(
services
=>
{
{
services
.
AddSingleton
<
ITracker
Wrapper
,
TrackerWrapp
er
>();
services
.
AddSingleton
<
ITracker
,
Track
er
>();
services
.
AddSingleton
<
IWalletManager
,
WalletManager
>();
services
.
AddSingleton
<
IWalletManager
,
WalletManager
>();
services
.
AddSingleton
<
WalletController
>();
services
.
AddSingleton
<
WalletController
>();
});
});
...
...
Breeze/src/Breeze.Wallet/WalletManager.cs
View file @
a17f8ca6
...
@@ -2,11 +2,12 @@
...
@@ -2,11 +2,12 @@
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.IO
;
using
System.Linq
;
using
System.Linq
;
using
System.Runtime.InteropServices
;
using
Breeze.Wallet.Helpers
;
using
Breeze.Wallet.Helpers
;
using
Breeze.Wallet.Models
;
using
Breeze.Wallet.Models
;
using
NBitcoin
;
using
NBitcoin
;
using
Newtonsoft.Json
;
using
Newtonsoft.Json
;
using
Stratis.Bitcoin.Utilities
;
using
Transaction
=
NBitcoin
.
Transaction
;
namespace
Breeze.Wallet
namespace
Breeze.Wallet
{
{
...
@@ -16,10 +17,16 @@ namespace Breeze.Wallet
...
@@ -16,10 +17,16 @@ namespace Breeze.Wallet
public
class
WalletManager
:
IWalletManager
public
class
WalletManager
:
IWalletManager
{
{
public
List
<
Wallet
>
Wallets
{
get
;
}
public
List
<
Wallet
>
Wallets
{
get
;
}
public
WalletManager
()
public
WalletManager
()
{
{
this
.
Wallets
=
new
List
<
Wallet
>();
this
.
Wallets
=
new
List
<
Wallet
>();
// find wallets and load them in memory
foreach
(
var
path
in
this
.
GetWalletFilesPaths
())
{
this
.
Load
(
this
.
GetWallet
(
path
));
}
}
}
/// <inheritdoc />
/// <inheritdoc />
...
@@ -37,6 +44,7 @@ namespace Breeze.Wallet
...
@@ -37,6 +44,7 @@ namespace Breeze.Wallet
ExtKey
extendedKey
=
mnemonic
.
DeriveExtKey
(
passphrase
);
ExtKey
extendedKey
=
mnemonic
.
DeriveExtKey
(
passphrase
);
// create a wallet file
// create a wallet file
Wallet
wallet
=
this
.
GenerateWalletFile
(
password
,
folderPath
,
name
,
WalletHelpers
.
GetNetwork
(
network
),
extendedKey
);
Wallet
wallet
=
this
.
GenerateWalletFile
(
password
,
folderPath
,
name
,
WalletHelpers
.
GetNetwork
(
network
),
extendedKey
);
this
.
Load
(
wallet
);
this
.
Load
(
wallet
);
...
@@ -48,11 +56,8 @@ namespace Breeze.Wallet
...
@@ -48,11 +56,8 @@ namespace Breeze.Wallet
{
{
string
walletFilePath
=
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
);
string
walletFilePath
=
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
);
if
(!
File
.
Exists
(
walletFilePath
))
throw
new
FileNotFoundException
(
$"No wallet file found at
{
walletFilePath
}
"
);
// load the file from the local system
// load the file from the local system
Wallet
wallet
=
JsonConvert
.
DeserializeObject
<
Wallet
>(
File
.
ReadAllText
(
walletFilePath
)
);
Wallet
wallet
=
this
.
GetWallet
(
walletFilePath
);
this
.
Load
(
wallet
);
this
.
Load
(
wallet
);
return
wallet
;
return
wallet
;
...
@@ -199,8 +204,7 @@ namespace Breeze.Wallet
...
@@ -199,8 +204,7 @@ namespace Breeze.Wallet
throw
new
System
.
NotImplementedException
();
throw
new
System
.
NotImplementedException
();
}
}
public
WalletBuildTransactionModel
BuildTransaction
(
string
password
,
string
address
,
Money
amount
,
string
feeType
,
public
WalletBuildTransactionModel
BuildTransaction
(
string
password
,
string
address
,
Money
amount
,
string
feeType
,
bool
allowUnconfirmed
)
bool
allowUnconfirmed
)
{
{
throw
new
System
.
NotImplementedException
();
throw
new
System
.
NotImplementedException
();
}
}
...
@@ -210,6 +214,27 @@ namespace Breeze.Wallet
...
@@ -210,6 +214,27 @@ namespace Breeze.Wallet
throw
new
System
.
NotImplementedException
();
throw
new
System
.
NotImplementedException
();
}
}
/// <inheritdoc />
public
void
ProcessBlock
(
CoinType
coinType
,
int
height
,
Block
block
)
{
Console
.
WriteLine
(
$"block notification: height:
{
height
}
, block hash:
{
block
.
Header
.
GetHash
()}
, coin type:
{
coinType
}
"
);
// update the wallets with the last processed block height
foreach
(
var
wallet
in
this
.
Wallets
)
{
foreach
(
var
accountRoot
in
wallet
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
))
{
accountRoot
.
LastBlockSyncedHeight
=
height
;
}
}
}
/// <inheritdoc />
public
void
ProcessTransaction
(
CoinType
coinType
,
Transaction
transaction
)
{
Console
.
WriteLine
(
$"transaction notification: tx hash
{
transaction
.
GetHash
()}
, coin type:
{
coinType
}
"
);
}
/// <inheritdoc />
/// <inheritdoc />
public
void
DeleteWallet
(
string
walletFilePath
)
public
void
DeleteWallet
(
string
walletFilePath
)
{
{
...
@@ -219,7 +244,11 @@ namespace Breeze.Wallet
...
@@ -219,7 +244,11 @@ namespace Breeze.Wallet
/// <inheritdoc />
/// <inheritdoc />
public
void
Dispose
()
public
void
Dispose
()
{
{
// TODO Safely persist the wallet before disposing
// safely persist the wallets to the file system before disposing
foreach
(
var
wallet
in
this
.
Wallets
)
{
this
.
SaveToFile
(
wallet
);
}
}
}
/// <summary>
/// <summary>
...
@@ -230,7 +259,6 @@ namespace Breeze.Wallet
...
@@ -230,7 +259,6 @@ namespace Breeze.Wallet
/// <param name="name">The name of the wallet.</param>
/// <param name="name">The name of the wallet.</param>
/// <param name="network">The network this wallet is for.</param>
/// <param name="network">The network this wallet is for.</param>
/// <param name="extendedKey">The root key used to generate keys.</param>
/// <param name="extendedKey">The root key used to generate keys.</param>
/// <param name="coinType">The type of coin for which this wallet is created.</param>
/// <param name="creationTime">The time this wallet was created.</param>
/// <param name="creationTime">The time this wallet was created.</param>
/// <returns></returns>
/// <returns></returns>
/// <exception cref="System.NotSupportedException"></exception>
/// <exception cref="System.NotSupportedException"></exception>
...
@@ -250,8 +278,10 @@ namespace Breeze.Wallet
...
@@ -250,8 +278,10 @@ namespace Breeze.Wallet
Network
=
network
,
Network
=
network
,
AccountsRoot
=
new
List
<
AccountRoot
>
{
AccountsRoot
=
new
List
<
AccountRoot
>
{
new
AccountRoot
{
Accounts
=
new
List
<
HdAccount
>(),
CoinType
=
CoinType
.
Bitcoin
},
new
AccountRoot
{
Accounts
=
new
List
<
HdAccount
>(),
CoinType
=
CoinType
.
Bitcoin
},
new
AccountRoot
{
Accounts
=
new
List
<
HdAccount
>(),
CoinType
=
CoinType
.
Testnet
},
new
AccountRoot
{
Accounts
=
new
List
<
HdAccount
>(),
CoinType
=
CoinType
.
Stratis
}
},
new
AccountRoot
{
Accounts
=
new
List
<
HdAccount
>(),
CoinType
=
CoinType
.
Stratis
}
},
WalletFilePath
=
walletFilePath
WalletFilePath
=
walletFilePath
,
};
};
// create a folder if none exists and persist the file
// create a folder if none exists and persist the file
...
@@ -270,16 +300,33 @@ namespace Breeze.Wallet
...
@@ -270,16 +300,33 @@ namespace Breeze.Wallet
File
.
WriteAllText
(
wallet
.
WalletFilePath
,
JsonConvert
.
SerializeObject
(
wallet
,
Formatting
.
Indented
));
File
.
WriteAllText
(
wallet
.
WalletFilePath
,
JsonConvert
.
SerializeObject
(
wallet
,
Formatting
.
Indented
));
}
}
/// <summary>
/// Gets the wallet located at the specified path.
/// </summary>
/// <param name="walletFilePath">The wallet file path.</param>
/// <returns></returns>
/// <exception cref="System.IO.FileNotFoundException"></exception>
private
Wallet
GetWallet
(
string
walletFilePath
)
{
if
(!
File
.
Exists
(
walletFilePath
))
throw
new
FileNotFoundException
(
$"No wallet file found at
{
walletFilePath
}
"
);
// load the file from the local system
return
JsonConvert
.
DeserializeObject
<
Wallet
>(
File
.
ReadAllText
(
walletFilePath
));
}
/// <summary>
/// <summary>
/// Loads the wallet to be used by the manager.
/// Loads the wallet to be used by the manager.
/// </summary>
/// </summary>
/// <param name="wallet">The wallet to load.</param>
/// <param name="wallet">The wallet to load.</param>
private
void
Load
(
Wallet
wallet
)
private
void
Load
(
Wallet
wallet
)
{
{
if
(
this
.
Wallets
.
A
ll
(
w
=>
w
.
Name
!
=
wallet
.
Name
))
if
(
this
.
Wallets
.
A
ny
(
w
=>
w
.
Name
=
=
wallet
.
Name
))
{
{
this
.
Wallets
.
Add
(
wallet
)
;
return
;
}
}
this
.
Wallets
.
Add
(
wallet
);
}
}
private
BitcoinPubKeyAddress
GenerateAddress
(
string
accountExtPubKey
,
int
index
,
bool
isChange
,
Network
network
)
private
BitcoinPubKeyAddress
GenerateAddress
(
string
accountExtPubKey
,
int
index
,
bool
isChange
,
Network
network
)
...
@@ -290,6 +337,14 @@ namespace Breeze.Wallet
...
@@ -290,6 +337,14 @@ namespace Breeze.Wallet
return
extPubKey
.
PubKey
.
GetAddress
(
network
);
return
extPubKey
.
PubKey
.
GetAddress
(
network
);
}
}
private
IEnumerable
<
string
>
GetWalletFilesPaths
()
{
// TODO look in user-chosen folder as well.
// maybe the api can maintain a list of wallet paths it knows about
var
defaultFolderPath
=
GetDefaultWalletFolderPath
();
return
Directory
.
EnumerateFiles
(
defaultFolderPath
,
"*.json"
,
SearchOption
.
TopDirectoryOnly
);
}
/// <summary>
/// <summary>
/// Creates the bip44 path.
/// Creates the bip44 path.
/// </summary>
/// </summary>
...
@@ -306,5 +361,19 @@ namespace Breeze.Wallet
...
@@ -306,5 +361,19 @@ namespace Breeze.Wallet
int
change
=
isChange
?
1
:
0
;
int
change
=
isChange
?
1
:
0
;
return
$"m/44'/
{(
int
)
coinType
}
'/
{
accountIndex
}
'/
{
change
}
/
{
addressIndex
}
"
;
return
$"m/44'/
{(
int
)
coinType
}
'/
{
accountIndex
}
'/
{
change
}
/
{
addressIndex
}
"
;
}
}
/// <summary>
/// Gets the path of the default folder in which the wallets will be stored.
/// </summary>
/// <returns>The folder path for Windows, Linux or OSX systems.</returns>
public
static
string
GetDefaultWalletFolderPath
()
{
if
(
RuntimeInformation
.
IsOSPlatform
(
OSPlatform
.
Windows
))
{
return
$@"
{
Environment
.
GetEnvironmentVariable
(
"AppData"
)}
\Breeze"
;
}
return
$"
{
Environment
.
GetEnvironmentVariable
(
"HOME"
)}
/.breeze"
;
}
}
}
}
}
Breeze/src/Breeze.Wallet/Wrappers/ITrackerWrapper.cs
deleted
100644 → 0
View file @
a48af926
using
NBitcoin
;
namespace
Breeze.Wallet.Wrappers
{
public
interface
ITrackerWrapper
{
void
NotifyAboutBlock
(
int
height
,
Block
block
);
void
NotifyAboutTransaction
(
Transaction
transaction
);
uint256
GetLastProcessedBlock
();
}
}
Breeze/src/Breeze.Wallet/Wrappers/TrackerWrapper.cs
deleted
100644 → 0
View file @
a48af926
using
NBitcoin
;
using
System
;
namespace
Breeze.Wallet.Wrappers
{
public
class
TrackerWrapper
:
ITrackerWrapper
{
// private readonly Tracker tracker;
public
TrackerWrapper
(
Network
network
)
{
//this.tracker = new Tracker(network);
}
/// <summary>
/// Get the hash of the last block that has been succesfully processed.
/// </summary>
/// <returns>The hash of the block</returns>
public
uint256
GetLastProcessedBlock
()
{
// TODO use Tracker.BestHeight. Genesis hash for now.
return
uint256
.
Parse
(
"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
);
}
public
void
NotifyAboutBlock
(
int
height
,
Block
block
)
{
// this.tracker.AddOrReplaceBlock(new Height(height), block);
Console
.
WriteLine
(
$"block notification: height:
{
height
}
, block hash:
{
block
.
Header
.
GetHash
()}
"
);
}
public
void
NotifyAboutTransaction
(
Transaction
transaction
)
{
// TODO what should the height be? is it necessary?
// this.tracker.ProcessTransaction(new SmartTransaction(transaction, new Height(0)));
Console
.
WriteLine
(
$"transaction notification: tx hash
{
transaction
.
GetHash
()}
"
);
}
}
}
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