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
135a3452
Commit
135a3452
authored
May 10, 2017
by
Pieterjan Vanhoof
Committed by
GitHub
May 10, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #44 from bokobza/feature/build-transaction
Feature/build transaction
parents
823f271e
d520c752
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
145 additions
and
49 deletions
+145
-49
.gitignore
.gitignore
+1
-1
Breeze.sln
Breeze/Breeze.sln
+1
-1
Breeze.Api.csproj
Breeze/src/Breeze.Api/Breeze.Api.csproj
+1
-1
Breeze.Daemon.csproj
Breeze/src/Breeze.Daemon/Breeze.Daemon.csproj
+2
-2
Program.cs
Breeze/src/Breeze.Daemon/Program.cs
+1
-1
AssemblyInfo.cs
Breeze/src/Breeze.Daemon/Properties/AssemblyInfo.cs
+1
-1
Breeze.Wallet.csproj
Breeze/src/Breeze.Wallet/Breeze.Wallet.csproj
+1
-1
WalletController.cs
Breeze/src/Breeze.Wallet/Controllers/WalletController.cs
+4
-3
IWalletManager.cs
Breeze/src/Breeze.Wallet/IWalletManager.cs
+18
-2
Wallet.cs
Breeze/src/Breeze.Wallet/Wallet.cs
+47
-9
WalletManager.cs
Breeze/src/Breeze.Wallet/WalletManager.cs
+68
-27
No files found.
.gitignore
View file @
135a3452
...
...
@@ -295,4 +295,4 @@ Thumbs.db
# DNX
project.lock.json
/Breeze/src/Breeze.D
ea
mon/Wallets
/Breeze/src/Breeze.D
ae
mon/Wallets
Breeze/Breeze.sln
View file @
135a3452
...
...
@@ -17,7 +17,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Breeze.Api.Tests", "src\Bre
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Breeze.Wallet", "src\Breeze.Wallet\Breeze.Wallet.csproj", "{D16CD478-9D1E-4C69-91AD-43539E94A215}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Breeze.D
eamon", "src\Breeze.Deamon\Breeze.Dea
mon.csproj", "{1B598E33-667F-496D-BC0D-88276E8E7632}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Breeze.D
aemon", "src\Breeze.Daemon\Breeze.Dae
mon.csproj", "{1B598E33-667F-496D-BC0D-88276E8E7632}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
...
...
Breeze/src/Breeze.Api/Breeze.Api.csproj
View file @
135a3452
...
...
@@ -12,7 +12,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\\Breeze.D
ea
mon\\bin\\Debug\\netcoreapp1.0\\Breeze.Api.xml</DocumentationFile>
<DocumentationFile>..\\Breeze.D
ae
mon\\bin\\Debug\\netcoreapp1.0\\Breeze.Api.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
...
...
Breeze/src/Breeze.D
eamon/Breeze.Dea
mon.csproj
→
Breeze/src/Breeze.D
aemon/Breeze.Dae
mon.csproj
View file @
135a3452
...
...
@@ -2,9 +2,9 @@
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<AssemblyName>Breeze.D
ea
mon</AssemblyName>
<AssemblyName>Breeze.D
ae
mon</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>Breeze.D
ea
mon</PackageId>
<PackageId>Breeze.D
ae
mon</PackageId>
<RuntimeFrameworkVersion>1.1.1</RuntimeFrameworkVersion>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
...
...
Breeze/src/Breeze.D
ea
mon/Program.cs
→
Breeze/src/Breeze.D
ae
mon/Program.cs
View file @
135a3452
...
...
@@ -9,7 +9,7 @@ using Stratis.Bitcoin.Logging;
using
Breeze.Wallet
;
using
Stratis.Bitcoin.Notifications
;
namespace
Breeze.D
ea
mon
namespace
Breeze.D
ae
mon
{
public
class
Program
{
...
...
Breeze/src/Breeze.D
ea
mon/Properties/AssemblyInfo.cs
→
Breeze/src/Breeze.D
ae
mon/Properties/AssemblyInfo.cs
View file @
135a3452
...
...
@@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Breeze.D
ea
mon")]
[assembly: AssemblyProduct("Breeze.D
ae
mon")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
...
...
Breeze/src/Breeze.Wallet/Breeze.Wallet.csproj
View file @
135a3452
...
...
@@ -12,7 +12,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\\Breeze.D
ea
mon\\bin\\Debug\\netcoreapp1.0\\Breeze.Wallet.xml</DocumentationFile>
<DocumentationFile>..\\Breeze.D
ae
mon\\bin\\Debug\\netcoreapp1.0\\Breeze.Wallet.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
...
...
Breeze/src/Breeze.Wallet/Controllers/WalletController.cs
View file @
135a3452
...
...
@@ -198,8 +198,9 @@ namespace Breeze.Wallet.Controllers
{
WalletHistoryModel
model
=
new
WalletHistoryModel
{
Transactions
=
new
List
<
TransactionItem
>()
};
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
)))
// get transactions contained in the wallet
var
addresses
=
this
.
walletManager
.
GetHistoryByCoinType
(
request
.
WalletName
,
request
.
CoinType
);
foreach
(
var
address
in
addresses
)
{
foreach
(
var
transaction
in
address
.
Transactions
)
{
...
...
@@ -213,7 +214,7 @@ namespace Breeze.Wallet.Controllers
});
}
}
model
.
Transactions
=
model
.
Transactions
.
OrderByDescending
(
t
=>
t
.
Timestamp
).
ToList
();
return
this
.
Json
(
model
);
}
...
...
Breeze/src/Breeze.Wallet/IWalletManager.cs
View file @
135a3452
...
...
@@ -74,7 +74,7 @@ namespace Breeze.Wallet
/// </remarks>
/// <returns>An unused account.</returns>
HdAccount
GetUnusedAccount
(
Wallet
wallet
,
CoinType
coinType
,
string
password
);
/// <summary>
/// Creates a new account.
/// </summary>
...
...
@@ -97,6 +97,22 @@ namespace Breeze.Wallet
/// <returns>An unused address or a newly created address, in Base58 format.</returns>
string
GetUnusedAddress
(
string
walletName
,
CoinType
coinType
,
string
accountName
);
/// <summary>
/// Gets a collection of addresses containing transactions for this coin.
/// </summary>
/// <param name="walletName">The name of the wallet to get history from.</param>
/// <param name="coinType">Type of the coin.</param>
/// <returns></returns>
IEnumerable
<
HdAddress
>
GetHistoryByCoinType
(
string
walletName
,
CoinType
coinType
);
/// <summary>
/// Gets a collection of addresses containing transactions for this coin.
/// </summary>
/// <param name="wallet">The wallet to get history from.</param>
/// <param name="coinType">Type of the coin.</param>
/// <returns></returns>
IEnumerable
<
HdAddress
>
GetHistoryByCoinType
(
Wallet
wallet
,
CoinType
coinType
);
WalletGeneralInfoModel
GetGeneralInfo
(
string
walletName
);
/// <summary>
...
...
@@ -126,6 +142,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
);
}
}
Breeze/src/Breeze.Wallet/Wallet.cs
View file @
135a3452
...
...
@@ -57,6 +57,33 @@ namespace Breeze.Wallet
/// </summary>
[
JsonProperty
(
PropertyName
=
"accountsRoot"
)]
public
IEnumerable
<
AccountRoot
>
AccountsRoot
{
get
;
set
;
}
/// <summary>
/// Gets the type of the accounts by coin.
/// </summary>
/// <param name="coinType">Type of the coin.</param>
/// <returns></returns>
public
IEnumerable
<
HdAccount
>
GetAccountsByCoinType
(
CoinType
coinType
)
{
return
this
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
).
SelectMany
(
a
=>
a
.
Accounts
);
}
/// <summary>
/// Gets all the transactions by coin type.
/// </summary>
/// <param name="coinType">Type of the coin.</param>
/// <returns></returns>
public
IEnumerable
<
TransactionData
>
GetAllTransactionsByCoinType
(
CoinType
coinType
)
{
List
<
TransactionData
>
result
=
new
List
<
TransactionData
>();
var
accounts
=
this
.
GetAccountsByCoinType
(
coinType
).
ToList
();
foreach
(
var
address
in
accounts
.
SelectMany
(
a
=>
a
.
ExternalAddresses
).
Concat
(
accounts
.
SelectMany
(
a
=>
a
.
InternalAddresses
)))
{
result
.
AddRange
(
address
.
Transactions
);
}
return
result
;
}
}
/// <summary>
...
...
@@ -219,7 +246,18 @@ namespace Breeze.Wallet
// gets the used address with the highest index
var
index
=
usedAddresses
.
Max
(
a
=>
a
.
Index
);
return
usedAddresses
.
Single
(
a
=>
a
.
Index
==
index
);
}
}
/// <summary>
/// Gets a collection of transactions by id.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns></returns>
public
IEnumerable
<
TransactionData
>
GetTransactionsById
(
uint256
id
)
{
var
addresses
=
this
.
ExternalAddresses
.
Concat
(
this
.
InternalAddresses
);
return
addresses
.
SelectMany
(
a
=>
a
.
Transactions
.
Where
(
t
=>
t
.
Id
==
id
));
}
}
/// <summary>
...
...
@@ -232,14 +270,7 @@ namespace Breeze.Wallet
/// </summary>
[
JsonProperty
(
PropertyName
=
"index"
)]
public
int
Index
{
get
;
set
;
}
/// <summary>
/// Gets or sets the creation time.
/// </summary>
[
JsonProperty
(
PropertyName
=
"creationTime"
)]
[
JsonConverter
(
typeof
(
DateTimeOffsetConverter
))]
public
DateTimeOffset
CreationTime
{
get
;
set
;
}
/// <summary>
/// The script pub key for this address.
/// </summary>
...
...
@@ -284,6 +315,13 @@ namespace Breeze.Wallet
[
JsonConverter
(
typeof
(
UInt256JsonConverter
))]
public
uint256
Id
{
get
;
set
;
}
/// <summary>
/// The id of the transaction in which the output referenced in this transaction is spent.
/// </summary>
[
JsonProperty
(
PropertyName
=
"spentIn"
,
NullValueHandling
=
NullValueHandling
.
Ignore
)]
[
JsonConverter
(
typeof
(
UInt256JsonConverter
))]
public
uint256
SpentInTransaction
{
get
;
set
;
}
/// <summary>
/// The transaction amount.
/// </summary>
...
...
Breeze/src/Breeze.Wallet/WalletManager.cs
View file @
135a3452
...
...
@@ -40,14 +40,14 @@ namespace Breeze.Wallet
// find wallets and load them in memory
foreach
(
var
path
in
this
.
GetWalletFilesPaths
())
{
this
.
Load
(
this
.
Get
Wallet
(
path
));
this
.
Load
(
this
.
Deserialize
Wallet
(
path
));
}
// load data in memory for faster lookups
// TODO get the coin type from somewhere else
this
.
PubKeys
=
this
.
LoadKeys
(
CoinType
.
Bitcoin
);
this
.
TrackedTransactions
=
this
.
LoadTransactions
(
CoinType
.
Bitcoin
);
this
.
TransactionFound
+=
this
.
OnTransactionFound
;
this
.
TransactionFound
+=
this
.
OnTransactionFound
;
}
/// <inheritdoc />
...
...
@@ -91,7 +91,7 @@ namespace Breeze.Wallet
string
walletFilePath
=
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
);
// load the file from the local system
Wallet
wallet
=
this
.
Get
Wallet
(
walletFilePath
);
Wallet
wallet
=
this
.
Deserialize
Wallet
(
walletFilePath
);
this
.
Load
(
wallet
);
return
wallet
;
...
...
@@ -133,11 +133,7 @@ namespace Breeze.Wallet
/// <inheritdoc />
public
HdAccount
GetUnusedAccount
(
string
walletName
,
CoinType
coinType
,
string
password
)
{
Wallet
wallet
=
this
.
Wallets
.
SingleOrDefault
(
w
=>
w
.
Name
==
walletName
);
if
(
wallet
==
null
)
{
throw
new
Exception
(
$"No wallet with name
{
walletName
}
could be found."
);
}
Wallet
wallet
=
this
.
GetWalletByName
(
walletName
);
return
this
.
GetUnusedAccount
(
wallet
,
coinType
,
password
);
}
...
...
@@ -207,11 +203,7 @@ namespace Breeze.Wallet
/// <inheritdoc />
public
string
GetUnusedAddress
(
string
walletName
,
CoinType
coinType
,
string
accountName
)
{
Wallet
wallet
=
this
.
Wallets
.
SingleOrDefault
(
w
=>
w
.
Name
==
walletName
);
if
(
wallet
==
null
)
{
throw
new
Exception
(
$"No wallet with name
{
walletName
}
could be found."
);
}
Wallet
wallet
=
this
.
GetWalletByName
(
walletName
);
// get the account
HdAccount
account
=
wallet
.
AccountsRoot
.
Single
(
a
=>
a
.
CoinType
==
coinType
).
Accounts
.
SingleOrDefault
(
a
=>
a
.
Name
==
accountName
);
...
...
@@ -242,6 +234,28 @@ namespace Breeze.Wallet
return
account
.
GetFirstUnusedExternalAddress
().
Address
;
}
/// <inheritdoc />
public
IEnumerable
<
HdAddress
>
GetHistoryByCoinType
(
string
walletName
,
CoinType
coinType
)
{
Wallet
wallet
=
this
.
GetWalletByName
(
walletName
);
return
this
.
GetHistoryByCoinType
(
wallet
,
coinType
);
}
/// <inheritdoc />
public
IEnumerable
<
HdAddress
>
GetHistoryByCoinType
(
Wallet
wallet
,
CoinType
coinType
)
{
var
accounts
=
wallet
.
GetAccountsByCoinType
(
coinType
).
ToList
();
foreach
(
var
address
in
accounts
.
SelectMany
(
a
=>
a
.
ExternalAddresses
).
Concat
(
accounts
.
SelectMany
(
a
=>
a
.
InternalAddresses
)))
{
if
(
address
.
Transactions
.
Any
())
{
yield
return
address
;
}
}
}
/// <summary>
/// Creates a number of addresses in the provided account.
/// </summary>
...
...
@@ -275,8 +289,7 @@ namespace Breeze.Wallet
HdPath
=
CreateBip44Path
(
account
.
GetCoinType
(),
account
.
Index
,
i
,
isChange
),
ScriptPubKey
=
address
.
ScriptPubKey
,
Address
=
address
.
ToString
(),
Transactions
=
new
List
<
TransactionData
>(),
CreationTime
=
DateTimeOffset
.
Now
Transactions
=
new
List
<
TransactionData
>()
}});
addressesCreated
.
Add
(
address
.
ToString
());
...
...
@@ -302,9 +315,9 @@ namespace Breeze.Wallet
/// <inheritdoc />
public
IEnumerable
<
HdAccount
>
GetAccountsByCoinType
(
string
walletName
,
CoinType
coinType
)
{
return
this
.
Wallets
.
SelectMany
(
w
=>
w
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
)).
SelectMany
(
a
=>
a
.
Accounts
);
Wallet
wallet
=
this
.
GetWalletByName
(
walletName
);
return
wallet
.
GetAccountsByCoinType
(
coinType
);
}
public
WalletBuildTransactionModel
BuildTransaction
(
string
password
,
string
address
,
Money
amount
,
string
feeType
,
bool
allowUnconfirmed
)
...
...
@@ -342,13 +355,13 @@ namespace Breeze.Wallet
{
Console
.
WriteLine
(
$"transaction notification: tx hash
{
transaction
.
GetHash
()}
, coin type:
{
coinType
}
"
);
foreach
(
var
k
in
this
.
PubKeys
)
foreach
(
var
pubKey
in
this
.
PubKeys
)
{
// check if the outputs contain one of our addresses
var
utxo
=
transaction
.
Outputs
.
SingleOrDefault
(
o
=>
k
==
o
.
ScriptPubKey
);
var
utxo
=
transaction
.
Outputs
.
SingleOrDefault
(
o
=>
pubKey
==
o
.
ScriptPubKey
);
if
(
utxo
!=
null
)
{
AddTransactionToWallet
(
coinType
,
transaction
.
GetHash
(),
transaction
.
Time
,
transaction
.
Outputs
.
IndexOf
(
utxo
),
utxo
.
Value
,
k
,
blockHeight
,
blockTime
);
AddTransactionToWallet
(
coinType
,
transaction
.
GetHash
(),
transaction
.
Time
,
transaction
.
Outputs
.
IndexOf
(
utxo
),
utxo
.
Value
,
pubKey
,
blockHeight
,
blockTime
);
}
// if the inputs have a reference to a transaction containing one of our scripts
...
...
@@ -359,7 +372,7 @@ namespace Breeze.Wallet
// compare the index of the output in its original transaction and the index references in the input
if
(
input
.
PrevOut
.
N
==
tTx
.
Index
)
{
AddTransactionToWallet
(
coinType
,
transaction
.
GetHash
(),
transaction
.
Time
,
null
,
-
tTx
.
Amount
,
k
,
blockHeight
,
blockTime
);
AddTransactionToWallet
(
coinType
,
transaction
.
GetHash
(),
transaction
.
Time
,
null
,
-
tTx
.
Amount
,
pubKey
,
blockHeight
,
blockTime
,
tTx
.
Hash
,
tTx
.
Index
);
}
}
}
...
...
@@ -376,7 +389,9 @@ namespace Breeze.Wallet
/// <param name="script">The script.</param>
/// <param name="blockHeight">Height of the block.</param>
/// <param name="blockTime">The block time.</param>
private
void
AddTransactionToWallet
(
CoinType
coinType
,
uint256
transactionHash
,
uint
time
,
int
?
index
,
Money
amount
,
Script
script
,
int
?
blockHeight
=
null
,
uint
?
blockTime
=
null
)
/// <param name="spendingTransactionId">The id of the transaction containing the output being spent, if this is a spending transaction.</param>
/// <param name="spendingTransactionIndex">The index of the output in the transaction being referenced, if this is a spending transaction.</param>
private
void
AddTransactionToWallet
(
CoinType
coinType
,
uint256
transactionHash
,
uint
time
,
int
?
index
,
Money
amount
,
Script
script
,
int
?
blockHeight
=
null
,
uint
?
blockTime
=
null
,
uint256
spendingTransactionId
=
null
,
int
?
spendingTransactionIndex
=
null
)
{
// selects all the transactions we already have in the wallet
var
txs
=
this
.
Wallets
.
...
...
@@ -403,7 +418,7 @@ namespace Breeze.Wallet
Amount
=
amount
,
BlockHeight
=
blockHeight
,
Confirmed
=
blockHeight
.
HasValue
,
Id
=
transactionHash
,
Id
=
transactionHash
,
CreationTime
=
DateTimeOffset
.
FromUnixTimeMilliseconds
(
blockTime
??
time
),
Index
=
index
}
...
...
@@ -412,6 +427,16 @@ namespace Breeze.Wallet
// notify a transaction has been found
this
.
TransactionFound
?.
Invoke
(
this
,
new
TransactionFoundEventArgs
(
wallet
,
accountRoot
.
CoinType
,
account
,
address
,
false
));
}
// if this is a spending transaction, mark the spent transaction as such
if
(
spendingTransactionId
!=
null
)
{
var
transactions
=
account
.
GetTransactionsById
(
spendingTransactionId
);
if
(
transactions
.
Any
())
{
transactions
.
Single
(
t
=>
t
.
Index
==
spendingTransactionIndex
).
SpentInTransaction
=
transactionHash
;
}
}
}
}
}
...
...
@@ -518,7 +543,7 @@ namespace Breeze.Wallet
/// <param name="walletFilePath">The wallet file path.</param>
/// <returns></returns>
/// <exception cref="System.IO.FileNotFoundException"></exception>
private
Wallet
Get
Wallet
(
string
walletFilePath
)
private
Wallet
Deserialize
Wallet
(
string
walletFilePath
)
{
if
(!
File
.
Exists
(
walletFilePath
))
throw
new
FileNotFoundException
(
$"No wallet file found at
{
walletFilePath
}
"
);
...
...
@@ -600,8 +625,8 @@ namespace Breeze.Wallet
SelectMany
(
a
=>
a
.
Accounts
).
SelectMany
(
a
=>
a
.
ExternalAddresses
).
Select
(
s
=>
s
.
ScriptPubKey
));
// uncomment the following for testing on a random address
//Select(t => (new BitcoinPubKeyAddress(t.Address, Network.Main)).ScriptPubKey));
// uncomment the following for testing on a random address
//Select(t => (new BitcoinPubKeyAddress(t.Address, Network.Main)).ScriptPubKey));
}
/// <summary>
...
...
@@ -623,6 +648,22 @@ namespace Breeze.Wallet
Amount
=
t
.
Amount
}));
}
/// <summary>
/// Gets a wallet given its name.
/// </summary>
/// <param name="walletName">The name of the wallet to get.</param>
/// <returns>A wallet or null if it doesn't exist</returns>
private
Wallet
GetWalletByName
(
string
walletName
)
{
Wallet
wallet
=
this
.
Wallets
.
SingleOrDefault
(
w
=>
w
.
Name
==
walletName
);
if
(
wallet
==
null
)
{
throw
new
Exception
(
$"No wallet with name
{
walletName
}
could be found."
);
}
return
wallet
;
}
}
public
class
TransactionDetails
...
...
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