Skip to content

Commit

Permalink
Create FallbackFeeRateApi (#3974)
Browse files Browse the repository at this point in the history
* Create AggregateFeeRateApi

* Rename, add docs
  • Loading branch information
benthecarman committed Jan 13, 2022
1 parent e095a1b commit 5f4053b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
Expand Up @@ -99,6 +99,18 @@ class FeeRateProviderTest extends BitcoinSAsyncTest {
}
}

it must "use an aggregate of fee providers" in {
val expected = SatoshisPerByte(Satoshis(4))
val providerA = ConstantFeeRateProvider(expected)
val providerB = ConstantFeeRateProvider(SatoshisPerByte(Satoshis(2)))

val provider = FallbackFeeRateApi(Vector(providerA, providerB))

provider.getFeeRate().map { feeRate =>
assert(feeRate == expected)
}
}

private def testProvider(provider: FeeRateApi): Future[Assertion] = {
provider.getFeeRate().map { feeRate =>
assert(feeRate.toLong > 0)
Expand Down
@@ -0,0 +1,37 @@
package org.bitcoins.feeprovider

import org.bitcoins.core.api.feeprovider.FeeRateApi
import org.bitcoins.core.util.FutureUtil
import org.bitcoins.core.wallet.fee.FeeUnit

import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NonFatal

/** Takes multiple [[FeeRateApi FeeRateApis]] and attempts to get a fee rate from
* one in order until one succeeds.
*/
case class FallbackFeeRateApi(providers: Vector[FeeRateApi])(implicit
ec: ExecutionContext)
extends FeeRateApi {

override def getFeeRate(): Future[FeeUnit] = {
val init: Option[FeeUnit] = None
val retOptF = FutureUtil.foldLeftAsync(init, providers) {
case (ret, provider) =>
ret match {
case Some(value) => Future.successful(value).map(Some(_))
case None =>
provider
.getFeeRate()
.map(Some(_))
.recover { case NonFatal(_) => None }
}
}

retOptF.map {
case Some(ret) => ret
case None =>
sys.error("Failed to get fee rate from any provider")
}
}
}

0 comments on commit 5f4053b

Please sign in to comment.