mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 10:46:42 +01:00
Import Seed cli commands (#2376)
* Import Seed cli commands * Respond to review
This commit is contained in:
parent
4d9c9415d9
commit
559bebbdbe
7 changed files with 274 additions and 10 deletions
|
@ -2,7 +2,12 @@ package org.bitcoins.commons.serializers
|
||||||
|
|
||||||
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
|
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
|
||||||
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
||||||
import org.bitcoins.core.crypto.ExtPublicKey
|
import org.bitcoins.core.crypto.{
|
||||||
|
ExtKey,
|
||||||
|
ExtPrivateKey,
|
||||||
|
ExtPublicKey,
|
||||||
|
MnemonicCode
|
||||||
|
}
|
||||||
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
||||||
import org.bitcoins.core.number.UInt32
|
import org.bitcoins.core.number.UInt32
|
||||||
import org.bitcoins.core.protocol.dlc.DLCMessage._
|
import org.bitcoins.core.protocol.dlc.DLCMessage._
|
||||||
|
@ -507,4 +512,12 @@ object Picklers {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implicit val mnemonicCodePickler: ReadWriter[MnemonicCode] =
|
||||||
|
readwriter[String].bimap(
|
||||||
|
_.words.mkString(" "),
|
||||||
|
str => MnemonicCode.fromWords(str.split(' ').toVector))
|
||||||
|
|
||||||
|
implicit val extPrivateKeyPickler: ReadWriter[ExtPrivateKey] =
|
||||||
|
readwriter[String].bimap(ExtKey.toString, ExtPrivateKey.fromString)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ package org.bitcoins.cli
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.time.{Instant, ZoneId, ZonedDateTime}
|
import java.time.{Instant, ZoneId, ZonedDateTime}
|
||||||
|
|
||||||
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
|
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
|
||||||
import org.bitcoins.core.protocol.dlc.DLCMessage._
|
import org.bitcoins.core.protocol.dlc.DLCMessage._
|
||||||
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
||||||
import org.bitcoins.core.config.{NetworkParameters, Networks}
|
import org.bitcoins.core.config.{NetworkParameters, Networks}
|
||||||
|
import org.bitcoins.core.crypto.{ExtPrivateKey, MnemonicCode}
|
||||||
import org.bitcoins.core.currency._
|
import org.bitcoins.core.currency._
|
||||||
import org.bitcoins.core.number.UInt32
|
import org.bitcoins.core.number.UInt32
|
||||||
import org.bitcoins.core.protocol.BlockStamp.BlockTime
|
import org.bitcoins.core.protocol.BlockStamp.BlockTime
|
||||||
|
@ -317,4 +317,21 @@ object CliReaders {
|
||||||
override def reads: String => LnMessage[DLCSignTLV] =
|
override def reads: String => LnMessage[DLCSignTLV] =
|
||||||
LnMessageFactory(DLCSignTLV).fromHex
|
LnMessageFactory(DLCSignTLV).fromHex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implicit val extPrivKeyReads: Read[ExtPrivateKey] = new Read[ExtPrivateKey] {
|
||||||
|
override def arity: Int = 1
|
||||||
|
|
||||||
|
override def reads: String => ExtPrivateKey = ExtPrivateKey.fromString
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit val mnemonicCodeReads: Read[MnemonicCode] = new Read[MnemonicCode] {
|
||||||
|
override def arity: Int = 1
|
||||||
|
|
||||||
|
override def reads: String => MnemonicCode =
|
||||||
|
str => {
|
||||||
|
val words = str.split(' ')
|
||||||
|
|
||||||
|
MnemonicCode.fromWords(words.toVector)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.bitcoins.core.protocol.dlc.DLCMessage._
|
||||||
import org.bitcoins.commons.serializers.Picklers._
|
import org.bitcoins.commons.serializers.Picklers._
|
||||||
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
||||||
import org.bitcoins.core.config.NetworkParameters
|
import org.bitcoins.core.config.NetworkParameters
|
||||||
|
import org.bitcoins.core.crypto.{ExtPrivateKey, MnemonicCode}
|
||||||
import org.bitcoins.core.currency._
|
import org.bitcoins.core.currency._
|
||||||
import org.bitcoins.core.number.UInt32
|
import org.bitcoins.core.number.UInt32
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
|
@ -757,6 +758,68 @@ object ConsoleCli {
|
||||||
case other => other
|
case other => other
|
||||||
}))
|
}))
|
||||||
),
|
),
|
||||||
|
cmd("importseed")
|
||||||
|
.action((_, conf) => conf.copy(command = ImportSeed("", null, None)))
|
||||||
|
.text("Imports a mnemonic seed as a new seed file")
|
||||||
|
.children(
|
||||||
|
arg[String]("walletname")
|
||||||
|
.text("Name to associate with this seed")
|
||||||
|
.required()
|
||||||
|
.action((walletName, conf) =>
|
||||||
|
conf.copy(command = conf.command match {
|
||||||
|
case is: ImportSeed =>
|
||||||
|
is.copy(walletName = walletName)
|
||||||
|
case other => other
|
||||||
|
})),
|
||||||
|
arg[MnemonicCode]("words")
|
||||||
|
.text("Mnemonic seed words, space separated")
|
||||||
|
.required()
|
||||||
|
.action((mnemonic, conf) =>
|
||||||
|
conf.copy(command = conf.command match {
|
||||||
|
case is: ImportSeed =>
|
||||||
|
is.copy(mnemonic = mnemonic)
|
||||||
|
case other => other
|
||||||
|
})),
|
||||||
|
arg[AesPassword]("passphrase")
|
||||||
|
.text("Passphrase to encrypt the seed with")
|
||||||
|
.action((password, conf) =>
|
||||||
|
conf.copy(command = conf.command match {
|
||||||
|
case is: ImportSeed =>
|
||||||
|
is.copy(passwordOpt = Some(password))
|
||||||
|
case other => other
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
cmd("importxprv")
|
||||||
|
.action((_, conf) => conf.copy(command = ImportXprv("", null, None)))
|
||||||
|
.text("Imports a xprv as a new seed file")
|
||||||
|
.children(
|
||||||
|
arg[String]("walletname")
|
||||||
|
.text("What name to associate with this seed")
|
||||||
|
.required()
|
||||||
|
.action((walletName, conf) =>
|
||||||
|
conf.copy(command = conf.command match {
|
||||||
|
case ix: ImportXprv =>
|
||||||
|
ix.copy(walletName = walletName)
|
||||||
|
case other => other
|
||||||
|
})),
|
||||||
|
arg[ExtPrivateKey]("xprv")
|
||||||
|
.text("base58 encoded extended private key")
|
||||||
|
.required()
|
||||||
|
.action((xprv, conf) =>
|
||||||
|
conf.copy(command = conf.command match {
|
||||||
|
case ix: ImportXprv =>
|
||||||
|
ix.copy(xprv = xprv)
|
||||||
|
case other => other
|
||||||
|
})),
|
||||||
|
arg[AesPassword]("passphrase")
|
||||||
|
.text("Passphrase to encrypt this seed with")
|
||||||
|
.action((password, conf) =>
|
||||||
|
conf.copy(command = conf.command match {
|
||||||
|
case ix: ImportXprv =>
|
||||||
|
ix.copy(passwordOpt = Some(password))
|
||||||
|
case other => other
|
||||||
|
}))
|
||||||
|
),
|
||||||
cmd("keymanagerpassphrasechange")
|
cmd("keymanagerpassphrasechange")
|
||||||
.action((_, conf) =>
|
.action((_, conf) =>
|
||||||
conf.copy(command = KeyManagerPassphraseChange(null, null)))
|
conf.copy(command = KeyManagerPassphraseChange(null, null)))
|
||||||
|
@ -1370,6 +1433,18 @@ object ConsoleCli {
|
||||||
case KeyManagerPassphraseSet(password) =>
|
case KeyManagerPassphraseSet(password) =>
|
||||||
RequestParam("keymanagerpassphraseset", Seq(up.writeJs(password)))
|
RequestParam("keymanagerpassphraseset", Seq(up.writeJs(password)))
|
||||||
|
|
||||||
|
case ImportSeed(walletName, mnemonic, passwordOpt) =>
|
||||||
|
RequestParam("importseed",
|
||||||
|
Seq(up.writeJs(walletName),
|
||||||
|
up.writeJs(mnemonic),
|
||||||
|
up.writeJs(passwordOpt)))
|
||||||
|
|
||||||
|
case ImportXprv(walletName, xprv, passwordOpt) =>
|
||||||
|
RequestParam("importxprv",
|
||||||
|
Seq(up.writeJs(walletName),
|
||||||
|
up.writeJs(xprv),
|
||||||
|
up.writeJs(passwordOpt)))
|
||||||
|
|
||||||
// height
|
// height
|
||||||
case GetBlockCount => RequestParam("getblockcount")
|
case GetBlockCount => RequestParam("getblockcount")
|
||||||
// filter count
|
// filter count
|
||||||
|
@ -1678,6 +1753,18 @@ object CliCommand {
|
||||||
extends CliCommand
|
extends CliCommand
|
||||||
case class KeyManagerPassphraseSet(password: AesPassword) extends CliCommand
|
case class KeyManagerPassphraseSet(password: AesPassword) extends CliCommand
|
||||||
|
|
||||||
|
case class ImportSeed(
|
||||||
|
walletName: String,
|
||||||
|
mnemonic: MnemonicCode,
|
||||||
|
passwordOpt: Option[AesPassword])
|
||||||
|
extends CliCommand
|
||||||
|
|
||||||
|
case class ImportXprv(
|
||||||
|
walletName: String,
|
||||||
|
xprv: ExtPrivateKey,
|
||||||
|
passwordOpt: Option[AesPassword])
|
||||||
|
extends CliCommand
|
||||||
|
|
||||||
// Node
|
// Node
|
||||||
case object GetPeers extends CliCommand
|
case object GetPeers extends CliCommand
|
||||||
case object Stop extends CliCommand
|
case object Stop extends CliCommand
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.bitcoins.server
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
|
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
|
||||||
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
||||||
|
import org.bitcoins.core.crypto._
|
||||||
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
||||||
import org.bitcoins.core.protocol.BlockStamp.BlockHeight
|
import org.bitcoins.core.protocol.BlockStamp.BlockHeight
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
|
@ -258,6 +259,91 @@ object KeyManagerPassphraseSet extends ServerJsonModels {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class ImportSeed(
|
||||||
|
walletName: String,
|
||||||
|
mnemonic: MnemonicCode,
|
||||||
|
passwordOpt: Option[AesPassword])
|
||||||
|
|
||||||
|
object ImportSeed extends ServerJsonModels {
|
||||||
|
|
||||||
|
def fromJsArr(jsArr: ujson.Arr): Try[ImportSeed] = {
|
||||||
|
jsArr.arr.toList match {
|
||||||
|
case walletNameJs :: mnemonicJs :: passJs :: Nil =>
|
||||||
|
Try {
|
||||||
|
val walletName = walletNameJs.str
|
||||||
|
|
||||||
|
val mnemonicWords = mnemonicJs match {
|
||||||
|
case Str(str) => str.split(' ').toVector
|
||||||
|
case Arr(arr) => arr.map(_.str).toVector
|
||||||
|
case Null | False | True | Num(_) | Obj(_) =>
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"mnemonic must be a string or array of strings")
|
||||||
|
}
|
||||||
|
val mnemonic = MnemonicCode.fromWords(mnemonicWords)
|
||||||
|
|
||||||
|
val pass = passJs match {
|
||||||
|
case Str(str) =>
|
||||||
|
Some(AesPassword.fromString(str))
|
||||||
|
case Null =>
|
||||||
|
None
|
||||||
|
case Arr(_) | False | True | Num(_) | Obj(_) =>
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"password must be a string or null")
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportSeed(walletName, mnemonic, pass)
|
||||||
|
}
|
||||||
|
case Nil =>
|
||||||
|
Failure(
|
||||||
|
new IllegalArgumentException(
|
||||||
|
"Missing walletName, mnemonic, and password argument"))
|
||||||
|
case other =>
|
||||||
|
Failure(
|
||||||
|
new IllegalArgumentException(
|
||||||
|
s"Bad number of arguments: ${other.length}. Expected: 3"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case class ImportXprv(
|
||||||
|
walletName: String,
|
||||||
|
xprv: ExtPrivateKey,
|
||||||
|
passwordOpt: Option[AesPassword])
|
||||||
|
|
||||||
|
object ImportXprv extends ServerJsonModels {
|
||||||
|
|
||||||
|
def fromJsArr(jsArr: ujson.Arr): Try[ImportXprv] = {
|
||||||
|
jsArr.arr.toList match {
|
||||||
|
case walletNameJs :: xprvJs :: passJs :: Nil =>
|
||||||
|
Try {
|
||||||
|
val walletName = walletNameJs.str
|
||||||
|
|
||||||
|
val xprv = ExtPrivateKey.fromString(xprvJs.str)
|
||||||
|
|
||||||
|
val pass = passJs match {
|
||||||
|
case Str(str) =>
|
||||||
|
Some(AesPassword.fromString(str))
|
||||||
|
case Null =>
|
||||||
|
None
|
||||||
|
case Arr(_) | False | True | Bool(_) | Num(_) | Obj(_) =>
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"password must be a string or null")
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportXprv(walletName, xprv, pass)
|
||||||
|
}
|
||||||
|
case Nil =>
|
||||||
|
Failure(
|
||||||
|
new IllegalArgumentException(
|
||||||
|
"Missing walletName, xprv, and password argument"))
|
||||||
|
case other =>
|
||||||
|
Failure(
|
||||||
|
new IllegalArgumentException(
|
||||||
|
s"Bad number of arguments: ${other.length}. Expected: 3"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case class CombinePSBTs(psbts: Seq[PSBT])
|
case class CombinePSBTs(psbts: Seq[PSBT])
|
||||||
|
|
||||||
object CombinePSBTs extends ServerJsonModels {
|
object CombinePSBTs extends ServerJsonModels {
|
||||||
|
|
|
@ -10,10 +10,12 @@ import org.bitcoins.core.currency._
|
||||||
import org.bitcoins.core.protocol.transaction.Transaction
|
import org.bitcoins.core.protocol.transaction.Transaction
|
||||||
import org.bitcoins.core.wallet.utxo.{AddressLabelTagType, TxoState}
|
import org.bitcoins.core.wallet.utxo.{AddressLabelTagType, TxoState}
|
||||||
import org.bitcoins.crypto.NetworkElement
|
import org.bitcoins.crypto.NetworkElement
|
||||||
import org.bitcoins.keymanager.WalletStorage
|
import org.bitcoins.keymanager._
|
||||||
|
import org.bitcoins.keymanager.config.KeyManagerAppConfig
|
||||||
import org.bitcoins.wallet.config.WalletAppConfig
|
import org.bitcoins.wallet.config.WalletAppConfig
|
||||||
import ujson._
|
import ujson._
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
import scala.util.{Failure, Success}
|
import scala.util.{Failure, Success}
|
||||||
|
|
||||||
|
@ -23,6 +25,8 @@ case class WalletRoutes(wallet: AnyHDWalletApi)(implicit
|
||||||
extends ServerRoute {
|
extends ServerRoute {
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
|
|
||||||
|
implicit val kmConf: KeyManagerAppConfig = walletConf.kmConf
|
||||||
|
|
||||||
private def spendingInfoDbToJson(spendingInfoDb: SpendingInfoDb): Value = {
|
private def spendingInfoDbToJson(spendingInfoDb: SpendingInfoDb): Value = {
|
||||||
Obj(
|
Obj(
|
||||||
"outpoint" -> Str(spendingInfoDb.outPoint.hex),
|
"outpoint" -> Str(spendingInfoDb.outPoint.hex),
|
||||||
|
@ -469,6 +473,54 @@ case class WalletRoutes(wallet: AnyHDWalletApi)(implicit
|
||||||
val path = walletConf.seedPath
|
val path = walletConf.seedPath
|
||||||
WalletStorage.changeAesPassword(path, None, Some(password))
|
WalletStorage.changeAesPassword(path, None, Some(password))
|
||||||
|
|
||||||
|
Server.httpSuccess(ujson.Null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ServerCommand("importseed", arr) =>
|
||||||
|
ImportSeed.fromJsArr(arr) match {
|
||||||
|
case Failure(err) =>
|
||||||
|
reject(ValidationRejection("failure", Some(err)))
|
||||||
|
case Success(ImportSeed(walletName, mnemonic, passwordOpt)) =>
|
||||||
|
complete {
|
||||||
|
val seedPath = kmConf.seedFolder.resolve(
|
||||||
|
s"$walletName-${WalletStorage.ENCRYPTED_SEED_FILE_NAME}")
|
||||||
|
|
||||||
|
val creationTime = Instant.ofEpochSecond(WalletStorage.GENESIS_TIME)
|
||||||
|
|
||||||
|
val mnemonicState = passwordOpt match {
|
||||||
|
case Some(pass) =>
|
||||||
|
DecryptedMnemonic(mnemonic, creationTime).encrypt(pass)
|
||||||
|
case None =>
|
||||||
|
DecryptedMnemonic(mnemonic, creationTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletStorage.writeSeedToDisk(seedPath, mnemonicState)
|
||||||
|
|
||||||
|
Server.httpSuccess(ujson.Null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ServerCommand("importxprv", arr) =>
|
||||||
|
ImportXprv.fromJsArr(arr) match {
|
||||||
|
case Failure(err) =>
|
||||||
|
reject(ValidationRejection("failure", Some(err)))
|
||||||
|
case Success(ImportXprv(walletName, xprv, passwordOpt)) =>
|
||||||
|
complete {
|
||||||
|
val seedPath = kmConf.seedFolder.resolve(
|
||||||
|
s"$walletName-${WalletStorage.ENCRYPTED_SEED_FILE_NAME}")
|
||||||
|
|
||||||
|
val creationTime = Instant.ofEpochSecond(WalletStorage.GENESIS_TIME)
|
||||||
|
|
||||||
|
val mnemonicState = passwordOpt match {
|
||||||
|
case Some(pass) =>
|
||||||
|
DecryptedExtPrivKey(xprv, creationTime).encrypt(pass)
|
||||||
|
case None =>
|
||||||
|
DecryptedExtPrivKey(xprv, creationTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletStorage.writeSeedToDisk(seedPath, mnemonicState)
|
||||||
|
|
||||||
Server.httpSuccess(ujson.Null)
|
Server.httpSuccess(ujson.Null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,10 +189,18 @@ For more information on how to use our built in `cli` to interact with the serve
|
||||||
- `lockunspent` `unlock` `transactions` - Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.
|
- `lockunspent` `unlock` `transactions` - Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.
|
||||||
- `unlock` - Whether to unlock (true) or lock (false) the specified transactions
|
- `unlock` - Whether to unlock (true) or lock (false) the specified transactions
|
||||||
- `transactions` - The transaction outpoints to unlock/lock
|
- `transactions` - The transaction outpoints to unlock/lock
|
||||||
- `walletpassphrasechange` `oldpassphrase` `newpassphrase` - Changes the wallet passphrase
|
- `importseed` `walletname` `words` `passphrase` - Imports a mnemonic seed as a new seed file
|
||||||
|
- `walletname` - Name to associate with this seed
|
||||||
|
- `words` - Mnemonic seed words, space separated
|
||||||
|
- `passphrase` - Passphrase to encrypt this seed with
|
||||||
|
- `importxprv` `walletname` `xprv` `passphrase` - Imports a mnemonic seed as a new seed file
|
||||||
|
- `walletname` - Name to associate with this seed
|
||||||
|
- `xprv` - base58 encoded extended private key
|
||||||
|
- `passphrase` - Passphrase to encrypt this seed with
|
||||||
|
- `keymanagerpassphrasechange` `oldpassphrase` `newpassphrase` - Changes the wallet passphrase
|
||||||
- `oldpassphrase` - The current passphrase
|
- `oldpassphrase` - The current passphrase
|
||||||
- `newpassphrase` - The new passphrase
|
- `newpassphrase` - The new passphrase
|
||||||
- `walletpassphraseset` `passphrase` - Encrypts the wallet with the given passphrase
|
- `keymanagerpassphraseset` `passphrase` - Encrypts the wallet with the given passphrase
|
||||||
- `passphrase` - The passphrase to encrypt the wallet with
|
- `passphrase` - The passphrase to encrypt the wallet with
|
||||||
|
|
||||||
#### Network
|
#### Network
|
||||||
|
|
|
@ -33,6 +33,9 @@ case class KeyManagerAppConfig(
|
||||||
config.getStringOrNone(s"bitcoin-s.wallet.walletName")
|
config.getStringOrNone(s"bitcoin-s.wallet.walletName")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy val seedFolder: Path = baseDatadir
|
||||||
|
.resolve(WalletStorage.SEED_FOLDER_NAME)
|
||||||
|
|
||||||
/** The path to our encrypted mnemonic seed */
|
/** The path to our encrypted mnemonic seed */
|
||||||
lazy val seedPath: Path = {
|
lazy val seedPath: Path = {
|
||||||
val prefix = walletNameOpt match {
|
val prefix = walletNameOpt match {
|
||||||
|
@ -40,17 +43,15 @@ case class KeyManagerAppConfig(
|
||||||
s"$walletName-"
|
s"$walletName-"
|
||||||
case None => ""
|
case None => ""
|
||||||
}
|
}
|
||||||
baseDatadir
|
|
||||||
.resolve(WalletStorage.SEED_FOLDER_NAME)
|
seedFolder.resolve(s"$prefix${WalletStorage.ENCRYPTED_SEED_FILE_NAME}")
|
||||||
.resolve(s"$prefix${WalletStorage.ENCRYPTED_SEED_FILE_NAME}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def start(): Future[Unit] = {
|
override def start(): Future[Unit] = {
|
||||||
val oldDefaultFile =
|
val oldDefaultFile =
|
||||||
baseDatadir.resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
|
baseDatadir.resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
|
||||||
|
|
||||||
val newDefaultFile = baseDatadir
|
val newDefaultFile = seedFolder
|
||||||
.resolve(WalletStorage.SEED_FOLDER_NAME)
|
|
||||||
.resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
|
.resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
|
||||||
|
|
||||||
if (!Files.exists(newDefaultFile) && Files.exists(oldDefaultFile)) {
|
if (!Files.exists(newDefaultFile) && Files.exists(oldDefaultFile)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue