diff --git a/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/db/androidDbFactory.kt b/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/db/androidDbFactory.kt index e2cae98a9..c90a9513b 100644 --- a/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/db/androidDbFactory.kt +++ b/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/db/androidDbFactory.kt @@ -18,15 +18,15 @@ package fr.acinq.phoenix.db import com.squareup.sqldelight.android.AndroidSqliteDriver import com.squareup.sqldelight.db.SqlDriver -import fr.acinq.lightning.NodeParams +import fr.acinq.bitcoin.Bitcoin.Chain import fr.acinq.phoenix.utils.PlatformContext import java.util.* -actual fun createChannelsDbDriver(ctx: PlatformContext, chain: NodeParams.Chain, nodeIdHash: String): SqlDriver { +actual fun createChannelsDbDriver(ctx: PlatformContext, chain: Chain, nodeIdHash: String): SqlDriver { return AndroidSqliteDriver(ChannelsDatabase.Schema, ctx.applicationContext, "channels-${chain.name.lowercase()}-$nodeIdHash.sqlite") } -actual fun createPaymentsDbDriver(ctx: PlatformContext, chain: NodeParams.Chain, nodeIdHash: String): SqlDriver { +actual fun createPaymentsDbDriver(ctx: PlatformContext, chain: Chain, nodeIdHash: String): SqlDriver { return AndroidSqliteDriver(PaymentsDatabase.Schema, ctx.applicationContext, "payments-${chain.name.lowercase()}-$nodeIdHash.sqlite") } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt index 055fc1c34..9be923bea 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt @@ -16,7 +16,7 @@ package fr.acinq.phoenix -import fr.acinq.lightning.NodeParams +import fr.acinq.bitcoin.Bitcoin import fr.acinq.lightning.blockchain.electrum.ElectrumClient import fr.acinq.lightning.blockchain.electrum.ElectrumWatcher import fr.acinq.lightning.io.TcpSocket @@ -74,7 +74,7 @@ class PhoenixBusiness( } } - val chain: NodeParams.Chain = NodeParamsManager.chain + val chain: Bitcoin.Chain = NodeParamsManager.chain val electrumClient by lazy { ElectrumClient(scope = MainScope(), loggerFactory = loggerFactory, pingInterval = 30.seconds, rpcTimeout = 10.seconds) } internal val electrumWatcher by lazy { ElectrumWatcher(electrumClient, MainScope(), loggerFactory) } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt index 6c9b7c0e2..bff7d078d 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt @@ -1,7 +1,7 @@ package fr.acinq.phoenix.controllers.config +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.ByteVector32 -import fr.acinq.lightning.NodeParams import fr.acinq.lightning.channel.* import fr.acinq.lightning.channel.states.* import fr.acinq.lightning.io.WrappedChannelCommand @@ -18,7 +18,7 @@ import kotlinx.coroutines.launch class AppCloseChannelsConfigurationController( loggerFactory: LoggerFactory, private val peerManager: PeerManager, - private val chain: NodeParams.Chain, + private val chain: Bitcoin.Chain, private val isForceClose: Boolean ) : AppController( loggerFactory = loggerFactory, diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt index 27a9071bb..cdb948419 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt @@ -16,10 +16,9 @@ package fr.acinq.phoenix.controllers.payments -import co.touchlab.kermit.Logger +import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.Lightning.randomBytes32 import fr.acinq.lightning.logging.LoggerFactory -import fr.acinq.lightning.utils.Either import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.controllers.AppController import fr.acinq.phoenix.managers.PeerManager diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/Scan.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/Scan.kt index 8d3c8e062..cf38a5f28 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/Scan.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/Scan.kt @@ -16,10 +16,11 @@ package fr.acinq.phoenix.controllers.payments +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.Satoshi import fr.acinq.lightning.MilliSatoshi -import fr.acinq.lightning.NodeParams import fr.acinq.lightning.TrampolineFees +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.phoenix.controllers.MVI import fr.acinq.phoenix.data.BitcoinUri @@ -37,7 +38,7 @@ object Scan { object UnknownFormat : BadRequestReason() object AlreadyPaidInvoice : BadRequestReason() data class Expired(val timestampSeconds: Long, val expirySeconds: Long) : BadRequestReason() - data class ChainMismatch(val expected: NodeParams.Chain) : BadRequestReason() + data class ChainMismatch(val expected: Bitcoin.Chain) : BadRequestReason() data class ServiceError(val url: Url, val error: LnurlError.RemoteFailure) : BadRequestReason() data class InvalidLnurl(val url: Url) : BadRequestReason() data class UnsupportedLnurl(val url: Url) : BadRequestReason() @@ -46,7 +47,7 @@ object Scan { sealed class LnurlPayError { data class RemoteError(val err: LnurlError.RemoteFailure) : LnurlPayError() data class BadResponseError(val err: LnurlError.Pay.Invoice) : LnurlPayError() - data class ChainMismatch(val expected: NodeParams.Chain) : LnurlPayError() + data class ChainMismatch(val expected: Bitcoin.Chain) : LnurlPayError() object AlreadyPaidInvoice : LnurlPayError() } @@ -68,12 +69,12 @@ object Scan { val reason: BadRequestReason ) : Model() - sealed class InvoiceFlow : Model() { - data class InvoiceRequest( + sealed class Bolt11InvoiceFlow : Model() { + data class Bolt11InvoiceRequest( val request: String, - val paymentRequest: PaymentRequest, - ): InvoiceFlow() - object Sending: InvoiceFlow() + val invoice: Bolt11Invoice, + ): Bolt11InvoiceFlow() + object Sending: Bolt11InvoiceFlow() } data class OnchainFlow(val uri: BitcoinUri): Model() @@ -139,12 +140,12 @@ object Scan { val request: String ) : Intent() - sealed class InvoiceFlow : Intent() { - data class SendInvoicePayment( - val paymentRequest: PaymentRequest, + sealed class Bolt11InvoiceFlow : Intent() { + data class SendBolt11Invoice( + val invoice: Bolt11Invoice, val amount: MilliSatoshi, val trampolineFees: TrampolineFees - ) : InvoiceFlow() + ) : Bolt11InvoiceFlow() } object CancelLnurlServiceFetch : Intent() diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt index 02f74603e..232057abb 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt @@ -16,14 +16,13 @@ package fr.acinq.phoenix.controllers.payments -import co.touchlab.kermit.Logger +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.BitcoinError import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.* import fr.acinq.lightning.db.LightningOutgoingPayment import fr.acinq.lightning.io.SendPayment import fr.acinq.lightning.logging.LoggerFactory -import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.lightning.utils.* import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.controllers.AppController @@ -35,6 +34,7 @@ import fr.acinq.phoenix.utils.Parser import fr.acinq.phoenix.utils.extensions.chain import fr.acinq.lightning.logging.error import fr.acinq.lightning.logging.info +import fr.acinq.lightning.payment.Bolt11Invoice import io.ktor.http.Url import kotlinx.coroutines.* import kotlinx.coroutines.flow.filterNotNull @@ -51,7 +51,7 @@ class AppScanController( private val peerManager: PeerManager, private val lnurlManager: LnurlManager, private val databaseManager: DatabaseManager, - private val chain: NodeParams.Chain, + private val chain: Bitcoin.Chain, ) : AppController( loggerFactory = loggerFactory, firstModel = firstModel ?: Scan.Model.Ready @@ -82,14 +82,14 @@ class AppScanController( when (intent) { is Scan.Intent.Reset -> launch { model(Scan.Model.Ready) } is Scan.Intent.Parse -> launch { processScannedInput(intent) } - is Scan.Intent.InvoiceFlow.SendInvoicePayment -> launch { - sendPayment( + is Scan.Intent.Bolt11InvoiceFlow.SendBolt11Invoice -> launch { + payBolt11Invoice( amountToSend = intent.amount, trampolineFees = intent.trampolineFees, - paymentRequest = intent.paymentRequest, + invoice = intent.invoice, metadata = null, ) - model(Scan.Model.InvoiceFlow.Sending) + model(Scan.Model.Bolt11InvoiceFlow.Sending) } is Scan.Intent.CancelLnurlServiceFetch -> launch { cancelLnurlFetch() } is Scan.Intent.LnurlPayFlow.RequestInvoice -> launch { processLnurlPayRequestInvoice(intent) } @@ -105,8 +105,8 @@ class AppScanController( ) { val input = Parser.removeExcessInput(intent.request) - Parser.readPaymentRequest(input)?.let { - processLightningInvoice(it) + Parser.readBolt11Invoice(input)?.let { + processBolt11Invoice(it) } ?: readLnurl(input)?.let { processLnurl(it) } ?: readBitcoinAddress(input)?.let { @@ -119,12 +119,12 @@ class AppScanController( } /** Inspects the Lightning invoice for errors and update the model with the adequate value. */ - private suspend fun processLightningInvoice(paymentRequest: PaymentRequest) { - val model = checkForBadRequest(paymentRequest)?.let { - Scan.Model.BadRequest(request = paymentRequest.write(), reason = it) - } ?: Scan.Model.InvoiceFlow.InvoiceRequest( - request = paymentRequest.write(), - paymentRequest = paymentRequest, + private suspend fun processBolt11Invoice(invoice: Bolt11Invoice) { + val model = checkForBadBolt11Invoice(invoice)?.let { + Scan.Model.BadRequest(request = invoice.write(), reason = it) + } ?: Scan.Model.Bolt11InvoiceFlow.Bolt11InvoiceRequest( + request = invoice.write(), + invoice = invoice, ) model(model) } @@ -204,10 +204,10 @@ class AppScanController( } /** Extract invoice and send it to the Peer to make the payment, attaching custom trampoline fees if needed. */ - private suspend fun sendPayment( + private suspend fun payBolt11Invoice( amountToSend: MilliSatoshi, trampolineFees: TrampolineFees, - paymentRequest: PaymentRequest, + invoice: Bolt11Invoice, metadata: WalletPaymentMetadata?, ) { val paymentId = UUID.randomUUID() @@ -225,8 +225,8 @@ class AppScanController( SendPayment( paymentId = paymentId, amount = amountToSend, - recipient = paymentRequest.nodeId, - paymentRequest = paymentRequest, + recipient = invoice.nodeId, + paymentRequest = invoice, trampolineFeesOverride = listOf(trampolineFees) ) ) @@ -253,7 +253,7 @@ class AppScanController( requestPayInvoiceTask = task try { val invoice = task.await() - when (val check = checkForBadRequest(invoice.paymentRequest)) { + when (checkForBadBolt11Invoice(invoice.invoice)) { is Scan.BadRequestReason.ChainMismatch -> Either.Left( Scan.LnurlPayError.ChainMismatch(expected = chain) ) @@ -289,10 +289,10 @@ class AppScanController( ) } is Either.Right -> { - sendPayment( + payBolt11Invoice( amountToSend = intent.amount, trampolineFees = intent.trampolineFees, - paymentRequest = result.value.paymentRequest, + invoice = result.value.invoice, metadata = WalletPaymentMetadata( lnurl = LnurlPayMetadata( pay = intent.paymentIntent, @@ -336,7 +336,7 @@ class AppScanController( val paymentRequest = peerManager.getPeer().createInvoice( paymentPreimage = Lightning.randomBytes32(), amount = intent.amount, - description = fr.acinq.lightning.utils.Either.Left(intent.description ?: intent.lnurlWithdraw.defaultDescription), + description = Either.Left(intent.description ?: intent.lnurlWithdraw.defaultDescription), expirySeconds = (3600 * 24 * 7).toLong(), // one week ) @@ -439,7 +439,7 @@ class AppScanController( fun inspectClipboard(data: String): Scan.ClipboardContent? { val input = Parser.removeExcessInput(data) - return Parser.readPaymentRequest(input)?.let { + return Parser.readBolt11Invoice(input)?.let { Scan.ClipboardContent.InvoiceRequest(it) } ?: readLnurl(input)?.let { when (it) { @@ -462,21 +462,21 @@ class AppScanController( } /** Checks that the invoice is on same chain and has not already been paid. */ - private suspend fun checkForBadRequest( - paymentRequest: PaymentRequest + private suspend fun checkForBadBolt11Invoice( + invoice: Bolt11Invoice ): Scan.BadRequestReason? { - val actualChain = paymentRequest.chain + val actualChain = invoice.chain if (chain != actualChain) { return Scan.BadRequestReason.ChainMismatch(expected = chain) } - if (paymentRequest.isExpired(currentTimestampSeconds())) { - return Scan.BadRequestReason.Expired(paymentRequest.timestampSeconds, paymentRequest.expirySeconds ?: PaymentRequest.DEFAULT_EXPIRY_SECONDS.toLong()) + if (invoice.isExpired(currentTimestampSeconds())) { + return Scan.BadRequestReason.Expired(invoice.timestampSeconds, invoice.expirySeconds ?: Bolt11Invoice.DEFAULT_EXPIRY_SECONDS.toLong()) } val db = databaseManager.databases.filterNotNull().first() - return if (db.payments.listLightningOutgoingPayments(paymentRequest.paymentHash).any { it.status is LightningOutgoingPayment.Status.Completed.Succeeded }) { + return if (db.payments.listLightningOutgoingPayments(invoice.paymentHash).any { it.status is LightningOutgoingPayment.Status.Completed.Succeeded }) { Scan.BadRequestReason.AlreadyPaidInvoice } else { null diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/BitcoinAddress.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/BitcoinAddress.kt index 4f1f2a1b9..9c1e67e8d 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/BitcoinAddress.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/BitcoinAddress.kt @@ -16,15 +16,16 @@ package fr.acinq.phoenix.data +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.BitcoinError import fr.acinq.bitcoin.ByteVector import fr.acinq.bitcoin.Satoshi -import fr.acinq.lightning.NodeParams +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.lightning.payment.PaymentRequest import io.ktor.http.* data class BitcoinUri( - val chain: NodeParams.Chain, + val chain: Bitcoin.Chain, /** Actual Bitcoin address; may be different than the source, e.g. if the source is an URI like "bitcoin:xyz?param=123". */ val address: String, val script: ByteVector, @@ -34,7 +35,7 @@ data class BitcoinUri( /** Amount requested in the URI. */ val amount: Satoshi? = null, /** A Bitcoin URI may contain a Lightning payment request as an alternative way to make the payment. */ - val paymentRequest: PaymentRequest? = null, + val paymentRequest: Bolt11Invoice? = null, /** Other bip-21 parameters in the URI that we do not handle. */ val ignoredParams: Parameters = Parameters.Empty, ) { diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt index 74c5b40e7..23c097e47 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt @@ -18,9 +18,9 @@ package fr.acinq.phoenix.data.lnurl import co.touchlab.kermit.Logger import fr.acinq.bitcoin.ByteVector +import fr.acinq.bitcoin.utils.Try import fr.acinq.lightning.MilliSatoshi -import fr.acinq.lightning.payment.PaymentRequest -import fr.acinq.lightning.utils.Try +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.phoenix.data.lnurl.Lnurl.Companion.format import fr.acinq.phoenix.db.cloud.b64Decode import io.ktor.http.* @@ -68,7 +68,7 @@ sealed class LnurlPay : Lnurl.Qualified { */ data class Invoice( override val initialUrl: Url, - val paymentRequest: PaymentRequest, + val invoice: Bolt11Invoice, val successAction: SuccessAction? ) : LnurlPay() { sealed class SuccessAction { @@ -111,13 +111,13 @@ sealed class LnurlPay : Lnurl.Qualified { ): Invoice { try { val pr = json["pr"]?.jsonPrimitive?.content ?: throw LnurlError.Pay.Invoice.Malformed(origin, "missing pr") - val paymentRequest = when (val res = PaymentRequest.read(pr)) { + val invoice = when (val res = Bolt11Invoice.read(pr)) { is Try.Success -> res.result is Try.Failure -> throw LnurlError.Pay.Invoice.Malformed(origin, res.error.message ?: res.error::class.toString()) } val successAction = parseSuccessAction(origin, json) - return Invoice(intent.initialUrl, paymentRequest, successAction) + return Invoice(intent.initialUrl, invoice, successAction) } catch (t: Throwable) { when (t) { is LnurlError.Pay.Invoice -> throw t diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/DbFactory.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/DbFactory.kt index 522b4b58b..0733cde0f 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/DbFactory.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/DbFactory.kt @@ -17,11 +17,11 @@ package fr.acinq.phoenix.db import com.squareup.sqldelight.db.SqlDriver -import fr.acinq.lightning.NodeParams +import fr.acinq.bitcoin.Bitcoin import fr.acinq.phoenix.utils.PlatformContext -expect fun createChannelsDbDriver(ctx: PlatformContext, chain: NodeParams.Chain, nodeIdHash: String): SqlDriver +expect fun createChannelsDbDriver(ctx: PlatformContext, chain: Bitcoin.Chain, nodeIdHash: String): SqlDriver -expect fun createPaymentsDbDriver(ctx: PlatformContext, chain: NodeParams.Chain, nodeIdHash: String): SqlDriver +expect fun createPaymentsDbDriver(ctx: PlatformContext, chain: Bitcoin.Chain, nodeIdHash: String): SqlDriver expect fun createAppDbDriver(ctx: PlatformContext): SqlDriver \ No newline at end of file diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt index 001f45f3f..d73e09d8e 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt @@ -23,6 +23,7 @@ import com.squareup.sqldelight.runtime.coroutines.asFlow import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.Crypto import fr.acinq.bitcoin.TxId +import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.channel.ChannelException import fr.acinq.lightning.db.* import fr.acinq.lightning.logging.LoggerFactory diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/IncomingOriginType.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/IncomingOriginType.kt index 3cdfa418e..b4c6321e8 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/IncomingOriginType.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/IncomingOriginType.kt @@ -25,7 +25,7 @@ import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.OutPoint import fr.acinq.bitcoin.TxId import fr.acinq.lightning.db.IncomingPayment -import fr.acinq.lightning.payment.PaymentRequest +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.phoenix.db.payments.DbTypesHelper.decodeBlob import fr.acinq.phoenix.db.serializers.v1.ByteVector32Serializer import fr.acinq.phoenix.db.serializers.v1.OutpointSerializer @@ -69,7 +69,7 @@ sealed class IncomingOriginData { fun deserialize(typeVersion: IncomingOriginTypeVersion, blob: ByteArray): IncomingPayment.Origin = decodeBlob(blob) { json, format -> when (typeVersion) { IncomingOriginTypeVersion.KEYSEND_V0 -> IncomingPayment.Origin.KeySend - IncomingOriginTypeVersion.INVOICE_V0 -> format.decodeFromString(json).let { IncomingPayment.Origin.Invoice(PaymentRequest.read(it.paymentRequest).get()) } + IncomingOriginTypeVersion.INVOICE_V0 -> format.decodeFromString(json).let { IncomingPayment.Origin.Invoice(Bolt11Invoice.read(it.paymentRequest).get()) } IncomingOriginTypeVersion.SWAPIN_V0 -> format.decodeFromString(json).let { IncomingPayment.Origin.SwapIn(it.address) } IncomingOriginTypeVersion.ONCHAIN_V0 -> format.decodeFromString(json).let { IncomingPayment.Origin.OnChain(TxId(it.txId), it.outpoints.toSet()) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingDetailsType.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingDetailsType.kt index cb66333ce..601c7aebe 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingDetailsType.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingDetailsType.kt @@ -24,14 +24,14 @@ package fr.acinq.phoenix.db.payments import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.Satoshi import fr.acinq.lightning.db.LightningOutgoingPayment -import fr.acinq.lightning.payment.PaymentRequest +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.phoenix.db.serializers.v1.ByteVector32Serializer import fr.acinq.phoenix.db.serializers.v1.SatoshiSerializer +import fr.acinq.phoenix.utils.extensions.write import io.ktor.utils.io.charsets.* import io.ktor.utils.io.core.* import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers -import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -77,9 +77,9 @@ sealed class OutgoingDetailsData { @Suppress("DEPRECATION") fun deserialize(typeVersion: OutgoingDetailsTypeVersion, blob: ByteArray): LightningOutgoingPayment.Details? = DbTypesHelper.decodeBlob(blob) { json, format -> when (typeVersion) { - OutgoingDetailsTypeVersion.NORMAL_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.Normal(PaymentRequest.read(it.paymentRequest).get()) } + OutgoingDetailsTypeVersion.NORMAL_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.Normal(Bolt11Invoice.read(it.paymentRequest).get()) } OutgoingDetailsTypeVersion.KEYSEND_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.KeySend(it.preimage) } - OutgoingDetailsTypeVersion.SWAPOUT_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.SwapOut(it.address, PaymentRequest.read(it.paymentRequest).get(), it.swapOutFee) } + OutgoingDetailsTypeVersion.SWAPOUT_V0 -> format.decodeFromString(json).let { LightningOutgoingPayment.Details.SwapOut(it.address, Bolt11Invoice.read(it.paymentRequest).get(), it.swapOutFee) } OutgoingDetailsTypeVersion.CLOSING_V0 -> null } } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingQueries.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingQueries.kt index ee82bd384..4def43ee6 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingQueries.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/payments/OutgoingQueries.kt @@ -19,6 +19,7 @@ package fr.acinq.phoenix.db.payments import com.squareup.sqldelight.ColumnAdapter import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.PublicKey +import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.MilliSatoshi import fr.acinq.lightning.ShortChannelId import fr.acinq.lightning.channel.ChannelException diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt index 3a76dc35c..6f0fe29ec 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt @@ -1,6 +1,6 @@ package fr.acinq.phoenix.managers -import fr.acinq.lightning.NodeParams +import fr.acinq.bitcoin.Bitcoin import fr.acinq.lightning.blockchain.electrum.ElectrumWatcher import fr.acinq.lightning.blockchain.electrum.HeaderSubscriptionResponse import fr.acinq.lightning.blockchain.fee.FeeratePerByte @@ -32,7 +32,7 @@ class AppConfigurationManager( private val appDb: SqliteAppDb, private val httpClient: HttpClient, private val electrumWatcher: ElectrumWatcher, - private val chain: NodeParams.Chain, + private val chain: Bitcoin.Chain, loggerFactory: LoggerFactory ) : CoroutineScope by MainScope() { @@ -163,9 +163,10 @@ class AppConfigurationManager( } fun randomElectrumServer() = when (chain) { - NodeParams.Chain.Mainnet -> mainnetElectrumServers.random() - NodeParams.Chain.Testnet -> testnetElectrumServers.random() - NodeParams.Chain.Regtest -> platformElectrumRegtestConf() + Bitcoin.Chain.Mainnet -> mainnetElectrumServers.random() + Bitcoin.Chain.Testnet -> testnetElectrumServers.random() + Bitcoin.Chain.Signet -> TODO() + Bitcoin.Chain.Regtest -> platformElectrumRegtestConf() } /** The flow containing the electrum header responses messages. */ diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt index ab6563f47..a0fa97805 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt @@ -1,10 +1,7 @@ package fr.acinq.phoenix.managers -import co.touchlab.kermit.Logger -import co.touchlab.kermit.Severity -import co.touchlab.kermit.StaticConfig +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.byteVector -import fr.acinq.lightning.NodeParams import fr.acinq.lightning.db.ChannelsDb import fr.acinq.lightning.db.Databases import fr.acinq.lightning.db.PaymentsDb @@ -24,7 +21,7 @@ import kotlinx.coroutines.launch class DatabaseManager( loggerFactory: LoggerFactory, private val ctx: PlatformContext, - private val chain: NodeParams.Chain, + private val chain: Bitcoin.Chain, private val nodeParamsManager: NodeParamsManager, private val currencyManager: CurrencyManager ) : CoroutineScope by MainScope() { diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt index 08aaa625b..2d3d4fe5b 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt @@ -22,6 +22,7 @@ import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.lnurl.* import fr.acinq.lightning.logging.error +import fr.acinq.phoenix.utils.extensions.write import io.ktor.client.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* @@ -110,8 +111,8 @@ class LnurlManager( val invoice = LnurlPay.parseLnurlPayInvoice(intent, origin, json) // SPECS: LN WALLET verifies that the amount in the provided invoice equals the amount previously specified by user. - if (amount != invoice.paymentRequest.amount) { - log.error { "rejecting invoice from $origin with amount_invoice=${invoice.paymentRequest.amount} requested_amount=$amount" } + if (amount != invoice.invoice.amount) { + log.error { "rejecting invoice from $origin with amount_invoice=${invoice.invoice.amount} requested_amount=$amount" } throw LnurlError.Pay.Invoice.InvalidAmount(origin) } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt index e8fd40784..d876320cd 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt @@ -16,6 +16,7 @@ package fr.acinq.phoenix.managers +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.PublicKey import fr.acinq.bitcoin.Satoshi import fr.acinq.lightning.NodeParams @@ -36,7 +37,7 @@ import kotlinx.coroutines.launch class NodeParamsManager( loggerFactory: LoggerFactory, - chain: NodeParams.Chain, + chain: Bitcoin.Chain, walletManager: WalletManager, appConfigurationManager: AppConfigurationManager, ) : CoroutineScope by MainScope() { @@ -64,7 +65,6 @@ class NodeParamsManager( loggerFactory = loggerFactory, keyManager = keyManager, ).copy( - alias = "phoenix", zeroConfPeers = setOf(trampolineNodeId), liquidityPolicy = MutableStateFlow(startupParams.liquidityPolicy), ) @@ -79,7 +79,7 @@ class NodeParamsManager( } companion object { - val chain = NodeParams.Chain.Testnet + val chain = Bitcoin.Chain.Testnet val trampolineNodeId = PublicKey.fromHex("03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134") val trampolineNodeUri = NodeUri(id = trampolineNodeId, "13.248.222.197", 9735) const val remoteSwapInXpub = "tpubDAmCFB21J9ExKBRPDcVxSvGs9jtcf8U1wWWbS1xTYmnUsuUHPCoFdCnEGxLE3THSWcQE48GHJnyz8XPbYUivBMbLSMBifFd3G9KmafkM9og" diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/WalletManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/WalletManager.kt index 952f4ba76..1c45ed1ef 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/WalletManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/WalletManager.kt @@ -17,7 +17,6 @@ package fr.acinq.phoenix.managers import fr.acinq.bitcoin.* -import fr.acinq.lightning.NodeParams import fr.acinq.lightning.crypto.KeyManager import fr.acinq.lightning.crypto.LocalKeyManager import fr.acinq.lightning.crypto.div @@ -26,7 +25,7 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.* class WalletManager( - private val chain: NodeParams.Chain + private val chain: Bitcoin.Chain ) : CoroutineScope by MainScope() { private val _localKeyManager = MutableStateFlow(null) @@ -98,7 +97,7 @@ fun LocalKeyManager.cloudKeyHash(): String { return Crypto.hash160(cloudKey()).byteVector().toHex() } -fun LocalKeyManager.isMainnet() = chain == NodeParams.Chain.Mainnet +fun LocalKeyManager.isMainnet() = chain == Bitcoin.Chain.Mainnet val LocalKeyManager.finalOnChainWalletPath: String get() = (KeyManager.Bip84OnChainKeys.bip84BasePath(chain) / finalOnChainWallet.account).toString() diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/BlockchainExplorer.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/BlockchainExplorer.kt index 1fb51a6a6..cad649909 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/BlockchainExplorer.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/BlockchainExplorer.kt @@ -1,10 +1,10 @@ package fr.acinq.phoenix.utils +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.TxId -import fr.acinq.lightning.NodeParams -class BlockchainExplorer(private val chain: NodeParams.Chain) { +class BlockchainExplorer(private val chain: Bitcoin.Chain) { sealed class Website(val base: String) { object MempoolSpace: Website("https://mempool.space") @@ -15,16 +15,18 @@ class BlockchainExplorer(private val chain: NodeParams.Chain) { return when (website) { Website.MempoolSpace -> { when (chain) { - NodeParams.Chain.Mainnet -> "${website.base}/tx/$txId" - NodeParams.Chain.Testnet -> "${website.base}/testnet/tx/$txId" - NodeParams.Chain.Regtest -> "${website.base}/_REGTEST_/tx/$txId" + Bitcoin.Chain.Mainnet -> "${website.base}/tx/$txId" + Bitcoin.Chain.Testnet -> "${website.base}/testnet/tx/$txId" + Bitcoin.Chain.Signet -> "${website.base}/signet/tx/$txId" + Bitcoin.Chain.Regtest -> "${website.base}/_REGTEST_/tx/$txId" } } Website.BlockstreamInfo -> { when (chain) { - NodeParams.Chain.Mainnet -> "${website.base}/tx/$txId" - NodeParams.Chain.Testnet -> "${website.base}/testnet/tx/$txId" - NodeParams.Chain.Regtest -> "${website.base}/_REGTEST_/tx/$txId" + Bitcoin.Chain.Mainnet -> "${website.base}/tx/$txId" + Bitcoin.Chain.Testnet -> "${website.base}/testnet/tx/$txId" + Bitcoin.Chain.Signet -> "${website.base}/signet/tx/$txId" + Bitcoin.Chain.Regtest -> "${website.base}/_REGTEST_/tx/$txId" } } } @@ -34,16 +36,18 @@ class BlockchainExplorer(private val chain: NodeParams.Chain) { return when (website) { Website.MempoolSpace -> { when (chain) { - NodeParams.Chain.Mainnet -> "${website.base}/address/$addr" - NodeParams.Chain.Testnet -> "${website.base}/testnet/address/$addr" - NodeParams.Chain.Regtest -> "${website.base}/_REGTEST_/address/$addr" + Bitcoin.Chain.Mainnet -> "${website.base}/address/$addr" + Bitcoin.Chain.Testnet -> "${website.base}/testnet/address/$addr" + Bitcoin.Chain.Signet -> "${website.base}/signet/address/$addr" + Bitcoin.Chain.Regtest -> "${website.base}/_REGTEST_/address/$addr" } } Website.BlockstreamInfo -> { when (chain) { - NodeParams.Chain.Mainnet -> "${website.base}/address/$addr" - NodeParams.Chain.Testnet -> "${website.base}/testnet/address/$addr" - NodeParams.Chain.Regtest -> "${website.base}/_REGTEST_/address/$addr" + Bitcoin.Chain.Mainnet -> "${website.base}/address/$addr" + Bitcoin.Chain.Testnet -> "${website.base}/testnet/address/$addr" + Bitcoin.Chain.Signet -> "${website.base}/signet/address/$addr" + Bitcoin.Chain.Regtest -> "${website.base}/_REGTEST_/address/$addr" } } } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Parser.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Parser.kt index c2cb2f058..224296d7d 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Parser.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Parser.kt @@ -18,9 +18,9 @@ package fr.acinq.phoenix.utils import fr.acinq.bitcoin.* import fr.acinq.bitcoin.utils.Either -import fr.acinq.lightning.NodeParams +import fr.acinq.bitcoin.utils.Try +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.lightning.payment.PaymentRequest -import fr.acinq.lightning.utils.Try import fr.acinq.lightning.utils.sat import fr.acinq.phoenix.data.* import io.ktor.http.* @@ -69,9 +69,9 @@ object Parser { } /** Reads a payment request after stripping prefixes. Return null if input is invalid. */ - fun readPaymentRequest( + fun readBolt11Invoice( input: String - ): PaymentRequest? = when (val res = PaymentRequest.read(trimMatchingPrefix(removeExcessInput(input), lightningPrefixes))) { + ): Bolt11Invoice? = when (val res = Bolt11Invoice.read(trimMatchingPrefix(removeExcessInput(input), lightningPrefixes))) { is Try.Success -> res.get() is Try.Failure -> null } @@ -83,7 +83,7 @@ object Parser { * @param input can range from a basic bitcoin address to a sophisticated Bitcoin URI with a prefix and parameters. */ fun readBitcoinAddress( - chain: NodeParams.Chain, + chain: Bitcoin.Chain, input: String ): Either { val cleanInput = removeExcessInput(input) @@ -117,7 +117,7 @@ object Parser { val label = url.parameters["label"] val message = url.parameters["message"] val lightning = url.parameters["lightning"]?.let { - when (val res = PaymentRequest.read(it)) { + when (val res = Bolt11Invoice.read(it)) { is Try.Success -> res.get() is Try.Failure -> null } @@ -135,7 +135,7 @@ object Parser { } /** Transforms a bitcoin address into a public key script if valid, otherwise returns null. */ - fun addressToPublicKeyScriptOrNull(chain: NodeParams.Chain, address: String): ByteVector? { + fun addressToPublicKeyScriptOrNull(chain: Bitcoin.Chain, address: String): ByteVector? { return readBitcoinAddress(chain, address).right?.script } } \ No newline at end of file diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentExtensions.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentExtensions.kt index ae2608593..04b33677e 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentExtensions.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentExtensions.kt @@ -16,8 +16,10 @@ package fr.acinq.phoenix.utils.extensions -import fr.acinq.lightning.NodeParams +import fr.acinq.bitcoin.Bitcoin import fr.acinq.lightning.db.* +import fr.acinq.lightning.payment.Bolt11Invoice +import fr.acinq.lightning.payment.Bolt12Invoice import fr.acinq.lightning.payment.PaymentRequest /** Standardized location for extending types from: fr.acinq.lightning. */ @@ -72,24 +74,3 @@ fun WalletPayment.errorMessage(): String? = when (this) { } is IncomingPayment -> null } - -/** - * In Objective-C, the function name `description()` is already in use (part of NSObject). - * So we need to alias it. - */ -fun PaymentRequest.desc(): String? = this.description - -/** - * Since unix epoch - */ -fun PaymentRequest.expiryTimestampSeconds(): Long? = this.expirySeconds?.let { - this.timestampSeconds + it -} - -val PaymentRequest.chain: NodeParams.Chain - get() = when (prefix) { - "lnbc" -> NodeParams.Chain.Mainnet - "lntb" -> NodeParams.Chain.Testnet - "lnbcrt" -> NodeParams.Chain.Regtest - else -> throw IllegalArgumentException("unhandled invoice prefix=$prefix") - } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentRequestExtensions.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentRequestExtensions.kt index 46dcb0b39..16778f089 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentRequestExtensions.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/extensions/PaymentRequestExtensions.kt @@ -16,8 +16,36 @@ package fr.acinq.phoenix.utils.extensions +import fr.acinq.bitcoin.Bitcoin import fr.acinq.lightning.Feature -import fr.acinq.lightning.Features +import fr.acinq.lightning.payment.Bolt11Invoice +import fr.acinq.lightning.payment.Bolt12Invoice import fr.acinq.lightning.payment.PaymentRequest -fun PaymentRequest.isAmountlessTrampoline() = amount == null && !Features(features).hasFeature(Feature.TrampolinePayment) \ No newline at end of file +fun Bolt11Invoice.isAmountlessTrampoline() = this.amount == null && this.features.hasFeature(Feature.TrampolinePayment) + +/** + * In Objective-C, the function name `description()` is already in use (part of NSObject). + * So we need to alias it. + */ +fun Bolt11Invoice.desc(): String? = this.description + +val PaymentRequest.chain: Bitcoin.Chain + get() = when (this) { + is Bolt11Invoice -> { + when (prefix) { + "lnbc" -> Bitcoin.Chain.Mainnet + "lntb" -> Bitcoin.Chain.Testnet + "lnbcrt" -> Bitcoin.Chain.Regtest + else -> throw IllegalArgumentException("unhandled invoice prefix=$prefix") + } + } + is Bolt12Invoice -> TODO() + } + +fun PaymentRequest.write(): String { + return when (this) { + is Bolt11Invoice -> this.write() + is Bolt12Invoice -> this.write() + } +} \ No newline at end of file diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt index d32d3ee28..9ef7c750e 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt @@ -16,6 +16,7 @@ package fr.acinq.phoenix +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.Block import fr.acinq.bitcoin.MnemonicCode import fr.acinq.bitcoin.PublicKey @@ -39,13 +40,12 @@ object TestConstants { private val entropy = Hex.decode("0202020202020202020202020202020202020202020202020202020202020202") val mnemonics = MnemonicCode.toMnemonics(entropy) val seed = MnemonicCode.toSeed(mnemonics, "").toByteVector32() - val keyManager = LocalKeyManager(seed, NodeParams.Chain.Regtest, swapInServerXpub) + val keyManager = LocalKeyManager(seed, Bitcoin.Chain.Regtest, swapInServerXpub) val nodeParams = NodeParams( - chain = NodeParams.Chain.Regtest, + chain = Bitcoin.Chain.Regtest, loggerFactory = testLoggerFactory, keyManager = keyManager, ).copy( - alias = "bob", dustLimit = 1_000.sat, maxRemoteDustLimit = 1_500.sat, onChainFeeConf = OnChainFeeConf( @@ -58,7 +58,7 @@ object TestConstants { toRemoteDelayBlocks = CltvExpiryDelta(144), maxToLocalDelayBlocks = CltvExpiryDelta(1024), feeBase = 10.msat, - feeProportionalMillionth = 10, + feeProportionalMillionths = 10, paymentRecipientExpiryParams = RecipientCltvExpiryParams(CltvExpiryDelta(0), CltvExpiryDelta(0)), ) } diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlAuthTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlAuthTest.kt index 1bf23b22f..004d67764 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlAuthTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlAuthTest.kt @@ -17,7 +17,6 @@ package fr.acinq.phoenix.data.lnurl import fr.acinq.bitcoin.* -import fr.acinq.lightning.NodeParams import fr.acinq.lightning.crypto.LocalKeyManager import fr.acinq.lightning.utils.toByteVector import fr.acinq.secp256k1.Hex @@ -28,7 +27,7 @@ import kotlin.test.assertEquals class LnurlAuthTest { private val mnemonics = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" private val seed = MnemonicCode.toSeed(mnemonics, passphrase = "").toByteVector() - private val keyManager = LocalKeyManager(seed, NodeParams.Chain.Testnet, remoteSwapInExtendedPublicKey = "tpubDDt5vQap1awkyDXx1z1cP7QFKSZHDCCpbU8nSq9jy7X2grTjUVZDePexf6gc6AHtRRzkgfPW87K6EKUVV6t3Hu2hg7YkHkmMeLSfrP85x41") + private val keyManager = LocalKeyManager(seed, Bitcoin.Chain.Testnet, remoteSwapInExtendedPublicKey = "tpubDDt5vQap1awkyDXx1z1cP7QFKSZHDCCpbU8nSq9jy7X2grTjUVZDePexf6gc6AHtRRzkgfPW87K6EKUVV6t3Hu2hg7YkHkmMeLSfrP85x41") @Test fun specs_test_vectors() { diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/IncomingPaymentDbTypeVersionTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/IncomingPaymentDbTypeVersionTest.kt index 67d1fd78f..68edda462 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/IncomingPaymentDbTypeVersionTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/IncomingPaymentDbTypeVersionTest.kt @@ -19,7 +19,7 @@ package fr.acinq.phoenix.db import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.TxId import fr.acinq.lightning.db.IncomingPayment -import fr.acinq.lightning.payment.PaymentRequest +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.lightning.utils.msat import fr.acinq.lightning.utils.sat import fr.acinq.phoenix.db.payments.* @@ -35,12 +35,12 @@ class IncomingPaymentDbTypeVersionTest { val channelId1 = ByteVector32.fromValidHex("3b6208285563c9adb009781acf1626f1c2a3b1a3492d5ec312ead8282c7ad6da") val address1 = "tb1q97tpc0y4rvdnu9wm7nu354lmmzdm8du228u3g4" - val invoice1 = - PaymentRequest.read("lntb1500n1ps9u963pp5llphsu6evgmzgk8g2e73su44wn6txmwywdzwvtdwzrt9pqxc9f5sdpzxysy2umswfjhxum0yppk76twypgxzmnwvycqp7xqrrss9qy9qsqsp5qa7092geq6ptp24uzlfw0vj3w4whh2zuc9rquwca69acwx5khckqvslyw2n6dallc868vxu3uueyhw6pe00cmluynv7ca4tknz7g274rp9ucwqpx5ydejsmzl4xpegqtemcq6vwvu8alpxttlj82e7j26gspfj06gn").get() + val bolt11Invoice = + Bolt11Invoice.read("lntb1500n1ps9u963pp5llphsu6evgmzgk8g2e73su44wn6txmwywdzwvtdwzrt9pqxc9f5sdpzxysy2umswfjhxum0yppk76twypgxzmnwvycqp7xqrrss9qy9qsqsp5qa7092geq6ptp24uzlfw0vj3w4whh2zuc9rquwca69acwx5khckqvslyw2n6dallc868vxu3uueyhw6pe00cmluynv7ca4tknz7g274rp9ucwqpx5ydejsmzl4xpegqtemcq6vwvu8alpxttlj82e7j26gspfj06gn").get() @Test fun incoming_origin_invoice() { - val origin = IncomingPayment.Origin.Invoice(invoice1) + val origin = IncomingPayment.Origin.Invoice(bolt11Invoice) val deserialized = IncomingOriginData.deserialize(IncomingOriginTypeVersion.INVOICE_V0, origin.mapToDb().second) assertEquals(origin, deserialized) } diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/OutgoingPaymentDbTypeVersionTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/OutgoingPaymentDbTypeVersionTest.kt index 242ca76b8..dea976181 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/OutgoingPaymentDbTypeVersionTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/OutgoingPaymentDbTypeVersionTest.kt @@ -18,11 +18,9 @@ package fr.acinq.phoenix.db import fr.acinq.lightning.Lightning.randomBytes32 import fr.acinq.lightning.channel.InvalidFinalScript -import fr.acinq.lightning.db.ChannelClosingType import fr.acinq.lightning.db.LightningOutgoingPayment +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.lightning.payment.FinalFailure -import fr.acinq.lightning.payment.PaymentRequest -import fr.acinq.lightning.utils.UUID import fr.acinq.lightning.utils.sat import fr.acinq.lightning.wire.PermanentNodeFailure import fr.acinq.phoenix.db.payments.* @@ -34,12 +32,12 @@ class OutgoingPaymentDbTypeVersionTest { val channelId1 = randomBytes32() val address1 = "tb1q97tpc0y4rvdnu9wm7nu354lmmzdm8du228u3g4" val preimage1 = randomBytes32() - val paymentRequest1 = - PaymentRequest.read("lntb1500n1ps9utezpp5xjfvpvgg3zykv2kdd9yws86xw5ww2kr60h9yphth2h6fly87a9gqdpzxysy2umswfjhxum0yppk76twypgxzmnwvycqp7xqrrss9qy9qsqsp5vm25lch9spq2m9fxqrgcxq0mxrgaehstd9javflyadsle5d97p9qmu9zsjn7l59lmps3568tz9ppla4xhawjptjyrw32jed84fe75z0ka0kmnntc9la95acvc0mjav6rdv5037y6zq9e0eqhenlt8y0yh8cpj467cl").get() + val bolt11Invoice = + Bolt11Invoice.read("lntb1500n1ps9utezpp5xjfvpvgg3zykv2kdd9yws86xw5ww2kr60h9yphth2h6fly87a9gqdpzxysy2umswfjhxum0yppk76twypgxzmnwvycqp7xqrrss9qy9qsqsp5vm25lch9spq2m9fxqrgcxq0mxrgaehstd9javflyadsle5d97p9qmu9zsjn7l59lmps3568tz9ppla4xhawjptjyrw32jed84fe75z0ka0kmnntc9la95acvc0mjav6rdv5037y6zq9e0eqhenlt8y0yh8cpj467cl").get() @Test fun outgoing_details_normal() { - val details = LightningOutgoingPayment.Details.Normal(paymentRequest1) + val details = LightningOutgoingPayment.Details.Normal(bolt11Invoice) val deserialized = OutgoingDetailsData.deserialize(OutgoingDetailsTypeVersion.NORMAL_V0, details.mapToDb().second) assertEquals(details, deserialized) } @@ -53,7 +51,7 @@ class OutgoingPaymentDbTypeVersionTest { @Test fun outgoing_details_swapout() { - val details = LightningOutgoingPayment.Details.SwapOut(address1, paymentRequest1, 1_000.sat) + val details = LightningOutgoingPayment.Details.SwapOut(address1, bolt11Invoice, 1_000.sat) val deserialized = OutgoingDetailsData.deserialize(OutgoingDetailsTypeVersion.SWAPOUT_V0, details.mapToDb().second) assertEquals(details, deserialized) } diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt index 7481789c6..f2e62b131 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt @@ -18,6 +18,7 @@ package fr.acinq.phoenix.db import com.squareup.sqldelight.db.SqlDriver import fr.acinq.bitcoin.* +import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.* import fr.acinq.lightning.Lightning.randomBytes32 import fr.acinq.lightning.channel.TooManyAcceptedHtlcs diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/cloud/CloudDataTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/cloud/CloudDataTest.kt index 531a61718..dc5630c7e 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/cloud/CloudDataTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/cloud/CloudDataTest.kt @@ -1,12 +1,13 @@ package fr.acinq.phoenix.db.cloud import fr.acinq.bitcoin.* +import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.* import fr.acinq.lightning.Lightning.randomBytes32 import fr.acinq.lightning.Lightning.randomKey import fr.acinq.lightning.db.* +import fr.acinq.lightning.payment.Bolt11Invoice import fr.acinq.lightning.payment.FinalFailure -import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.lightning.utils.* import fr.acinq.phoenix.runTest import fr.acinq.secp256k1.Hex @@ -60,7 +61,7 @@ class CloudDataTest { @Test fun incoming__invoice() = runTest { - val invoice = createInvoice(preimage, 250_000.msat) + val invoice = createBolt11Invoice(preimage, 250_000.msat) testRoundtrip( IncomingPayment( preimage = preimage, @@ -94,7 +95,7 @@ class CloudDataTest { @Test fun incoming__receivedWith_lightning() = runTest { - val invoice = createInvoice(preimage, 250_000.msat) + val invoice = createBolt11Invoice(preimage, 250_000.msat) val receivedWith1 = IncomingPayment.ReceivedWith.LightningPayment( amount = 100_000.msat, channelId = channelId, htlcId = 1L ) @@ -112,7 +113,7 @@ class CloudDataTest { @Test fun incoming__receivedWith_newChannel() = runTest { - val invoice = createInvoice(preimage, 10_000_000.msat) + val invoice = createBolt11Invoice(preimage, 10_000_000.msat) val receivedWith = IncomingPayment.ReceivedWith.NewChannel( amount = 7_000_000.msat, miningFee = 2_000.sat, serviceFee = 1_000_000.msat, channelId = channelId, txId = TxId(randomBytes32()), confirmedAt = 500, lockedAt = 800 ) @@ -149,7 +150,7 @@ class CloudDataTest { @Test fun outgoing__normal() = runTest { - val invoice = createInvoice(preimage, 1_000_000.msat) + val invoice = createBolt11Invoice(preimage, 1_000_000.msat) testRoundtrip( LightningOutgoingPayment( id = uuid, @@ -176,7 +177,7 @@ class CloudDataTest { @Test fun outgoing__swapOut() = runTest { - val invoice = createInvoice(preimage, 1_000_000.msat) + val invoice = createBolt11Invoice(preimage, 1_000_000.msat) testRoundtrip( LightningOutgoingPayment( id = uuid, @@ -230,7 +231,7 @@ class CloudDataTest { @Test fun outgoing__failed() = runTest { val recipientAmount = 500_000.msat - val invoice = createInvoice(preimage, recipientAmount) + val invoice = createBolt11Invoice(preimage, recipientAmount) val (a, b) = listOf(randomKey().publicKey(), randomKey().publicKey()) val part = LightningOutgoingPayment.Part( id = UUID.randomUUID(), @@ -266,7 +267,7 @@ class CloudDataTest { @Test fun outgoing__succeeded_offChain() = runTest { val recipientAmount = 500_000.msat - val invoice = createInvoice(preimage, recipientAmount) + val invoice = createBolt11Invoice(preimage, recipientAmount) val (a, b) = listOf(randomKey().publicKey(), randomKey().publicKey()) val part1 = LightningOutgoingPayment.Part( id = UUID.randomUUID(), @@ -421,8 +422,8 @@ class CloudDataTest { Feature.BasicMultiPartPayment to FeatureSupport.Optional ) - private fun createInvoice(preimage: ByteVector32, amount: MilliSatoshi): PaymentRequest { - return PaymentRequest.create( + private fun createBolt11Invoice(preimage: ByteVector32, amount: MilliSatoshi): Bolt11Invoice { + return Bolt11Invoice.create( chainHash = Block.LivenetGenesisBlock.hash, amount = amount, paymentHash = Crypto.sha256(preimage).toByteVector32(), diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/CsvWriterTests.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/CsvWriterTests.kt index 6e24d8337..3553b8ef9 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/CsvWriterTests.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/CsvWriterTests.kt @@ -5,6 +5,7 @@ import fr.acinq.bitcoin.OutPoint import fr.acinq.bitcoin.PrivateKey import fr.acinq.bitcoin.PublicKey import fr.acinq.bitcoin.TxId +import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.CltvExpiryDelta import fr.acinq.lightning.Lightning.randomBytes32 import fr.acinq.lightning.MilliSatoshi @@ -13,7 +14,6 @@ import fr.acinq.lightning.db.ChannelClosingType import fr.acinq.lightning.db.IncomingPayment import fr.acinq.lightning.db.LightningOutgoingPayment import fr.acinq.lightning.payment.PaymentRequest -import fr.acinq.lightning.utils.Either import fr.acinq.lightning.utils.UUID import fr.acinq.lightning.utils.currentTimestampSeconds import fr.acinq.lightning.utils.msat diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/ParserTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/ParserTest.kt index 282a50b96..4d86dc522 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/ParserTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/ParserTest.kt @@ -17,10 +17,10 @@ package fr.acinq.phoenix.utils +import fr.acinq.bitcoin.Bitcoin import fr.acinq.bitcoin.BitcoinError import fr.acinq.bitcoin.ByteVector import fr.acinq.bitcoin.utils.Either -import fr.acinq.lightning.NodeParams import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.lightning.utils.sat import fr.acinq.phoenix.data.BitcoinUriError @@ -34,44 +34,44 @@ class ParserTest { @Test fun parse_bitcoin_uri_with_valid_addresses() { - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Testnet, "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Testnet, "2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Testnet, "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Testnet, "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7")) - assertIs>(Parser.readBitcoinAddress(NodeParams.Chain.Testnet, "tb1p607g5ea77m370pey3y5rg58fz7542hnpg40rs2cqw6w69yt5lf2qlktj2a")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Testnet, "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Testnet, "2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Testnet, "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Testnet, "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7")) + assertIs>(Parser.readBitcoinAddress(Bitcoin.Chain.Testnet, "tb1p607g5ea77m370pey3y5rg58fz7542hnpg40rs2cqw6w69yt5lf2qlktj2a")) } @Test fun parse_bitcoin_uri_chain_mismatch() { assertEquals( expected = Either.Left(BitcoinUriError.InvalidScript(error = BitcoinError.ChainHashMismatch)), - actual = Parser.readBitcoinAddress(NodeParams.Chain.Testnet, "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3") + actual = Parser.readBitcoinAddress(Bitcoin.Chain.Testnet, "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3") ) assertEquals( expected = Either.Left(BitcoinUriError.InvalidScript(error = BitcoinError.ChainHashMismatch)), - actual = Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx") + actual = Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx") ) } @Test fun parse_bitcoin_uri_with_invalid_addresses() { assertIs>( - Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhe") + Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhe") ) } @Test fun parse_bitcoin_uri_with_bitcoin_prefixes() { assertIs>( - Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") ) assertIs>( - Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "bitcoin://bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "bitcoin://bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") ) } @@ -79,13 +79,13 @@ class ParserTest { fun parse_bitcoin_uri_with_non_bitcoin_prefixes() { // non-bitcoin prefixes are not trimmed, so error is invalid script assertIs>( - Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "btc:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "btc:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") ) assertIs>( - Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "lightning:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "lightning:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") ) assertIs>( - Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, "lnurl://bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, "lnurl://bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") ) } @@ -95,7 +95,7 @@ class ParserTest { // ignore unhandled params "bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?somethingyoudontunderstand=50&somethingelseyoudontget=999" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", script = ByteVector("76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac"), ignoredParams = ParametersBuilder().apply { set("somethingyoudontunderstand", "50"); set("somethingelseyoudontget", "999") }.build() @@ -104,7 +104,7 @@ class ParserTest { // ignore payjoin parameter "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?pj=https://acinq.co" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), ignoredParams = ParametersBuilder().apply { set("pj", "https://acinq.co") }.build() @@ -115,7 +115,7 @@ class ParserTest { BitcoinUriError.UnhandledRequiredParams(parameters = listOf("req-somethingyoudontunderstand" to "50", "req-somethingelseyoudontget" to "999")) ), ).forEach { - assertEquals(it.second, Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, it.first)) + assertEquals(it.second, Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, it.first)) } } @@ -125,7 +125,7 @@ class ParserTest { // valid lightning invoice "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?foo=bar&lightning=lntb15u1p05vazrpp5apz75ghtq3ynmc5qm98tsgucmsav44fyffpguhzdep2kcgkfme4sdq4xysyymr0vd4kzcmrd9hx7cqp2xqrrss9qy9qsqsp5v4hqr48qe0u7al6lxwdpmp3w6k7evjdavm0lh7arpv3qaf038s5st2d8k8vvmxyav2wkfym9jp4mk64srmswgh7l6sqtq7l4xl3nknf8snltamvpw5p3yl9nxg0ax9k0698rr94qx6unrv8yhccmh4z9ghcq77hxps" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), paymentRequest = PaymentRequest.read("lntb15u1p05vazrpp5apz75ghtq3ynmc5qm98tsgucmsav44fyffpguhzdep2kcgkfme4sdq4xysyymr0vd4kzcmrd9hx7cqp2xqrrss9qy9qsqsp5v4hqr48qe0u7al6lxwdpmp3w6k7evjdavm0lh7arpv3qaf038s5st2d8k8vvmxyav2wkfym9jp4mk64srmswgh7l6sqtq7l4xl3nknf8snltamvpw5p3yl9nxg0ax9k0698rr94qx6unrv8yhccmh4z9ghcq77hxps").get(), @@ -134,14 +134,14 @@ class ParserTest { ), // invalid lightning invoice "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?lightning=lntb15u1p05vazrpp" to Either.Right( - BitcoinUri(chain = NodeParams.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6")) + BitcoinUri(chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6")) ), // empty lightning invoice "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?lightning=" to Either.Right( - BitcoinUri(chain = NodeParams.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6")) + BitcoinUri(chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6")) ), ).forEach { (address, expected) -> - val uri = Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, address) + val uri = Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, address) assertEquals(expected, uri) } } @@ -151,7 +151,7 @@ class ParserTest { listOf>>( "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=0.0123 " to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = 12_30000.sat @@ -159,7 +159,7 @@ class ParserTest { ), "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=1.23456789999" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = 1_234_56789.sat @@ -167,7 +167,7 @@ class ParserTest { ), "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=21000000.000" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = 21_000_000_000_00000.sat @@ -176,7 +176,7 @@ class ParserTest { // amount with invalid chars is ignored "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=0.001a2" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = null @@ -185,7 +185,7 @@ class ParserTest { // amount with two decimal separators is ignored "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=0.001.2" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = null @@ -194,7 +194,7 @@ class ParserTest { // amount with a comma separator is ignored "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=0,0012" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = null @@ -203,7 +203,7 @@ class ParserTest { // amount < 1 sat is ignored "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=0.000000001" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = null @@ -212,14 +212,14 @@ class ParserTest { // amount > 21e6 btc is ignored "bitcoin:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4?amount=21000000.00000001" to Either.Right( BitcoinUri( - chain = NodeParams.Chain.Mainnet, + chain = Bitcoin.Chain.Mainnet, address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", script = ByteVector("0014751e76e8199196d454941c45d1b3a323f1433bd6"), amount = null ) ) ).forEach { - assertEquals(it.second, Parser.readBitcoinAddress(NodeParams.Chain.Mainnet, it.first)) + assertEquals(it.second, Parser.readBitcoinAddress(Bitcoin.Chain.Mainnet, it.first)) } } diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/db/iosDbFactory.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/db/iosDbFactory.kt index 33ed4d157..d44451b2c 100644 --- a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/db/iosDbFactory.kt +++ b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/db/iosDbFactory.kt @@ -20,13 +20,13 @@ import co.touchlab.sqliter.DatabaseConfiguration import com.squareup.sqldelight.db.SqlDriver import com.squareup.sqldelight.drivers.native.NativeSqliteDriver import com.squareup.sqldelight.drivers.native.wrapConnection -import fr.acinq.lightning.NodeParams +import fr.acinq.bitcoin.Bitcoin import fr.acinq.phoenix.utils.PlatformContext import fr.acinq.phoenix.utils.getDatabaseFilesDirectoryPath actual fun createChannelsDbDriver( ctx: PlatformContext, - chain: NodeParams.Chain, + chain: Bitcoin.Chain, nodeIdHash: String ): SqlDriver { val schema = ChannelsDatabase.Schema @@ -55,7 +55,7 @@ actual fun createChannelsDbDriver( actual fun createPaymentsDbDriver( ctx: PlatformContext, - chain: NodeParams.Chain, + chain: Bitcoin.Chain, nodeIdHash: String ): SqlDriver { val schema = PaymentsDatabase.Schema diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/LightningExposure.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/LightningExposure.kt index 6eec2f03b..b7c36b512 100644 --- a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/LightningExposure.kt +++ b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/LightningExposure.kt @@ -1,14 +1,14 @@ package fr.acinq.phoenix.utils +import fr.acinq.bitcoin.Bitcoin +import fr.acinq.bitcoin.Block +import fr.acinq.bitcoin.BlockHash import fr.acinq.bitcoin.ByteVector -import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.ByteVector64 -import fr.acinq.bitcoin.Crypto import fr.acinq.bitcoin.PrivateKey import fr.acinq.bitcoin.PublicKey import fr.acinq.bitcoin.Satoshi import fr.acinq.bitcoin.TxId -import fr.acinq.bitcoin.io.ByteArrayOutput import fr.acinq.lightning.ChannelEvents import fr.acinq.lightning.DefaultSwapInParams import fr.acinq.lightning.LiquidityEvents @@ -39,9 +39,8 @@ import fr.acinq.lightning.io.PeerEvent import fr.acinq.lightning.io.TcpSocket import fr.acinq.lightning.payment.LiquidityPolicy import fr.acinq.lightning.utils.Connection -import fr.acinq.lightning.wire.LightningCodecs import fr.acinq.lightning.wire.LiquidityAds -import fr.acinq.phoenix.db.payments.WalletPaymentMetadataRow +import fr.acinq.phoenix.PhoenixBusiness /** * Class types from lightning-kmp & bitcoin-kmp are not exported to iOS unless we explicitly @@ -465,4 +464,22 @@ suspend fun Peer._requestInboundLiquidity( } val InboundLiquidityOutgoingPayment._lease: LiquidityAds_Lease - get() = LiquidityAds_Lease(this.lease) \ No newline at end of file + get() = LiquidityAds_Lease(this.lease) + +data class Bitcoin_Chain(public val name: String, val hash: BlockHash) { + constructor(src: Bitcoin.Chain) : this( + name = src.name, + hash = src.chainHash + ) + + fun unwrap(): Bitcoin.Chain = when (this.hash) { + Block.RegtestGenesisBlock.hash -> Bitcoin.Chain.Regtest + Block.TestnetGenesisBlock.hash -> Bitcoin.Chain.Testnet + Block.SignetGenesisBlock.hash -> Bitcoin.Chain.Signet + Block.LivenetGenesisBlock.hash -> Bitcoin.Chain.Mainnet + else -> throw IllegalArgumentException("unsupported hash=${this.hash}") + } +} + +val PhoenixBusiness._chain: Bitcoin_Chain + get() = Bitcoin_Chain(this.chain) \ No newline at end of file