Move Node type of out Wallet API (#1708)

* Move Node type of out wallet api

* Remove extensions, add scaladocs
This commit is contained in:
Ben Carman 2020-07-29 05:57:48 -05:00 committed by GitHub
parent c3dfb369d7
commit 26d5a09532
12 changed files with 174 additions and 167 deletions

View file

@ -2,7 +2,7 @@ package org.bitcoins.wallet
import org.bitcoins.core.hd.AddressType import org.bitcoins.core.hd.AddressType
import org.bitcoins.core.protocol.BitcoinAddress import org.bitcoins.core.protocol.BitcoinAddress
import org.bitcoins.wallet.api.HDWalletApi import org.bitcoins.wallet.api.AnyHDWalletApi
import org.bitcoins.wallet.models.AccountDb import org.bitcoins.wallet.models.AccountDb
import scala.concurrent.Future import scala.concurrent.Future
@ -11,7 +11,7 @@ import scala.concurrent.Future
* ScalaMock cannot stub traits with protected methods, * ScalaMock cannot stub traits with protected methods,
* so we need to stub them manually. * so we need to stub them manually.
*/ */
abstract class MockWalletApi extends HDWalletApi { abstract class MockWalletApi extends AnyHDWalletApi {
override protected[wallet] def getNewChangeAddress( override protected[wallet] def getNewChangeAddress(
account: AccountDb): Future[BitcoinAddress] = stub account: AccountDb): Future[BitcoinAddress] = stub

View file

@ -19,7 +19,7 @@ import org.bitcoins.feeprovider.BitcoinerLiveFeeRateProvider
import org.bitcoins.node._ import org.bitcoins.node._
import org.bitcoins.node.config.NodeAppConfig import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.models.Peer import org.bitcoins.node.models.Peer
import org.bitcoins.wallet.api._ import org.bitcoins.wallet.Wallet
import org.bitcoins.wallet.config.WalletAppConfig import org.bitcoins.wallet.config.WalletAppConfig
import scala.concurrent.{ExecutionContext, Future, Promise} import scala.concurrent.{ExecutionContext, Future, Promise}
@ -157,11 +157,11 @@ object Main extends App with BitcoinSLogger {
//start everything! //start everything!
runMain() runMain()
private def createCallbacks(wallet: WalletApi)(implicit private def createCallbacks(wallet: Wallet)(implicit
nodeConf: NodeAppConfig, nodeConf: NodeAppConfig,
ec: ExecutionContext): Future[NodeCallbacks] = { ec: ExecutionContext): Future[NodeCallbacks] = {
lazy val onTx: OnTxReceived = { tx => lazy val onTx: OnTxReceived = { tx =>
wallet.processTransaction(tx, blockHash = None).map(_ => ()) wallet.processTransaction(tx, blockHashOpt = None).map(_ => ())
} }
lazy val onCompactFilters: OnCompactFiltersReceived = { blockFilters => lazy val onCompactFilters: OnCompactFiltersReceived = { blockFilters =>
wallet wallet
@ -192,7 +192,7 @@ object Main extends App with BitcoinSLogger {
} }
} }
private def addCallbacksAndBloomFilterToNode(node: Node, wallet: WalletApi)( private def addCallbacksAndBloomFilterToNode(node: Node, wallet: Wallet)(
implicit implicit
nodeAppConfig: NodeAppConfig, nodeAppConfig: NodeAppConfig,
ec: ExecutionContext): Future[Node] = { ec: ExecutionContext): Future[Node] = {
@ -233,7 +233,7 @@ object Main extends App with BitcoinSLogger {
private def startHttpServer( private def startHttpServer(
node: Node, node: Node,
wallet: HDWalletApi, wallet: Wallet,
rpcPortOpt: Option[Int])(implicit rpcPortOpt: Option[Int])(implicit
system: ActorSystem, system: ActorSystem,
conf: BitcoinSAppConfig): Future[Http.ServerBinding] = { conf: BitcoinSAppConfig): Future[Http.ServerBinding] = {

View file

@ -6,12 +6,12 @@ import akka.http.scaladsl.server._
import org.bitcoins.commons.serializers.Picklers._ import org.bitcoins.commons.serializers.Picklers._
import org.bitcoins.core.currency._ import org.bitcoins.core.currency._
import org.bitcoins.node.Node import org.bitcoins.node.Node
import org.bitcoins.wallet.api.HDWalletApi import org.bitcoins.wallet.api.AnyHDWalletApi
import scala.concurrent.Future import scala.concurrent.Future
import scala.util.{Failure, Success} import scala.util.{Failure, Success}
case class WalletRoutes(wallet: HDWalletApi, node: Node)(implicit case class WalletRoutes(wallet: AnyHDWalletApi, node: Node)(implicit
system: ActorSystem) system: ActorSystem)
extends ServerRoute { extends ServerRoute {
import system.dispatcher import system.dispatcher

View file

@ -14,7 +14,7 @@ import org.bitcoins.testkit.node.{
NodeUnitTest NodeUnitTest
} }
import org.bitcoins.testkit.wallet.BitcoinSWalletTest import org.bitcoins.testkit.wallet.BitcoinSWalletTest
import org.bitcoins.wallet.api.WalletApi import org.bitcoins.wallet.Wallet
import org.scalatest.FutureOutcome import org.scalatest.FutureOutcome
import scala.concurrent.{Future, Promise} import scala.concurrent.{Future, Promise}
@ -42,8 +42,8 @@ class NeutrinoNodeWithWalletTest extends NodeUnitTest {
} }
} }
private var walletP: Promise[WalletApi] = Promise() private var walletP: Promise[Wallet] = Promise()
private var walletF: Future[WalletApi] = walletP.future private var walletF: Future[Wallet] = walletP.future
after { after {
//reset assertion after a test runs, because we //reset assertion after a test runs, because we
//are doing mutation to work around our callback //are doing mutation to work around our callback

View file

@ -10,7 +10,7 @@ import org.bitcoins.crypto.AesPassword
import org.bitcoins.keymanager.KeyManagerUnlockError.MnemonicNotFound import org.bitcoins.keymanager.KeyManagerUnlockError.MnemonicNotFound
import org.bitcoins.keymanager.{KeyManagerUnlockError, WalletStorage} import org.bitcoins.keymanager.{KeyManagerUnlockError, WalletStorage}
import org.bitcoins.testkit.wallet.BitcoinSWalletTest import org.bitcoins.testkit.wallet.BitcoinSWalletTest
import org.bitcoins.wallet.api.WalletApi.BlockMatchingResponse import org.bitcoins.wallet.api.NeutrinoWalletApi.BlockMatchingResponse
import org.bitcoins.wallet.models.AddressDb import org.bitcoins.wallet.models.AddressDb
import org.scalatest.FutureOutcome import org.scalatest.FutureOutcome
import org.scalatest.compatible.Assertion import org.scalatest.compatible.Assertion

View file

@ -52,7 +52,7 @@ import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success} import scala.util.{Failure, Success}
abstract class Wallet abstract class Wallet
extends HDWalletApi extends AnyHDWalletApi
with UtxoHandling with UtxoHandling
with AddressHandling with AddressHandling
with AccountHandling with AccountHandling

View file

@ -3,12 +3,12 @@ package org.bitcoins.wallet.api
import org.bitcoins.commons.jsonmodels.wallet.CoinSelectionAlgo import org.bitcoins.commons.jsonmodels.wallet.CoinSelectionAlgo
import org.bitcoins.core.currency.CurrencyUnit import org.bitcoins.core.currency.CurrencyUnit
import org.bitcoins.core.hd.{AddressType, HDAccount, HDChainType, HDPurpose} import org.bitcoins.core.hd.{AddressType, HDAccount, HDChainType, HDPurpose}
import org.bitcoins.core.protocol.BitcoinAddress
import org.bitcoins.core.protocol.transaction.{ import org.bitcoins.core.protocol.transaction.{
Transaction, Transaction,
TransactionOutPoint, TransactionOutPoint,
TransactionOutput TransactionOutput
} }
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
import org.bitcoins.core.wallet.fee.FeeUnit import org.bitcoins.core.wallet.fee.FeeUnit
import org.bitcoins.core.wallet.utxo.{AddressTag, TxoState} import org.bitcoins.core.wallet.utxo.{AddressTag, TxoState}
import org.bitcoins.keymanager.KeyManagerParams import org.bitcoins.keymanager.KeyManagerParams
@ -492,47 +492,6 @@ trait HDWalletApi extends WalletApi {
ec: ExecutionContext): Future[Vector[AccountDb]] = ec: ExecutionContext): Future[Vector[AccountDb]] =
listAccounts().map(_.filter(_.hdAccount.purpose == purpose)) listAccounts().map(_.filter(_.hdAccount.purpose == purpose))
def rescanNeutrinoWallet(
account: HDAccount,
startOpt: Option[BlockStamp],
endOpt: Option[BlockStamp],
addressBatchSize: Int,
useCreationTime: Boolean): Future[Unit]
override def rescanNeutrinoWallet(
startOpt: Option[BlockStamp],
endOpt: Option[BlockStamp],
addressBatchSize: Int,
useCreationTime: Boolean)(implicit ec: ExecutionContext): Future[Unit] = {
for {
account <- getDefaultAccount()
_ <- rescanNeutrinoWallet(account.hdAccount,
startOpt,
endOpt,
addressBatchSize,
useCreationTime)
} yield ()
}
def fullRescanNeutrinoWallet(
account: HDAccount,
addressBatchSize: Int): Future[Unit] = {
rescanNeutrinoWallet(account = account,
startOpt = None,
endOpt = None,
addressBatchSize = addressBatchSize,
useCreationTime = false)
}
/** Helper method to rescan the ENTIRE blockchain. */
override def fullRescanNeutrinoWallet(addressBatchSize: Int)(implicit
ec: ExecutionContext): Future[Unit] = {
for {
account <- getDefaultAccount()
_ <- fullRescanNeutrinoWallet(account.hdAccount, addressBatchSize)
} yield ()
}
def createNewAccount(keyManagerParams: KeyManagerParams): Future[HDWalletApi] def createNewAccount(keyManagerParams: KeyManagerParams): Future[HDWalletApi]
/** /**

View file

@ -0,0 +1,101 @@
package org.bitcoins.wallet.api
import org.bitcoins.core.gcs.GolombFilter
import org.bitcoins.core.protocol.BlockStamp
import org.bitcoins.core.protocol.blockchain.Block
import org.bitcoins.core.protocol.script.ScriptPubKey
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
import org.bitcoins.wallet.api.NeutrinoWalletApi.BlockMatchingResponse
import scala.concurrent.{ExecutionContext, Future}
trait NeutrinoWalletApi { self: WalletApi =>
/**
* Processes the give block, updating our DB state if it's relevant to us.
* @param block The block we're processing
*/
def processBlock(block: Block): Future[WalletApi]
def processCompactFilter(
blockHash: DoubleSha256Digest,
blockFilter: GolombFilter): Future[WalletApi] =
processCompactFilters(Vector((blockHash, blockFilter)))
def processCompactFilters(
blockFilters: Vector[(DoubleSha256Digest, GolombFilter)]): Future[
WalletApi]
/**
* Iterates over the block filters in order to find filters that match to the given addresses
*
* I queries the filter database for [[batchSize]] filters a time
* and tries to run [[GolombFilter.matchesAny]] for each filter.
*
* It tries to match the filters in parallel using [[parallelismLevel]] threads.
* For best results use it with a separate execution context.
*
* @param scripts list of [[ScriptPubKey]]'s to watch
* @param startOpt start point (if empty it starts with the genesis block)
* @param endOpt end point (if empty it ends with the best tip)
* @param batchSize number of filters that can be matched in one batch
* @param parallelismLevel max number of threads required to perform matching
* (default [[Runtime.getRuntime.availableProcessors()]])
* @return a list of matching block hashes
*/
def getMatchingBlocks(
scripts: Vector[ScriptPubKey],
startOpt: Option[BlockStamp] = None,
endOpt: Option[BlockStamp] = None,
batchSize: Int = 100,
parallelismLevel: Int = Runtime.getRuntime.availableProcessors())(implicit
ec: ExecutionContext): Future[Vector[BlockMatchingResponse]]
/**
* Recreates the account using BIP-157 approach
*
* DANGER! This method removes all records from the wallet database
* and creates new ones while the account discovery process.
*
* The Wallet UI should check if the database is empty before calling
* this method and let the end users to decide whether they want to proceed or not.
*
* This method generates [[addressBatchSize]] of addresses, then matches them against the BIP-158 compact filters,
* and downloads and processes the matched blocks. This method keeps doing the steps until there are [[WalletConfig.addressGapLimit]]
* or more unused addresses in a row. In this case it considers the discovery process completed.
*
* [[addressBatchSize]] - the number of addresses we should generate from a keychain to attempt to match in in a rescan
* [[WalletConfig.addressGapLimit]] - the number of addresses required to go without a match before we determine that our wallet is "discovered".
* For instance, if addressBatchSize=100, and AddressGapLimit=20 we do a rescan and the last address we find containing
* funds is at index 75, we would not generate more addresses to try and rescan. However if the last index containing
* funds was 81, we would generate another 100 addresses from the keychain and attempt to rescan those.
*
* @param startOpt start block (if None it starts from the genesis block)
* @param endOpt end block (if None it ends at the current tip)
* @param addressBatchSize how many addresses to match in a single pass
*/
def rescanNeutrinoWallet(
startOpt: Option[BlockStamp],
endOpt: Option[BlockStamp],
addressBatchSize: Int,
useCreationTime: Boolean)(implicit ec: ExecutionContext): Future[Unit]
/** Helper method to rescan the ENTIRE blockchain. */
def fullRescanNeutrinoWallet(addressBatchSize: Int)(implicit
ec: ExecutionContext): Future[Unit] =
rescanNeutrinoWallet(startOpt = None,
endOpt = None,
addressBatchSize = addressBatchSize,
useCreationTime = false)
def discoveryBatchSize(): Int = 25
}
object NeutrinoWalletApi {
case class BlockMatchingResponse(
blockHash: DoubleSha256DigestBE,
blockHeight: Int)
}

View file

@ -0,0 +1,26 @@
package org.bitcoins.wallet.api
import org.bitcoins.core.bloom.BloomFilter
import scala.concurrent.Future
/**
* API for the wallet project.
*
* This wallet API is BIP44 compliant.
*
* @see [[https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP44]]
*/
trait SpvWalletApi { self: WalletApi =>
/**
* Recreates the account using BIP-44 approach
*/
def rescanSPVWallet(): Future[Unit]
/**
* Retrieves a bloom filter that that can be sent to a P2P network node
* to get information about our transactions, pubkeys and scripts.
*/
def getBloomFilter(): Future[BloomFilter]
}

View file

@ -4,26 +4,22 @@ import java.time.Instant
import org.bitcoins.commons.jsonmodels.wallet.CoinSelectionAlgo import org.bitcoins.commons.jsonmodels.wallet.CoinSelectionAlgo
import org.bitcoins.core.api.{ChainQueryApi, FeeRateApi, NodeApi} import org.bitcoins.core.api.{ChainQueryApi, FeeRateApi, NodeApi}
import org.bitcoins.core.bloom.BloomFilter
import org.bitcoins.core.config.NetworkParameters import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.currency.CurrencyUnit import org.bitcoins.core.currency.CurrencyUnit
import org.bitcoins.core.gcs.GolombFilter
import org.bitcoins.core.hd.AddressType import org.bitcoins.core.hd.AddressType
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader} import org.bitcoins.core.protocol.BitcoinAddress
import org.bitcoins.core.protocol.script.ScriptPubKey import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.core.protocol.transaction.{ import org.bitcoins.core.protocol.transaction.{
Transaction, Transaction,
TransactionOutPoint, TransactionOutPoint,
TransactionOutput TransactionOutput
} }
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
import org.bitcoins.core.util.FutureUtil import org.bitcoins.core.util.FutureUtil
import org.bitcoins.core.wallet.fee.FeeUnit import org.bitcoins.core.wallet.fee.FeeUnit
import org.bitcoins.core.wallet.utxo.{AddressTag, TxoState} import org.bitcoins.core.wallet.utxo.{AddressTag, TxoState}
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE} import org.bitcoins.crypto.DoubleSha256DigestBE
import org.bitcoins.keymanager._ import org.bitcoins.keymanager._
import org.bitcoins.wallet.WalletLogger import org.bitcoins.wallet.WalletLogger
import org.bitcoins.wallet.api.WalletApi.BlockMatchingResponse
import org.bitcoins.wallet.models.{AddressDb, SpendingInfoDb} import org.bitcoins.wallet.models.{AddressDb, SpendingInfoDb}
import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.{ExecutionContext, Future}
@ -50,12 +46,6 @@ trait WalletApi extends WalletLogger {
def stop(): Unit def stop(): Unit
/**
* Retrieves a bloom filter that that can be sent to a P2P network node
* to get information about our transactions, pubkeys and scripts.
*/
def getBloomFilter(): Future[BloomFilter]
/** /**
* Processes the given transaction, updating our DB state if it's relevant to us. * Processes the given transaction, updating our DB state if it's relevant to us.
* @param transaction The transaction we're processing * @param transaction The transaction we're processing
@ -82,21 +72,6 @@ trait WalletApi extends WalletLogger {
def updateUtxoPendingStates( def updateUtxoPendingStates(
blockHeader: BlockHeader): Future[Vector[SpendingInfoDb]] blockHeader: BlockHeader): Future[Vector[SpendingInfoDb]]
/**
* Processes the give block, updating our DB state if it's relevant to us.
* @param block The block we're processing
*/
def processBlock(block: Block): Future[WalletApi]
def processCompactFilter(
blockHash: DoubleSha256Digest,
blockFilter: GolombFilter): Future[WalletApi] =
processCompactFilters(Vector((blockHash, blockFilter)))
def processCompactFilters(
blockFilters: Vector[(DoubleSha256Digest, GolombFilter)]): Future[
WalletApi]
/** Gets the sum of all UTXOs in this wallet */ /** Gets the sum of all UTXOs in this wallet */
def getBalance()(implicit ec: ExecutionContext): Future[CurrencyUnit] = { def getBalance()(implicit ec: ExecutionContext): Future[CurrencyUnit] = {
val confirmedF = getConfirmedBalance() val confirmedF = getConfirmedBalance()
@ -130,13 +105,6 @@ trait WalletApi extends WalletLogger {
def getUnconfirmedBalance(tag: AddressTag): Future[CurrencyUnit] def getUnconfirmedBalance(tag: AddressTag): Future[CurrencyUnit]
/**
* If a UTXO is spent outside of the wallet, we
* need to remove it from the database so it won't be
* attempted spent again by us.
*/
// def updateUtxo: Future[WalletApi]
/** Lists unspent transaction outputs in the wallet /** Lists unspent transaction outputs in the wallet
* @return Vector[SpendingInfoDb] * @return Vector[SpendingInfoDb]
*/ */
@ -237,72 +205,6 @@ trait WalletApi extends WalletLogger {
protected[wallet] def getNewChangeAddress()(implicit protected[wallet] def getNewChangeAddress()(implicit
ec: ExecutionContext): Future[BitcoinAddress] ec: ExecutionContext): Future[BitcoinAddress]
/**
* Iterates over the block filters in order to find filters that match to the given addresses
*
* I queries the filter database for [[batchSize]] filters a time
* and tries to run [[GolombFilter.matchesAny]] for each filter.
*
* It tries to match the filters in parallel using [[parallelismLevel]] threads.
* For best results use it with a separate execution context.
*
* @param scripts list of [[ScriptPubKey]]'s to watch
* @param startOpt start point (if empty it starts with the genesis block)
* @param endOpt end point (if empty it ends with the best tip)
* @param batchSize number of filters that can be matched in one batch
* @param parallelismLevel max number of threads required to perform matching
* (default [[Runtime.getRuntime.availableProcessors()]])
* @return a list of matching block hashes
*/
def getMatchingBlocks(
scripts: Vector[ScriptPubKey],
startOpt: Option[BlockStamp] = None,
endOpt: Option[BlockStamp] = None,
batchSize: Int = 100,
parallelismLevel: Int = Runtime.getRuntime.availableProcessors())(implicit
ec: ExecutionContext): Future[Vector[BlockMatchingResponse]]
/**
* Recreates the account using BIP-157 approach
*
* DANGER! This method removes all records from the wallet database
* and creates new ones while the account discovery process.
*
* The Wallet UI should check if the database is empty before calling
* this method and let the end users to decide whether they want to proceed or not.
*
* This method generates [[addressBatchSize]] of addresses, then matches them against the BIP-158 compact filters,
* and downloads and processes the matched blocks. This method keeps doing the steps until there are [[WalletConfig.addressGapLimit]]
* or more unused addresses in a row. In this case it considers the discovery process completed.
*
* [[addressBatchSize]] - the number of addresses we should generate from a keychain to attempt to match in in a rescan
* [[WalletConfig.addressGapLimit]] - the number of addresses required to go without a match before we determine that our wallet is "discovered".
* For instance, if addressBatchSize=100, and AddressGapLimit=20 we do a rescan and the last address we find containing
* funds is at index 75, we would not generate more addresses to try and rescan. However if the last index containing
* funds was 81, we would generate another 100 addresses from the keychain and attempt to rescan those.
*
* @param startOpt start block (if None it starts from the genesis block)
* @param endOpt end block (if None it ends at the current tip)
* @param addressBatchSize how many addresses to match in a single pass
*/
def rescanNeutrinoWallet(
startOpt: Option[BlockStamp],
endOpt: Option[BlockStamp],
addressBatchSize: Int,
useCreationTime: Boolean)(implicit ec: ExecutionContext): Future[Unit]
/** Helper method to rescan the ENTIRE blockchain. */
def fullRescanNeutrinoWallet(addressBatchSize: Int)(implicit
ec: ExecutionContext): Future[Unit]
/**
* Recreates the account using BIP-44 approach
*/
def rescanSPVWallet(): Future[Unit]
def discoveryBatchSize(): Int = 25
def keyManager: KeyManager def keyManager: KeyManager
protected def determineFeeRate(feeRateOpt: Option[FeeUnit]): Future[FeeUnit] = protected def determineFeeRate(feeRateOpt: Option[FeeUnit]): Future[FeeUnit] =
@ -426,10 +328,14 @@ trait WalletApi extends WalletLogger {
} }
object WalletApi { /** An HDWallet that uses Neutrino to sync */
trait NeutrinoHDWalletApi extends HDWalletApi with NeutrinoWalletApi
case class BlockMatchingResponse( /** An HDWallet that uses SPV to sync */
blockHash: DoubleSha256DigestBE, trait SpvHDWalletApi extends HDWalletApi with SpvWalletApi
blockHeight: Int)
} /** An HDWallet that supports both Neutrino and SPV methods of syncing */
trait AnyHDWalletApi
extends HDWalletApi
with NeutrinoWalletApi
with SpvWalletApi

View file

@ -14,7 +14,6 @@ import org.bitcoins.keymanager.{
KeyManagerParams, KeyManagerParams,
WalletStorage WalletStorage
} }
import org.bitcoins.wallet.api.HDWalletApi
import org.bitcoins.wallet.db.WalletDbManagement import org.bitcoins.wallet.db.WalletDbManagement
import org.bitcoins.wallet.models.AccountDAO import org.bitcoins.wallet.models.AccountDAO
import org.bitcoins.wallet.{Wallet, WalletLogger} import org.bitcoins.wallet.{Wallet, WalletLogger}
@ -162,7 +161,7 @@ case class WalletAppConfig(
chainQueryApi: ChainQueryApi, chainQueryApi: ChainQueryApi,
feeRateApi: FeeRateApi, feeRateApi: FeeRateApi,
bip39PasswordOpt: Option[String])(implicit bip39PasswordOpt: Option[String])(implicit
ec: ExecutionContext): Future[HDWalletApi] = { ec: ExecutionContext): Future[Wallet] = {
WalletAppConfig.createHDWallet( WalletAppConfig.createHDWallet(
nodeApi = nodeApi, nodeApi = nodeApi,
chainQueryApi = chainQueryApi, chainQueryApi = chainQueryApi,
@ -194,7 +193,7 @@ object WalletAppConfig
feeRateApi: FeeRateApi, feeRateApi: FeeRateApi,
bip39PasswordOpt: Option[String])(implicit bip39PasswordOpt: Option[String])(implicit
walletConf: WalletAppConfig, walletConf: WalletAppConfig,
ec: ExecutionContext): Future[HDWalletApi] = { ec: ExecutionContext): Future[Wallet] = {
walletConf.hasWallet().flatMap { walletExists => walletConf.hasWallet().flatMap { walletExists =>
if (walletExists) { if (walletExists) {
logger.info(s"Using pre-existing wallet") logger.info(s"Using pre-existing wallet")

View file

@ -9,9 +9,9 @@ import org.bitcoins.core.protocol.BlockStamp.BlockHeight
import org.bitcoins.core.protocol.script.ScriptPubKey import org.bitcoins.core.protocol.script.ScriptPubKey
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp} import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
import org.bitcoins.core.util.FutureUtil import org.bitcoins.core.util.FutureUtil
import org.bitcoins.wallet.api.WalletApi.BlockMatchingResponse
import org.bitcoins.wallet.{Wallet, WalletLogger}
import org.bitcoins.crypto.DoubleSha256Digest import org.bitcoins.crypto.DoubleSha256Digest
import org.bitcoins.wallet.api.NeutrinoWalletApi.BlockMatchingResponse
import org.bitcoins.wallet.{Wallet, WalletLogger}
import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.{ExecutionContext, Future}
@ -23,6 +23,22 @@ private[wallet] trait RescanHandling extends WalletLogger {
/** @inheritdoc */ /** @inheritdoc */
override def rescanNeutrinoWallet( override def rescanNeutrinoWallet(
startOpt: Option[BlockStamp],
endOpt: Option[BlockStamp],
addressBatchSize: Int,
useCreationTime: Boolean)(implicit ec: ExecutionContext): Future[Unit] = {
for {
account <- getDefaultAccount()
_ <- rescanNeutrinoWallet(account.hdAccount,
startOpt,
endOpt,
addressBatchSize,
useCreationTime)
} yield ()
}
/** @inheritdoc */
def rescanNeutrinoWallet(
account: HDAccount, account: HDAccount,
startOpt: Option[BlockStamp], startOpt: Option[BlockStamp],
endOpt: Option[BlockStamp], endOpt: Option[BlockStamp],