2020 06 09 addr invoice string factory (#1538)

* Implement StringFactory with Address and LnInvoice

* Address code review

* Run scalafmt
This commit is contained in:
Chris Stewart 2020-06-11 10:44:12 -05:00 committed by GitHub
parent 5c2fb8f580
commit c54d6dcbdc
26 changed files with 163 additions and 136 deletions

View File

@ -227,7 +227,7 @@ object JsonReaders {
implicit object AddressReads extends Reads[Address] {
override def reads(json: JsValue): JsResult[Address] = json match {
case JsString(s) =>
Address.fromString(s) match {
Address.fromStringT(s) match {
case Success(address) => JsSuccess(address)
case Failure(err) =>
SerializerUtil.buildErrorMsg("address", err)
@ -279,7 +279,7 @@ object JsonReaders {
implicit object P2PKHAddressReads extends Reads[P2PKHAddress] {
override def reads(json: JsValue): JsResult[P2PKHAddress] = json match {
case JsString(s) =>
P2PKHAddress.fromString(s) match {
P2PKHAddress.fromStringT(s) match {
case Success(address) => JsSuccess(address)
case Failure(err) =>
SerializerUtil.buildErrorMsg("p2pkhaddress", err)
@ -293,7 +293,7 @@ object JsonReaders {
implicit object P2SHAddressReads extends Reads[P2SHAddress] {
override def reads(json: JsValue): JsResult[P2SHAddress] = json match {
case JsString(s) =>
P2SHAddress.fromString(s) match {
P2SHAddress.fromStringT(s) match {
case Success(address) => JsSuccess(address)
case Failure(err) =>
SerializerUtil.buildErrorMsg("p2shaddress", err)
@ -338,7 +338,7 @@ object JsonReaders {
implicit object BitcoinAddressReads extends Reads[BitcoinAddress] {
override def reads(json: JsValue): JsResult[BitcoinAddress] = json match {
case JsString(s) =>
BitcoinAddress.fromString(s) match {
BitcoinAddress.fromStringT(s) match {
case Success(address) =>
JsSuccess(address)
case Failure(err) =>
@ -392,7 +392,7 @@ object JsonReaders {
.map(_.asInstanceOf[JsString].value)
val addressResult = jsStrings.find(BitcoinAddress.isValid) match {
case Some(s) =>
BitcoinAddress.fromString(s) match {
BitcoinAddress.fromStringT(s) match {
case Success(a) => JsSuccess(a)
case Failure(err) =>
SerializerUtil.buildErrorMsg("address", err)
@ -996,7 +996,7 @@ object JsonReaders {
implicit val lnInvoiceReads: Reads[LnInvoice] =
Reads[LnInvoice] {
case JsString(invoice) =>
LnInvoice.fromString(invoice) match {
LnInvoice.fromStringT(invoice) match {
case Success(paymentRequest) => JsSuccess(paymentRequest)
case Failure(err) =>
JsError(s"Invalid refund invoice: ${err.toString}")

View File

@ -599,7 +599,7 @@ object JsonSerializers {
implicit def mapAddressesByLabelReads: Reads[
Map[BitcoinAddress, LabelResult]] =
Reads.mapReads[BitcoinAddress, LabelResult](s =>
JsSuccess(BitcoinAddress.fromString(s).get))
JsSuccess(BitcoinAddress.fromString(s)))
implicit def mapBitcoinerLiveEstimateReads: Reads[
Map[Int, BitcoinerLiveEstimate]] =

View File

@ -46,7 +46,7 @@ class WalletGUIModel() {
taskRunner.run(
caption = s"Send $amount to $address",
op = {
ConsoleCli.exec(SendToAddress(BitcoinAddress(address).get,
ConsoleCli.exec(SendToAddress(BitcoinAddress.fromString(address),
Bitcoins(BigDecimal(amount)),
satoshisPerVirtualByte = None),
Config.empty) match {

View File

@ -48,7 +48,7 @@ class RoutesSpec
// the genesis address
val testAddressStr = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
val testAddress = BitcoinAddress(testAddressStr).get
val testAddress = BitcoinAddress.fromString(testAddressStr)
val mockWalletApi = mock[MockWalletApi]

View File

@ -261,8 +261,8 @@ class WalletRpcTest extends BitcoindRpcTest {
(BitcoinAddress.fromScriptPubKey(out.scriptPubKey, networkParam),
out.value))
assert(changeAddresses.size == 1)
assert(changeAddresses.head._1.get != address)
(changeAddresses.head._1.get, changeAddresses.head._2)
assert(changeAddresses.head._1 != address)
(changeAddresses.head._1, changeAddresses.head._2)
}
}
@ -360,7 +360,6 @@ class WalletRpcTest extends BitcoindRpcTest {
val address = Bech32Address
.fromString("bcrt1q9h9wkz6ad49szfl035wh3qdacuslkp6j9pfp4j")
.get
for {
(client, otherClient, _) <- clientsF

View File

@ -78,7 +78,7 @@ trait WalletRpc { self: Client =>
List(JsString(accountOrLabel)) ++ addressType.map(Json.toJson(_)).toList
bitcoindCall[BitcoinAddress]("getnewaddress", params).map(addr =>
BitcoinAddress.fromScriptPubKey(addr.scriptPubKey, instance.network).get)
BitcoinAddress.fromScriptPubKey(addr.scriptPubKey, instance.network))
}
def getNewAddress: Future[BitcoinAddress] =

View File

@ -9,17 +9,17 @@ import org.bitcoins.testkit.util.{BitcoinSUnitTest, TestUtil}
class AddressFactoryTest extends BitcoinSUnitTest {
"AddressFactory" must "create an address from a base58 encoded string" in {
Address(TestUtil.bitcoinAddress.get.value) must be(TestUtil.bitcoinAddress)
Address(TestUtil.bitcoinAddress.value) must be(TestUtil.bitcoinAddress)
}
it must "create an address from a sequence of bytes" in {
val decoded = Base58.decode(TestUtil.bitcoinAddress.get.value)
val decoded = Base58.decode(TestUtil.bitcoinAddress.value)
Address(decoded) must be(TestUtil.bitcoinAddress)
}
it must "throw an exception if we give a hex string to create a bitcoin address from" in {
intercept[IllegalArgumentException] {
throw Address.fromHex("01234567890abcdef").failed.get
Address.fromHex("01234567890abcdef")
}
}
}

View File

@ -12,13 +12,13 @@ class AddressTest extends BitcoinSUnitTest {
it must "have serialization symmetry" in {
forAll(AddressGenerator.address) { addr =>
val fromSPK = Address
.fromScriptPubKey(addr.scriptPubKey, addr.networkParameters)
.fromScriptPubKeyT(addr.scriptPubKey, addr.networkParameters)
fromSPK match {
case Success(newAddr) => assert(newAddr.value == addr.value)
case Failure(exception) => fail(exception.getMessage)
}
val fromStringT = Address.fromString(addr.value)
val fromStringT = Address.fromStringT(addr.value)
fromStringT match {
case Success(newAddr) => assert(newAddr.value == addr.value)
case Failure(exception) => fail(exception.getMessage)

View File

@ -46,7 +46,7 @@ class Bech32Spec extends Properties("Bech32Spec") {
val replacementChar = pickReplacementChar(l.head)
val replaced = s"$f$replacementChar${l.tail}"
//should fail because we replaced a char in the addr, so checksum invalid
Bech32Address.fromString(replaced).isFailure
Bech32Address.fromStringT(replaced).isFailure
}
}
@ -55,7 +55,7 @@ class Bech32Spec extends Properties("Bech32Spec") {
val old = addr.value
val replaced = switchCaseRandChar(old)
//should fail because we we switched the case of a random char
val actual = Bech32Address.fromString(replaced)
val actual = Bech32Address.fromStringT(replaced)
actual.isFailure
}
}

View File

@ -21,7 +21,7 @@ class Bech32Test extends BitcoinSUnitTest {
it must "decode a regtest address from Bitcoin Core" in {
val addrStr = "bcrt1qq6w6pu6zq90az9krn53zlkvgyzkyeglzukyepf"
val addrT = Address.fromString(addrStr)
val addrT = Address.fromStringT(addrStr)
addrT match {
case Success(addr: Bech32Address) => assert(addr.value == addrStr)
case _ => fail()

View File

@ -49,7 +49,7 @@ class BitcoinAddressSpec extends Properties("BitcoinAddressSpec") {
Prop.forAll(AddressGenerator.address) { addr =>
val spk = addr.scriptPubKey
val network = addr.networkParameters
Address.fromScriptPubKey(spk, network).get == addr
Address.fromScriptPubKey(spk, network) == addr
}
}
}

View File

@ -17,7 +17,7 @@ class BitcoinAddressTest extends BitcoinSUnitTest {
"3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy" must "be a valid bitcoin address" in {
val address = "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy"
BitcoinAddress(address).get.value must be(address)
BitcoinAddress(address).value must be(address)
}
@ -35,7 +35,7 @@ class BitcoinAddressTest extends BitcoinSUnitTest {
"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq" must "be a valid Bech32 address" in {
val address = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq"
Address.fromString(address) match {
Address.fromStringT(address) match {
case Success(bech: Bech32Address) =>
assert(bech.networkParameters == MainNet)
case Success(other: BitcoinAddress) =>
@ -46,7 +46,7 @@ class BitcoinAddressTest extends BitcoinSUnitTest {
"tb1q9yqzjcywvuy9lz2vuvv6xmkhe7zg9kkp35mdrn" must "be a valid Bech32 address" in {
val address = "tb1q9yqzjcywvuy9lz2vuvv6xmkhe7zg9kkp35mdrn"
Address.fromString(address) match {
Address.fromStringT(address) match {
case Success(bech: Bech32Address) =>
assert(bech.networkParameters == TestNet3)
case Success(other: BitcoinAddress) =>
@ -57,7 +57,7 @@ class BitcoinAddressTest extends BitcoinSUnitTest {
"bcrt1q03nrxf0s99sny47mp47a8grdvrcph2v4c78rvd" must "be a valid Bec32 addres" in {
val address = "bcrt1q03nrxf0s99sny47mp47a8grdvrcph2v4c78rvd"
Address.fromString(address) match {
Address.fromStringT(address) match {
case Success(bech: Bech32Address) =>
assert(bech.networkParameters == RegTest)
case Success(other: BitcoinAddress) =>
@ -67,24 +67,24 @@ class BitcoinAddressTest extends BitcoinSUnitTest {
}
"The empty string" must "not be a valid bitcoin address" in {
BitcoinAddress.fromString("").isFailure must be(true)
BitcoinAddress.fromStringT("").isFailure must be(true)
Try(BitcoinAddress.fromStringExn("")).isFailure must be(true)
}
"A string that is 25 characters long" must "not be a valid bitcoin address" in {
val address = "3J98t1WpEZ73CNmQviecrnyiW"
BitcoinAddress.fromString(address).isFailure must be(true)
BitcoinAddress.fromStringT(address).isFailure must be(true)
}
"A string that is 36 characters long" must "not be a valid bitcoin address" in {
val address = "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLyyy"
BitcoinAddress.fromString(address).isFailure must be(true)
BitcoinAddress.fromStringT(address).isFailure must be(true)
}
it must "encode a pubKeyHash to an address" in {
//from https://stackoverflow.com/questions/19233053/hashing-from-a-public-key-to-a-bitcoin-address-in-php
val hash = Sha256Hash160Digest("010966776006953d5567439e5e39f86a0d273bee")
val address = Address("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM").get
val address = Address("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM")
P2PKHAddress(hash, MainNet) must be(address)
}
@ -94,38 +94,39 @@ class BitcoinAddressTest extends BitcoinSUnitTest {
"455141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51ae"
val scriptPubKey = ScriptPubKey(hex)
val addr = P2SHAddress(scriptPubKey, MainNet)
addr must be(BitcoinAddress("3P14159f73E4gFr7JterCCQh9QjiTjiZrG").get)
addr must be(BitcoinAddress("3P14159f73E4gFr7JterCCQh9QjiTjiZrG"))
}
it must "create a bech32 address from a WitnessScriptPubKey" in {
val scriptPubKey = P2WPKHWitnessSPKV0(ECPublicKey.freshPublicKey)
assert(Bech32Address.fromScriptPubKey(scriptPubKey, RegTest).isSuccess)
assert(Bech32Address.fromScriptPubKeyT(scriptPubKey, RegTest).isSuccess)
}
it must "fail to create a bech32 address from an invalid ScriptPubKey" in {
assert(Bech32Address.fromScriptPubKey(EmptyScriptPubKey, RegTest).isFailure)
assert(
Bech32Address.fromScriptPubKeyT(EmptyScriptPubKey, RegTest).isFailure)
}
it must "create an address from a P2PKHScriptPubKey" in {
val scriptPubKey = P2PKHScriptPubKey(ECPublicKey.freshPublicKey)
assert(P2PKHAddress.fromScriptPubKey(scriptPubKey, RegTest).isSuccess)
assert(P2PKHAddress.fromScriptPubKeyT(scriptPubKey, RegTest).isSuccess)
}
it must "fail to create a P2PKHAddress address from an invalid ScriptPubKey" in {
assert(P2PKHAddress.fromScriptPubKey(EmptyScriptPubKey, RegTest).isFailure)
assert(P2PKHAddress.fromScriptPubKeyT(EmptyScriptPubKey, RegTest).isFailure)
}
it must "create an address from a P2SHScriptPubKey" in {
val scriptPubKey = P2SHScriptPubKey(EmptyScriptPubKey)
assert(P2SHAddress.fromScriptPubKey(scriptPubKey, RegTest).isSuccess)
assert(P2SHAddress.fromScriptPubKeyT(scriptPubKey, RegTest).isSuccess)
}
it must "fail to create a P2SHScriptPubKey address from an invalid ScriptPubKey" in {
assert(P2SHAddress.fromScriptPubKey(EmptyScriptPubKey, RegTest).isFailure)
assert(P2SHAddress.fromScriptPubKeyT(EmptyScriptPubKey, RegTest).isFailure)
}
it must "create an address from a ScriptPubKey" in {
val scriptPubKey = P2SHScriptPubKey(EmptyScriptPubKey)
assert(Address.fromScriptPubKey(scriptPubKey, RegTest).isSuccess)
assert(Address.fromScriptPubKeyT(scriptPubKey, RegTest).isSuccess)
}
}

View File

@ -85,7 +85,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
serialized must be(
"lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w")
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get.toString must be(invoice.toString)
}
@ -111,7 +111,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
serialized must be(
"lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspfj9srp")
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get.toString must be(invoice.toString)
}
@ -145,7 +145,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
invoice.toString must be(
"lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny")
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get must be(invoice)
}
@ -176,7 +176,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
invoice.toString must be(
"lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqscc6gd6ql3jrc5yzme8v4ntcewwz5cnw92tz0pc8qcuufvq7khhr8wpald05e92xw006sq94mg8v2ndf4sefvf9sygkshp5zfem29trqq2yxxz7")
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get must be(invoice)
}
@ -188,7 +188,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
"3925b6f67e2c340036ed12093dd44e0368df1b6ea26c53dbe4811f58fd5db8c1")
val descriptionHashTagE = Right(LnTag.DescriptionHashTag(descriptionHash))
val fallbackAddr = LnTag.FallbackAddressTag(
P2PKHAddress.fromString("mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP").get)
P2PKHAddress.fromString("mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP"))
val lnTags = LnTaggedFields(paymentHash = paymentTag,
descriptionOrHash = descriptionHashTagE,
@ -209,7 +209,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
//For that reason, the example #5 output we are matching against has been modified to fit the order in which we encode our invoices.
//TODO: Add checksum data to check
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get.toString must be(serialized)
}
@ -218,7 +218,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
"lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzqj9n4evl6mr5aj9f58zp6fyjzup6ywn3x6sk8akg5v4tgn2q8g4fhx05wf6juaxu9760yp46454gpg5mtzgerlzezqcqvjnhjh8z3g2qqdhhwkj"
val fallbackAddr = LnTag.FallbackAddressTag(
P2PKHAddress.fromString("1RustyRX2oai4EYYDpQGWvEL62BBGqN9T").get)
P2PKHAddress.fromString("1RustyRX2oai4EYYDpQGWvEL62BBGqN9T"))
val signature = ECDigitalSignature.fromRS(
"91675cb3fad8e9d915343883a49242e074474e26d42c7ed914655689a8074553733e8e4ea5ce9b85f69e40d755a55014536b12323f8b220600c94ef2b9c51428")
@ -258,7 +258,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
val serialized = lnInvoice.toString
serialized must be(expected)
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get.toString must be(serialized)
}
@ -270,7 +270,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
"4nvjcpxlekvmxl6qcs9j3tz0469gqsjurz5"
val fallbackAddr = LnTag.FallbackAddressTag(
P2SHAddress.fromString("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX").get)
P2SHAddress.fromString("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"))
val lnTags = LnTaggedFields(paymentHash = paymentTag,
descriptionOrHash = descpriptionHashTag,
@ -289,7 +289,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
lnInvoice.toString must be(expected)
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get.toString must be(serialized)
}
@ -306,8 +306,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
val fallbackAddr = LnTag.FallbackAddressTag(
Bech32Address
.fromString("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")
.get)
.fromString("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"))
val lnTags = LnTaggedFields(paymentHash = paymentTag,
descriptionOrHash = descpriptionHashTag,
@ -328,7 +327,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
serialized must be(expected)
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get must be(lnInvoice)
}
@ -344,8 +343,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
val fallbackAddr = LnTag.FallbackAddressTag(
Bech32Address
.fromString(
"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3")
.get)
"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3"))
val lnTags = LnTaggedFields(paymentHash = paymentTag,
descriptionOrHash = descpriptionHashTag,
@ -366,7 +364,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
lnInvoice.toString must be(expected)
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get must be(lnInvoice)
}
@ -404,7 +402,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
// TODO uncomment when https://github.com/bitcoin-s/bitcoin-s/issues/1064 is fixed
// serialized must be(expected)
val deserialized = LnInvoice.fromString(serialized)
val deserialized = LnInvoice.fromStringT(serialized)
deserialized.get.toString must be(serialized)
}
@ -414,7 +412,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
val bech32 =
"lnbcrt1m1pd6ssf3pp5mqcepx6yzx7uu0uagw5x3c7kqhnpwr3mfn844hjux8tlza6ztr7sdqqxqrrss0rl3gzer9gfc54fs84rd4xk6g8nf0syharnnyljc9za933memdzxrjz0v2v94ntuhdxduk3z0nlmpmznryvvvl4gzgu28kjkm4ey98gpmyhjfa"
val invoiceT = LnInvoice.fromString(bech32)
val invoiceT = LnInvoice.fromStringT(bech32)
val deserialized = invoiceT.get.toString
@ -430,7 +428,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
it must "have serialization symmetry for the invoices" in {
forAll(LnInvoiceGen.lnInvoice) { invoice =>
LnInvoice.fromString(invoice.toString).get == invoice
LnInvoice.fromStringT(invoice.toString).get == invoice
}
}
@ -472,7 +470,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
"6b80b9b7320bc1203534e78f86b6a32945c35ab464e475ed00e92c7b98755f9d"
val str =
"lntb100n1pwz34mzpp5dwqtndejp0qjqdf5u78cdd4r99zuxk45vnj8tmgqayk8hxr4t7wsd890v3xgatjv96xjmmwygarzvpsxqczcgnrdpskumn9ds3r5gn5wfskgetnygkzyetkv4h8gg36yfeh2cnnvdexjcn9ygkzyat4d9jzyw3zxqcrzvfjxgenxtf5xs6n2tfkxcmnwtfc8qunjttpv93xycmrv3jx2etxvc3zcgn90p3ksctwvajjyw3zvf5hgenfdejhsg3vyfehjmtzdakzyw3zgf2yx42ngs386xqrrssqr6xn7dtkyxk0rhl98k3esksst578uwhud5glp9svq24ddwlgqwz6v9uf7mqljrj07xl87ufrn4yfplrsz2vpmc9xwv44634h54dq3sq257hh4"
val invoice = LnInvoice.fromString(str).get
val invoice = LnInvoice.fromStringT(str).get
invoice.lnTags.paymentHash.hash.hex must be(expectedHash)
@ -504,7 +502,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
// generated by Eclair 3.3.0-SNAPSHOT
val serialized =
"lnbcrt10n1p0px7lfpp5ghc2y7ttnwy58jx0dfcsdxy7ey0qfryn0wcmm04ckud0qw73kt9sdq9vehk7xqrrss9qypqqqsp5qlf6efygd26y03y66jdqqfmlxthplnu5cc8648fgn88twhpyvmgqg9k5kd0k8vv3xvvqpkhkt9chdl579maq45gvck4g0yd0eggmvfkzgvjmwn29r99p57tgyl3l3s82hlc4e97at55xl5lyzpfk6n36yyqqxeem8q"
val invoice = LnInvoice.fromString(serialized).get
val invoice = LnInvoice.fromStringT(serialized).get
invoice.lnTags.secret must be(
Some(LnTag.SecretTag(PaymentSecret.fromHex(
"07d3aca4886ab447c49ad49a00277f32ee1fcf94c60faa9d2899ceb75c2466d0"))))
@ -517,7 +515,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
val strWithError =
"lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspfj9srqqqqqp"
assert(LnInvoice.fromString(strWithError).isFailure)
assert(LnInvoice.fromStringT(strWithError).isFailure)
}
it must "parse unknown tags" in {
@ -536,7 +534,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
LnTaggedFields(Vector(paymentTag, descriptionTag, unknownTag))
val expected = LnInvoice(hrpTestNetMilli, time, tags, key)
val serialized = expected.toString
val deserialized = LnInvoice.fromString(serialized).get
val deserialized = LnInvoice.fromStringT(serialized).get
deserialized must be(expected)
deserialized.toString must be(serialized)
deserialized.lnTags.tags.size must be(3)
@ -547,7 +545,7 @@ class LnInvoiceUnitTest extends BitcoinSUnitTest {
it must "recover public keys" in {
def testInvoice(str: String, nodeId: String): Unit = {
val i = LnInvoice.fromString(str).get
val i = LnInvoice.fromStringT(str).get
i.toString must be(str)
i.nodeId must be(NodeId.fromHex(nodeId))
}

View File

@ -152,7 +152,7 @@ object Bech32Address extends AddressFactory[Bech32Address] {
/** Tries to convert the given string a to a
* [[org.bitcoins.core.protocol.script.WitnessScriptPubKey WitnessScriptPubKey]] */
def fromStringToWitSPK(string: String): Try[WitnessScriptPubKey] = {
val decoded = fromString(string)
val decoded = fromStringT(string)
decoded.flatMap {
case bech32Addr =>
val bytes = bech32Addr.data
@ -182,14 +182,19 @@ object Bech32Address extends AddressFactory[Bech32Address] {
}
/** Decodes bech32 string to the [[org.bitcoins.core.protocol.BtcHumanReadablePart HumanReadablePart]] & data part */
override def fromString(bech32: String): Try[Bech32Address] = {
for {
override def fromString(bech32: String): Bech32Address = {
val bech32T = for {
(hrp, data) <- Bech32.splitToHrpAndData(bech32)
btcHrp <- BtcHumanReadablePart(hrp)
} yield Bech32Address(btcHrp, data)
bech32T match {
case Success(bech32) => bech32
case Failure(exn) => throw exn
}
}
override def fromScriptPubKey(
override def fromScriptPubKeyT(
spk: ScriptPubKey,
np: NetworkParameters): Try[Bech32Address] =
spk match {
@ -232,9 +237,9 @@ object P2PKHAddress extends AddressFactory[P2PKHAddress] {
P2PKHAddress(spk.pubKeyHash, networkParameters)
}
override def fromString(address: String): Try[P2PKHAddress] = {
override def fromString(address: String): P2PKHAddress = {
val decodeCheckP2PKH: Try[ByteVector] = Base58.decodeCheck(address)
decodeCheckP2PKH.flatMap { bytes =>
val p2pkhT = decodeCheckP2PKH.flatMap { bytes =>
val networkBytes: Option[(NetworkParameters, ByteVector)] =
Networks.knownNetworks
.map(n => (n, n.p2pkhNetworkByte))
@ -259,9 +264,14 @@ object P2PKHAddress extends AddressFactory[P2PKHAddress] {
s"Given address was not a valid P2PKH address, got: $address"))
}
}
p2pkhT match {
case Success(p2pkh) => p2pkh
case Failure(exn) => throw exn
}
}
override def fromScriptPubKey(
override def fromScriptPubKeyT(
spk: ScriptPubKey,
np: NetworkParameters): Try[P2PKHAddress] =
spk match {
@ -306,9 +316,9 @@ object P2SHAddress extends AddressFactory[P2SHAddress] {
network: NetworkParameters): P2SHAddress =
P2SHAddressImpl(hash, network)
override def fromString(address: String): Try[P2SHAddress] = {
override def fromString(address: String): P2SHAddress = {
val decodeCheckP2SH: Try[ByteVector] = Base58.decodeCheck(address)
decodeCheckP2SH.flatMap { bytes =>
val p2shT = decodeCheckP2SH.flatMap { bytes =>
val networkBytes: Option[(NetworkParameters, ByteVector)] =
Networks.knownNetworks
.map(n => (n, n.p2shNetworkByte))
@ -333,9 +343,14 @@ object P2SHAddress extends AddressFactory[P2SHAddress] {
s"Given address was not a valid P2PKH address, got: $address"))
}
}
p2shT match {
case Success(p2sh) => p2sh
case Failure(exn) => throw exn
}
}
override def fromScriptPubKey(
override def fromScriptPubKeyT(
spk: ScriptPubKey,
np: NetworkParameters): Try[P2SHAddress] =
spk match {
@ -355,18 +370,23 @@ object P2SHAddress extends AddressFactory[P2SHAddress] {
object BitcoinAddress extends AddressFactory[BitcoinAddress] {
/** Creates a [[org.bitcoins.core.protocol.BitcoinAddress BitcoinAddress]] from the given string value */
def apply(value: String): Try[BitcoinAddress] = fromString(value)
def apply(value: String): BitcoinAddress = fromString(value)
override def fromString(value: String): Try[BitcoinAddress] = {
P2PKHAddress
.fromString(value)
.orElse(P2SHAddress.fromString(value))
.orElse(Bech32Address.fromString(value))
.orElse(Failure(new IllegalArgumentException(
s"Could not decode the given value to a BitcoinAddress, got: $value")))
override def fromString(value: String): BitcoinAddress = {
val addressT = P2PKHAddress
.fromStringT(value)
.orElse(P2SHAddress.fromStringT(value))
.orElse(Bech32Address.fromStringT(value))
addressT match {
case Success(addr) => addr
case Failure(_) =>
throw new IllegalArgumentException(
s"Could not decode the given value to a BitcoinAddress, got: $value")
}
}
override def fromScriptPubKey(
override def fromScriptPubKeyT(
spk: ScriptPubKey,
np: NetworkParameters): Try[BitcoinAddress] =
spk match {
@ -387,31 +407,32 @@ object BitcoinAddress extends AddressFactory[BitcoinAddress] {
object Address extends AddressFactory[Address] {
def fromBytes(bytes: ByteVector): Try[Address] = {
def fromBytes(bytes: ByteVector): Address = {
val encoded = Base58.encode(bytes)
BitcoinAddress.fromString(encoded)
}
def fromHex(hex: String): Try[Address] =
def fromHex(hex: String): Address =
fromBytes(BytesUtil.decodeHex(hex))
def apply(bytes: ByteVector): Try[Address] = fromBytes(bytes)
def apply(bytes: ByteVector): Address = fromBytes(bytes)
def apply(str: String): Try[Address] = fromString(str)
def apply(str: String): Address = fromString(str)
override def fromString(str: String): Try[Address] = {
override def fromString(str: String): Address = {
BitcoinAddress.fromString(str)
}
override def fromScriptPubKey(
override def fromScriptPubKeyT(
spk: ScriptPubKey,
network: NetworkParameters): Try[Address] =
network match {
case _: BitcoinNetwork => BitcoinAddress.fromScriptPubKey(spk, network)
case _: BitcoinNetwork => BitcoinAddress.fromScriptPubKeyT(spk, network)
}
def apply(
spk: ScriptPubKey,
networkParameters: NetworkParameters): Try[Address] = {
fromScriptPubKey(spk, networkParameters)
fromScriptPubKeyT(spk, networkParameters)
}
}

View File

@ -2,26 +2,32 @@ package org.bitcoins.core.protocol
import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.protocol.script.ScriptPubKey
import org.bitcoins.crypto.StringFactory
import scala.util.{Failure, Success, Try}
abstract class AddressFactory[T] {
/** Attempts to create an address from the given String */
def fromString(str: String): Try[T]
abstract class AddressFactory[T <: Address] extends StringFactory[T] {
/** Same as fromString, but throws the exception */
def fromStringExn(str: String): T = fromString(str) match {
case Success(addr) => addr
case Failure(exn) => throw exn
def fromStringExn(str: String): T = fromString(str)
def fromScriptPubKey(spk: ScriptPubKey, np: NetworkParameters): T= {
fromScriptPubKeyT(spk,np) match {
case Success(addr) => addr
case Failure(exn) => throw exn
}
}
/**
* Attempts to create a address from the given [[org.bitcoins.core.protocol.script.ScriptPubKey ScriptPubKey]]
* and [[org.bitcoins.core.config.NetworkParameters NetworkParameters]]
*/
def fromScriptPubKey(spk: ScriptPubKey, np: NetworkParameters): Try[T]
* Attempts to create a address from the given [[org.bitcoins.core.protocol.script.ScriptPubKey ScriptPubKey]]
* and [[org.bitcoins.core.config.NetworkParameters NetworkParameters]]
*/
def fromScriptPubKeyT(spk: ScriptPubKey, np: NetworkParameters): Try[T]
def fromScriptPubKeyOpt(spk: ScriptPubKey, np: NetworkParameters): Option[T] = {
fromScriptPubKeyT(spk,np).toOption
}
/** Checks if the given string is a valid address */
def isValid(str: String): Boolean = fromString(str).isSuccess
def isValid(str: String): Boolean = fromStringT(str).isSuccess
}

View File

@ -5,7 +5,7 @@ import org.bitcoins.core.protocol.ln.currency.{LnCurrencyUnit, PicoBitcoins}
import org.bitcoins.core.protocol.ln.node.NodeId
import org.bitcoins.core.protocol.ln.util.LnUtil
import org.bitcoins.core.util._
import org.bitcoins.crypto.{CryptoUtil, ECPrivateKey, Sha256Digest}
import org.bitcoins.crypto.{CryptoUtil, ECPrivateKey, Sha256Digest, StringFactory}
import scodec.bits.ByteVector
import scala.util.{Failure, Success, Try}
@ -109,7 +109,7 @@ sealed abstract class LnInvoice {
}
}
object LnInvoice extends BitcoinSLogger {
object LnInvoice extends StringFactory[LnInvoice] with BitcoinSLogger {
private case class LnInvoiceImpl(
hrp: LnHumanReadablePart,
timestamp: UInt64,
@ -175,16 +175,15 @@ object LnInvoice extends BitcoinSLogger {
}
def fromString(bech32String: String): Try[LnInvoice] = {
override def fromString(bech32String: String): LnInvoice = {
val sepIndexes = {
bech32String.zipWithIndex.filter {
case (sep, _) => sep == Bech32.separator
}
}
if (sepIndexes.isEmpty) {
Failure(
new IllegalArgumentException(
"LnInvoice did not have the correct separator"))
throw new IllegalArgumentException(
"LnInvoice did not have the correct separator")
} else {
val (_, sepIndex) = sepIndexes.last
@ -193,9 +192,9 @@ object LnInvoice extends BitcoinSLogger {
val (_, data) = bech32String.splitAt(sepIndex + 1)
if (hrp.length < 1) {
Failure(new IllegalArgumentException("HumanReadablePart is too short"))
throw new IllegalArgumentException("HumanReadablePart is too short")
} else if (data.length < 6) {
Failure(new IllegalArgumentException("Data part is too short"))
throw new IllegalArgumentException("Data part is too short")
} else {
val hrpValid = LnHumanReadablePart.fromString(hrp)
@ -209,9 +208,14 @@ object LnInvoice extends BitcoinSLogger {
}
}
isChecksumValid.flatMap { d: Vector[UInt5] =>
val invoiceT = isChecksumValid.flatMap { d: Vector[UInt5] =>
hrpValid.map(h => LnInvoice(h, d))
}
invoiceT match {
case Success(i) => i
case Failure(exn) => throw exn
}
}
}
}

View File

@ -13,7 +13,7 @@ trait StringFactory[T] {
fromStringT(string).toOption
}
/** Tries to parsea string to type t, returns [[scala.util.Failure]] if the fails */
/** Tries to parse string to type t, returns [[scala.util.Failure]] if the fails */
def fromStringT(string: String): Try[T] = {
Try(fromString(string))
}

View File

@ -16,7 +16,7 @@ import scodec.bits._
```
```scala mdoc:to-string
val lnInvoiceT: Try[LnInvoice] = LnInvoice.fromString(bech32String = "lnbc1u1p0d0k6npp5qndcvujqf47244g6yhd3laqj8c3ckummaahrs375gsgau4upg32qdq623jhxapqv3jhxcmjd9c8g6t0dccqzpgxqrrssrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz2uagqqjjgqqqqqqqlgqqqqqqgq9qsp5nyg950yy703ah6sazalytaksg0lvyxq3veze5lqswp6rh3jx9css9qy9qsq0d4vhtxkkvse0yx8cgcpemhzatw2wtyvy04ve7n0j3k78l40qpqpvg07vjldvn8zx6nana6glmnlwqvm4fz0pttw7k3rh7wzr48nccsqhnd8wv")
val lnInvoiceT: Try[LnInvoice] = LnInvoice.fromStringT(string = "lnbc1u1p0d0k6npp5qndcvujqf47244g6yhd3laqj8c3ckummaahrs375gsgau4upg32qdq623jhxapqv3jhxcmjd9c8g6t0dccqzpgxqrrssrzjqvgptfurj3528snx6e3dtwepafxw5fpzdymw9pj20jj09sunnqmwqz2uagqqjjgqqqqqqqlgqqqqqqgq9qsp5nyg950yy703ah6sazalytaksg0lvyxq3veze5lqswp6rh3jx9css9qy9qsq0d4vhtxkkvse0yx8cgcpemhzatw2wtyvy04ve7n0j3k78l40qpqpvg07vjldvn8zx6nana6glmnlwqvm4fz0pttw7k3rh7wzr48nccsqhnd8wv")
val paymentPreImage = PaymentPreimage(hex"a8c5260174cab81047ba14e8fd96b23074aec7407867343b2d270861e3f0ee66")
@ -26,4 +26,4 @@ val nodeId = NodeId(ECPublicKey("034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f8
val millsats100 = MilliSatoshis(BigInt(100))
```
```

View File

@ -326,7 +326,7 @@ class EclairRpcClientTest extends BitcoinSAsyncTest {
}
}
val testBitcoinAddress = BitcoinAddress("n3p1ct69ao3qxWvEvzLhLtWG2zJGTjN3EV").get
val testBitcoinAddress = BitcoinAddress("n3p1ct69ao3qxWvEvzLhLtWG2zJGTjN3EV")
it should "be able to create an invoice with amount, expiry time, and fallbackAddress" in {
for {
@ -807,7 +807,7 @@ class EclairRpcClientTest extends BitcoinSAsyncTest {
}
paymentRequestF.map { paymentRequest =>
val i = LnInvoice.fromString(paymentRequest.serialized).get
val i = LnInvoice.fromString(paymentRequest.serialized)
assert(i.amount.get.toMSat == amt)
assert(paymentRequest.expiry == expiry)
}

View File

@ -358,7 +358,7 @@ class EclairRpcClient(val instance: EclairInstance, binary: Option[File] = None)
val responseF = eclairCall[InvoiceResult]("createinvoice", params: _*)
responseF.flatMap { res =>
Future.fromTry(LnInvoice.fromString(res.serialized))
Future.fromTry(LnInvoice.fromStringT(res.serialized))
}
}
@ -566,7 +566,7 @@ class EclairRpcClient(val instance: EclairInstance, binary: Option[File] = None)
val resF =
eclairCall[InvoiceResult]("getinvoice", "paymentHash" -> paymentHash.hex)
resF.flatMap { res =>
Future.fromTry(LnInvoice.fromString(res.serialized))
Future.fromTry(LnInvoice.fromStringT(res.serialized))
}
}
@ -592,7 +592,7 @@ class EclairRpcClient(val instance: EclairInstance, binary: Option[File] = None)
to.map(x => "to" -> x.getEpochSecond.toString)).flatten: _*)
resF.flatMap(xs =>
Future.sequence(xs.map(x =>
Future.fromTry(LnInvoice.fromString(x.serialized)))))
Future.fromTry(LnInvoice.fromStringT(x.serialized)))))
}
override def usableBalances(): Future[Vector[UsableBalancesResult]] = {

View File

@ -37,7 +37,7 @@ object TestUtil {
def testP2SHAddress = BitcoinAddress("2MzYbQdkSVp5wVyMRp6A5PHPuQNHpiaTbCj")
val bech32Address: Bech32Address =
Bech32Address.fromString("bcrt1qq6w6pu6zq90az9krn53zlkvgyzkyeglzukyepf").get
Bech32Address.fromString("bcrt1qq6w6pu6zq90az9krn53zlkvgyzkyeglzukyepf")
def bitcoinAddress = BitcoinAddress("1C4kYhyLftmkn48YarSoLupxHfYFo8kp64")
def multiSigAddress = BitcoinAddress("342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey")

View File

@ -22,7 +22,6 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
val testAddr: BitcoinAddress =
BitcoinAddress
.fromString("bcrt1qlhctylgvdsvaanv539rg7hyn0sjkdm23y70kgq")
.get
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
withFundedWalletAndBitcoind(test)

View File

@ -26,7 +26,7 @@ class WalletSendingTest extends BitcoinSWalletTest {
behavior of "Wallet"
val testAddress: BitcoinAddress =
BitcoinAddress("bcrt1qlhctylgvdsvaanv539rg7hyn0sjkdm23y70kgq").get
BitcoinAddress("bcrt1qlhctylgvdsvaanv539rg7hyn0sjkdm23y70kgq")
val amountToSend: Bitcoins = Bitcoins(0.5)
@ -45,10 +45,10 @@ class WalletSendingTest extends BitcoinSWalletTest {
}
val addresses = Vector(
BitcoinAddress("bcrt1qlhctylgvdsvaanv539rg7hyn0sjkdm23y70kgq").get,
BitcoinAddress("bcrt1qf4rju7adz5hpuymkfwvg5s94mydc8llk94v74w").get,
BitcoinAddress("bcrt1q9h9wkz6ad49szfl035wh3qdacuslkp6j9pfp4j").get,
BitcoinAddress("bcrt1q9scvqvyf3ssed8zqnfgk5zttnneatg2aszu5q9").get
BitcoinAddress("bcrt1qlhctylgvdsvaanv539rg7hyn0sjkdm23y70kgq"),
BitcoinAddress("bcrt1qf4rju7adz5hpuymkfwvg5s94mydc8llk94v74w"),
BitcoinAddress("bcrt1q9h9wkz6ad49szfl035wh3qdacuslkp6j9pfp4j"),
BitcoinAddress("bcrt1q9scvqvyf3ssed8zqnfgk5zttnneatg2aszu5q9")
)
val amounts = Vector(
@ -184,10 +184,9 @@ class WalletSendingTest extends BitcoinSWalletTest {
val wallet = fundedWallet.wallet
val sendToAddressesF =
wallet.sendToAddress(
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa").get,
Satoshis(1000),
feeRateOpt)
wallet.sendToAddress(BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"),
Satoshis(1000),
feeRateOpt)
recoverToSucceededIf[IllegalArgumentException] {
sendToAddressesF
@ -198,10 +197,10 @@ class WalletSendingTest extends BitcoinSWalletTest {
val wallet = fundedWallet.wallet
val addrs = Vector(
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa").get,
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa").get,
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa").get,
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa").get
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"),
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"),
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"),
BitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa")
)
val sendToAddressesF =

View File

@ -156,7 +156,7 @@ class WalletUnitTest extends BitcoinSWalletTest {
matched <- wallet.getMatchingBlocks(
scripts = Vector(
// this is a random address which is included into the test block
BitcoinAddress("n1RH2x3b3ah4TGQtgrmNAHfmad9wr8U2QY").get.scriptPubKey),
BitcoinAddress("n1RH2x3b3ah4TGQtgrmNAHfmad9wr8U2QY").scriptPubKey),
startOpt = None,
endOpt = None
)(system.dispatcher)

View File

@ -282,7 +282,7 @@ trait WalletApi extends WalletLogger {
def getAddressInfo(
spendingInfoDb: SpendingInfoDb): Future[Option[AddressInfo]] = {
val addressT = BitcoinAddress.fromScriptPubKey(
val addressT = BitcoinAddress.fromScriptPubKeyT(
spk = spendingInfoDb.output.scriptPubKey,
np = networkParameters)
addressT match {

View File

@ -87,7 +87,7 @@ private[wallet] trait UtxoHandling extends WalletLogger {
*/
private def findAddress(
spk: ScriptPubKey): Future[CompatEither[AddUtxoError, AddressDb]] =
BitcoinAddress.fromScriptPubKey(spk, networkParameters) match {
BitcoinAddress.fromScriptPubKeyT(spk, networkParameters) match {
case Success(address) =>
addressDAO.findAddress(address).map {
case Some(addrDb) => CompatRight(addrDb)