Apply string factory to a bunch of easy things (#1891)

* Apply string factory to a bunch of easy things

* Refactor HDPath, ExtKey, and LnTagPrefix to use StringFactory

* Implemen StringFactory on LnHumanReadablePart, ScriptType, ServiceIdentifier

* Implement StringFactory on AesCrypt, NodeUri, AddressTag, PSBT, TxoState

* Fix failing tests, fix website compile

* Apply StringFactory to all ScriptOperations, ChannelState, Script Parsing
This commit is contained in:
Chris Stewart 2020-08-25 10:48:37 -05:00 committed by GitHub
parent 2252dc528e
commit 955978f635
54 changed files with 358 additions and 231 deletions

View file

@ -20,7 +20,8 @@ import org.bitcoins.crypto.{
DoubleSha256Digest,
DoubleSha256DigestBE,
ECDigitalSignature,
Sha256Digest
Sha256Digest,
StringFactory
}
import play.api.libs.json.JsObject
@ -48,17 +49,18 @@ case class PeerInfo(
case class ChannelCommandResult(
results: scala.collection.Map[
Either[ShortChannelId, FundedChannelId],
ChannelCommandResult.State]
State]
)
sealed trait State
object ChannelCommandResult extends StringFactory[State] {
object ChannelCommandResult {
sealed trait State
case object OK extends State
case object ChannelOpened extends State
case object ChannelClosed extends State
case class Error(message: String) extends State
def fromString(s: String): State =
override def fromString(s: String): State =
if (s == "ok") {
ChannelCommandResult.OK
} else if (s.startsWith("created channel ")) {
@ -161,9 +163,9 @@ object ChannelStats {
case object In extends Direction
case object Out extends Direction
object Direction {
object Direction extends StringFactory[Direction] {
def fromString(s: String): Direction =
override def fromString(s: String): Direction =
if (s.toUpperCase == "IN") {
ChannelStats.In
} else if (s.toUpperCase == "OUT") {
@ -279,13 +281,13 @@ case class PaymentRequest(
sealed trait PaymentType
object PaymentType {
object PaymentType extends StringFactory[PaymentType] {
case object Standard extends PaymentType
case object SwapIn extends PaymentType
case object SwapOut extends PaymentType
def fromString(str: String): PaymentType =
override def fromString(str: String): PaymentType =
str match {
case "Standard" => Standard
case "SwapIn" => SwapIn

View file

@ -579,7 +579,7 @@ object JsonReaders {
override def reads(json: JsValue): JsResult[ScriptType] =
json
.validate[String]
.map(ScriptType.fromStringExn)
.map(ScriptType.fromString)
}
implicit object TestMempoolAcceptResultReads
@ -649,7 +649,7 @@ object JsonReaders {
implicit val channelStateReads: Reads[ChannelState] = {
Reads { jsValue: JsValue =>
SerializerUtil.processJsStringOpt(ChannelState.fromString)(jsValue)
SerializerUtil.processJsStringOpt(ChannelState.fromStringOpt)(jsValue)
}
}
@ -691,8 +691,8 @@ object JsonReaders {
implicit val lnHrpReads: Reads[LnHumanReadablePart] = {
Reads { jsValue =>
SerializerUtil.processJsStringOpt(
LnHumanReadablePart.fromString(_).toOption)(jsValue)
SerializerUtil.processJsStringOpt(LnHumanReadablePart.fromStringOpt(_))(
jsValue)
}
}
@ -878,8 +878,7 @@ object JsonReaders {
}
}
implicit val channelCommandResultStateReads: Reads[
ChannelCommandResult.State] = Reads { jsValue =>
implicit val channelCommandResultStateReads: Reads[State] = Reads { jsValue =>
SerializerUtil.processJsString(ChannelCommandResult.fromString)(jsValue)
}
@ -890,7 +889,7 @@ object JsonReaders {
case Success(id) => Right(id)
case Failure(_) => Left(ShortChannelId.fromHumanReadableString(x._1))
}
(channelId, x._2.validate[ChannelCommandResult.State].get)
(channelId, x._2.validate[State].get)
}))
case err @ (JsNull | _: JsBoolean | _: JsString | _: JsArray |
_: JsNumber) =>

View file

@ -97,8 +97,7 @@ object JsonSerializers {
implicit val xpubFormat: Format[ExtPublicKey] = new Format[ExtPublicKey] {
override def reads(json: JsValue): JsResult[ExtPublicKey] =
SerializerUtil.processJsStringOpt(ExtPublicKey.fromString(_).toOption)(
json)
SerializerUtil.processJsStringOpt(ExtPublicKey.fromStringOpt(_))(json)
override def writes(key: ExtPublicKey): JsValue = JsString(key.toString)
}
@ -106,8 +105,7 @@ object JsonSerializers {
implicit val xprivForamt: Format[ExtPrivateKey] = new Format[ExtPrivateKey] {
override def reads(json: JsValue): JsResult[ExtPrivateKey] =
SerializerUtil.processJsStringOpt(ExtPrivateKey.fromString(_).toOption)(
json)
SerializerUtil.processJsStringOpt(ExtPrivateKey.fromStringOpt(_))(json)
override def writes(key: ExtPrivateKey): JsValue = JsString(key.toString)
}

View file

@ -20,7 +20,7 @@ object Picklers {
implicit val bitcoinAddressPickler: ReadWriter[BitcoinAddress] =
readwriter[String]
.bimap(_.value, BitcoinAddress.fromStringExn)
.bimap(_.value, BitcoinAddress.fromString)
implicit val bitcoinsPickler: ReadWriter[Bitcoins] =
readwriter[Double].bimap(_.toBigDecimal.toDouble, Bitcoins(_))
@ -82,13 +82,13 @@ object Picklers {
readwriter[String].bimap(_.hex, Transaction.fromHex)
implicit val extPubKeyPickler: ReadWriter[ExtPublicKey] =
readwriter[String].bimap(_.toString, ExtPublicKey.fromString(_).get)
readwriter[String].bimap(_.toString, ExtPublicKey.fromString(_))
implicit val transactionOutPointPickler: ReadWriter[TransactionOutPoint] =
readwriter[String].bimap(_.hex, TransactionOutPoint.fromHex)
implicit val coinSelectionAlgoPickler: ReadWriter[CoinSelectionAlgo] =
readwriter[String].bimap(_.toString, CoinSelectionAlgo.fromString(_).get)
readwriter[String].bimap(_.toString, CoinSelectionAlgo.fromString(_))
implicit val addressLabelTagPickler: ReadWriter[AddressLabelTag] =
readwriter[String].bimap(_.name, AddressLabelTag)

View file

@ -42,7 +42,7 @@ object CliReaders {
new Read[BitcoinAddress] {
val arity: Int = 1
val reads: String => BitcoinAddress = BitcoinAddress.fromStringExn
val reads: String => BitcoinAddress = BitcoinAddress.fromString
}
implicit val bitcoinsReads: Read[Bitcoins] =
@ -129,7 +129,7 @@ object CliReaders {
val arity: Int = 1
val reads: String => CoinSelectionAlgo =
CoinSelectionAlgo.fromString(_).get
CoinSelectionAlgo.fromString(_)
}
implicit val schnorrSigReads: Read[SchnorrDigitalSignature] =

View file

@ -436,7 +436,6 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
val xpub = ExtPublicKey
.fromString(
"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8")
.get
val accountDb =
AccountDb(xpub = xpub,
@ -477,7 +476,7 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
"get address info" in {
val key = ECPublicKey.freshPublicKey
val hdPath = HDPath.fromString("m/84'/1'/0'/0/0").get
val hdPath = HDPath.fromString("m/84'/1'/0'/0/0")
(mockWalletApi
.getAddressInfo(_: BitcoinAddress))

View file

@ -466,7 +466,7 @@ trait ServerJsonModels {
def jsToBitcoinAddress(js: Value): BitcoinAddress = {
try {
BitcoinAddress.fromStringExn(js.str)
BitcoinAddress.fromString(js.str)
} catch {
case _: IllegalArgumentException =>
throw Value.InvalidData(js, "Expected a valid address")
@ -490,8 +490,6 @@ trait ServerJsonModels {
def jsToCoinSelectionAlgo(js: Value): CoinSelectionAlgo =
CoinSelectionAlgo
.fromString(js.str)
.getOrElse(
throw new IllegalArgumentException("Invalid CoinSelectionAlgo"))
def jsToTx(js: Value): Transaction = Transaction.fromHex(js.str)

View file

@ -18,7 +18,7 @@ class ExtKeySpec extends BitcoinSUnitTest {
it must "have serialization symmetry" in {
Prop.forAll(CryptoGenerators.extKey) { extKey =>
ExtKey.fromString(extKey.toString) == Success(extKey) &&
ExtKey.fromStringT(extKey.toString) == Success(extKey) &&
ExtKey(extKey.bytes) == extKey
}
}

View file

@ -43,7 +43,7 @@ class ExtKeyTest extends BitcoinSUnitTest {
it must "fail to make a private key out of a public key" in {
forAll(CryptoGenerators.extPublicKey) { pub =>
val attempt = ExtPrivateKey.fromString(pub.toString)
val attempt = ExtPrivateKey.fromStringT(pub.toString)
attempt match {
case Success(_) => fail
case Failure(exc) => assert(exc.getMessage.contains("expected private"))
@ -237,7 +237,7 @@ class ExtKeyTest extends BitcoinSUnitTest {
//actual priv key 68e5ed2b2c8fc5a6605107d29d074e3d6ccb119c2811007e32f48305176f814c
val str =
"xprv9s21ZrQH143K4LCRq4tUZUt3fiTNZr6QTiep3HGzMxtSwfxKAhBmNJJnsmoyWuYZCPC4DNsiVwToHJbxZtq4iEkozBhMzWNTiCH4tzJNjPi"
val masterPriv = ExtPrivateKey.fromString(str).get
val masterPriv = ExtPrivateKey.fromString(str)
val idx = UInt32((1L << 31) - 1)
val path1 = masterPriv.deriveChildPrivKey(idx).extPublicKey.key
val path2 = masterPriv.extPublicKey.deriveChildPubKey(idx).get.key

View file

@ -220,7 +220,7 @@ class MnemonicCodeTest extends BitcoinSUnitTest {
entropy = ByteVector.fromValidHex(rawEntropy),
expectedWords = rawWords.split(" ").toVector,
expectedSeed = BIP39Seed.fromHex(rawSeed),
expectedXPriv = ExtPrivateKey.fromString(rawXpriv).get
expectedXPriv = ExtPrivateKey.fromString(rawXpriv)
)
}

View file

@ -98,7 +98,7 @@ class HDPathTest extends BitcoinSUnitTest {
it must "have toString/fromString symmetry" in {
forAll(HDGenerators.hdPath) { path =>
val pathFromString = HDPath.fromString(path.toString)
val pathFromString = HDPath.fromStringOpt(path.toString)
val resultOpt = pathFromString.map {
case value: LegacyHDPath =>
assert(value == path.asInstanceOf[LegacyHDPath])
@ -119,7 +119,7 @@ class HDPathTest extends BitcoinSUnitTest {
}
forAll(badPaths) { badPath =>
val attempt = HDPath.fromString(badPath.toString)
val attempt = HDPath.fromStringOpt(badPath.toString)
attempt match {
case None =>
succeed
@ -214,7 +214,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(first.account.index == 0)
assert(first.chain.chainType == HDChainType.External)
assert(first.address.index == 0)
assert(HDPath.fromString(firstString).contains(first))
assert(HDPath.fromStringOpt(firstString).contains(first))
val secondString = " m / 44' / 0' / 0' / 0 / 1 "
val second = LegacyHDPath.fromString(secondString)
@ -223,7 +223,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(second.account.index == 0)
assert(second.chain.chainType == HDChainType.External)
assert(second.address.index == 1)
assert(HDPath.fromString(secondString).contains(second))
assert(HDPath.fromStringOpt(secondString).contains(second))
val thirdString = " m / 44' / 0' / 0' / 1 / 0 "
val third = LegacyHDPath.fromString(thirdString)
@ -232,7 +232,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(third.account.index == 0)
assert(third.chain.chainType == HDChainType.Change)
assert(third.address.index == 0)
assert(HDPath.fromString(thirdString).contains(third))
assert(HDPath.fromStringOpt(thirdString).contains(third))
val fourthString = " m / 44' / 0' / 0' / 1 / 1 "
val fourth = LegacyHDPath.fromString(fourthString)
@ -241,7 +241,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(fourth.account.index == 0)
assert(fourth.chain.chainType == HDChainType.Change)
assert(fourth.address.index == 1)
assert(HDPath.fromString(fourthString).contains(fourth))
assert(HDPath.fromStringOpt(fourthString).contains(fourth))
val fifthString = " m / 44' / 0' / 1' / 0 / 0 "
val fifth = LegacyHDPath.fromString(fifthString)
@ -250,7 +250,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(fifth.account.index == 1)
assert(fifth.chain.chainType == HDChainType.External)
assert(fifth.address.index == 0)
assert(HDPath.fromString(fifthString).contains(fifth))
assert(HDPath.fromStringOpt(fifthString).contains(fifth))
val sixthString = " m / 44' / 0' / 1' / 0 / 1 "
val sixth = LegacyHDPath.fromString(sixthString)
@ -259,7 +259,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(sixth.account.index == 1)
assert(sixth.chain.chainType == HDChainType.External)
assert(sixth.address.index == 1)
assert(HDPath.fromString(sixthString).contains(sixth))
assert(HDPath.fromStringOpt(sixthString).contains(sixth))
val seventhString = " m / 44' / 0' / 1' / 1 / 0 "
val seventh = LegacyHDPath.fromString(seventhString)
@ -268,7 +268,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(seventh.account.index == 1)
assert(seventh.chain.chainType == HDChainType.Change)
assert(seventh.address.index == 0)
assert(HDPath.fromString(seventhString).contains(seventh))
assert(HDPath.fromStringOpt(seventhString).contains(seventh))
val eightString = " m / 44' / 0' / 1' / 1 / 1 "
val eigth = LegacyHDPath.fromString(eightString)
@ -277,7 +277,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(eigth.account.index == 1)
assert(eigth.chain.chainType == HDChainType.Change)
assert(eigth.address.index == 1)
assert(HDPath.fromString(eightString).contains(eigth))
assert(HDPath.fromStringOpt(eightString).contains(eigth))
val ninthString = " m / 44' / 1' / 0' / 0 / 1 "
val ninth = LegacyHDPath.fromString(ninthString)
@ -286,7 +286,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(ninth.account.index == 0)
assert(ninth.chain.chainType == HDChainType.External)
assert(ninth.address.index == 1)
assert(HDPath.fromString(ninthString).contains(ninth))
assert(HDPath.fromStringOpt(ninthString).contains(ninth))
val tenthString = " m / 44' / 1' / 0' / 0 / 1 "
val tenth = LegacyHDPath.fromString(tenthString)
@ -295,7 +295,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(tenth.account.index == 0)
assert(tenth.chain.chainType == HDChainType.External)
assert(tenth.address.index == 1)
assert(HDPath.fromString(tenthString).contains(tenth))
assert(HDPath.fromStringOpt(tenthString).contains(tenth))
val eleventhString = " m / 44' / 1' / 0' / 1 / 0 "
val eleventh = LegacyHDPath.fromString(eleventhString)
@ -304,7 +304,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(eleventh.account.index == 0)
assert(eleventh.chain.chainType == HDChainType.Change)
assert(eleventh.address.index == 0)
assert(HDPath.fromString(eleventhString).contains(eleventh))
assert(HDPath.fromStringOpt(eleventhString).contains(eleventh))
val twelfthString = " m / 44' / 1' / 0' / 1 / 1 "
val twelfth = LegacyHDPath.fromString(twelfthString)
@ -313,7 +313,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(twelfth.account.index == 0)
assert(twelfth.chain.chainType == HDChainType.Change)
assert(twelfth.address.index == 1)
assert(HDPath.fromString(twelfthString).contains(twelfth))
assert(HDPath.fromStringOpt(twelfthString).contains(twelfth))
val thirteenthString = " m / 44' / 1' / 1' / 0 / 0 "
val thirteenth = LegacyHDPath.fromString(thirteenthString)
@ -322,7 +322,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(thirteenth.account.index == 1)
assert(thirteenth.chain.chainType == HDChainType.External)
assert(thirteenth.address.index == 0)
assert(HDPath.fromString(thirteenthString).contains(thirteenth))
assert(HDPath.fromStringOpt(thirteenthString).contains(thirteenth))
val fourteenthString = " m / 44' / 1' / 1' / 0 / 1 "
val fourteenth = LegacyHDPath.fromString(fourteenthString)
@ -331,7 +331,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(fourteenth.account.index == 1)
assert(fourteenth.chain.chainType == HDChainType.External)
assert(fourteenth.address.index == 1)
assert(HDPath.fromString(fourteenthString).contains(fourteenth))
assert(HDPath.fromStringOpt(fourteenthString).contains(fourteenth))
val fifteenthString = " m / 44' / 1' / 1' / 1 / 0 "
val fifteenth = LegacyHDPath.fromString(fifteenthString)
@ -340,7 +340,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(fifteenth.account.index == 1)
assert(fifteenth.chain.chainType == HDChainType.Change)
assert(fifteenth.address.index == 0)
assert(HDPath.fromString(fifteenthString).contains(fifteenth))
assert(HDPath.fromStringOpt(fifteenthString).contains(fifteenth))
val sixteenthString = " m / 44' / 1' / 1' / 1 / 1 "
val sixteenth = LegacyHDPath.fromString(sixteenthString)
@ -349,7 +349,7 @@ class HDPathTest extends BitcoinSUnitTest {
assert(sixteenth.account.index == 1)
assert(sixteenth.chain.chainType == HDChainType.Change)
assert(sixteenth.address.index == 1)
assert(HDPath.fromString(sixteenthString).contains(sixteenth))
assert(HDPath.fromStringOpt(sixteenthString).contains(sixteenth))
}
@ -372,10 +372,10 @@ class HDPathTest extends BitcoinSUnitTest {
val xpriv = seed.toExtPrivateKey(ExtKeyVersion.SegWitMainNetPriv)
val xpub = xpriv.extPublicKey
assert(ExtPrivateKey.fromString("zprvAWgYBB").isFailure)
val Success(expectedXpriv) = ExtPrivateKey.fromString(
assert(ExtPrivateKey.fromStringT("zprvAWgYBB").isFailure)
val Success(expectedXpriv) = ExtPrivateKey.fromStringT(
"zprvAWgYBBk7JR8Gjrh4UJQ2uJdG1r3WNRRfURiABBE3RvMXYSrRJL62XuezvGdPvG6GFBZduosCc1YP5wixPox7zhZLfiUm8aunE96BBa4Kei5")
val Success(expectedXpub) = ExtPublicKey.fromString(
val Success(expectedXpub) = ExtPublicKey.fromStringT(
"zpub6jftahH18ngZxLmXaKw3GSZzZsszmt9WqedkyZdezFtWRFBZqsQH5hyUmb4pCEeZGmVfQuP5bedXTB8is6fTv19U1GQRyQUKQGUTzyHACMF")
assert(xpriv == expectedXpriv)
@ -489,7 +489,7 @@ class HDPathTest extends BitcoinSUnitTest {
ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.LegacyMainNetPriv, seed)
val path = LegacyHDPath.fromString("m/44'/0'/0'/0/0")
val Success(xpub) = rootXpriv.deriveChildPubKey(path)
val Success(expectedXpub) = ExtPublicKey.fromString(
val Success(expectedXpub) = ExtPublicKey.fromStringT(
"xpub6FR8LqriB4qyPvdtZwhHW2HQP4daR2qXsYAAsfaiF8DoFJJ5AqGCpiGM3kFC4Z9AZWnReXrzp2nzhp91myPjz96e3wrJoMvgnCyMBjKz8vJ")
assert(xpub == expectedXpub)
}
@ -500,7 +500,7 @@ class HDPathTest extends BitcoinSUnitTest {
ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.LegacyTestNet3Priv, seed)
val path = LegacyHDPath.fromString("m/44'/0'/0'/0/0")
val Success(xpub) = rootXpriv.deriveChildPubKey(path)
val Success(expectedXpub) = ExtPublicKey.fromString(
val Success(expectedXpub) = ExtPublicKey.fromStringT(
"tpubDFnks5gPtLoRfipk28gNhwcmiBjEQRLbRAkUEDdrb2ygzaxnF47Hy9wBHnKyb46QMRKLG7NsM8d3PzddAqEysaYw7YbcUtavNAZkwjM7aqi")
assert(xpub == expectedXpub)
}
@ -511,7 +511,7 @@ class HDPathTest extends BitcoinSUnitTest {
ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.NestedSegWitMainNetPriv, seed)
val path = NestedSegWitHDPath.fromString("m/49'/0'/0'/0/0")
val Success(xpub) = rootXpriv.deriveChildPubKey(path)
val Success(expectedXpub) = ExtPublicKey.fromString(
val Success(expectedXpub) = ExtPublicKey.fromStringT(
"ypub6c6461WnUp9LoRskZCU3bHBJahDvtrPwCCo1WEtuhsrFGZ8Mn2YMNGab2tj5eujgsMx5U1BZz7hA1q87ZdVSXZdArxM9G5Y9iZchQFrov4q")
assert(xpub == expectedXpub)
}
@ -523,7 +523,7 @@ class HDPathTest extends BitcoinSUnitTest {
seed)
val path = NestedSegWitHDPath.fromString("m/49'/0'/0'/0/0")
val Success(xpub) = rootXpriv.deriveChildPubKey(path)
val Success(expectedXpub) = ExtPublicKey.fromString(
val Success(expectedXpub) = ExtPublicKey.fromStringT(
"upub5JkzsLq7t5yRQF7HDmKYkvoHtpe98NRwXki8NfKNBrLj49sSmPt6t1x2x4tjfH81EoUrU6oL9UGxUgfrgqqPLctmPbZSvSGCdfN7qyMHU7g")
assert(xpub == expectedXpub)
}
@ -534,7 +534,7 @@ class HDPathTest extends BitcoinSUnitTest {
ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.SegWitMainNetPriv, seed)
val path = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
val Success(xpub) = rootXpriv.deriveChildPubKey(path)
val Success(expectedXpub) = ExtPublicKey.fromString(
val Success(expectedXpub) = ExtPublicKey.fromStringT(
"zpub6vibtacmZKTajuFATBMJPq629qFzaonkAHzWDBEgpHnuhDBozTVWxbF4zJ1Hm4tdkAMJTg9kUqizEz4JQXGkxyotn3MCxbT92mJ8XVcNN5E")
assert(xpub == expectedXpub)
}
@ -545,7 +545,7 @@ class HDPathTest extends BitcoinSUnitTest {
ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.SegWitTestNet3Priv, seed)
val path = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
val Success(xpub) = rootXpriv.deriveChildPubKey(path)
val Success(expectedXpub) = ExtPublicKey.fromString(
val Success(expectedXpub) = ExtPublicKey.fromStringT(
"vpub5dPYfuw6xbHfLiUh7kCoZUi1TxgCpKpkVqud5bf9JGHPUovtypqGULcWuUAwmSGx7bt5TmmWeCJnhqc3Xjchn35VJgZWcxBBws3Yy6zYa7G")
assert(xpub == expectedXpub)
}
@ -579,14 +579,14 @@ class HDPathTest extends BitcoinSUnitTest {
// we pass in the wrong version bytes to make the test vector
// from bip49 pass
val rootXpriv = seed.toExtPrivateKey(ExtKeyVersion.LegacyTestNet3Priv)
val Success(expectedRootXpriv) = ExtPrivateKey.fromString(
val Success(expectedRootXpriv) = ExtPrivateKey.fromStringT(
"tprv8ZgxMBicQKsPe5YMU9gHen4Ez3ApihUfykaqUorj9t6FDqy3nP6eoXiAo2ssvpAjoLroQxHqr3R5nE3a5dU3DHTjTgJDd7zrbniJr6nrCzd")
val path = NestedSegWitHDPath.fromString("m/49'/1'/0'/0/0")
val firstAccount = path.account
val accountXpriv = rootXpriv.deriveChildPrivKey(firstAccount)
val Success(expectedAccountXpriv) = ExtPrivateKey.fromString(
val Success(expectedAccountXpriv) = ExtPrivateKey.fromStringT(
"tprv8gRrNu65W2Msef2BdBSUgFdRTGzC8EwVXnV7UGS3faeXtuMVtGfEdidVeGbThs4ELEoayCAzZQ4uUji9DUiAs7erdVskqju7hrBcDvDsdbY")
assert(expectedAccountXpriv == accountXpriv)
@ -640,9 +640,9 @@ class HDPathTest extends BitcoinSUnitTest {
val accountXpriv = rootXpriv.deriveChildPrivKey(legacyPathAccount)
val accountXpub = accountXpriv.extPublicKey
val Success(expectedAccountXpriv) = ExtPrivateKey.fromString(
val Success(expectedAccountXpriv) = ExtPrivateKey.fromStringT(
"xprv9xpXFhFpqdQK3TmytPBqXtGSwS3DLjojFhTGht8gwAAii8py5X6pxeBnQ6ehJiyJ6nDjWGJfZ95WxByFXVkDxHXrqu53WCRGypk2ttuqncb")
val Success(expectedAccountXpub) = ExtPublicKey.fromString(
val Success(expectedAccountXpub) = ExtPublicKey.fromStringT(
"xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj")
assert(expectedAccountXpriv == accountXpriv)
@ -659,9 +659,9 @@ class HDPathTest extends BitcoinSUnitTest {
val accountXpriv = rootXpriv.deriveChildPrivKey(nestedSegwithPathAccount)
val accountXpub = accountXpriv.extPublicKey
val Success(expectedAccountXpriv) = ExtPrivateKey.fromString(
val Success(expectedAccountXpriv) = ExtPrivateKey.fromStringT(
"yprvAHwhK6RbpuS3dgCYHM5jc2ZvEKd7Bi61u9FVhYMpgMSuZS613T1xxQeKTffhrHY79hZ5PsskBjcc6C2V7DrnsMsNaGDaWev3GLRQRgV7hxF")
val Success(expectedAccountXpub) = ExtPublicKey.fromString(
val Success(expectedAccountXpub) = ExtPublicKey.fromStringT(
"ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP")
assert(expectedAccountXpriv == accountXpriv)
@ -677,9 +677,9 @@ class HDPathTest extends BitcoinSUnitTest {
val accountXpriv = rootXpriv.deriveChildPrivKey(segwithPathAccount)
val accountXpub = accountXpriv.extPublicKey
val Success(expectedAccountXpriv) = ExtPrivateKey.fromString(
val Success(expectedAccountXpriv) = ExtPrivateKey.fromStringT(
"zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE")
val Success(expectedAccountXpub) = ExtPublicKey.fromString(
val Success(expectedAccountXpub) = ExtPublicKey.fromStringT(
"zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs")
assert(expectedAccountXpriv == accountXpriv)

View file

@ -46,25 +46,25 @@ class LnHumanReadablePartTest extends BitcoinSUnitTest {
it must "deserialize hrp from string" in {
LnHumanReadablePart.fromString("lnbc").get must be(
LnHumanReadablePart.fromString("lnbc") must be(
LnHumanReadablePart(LnBitcoinMainNet))
LnHumanReadablePart.fromString("lntb").get must be(
LnHumanReadablePart.fromString("lntb") must be(
LnHumanReadablePart(LnBitcoinTestNet))
LnHumanReadablePart.fromString("lnbcrt").get must be(
LnHumanReadablePart.fromString("lnbcrt") must be(
LnHumanReadablePart(LnBitcoinRegTest))
LnHumanReadablePart.fromString("lnbc1m").get must be(
LnHumanReadablePart.fromString("lnbc1m") must be(
LnHumanReadablePart(LnBitcoinMainNet, mBtcOpt))
LnHumanReadablePart.fromString("lntb1m").get must be(
LnHumanReadablePart.fromString("lntb1m") must be(
LnHumanReadablePart(LnBitcoinTestNet, mBtcOpt))
LnHumanReadablePart.fromString("lnbcrt1m").get must be(
LnHumanReadablePart.fromString("lnbcrt1m") must be(
LnHumanReadablePart(LnBitcoinRegTest, mBtcOpt))
}
it must "fail to deserialize hrp from invalid string" in {
LnHumanReadablePart.fromString("invalid").isFailure must be(true)
LnHumanReadablePart.fromString("lnbc9000").isFailure must be(true)
LnHumanReadablePart.fromString("lnbc90z0m").isFailure must be(true)
LnHumanReadablePart.fromStringT("invalid").isFailure must be(true)
LnHumanReadablePart.fromStringT("lnbc9000").isFailure must be(true)
LnHumanReadablePart.fromStringT("lnbc90z0m").isFailure must be(true)
}
}

View file

@ -422,7 +422,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
it must "have serialization symmetry for LnHrps" in {
forAll(LnInvoiceGen.lnHrp) { hrp =>
LnHumanReadablePart.fromString(hrp.toString).get == hrp
LnHumanReadablePart.fromString(hrp.toString) == hrp
}
}

View file

@ -60,7 +60,7 @@ class PSBTSerializerTest extends BitcoinSAsyncTest {
val xpub1 = ExtPublicKey
.fromString(
"tpubDBkJeJo2X94Yq3RVz65DoUgyLUkaDrkfyrn2VcgyCRSKCRonvKvCF2FpYDGJWDkdRHBajXJGpc63GnumUt63ySvqCu2XaTRGVTKMYGuFk9H")
.get
val finger1 = hex"d90c6a4f"
val path1 = BIP32Path.fromString("m/174'/0'")
@ -69,7 +69,7 @@ class PSBTSerializerTest extends BitcoinSAsyncTest {
val xpub2 = ExtPublicKey
.fromString(
"tpubDBkJeJo2X94YsvtBEU1eKoibEWiNv51nW5iHhs6VZp59jsE6nen8KZMFyGHuGbCvqjRqirgeMcfpVBkttpUUT6brm4duzSGoZeTbhqCNUu6")
.get
val finger2 = hex"d90c6a4f"
val path2 = BIP32Path.fromString("m/174'/1'")

View file

@ -73,7 +73,6 @@ class PSBTUnitTest extends BitcoinSAsyncTest {
val extKey = ExtKey
.fromString(
"tprv8ZgxMBicQKsPd9TeAdPADNnSyH9SSUUbTVeFszDE23Ki6TBB5nCefAdHkK8Fm3qMQR6sHwA56zqRmKmxnHk37JkiFzvncDqoKmPWubu7hDF")
.get
val psbt = start
.addUTXOToInput(

View file

@ -7,7 +7,7 @@ class ScriptTypeTest extends BitcoinSUnitTest {
it must "have serialization symmetry" in {
ScriptType.all.foreach { scriptType =>
val newScriptType = ScriptType.fromString(scriptType.toString)
val newScriptType = ScriptType.fromStringOpt(scriptType.toString)
assert(newScriptType.contains(scriptType))
}
@ -16,7 +16,7 @@ class ScriptTypeTest extends BitcoinSUnitTest {
it must "fail when nonsense ScriptType is used" in {
val lyrics = "Never gonna give you up, never gonna let you down"
assert(ScriptType.fromString(lyrics).isEmpty)
assertThrows[IllegalArgumentException](ScriptType.fromStringExn(lyrics))
assert(ScriptType.fromStringOpt(lyrics).isEmpty)
assertThrows[RuntimeException](ScriptType.fromString(lyrics))
}
}

View file

@ -7,9 +7,9 @@ import org.bitcoins.testkit.util.BitcoinSUnitTest
*/
class ArithmeticOperationsFactoryTest extends BitcoinSUnitTest {
"ArithmeticOperationsFactory" must "match strings with arithmetic operations" in {
ArithmeticOperation.fromString("OP_1ADD") must be(Some(OP_1ADD))
ArithmeticOperation.fromString("OP_ADD") must be(Some(OP_ADD))
ArithmeticOperation.fromString("OP_LESSTHAN") must be(Some(OP_LESSTHAN))
ArithmeticOperation.fromString("OP_RANDOM") must be(None)
ArithmeticOperation.fromStringOpt("OP_1ADD") must be(Some(OP_1ADD))
ArithmeticOperation.fromStringOpt("OP_ADD") must be(Some(OP_ADD))
ArithmeticOperation.fromStringOpt("OP_LESSTHAN") must be(Some(OP_LESSTHAN))
ArithmeticOperation.fromStringOpt("OP_RANDOM") must be(None)
}
}

View file

@ -8,8 +8,9 @@ import org.bitcoins.testkit.util.BitcoinSUnitTest
class BitwiseOperationsFactoryTest extends BitcoinSUnitTest {
"BitwiseOperationsFactory" must "match strings with bitwise operations" in {
BitwiseOperation.fromString("OP_EQUAL") must be(Some(OP_EQUAL))
BitwiseOperation.fromString("OP_EQUALVERIFY") must be(Some(OP_EQUALVERIFY))
BitwiseOperation.fromString("RANDOM") must be(None)
BitwiseOperation.fromStringOpt("OP_EQUAL") must be(Some(OP_EQUAL))
BitwiseOperation.fromStringOpt("OP_EQUALVERIFY") must be(
Some(OP_EQUALVERIFY))
BitwiseOperation.fromStringOpt("RANDOM") must be(None)
}
}

View file

@ -8,13 +8,13 @@ import org.bitcoins.testkit.util.BitcoinSUnitTest
class ControlOperationsFactoryTest extends BitcoinSUnitTest {
"ControlOperationsFactory" must "match a string with a control operation" in {
ControlOperations.fromString("OP_ELSE") must be(Some(OP_ELSE))
ControlOperations.fromString("OP_ENDIF") must be(Some(OP_ENDIF))
ControlOperations.fromString("OP_IF") must be(Some(OP_IF))
ControlOperations.fromString("OP_NOTIF") must be(Some(OP_NOTIF))
ControlOperations.fromString("OP_RETURN") must be(Some(OP_RETURN))
ControlOperations.fromString("OP_VERIFY") must be(Some(OP_VERIFY))
ControlOperations.fromString("RANDOM") must be(None)
ControlOperations.fromStringOpt("OP_ELSE") must be(Some(OP_ELSE))
ControlOperations.fromStringOpt("OP_ENDIF") must be(Some(OP_ENDIF))
ControlOperations.fromStringOpt("OP_IF") must be(Some(OP_IF))
ControlOperations.fromStringOpt("OP_NOTIF") must be(Some(OP_NOTIF))
ControlOperations.fromStringOpt("OP_RETURN") must be(Some(OP_RETURN))
ControlOperations.fromStringOpt("OP_VERIFY") must be(Some(OP_VERIFY))
ControlOperations.fromStringOpt("RANDOM") must be(None)
}
}

View file

@ -8,9 +8,9 @@ import org.bitcoins.testkit.util.BitcoinSUnitTest
class CryptoOperationsFactoryTest extends BitcoinSUnitTest {
"CryptoOperationsFactory" must "match strings with crypto operations" in {
CryptoOperation.fromString("OP_CHECKSIG") must be(Some(OP_CHECKSIG))
CryptoOperation.fromString("OP_HASH160") must be(Some(OP_HASH160))
CryptoOperation.fromString("OP_SHA256") must be(Some(OP_SHA256))
CryptoOperation.fromString("RANDOM") must be(None)
CryptoOperation.fromStringOpt("OP_CHECKSIG") must be(Some(OP_CHECKSIG))
CryptoOperation.fromStringOpt("OP_HASH160") must be(Some(OP_HASH160))
CryptoOperation.fromStringOpt("OP_SHA256") must be(Some(OP_SHA256))
CryptoOperation.fromStringOpt("RANDOM") must be(None)
}
}

View file

@ -8,63 +8,60 @@ import org.bitcoins.testkit.util.BitcoinSUnitTest
class ScriptFlagFactoryTest extends BitcoinSUnitTest {
"ScriptFlagFactory" must "find a NONE script flag" in {
ScriptFlagFactory.fromString("NONE").get must be(ScriptVerifyNone)
ScriptFlagFactory.fromString("NONE") must be(ScriptVerifyNone)
}
it must "find a P2SH script flag" in {
ScriptFlagFactory.fromString("P2SH").get must be(ScriptVerifyP2SH)
ScriptFlagFactory.fromString("P2SH") must be(ScriptVerifyP2SH)
}
it must "find a STRICTENC flag" in {
ScriptFlagFactory.fromString("STRICTENC").get must be(ScriptVerifyStrictEnc)
ScriptFlagFactory.fromString("STRICTENC") must be(ScriptVerifyStrictEnc)
}
it must "find a DERSIG flag" in {
ScriptFlagFactory.fromString("DERSIG").get must be(ScriptVerifyDerSig)
ScriptFlagFactory.fromString("DERSIG") must be(ScriptVerifyDerSig)
}
it must "find a LOW_S flag" in {
ScriptFlagFactory.fromString("LOW_S").get must be(ScriptVerifyLowS)
ScriptFlagFactory.fromString("LOW_S") must be(ScriptVerifyLowS)
}
it must "find a SIGPUSHONLY flag" in {
ScriptFlagFactory.fromString("SIGPUSHONLY").get must be(
ScriptVerifySigPushOnly)
ScriptFlagFactory.fromString("SIGPUSHONLY") must be(ScriptVerifySigPushOnly)
}
it must "find a MINIMALDATA flag" in {
ScriptFlagFactory.fromString("MINIMALDATA").get must be(
ScriptVerifyMinimalData)
ScriptFlagFactory.fromString("MINIMALDATA") must be(ScriptVerifyMinimalData)
}
it must "find a NULLDUMMY flag" in {
ScriptFlagFactory.fromString("NULLDUMMY").get must be(ScriptVerifyNullDummy)
ScriptFlagFactory.fromString("NULLDUMMY") must be(ScriptVerifyNullDummy)
}
it must "find a DISCOURAGE_UPGRADABLE_NOPS flag" in {
ScriptFlagFactory.fromString("DISCOURAGE_UPGRADABLE_NOPS").get must be(
ScriptFlagFactory.fromString("DISCOURAGE_UPGRADABLE_NOPS") must be(
ScriptVerifyDiscourageUpgradableNOPs)
}
it must "find a CLEANSTACK flag" in {
ScriptFlagFactory.fromString("CLEANSTACK").get must be(
ScriptVerifyCleanStack)
ScriptFlagFactory.fromString("CLEANSTACK") must be(ScriptVerifyCleanStack)
}
it must "find a CHECKLOCKTIMEVERIFY flag" in {
ScriptFlagFactory.fromString("CHECKLOCKTIMEVERIFY").get must be(
ScriptFlagFactory.fromString("CHECKLOCKTIMEVERIFY") must be(
ScriptVerifyCheckLocktimeVerify)
}
it must "find a CHECKSEQUENCEVERIFY flag" in {
ScriptFlagFactory.fromString("CHECKSEQUENCEVERIFY").get must be(
ScriptFlagFactory.fromString("CHECKSEQUENCEVERIFY") must be(
ScriptVerifyCheckSequenceVerify)
}
it must "match a string version of a script flag" in {
val str = "MINIMALDATA"
ScriptFlagFactory.fromString(str) must be(Some(ScriptVerifyMinimalData))
ScriptFlagFactory.fromStringOpt(str) must be(Some(ScriptVerifyMinimalData))
}
it must "match a comma separated list of flags" in {

View file

@ -8,7 +8,7 @@ import org.bitcoins.testkit.util.BitcoinSUnitTest
class LocktimeOperationFactoryTest extends BitcoinSUnitTest {
"LocktimeOperationFactory" must "match lock time operations from strings" in {
LocktimeOperation.fromString("OP_CHECKLOCKTIMEVERIFY") must be(
LocktimeOperation.fromStringOpt("OP_CHECKLOCKTIMEVERIFY") must be(
Some(OP_CHECKLOCKTIMEVERIFY))
}

View file

@ -8,9 +8,10 @@ import org.bitcoins.testkit.util.BitcoinSUnitTest
class StackOperationFactoryTest extends BitcoinSUnitTest {
"StackOperationFactory" must "match correct operations with their strings" in {
StackOperation.fromString("OP_DUP") must be(Some(OP_DUP))
StackOperation.fromString("OP_FROMALTSTACK") must be(Some(OP_FROMALTSTACK))
StackOperation.fromString("RANDOM_OP") must be(None)
StackOperation.fromString("OP_IFDUP") must be(Some(OP_IFDUP))
StackOperation.fromStringOpt("OP_DUP") must be(Some(OP_DUP))
StackOperation.fromStringOpt("OP_FROMALTSTACK") must be(
Some(OP_FROMALTSTACK))
StackOperation.fromStringOpt("RANDOM_OP") must be(None)
StackOperation.fromStringOpt("OP_IFDUP") must be(Some(OP_IFDUP))
}
}

View file

@ -7,13 +7,13 @@ class AddressTagTest extends BitcoinSUnitTest {
behavior of "AddressTag"
it must "read StorageLocationTag from string" in {
StorageLocationTag.fromString("HotStorage").get must be(
StorageLocationTag.fromString("HotStorage") must be(
StorageLocationTag.HotStorage)
StorageLocationTag.fromString("ColdStorage").get must be(
StorageLocationTag.fromString("ColdStorage") must be(
StorageLocationTag.ColdStorage)
StorageLocationTag.fromString("DeepColdStorage").get must be(
StorageLocationTag.fromString("DeepColdStorage") must be(
StorageLocationTag.DeepColdStorage)
}

View file

@ -7,19 +7,18 @@ class TxoStateTest extends BitcoinSUnitTest {
behavior of "TxoState"
it must "read from string" in {
TxoState.fromString("doesnotexist").get must be(TxoState.DoesNotExist)
TxoState.fromString("doesnotexist") must be(TxoState.DoesNotExist)
TxoState.fromString("PendingConfirmationsReceived").get must be(
TxoState.fromString("PendingConfirmationsReceived") must be(
TxoState.PendingConfirmationsReceived)
TxoState.fromString("ConfirmedReceived").get must be(
TxoState.ConfirmedReceived)
TxoState.fromString("ConfirmedReceived") must be(TxoState.ConfirmedReceived)
TxoState.fromString("Reserved").get must be(TxoState.Reserved)
TxoState.fromString("Reserved") must be(TxoState.Reserved)
TxoState.fromString("PendingConfirmationsSpent").get must be(
TxoState.fromString("PendingConfirmationsSpent") must be(
TxoState.PendingConfirmationsSpent)
TxoState.fromString("ConfirmedSpent").get must be(TxoState.ConfirmedSpent)
TxoState.fromString("ConfirmedSpent") must be(TxoState.ConfirmedSpent)
}
}

View file

@ -1,9 +1,11 @@
package org.bitcoins.core.api.wallet
import org.bitcoins.crypto.StringFactory
/** Represents the various ways the wallet can do coin selection */
sealed abstract class CoinSelectionAlgo
object CoinSelectionAlgo {
object CoinSelectionAlgo extends StringFactory[CoinSelectionAlgo] {
/** Randomly selects utxos until it has enough to fund the desired amount,
* should only be used for research purposes
@ -32,7 +34,13 @@ object CoinSelectionAlgo {
AccumulateSmallestViable,
StandardAccumulate)
def fromString(str: String): Option[CoinSelectionAlgo] = {
override def fromStringOpt(str: String): Option[CoinSelectionAlgo] = {
all.find(state => str.toLowerCase() == state.toString.toLowerCase)
}
override def fromString(string: String): CoinSelectionAlgo = {
val algoOpt = fromStringOpt(string)
algoOpt.getOrElse(
sys.error(s"Could not find coin selection algorithm=${string}"))
}
}

View file

@ -159,7 +159,7 @@ object Networks extends StringFactory[NetworkParameters] {
val p2pkhNetworkBytes: Seq[ByteVector] = BitcoinNetworks.p2pkhNetworkBytes
val p2shNetworkBytes: Seq[ByteVector] = BitcoinNetworks.p2shNetworkBytes
def fromString(string: String): NetworkParameters =
override def fromString(string: String): NetworkParameters =
BitcoinNetworks.fromString(string)
def magicToNetwork: Map[ByteVector, NetworkParameters] =

View file

@ -14,7 +14,8 @@ import org.bitcoins.crypto.{
Factory,
FieldElement,
MaskedToString,
NetworkElement
NetworkElement,
StringFactory
}
import scodec.bits.{ByteVector, HexStringSyntax}
@ -125,13 +126,21 @@ sealed abstract class ExtKey extends NetworkElement {
}
object ExtKey extends Factory[ExtKey] {
object ExtKey extends Factory[ExtKey] with StringFactory[ExtKey] {
val hardenedIdx = UInt32(NumberUtil.pow2(31).toLong)
val masterFingerprint: ByteVector = hex"00000000"
/** Takes in a base58 string and tries to convert it to an extended key */
def fromString(base58: String): Try[ExtKey] = {
override def fromString(base58: String): ExtKey = {
fromStringT(base58) match {
case Success(key) => key
case Failure(exn) =>
throw exn
}
}
override def fromStringT(base58: String): Try[ExtKey] = {
val decoded: Try[ByteVector] = Base58.decodeCheck(base58)
val extKey = decoded.flatMap { bytes =>
require(bytes.size == 78, "Not 78 bytes")
@ -268,7 +277,9 @@ sealed abstract class ExtPrivateKey
}
}
object ExtPrivateKey extends Factory[ExtPrivateKey] {
object ExtPrivateKey
extends Factory[ExtPrivateKey]
with StringFactory[ExtPrivateKey] {
private case class ExtPrivateKeyImpl(
version: ExtKeyPrivVersion,
@ -297,8 +308,8 @@ object ExtPrivateKey extends Factory[ExtPrivateKey] {
}
/** Takes in a base58 string and tries to convert it to an extended private key */
def fromString(base58: String): Try[ExtPrivateKey] =
ExtKey.fromString(base58) match {
override def fromStringT(base58: String): Try[ExtPrivateKey] =
ExtKey.fromStringT(base58) match {
case Success(priv: ExtPrivateKey) => Success(priv)
case Success(_: ExtPublicKey) =>
Failure(
@ -310,11 +321,18 @@ object ExtPrivateKey extends Factory[ExtPrivateKey] {
case Failure(exc) => Failure(exc)
}
override def fromString(base58: String): ExtPrivateKey = {
fromStringT(base58) match {
case Success(key) => key
case Failure(exn) => throw exn
}
}
override def fromBytes(bytes: ByteVector): ExtPrivateKey = {
require(bytes.size == 78, "ExtPrivateKey can only be 78 bytes")
val base58 =
Base58.encode(bytes ++ CryptoUtil.doubleSHA256(bytes).bytes.take(4))
ExtKey.fromString(base58) match {
ExtKey.fromStringT(base58) match {
case Success(priv: ExtPrivateKey) => priv
case Success(_: ExtPublicKey) =>
throw new IllegalArgumentException(
@ -418,7 +436,9 @@ sealed abstract class ExtPublicKey extends ExtKey {
}
}
object ExtPublicKey extends Factory[ExtPublicKey] {
object ExtPublicKey
extends Factory[ExtPublicKey]
with StringFactory[ExtPublicKey] {
private case class ExtPublicKeyImpl(
version: ExtKeyPubVersion,
@ -440,8 +460,8 @@ object ExtPublicKey extends Factory[ExtPublicKey] {
}
/** Takes in a base58 string and tries to convert it to an extended public key */
def fromString(base58: String): Try[ExtPublicKey] =
ExtKey.fromString(base58) match {
override def fromStringT(base58: String): Try[ExtPublicKey] =
ExtKey.fromStringT(base58) match {
case Success(pub: ExtPublicKey) => Success(pub)
case Success(_: ExtPrivateKey) =>
Failure(
@ -453,11 +473,18 @@ object ExtPublicKey extends Factory[ExtPublicKey] {
case Failure(fail) => Failure(fail)
}
override def fromString(base58: String): ExtPublicKey = {
fromStringT(base58) match {
case Success(key) => key
case Failure(exn) => throw exn
}
}
override def fromBytes(bytes: ByteVector): ExtPublicKey = {
require(bytes.size == 78, "ExtPublicKey can only be 78 bytes")
val base58 =
Base58.encode(bytes ++ CryptoUtil.doubleSHA256(bytes).bytes.take(4))
ExtKey.fromString(base58) match {
ExtKey.fromStringT(base58) match {
case Success(_: ExtPrivateKey) =>
throw new IllegalArgumentException(
"Cannot create ext privatkey in ExtPublicKey")

View file

@ -3,7 +3,7 @@ package org.bitcoins.core.hd
import org.bitcoins.core.crypto.ExtKey
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.util.SeqWrapper
import org.bitcoins.crypto.Factory
import org.bitcoins.crypto.{Factory, StringFactory}
import scodec.bits.ByteVector
abstract class BIP32Path extends SeqWrapper[BIP32Node] {
@ -93,7 +93,7 @@ abstract class BIP32Path extends SeqWrapper[BIP32Node] {
}
object BIP32Path extends Factory[BIP32Path] {
object BIP32Path extends Factory[BIP32Path] with StringFactory[BIP32Path] {
private case class BIP32PathImpl(path: Vector[BIP32Node]) extends BIP32Path
/**
@ -125,7 +125,7 @@ object BIP32Path extends Factory[BIP32Path] {
* and [[https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP44]]
* for examples of this notation.
*/
def fromString(string: String): BIP32Path = {
override def fromString(string: String): BIP32Path = {
val parts = string
.split("/")
.toVector
@ -167,7 +167,7 @@ object BIP32Path extends Factory[BIP32Path] {
BIP32Path(path)
}
def fromBytes(bytes: ByteVector): BIP32Path =
override def fromBytes(bytes: ByteVector): BIP32Path =
fromBytes(bytes, littleEndian = false)
override def fromBytesLE(bytes: ByteVector): BIP32Path =

View file

@ -1,6 +1,8 @@
package org.bitcoins.core.hd
import scala.util.Try
import org.bitcoins.crypto.StringFactory
import scala.util.{Failure, Success, Try}
private[bitcoins] trait HDPath extends BIP32Path {
@ -54,12 +56,19 @@ private[bitcoins] trait HDPath extends BIP32Path {
override val path: Vector[BIP32Node] = address.path
}
object HDPath {
object HDPath extends StringFactory[HDPath] {
/** Attempts to parse a string into a valid HD path */
def fromString(string: String): Option[HDPath] =
Try(LegacyHDPath.fromString(string))
.orElse(Try(SegWitHDPath.fromString(string)))
.orElse(Try(NestedSegWitHDPath.fromString(string)))
.toOption
override def fromStringT(string: String): Try[HDPath] =
LegacyHDPath
.fromStringT(string)
.orElse(SegWitHDPath.fromStringT(string))
.orElse(NestedSegWitHDPath.fromStringT(string))
override def fromString(string: String): HDPath = {
fromStringT(string) match {
case Success(path) => path
case Failure(exn) => throw exn
}
}
}

View file

@ -1,8 +1,11 @@
package org.bitcoins.core.hd
import org.bitcoins.crypto.StringFactory
import scala.util.Try
private[hd] trait HDPathFactory[PathType <: BIP32Path] {
private[hd] trait HDPathFactory[PathType <: BIP32Path]
extends StringFactory[PathType] {
private lazy val pathName = getClass.getSimpleName
@ -32,7 +35,7 @@ private[hd] trait HDPathFactory[PathType <: BIP32Path] {
}
/** Parses a string representation of a HD path */
def fromString(string: String): PathType = {
override def fromString(string: String): PathType = {
val bip32Path = BIP32Path.fromString(string)
val children = bip32Path.path

View file

@ -2,7 +2,7 @@ package org.bitcoins.core.p2p
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.serializers.p2p.messages.RawServiceIdentifierSerializer
import org.bitcoins.crypto.{Factory, NetworkElement}
import org.bitcoins.crypto.{Factory, NetworkElement, StringFactory}
import scodec.bits.ByteVector
/**
@ -106,7 +106,9 @@ sealed trait UnknownService extends ServiceIdentifier {
override def toString(): String = s"UnknownService(${num.toLong})"
}
object ServiceIdentifier extends Factory[ServiceIdentifier] {
object ServiceIdentifier
extends Factory[ServiceIdentifier]
with StringFactory[ServiceIdentifier] {
/**
* This node is not a full node.
@ -172,7 +174,7 @@ object ServiceIdentifier extends Factory[ServiceIdentifier] {
def fromBytes(bytes: ByteVector): ServiceIdentifier =
RawServiceIdentifierSerializer.read(bytes)
def fromString(string: String): ServiceIdentifier =
override def fromString(string: String): ServiceIdentifier =
string match {
case "NETWORK" => NODE_NETWORK
case "NETWORK_LIMITED" => NODE_NETWORK_LIMITED

View file

@ -9,6 +9,7 @@ import scala.util.{Failure, Success, Try}
abstract class AddressFactory[T <: Address] extends StringFactory[T] {
/** Same as fromString, but throws the exception */
@deprecated(s"Use fromString() instead", "2020-08-24")
def fromStringExn(str: String): T = fromString(str)
def fromScriptPubKey(spk: ScriptPubKey, np: NetworkParameters): T = {

View file

@ -4,6 +4,7 @@ import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.protocol.ln.LnParams._
import org.bitcoins.core.protocol.ln.currency.{LnCurrencyUnit, LnCurrencyUnits}
import org.bitcoins.core.util.Bech32HumanReadablePart
import org.bitcoins.crypto.StringFactory
import scodec.bits.ByteVector
import scala.util.matching.Regex
@ -34,7 +35,7 @@ sealed abstract class LnHumanReadablePart extends Bech32HumanReadablePart {
override lazy val toString: String = chars
}
object LnHumanReadablePart {
object LnHumanReadablePart extends StringFactory[LnHumanReadablePart] {
/** Prefix for generating a LN invoice on the Bitcoin MainNet */
case class lnbc(override val amount: Option[LnCurrencyUnit])
@ -55,7 +56,7 @@ object LnHumanReadablePart {
}
/** Tries to construct a LN HRP with optional amount specified from the given string */
def apply(bech32: String): Try[LnHumanReadablePart] = fromString(bech32)
def apply(bech32: String): Try[LnHumanReadablePart] = fromStringT(bech32)
def apply(network: NetworkParameters): LnHumanReadablePart = {
val lnNetwork = LnParams.fromNetworkParameters(network)
@ -108,7 +109,7 @@ object LnHumanReadablePart {
* and
* [[https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#Specification BIP173]]
*/
def fromString(bech32: String): Try[LnHumanReadablePart] = {
override def fromStringT(bech32: String): Try[LnHumanReadablePart] = {
//Select all of the letters, until we hit a number, as the network
val networkPattern: Regex = "^[a-z]*".r
val networkStringOpt = networkPattern.findFirstIn(bech32)
@ -136,4 +137,11 @@ object LnHumanReadablePart {
}
}
}
override def fromString(string: String): LnHumanReadablePart = {
fromStringT(string) match {
case Success(hrp) => hrp
case Failure(exn) => throw exn
}
}
}

View file

@ -203,7 +203,7 @@ object LnInvoice extends StringFactory[LnInvoice] with BitcoinSLogger {
throw new IllegalArgumentException("Data part is too short")
} else {
val hrpValid = LnHumanReadablePart.fromString(hrp)
val hrpValid = LnHumanReadablePart.fromStringT(hrp)
val dataValid = Bech32.checkDataValidity(data)

View file

@ -2,6 +2,7 @@ package org.bitcoins.core.protocol.ln
import org.bitcoins.core.number.UInt5
import org.bitcoins.core.util.Bech32
import org.bitcoins.crypto.StringFactory
sealed abstract class LnTagPrefix {
val value: Char
@ -13,7 +14,7 @@ sealed abstract class LnTagPrefix {
* This defines the necessary Lightning Network Tag Prefix's, as specified in BOLT-11
* Please see: https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md#tagged-fields
*/
object LnTagPrefix {
object LnTagPrefix extends StringFactory[LnTagPrefix] {
case class Unknown(value: Char) extends LnTagPrefix
@ -72,11 +73,11 @@ object LnTagPrefix {
.map(prefix => prefix.value -> prefix)
.toMap
def fromString(str: String): Option[LnTagPrefix] = {
override def fromString(str: String): LnTagPrefix = {
if (str.length == 1) {
Option(fromChar(str.head))
fromChar(str.head)
} else {
None
sys.error(s"LnTagPrefix can only be one char in length, got=${str}")
}
}

View file

@ -1,11 +1,13 @@
package org.bitcoins.core.protocol.ln.channel
import org.bitcoins.crypto.StringFactory
/**
* Copied from [[https://github.com/ACINQ/eclair/blob/master/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala Eclair]]
*/
sealed trait ChannelState
object ChannelState {
object ChannelState extends StringFactory[ChannelState] {
case object WAIT_FOR_INIT_INTERNAL extends ChannelState
case object WAIT_FOR_OPEN_CHANNEL extends ChannelState
case object WAIT_FOR_ACCEPT_CHANNEL extends ChannelState
@ -48,7 +50,14 @@ object ChannelState {
ERR_INFORMATION_LEAK
).map(state => state.toString -> state).toMap
def fromString(str: String): Option[ChannelState] = {
override def fromStringOpt(str: String): Option[ChannelState] = {
all.get(str)
}
override def fromString(str: String): ChannelState = {
fromStringOpt(str) match {
case Some(state) => state
case None => sys.error(s"Could not find channel state=${str}")
}
}
}

View file

@ -672,7 +672,7 @@ case class PSBT(
}
}
object PSBT extends Factory[PSBT] {
object PSBT extends Factory[PSBT] with StringFactory[PSBT] {
// The known version of PSBTs this library can process defined by https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#version-numbers
final val knownVersions: Vector[UInt32] = Vector(UInt32.zero)
@ -682,7 +682,7 @@ object PSBT extends Factory[PSBT] {
final val empty = fromUnsignedTx(EmptyTransaction)
def fromString(str: String): PSBT = {
override def fromString(str: String): PSBT = {
ByteVector.fromHex(str) match {
case Some(hex) =>
PSBT(hex)

View file

@ -10,6 +10,7 @@ import org.bitcoins.core.script.reserved.ReservedOperation
import org.bitcoins.core.script.splice.SpliceOperation
import org.bitcoins.core.script.stack.StackOperation
import org.bitcoins.core.util.{BitcoinSLogger, BytesUtil}
import org.bitcoins.crypto.StringFactory
import scodec.bits.ByteVector
/**
@ -17,7 +18,9 @@ import scodec.bits.ByteVector
* Responsible for matching script op codes with their given
* hexadecimal representation or byte representation
*/
trait ScriptOperationFactory[T <: ScriptOperation] extends BitcoinSLogger {
trait ScriptOperationFactory[T <: ScriptOperation]
extends StringFactory[T]
with BitcoinSLogger {
/** All of the [[org.bitcoins.core.script.ScriptOperation ScriptOperation]]s for a particular `T`. */
def operations: Vector[T]
@ -25,7 +28,7 @@ trait ScriptOperationFactory[T <: ScriptOperation] extends BitcoinSLogger {
/**
* Finds a [[org.bitcoins.core.script.ScriptOperation ScriptOperation]] from a given string
*/
def fromString(str: String): Option[T] = {
override def fromStringOpt(str: String): Option[T] = {
val result: Option[T] = operations.find(_.toString == str)
if (result.isEmpty) {
//try and remove the 'OP_' prefix on the operations and see if it matches anything.
@ -34,6 +37,14 @@ trait ScriptOperationFactory[T <: ScriptOperation] extends BitcoinSLogger {
} else result
}
override def fromString(str: String): T = {
fromStringOpt(str) match {
case Some(op) => op
case None =>
sys.error(s"Could not find script operation=${str}")
}
}
/**
* Finds a [[org.bitcoins.core.script.ScriptOperation ScriptOperation]] from its hexadecimal representation.
*/

View file

@ -1,5 +1,7 @@
package org.bitcoins.core.script
import org.bitcoins.crypto.StringFactory
/**
* The different Bitcoin Script type variations
*
@ -38,7 +40,7 @@ sealed abstract class ScriptType {
* and [[https://github.com/bitcoin/bitcoin/blob/03732f8644a449af34f4df1bb3b8915fb15ef22c/src/script/standard.cpp#L27 standarc.cpp]]
* from Bitcoin Core
*/
object ScriptType {
object ScriptType extends StringFactory[ScriptType] {
private[script] val all: Seq[ScriptType] = Vector(
NONSTANDARD,
@ -59,15 +61,15 @@ object ScriptType {
WITNESS_COMMITMENT
)
def fromString(string: String): Option[ScriptType] =
override def fromStringOpt(string: String): Option[ScriptType] =
all.find(_.toString == string)
/** Throws if given string is invalid */
def fromStringExn(string: String): ScriptType =
fromString(string)
.getOrElse(
throw new IllegalArgumentException(
s"$string is not a valid script type!"))
override def fromString(string: String): ScriptType =
fromStringOpt(string) match {
case Some(scriptType) => scriptType
case None => sys.error(s"Could not find scriptType=${string}")
}
final case object NONSTANDARD extends ScriptType

View file

@ -1,11 +1,13 @@
package org.bitcoins.core.script.flag
import org.bitcoins.crypto.StringFactory
/**
* Created by chris on 3/23/16.
* Trait used to create a script flag used to evaluate scripts in a
* certain way
*/
trait ScriptFlagFactory {
trait ScriptFlagFactory extends StringFactory[ScriptFlag] {
/**
* All the [[ScriptFlag]]s found inside of bitcoin core
@ -33,16 +35,23 @@ trait ScriptFlagFactory {
)
/** Takes in a string and tries to match it with a [[ScriptFlag]]. */
def fromString(str: String): Option[ScriptFlag] = {
override def fromStringOpt(str: String): Option[ScriptFlag] = {
flags.find(_.name == str)
}
override def fromString(str: String): ScriptFlag = {
fromStringOpt(str) match {
case Some(flag) => flag
case None => sys.error(s"Could not find ScriptFlag for string=${str}")
}
}
/**
* Parses the given list into[[ScriptFlag]]s
* the strings that do not match a [[ScriptFlag]] are discarded.
*/
def fromList(list: Seq[String]): Seq[ScriptFlag] = {
list.flatMap(fromString(_))
list.flatMap(fromStringOpt(_))
}
/** Parses a list of [[ScriptFlag]]s that is separated by commas. */

View file

@ -4,7 +4,7 @@ import org.bitcoins.core.number.UInt32
import org.bitcoins.core.script._
import org.bitcoins.core.script.constant._
import org.bitcoins.core.util.BytesUtil
import org.bitcoins.crypto.Factory
import org.bitcoins.crypto.{Factory, StringFactory}
import scodec.bits.ByteVector
import scala.annotation.tailrec
@ -13,10 +13,12 @@ import scala.util.Try
/**
* Created by chris on 1/7/16.
*/
sealed abstract class ScriptParser extends Factory[Vector[ScriptToken]] {
sealed abstract class ScriptParser
extends Factory[Vector[ScriptToken]]
with StringFactory[Vector[ScriptToken]] {
/** Parses a list of bytes into a list of script tokens */
def fromBytes(bytes: ByteVector): Vector[ScriptToken] = {
override def fromBytes(bytes: ByteVector): Vector[ScriptToken] = {
val scriptTokens: Vector[ScriptToken] = parse(bytes)
scriptTokens
}
@ -26,7 +28,7 @@ sealed abstract class ScriptParser extends Factory[Vector[ScriptToken]] {
* example: "OP_DUP OP_HASH160 e2e7c1ab3f807151e832dd1accb3d4f5d7d19b4b OP_EQUALVERIFY OP_CHECKSIG"
* example: ["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved (ok if not executed)"] (from script_valid.json)
*/
def fromString(str: String): Vector[ScriptToken] = {
override def fromString(str: String): Vector[ScriptToken] = {
if (
str.size > 1 && str.substring(0, 2) == "0x" && str
.split(" ")
@ -97,8 +99,8 @@ sealed abstract class ScriptParser extends Factory[Vector[ScriptToken]] {
case h +: t if h == "" => loop(t, accum)
case h +: t if h == "0" => loop(t, OP_0.bytes ++ accum)
case h +: t if ScriptOperation.fromString(h).isDefined =>
val op = ScriptOperation.fromString(h).get
case h +: t if ScriptOperation.fromStringOpt(h).isDefined =>
val op = ScriptOperation.fromString(h)
loop(t, op.bytes ++ accum)
case h +: t if tryParsingLong(h) =>
val hexLong =

View file

@ -1,5 +1,7 @@
package org.bitcoins.core.wallet.utxo
import org.bitcoins.crypto.StringFactory
/** A type of address tag, many AddressTags of the same type
* should inherit the AddressTagType that they all share
*/
@ -30,7 +32,7 @@ trait AddressTag {
def !=(at: AddressTag): Boolean = !(this == at)
}
trait AddressTagFactory[Tag <: AddressTag] {
trait AddressTagFactory[Tag <: AddressTag] extends StringFactory[Tag] {
def tagType: AddressTagType
@ -38,6 +40,13 @@ trait AddressTagFactory[Tag <: AddressTag] {
def all: Vector[Tag]
def fromString(str: String): Option[Tag] =
override def fromStringOpt(str: String): Option[Tag] =
all.find(tag => str.toLowerCase() == tag.toString.toLowerCase)
override def fromString(string: String): Tag = {
fromStringOpt(string) match {
case Some(t) => t
case None => sys.error(s"Could not find tag for string=${string}")
}
}
}

View file

@ -1,5 +1,7 @@
package org.bitcoins.core.wallet.utxo
import org.bitcoins.crypto.StringFactory
/**
* An AddressTagNames that is native to Bitcoin-S.
* InternalAddressTagNames are still usable when using Bitcoin-S
@ -51,26 +53,26 @@ object UnknownAddressTag {
UnknownAddressTag(tagName, UnknownAddressTagType(tagType))
}
object InternalAddressTagName {
object InternalAddressTagName extends StringFactory[InternalAddressTagName] {
val all: Seq[InternalAddressTagName] = StorageLocationTag.tagNames
def fromStringOpt(string: String): Option[InternalAddressTagName] =
override def fromStringOpt(string: String): Option[InternalAddressTagName] =
all.find(_.name.toLowerCase == string.toLowerCase)
def fromString(string: String): InternalAddressTagName =
override def fromString(string: String): InternalAddressTagName =
fromStringOpt(string).getOrElse(UnknownAddressTagName(string))
}
object InternalAddressTagType {
object InternalAddressTagType extends StringFactory[InternalAddressTagType] {
val all: Seq[InternalAddressTagType] =
Vector(StorageLocationTagType, AddressLabelTagType)
def fromStringOpt(string: String): Option[InternalAddressTagType] =
override def fromStringOpt(string: String): Option[InternalAddressTagType] =
all.find(_.typeName.toLowerCase == string.toLowerCase)
def fromString(string: String): InternalAddressTagType =
override def fromString(string: String): InternalAddressTagType =
fromStringOpt(string).getOrElse(UnknownAddressTagType(string))
}

View file

@ -1,5 +1,7 @@
package org.bitcoins.core.wallet.utxo
import org.bitcoins.crypto.StringFactory
/** Represents the various states a transaction output can be in */
sealed abstract class TxoState
@ -7,7 +9,7 @@ sealed abstract class ReceivedState extends TxoState
sealed abstract class SpentState extends TxoState
object TxoState {
object TxoState extends StringFactory[TxoState] {
/** Means that no funds have been sent to this utxo EVER */
final case object DoesNotExist extends TxoState
@ -47,7 +49,15 @@ object TxoState {
PendingConfirmationsSpent,
ConfirmedSpent)
def fromString(str: String): Option[TxoState] = {
override def fromStringOpt(str: String): Option[TxoState] = {
all.find(state => str.toLowerCase() == state.toString.toLowerCase)
}
override def fromString(string: String): TxoState = {
fromStringOpt(string) match {
case Some(state) => state
case None =>
sys.error(s"Could not find txo state for string=${string}")
}
}
}

View file

@ -375,7 +375,7 @@ class AesCryptTest extends BitcoinSUnitTest {
}
it must "fail to create an empty AES password" in {
assert(AesPassword.fromString("").isEmpty)
assert(AesPassword.fromStringOpt("").isEmpty)
intercept[IllegalArgumentException] {
AesPassword.fromNonEmptyString("")
}

View file

@ -131,7 +131,7 @@ final case class AesPassword private (private val value: String)
}
}
object AesPassword {
object AesPassword extends StringFactory[AesPassword] {
private val KEY_SIZE = 256
private val ITERATIONS = 65536
@ -142,15 +142,24 @@ object AesPassword {
/** Tries to construct a password from the given string. Fails
* if the string is empty.
*/
def fromString(string: String): Option[AesPassword] = {
override def fromStringOpt(string: String): Option[AesPassword] = {
if (string.isEmpty) None else Some(AesPassword(string))
}
override def fromString(string: String): AesPassword = {
fromStringOpt(string) match {
case Some(password) => password
case None =>
sys.error(
s"Could not construct AesPassword from given string, not logging in case it's sensitive")
}
}
/** Constructs a password from the given string. Throws
* if the string is empty.
*/
def fromNonEmptyString(string: String): AesPassword =
fromString(string).getOrElse(
fromStringOpt(string).getOrElse(
throw new IllegalArgumentException(
"Cannot construct empty AES passwords!"))
}

View file

@ -164,7 +164,7 @@ class DbCommonsColumnMappers(val profile: JdbcProfile) {
implicit val xpubMapper: BaseColumnType[ExtPublicKey] = {
MappedColumnType
.base[ExtPublicKey, String](_.toString, ExtPublicKey.fromString(_).get)
.base[ExtPublicKey, String](_.toString, ExtPublicKey.fromString(_))
}
implicit val hdCoinTypeMapper: BaseColumnType[HDCoinType] = {
@ -173,15 +173,11 @@ class DbCommonsColumnMappers(val profile: JdbcProfile) {
implicit val hdPathMappper: BaseColumnType[HDPath] =
MappedColumnType
.base[HDPath, String](_.toString,
HDPath.fromString(_).get
) // hm rethink .get?
.base[HDPath, String](_.toString, HDPath.fromString(_))
implicit val segwitPathMappper: BaseColumnType[SegWitHDPath] =
MappedColumnType
.base[SegWitHDPath, String](_.toString,
SegWitHDPath.fromString
) // hm rethink .get?
.base[SegWitHDPath, String](_.toString, SegWitHDPath.fromString)
implicit val hdChainTypeMapper: BaseColumnType[HDChainType] =
MappedColumnType.base[HDChainType, Int](_.index, HDChainType.fromInt)
@ -194,15 +190,15 @@ class DbCommonsColumnMappers(val profile: JdbcProfile) {
implicit val bitcoinAddressMapper: BaseColumnType[BitcoinAddress] =
MappedColumnType
.base[BitcoinAddress, String](_.value, BitcoinAddress.fromStringExn)
.base[BitcoinAddress, String](_.value, BitcoinAddress.fromString)
implicit val bech32AddressMapper: BaseColumnType[Bech32Address] =
MappedColumnType
.base[Bech32Address, String](_.value, Bech32Address.fromStringExn)
.base[Bech32Address, String](_.value, Bech32Address.fromString)
implicit val scriptTypeMapper: BaseColumnType[ScriptType] =
MappedColumnType
.base[ScriptType, String](_.toString, ScriptType.fromStringExn)
.base[ScriptType, String](_.toString, ScriptType.fromString)
implicit val txMapper: BaseColumnType[Transaction] =
MappedColumnType.base[Transaction, String](_.hex, Transaction.fromHex)
@ -217,7 +213,7 @@ class DbCommonsColumnMappers(val profile: JdbcProfile) {
implicit val txoStateMapper: BaseColumnType[TxoState] = {
MappedColumnType
.base[TxoState, String](_.toString, TxoState.fromString(_).get)
.base[TxoState, String](_.toString, TxoState.fromString(_))
}
implicit val satoshisPerByteMapper: BaseColumnType[SatoshisPerByte] = {

View file

@ -127,7 +127,7 @@ object UserIdTags extends AddressTagFactory[UserIdTag] {
override val tagNames = Vector(CompanyTagName, InsuranceFundTagName)
override def fromString(str: String): Option[UserIdTag] = {
override def fromStringOpt(str: String): Option[UserIdTag] = {
all.find(tag => str.toLowerCase() == tag.toString.toLowerCase) match {
case Some(tag) =>
Some(tag)
@ -136,6 +136,14 @@ object UserIdTags extends AddressTagFactory[UserIdTag] {
}
}
override def fromString(str: String): UserIdTag = {
fromStringOpt(str) match {
case Some(tag) => tag
case None => sys.error(s"Could not find tag=$str")
}
}
def fromUID(uid: Long): UserIdTag = {
UserId(uid.toString)
}

View file

@ -10,7 +10,7 @@ class NodeUriTest extends BitcoinSAsyncTest {
it must "read the suredbits node uri" in {
val sb =
"0338f57e4e20abf4d5c86b71b59e995ce4378e373b021a7b6f41dabb42d3aad069@ln.test.suredbits.com:9735"
val uriT = NodeUri.fromString(sb)
val uriT = NodeUri.fromStringT(sb)
assert(uriT.isSuccess == true)
assert(uriT.get.toString == sb)
@ -29,7 +29,7 @@ class NodeUriTest extends BitcoinSAsyncTest {
val sb =
"0338f57e4e20abf4d5c86b71b59e995ce4378e373b021a7b6f41dabb42d3aad069@127.0.0.1:9735"
val uriT = NodeUri.fromString(sb)
val uriT = NodeUri.fromStringT(sb)
assert(uriT.isSuccess)
@ -38,14 +38,14 @@ class NodeUriTest extends BitcoinSAsyncTest {
it must "fail to read a node uri without a nodeId" in {
val sb = "@ln.test.suredbits.com"
val uriT = NodeUri.fromString(sb)
val uriT = NodeUri.fromStringT(sb)
assert(uriT.isFailure == true)
}
it must "fail to read a node uri with a invalid port" in {
val sb =
"0338f57e4e20abf4d5c86b71b59e995ce4378e373b021a7b6f41dabb42d3aad069@ln.test.suredbits.com:abc2"
val uriT = NodeUri.fromString(sb)
val uriT = NodeUri.fromStringT(sb)
assert(uriT.isFailure == true)
}
}

View file

@ -1,6 +1,7 @@
package org.bitcoins.eclair.rpc.network
import org.bitcoins.core.protocol.ln.node.NodeId
import org.bitcoins.crypto.StringFactory
import scala.util.{Failure, Success, Try}
@ -8,11 +9,11 @@ case class NodeUri(nodeId: NodeId, host: String, port: Int) {
override def toString = s"$nodeId@$host:$port"
}
object NodeUri {
object NodeUri extends StringFactory[NodeUri] {
private val defaultPort = ":9735"
def fromString(uri: String): Try[NodeUri] = {
override def fromStringT(uri: String): Try[NodeUri] = {
val patternWithPort = """(\w+)@([\w.]+(\w+)):(\d{2,5})""".r
val isUriWithPort = patternWithPort.findFirstIn(uri)
@ -27,8 +28,15 @@ object NodeUri {
nodeUriT
}
override def fromString(string: String): NodeUri = {
fromStringT(string) match {
case Success(uri) => uri
case Failure(exn) => throw exn
}
}
def fromStringNoPort(uri: String): Try[NodeUri] = {
fromString(uri + defaultPort)
fromStringT(uri + defaultPort)
}
/**

View file

@ -29,7 +29,7 @@ class BIP39LockedKeyManagerApiTest extends KeyManagerApiUnitTest {
it must "fail to read bad json in the seed file" in {
val km = withInitializedKeyManager()
val badPassword = AesPassword.fromString("other bad password").get
val badPassword = AesPassword.fromString("other bad password")
val unlockedE = BIP39LockedKeyManager.unlock(passphrase = badPassword,
bip39PasswordOpt = None,
kmParams = km.kmParams)
@ -47,7 +47,7 @@ class BIP39LockedKeyManagerApiTest extends KeyManagerApiUnitTest {
val km = withInitializedKeyManager()
val badPath = km.kmParams.copy(seedPath = badSeedPath)
val badPassword = AesPassword.fromString("other bad password").get
val badPassword = AesPassword.fromString("other bad password")
val unlockedE = BIP39LockedKeyManager.unlock(badPassword, None, badPath)
unlockedE match {

View file

@ -87,7 +87,7 @@ case class BIP39KeyManager(
object BIP39KeyManager
extends BIP39KeyManagerCreateApi[BIP39KeyManager]
with BitcoinSLogger {
val badPassphrase = AesPassword.fromString("changeMe").get
val badPassphrase = AesPassword.fromString("changeMe")
/** Initializes the mnemonic seed and saves it to file */
override def initializeWithEntropy(

View file

@ -62,7 +62,7 @@ class TrezorAddressTest extends BitcoinSWalletTest with EmptyFixture {
override def reads(json: JsValue): JsResult[HDPath] =
json
.validate[String]
.flatMap(HDPath.fromString(_) match {
.flatMap(HDPath.fromStringOpt(_) match {
case None => JsError(s"Could not read $json")
case Some(value) => JsSuccess(value)
})