diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Althash.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Althash.cs deleted file mode 100644 index f052aef6c..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Althash.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitAlthash() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("HTML"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Htmlcoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://explorer.htmlcoin.com/api/tx/{0}" : "https://explorer.htmlcoin.com/api/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "HTML_X = HTML_USD", - "HTML_USD = hitbtc(HTML_USD)" - }, - CryptoImagePath = "imlegacy/althash.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("172'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Argoneum.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Argoneum.cs deleted file mode 100644 index 02ecda970..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Argoneum.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NBitcoin; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitArgoneum() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("AGM"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Argoneum", - BlockExplorerLink = NetworkType == ChainName.Mainnet - ? "https://chainz.cryptoid.info/agm/tx.dws?{0}" - : "https://chainz.cryptoid.info/agm-test/tx.dws?{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "AGM_X = AGM_BTC * BTC_X", - "AGM_BTC = argoneum(AGM_BTC)" - }, - CryptoImagePath = "imlegacy/argoneum.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("421'") - : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.BGold.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.BGold.cs deleted file mode 100644 index 27f30d10a..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.BGold.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitBGold() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("BTG"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "BGold", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://btgexplorer.com/tx/{0}" : "https://testnet.btgexplorer.com/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "BTG_X = BTG_BTC * BTC_X", - "BTG_BTC = gate(BTG_BTC)", - }, - CryptoImagePath = "imlegacy/btg.svg", - LightningImagePath = "imlegacy/btg-lightning.svg", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("156'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.BPlus.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.BPlus.cs deleted file mode 100644 index 8adf3a431..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.BPlus.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitBPlus() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("XBC"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "BPlus", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://chainz.cryptoid.info/xbc/tx.dws?{0}" : "https://chainz.cryptoid.info/xbc/tx.dws?{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "XBC_X = XBC_BTC * BTC_X", - "XBC_BTC = cryptopia(XBC_BTC)" - }, - CryptoImagePath = "imlegacy/xbc.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("65'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Bitcore.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Bitcore.cs deleted file mode 100644 index 6d7b9e9f6..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Bitcore.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitBitcore() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("BTX"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "BitCore", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://explorer.bitcore.cc/tx/{0}" : "https://explorer.bitcore.cc/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "BTX_X = BTX_BTC * BTC_X", - "BTX_BTC = graviex(BTX_BTC)" - }, - CryptoImagePath = "imlegacy/bitcore.svg", - LightningImagePath = "imlegacy/bitcore-lightning.svg", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("160'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Dash.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Dash.cs deleted file mode 100644 index 9f75fb4f6..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Dash.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NBitcoin; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitDash() - { - //not needed: NBitcoin.Altcoins.Dash.Instance.EnsureRegistered(); - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("DASH"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Dash", - BlockExplorerLink = NetworkType == ChainName.Mainnet - ? "https://insight.dash.org/insight/tx/{0}" - : "https://testnet-insight.dashevo.org/insight/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "DASH_X = DASH_BTC * BTC_X", - "DASH_BTC = bitfinex(DSH_BTC)" - }, - CryptoImagePath = "imlegacy/dash.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - //https://github.com/satoshilabs/slips/blob/master/slip-0044.md - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("5'") - : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Dogecoin.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Dogecoin.cs deleted file mode 100644 index 3b162df08..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Dogecoin.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitDogecoin() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("DOGE"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Dogecoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://dogechain.info/tx/{0}" : "https://dogechain.info/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "DOGE_X = DOGE_BTC * BTC_X", - "DOGE_BTC = bittrex(DOGE_BTC)" - }, - CryptoImagePath = "imlegacy/dogecoin.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("3'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Feathercoin.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Feathercoin.cs deleted file mode 100644 index 0d046ad30..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Feathercoin.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitFeathercoin() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("FTC"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Feathercoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://explorer.feathercoin.com/tx/{0}" : "https://explorer.feathercoin.com/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "FTC_X = FTC_BTC * BTC_X", - "FTC_BTC = bittrex(FTC_BTC)" - }, - CryptoImagePath = "imlegacy/feathercoin.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("8'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Groestlcoin.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Groestlcoin.cs deleted file mode 100644 index 54dcc5e5e..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Groestlcoin.cs +++ /dev/null @@ -1,33 +0,0 @@ -using NBitcoin; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitGroestlcoin() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("GRS"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Groestlcoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet - ? "https://chainz.cryptoid.info/grs/tx.dws?{0}.htm" - : "https://chainz.cryptoid.info/grs-test/tx.dws?{0}.htm", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "GRS_X = GRS_BTC * BTC_X", - "GRS_BTC = bittrex(GRS_BTC)" - }, - CryptoImagePath = "imlegacy/groestlcoin.png", - LightningImagePath = "imlegacy/groestlcoin-lightning.svg", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("17'") : new KeyPath("1'"), - SupportRBF = true, - SupportPayJoin = true, - VaultSupported = true - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Litecoin.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Litecoin.cs deleted file mode 100644 index 72d4b0f45..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Litecoin.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitLitecoin() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LTC"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Litecoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet - ? "https://live.blockcypher.com/ltc/tx/{0}/" - : "http://explorer.litecointools.com/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "LTC_X = LTC_BTC * BTC_X", - "LTC_BTC = coingecko(LTC_BTC)" - }, - CryptoImagePath = "imlegacy/litecoin.svg", - LightningImagePath = "imlegacy/litecoin-lightning.svg", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("2'") : new KeyPath("1'"), - //https://github.com/pooler/electrum-ltc/blob/0d6989a9d2fb2edbea421c116e49d1015c7c5a91/electrum_ltc/constants.py - ElectrumMapping = NetworkType == ChainName.Mainnet - ? new Dictionary() - { - {0x0488b21eU, DerivationType.Legacy }, - {0x049d7cb2U, DerivationType.SegwitP2SH }, - {0x04b24746U, DerivationType.Segwit }, - } - : new Dictionary() - { - {0x043587cfU, DerivationType.Legacy }, - {0x044a5262U, DerivationType.SegwitP2SH }, - {0x045f1cf6U, DerivationType.Segwit } - } - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Monacoin.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Monacoin.cs deleted file mode 100644 index c8b997f32..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Monacoin.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitMonacoin() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("MONA"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Monacoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://mona.insight.monaco-ex.org/insight/tx/{0}" : "https://testnet-mona.insight.monaco-ex.org/insight/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "MONA_X = MONA_BTC * BTC_X", - "MONA_BTC = bittrex(MONA_BTC)" - }, - CryptoImagePath = "imlegacy/monacoin.png", - LightningImagePath = "imlegacy/mona-lightning.svg", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("22'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Polis.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Polis.cs deleted file mode 100644 index 2110f4f55..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Polis.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitPolis() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("POLIS"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Polis", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://blockbook.polispay.org/tx/{0}" : "https://blockbook.polispay.org/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "POLIS_X = POLIS_BTC * BTC_X", - "POLIS_BTC = polispay(POLIS_BTC)" - }, - CryptoImagePath = "imlegacy/polis.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("1997'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Ufo.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Ufo.cs deleted file mode 100644 index b5c69e553..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Ufo.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitUfo() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("UFO"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Ufo", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://chainz.cryptoid.info/ufo/tx.dws?{0}" : "https://chainz.cryptoid.info/ufo/tx.dws?{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "UFO_X = UFO_BTC * BTC_X", - "UFO_BTC = coinexchange(UFO_BTC)" - }, - CryptoImagePath = "imlegacy/ufo.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("202'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Viacoin.cs b/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Viacoin.cs deleted file mode 100644 index ef56584c6..000000000 --- a/BTCPayServer.Common/Altcoins/BTCPayNetworkProvider.Viacoin.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitViacoin() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("VIA"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Viacoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://explorer.viacoin.org/tx/{0}" : "https://explorer.viacoin.org/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - DefaultRateRules = new[] - { - "VIA_X = VIA_BTC * BTC_X", - "VIA_BTC = bittrex(VIA_BTC)" - }, - CryptoImagePath = "imlegacy/viacoin.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("14'") : new KeyPath("1'") - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/Liquid/BTCPayNetworkProvider.Liquid.cs b/BTCPayServer.Common/Altcoins/Liquid/BTCPayNetworkProvider.Liquid.cs deleted file mode 100644 index d04d891ea..000000000 --- a/BTCPayServer.Common/Altcoins/Liquid/BTCPayNetworkProvider.Liquid.cs +++ /dev/null @@ -1,37 +0,0 @@ -#if ALTCOINS -using NBitcoin; -using NBitcoin.Altcoins; -using NBitcoin.Altcoins.Elements; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitLiquid() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LBTC"); - Add(new ElementsBTCPayNetwork() - { - AssetId = NetworkType == ChainName.Mainnet ? ElementsParams.PeggedAssetId : ElementsParams.PeggedAssetId, - CryptoCode = "LBTC", - NetworkCryptoCode = "LBTC", - DisplayName = "Liquid Bitcoin", - DefaultRateRules = new[] - { - "LBTC_X = LBTC_BTC * BTC_X", - "LBTC_BTC = 1", - }, - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://liquid.network/tx/{0}" : "https://liquid.network/testnet/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - CryptoImagePath = "imlegacy/liquid.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), - SupportRBF = true - }); - } - } - - -} -#endif diff --git a/BTCPayServer.Common/Altcoins/Liquid/BTCPayNetworkProvider.LiquidAssets.cs b/BTCPayServer.Common/Altcoins/Liquid/BTCPayNetworkProvider.LiquidAssets.cs deleted file mode 100644 index e02e2275b..000000000 --- a/BTCPayServer.Common/Altcoins/Liquid/BTCPayNetworkProvider.LiquidAssets.cs +++ /dev/null @@ -1,83 +0,0 @@ -#if ALTCOINS -using NBitcoin; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitLiquidAssets() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LBTC"); - Add(new ElementsBTCPayNetwork() - { - CryptoCode = "USDt", - NetworkCryptoCode = "LBTC", - ShowSyncSummary = false, - DefaultRateRules = new[] - { - "USDT_UST = 1", - "USDT_X = USDT_BTC * BTC_X", - "USDT_BTC = bitfinex(UST_BTC)", - }, - AssetId = NetworkType == ChainName.Regtest? null: new uint256("ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2"), - DisplayName = "Liquid Tether", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://liquid.network/tx/{0}" : "https://liquid.network/testnet/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - CryptoImagePath = "imlegacy/liquid-tether.svg", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), - SupportRBF = true, - SupportLightning = false - }); - - Add(new ElementsBTCPayNetwork() - { - CryptoCode = "ETB", - NetworkCryptoCode = "LBTC", - ShowSyncSummary = false, - DefaultRateRules = new[] - { - - "ETB_X = ETB_BTC * BTC_X", - "ETB_BTC = bitpay(ETB_BTC)" - }, - Divisibility = 2, - AssetId = NetworkType == ChainName.Regtest? null: new uint256("aa775044c32a7df391902b3659f46dfe004ccb2644ce2ddc7dba31e889391caf"), - DisplayName = "Ethiopian Birr", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://liquid.network/tx/{0}" : "https://liquid.network/testnet/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - CryptoImagePath = "imlegacy/etb.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), - SupportRBF = true, - SupportLightning = false - }); - - Add(new ElementsBTCPayNetwork() - { - CryptoCode = "LCAD", - NetworkCryptoCode = "LBTC", - ShowSyncSummary = false, - DefaultRateRules = new[] - { - "LCAD_CAD = 1", - "LCAD_X = CAD_BTC * BTC_X", - "LCAD_BTC = bylls(CAD_BTC)", - "CAD_BTC = LCAD_BTC" - }, - AssetId = NetworkType == ChainName.Regtest? null: new uint256("0e99c1a6da379d1f4151fb9df90449d40d0608f6cb33a5bcbfc8c265f42bab0a"), - DisplayName = "Liquid CAD", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://liquid.network/tx/{0}" : "https://liquid.network/testnet/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - CryptoImagePath = "imlegacy/lcad.png", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), - SupportRBF = true, - SupportLightning = false - }); - } - } - - -} -#endif diff --git a/BTCPayServer.Common/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs b/BTCPayServer.Common/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs deleted file mode 100644 index 1a9358321..000000000 --- a/BTCPayServer.Common/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs +++ /dev/null @@ -1,51 +0,0 @@ -#if ALTCOINS -using System; -using System.Collections.Generic; -using System.Linq; -using BTCPayServer.Common; -using NBitcoin; -using NBXplorer; -using NBXplorer.Models; - -namespace BTCPayServer -{ - public class ElementsBTCPayNetwork : BTCPayNetwork - { - public string NetworkCryptoCode { get; set; } - public uint256 AssetId { get; set; } - public override bool ReadonlyWallet { get; set; } = true; - - public override IEnumerable<(MatchedOutput matchedOutput, OutPoint outPoint)> GetValidOutputs( - NewTransactionEvent evtOutputs) - { - return evtOutputs.Outputs.Where(output => - (output.Value is not AssetMoney && NetworkCryptoCode.Equals(evtOutputs.CryptoCode, StringComparison.InvariantCultureIgnoreCase)) || - (output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId)).Select(output => - { - var outpoint = new OutPoint(evtOutputs.TransactionData.TransactionHash, output.Index); - return (output, outpoint); - }); - } - - public override List FilterValidTransactions(List transactionInformationSet) - { - return transactionInformationSet.FindAll(information => - information.Outputs.Any(output => - output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId) || - information.Inputs.Any(output => - output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId)); - } - - public override PaymentUrlBuilder GenerateBIP21(string cryptoInfoAddress, decimal? cryptoInfoDue) - { - //precision 0: 10 = 0.00000010 - //precision 2: 10 = 0.00001000 - //precision 8: 10 = 10 - var money = cryptoInfoDue / (decimal)Math.Pow(10, 8 - Divisibility); - var builder = base.GenerateBIP21(cryptoInfoAddress, money); - builder.QueryParams.Add("assetid", AssetId.ToString()); - return builder; - } - } -} -#endif diff --git a/BTCPayServer.Common/Altcoins/Liquid/LiquidExtensions.cs b/BTCPayServer.Common/Altcoins/Liquid/LiquidExtensions.cs deleted file mode 100644 index ccfd8e67e..000000000 --- a/BTCPayServer.Common/Altcoins/Liquid/LiquidExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -#if ALTCOINS -using System.Collections.Generic; -using System.Linq; - -namespace BTCPayServer -{ - public static class LiquidExtensions - { - public static IEnumerable GetAllElementsSubChains(this BTCPayNetworkProvider networkProvider, BTCPayNetworkProvider unfiltered) - { - var elementsBased = networkProvider.GetAll().OfType(); - var parentChains = elementsBased.Select(network => network.NetworkCryptoCode.ToUpperInvariant()).Distinct(); - return unfiltered.GetAll().OfType() - .Where(network => parentChains.Contains(network.NetworkCryptoCode)).Select(network => network.CryptoCode.ToUpperInvariant()); - } - } -} -#endif diff --git a/BTCPayServer.Common/Altcoins/Monero/BTCPayNetworkProvider.Monero.cs b/BTCPayServer.Common/Altcoins/Monero/BTCPayNetworkProvider.Monero.cs deleted file mode 100644 index 42d3d5c93..000000000 --- a/BTCPayServer.Common/Altcoins/Monero/BTCPayNetworkProvider.Monero.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NBitcoin; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitMonero() - { - Add(new MoneroLikeSpecificBtcPayNetwork() - { - CryptoCode = "XMR", - DisplayName = "Monero", - Divisibility = 12, - BlockExplorerLink = - NetworkType == ChainName.Mainnet - ? "https://www.exploremonero.com/transaction/{0}" - : "https://testnet.xmrchain.net/tx/{0}", - DefaultRateRules = new[] - { - "XMR_X = XMR_BTC * BTC_X", - "XMR_BTC = kraken(XMR_BTC)" - }, - CryptoImagePath = "/imlegacy/monero.svg", - UriScheme = "monero" - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/Monero/MoneroLikeSpecificBtcPayNetwork.cs b/BTCPayServer.Common/Altcoins/Monero/MoneroLikeSpecificBtcPayNetwork.cs deleted file mode 100644 index 76f532989..000000000 --- a/BTCPayServer.Common/Altcoins/Monero/MoneroLikeSpecificBtcPayNetwork.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BTCPayServer -{ - public class MoneroLikeSpecificBtcPayNetwork : BTCPayNetworkBase - { - public int MaxTrackedConfirmation = 10; - public string UriScheme { get; set; } - } -} diff --git a/BTCPayServer.Common/Altcoins/Zcash/BTCPayNetworkProvider.Zcash.cs b/BTCPayServer.Common/Altcoins/Zcash/BTCPayNetworkProvider.Zcash.cs deleted file mode 100644 index 12c18bf78..000000000 --- a/BTCPayServer.Common/Altcoins/Zcash/BTCPayNetworkProvider.Zcash.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NBitcoin; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - // Change this if you want another zcash coin - public void InitZcash() - { - Add(new ZcashLikeSpecificBtcPayNetwork() - { - CryptoCode = "ZEC", - DisplayName = "Zcash", - Divisibility = 8, - BlockExplorerLink = - NetworkType == ChainName.Mainnet - ? "https://www.exploreZcash.com/transaction/{0}" - : "https://testnet.xmrchain.net/tx/{0}", - DefaultRateRules = new[] - { - "ZEC_X = ZEC_BTC * BTC_X", - "ZEC_BTC = kraken(ZEC_BTC)" - }, - CryptoImagePath = "/imlegacy/zcash.png", - UriScheme = "zcash" - }); - } - } -} diff --git a/BTCPayServer.Common/Altcoins/Zcash/ZcashLikeSpecificBtcPayNetwork.cs b/BTCPayServer.Common/Altcoins/Zcash/ZcashLikeSpecificBtcPayNetwork.cs deleted file mode 100644 index 9ebd8158d..000000000 --- a/BTCPayServer.Common/Altcoins/Zcash/ZcashLikeSpecificBtcPayNetwork.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BTCPayServer -{ - public class ZcashLikeSpecificBtcPayNetwork : BTCPayNetworkBase - { - public int MaxTrackedConfirmation = 10; - public string UriScheme { get; set; } - } -} diff --git a/BTCPayServer.Common/BTCPayNetwork.cs b/BTCPayServer.Common/BTCPayNetwork.cs index a59ba496a..8ec4644b9 100644 --- a/BTCPayServer.Common/BTCPayNetwork.cs +++ b/BTCPayServer.Common/BTCPayNetwork.cs @@ -4,6 +4,8 @@ using System.Globalization; using System.IO; using System.Linq; using BTCPayServer.Common; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; using NBitcoin; using NBXplorer; using NBXplorer.Models; @@ -62,6 +64,31 @@ namespace BTCPayServer public KeyPath CoinType { get; set; } public Dictionary ElectrumMapping = new Dictionary(); + public BTCPayNetwork SetDefaultElectrumMapping(ChainName chainName) + { + //https://github.com/spesmilo/electrum/blob/11733d6bc271646a00b69ff07657119598874da4/electrum/constants.py + ElectrumMapping = chainName == ChainName.Mainnet + ? new Dictionary() + { + {0x0488b21eU, DerivationType.Legacy }, // xpub + {0x049d7cb2U, DerivationType.SegwitP2SH }, // ypub + {0x04b24746U, DerivationType.Segwit }, //zpub + } + : new Dictionary() + { + {0x043587cfU, DerivationType.Legacy}, // tpub + {0x044a5262U, DerivationType.SegwitP2SH}, // upub + {0x045f1cf6U, DerivationType.Segwit} // vpub + }; + if (!NBitcoinNetwork.Consensus.SupportSegwit) + { + ElectrumMapping = + ElectrumMapping + .Where(kv => kv.Value == DerivationType.Legacy) + .ToDictionary(k => k.Key, k => k.Value); + } + return this; + } public virtual bool WalletSupported { get; set; } = true; public virtual bool ReadonlyWallet { get; set; } = false; @@ -107,25 +134,8 @@ namespace BTCPayServer public abstract class BTCPayNetworkBase { - private string _blockExplorerLink; public bool ShowSyncSummary { get; set; } = true; public string CryptoCode { get; set; } - - public string BlockExplorerLink - { - get => _blockExplorerLink; - set - { - if (string.IsNullOrEmpty(BlockExplorerLinkDefault)) - { - BlockExplorerLinkDefault = value; - } - - _blockExplorerLink = value; - } - } - - public string BlockExplorerLinkDefault { get; set; } public string DisplayName { get; set; } public int Divisibility { get; set; } = 8; public bool IsBTC @@ -153,5 +163,8 @@ namespace BTCPayServer { return NBitcoin.JsonConverters.Serializer.ToString(obj, null); } + + [Obsolete("Use TransactionLinkProviders service instead")] + public string BlockExplorerLink { get; set; } } } diff --git a/BTCPayServer.Common/BTCPayNetworkProvider.Bitcoin.cs b/BTCPayServer.Common/BTCPayNetworkProvider.Bitcoin.cs deleted file mode 100644 index 30ab55baa..000000000 --- a/BTCPayServer.Common/BTCPayNetworkProvider.Bitcoin.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using NBitcoin; -using NBXplorer; - -namespace BTCPayServer -{ - public partial class BTCPayNetworkProvider - { - public void InitBitcoin() - { - var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("BTC"); - Add(new BTCPayNetwork() - { - CryptoCode = nbxplorerNetwork.CryptoCode, - DisplayName = "Bitcoin", - BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://mempool.space/tx/{0}" : - NetworkType == Bitcoin.Instance.Signet.ChainName ? "https://mempool.space/signet/tx/{0}" - : "https://mempool.space/testnet/tx/{0}", - NBXplorerNetwork = nbxplorerNetwork, - CryptoImagePath = "imlegacy/bitcoin.svg", - LightningImagePath = "imlegacy/bitcoin-lightning.svg", - DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), - CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("0'") : new KeyPath("1'"), - SupportRBF = true, - SupportPayJoin = true, - VaultSupported = true, - //https://github.com/spesmilo/electrum/blob/11733d6bc271646a00b69ff07657119598874da4/electrum/constants.py - ElectrumMapping = NetworkType == ChainName.Mainnet - ? new Dictionary() - { - {0x0488b21eU, DerivationType.Legacy }, // xpub - {0x049d7cb2U, DerivationType.SegwitP2SH }, // ypub - {0x04b24746U, DerivationType.Segwit }, //zpub - } - : new Dictionary() - { - {0x043587cfU, DerivationType.Legacy}, // tpub - {0x044a5262U, DerivationType.SegwitP2SH}, // upub - {0x045f1cf6U, DerivationType.Segwit} // vpub - } - }); - } - } -} diff --git a/BTCPayServer.Common/BTCPayNetworkProvider.cs b/BTCPayServer.Common/BTCPayNetworkProvider.cs index 2888d9bac..a50916eb9 100644 --- a/BTCPayServer.Common/BTCPayNetworkProvider.cs +++ b/BTCPayServer.Common/BTCPayNetworkProvider.cs @@ -1,8 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; +using BTCPayServer.Configuration; +using BTCPayServer.Logging; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; using NBitcoin; using NBXplorer; +using StandardConfiguration; namespace BTCPayServer { @@ -19,92 +26,39 @@ namespace BTCPayServer } } - BTCPayNetworkProvider(BTCPayNetworkProvider unfiltered, string[] cryptoCodes) - { - NetworkType = unfiltered.NetworkType; - _NBXplorerNetworkProvider = new NBXplorerNetworkProvider(unfiltered.NetworkType); - _Networks = new Dictionary(); - cryptoCodes = cryptoCodes.Select(c => c.ToUpperInvariant()).ToArray(); - foreach (var network in unfiltered._Networks) - { - if (cryptoCodes.Contains(network.Key)) - { - _Networks.Add(network.Key, network.Value); - } - } - } - - public ChainName NetworkType { get; private set; } - public BTCPayNetworkProvider(ChainName networkType) + public BTCPayNetworkProvider( + IEnumerable networks, + SelectedChains selectedChains, + NBXplorerNetworkProvider nbxplorerNetworkProvider, + Logs logs, + IConfiguration configuration) { - _NBXplorerNetworkProvider = new NBXplorerNetworkProvider(networkType); - NetworkType = networkType; - InitBitcoin(); -#if ALTCOINS - InitLiquid(); - InitLiquidAssets(); - InitLitecoin(); - InitBitcore(); - InitDogecoin(); - InitBGold(); - InitMonacoin(); - InitDash(); - InitFeathercoin(); - InitAlthash(); - InitGroestlcoin(); - InitViacoin(); - InitMonero(); - InitZcash(); - // InitArgoneum();//their rate source is down 9/15/20. - // InitMonetaryUnit(); Not supported from Bittrex from 11/23/2022, dead shitcoin +#if !ALTCOINS + var onlyBTC = networks.Count() == 1 && networks.First().IsBTC; + if (!onlyBTC) + throw new ConfigException($"This build of BTCPay Server does not support altcoins"); +#endif - // Assume that electrum mappings are same as BTC if not specified - foreach (var network in _Networks.Values.OfType()) + _NBXplorerNetworkProvider = nbxplorerNetworkProvider; + NetworkType = nbxplorerNetworkProvider.NetworkType; + foreach (var network in networks) { - if (network.ElectrumMapping.Count == 0) - { - network.ElectrumMapping = GetNetwork("BTC").ElectrumMapping; - if (!network.NBitcoinNetwork.Consensus.SupportSegwit) - { - network.ElectrumMapping = - network.ElectrumMapping - .Where(kv => kv.Value == DerivationType.Legacy) - .ToDictionary(k => k.Key, k => k.Value); - } - } + _Networks.Add(network.CryptoCode.ToUpperInvariant(), network); } - // Disabled because of https://twitter.com/Cryptopia_NZ/status/1085084168852291586 - //InitBPlus(); - //InitUfo(); -#endif - } + foreach (var chain in selectedChains.ExplicitlySelected) + { + if (GetNetwork(chain) == null) + throw new ConfigException($"Invalid chains \"{chain}\""); + } - /// - /// Keep only the specified crypto - /// - /// Crypto to support - /// - public BTCPayNetworkProvider Filter(string[] cryptoCodes) - { - return new BTCPayNetworkProvider(this, cryptoCodes); + logs.Configuration.LogInformation( + "Supported chains: " + String.Join(',', _Networks.Select(n => n.Key).ToArray())); } public BTCPayNetwork BTC => GetNetwork("BTC"); public BTCPayNetworkBase DefaultNetwork => BTC ?? GetAll().First(); - - public void Add(BTCPayNetwork network) - { - if (network.NBitcoinNetwork == null) - return; - Add(network as BTCPayNetworkBase); - } - public void Add(BTCPayNetworkBase network) - { - _Networks.Add(network.CryptoCode.ToUpperInvariant(), network); - } - public IEnumerable GetAll() { return _Networks.Values.ToArray(); diff --git a/BTCPayServer.Common/BTCPayServer.Common.csproj b/BTCPayServer.Common/BTCPayServer.Common.csproj index 2d851445c..601c8b545 100644 --- a/BTCPayServer.Common/BTCPayServer.Common.csproj +++ b/BTCPayServer.Common/BTCPayServer.Common.csproj @@ -10,4 +10,7 @@ + + + diff --git a/BTCPayServer/Configuration/ConfigException.cs b/BTCPayServer.Common/Configuration/ConfigException.cs similarity index 100% rename from BTCPayServer/Configuration/ConfigException.cs rename to BTCPayServer.Common/Configuration/ConfigException.cs diff --git a/BTCPayServer.Common/SelectedChains.cs b/BTCPayServer.Common/SelectedChains.cs new file mode 100644 index 000000000..d8d05a77f --- /dev/null +++ b/BTCPayServer.Common/SelectedChains.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BTCPayServer.Logging; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Bson; + +namespace BTCPayServer +{ + public class SelectedChains + { + HashSet chains = new HashSet(StringComparer.OrdinalIgnoreCase); + bool all = false; + public SelectedChains(IConfiguration configuration, Logs logs) + { + foreach (var chain in (configuration["chains"] ?? "btc") + .Split(',', StringSplitOptions.RemoveEmptyEntries) + .Select(t => t.ToUpperInvariant())) + { + if (new[] { "ETH", "USDT20", "FAU" }.Contains(chain, StringComparer.OrdinalIgnoreCase)) + { + logs.Configuration.LogWarning($"'{chain}' is not anymore supported, please remove it from 'chains'"); + continue; + } + if (chain == "*") + { + all = true; + continue; + } + chains.Add(chain); + } + if (chains.Count == 0) + chains.Add("BTC"); + if (all) + chains.Clear(); + } + + public bool Contains(string cryptoCode) + { + return all || chains.Contains(cryptoCode); + } + public void Add(string cryptoCode) + { + chains.Add(cryptoCode); + } + public IEnumerable ExplicitlySelected => chains; + } +} diff --git a/BTCPayServer.Tests/AltcoinTests/ElementsTests.cs b/BTCPayServer.Tests/AltcoinTests/ElementsTests.cs index 71a911c7b..5e6b870af 100644 --- a/BTCPayServer.Tests/AltcoinTests/ElementsTests.cs +++ b/BTCPayServer.Tests/AltcoinTests/ElementsTests.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using BTCPayServer.Configuration; using BTCPayServer.Controllers; using BTCPayServer.Models.WalletViewModels; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Wallets; using BTCPayServer.Tests.Logging; using Microsoft.AspNetCore.Mvc; diff --git a/BTCPayServer.Tests/FastTests.cs b/BTCPayServer.Tests/FastTests.cs index 230774667..038063957 100644 --- a/BTCPayServer.Tests/FastTests.cs +++ b/BTCPayServer.Tests/FastTests.cs @@ -10,6 +10,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BTCPayServer.Abstractions.Extensions; +using BTCPayServer.Abstractions.Models; using BTCPayServer.Client; using BTCPayServer.Client.Models; using BTCPayServer.Configuration; @@ -18,9 +19,12 @@ using BTCPayServer.Data; using BTCPayServer.HostedServices; using BTCPayServer.Hosting; using BTCPayServer.JsonConverters; +using BTCPayServer.Logging; using BTCPayServer.Payments; using BTCPayServer.Payments.Bitcoin; using BTCPayServer.Payments.Lightning; +using BTCPayServer.Plugins; +using BTCPayServer.Plugins.Bitcoin; using BTCPayServer.Rating; using BTCPayServer.Services; using BTCPayServer.Services.Apps; @@ -410,7 +414,7 @@ namespace BTCPayServer.Tests public void CanCalculateDust() { var entity = new InvoiceEntity() { Currency = "USD" }; - entity.Networks = new BTCPayNetworkProvider(ChainName.Regtest); + entity.Networks = CreateNetworkProvider(ChainName.Regtest); #pragma warning disable CS0618 entity.Payments = new System.Collections.Generic.List(); entity.SetPaymentMethod(new PaymentMethod() @@ -456,7 +460,7 @@ namespace BTCPayServer.Tests [Fact] public void CanCalculateCryptoDue() { - var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest); + var networkProvider = CreateNetworkProvider(ChainName.Regtest); var entity = new InvoiceEntity() { Currency = "USD" }; entity.Networks = networkProvider; #pragma warning disable CS0618 @@ -644,7 +648,7 @@ namespace BTCPayServer.Tests [Fact] public void CanAcceptInvoiceWithTolerance() { - var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest); + var networkProvider = CreateNetworkProvider(ChainName.Regtest); var paymentMethodHandlerDictionary = new PaymentMethodHandlerDictionary(new IPaymentMethodHandler[] { new BitcoinLikePaymentHandler(null, networkProvider, null, null, null, null), @@ -764,7 +768,7 @@ namespace BTCPayServer.Tests [Fact] public async Task CanEnumerateTorServices() { - var tor = new TorServices(new BTCPayNetworkProvider(ChainName.Regtest), + var tor = new TorServices(CreateNetworkProvider(ChainName.Regtest), new OptionsWrapper(new BTCPayServerOptions() { TorrcFile = TestUtils.GetTestDataFullPath("Tor/torrc") @@ -776,7 +780,7 @@ namespace BTCPayServer.Tests Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.RPC)); Assert.True(tor.Services.Count(t => t.ServiceType == TorServiceType.Other) > 1); - tor = new TorServices(new BTCPayNetworkProvider(ChainName.Regtest), + tor = new TorServices(CreateNetworkProvider(ChainName.Regtest), new OptionsWrapper(new BTCPayServerOptions() { TorrcFile = null, @@ -813,7 +817,7 @@ namespace BTCPayServer.Tests [Fact] public void CanParseDerivationSchemes() { - var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest); + var networkProvider = CreateNetworkProvider(ChainName.Regtest); var parser = new DerivationSchemeParser(networkProvider.BTC); // xpub @@ -839,7 +843,7 @@ namespace BTCPayServer.Tests Assert.Equal(expected, inner.ToString()); // Output Descriptor - networkProvider = new BTCPayNetworkProvider(ChainName.Mainnet); + networkProvider = CreateNetworkProvider(ChainName.Mainnet); parser = new DerivationSchemeParser(networkProvider.BTC); var od = "wpkh([8bafd160/49h/0h/0h]xpub661MyMwAqRbcGVBsTGeNZN6QGVHmMHLdSA4FteGsRrEriu4pnVZMZWnruFFFXkMnyoBjyHndD3Qwcfz4MPzBUxjSevweNFQx7SAYZATtcDw/0/*)#9x4vkw48"; (strategyBase, rootedKeyPath) = parser.ParseOutputDescriptor(od); @@ -881,8 +885,8 @@ namespace BTCPayServer.Tests [Fact] public void ParseDerivationSchemeSettings() { - var testnet = new BTCPayNetworkProvider(ChainName.Testnet).GetNetwork("BTC"); - var mainnet = new BTCPayNetworkProvider(ChainName.Mainnet).GetNetwork("BTC"); + var testnet = CreateNetworkProvider(ChainName.Testnet).GetNetwork("BTC"); + var mainnet = CreateNetworkProvider(ChainName.Mainnet).GetNetwork("BTC"); var root = new Mnemonic( "usage fever hen zero slide mammal silent heavy donate budget pulse say brain thank sausage brand craft about save attract muffin advance illegal cabbage") .DeriveExtKey(); @@ -1245,7 +1249,7 @@ namespace BTCPayServer.Tests [Fact] public void HasCurrencyDataForNetworks() { - var btcPayNetworkProvider = new BTCPayNetworkProvider(ChainName.Regtest); + var btcPayNetworkProvider = CreateNetworkProvider(ChainName.Regtest); foreach (var network in btcPayNetworkProvider.GetAll()) { var cd = CurrencyNameTable.Instance.GetCurrencyData(network.CryptoCode, false); @@ -1824,8 +1828,7 @@ namespace BTCPayServer.Tests new KeyValuePair("chains", "usdt")} }) }); - - var networkProvider = config.ConfigureNetworkProvider(BTCPayLogs); + var networkProvider = CreateNetworkProvider(config); Assert.NotNull(networkProvider.GetNetwork("LBTC")); Assert.NotNull(networkProvider.GetNetwork("USDT")); } @@ -1833,9 +1836,9 @@ namespace BTCPayServer.Tests [Trait("Altcoins", "Altcoins")] public void CanParseDerivationScheme() { - var testnetNetworkProvider = new BTCPayNetworkProvider(ChainName.Testnet); - var regtestNetworkProvider = new BTCPayNetworkProvider(ChainName.Regtest); - var mainnetNetworkProvider = new BTCPayNetworkProvider(ChainName.Mainnet); + var testnetNetworkProvider = CreateNetworkProvider(ChainName.Testnet); + var regtestNetworkProvider = CreateNetworkProvider(ChainName.Regtest); + var mainnetNetworkProvider = CreateNetworkProvider(ChainName.Mainnet); var testnetParser = new DerivationSchemeParser(testnetNetworkProvider.GetNetwork("BTC")); var mainnetParser = new DerivationSchemeParser(mainnetNetworkProvider.GetNetwork("BTC")); NBXplorer.DerivationStrategy.DerivationStrategyBase result; @@ -2001,7 +2004,7 @@ namespace BTCPayServer.Tests { #pragma warning disable CS0618 var dummy = new Key().PubKey.GetAddress(ScriptPubKeyType.Legacy, Network.RegTest).ToString(); - var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest); + var networkProvider = CreateNetworkProvider(ChainName.Regtest); var networkBTC = networkProvider.GetNetwork("BTC"); var networkLTC = networkProvider.GetNetwork("LTC"); InvoiceEntity invoiceEntity = new InvoiceEntity(); @@ -2118,7 +2121,7 @@ namespace BTCPayServer.Tests { ["derivationStrategy"] = "tpubDDLQZ1WMdy5YJAJWmRNoTJ3uQkavEPXCXnmD4eAuo9BKbzFUBbJmVHys5M3ku4Qw1C165wGpVWH55gZpHjdsCyntwNzhmCAzGejSL6rzbyf" }; - var scheme = DerivationSchemeSettings.Parse("tpubDDLQZ1WMdy5YJAJWmRNoTJ3uQkavEPXCXnmD4eAuo9BKbzFUBbJmVHys5M3ku4Qw1C165wGpVWH55gZpHjdsCyntwNzhmCAzGejSL6rzbyf", new BTCPayNetworkProvider(ChainName.Regtest).BTC); + var scheme = DerivationSchemeSettings.Parse("tpubDDLQZ1WMdy5YJAJWmRNoTJ3uQkavEPXCXnmD4eAuo9BKbzFUBbJmVHys5M3ku4Qw1C165wGpVWH55gZpHjdsCyntwNzhmCAzGejSL6rzbyf", CreateNetworkProvider(ChainName.Regtest).BTC); scheme.Source = "ManualDerivationScheme"; scheme.AccountOriginal = "tpubDDLQZ1WMdy5YJAJWmRNoTJ3uQkavEPXCXnmD4eAuo9BKbzFUBbJmVHys5M3ku4Qw1C165wGpVWH55gZpHjdsCyntwNzhmCAzGejSL6rzbyf"; @@ -2138,7 +2141,7 @@ namespace BTCPayServer.Tests .Select(o => { var entity = JsonConvert.DeserializeObject(o.ToString()); - entity.Networks = new BTCPayNetworkProvider(ChainName.Regtest); + entity.Networks = CreateNetworkProvider(ChainName.Regtest); return entity.DerivationStrategies.ToString(); }) .ToHashSet(); diff --git a/BTCPayServer.Tests/ServerTester.cs b/BTCPayServer.Tests/ServerTester.cs index d6c786296..cf3ac597c 100644 --- a/BTCPayServer.Tests/ServerTester.cs +++ b/BTCPayServer.Tests/ServerTester.cs @@ -5,11 +5,14 @@ using System.IO; using System.Linq; using System.Net.Http; using System.Threading.Tasks; +using BTCPayServer.Hosting; using BTCPayServer.Lightning; using BTCPayServer.Lightning.CLightning; using BTCPayServer.Payments.Lightning; using BTCPayServer.Tests.Lnd; using BTCPayServer.Tests.Logging; +using Microsoft.Extensions.Configuration.Memory; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using NBitcoin; using NBitcoin.RPC; @@ -26,7 +29,7 @@ namespace BTCPayServer.Tests public ILoggerProvider LoggerProvider { get; } internal ILog TestLogs; - public ServerTester(string scope, bool newDb, ILog testLogs, ILoggerProvider loggerProvider) + public ServerTester(string scope, bool newDb, ILog testLogs, ILoggerProvider loggerProvider, BTCPayNetworkProvider networkProvider) { LoggerProvider = loggerProvider; this.TestLogs = testLogs; @@ -36,7 +39,7 @@ namespace BTCPayServer.Tests if (!Directory.Exists(_Directory)) Directory.CreateDirectory(_Directory); - NetworkProvider = new BTCPayNetworkProvider(ChainName.Regtest); + NetworkProvider = networkProvider; ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("BTC").NBitcoinNetwork); ExplorerNode.ScanRPCCapabilities(); diff --git a/BTCPayServer.Tests/TestUtils.cs b/BTCPayServer.Tests/TestUtils.cs index 6c8afe167..09c3b0cc3 100644 --- a/BTCPayServer.Tests/TestUtils.cs +++ b/BTCPayServer.Tests/TestUtils.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; +using NBitcoin; using OpenQA.Selenium; using Xunit; using Xunit.Sdk; diff --git a/BTCPayServer.Tests/ThirdPartyTests.cs b/BTCPayServer.Tests/ThirdPartyTests.cs index feea2bc73..e40af721f 100644 --- a/BTCPayServer.Tests/ThirdPartyTests.cs +++ b/BTCPayServer.Tests/ThirdPartyTests.cs @@ -300,7 +300,7 @@ retry: [Fact()] public void CanSolveTheDogesRatesOnKraken() { - var provider = new BTCPayNetworkProvider(ChainName.Mainnet); + var provider = CreateNetworkProvider(ChainName.Mainnet); var factory = FastTests.CreateBTCPayRateFactory(); var fetcher = new RateFetcher(factory); @@ -318,7 +318,7 @@ retry: { var factory = FastTests.CreateBTCPayRateFactory(); var fetcher = new RateFetcher(factory); - var provider = new BTCPayNetworkProvider(ChainName.Mainnet); + var provider = CreateNetworkProvider(ChainName.Mainnet); var b = new StoreBlob(); string[] temporarilyBroken = { "COP", "UGX" }; foreach (var k in StoreBlob.RecommendedExchanges) @@ -351,7 +351,7 @@ retry: public async Task CanGetRateCryptoCurrenciesByDefault() { using var cts = new CancellationTokenSource(60_000); - var provider = new BTCPayNetworkProvider(ChainName.Mainnet); + var provider = CreateNetworkProvider(ChainName.Mainnet); var factory = FastTests.CreateBTCPayRateFactory(); var fetcher = new RateFetcher(factory); var pairs = diff --git a/BTCPayServer.Tests/UnitTestBase.cs b/BTCPayServer.Tests/UnitTestBase.cs index 4b68023bd..22e75a095 100644 --- a/BTCPayServer.Tests/UnitTestBase.cs +++ b/BTCPayServer.Tests/UnitTestBase.cs @@ -3,8 +3,18 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using BTCPayServer.Abstractions.Models; +using BTCPayServer.Hosting; +using BTCPayServer.Logging; +using BTCPayServer.Plugins.Bitcoin; +using BTCPayServer.Plugins; using BTCPayServer.Tests.Logging; +using Microsoft.Extensions.DependencyInjection; +using NBXplorer; using Xunit.Abstractions; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.Memory; +using NBitcoin; namespace BTCPayServer.Tests { @@ -15,7 +25,53 @@ namespace BTCPayServer.Tests TestLogs = new XUnitLog(helper) { Name = "Tests" }; TestLogProvider = new XUnitLogProvider(helper); BTCPayLogs = new BTCPayServer.Logging.Logs(); - BTCPayLogs.Configure(new BTCPayServer.Logging.FuncLoggerFactory((n) => new XUnitLog(helper) { Name = n })); + LoggerFactory = new BTCPayServer.Logging.FuncLoggerFactory((n) => new XUnitLog(helper) { Name = n }); + BTCPayLogs.Configure(LoggerFactory); + } + + public BTCPayNetworkProvider CreateNetworkProvider(ChainName chainName) + { + var conf = new ConfigurationRoot(new List() + { + new MemoryConfigurationProvider(new MemoryConfigurationSource() + { + InitialData = new[] { + new KeyValuePair("chains", "*"), + new KeyValuePair("network", chainName.ToString()) + } + }) + }); + return CreateNetworkProvider(conf); + } + public BTCPayNetworkProvider CreateNetworkProvider(IConfiguration conf = null) + { + conf ??= new ConfigurationRoot(new List() + { + new MemoryConfigurationProvider(new MemoryConfigurationSource() + { + InitialData = new[] { + new KeyValuePair("chains", "*"), + new KeyValuePair("network", "regtest") + } + }) + }); + var bootstrap = Startup.CreateBootstrap(conf); + var services = new PluginServiceCollection(new ServiceCollection(), bootstrap); + var plugins = new List() { new BitcoinPlugin() }; +#if ALTCOINS + plugins.Add(new BTCPayServer.Plugins.Altcoins.AltcoinsPlugin()); +#endif + foreach (var p in plugins) + { + p.Execute(services); + } + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(); + var serviceProvider = services.BuildServiceProvider(); + return serviceProvider.GetService(); } public ILog TestLogs { @@ -26,14 +82,15 @@ namespace BTCPayServer.Tests get; } public BTCPayServer.Logging.Logs BTCPayLogs { get; } + public FuncLoggerFactory LoggerFactory { get; } public ServerTester CreateServerTester([CallerMemberNameAttribute] string scope = null, bool newDb = false) { - return new ServerTester(scope, newDb, TestLogs, TestLogProvider); + return new ServerTester(scope, newDb, TestLogs, TestLogProvider, CreateNetworkProvider()); } public SeleniumTester CreateSeleniumTester([CallerMemberNameAttribute] string scope = null, bool newDb = false) { - return new SeleniumTester() { Server = new ServerTester(scope, newDb, TestLogs, TestLogProvider) }; + return new SeleniumTester() { Server = new ServerTester(scope, newDb, TestLogs, TestLogProvider, CreateNetworkProvider()) }; } } } diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index 01cf0614f..99093453e 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -38,6 +38,7 @@ + diff --git a/BTCPayServer/Components/StoreRecentTransactions/StoreRecentTransactions.cs b/BTCPayServer/Components/StoreRecentTransactions/StoreRecentTransactions.cs index ca1e4d674..88c4f4b46 100644 --- a/BTCPayServer/Components/StoreRecentTransactions/StoreRecentTransactions.cs +++ b/BTCPayServer/Components/StoreRecentTransactions/StoreRecentTransactions.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Data; using BTCPayServer.Models.StoreViewModels; +using BTCPayServer.Payments; using BTCPayServer.Services; using BTCPayServer.Services.Labels; using BTCPayServer.Services.Stores; @@ -26,18 +27,22 @@ public class StoreRecentTransactions : ViewComponent private readonly BTCPayWalletProvider _walletProvider; private readonly WalletRepository _walletRepository; private readonly LabelService _labelService; + private readonly TransactionLinkProviders _transactionLinkProviders; + public BTCPayNetworkProvider NetworkProvider { get; } public StoreRecentTransactions( BTCPayNetworkProvider networkProvider, BTCPayWalletProvider walletProvider, WalletRepository walletRepository, - LabelService labelService) + LabelService labelService, + TransactionLinkProviders transactionLinkProviders) { NetworkProvider = networkProvider; _walletProvider = walletProvider; _walletRepository = walletRepository; _labelService = labelService; + _transactionLinkProviders = transactionLinkProviders; } public async Task InvokeAsync(StoreRecentTransactionsViewModel vm) @@ -60,7 +65,7 @@ public class StoreRecentTransactions : ViewComponent var wallet = _walletProvider.GetWallet(network); var allTransactions = await wallet.FetchTransactionHistory(derivationSettings.AccountDerivation, 0, 5, TimeSpan.FromDays(31.0), cancellationToken: this.HttpContext.RequestAborted); var walletTransactionsInfo = await _walletRepository.GetWalletTransactionsInfo(vm.WalletId, allTransactions.Select(t => t.TransactionId.ToString()).ToArray()); - + var pmi = new PaymentMethodId(vm.CryptoCode, PaymentTypes.BTCLike); transactions = allTransactions .Select(tx => { @@ -73,8 +78,7 @@ public class StoreRecentTransactions : ViewComponent Balance = tx.BalanceChange.ShowMoney(network), Currency = vm.CryptoCode, IsConfirmed = tx.Confirmations != 0, - Link = string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, - tx.TransactionId.ToString()), + Link = _transactionLinkProviders.GetTransactionLink(pmi, tx.TransactionId.ToString()), Timestamp = tx.SeenAt, Labels = labels }; diff --git a/BTCPayServer/Configuration/DefaultConfiguration.cs b/BTCPayServer/Configuration/DefaultConfiguration.cs index e4ab2e995..0eb6381c5 100644 --- a/BTCPayServer/Configuration/DefaultConfiguration.cs +++ b/BTCPayServer/Configuration/DefaultConfiguration.cs @@ -1,11 +1,20 @@ +using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Text; +using BTCPayServer.Hosting; +using BTCPayServer.Logging; +using BTCPayServer.Plugins; +using BTCPayServer.Plugins.Bitcoin; using CommandLine; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.Memory; +using Microsoft.Extensions.DependencyInjection; using NBitcoin; +using NBXplorer; namespace BTCPayServer.Configuration { @@ -13,7 +22,7 @@ namespace BTCPayServer.Configuration { protected override CommandLineApplication CreateCommandLineApplicationCore() { - var provider = new BTCPayNetworkProvider(ChainName.Mainnet); + var provider = CreateBTCPayNetworkProvider(ChainName.Mainnet); var chains = string.Join(",", provider.GetAll().Select(n => n.CryptoCode.ToLowerInvariant()).ToArray()); CommandLineApplication app = new CommandLineApplication(true) { @@ -134,7 +143,7 @@ namespace BTCPayServer.Configuration builder.AppendLine("#sqlitefile=sqlite.db"); builder.AppendLine(); builder.AppendLine("### NBXplorer settings ###"); - foreach (var n in new BTCPayNetworkProvider(networkType).GetAll().OfType()) + foreach (var n in CreateBTCPayNetworkProvider(networkType).GetAll().OfType()) { builder.AppendLine(CultureInfo.InvariantCulture, $"#{n.CryptoCode}.explorer.url={n.NBXplorerNetwork.DefaultSettings.DefaultUrl}"); builder.AppendLine(CultureInfo.InvariantCulture, $"#{n.CryptoCode}.explorer.cookiefile={n.NBXplorerNetwork.DefaultSettings.DefaultCookieFile}"); @@ -148,8 +157,27 @@ namespace BTCPayServer.Configuration return builder.ToString(); } - - + private BTCPayNetworkProvider CreateBTCPayNetworkProvider(ChainName networkType) + { + var collection = new ServiceCollection(); + var conf = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("network", networkType.ToString()) + }).Build(); + var services = new PluginServiceCollection(collection, Startup.CreateBootstrap(conf)); + var p1 = new BitcoinPlugin(); + p1.Execute(services); +#if ALTCOINS + var p2 = new Plugins.Altcoins.AltcoinsPlugin(); + p2.Execute(services); +#endif + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(services.BootstrapServices.GetRequiredService()); + services.AddSingleton(); + return services.BuildServiceProvider().GetRequiredService(); + } protected override IPEndPoint GetDefaultEndpoint(IConfiguration conf) { return new IPEndPoint(IPAddress.Parse("127.0.0.1"), BTCPayDefaultSettings.GetDefaultSettings(GetNetworkType(conf)).DefaultPort); diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainWalletsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainWalletsController.cs index 448ff0d22..ea0aa7125 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainWalletsController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreOnChainWalletsController.cs @@ -14,6 +14,7 @@ using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.HostedServices; using BTCPayServer.Models.WalletViewModels; +using BTCPayServer.Payments; using BTCPayServer.Payments.PayJoin; using BTCPayServer.Payments.PayJoin.Sender; using BTCPayServer.Services; @@ -54,6 +55,7 @@ namespace BTCPayServer.Controllers.Greenfield private readonly WalletReceiveService _walletReceiveService; private readonly IFeeProviderFactory _feeProviderFactory; private readonly UTXOLocker _utxoLocker; + private readonly TransactionLinkProviders _transactionLinkProviders; public GreenfieldStoreOnChainWalletsController( IAuthorizationService authorizationService, @@ -69,7 +71,8 @@ namespace BTCPayServer.Controllers.Greenfield EventAggregator eventAggregator, WalletReceiveService walletReceiveService, IFeeProviderFactory feeProviderFactory, - UTXOLocker utxoLocker + UTXOLocker utxoLocker, + TransactionLinkProviders transactionLinkProviders ) { _authorizationService = authorizationService; @@ -86,6 +89,7 @@ namespace BTCPayServer.Controllers.Greenfield _walletReceiveService = walletReceiveService; _feeProviderFactory = feeProviderFactory; _utxoLocker = utxoLocker; + _transactionLinkProviders = transactionLinkProviders; } [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)] @@ -312,6 +316,7 @@ namespace BTCPayServer.Controllers.Greenfield var utxos = await wallet.GetUnspentCoins(derivationScheme.AccountDerivation); var walletTransactionsInfoAsync = await _walletRepository.GetWalletTransactionsInfo(walletId, utxos.SelectMany(GetWalletObjectsQuery.Get).Distinct().ToArray()); + var pmi = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike); return Ok(utxos.Select(coin => { walletTransactionsInfoAsync.TryGetValue(coin.OutPoint.Hash.ToString(), out var info1); @@ -327,8 +332,7 @@ namespace BTCPayServer.Controllers.Greenfield #pragma warning disable CS0612 // Type or member is obsolete Labels = info?.LegacyLabels ?? new Dictionary(), #pragma warning restore CS0612 // Type or member is obsolete - Link = string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, - coin.OutPoint.Hash.ToString()), + Link = _transactionLinkProviders.GetTransactionLink(pmi, coin.OutPoint.ToString()), Timestamp = coin.Timestamp, KeyPath = coin.KeyPath, Confirmations = coin.Confirmations, diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index 1a5cc44ee..24e15cbad 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Linq; using System.Net.Mime; using System.Net.WebSockets; +using System.Reflection.Metadata; using System.Threading; using System.Threading.Tasks; using BTCPayServer.Abstractions.Constants; @@ -236,37 +237,7 @@ namespace BTCPayServer.Controllers JToken? receiptData = null; i.Metadata?.AdditionalData?.TryGetValue("receiptData", out receiptData); - var payments = i.GetPayments(true) - .Select(paymentEntity => - { - var paymentData = paymentEntity.GetCryptoPaymentData(); - var paymentMethodId = paymentEntity.GetPaymentMethodId(); - if (paymentData is null || paymentMethodId is null) - { - return null; - } - - string txId = paymentData.GetPaymentId(); - string? link = GetTransactionLink(paymentMethodId, txId); - - return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment - { - Amount = paymentEntity.PaidAmount.Gross, - Paid = paymentEntity.InvoicePaidAmount.Net, - ReceivedDate = paymentEntity.ReceivedTime.DateTime, - AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency), - PaidFormatted = _displayFormatter.Currency(paymentEntity.InvoicePaidAmount.Net, i.Currency, DisplayFormatter.CurrencyFormat.Symbol), - RateFormatted = _displayFormatter.Currency(paymentEntity.Rate, i.Currency, DisplayFormatter.CurrencyFormat.Symbol), - PaymentMethod = paymentMethodId.ToPrettyString(), - Link = link, - Id = txId, - Destination = paymentData.GetDestination(), - PaymentProof = paymentData.GetPaymentProof(), - PaymentType = paymentData.GetPaymentType() - }; - }) - .Where(payment => payment != null) - .ToList(); + var payments = ViewPaymentRequestViewModel.PaymentRequestInvoicePayment.GetViewModels(i, _displayFormatter, _transactionLinkProviders); vm.Amount = i.PaidAmount.Net; vm.Payments = receipt.ShowPayments is false ? null : payments; @@ -275,12 +246,6 @@ namespace BTCPayServer.Controllers return View(print ? "InvoiceReceiptPrint" : "InvoiceReceipt", vm); } - private string? GetTransactionLink(PaymentMethodId paymentMethodId, string txId) - { - var network = _NetworkProvider.GetNetwork(paymentMethodId.CryptoCode); - return network == null ? null : paymentMethodId.PaymentType.GetTransactionLink(network, txId); - } - [HttpGet("invoices/{invoiceId}/refund")] [Authorize(Policy = Policies.CanCreateNonApprovedPullPayments, AuthenticationSchemes = AuthenticationSchemes.Cookie)] public async Task Refund([FromServices] IEnumerable payoutHandlers, string invoiceId, CancellationToken cancellationToken) diff --git a/BTCPayServer/Controllers/UIInvoiceController.cs b/BTCPayServer/Controllers/UIInvoiceController.cs index c1de6a670..33918a5b8 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Client.Models; +using BTCPayServer.Services; using BTCPayServer.Data; using BTCPayServer.Events; using BTCPayServer.HostedServices; @@ -17,7 +18,6 @@ using BTCPayServer.Payments.Bitcoin; using BTCPayServer.Rating; using BTCPayServer.Security; using BTCPayServer.Security.Greenfield; -using BTCPayServer.Services; using BTCPayServer.Services.Apps; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.PaymentRequests; @@ -55,6 +55,7 @@ namespace BTCPayServer.Controllers private readonly InvoiceActivator _invoiceActivator; private readonly LinkGenerator _linkGenerator; private readonly IAuthorizationService _authorizationService; + private readonly TransactionLinkProviders _transactionLinkProviders; private readonly AppService _appService; private readonly IFileService _fileService; @@ -82,7 +83,8 @@ namespace BTCPayServer.Controllers LinkGenerator linkGenerator, AppService appService, IFileService fileService, - IAuthorizationService authorizationService) + IAuthorizationService authorizationService, + TransactionLinkProviders transactionLinkProviders) { _displayFormatter = displayFormatter; _CurrencyNameTable = currencyNameTable ?? throw new ArgumentNullException(nameof(currencyNameTable)); @@ -103,6 +105,7 @@ namespace BTCPayServer.Controllers _invoiceActivator = invoiceActivator; _linkGenerator = linkGenerator; _authorizationService = authorizationService; + _transactionLinkProviders = transactionLinkProviders; _fileService = fileService; _appService = appService; } diff --git a/BTCPayServer/Controllers/UIReportsController.CheatMode.cs b/BTCPayServer/Controllers/UIReportsController.CheatMode.cs index c3056a46a..82f2f4651 100644 --- a/BTCPayServer/Controllers/UIReportsController.CheatMode.cs +++ b/BTCPayServer/Controllers/UIReportsController.CheatMode.cs @@ -17,7 +17,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using System.Text.Json.Nodes; -using Org.BouncyCastle.Ocsp; using System.Threading; using System.Collections.Generic; using Newtonsoft.Json.Linq; diff --git a/BTCPayServer/Controllers/UIReportsController.cs b/BTCPayServer/Controllers/UIReportsController.cs index ef032c1fc..5a0cf5ab4 100644 --- a/BTCPayServer/Controllers/UIReportsController.cs +++ b/BTCPayServer/Controllers/UIReportsController.cs @@ -11,6 +11,8 @@ using BTCPayServer.Models.StoreReportsViewModels; using BTCPayServer.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Internal; using System.Threading; using Newtonsoft.Json.Linq; @@ -21,12 +23,13 @@ namespace BTCPayServer.Controllers; public partial class UIReportsController : Controller { public UIReportsController( - BTCPayNetworkProvider networkProvider, ApplicationDbContextFactory dbContextFactory, GreenfieldReportsController api, ReportService reportService, DisplayFormatter displayFormatter, - BTCPayServerEnvironment env) + BTCPayServerEnvironment env, + BTCPayNetworkProvider networkProvider, + TransactionLinkProviders transactionLinkProviders) { Api = api; ReportService = reportService; @@ -34,6 +37,7 @@ public partial class UIReportsController : Controller DBContextFactory = dbContextFactory; NetworkProvider = networkProvider; DisplayFormatter = displayFormatter; + TransactionLinkProviders = transactionLinkProviders; } private BTCPayNetworkProvider NetworkProvider { get; } private DisplayFormatter DisplayFormatter { get; } @@ -41,6 +45,7 @@ public partial class UIReportsController : Controller public ReportService ReportService { get; } public BTCPayServerEnvironment Env { get; } public ApplicationDbContextFactory DBContextFactory { get; } + public TransactionLinkProviders TransactionLinkProviders { get; } [HttpPost("stores/{storeId}/reports")] [AcceptMediaTypeConstraint("application/json")] @@ -67,7 +72,7 @@ public partial class UIReportsController : Controller var vm = new StoreReportsViewModel { InvoiceTemplateUrl = Url.Action(nameof(UIInvoiceController.Invoice), "UIInvoice", new { invoiceId = "INVOICE_ID" }), - ExplorerTemplateUrls = NetworkProvider.GetAll().ToDictionary(network => network.CryptoCode, network => network.BlockExplorerLink?.Replace("{0}", "TX_ID")), + ExplorerTemplateUrls = TransactionLinkProviders.ToDictionary(p => p.Key.CryptoCode, p => p.Value.BlockExplorerLink?.Replace("{0}", "TX_ID")), Request = new StoreReportRequest { ViewName = viewName ?? "Payments" }, AvailableViews = ReportService.ReportProviders .Values diff --git a/BTCPayServer/Controllers/UIServerController.cs b/BTCPayServer/Controllers/UIServerController.cs index 49dea49f6..0e6273331 100644 --- a/BTCPayServer/Controllers/UIServerController.cs +++ b/BTCPayServer/Controllers/UIServerController.cs @@ -20,6 +20,7 @@ using BTCPayServer.Hosting; using BTCPayServer.Logging; using BTCPayServer.Models; using BTCPayServer.Models.ServerViewModels; +using BTCPayServer.Payments; using BTCPayServer.Services; using BTCPayServer.Services.Apps; using BTCPayServer.Services.Mails; @@ -68,6 +69,7 @@ namespace BTCPayServer.Controllers private readonly IEnumerable _StorageProviderServices; private readonly LinkGenerator _linkGenerator; private readonly EmailSenderFactory _emailSenderFactory; + private readonly TransactionLinkProviders _transactionLinkProviders; public UIServerController( UserManager userManager, @@ -91,7 +93,8 @@ namespace BTCPayServer.Controllers LinkGenerator linkGenerator, EmailSenderFactory emailSenderFactory, IHostApplicationLifetime applicationLifetime, - IHtmlHelper html + IHtmlHelper html, + TransactionLinkProviders transactionLinkProviders ) { _policiesSettings = policiesSettings; @@ -116,6 +119,7 @@ namespace BTCPayServer.Controllers _emailSenderFactory = emailSenderFactory; ApplicationLifetime = applicationLifetime; Html = html; + _transactionLinkProviders = transactionLinkProviders; } [Route("server/maintenance")] @@ -328,8 +332,10 @@ namespace BTCPayServer.Controllers settings.DomainToAppMapping.RemoveAt(index); return View(settings); } - - settings.BlockExplorerLinks = settings.BlockExplorerLinks.Where(tuple => btcPayNetworkProvider.GetNetwork(tuple.CryptoCode).BlockExplorerLinkDefault != tuple.Link).ToList(); + settings.BlockExplorerLinks = settings.BlockExplorerLinks + .Where(tuple => _transactionLinkProviders.GetDefaultBlockExplorerLink(PaymentMethodId.Parse(tuple.CryptoCode)) != tuple.Link) + .Where(tuple => tuple.Link is not null) + .ToList(); if (!ModelState.IsValid) { @@ -362,7 +368,7 @@ namespace BTCPayServer.Controllers } await _SettingsRepository.UpdateSetting(settings); - BlockExplorerLinkStartupTask.SetLinkOnNetworks(settings.BlockExplorerLinks, btcPayNetworkProvider); + _ = _transactionLinkProviders.RefreshTransactionLinkTemplates(); TempData[WellKnownTempData.SuccessMessage] = "Policies updated successfully"; return RedirectToAction(nameof(Policies)); } diff --git a/BTCPayServer/Controllers/UIStoresController.cs b/BTCPayServer/Controllers/UIStoresController.cs index 47f7b2d36..2a8ab5e50 100644 --- a/BTCPayServer/Controllers/UIStoresController.cs +++ b/BTCPayServer/Controllers/UIStoresController.cs @@ -638,7 +638,7 @@ namespace BTCPayServer.Controllers WalletId = new WalletId(store.Id, paymentMethodId.CryptoCode), Enabled = !excludeFilters.Match(paymentMethodId) && strategy != null, #if ALTCOINS - Collapsed = network is ElementsBTCPayNetwork elementsBTCPayNetwork && elementsBTCPayNetwork.NetworkCryptoCode != elementsBTCPayNetwork.CryptoCode && string.IsNullOrEmpty(value) + Collapsed = network is Plugins.Altcoins.ElementsBTCPayNetwork elementsBTCPayNetwork && elementsBTCPayNetwork.NetworkCryptoCode != elementsBTCPayNetwork.CryptoCode && string.IsNullOrEmpty(value) #endif }); break; diff --git a/BTCPayServer/Controllers/UIWalletsController.cs b/BTCPayServer/Controllers/UIWalletsController.cs index d1f20856d..afae515a0 100644 --- a/BTCPayServer/Controllers/UIWalletsController.cs +++ b/BTCPayServer/Controllers/UIWalletsController.cs @@ -66,6 +66,7 @@ namespace BTCPayServer.Controllers private readonly DelayedTransactionBroadcaster _broadcaster; private readonly PayjoinClient _payjoinClient; private readonly LabelService _labelService; + private readonly TransactionLinkProviders _transactionLinkProviders; private readonly PullPaymentHostedService _pullPaymentHostedService; private readonly WalletHistogramService _walletHistogramService; @@ -89,10 +90,12 @@ namespace BTCPayServer.Controllers PayjoinClient payjoinClient, IServiceProvider serviceProvider, PullPaymentHostedService pullPaymentHostedService, - LabelService labelService) + LabelService labelService, + TransactionLinkProviders transactionLinkProviders) { _currencyTable = currencyTable; _labelService = labelService; + _transactionLinkProviders = transactionLinkProviders; Repository = repo; WalletRepository = walletRepository; RateFetcher = rateProvider; @@ -248,12 +251,12 @@ namespace BTCPayServer.Controllers } else { + var pmi = new PaymentMethodId(walletId.CryptoCode, PaymentTypes.BTCLike); foreach (var tx in transactions) { var vm = new ListTransactionsViewModel.TransactionViewModel(); vm.Id = tx.TransactionId.ToString(); - vm.Link = string.Format(CultureInfo.InvariantCulture, paymentMethod.Network.BlockExplorerLink, - vm.Id); + vm.Link = _transactionLinkProviders.GetTransactionLink(pmi, vm.Id); vm.Timestamp = tx.SeenAt; vm.Positive = tx.BalanceChange.GetValue(wallet.Network) >= 0; vm.Balance = tx.BalanceChange.ShowMoney(wallet.Network); @@ -590,7 +593,7 @@ namespace BTCPayServer.Controllers var utxos = await _walletProvider.GetWallet(network) .GetUnspentCoins(schemeSettings.AccountDerivation, false, cancellation); - + var pmi = new PaymentMethodId(vm.CryptoCode, PaymentTypes.BTCLike); var walletTransactionsInfoAsync = await this.WalletRepository.GetWalletTransactionsInfo(walletId, utxos.SelectMany(GetWalletObjectsQuery.Get).Distinct().ToArray()); vm.InputsAvailable = utxos.Select(coin => @@ -605,8 +608,7 @@ namespace BTCPayServer.Controllers Amount = coin.Value.GetValue(network), Comment = info?.Comment, Labels = _labelService.CreateTransactionTagModels(info, Request), - Link = string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, - coin.OutPoint.Hash.ToString()), + Link = _transactionLinkProviders.GetTransactionLink(pmi, coin.OutPoint.ToString()), Confirmations = coin.Confirmations }; }).ToArray(); diff --git a/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs b/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs index 010dae521..ac637dd14 100644 --- a/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs +++ b/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs @@ -37,6 +37,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler private readonly ApplicationDbContextFactory _dbContextFactory; private readonly NotificationSender _notificationSender; private readonly Logs Logs; + private readonly TransactionLinkProviders _transactionLinkProviders; public WalletRepository WalletRepository { get; } @@ -46,7 +47,8 @@ public class BitcoinLikePayoutHandler : IPayoutHandler BTCPayNetworkJsonSerializerSettings jsonSerializerSettings, ApplicationDbContextFactory dbContextFactory, NotificationSender notificationSender, - Logs logs) + Logs logs, + TransactionLinkProviders transactionLinkProviders) { _btcPayNetworkProvider = btcPayNetworkProvider; WalletRepository = walletRepository; @@ -55,6 +57,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler _dbContextFactory = dbContextFactory; _notificationSender = notificationSender; this.Logs = logs; + _transactionLinkProviders = transactionLinkProviders; } @@ -120,10 +123,9 @@ public class BitcoinLikePayoutHandler : IPayoutHandler var res = raw.ToObject( JsonSerializer.Create(_jsonSerializerSettings.GetSerializer(paymentMethodId.CryptoCode))); - var network = _btcPayNetworkProvider.GetNetwork(paymentMethodId.CryptoCode); if (res == null) return null; - res.LinkTemplate = network.BlockExplorerLink; + res.LinkTemplate = _transactionLinkProviders.GetBlockExplorerLink(paymentMethodId); return res; } return raw.ToObject(); diff --git a/BTCPayServer/Extensions.cs b/BTCPayServer/Extensions.cs index df6597a53..e5e4cbfb7 100644 --- a/BTCPayServer/Extensions.cs +++ b/BTCPayServer/Extensions.cs @@ -425,42 +425,6 @@ namespace BTCPayServer return controller.View("PostRedirect", redirectVm); } - public static BTCPayNetworkProvider ConfigureNetworkProvider(this IConfiguration configuration, Logs logs) - { - var _networkType = DefaultConfiguration.GetNetworkType(configuration); - var supportedChains = configuration.GetOrDefault("chains", "btc") - .Split(',', StringSplitOptions.RemoveEmptyEntries) - .Select(t => t.ToUpperInvariant()).ToHashSet(); - foreach (var c in supportedChains.ToList()) - { - if (new[] { "ETH", "USDT20", "FAU" }.Contains(c, StringComparer.OrdinalIgnoreCase)) - { - logs.Configuration.LogWarning($"'{c}' is not anymore supported, please remove it from 'chains'"); - supportedChains.Remove(c); - } - } - var networkProvider = new BTCPayNetworkProvider(_networkType); - var filtered = networkProvider.Filter(supportedChains.ToArray()); -#if ALTCOINS - supportedChains.AddRange(filtered.GetAllElementsSubChains(networkProvider)); -#endif -#if !ALTCOINS - var onlyBTC = supportedChains.Count == 1 && supportedChains.First() == "BTC"; - if (!onlyBTC) - throw new ConfigException($"This build of BTCPay Server does not support altcoins"); -#endif - var result = networkProvider.Filter(supportedChains.ToArray()); - foreach (var chain in supportedChains) - { - if (result.GetNetwork(chain) == null) - throw new ConfigException($"Invalid chains \"{chain}\""); - } - - logs.Configuration.LogInformation( - "Supported chains: " + String.Join(',', supportedChains.ToArray())); - return result; - } - public static DataDirectories Configure(this DataDirectories dataDirectories, IConfiguration configuration) { var networkType = DefaultConfiguration.GetNetworkType(configuration); diff --git a/BTCPayServer/Extensions/MoneyExtensions.cs b/BTCPayServer/Extensions/MoneyExtensions.cs index 81496d7c4..d275e42f6 100644 --- a/BTCPayServer/Extensions/MoneyExtensions.cs +++ b/BTCPayServer/Extensions/MoneyExtensions.cs @@ -18,7 +18,7 @@ namespace BTCPayServer return mb.Select(money => money.GetValue(network)).Sum(); #if ALTCOINS case AssetMoney assetMoney: - if (network is ElementsBTCPayNetwork elementsBTCPayNetwork) + if (network is BTCPayServer.Plugins.Altcoins.ElementsBTCPayNetwork elementsBTCPayNetwork) { return elementsBTCPayNetwork.AssetId == assetMoney.AssetId ? Convert(assetMoney.Quantity, elementsBTCPayNetwork.Divisibility) diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index 5c5084d6b..9252d4baf 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -225,11 +225,6 @@ namespace BTCPayServer.Hosting }; options.NBXplorerConnectionSettings.Add(setting); options.ConnectionString = configuration.GetOrDefault("explorer.postgres", null); - var blockExplorerLink = configuration.GetOrDefault("blockexplorerlink", null); - if (!string.IsNullOrEmpty(blockExplorerLink)) - { - btcPayNetwork.BlockExplorerLink = blockExplorerLink; - } } }); services.AddOptions().Configure( @@ -306,7 +301,7 @@ namespace BTCPayServer.Hosting } } }); - services.TryAddSingleton(o => configuration.ConfigureNetworkProvider(logs)); + services.TryAddSingleton(); services.TryAddSingleton(); services.AddTransient(); @@ -355,6 +350,7 @@ namespace BTCPayServer.Hosting return htmlSanitizer; }); + services.AddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); @@ -426,7 +422,7 @@ namespace BTCPayServer.Hosting services.AddSingleton(); services.AddScoped(); - + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -569,6 +565,15 @@ namespace BTCPayServer.Hosting { services.AddSingleton(); } + public static IServiceCollection AddBTCPayNetwork(this IServiceCollection services, BTCPayNetworkBase network) + { + services.AddSingleton(network); + return services; + } + public static void AddTransactionLinkProvider(this IServiceCollection services, PaymentMethodId paymentMethodId, TransactionLinkProvider provider) + { + services.AddSingleton(new TransactionLinkProviders.Entry(paymentMethodId, provider)); + } public static void AddRateProviderExchangeSharp(this IServiceCollection services, RateSourceInfo rateInfo) where T : ExchangeAPI { services.AddSingleton>(o => diff --git a/BTCPayServer/Hosting/BlockExplorerLinkStartupTask.cs b/BTCPayServer/Hosting/BlockExplorerLinkStartupTask.cs index 2f6b8b855..8c696099d 100644 --- a/BTCPayServer/Hosting/BlockExplorerLinkStartupTask.cs +++ b/BTCPayServer/Hosting/BlockExplorerLinkStartupTask.cs @@ -5,41 +5,35 @@ using System.Threading; using System.Threading.Tasks; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Services; +using Microsoft.Extensions.Configuration; namespace BTCPayServer.Hosting { public class BlockExplorerLinkStartupTask : IStartupTask { - private readonly SettingsRepository _settingsRepository; private readonly BTCPayNetworkProvider _btcPayNetworkProvider; + private readonly TransactionLinkProviders _transactionLinksProviders; + private readonly IConfiguration _configuration; - public BlockExplorerLinkStartupTask(SettingsRepository settingsRepository, - BTCPayNetworkProvider btcPayNetworkProvider) + public BlockExplorerLinkStartupTask( + BTCPayNetworkProvider btcPayNetworkProvider, + TransactionLinkProviders transactionLinksProviders, + IConfiguration configuration) { - _settingsRepository = settingsRepository; _btcPayNetworkProvider = btcPayNetworkProvider; + _transactionLinksProviders = transactionLinksProviders; + _configuration = configuration; } public async Task ExecuteAsync(CancellationToken cancellationToken = default) { - var settings = await _settingsRepository.GetSettingAsync(); - if (settings?.BlockExplorerLinks?.Any() is true) + var blockExplorerLink = _configuration["blockexplorerlink"]; + if (!string.IsNullOrEmpty(blockExplorerLink)) { - SetLinkOnNetworks(settings.BlockExplorerLinks, _btcPayNetworkProvider); - } - } - - public static void SetLinkOnNetworks(List links, - BTCPayNetworkProvider networkProvider) - { - var networks = networkProvider.GetAll(); - foreach (var network in networks) - { - var overrideLink = links.SingleOrDefault(item => - item.CryptoCode.Equals(network.CryptoCode, StringComparison.InvariantCultureIgnoreCase)); - network.BlockExplorerLink = overrideLink?.Link ?? network.BlockExplorerLinkDefault; - + foreach (var prov in _transactionLinksProviders.Values) + prov.OverrideBlockExplorerLink = blockExplorerLink; } + await _transactionLinksProviders.RefreshTransactionLinkTemplates(); } } } diff --git a/BTCPayServer/Hosting/Startup.cs b/BTCPayServer/Hosting/Startup.cs index 0bcf00d08..0541ac6b5 100644 --- a/BTCPayServer/Hosting/Startup.cs +++ b/BTCPayServer/Hosting/Startup.cs @@ -33,8 +33,10 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; +using NBXplorer; using NicolasDorier.RateLimits; namespace BTCPayServer.Hosting @@ -57,8 +59,29 @@ namespace BTCPayServer.Hosting } public ILoggerFactory LoggerFactory { get; } public Logs Logs { get; } + + public static ServiceProvider CreateBootstrap(IConfiguration conf) + { + return CreateBootstrap(conf, new Logs(), new FuncLoggerFactory(n => NullLogger.Instance)); + } + public static ServiceProvider CreateBootstrap(IConfiguration conf, Logs logs, ILoggerFactory loggerFactory) + { + ServiceCollection bootstrapServices = new ServiceCollection(); + var networkType = DefaultConfiguration.GetNetworkType(conf); + bootstrapServices.AddSingleton(logs); + bootstrapServices.AddSingleton(loggerFactory); + bootstrapServices.AddSingleton(conf); + bootstrapServices.AddSingleton(); + bootstrapServices.AddSingleton(new NBXplorerNetworkProvider(networkType)); + return bootstrapServices.BuildServiceProvider(); + } + public void ConfigureServices(IServiceCollection services) { + var bootstrapServiceProvider = CreateBootstrap(Configuration, Logs, LoggerFactory); + services.AddSingleton(bootstrapServiceProvider.GetRequiredService()); + services.AddSingleton(bootstrapServiceProvider.GetRequiredService()); + services.AddMemoryCache(); services.AddDataProtection() .SetApplicationName("BTCPay Server") @@ -143,7 +166,7 @@ namespace BTCPayServer.Hosting }) .AddNewtonsoftJson() .AddRazorRuntimeCompilation() - .AddPlugins(services, Configuration, LoggerFactory) + .AddPlugins(services, Configuration, LoggerFactory, bootstrapServiceProvider) .AddControllersAsServices(); services.AddServerSideBlazor(); diff --git a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs index 6ba0252a6..9b4e424f3 100644 --- a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs +++ b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs @@ -5,6 +5,7 @@ using System.Linq; using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.Payments; +using BTCPayServer.Services; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Rates; using BTCPayServer.Validation; @@ -212,6 +213,44 @@ namespace BTCPayServer.Models.PaymentRequestViewModels public class PaymentRequestInvoicePayment { + public static List + GetViewModels( + InvoiceEntity invoice, + DisplayFormatter displayFormatter, + TransactionLinkProviders txLinkProvider) + { + return invoice + .GetPayments(true) + .Select(paymentEntity => + { + var paymentData = paymentEntity.GetCryptoPaymentData(); + var paymentMethodId = paymentEntity.GetPaymentMethodId(); + if (paymentData is null || paymentMethodId is null) + { + return null; + } + string txId = paymentData.GetPaymentId(); + string link = txLinkProvider.GetTransactionLink(paymentMethodId, txId); + + return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment + { + Amount = paymentEntity.PaidAmount.Gross, + Paid = paymentEntity.InvoicePaidAmount.Net, + ReceivedDate = paymentEntity.ReceivedTime.DateTime, + AmountFormatted = displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency, DisplayFormatter.CurrencyFormat.None), + PaidFormatted = displayFormatter.Currency(paymentEntity.InvoicePaidAmount.Net, invoice.Currency, DisplayFormatter.CurrencyFormat.Symbol), + RateFormatted = displayFormatter.Currency(paymentEntity.Rate, invoice.Currency, DisplayFormatter.CurrencyFormat.Symbol), + PaymentMethod = paymentMethodId.ToPrettyString(), + Link = link, + Id = txId, + Destination = paymentData.GetDestination(), + PaymentProof = paymentData.GetPaymentProof(), + PaymentType = paymentData.GetPaymentType() + }; + }) + .Where(payment => payment != null) + .ToList(); + } public string PaymentMethod { get; set; } public decimal Amount { get; set; } public string AmountFormatted { get; set; } diff --git a/BTCPayServer/PaymentRequest/PaymentRequestService.cs b/BTCPayServer/PaymentRequest/PaymentRequestService.cs index ccc191402..fcfbc63ff 100644 --- a/BTCPayServer/PaymentRequest/PaymentRequestService.cs +++ b/BTCPayServer/PaymentRequest/PaymentRequestService.cs @@ -20,6 +20,7 @@ namespace BTCPayServer.PaymentRequest private readonly BTCPayNetworkProvider _BtcPayNetworkProvider; private readonly InvoiceRepository _invoiceRepository; private readonly CurrencyNameTable _currencies; + private readonly TransactionLinkProviders _transactionLinkProviders; private readonly DisplayFormatter _displayFormatter; public PaymentRequestService( @@ -27,12 +28,14 @@ namespace BTCPayServer.PaymentRequest BTCPayNetworkProvider btcPayNetworkProvider, InvoiceRepository invoiceRepository, DisplayFormatter displayFormatter, - CurrencyNameTable currencies) + CurrencyNameTable currencies, + TransactionLinkProviders transactionLinkProviders) { _PaymentRequestRepository = paymentRequestRepository; _BtcPayNetworkProvider = btcPayNetworkProvider; _invoiceRepository = invoiceRepository; _currencies = currencies; + _transactionLinkProviders = transactionLinkProviders; _displayFormatter = displayFormatter; } @@ -116,36 +119,7 @@ namespace BTCPayServer.PaymentRequest Invoices = new ViewPaymentRequestViewModel.InvoiceList(invoices.Select(entity => { var state = entity.GetInvoiceState(); - var payments = entity - .GetPayments(true) - .Select(paymentEntity => - { - var paymentData = paymentEntity.GetCryptoPaymentData(); - var paymentMethodId = paymentEntity.GetPaymentMethodId(); - if (paymentData is null || paymentMethodId is null) - { - return null; - } - - string txId = paymentData.GetPaymentId(); - string link = GetTransactionLink(paymentMethodId, txId); - - return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment - { - Amount = paymentEntity.PaidAmount.Gross, - Paid = paymentEntity.InvoicePaidAmount.Net, - ReceivedDate = paymentEntity.ReceivedTime.DateTime, - AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency), - PaidFormatted = _displayFormatter.Currency(paymentEntity.InvoicePaidAmount.Net, blob.Currency, DisplayFormatter.CurrencyFormat.Symbol), - RateFormatted = _displayFormatter.Currency(paymentEntity.Rate, blob.Currency, DisplayFormatter.CurrencyFormat.Symbol), - PaymentMethod = paymentMethodId.ToPrettyString(), - Link = link, - Id = txId, - Destination = paymentData.GetDestination() - }; - }) - .Where(payment => payment != null) - .ToList(); + var payments = ViewPaymentRequestViewModel.PaymentRequestInvoicePayment.GetViewModels(entity, _displayFormatter, _transactionLinkProviders); if (state.Status == InvoiceStatusLegacy.Invalid || state.Status == InvoiceStatusLegacy.Expired && !payments.Any()) @@ -166,13 +140,5 @@ namespace BTCPayServer.PaymentRequest .Where(invoice => invoice != null)) }; } - - private string GetTransactionLink(PaymentMethodId paymentMethodId, string txId) - { - var network = _BtcPayNetworkProvider.GetNetwork(paymentMethodId.CryptoCode); - if (network == null) - return null; - return paymentMethodId.PaymentType.GetTransactionLink(network, txId); - } } } diff --git a/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs b/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs index 7e255f6d6..9a77ee71e 100644 --- a/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs +++ b/BTCPayServer/Payments/PaymentTypes.Bitcoin.cs @@ -57,15 +57,6 @@ namespace BTCPayServer.Payments return DerivationSchemeSettings.Parse(((JValue)value).Value(), net); } - public override string GetTransactionLink(BTCPayNetworkBase network, string txId) - { - ArgumentNullException.ThrowIfNull(txId); - if (network?.BlockExplorerLink == null) - return null; - txId = txId.Split('-').First(); - return string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, txId); - } - public override string GetPaymentLink(BTCPayNetworkBase network, InvoiceEntity invoice, IPaymentMethodDetails paymentMethodDetails, decimal cryptoInfoDue, string serverUri) { diff --git a/BTCPayServer/Payments/PaymentTypes.Lightning.cs b/BTCPayServer/Payments/PaymentTypes.Lightning.cs index 493c16ce1..a89945bba 100644 --- a/BTCPayServer/Payments/PaymentTypes.Lightning.cs +++ b/BTCPayServer/Payments/PaymentTypes.Lightning.cs @@ -47,11 +47,6 @@ namespace BTCPayServer.Payments return JsonConvert.DeserializeObject(value.ToString()); } - public override string GetTransactionLink(BTCPayNetworkBase network, string txId) - { - return null; - } - public override string GetPaymentLink(BTCPayNetworkBase network, InvoiceEntity invoice, IPaymentMethodDetails paymentMethodDetails, decimal cryptoInfoDue, string serverUri) { diff --git a/BTCPayServer/Payments/PaymentTypes.cs b/BTCPayServer/Payments/PaymentTypes.cs index c83f082e8..e9423d24c 100644 --- a/BTCPayServer/Payments/PaymentTypes.cs +++ b/BTCPayServer/Payments/PaymentTypes.cs @@ -83,7 +83,6 @@ namespace BTCPayServer.Payments public abstract IPaymentMethodDetails DeserializePaymentMethodDetails(BTCPayNetworkBase network, string str); public abstract string SerializePaymentMethodDetails(BTCPayNetworkBase network, IPaymentMethodDetails details); public abstract ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value); - public abstract string GetTransactionLink(BTCPayNetworkBase network, string txId); public abstract string GetPaymentLink(BTCPayNetworkBase network, InvoiceEntity invoice, IPaymentMethodDetails paymentMethodDetails, decimal cryptoInfoDue, string serverUri); public abstract string InvoiceViewPaymentPartialName { get; } diff --git a/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.BGold.cs b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.BGold.cs new file mode 100644 index 000000000..998c7bf3b --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.BGold.cs @@ -0,0 +1,35 @@ +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; + +namespace BTCPayServer.Plugins.Altcoins; + +public partial class AltcoinsPlugin +{ + public void InitBGold(IServiceCollection services) + { + var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("BTG"); + var network = new BTCPayNetwork() + { + CryptoCode = nbxplorerNetwork.CryptoCode, + DisplayName = "BGold", + NBXplorerNetwork = nbxplorerNetwork, + DefaultRateRules = new[] + { + "BTG_X = BTG_BTC * BTC_X", + "BTG_BTC = gate(BTG_BTC)", + }, + CryptoImagePath = "imlegacy/btg.svg", + LightningImagePath = "imlegacy/btg-lightning.svg", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("156'") : new KeyPath("1'") + }.SetDefaultElectrumMapping(ChainName); + var blockExplorerLink = ChainName == ChainName.Mainnet ? "https://btgexplorer.com/tx/{0}" : "https://testnet.btgexplorer.com/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(nbxplorerNetwork.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(blockExplorerLink)); + } +} diff --git a/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Dash.cs b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Dash.cs new file mode 100644 index 000000000..680ab75e2 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Dash.cs @@ -0,0 +1,38 @@ +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; + +namespace BTCPayServer.Plugins.Altcoins; +public partial class AltcoinsPlugin +{ + public void InitDash(IServiceCollection services) + { + //not needed: NBitcoin.Altcoins.Dash.Instance.EnsureRegistered(); + var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("DASH"); + var network = new BTCPayNetwork() + { + CryptoCode = nbxplorerNetwork.CryptoCode, + DisplayName = "Dash", + NBXplorerNetwork = nbxplorerNetwork, + DefaultRateRules = new[] + { + "DASH_X = DASH_BTC * BTC_X", + "DASH_BTC = bitfinex(DSH_BTC)" + }, + CryptoImagePath = "imlegacy/dash.png", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + //https://github.com/satoshilabs/slips/blob/master/slip-0044.md + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("5'") + : new KeyPath("1'") + }.SetDefaultElectrumMapping(ChainName); + + var blockExplorerLink = ChainName == ChainName.Mainnet + ? "https://insight.dash.org/insight/tx/{0}" + : "https://testnet-insight.dashevo.org/insight/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(nbxplorerNetwork.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(blockExplorerLink)); + } +} diff --git a/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Dogecoin.cs b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Dogecoin.cs new file mode 100644 index 000000000..44479c42c --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Dogecoin.cs @@ -0,0 +1,36 @@ +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; +using NBXplorer; + +namespace BTCPayServer.Plugins.Altcoins; + +public partial class AltcoinsPlugin +{ + public void InitDogecoin(IServiceCollection services) + { + var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("DOGE"); + var network = new BTCPayNetwork() + { + CryptoCode = nbxplorerNetwork.CryptoCode, + DisplayName = "Dogecoin", + NBXplorerNetwork = nbxplorerNetwork, + DefaultRateRules = new[] + { + "DOGE_X = DOGE_BTC * BTC_X", + "DOGE_BTC = bittrex(DOGE_BTC)" + }, + CryptoImagePath = "imlegacy/dogecoin.png", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("3'") : new KeyPath("1'") + }.SetDefaultElectrumMapping(ChainName); + + var blockExplorerLink = ChainName == ChainName.Mainnet ? "https://dogechain.info/tx/{0}" : "https://dogechain.info/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(nbxplorerNetwork.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(blockExplorerLink)); + } +} + diff --git a/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Groestlcoin.cs b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Groestlcoin.cs new file mode 100644 index 000000000..21abfead6 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Groestlcoin.cs @@ -0,0 +1,40 @@ +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; + +namespace BTCPayServer.Plugins.Altcoins; + +public partial class AltcoinsPlugin +{ + public void InitGroestlcoin(IServiceCollection services) + { + var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("GRS"); + var network = new BTCPayNetwork() + { + CryptoCode = nbxplorerNetwork.CryptoCode, + DisplayName = "Groestlcoin", + NBXplorerNetwork = nbxplorerNetwork, + DefaultRateRules = new[] + { + "GRS_X = GRS_BTC * BTC_X", + "GRS_BTC = bittrex(GRS_BTC)" + }, + CryptoImagePath = "imlegacy/groestlcoin.png", + LightningImagePath = "imlegacy/groestlcoin-lightning.svg", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("17'") : new KeyPath("1'"), + SupportRBF = true, + SupportPayJoin = true, + VaultSupported = true + }.SetDefaultElectrumMapping(ChainName); + var blockExplorerLink = ChainName == ChainName.Mainnet + ? "https://chainz.cryptoid.info/grs/tx.dws?{0}.htm" + : "https://chainz.cryptoid.info/grs-test/tx.dws?{0}.htm"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(nbxplorerNetwork.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(blockExplorerLink)); + } +} + diff --git a/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Litecoin.cs b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Litecoin.cs new file mode 100644 index 000000000..89f111d21 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Litecoin.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; +using NBXplorer; + +namespace BTCPayServer.Plugins.Altcoins; + +public partial class AltcoinsPlugin +{ + public void InitLitecoin(IServiceCollection services) + { + var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LTC"); + var network = new BTCPayNetwork() + { + CryptoCode = nbxplorerNetwork.CryptoCode, + DisplayName = "Litecoin", + NBXplorerNetwork = nbxplorerNetwork, + DefaultRateRules = new[] + { + "LTC_X = LTC_BTC * BTC_X", + "LTC_BTC = coingecko(LTC_BTC)" + }, + CryptoImagePath = "imlegacy/litecoin.svg", + LightningImagePath = "imlegacy/litecoin-lightning.svg", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("2'") : new KeyPath("1'"), + //https://github.com/pooler/electrum-ltc/blob/0d6989a9d2fb2edbea421c116e49d1015c7c5a91/electrum_ltc/constants.py + ElectrumMapping = ChainName == ChainName.Mainnet + ? new Dictionary() + { + {0x0488b21eU, DerivationType.Legacy }, + {0x049d7cb2U, DerivationType.SegwitP2SH }, + {0x04b24746U, DerivationType.Segwit }, + } + : new Dictionary() + { + {0x043587cfU, DerivationType.Legacy }, + {0x044a5262U, DerivationType.SegwitP2SH }, + {0x045f1cf6U, DerivationType.Segwit } + } + }; + var blockExplorerLinks = ChainName == ChainName.Mainnet + ? "https://live.blockcypher.com/ltc/tx/{0}/" + : "http://explorer.litecointools.com/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(nbxplorerNetwork.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(blockExplorerLinks)); + } +} + diff --git a/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Monacoin.cs b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Monacoin.cs new file mode 100644 index 000000000..991834349 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.Monacoin.cs @@ -0,0 +1,36 @@ +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; +using NBXplorer; + +namespace BTCPayServer.Plugins.Altcoins; + +public partial class AltcoinsPlugin +{ + public void InitMonacoin(IServiceCollection services) + { + var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("MONA"); + var network = new BTCPayNetwork() + { + CryptoCode = nbxplorerNetwork.CryptoCode, + DisplayName = "Monacoin", + NBXplorerNetwork = nbxplorerNetwork, + DefaultRateRules = new[] + { + "MONA_X = MONA_BTC * BTC_X", + "MONA_BTC = bittrex(MONA_BTC)" + }, + CryptoImagePath = "imlegacy/monacoin.png", + LightningImagePath = "imlegacy/mona-lightning.svg", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("22'") : new KeyPath("1'") + }.SetDefaultElectrumMapping(ChainName); + + var blockExplorerLink = ChainName == ChainName.Mainnet ? "https://mona.insight.monaco-ex.org/insight/tx/{0}" : "https://testnet-mona.insight.monaco-ex.org/insight/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(nbxplorerNetwork.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(blockExplorerLink)); + } +} + diff --git a/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.cs b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.cs new file mode 100644 index 000000000..8663bc59a --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/AltcoinsPlugin.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BTCPayServer.Abstractions.Models; +using BTCPayServer.Hosting; +using BTCPayServer.Logging; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using NBitcoin; +using NBitcoin.Protocol; +using NBXplorer; + +namespace BTCPayServer.Plugins.Altcoins +{ + public partial class AltcoinsPlugin : BaseBTCPayServerPlugin + { + public override string Identifier => "BTCPayServer.Plugins.Altcoins"; + public override string Name => "Altcoins"; + public override string Description => "Add altcoins support"; + + public ChainName ChainName { get; private set; } + public NBXplorerNetworkProvider NBXplorerNetworkProvider { get; private set; } + public override void Execute(IServiceCollection applicationBuilder) + { + var services = (PluginServiceCollection)applicationBuilder; + var onChain = new Payments.PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike); + + NBXplorerNetworkProvider = services.BootstrapServices.GetRequiredService(); + ChainName = NBXplorerNetworkProvider.NetworkType; + + var selectedChains = services.BootstrapServices.GetRequiredService(); + + if (NBXplorerNetworkProvider.GetFromCryptoCode("LBTC") is { } liquidNBX) + { + if (selectedChains.Contains("LBTC")) + { + // Activating LBTC automatically activate the other liquid assets + InitUSDT(services, selectedChains, liquidNBX); + InitETB(services, selectedChains, liquidNBX); + InitLCAD(services, selectedChains, liquidNBX); + } + else + { + if (selectedChains.Contains("USDT")) + InitUSDT(services, selectedChains, liquidNBX); + if (selectedChains.Contains("ETB")) + InitETB(services, selectedChains, liquidNBX); + if (selectedChains.Contains("LCAD")) + InitLCAD(services, selectedChains, liquidNBX); + } + if (selectedChains.Contains("LBTC")) + InitLiquid(services, liquidNBX); + } + if (selectedChains.Contains("LTC")) + InitLitecoin(services); + if (selectedChains.Contains("DOGE")) + InitDogecoin(services); + if (selectedChains.Contains("BTG")) + InitBGold(services); + if (selectedChains.Contains("MONA")) + InitMonacoin(services); + if (selectedChains.Contains("DASH")) + InitDash(services); + if (selectedChains.Contains("GRS")) + InitGroestlcoin(services); + if (selectedChains.Contains("XMR")) + InitMonero(services); + if (selectedChains.Contains("ZEC")) + InitZcash(services); + } + } +} diff --git a/BTCPayServer/Plugins/Altcoins/Liquid/AltcoinsPlugin.Liquid.cs b/BTCPayServer/Plugins/Altcoins/Liquid/AltcoinsPlugin.Liquid.cs new file mode 100644 index 000000000..6f7c65c06 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/Liquid/AltcoinsPlugin.Liquid.cs @@ -0,0 +1,37 @@ +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; +using NBitcoin.Altcoins; +using NBitcoin.Altcoins.Elements; +using NBXplorer; + +namespace BTCPayServer.Plugins.Altcoins; +public partial class AltcoinsPlugin +{ + public void InitLiquid(IServiceCollection services, NBXplorer.NBXplorerNetwork nbxplorerNetwork) + { + var network = new ElementsBTCPayNetwork() + { + AssetId = ChainName == ChainName.Mainnet ? ElementsParams.PeggedAssetId : ElementsParams.PeggedAssetId, + CryptoCode = "LBTC", + NetworkCryptoCode = "LBTC", + DisplayName = "Liquid Bitcoin", + DefaultRateRules = new[] + { + "LBTC_X = LBTC_BTC * BTC_X", + "LBTC_BTC = 1", + }, + NBXplorerNetwork = nbxplorerNetwork, + CryptoImagePath = "imlegacy/liquid.png", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), + SupportRBF = true + }.SetDefaultElectrumMapping(ChainName); + + var blockExplorerLink = ChainName == ChainName.Mainnet ? "https://liquid.network/tx/{0}" : "https://liquid.network/testnet/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(nbxplorerNetwork.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(blockExplorerLink)); + } +} diff --git a/BTCPayServer/Plugins/Altcoins/Liquid/AltcoinsPlugin.LiquidAssets.cs b/BTCPayServer/Plugins/Altcoins/Liquid/AltcoinsPlugin.LiquidAssets.cs new file mode 100644 index 000000000..3bc9a27a5 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/Liquid/AltcoinsPlugin.LiquidAssets.cs @@ -0,0 +1,97 @@ +using System.Threading; +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using BTCPayServer.Services; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; + +namespace BTCPayServer.Plugins.Altcoins; +public partial class AltcoinsPlugin +{ + private void InitUSDT(IServiceCollection services, SelectedChains selectedChains, NBXplorer.NBXplorerNetwork nbxplorerNetwork) + { + var network = new ElementsBTCPayNetwork() + { + CryptoCode = "USDt", + NetworkCryptoCode = "LBTC", + ShowSyncSummary = false, + DefaultRateRules = new[] + { + "USDT_UST = 1", + "USDT_X = USDT_BTC * BTC_X", + "USDT_BTC = bitfinex(UST_BTC)", + }, + AssetId = new uint256("ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2"), + DisplayName = "Liquid Tether", + NBXplorerNetwork = nbxplorerNetwork, + CryptoImagePath = "imlegacy/liquid-tether.svg", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), + SupportRBF = true, + SupportLightning = false + }.SetDefaultElectrumMapping(ChainName); + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(LiquidBlockExplorer)); + selectedChains.Add("LBTC"); + } + + private void InitETB(IServiceCollection services, SelectedChains selectedChains, NBXplorer.NBXplorerNetwork nbxplorerNetwork) + { + var network = new ElementsBTCPayNetwork() + { + CryptoCode = "ETB", + NetworkCryptoCode = "LBTC", + ShowSyncSummary = false, + DefaultRateRules = new[] + { + + "ETB_X = ETB_BTC * BTC_X", + "ETB_BTC = bitpay(ETB_BTC)" + }, + Divisibility = 2, + AssetId = new uint256("aa775044c32a7df391902b3659f46dfe004ccb2644ce2ddc7dba31e889391caf"), + DisplayName = "Ethiopian Birr", + NBXplorerNetwork = nbxplorerNetwork, + CryptoImagePath = "imlegacy/etb.png", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), + SupportRBF = true, + SupportLightning = false + }.SetDefaultElectrumMapping(ChainName); + + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(LiquidBlockExplorer)); + selectedChains.Add("LBTC"); + } + + string LiquidBlockExplorer => ChainName == ChainName.Mainnet ? "https://liquid.network/tx/{0}" : "https://liquid.network/testnet/tx/{0}"; + private void InitLCAD(IServiceCollection services, SelectedChains selectedChains, NBXplorer.NBXplorerNetwork nbxplorerNetwork) + { + var network = new ElementsBTCPayNetwork() + { + CryptoCode = "LCAD", + NetworkCryptoCode = "LBTC", + ShowSyncSummary = false, + DefaultRateRules = new[] + { + "LCAD_CAD = 1", + "LCAD_X = CAD_BTC * BTC_X", + "LCAD_BTC = bylls(CAD_BTC)", + "CAD_BTC = LCAD_BTC" + }, + AssetId = new uint256("0e99c1a6da379d1f4151fb9df90449d40d0608f6cb33a5bcbfc8c265f42bab0a"), + DisplayName = "Liquid CAD", + NBXplorerNetwork = nbxplorerNetwork, + CryptoImagePath = "imlegacy/lcad.png", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(ChainName), + CoinType = ChainName == ChainName.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"), + SupportRBF = true, + SupportLightning = false + }.SetDefaultElectrumMapping(ChainName); + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike), new DefaultTransactionLinkProvider(LiquidBlockExplorer)); + selectedChains.Add("LBTC"); + } + +} diff --git a/BTCPayServer/Plugins/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs b/BTCPayServer/Plugins/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs new file mode 100644 index 000000000..ce540faba --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BTCPayServer.Common; +using NBitcoin; +using NBXplorer; +using NBXplorer.Models; + +namespace BTCPayServer.Plugins.Altcoins; + +public class ElementsBTCPayNetwork : BTCPayNetwork +{ + public string NetworkCryptoCode { get; set; } + public uint256 AssetId { get; set; } + public override bool ReadonlyWallet { get; set; } = true; + public bool IsNativeAsset => NetworkCryptoCode == CryptoCode; + + public override IEnumerable<(MatchedOutput matchedOutput, OutPoint outPoint)> GetValidOutputs( + NewTransactionEvent evtOutputs) + { + return evtOutputs.Outputs.Where(output => + output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId).Select(output => + { + var outpoint = new OutPoint(evtOutputs.TransactionData.TransactionHash, output.Index); + return (output, outpoint); + }); + } + + public override List FilterValidTransactions(List transactionInformationSet) + { + return transactionInformationSet.FindAll(information => + information.Outputs.Any(output => + output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId) || + information.Inputs.Any(output => + output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId)); + } + + public override PaymentUrlBuilder GenerateBIP21(string cryptoInfoAddress, decimal? cryptoInfoDue) + { + //precision 0: 10 = 0.00000010 + //precision 2: 10 = 0.00001000 + //precision 8: 10 = 10 + var money = cryptoInfoDue / (decimal)Math.Pow(10, 8 - Divisibility); + var builder = base.GenerateBIP21(cryptoInfoAddress, money); + builder.QueryParams.Add("assetid", AssetId.ToString()); + return builder; + } +} diff --git a/BTCPayServer/Plugins/Altcoins/Monero/AltcoinsPlugin.Monero.cs b/BTCPayServer/Plugins/Altcoins/Monero/AltcoinsPlugin.Monero.cs new file mode 100644 index 000000000..548a2eab6 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/Monero/AltcoinsPlugin.Monero.cs @@ -0,0 +1,33 @@ +using BTCPayServer.Hosting; +using BTCPayServer.Payments; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; + +namespace BTCPayServer.Plugins.Altcoins; + +public partial class AltcoinsPlugin +{ + public void InitMonero(IServiceCollection services) + { + var network = new MoneroLikeSpecificBtcPayNetwork() + { + CryptoCode = "XMR", + DisplayName = "Monero", + Divisibility = 12, + DefaultRateRules = new[] + { + "XMR_X = XMR_BTC * BTC_X", + "XMR_BTC = kraken(XMR_BTC)" + }, + CryptoImagePath = "/imlegacy/monero.svg", + UriScheme = "monero" + }; + var blockExplorerLink = ChainName == ChainName.Mainnet + ? "https://www.exploremonero.com/transaction/{0}" + : "https://testnet.xmrchain.net/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new Payments.PaymentMethodId("XMR", PaymentTypes.BTCLike), new SimpleTransactionLinkProvider(blockExplorerLink)); + } +} + diff --git a/BTCPayServer/Plugins/Altcoins/Monero/MoneroLikeSpecificBtcPayNetwork.cs b/BTCPayServer/Plugins/Altcoins/Monero/MoneroLikeSpecificBtcPayNetwork.cs new file mode 100644 index 000000000..9f4fd4530 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/Monero/MoneroLikeSpecificBtcPayNetwork.cs @@ -0,0 +1,8 @@ +namespace BTCPayServer.Plugins.Altcoins; + +public class MoneroLikeSpecificBtcPayNetwork : BTCPayNetworkBase +{ + public int MaxTrackedConfirmation = 10; + public string UriScheme { get; set; } +} + diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/JsonRpcClient.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/JsonRpcClient.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/JsonRpcClient.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/JsonRpcClient.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAccountRequest.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAccountRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAccountRequest.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAccountRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAccountResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAccountResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAccountResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAccountResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAddressRequest.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAddressRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAddressRequest.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAddressRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAddressResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAddressResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/CreateAddressResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/CreateAddressResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetAccountsRequest.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetAccountsRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetAccountsRequest.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetAccountsRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetAccountsResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetAccountsResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetAccountsResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetAccountsResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetFeeEstimateRequest.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetFeeEstimateRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetFeeEstimateRequest.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetFeeEstimateRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetFeeEstimateResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetFeeEstimateResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetFeeEstimateResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetFeeEstimateResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetHeightResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetHeightResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetHeightResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetHeightResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdRequest.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdRequest.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransferByTransactionIdResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransfersRequest.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransfersRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransfersRequest.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransfersRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransfersResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransfersResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/GetTransfersResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/GetTransfersResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/Info.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/Info.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/Info.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/Info.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/MakeUriRequest.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/MakeUriRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/MakeUriRequest.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/MakeUriRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/MakeUriResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/MakeUriResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/MakeUriResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/MakeUriResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/ParseStringConverter.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/ParseStringConverter.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/ParseStringConverter.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/ParseStringConverter.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/Peer.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/Peer.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/Peer.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/Peer.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/SubaddrIndex.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/SubaddrIndex.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/SubaddrIndex.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/SubaddrIndex.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/SubaddressAccount.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/SubaddressAccount.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/SubaddressAccount.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/SubaddressAccount.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/RPC/Models/SyncInfoResponse.cs b/BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/SyncInfoResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/RPC/Models/SyncInfoResponse.cs rename to BTCPayServer/Plugins/Altcoins/Monero/RPC/Models/SyncInfoResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Monero/Utils/MoneroMoney.cs b/BTCPayServer/Plugins/Altcoins/Monero/Utils/MoneroMoney.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Monero/Utils/MoneroMoney.cs rename to BTCPayServer/Plugins/Altcoins/Monero/Utils/MoneroMoney.cs diff --git a/BTCPayServer/Plugins/Altcoins/Zcash/AltcoinsPlugin.Zcash.cs b/BTCPayServer/Plugins/Altcoins/Zcash/AltcoinsPlugin.Zcash.cs new file mode 100644 index 000000000..4bd5216f5 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/Zcash/AltcoinsPlugin.Zcash.cs @@ -0,0 +1,51 @@ +#nullable enable +using BTCPayServer.Services; +using System.Globalization; +using System.Linq; +using NBitcoin; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.DependencyInjection; +using BTCPayServer.Hosting; +using BTCPayServer.Payments; + +namespace BTCPayServer.Plugins.Altcoins; + +public partial class AltcoinsPlugin +{ + // Change this if you want another zcash coin + public void InitZcash(IServiceCollection services) + { + var network = new ZcashLikeSpecificBtcPayNetwork() + { + CryptoCode = "ZEC", + DisplayName = "Zcash", + Divisibility = 8, + DefaultRateRules = new[] + { + "ZEC_X = ZEC_BTC * BTC_X", + "ZEC_BTC = kraken(ZEC_BTC)" + }, + CryptoImagePath = "/imlegacy/zcash.png", + UriScheme = "zcash" + }; + var blockExplorerLink = ChainName == ChainName.Mainnet + ? "https://www.exploreZcash.com/transaction/{0}" + : "https://testnet.xmrchain.net/tx/{0}"; + services.AddBTCPayNetwork(network) + .AddTransactionLinkProvider(new Payments.PaymentMethodId("ZEC", PaymentTypes.BTCLike), new SimpleTransactionLinkProvider(blockExplorerLink)); + } + class SimpleTransactionLinkProvider : DefaultTransactionLinkProvider + { + public SimpleTransactionLinkProvider(string blockExplorerLink) : base(blockExplorerLink) + { + } + + public override string? GetTransactionLink(string paymentId) + { + if (string.IsNullOrEmpty(BlockExplorerLink)) + return null; + return string.Format(CultureInfo.InvariantCulture, BlockExplorerLink, paymentId); + } + } +} + diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/JsonRpcClient.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/JsonRpcClient.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/JsonRpcClient.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/JsonRpcClient.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAccountRequest.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAccountRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAccountRequest.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAccountRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAccountResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAccountResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAccountResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAccountResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAddressRequest.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAddressRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAddressRequest.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAddressRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAddressResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAddressResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/CreateAddressResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/CreateAddressResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetAccountsRequest.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetAccountsRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetAccountsRequest.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetAccountsRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetAccountsResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetAccountsResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetAccountsResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetAccountsResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetFeeEstimateRequest.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetFeeEstimateRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetFeeEstimateRequest.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetFeeEstimateRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetFeeEstimateResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetFeeEstimateResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetFeeEstimateResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetFeeEstimateResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetHeightResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetHeightResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetHeightResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetHeightResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdRequest.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdRequest.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransferByTransactionIdResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransfersRequest.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransfersRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransfersRequest.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransfersRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransfersResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransfersResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/GetTransfersResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/GetTransfersResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/Info.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/Info.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/Info.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/Info.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/MakeUriRequest.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/MakeUriRequest.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/MakeUriRequest.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/MakeUriRequest.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/MakeUriResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/MakeUriResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/MakeUriResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/MakeUriResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/ParseStringConverter.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/ParseStringConverter.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/ParseStringConverter.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/ParseStringConverter.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/Peer.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/Peer.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/Peer.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/Peer.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/SubaddrIndex.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/SubaddrIndex.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/SubaddrIndex.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/SubaddrIndex.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/SubaddressAccount.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/SubaddressAccount.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/SubaddressAccount.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/SubaddressAccount.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/RPC/Models/SyncInfoResponse.cs b/BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/SyncInfoResponse.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/RPC/Models/SyncInfoResponse.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/RPC/Models/SyncInfoResponse.cs diff --git a/BTCPayServer.Common/Altcoins/Zcash/Utils/ZcashMoney.cs b/BTCPayServer/Plugins/Altcoins/Zcash/Utils/ZcashMoney.cs similarity index 100% rename from BTCPayServer.Common/Altcoins/Zcash/Utils/ZcashMoney.cs rename to BTCPayServer/Plugins/Altcoins/Zcash/Utils/ZcashMoney.cs diff --git a/BTCPayServer/Plugins/Altcoins/Zcash/ZcashLikeSpecificBtcPayNetwork.cs b/BTCPayServer/Plugins/Altcoins/Zcash/ZcashLikeSpecificBtcPayNetwork.cs new file mode 100644 index 000000000..98fc75e31 --- /dev/null +++ b/BTCPayServer/Plugins/Altcoins/Zcash/ZcashLikeSpecificBtcPayNetwork.cs @@ -0,0 +1,7 @@ +namespace BTCPayServer.Plugins.Altcoins; + +public class ZcashLikeSpecificBtcPayNetwork : BTCPayNetworkBase +{ + public int MaxTrackedConfirmation = 10; + public string UriScheme { get; set; } +} diff --git a/BTCPayServer/Plugins/Bitcoin/BitcoinPlugin.cs b/BTCPayServer/Plugins/Bitcoin/BitcoinPlugin.cs new file mode 100644 index 000000000..d055b2504 --- /dev/null +++ b/BTCPayServer/Plugins/Bitcoin/BitcoinPlugin.cs @@ -0,0 +1,54 @@ +#nullable enable +using BTCPayServer.Abstractions.Models; +using BTCPayServer.Hosting; +using BTCPayServer.Services; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; +using NBXplorer; + +namespace BTCPayServer.Plugins.Bitcoin +{ + public class BitcoinPlugin : BaseBTCPayServerPlugin + { + public override string Identifier => "BTCPayServer.Plugins.Bitcoin"; + public override string Name => "Bitcoin"; + public override string Description => "Add Bitcoin support"; + + public override void Execute(IServiceCollection applicationBuilder) + { + var services = (PluginServiceCollection)applicationBuilder; + var onChain = new Payments.PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike); + var nbxplorerNetworkProvider = services.BootstrapServices.GetRequiredService(); + var nbxplorerNetwork = nbxplorerNetworkProvider.GetFromCryptoCode("BTC"); + var chainName = nbxplorerNetwork.NBitcoinNetwork.ChainName; + var selectedChains = services.BootstrapServices.GetRequiredService(); + if (!services.BootstrapServices.GetRequiredService().Contains("BTC")) + return; + var blockExplorerLink = chainName == ChainName.Mainnet ? "https://mempool.space/tx/{0}" : + chainName == NBitcoin.Bitcoin.Instance.Signet.ChainName ? "https://mempool.space/signet/tx/{0}" + : "https://mempool.space/testnet/tx/{0}"; + + var defaultTransactionLinkProvider = new DefaultTransactionLinkProvider(blockExplorerLink); + + var network = new BTCPayNetwork() + { + CryptoCode = nbxplorerNetwork.CryptoCode, + DisplayName = "Bitcoin", + NBXplorerNetwork = nbxplorerNetwork, + CryptoImagePath = "imlegacy/bitcoin.svg", + LightningImagePath = "imlegacy/bitcoin-lightning.svg", + DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(chainName), + CoinType = chainName == ChainName.Mainnet ? new KeyPath("0'") : new KeyPath("1'"), + SupportRBF = true, + SupportPayJoin = true, + VaultSupported = true, +#pragma warning disable CS0618 // Type or member is obsolete + BlockExplorerLink = defaultTransactionLinkProvider.BlockExplorerLink +#pragma warning restore CS0618 // Type or member is obsolete + }.SetDefaultElectrumMapping(chainName); + + applicationBuilder.AddBTCPayNetwork(network); + applicationBuilder.AddTransactionLinkProvider(onChain, defaultTransactionLinkProvider); + } + } +} diff --git a/BTCPayServer/Plugins/PluginManager.cs b/BTCPayServer/Plugins/PluginManager.cs index f6f9ce03b..ea32dd72c 100644 --- a/BTCPayServer/Plugins/PluginManager.cs +++ b/BTCPayServer/Plugins/PluginManager.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Text.RegularExpressions; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Configuration; +using BTCPayServer.Logging; using McMaster.NETCore.Plugins; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -18,6 +19,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; +using NBXplorer; namespace BTCPayServer.Plugins { @@ -61,7 +63,7 @@ namespace BTCPayServer.Plugins return false; } public static IMvcBuilder AddPlugins(this IMvcBuilder mvcBuilder, IServiceCollection serviceCollection, - IConfiguration config, ILoggerFactory loggerFactory) + IConfiguration config, ILoggerFactory loggerFactory, ServiceProvider bootstrapServiceProvider) { var logger = loggerFactory.CreateLogger(typeof(PluginManager)); var pluginsFolder = new DataDirectories().Configure(config).PluginDir; @@ -184,7 +186,8 @@ namespace BTCPayServer.Plugins { logger.LogInformation( $"Adding and executing plugin {plugin.Identifier} - {plugin.Version}"); - plugin.Execute(serviceCollection); + var pluginServiceCollection = new PluginServiceCollection(serviceCollection, bootstrapServiceProvider); + plugin.Execute(pluginServiceCollection); serviceCollection.AddSingleton(plugin); } catch (Exception e) diff --git a/BTCPayServer/Plugins/PluginServiceCollection.cs b/BTCPayServer/Plugins/PluginServiceCollection.cs new file mode 100644 index 000000000..d8497ea01 --- /dev/null +++ b/BTCPayServer/Plugins/PluginServiceCollection.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using BTCPayServer.Configuration; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using NBitcoin; +using NBXplorer; + +namespace BTCPayServer.Plugins +{ + public class PluginServiceCollection : IServiceCollection + { + public PluginServiceCollection(IServiceCollection inner, IServiceProvider bootstrapServices) + { + Inner = inner; + BootstrapServices = bootstrapServices; + } + public ServiceDescriptor this[int index] { get => Inner[index]; set => Inner[index] = value; } + + public int Count => Inner.Count; + + public bool IsReadOnly => Inner.IsReadOnly; + + public IServiceCollection Inner { get; } + public IServiceProvider BootstrapServices { get; } + + public void Add(ServiceDescriptor item) + { + Inner.Add(item); + } + + public void Clear() + { + Inner.Clear(); + } + + public bool Contains(ServiceDescriptor item) + { + return Inner.Contains(item); + } + + public void CopyTo(ServiceDescriptor[] array, int arrayIndex) + { + Inner.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + return Inner.GetEnumerator(); + } + + public int IndexOf(ServiceDescriptor item) + { + return Inner.IndexOf(item); + } + + public void Insert(int index, ServiceDescriptor item) + { + Inner.Insert(index, item); + } + + public bool Remove(ServiceDescriptor item) + { + return Inner.Remove(item); + } + + public void RemoveAt(int index) + { + Inner.RemoveAt(index); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return Inner.GetEnumerator(); + } + } +} diff --git a/BTCPayServer/Services/Altcoins/Monero/MoneroLikeExtensions.cs b/BTCPayServer/Services/Altcoins/Monero/MoneroLikeExtensions.cs index 4f6bbbfb6..1e17e1538 100644 --- a/BTCPayServer/Services/Altcoins/Monero/MoneroLikeExtensions.cs +++ b/BTCPayServer/Services/Altcoins/Monero/MoneroLikeExtensions.cs @@ -7,6 +7,7 @@ using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Services; using BTCPayServer.Configuration; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Altcoins.Monero.Configuration; using BTCPayServer.Services.Altcoins.Monero.Payments; using BTCPayServer.Services.Altcoins.Monero.Services; @@ -52,11 +53,7 @@ namespace BTCPayServer.Services.Altcoins.Monero var btcPayNetworkProvider = serviceProvider.GetService(); var result = new MoneroLikeConfiguration(); - var supportedChains = configuration.GetOrDefault("chains", string.Empty) - .Split(',', StringSplitOptions.RemoveEmptyEntries) - .Select(t => t.ToUpperInvariant()); - - var supportedNetworks = btcPayNetworkProvider.Filter(supportedChains.ToArray()).GetAll() + var supportedNetworks = btcPayNetworkProvider.GetAll() .OfType(); foreach (var moneroLikeSpecificBtcPayNetwork in supportedNetworks) diff --git a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentData.cs b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentData.cs index 71478c9fc..01960d8f9 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentData.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentData.cs @@ -1,6 +1,7 @@ #if ALTCOINS using BTCPayServer.Client.Models; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Altcoins.Monero.Utils; using BTCPayServer.Services.Invoices; diff --git a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs index 2e0f0c412..b59b1ef0c 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs @@ -9,6 +9,7 @@ using BTCPayServer.Logging; using BTCPayServer.Models; using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Rating; using BTCPayServer.Services.Altcoins.Monero.RPC.Models; using BTCPayServer.Services.Altcoins.Monero.Services; diff --git a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs index 5be8982be..0990a1a4c 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentType.cs @@ -1,6 +1,7 @@ #if ALTCOINS using System.Globalization; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Invoices; using NBitcoin; using Newtonsoft.Json; @@ -44,11 +45,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments return JsonConvert.DeserializeObject(value.ToString()); } - public override string GetTransactionLink(BTCPayNetworkBase network, string txId) - { - return string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, txId); - } - public override string GetPaymentLink(BTCPayNetworkBase network, InvoiceEntity invoice, IPaymentMethodDetails paymentMethodDetails, decimal cryptoInfoDue, string serverUri) { return paymentMethodDetails.Activated diff --git a/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs b/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs index 4b299769d..0b85806eb 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using BTCPayServer.Events; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Altcoins.Monero.Configuration; using BTCPayServer.Services.Altcoins.Monero.Payments; using BTCPayServer.Services.Altcoins.Monero.RPC; diff --git a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentData.cs b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentData.cs index d049d1855..876a338ac 100644 --- a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentData.cs +++ b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentData.cs @@ -1,6 +1,7 @@ #if ALTCOINS using BTCPayServer.Client.Models; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Altcoins.Zcash.Utils; using BTCPayServer.Services.Invoices; diff --git a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs index 998087924..339aa9d20 100644 --- a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs +++ b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs @@ -9,6 +9,7 @@ using BTCPayServer.Logging; using BTCPayServer.Models; using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Rating; using BTCPayServer.Services.Altcoins.Zcash.RPC.Models; using BTCPayServer.Services.Altcoins.Zcash.Services; diff --git a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashPaymentType.cs b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashPaymentType.cs index 4ad64acfa..e3d089166 100644 --- a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashPaymentType.cs +++ b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashPaymentType.cs @@ -1,6 +1,7 @@ #if ALTCOINS using System.Globalization; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Invoices; using NBitcoin; using Newtonsoft.Json; @@ -44,11 +45,6 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Payments return JsonConvert.DeserializeObject(value.ToString()); } - public override string GetTransactionLink(BTCPayNetworkBase network, string txId) - { - return string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, txId); - } - public override string GetPaymentLink(BTCPayNetworkBase network, InvoiceEntity invoice, IPaymentMethodDetails paymentMethodDetails, decimal cryptoInfoDue, string serverUri) { return paymentMethodDetails.Activated diff --git a/BTCPayServer/Services/Altcoins/Zcash/Services/ZcashListener.cs b/BTCPayServer/Services/Altcoins/Zcash/Services/ZcashListener.cs index 8ce3b9312..d9555a949 100644 --- a/BTCPayServer/Services/Altcoins/Zcash/Services/ZcashListener.cs +++ b/BTCPayServer/Services/Altcoins/Zcash/Services/ZcashListener.cs @@ -8,6 +8,7 @@ using System.Threading.Channels; using System.Threading.Tasks; using BTCPayServer.Events; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Altcoins.Zcash.Configuration; using BTCPayServer.Services.Altcoins.Zcash.Payments; using BTCPayServer.Services.Altcoins.Zcash.RPC; diff --git a/BTCPayServer/Services/Altcoins/Zcash/ZcashLikeExtensions.cs b/BTCPayServer/Services/Altcoins/Zcash/ZcashLikeExtensions.cs index d6ed4d359..b67fa4826 100644 --- a/BTCPayServer/Services/Altcoins/Zcash/ZcashLikeExtensions.cs +++ b/BTCPayServer/Services/Altcoins/Zcash/ZcashLikeExtensions.cs @@ -5,6 +5,7 @@ using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Services; using BTCPayServer.Configuration; using BTCPayServer.Payments; +using BTCPayServer.Plugins.Altcoins; using BTCPayServer.Services.Altcoins.Zcash.Configuration; using BTCPayServer.Services.Altcoins.Zcash.Payments; using BTCPayServer.Services.Altcoins.Zcash.Services; @@ -36,11 +37,7 @@ namespace BTCPayServer.Services.Altcoins.Zcash var btcPayNetworkProvider = serviceProvider.GetService(); var result = new ZcashLikeConfiguration(); - var supportedChains = configuration.GetOrDefault("chains", string.Empty) - .Split(',', StringSplitOptions.RemoveEmptyEntries) - .Select(t => t.ToUpperInvariant()); - - var supportedNetworks = btcPayNetworkProvider.Filter(supportedChains.ToArray()).GetAll() + var supportedNetworks = btcPayNetworkProvider.GetAll() .OfType(); foreach (var ZcashLikeSpecificBtcPayNetwork in supportedNetworks) diff --git a/BTCPayServer/Services/Cheater.cs b/BTCPayServer/Services/Cheater.cs index bfb4ecf11..f90575ba2 100644 --- a/BTCPayServer/Services/Cheater.cs +++ b/BTCPayServer/Services/Cheater.cs @@ -42,8 +42,8 @@ namespace BTCPayServer.Services { var lbtcrpc = GetCashCow(liquid.CryptoCode); await lbtcrpc.SendCommandAsync("rescanblockchain"); - var elements = _prov.NetworkProviders.GetAll().OfType(); - foreach (ElementsBTCPayNetwork element in elements) + var elements = _prov.NetworkProviders.GetAll().OfType(); + foreach (Plugins.Altcoins.ElementsBTCPayNetwork element in elements) { try { diff --git a/BTCPayServer/Services/DefaultTransactionLinkProvider.cs b/BTCPayServer/Services/DefaultTransactionLinkProvider.cs new file mode 100644 index 000000000..d0034689b --- /dev/null +++ b/BTCPayServer/Services/DefaultTransactionLinkProvider.cs @@ -0,0 +1,25 @@ +#nullable enable +using NBitcoin; +using System.Globalization; +using System.Linq; + +namespace BTCPayServer.Services; + +public class DefaultTransactionLinkProvider : TransactionLinkProvider +{ + public DefaultTransactionLinkProvider(string? blockExplorerLinkDefault) + { + BlockExplorerLinkDefault = blockExplorerLinkDefault; + } + + public override string? OverrideBlockExplorerLink { get; set; } + public override string? BlockExplorerLinkDefault { get; } + + public override string? GetTransactionLink(string paymentId) + { + if (string.IsNullOrEmpty(BlockExplorerLink)) + return null; + paymentId = paymentId.Split('-').First(); + return string.Format(CultureInfo.InvariantCulture, BlockExplorerLink, paymentId); + } +} diff --git a/BTCPayServer/Services/Notifications/NotificationManager.cs b/BTCPayServer/Services/Notifications/NotificationManager.cs index 8be83e875..e4ecf4583 100644 --- a/BTCPayServer/Services/Notifications/NotificationManager.cs +++ b/BTCPayServer/Services/Notifications/NotificationManager.cs @@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; -using Org.BouncyCastle.Crypto.Generators; namespace BTCPayServer.Services.Notifications { diff --git a/BTCPayServer/Services/Reporting/OnChainWalletReportProvider.cs b/BTCPayServer/Services/Reporting/OnChainWalletReportProvider.cs index cc4b62476..90cc29ae7 100644 --- a/BTCPayServer/Services/Reporting/OnChainWalletReportProvider.cs +++ b/BTCPayServer/Services/Reporting/OnChainWalletReportProvider.cs @@ -120,7 +120,7 @@ public class OnChainWalletReportProvider : ReportProvider private string? GetAssetId(BTCPayNetwork network) { #if ALTCOINS - if (network is ElementsBTCPayNetwork elNetwork) + if (network is Plugins.Altcoins.ElementsBTCPayNetwork elNetwork) { if (elNetwork.CryptoCode == elNetwork.NetworkCryptoCode) return ""; diff --git a/BTCPayServer/Services/TransactionLinkProvider.cs b/BTCPayServer/Services/TransactionLinkProvider.cs new file mode 100644 index 000000000..330eb4198 --- /dev/null +++ b/BTCPayServer/Services/TransactionLinkProvider.cs @@ -0,0 +1,12 @@ +#nullable enable +using BTCPayServer; + +namespace BTCPayServer.Services; +public abstract class TransactionLinkProvider +{ + public abstract string? OverrideBlockExplorerLink { get; set; } + public abstract string? BlockExplorerLinkDefault { get; } + + public string? BlockExplorerLink => OverrideBlockExplorerLink ?? BlockExplorerLinkDefault; + public abstract string? GetTransactionLink(string paymentId); +} diff --git a/BTCPayServer/Services/TransactionLinkProviders.cs b/BTCPayServer/Services/TransactionLinkProviders.cs new file mode 100644 index 000000000..b46d87172 --- /dev/null +++ b/BTCPayServer/Services/TransactionLinkProviders.cs @@ -0,0 +1,58 @@ +#nullable enable +using System.Collections.Generic; +using System; +using BTCPayServer.Payments; +using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using System.Linq; + +namespace BTCPayServer.Services; + +public class TransactionLinkProviders : Dictionary +{ + public SettingsRepository SettingsRepository { get; } + + public record Entry(PaymentMethodId PaymentMethodId, TransactionLinkProvider Provider); + public TransactionLinkProviders(IEnumerable entries, SettingsRepository settingsRepository) + { + foreach (var e in entries) + { + Add(e.PaymentMethodId, e.Provider); + } + SettingsRepository = settingsRepository; + } + + public async Task RefreshTransactionLinkTemplates() + { + var settings = await SettingsRepository.GetSettingAsync(); + if (settings?.BlockExplorerLinks is {} links) + { + foreach ((var pmi, var prov) in this) + { + var overrideLink = links.SingleOrDefault(item => + item.CryptoCode.Equals(pmi.CryptoCode, StringComparison.InvariantCultureIgnoreCase) || + item.CryptoCode.Equals(pmi.ToString(), StringComparison.InvariantCultureIgnoreCase)); + prov.OverrideBlockExplorerLink = overrideLink?.Link ?? prov.BlockExplorerLinkDefault; + } + } + } + + public string? GetTransactionLink(PaymentMethodId paymentMethodId, string paymentId) + { + ArgumentNullException.ThrowIfNull(paymentMethodId); + ArgumentNullException.ThrowIfNull(paymentId); + TryGetValue(paymentMethodId, out var p); + return p?.GetTransactionLink(paymentId); + } + + public string? GetBlockExplorerLink(PaymentMethodId paymentMethodId) + { + TryGetValue(paymentMethodId, out var p); + return p?.BlockExplorerLink; + } + public string? GetDefaultBlockExplorerLink(PaymentMethodId paymentMethodId) + { + TryGetValue(paymentMethodId, out var p); + return p?.BlockExplorerLinkDefault; + } +} diff --git a/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml b/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml index 0fa5a8d8e..d5992a97a 100644 --- a/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml +++ b/BTCPayServer/Views/Shared/Bitcoin/ViewBitcoinLikePaymentData.cshtml @@ -3,6 +3,7 @@ @using BTCPayServer.Payments.Bitcoin @using BTCPayServer.Services @inject DisplayFormatter DisplayFormatter +@inject TransactionLinkProviders TransactionLinkProviders @model IEnumerable @{ PayjoinInformation payjoinInformation = null; @@ -10,13 +11,14 @@ .Where(entity => entity.GetPaymentMethodId()?.PaymentType == BitcoinPaymentType.Instance) .Select(payment => { + var pmi = payment.GetPaymentMethodId(); var m = new OnchainPaymentViewModel(); var onChainPaymentData = payment.GetCryptoPaymentData() as BitcoinLikePaymentData; if (onChainPaymentData is null) { return null; } - m.Crypto = payment.GetPaymentMethodId().CryptoCode; + m.Crypto = pmi.CryptoCode; m.DepositAddress = onChainPaymentData.GetDestination(); var confirmationCount = onChainPaymentData.ConfirmationCount; @@ -41,7 +43,7 @@ } m.TransactionId = onChainPaymentData.Outpoint.Hash.ToString(); m.ReceivedTime = payment.ReceivedTime; - m.TransactionLink = string.Format(CultureInfo.InvariantCulture, payment.Network.BlockExplorerLink, m.TransactionId); + m.TransactionLink = TransactionLinkProviders.GetTransactionLink(pmi, onChainPaymentData.Outpoint.ToString()); m.Replaced = !payment.Accounted; m.CryptoPaymentData = onChainPaymentData; m.NetworkFee = payment.NetworkFee; diff --git a/BTCPayServer/Views/Shared/Monero/ViewMoneroLikePaymentData.cshtml b/BTCPayServer/Views/Shared/Monero/ViewMoneroLikePaymentData.cshtml index e89bb8c47..ef2575099 100644 --- a/BTCPayServer/Views/Shared/Monero/ViewMoneroLikePaymentData.cshtml +++ b/BTCPayServer/Views/Shared/Monero/ViewMoneroLikePaymentData.cshtml @@ -1,9 +1,11 @@ @using System.Globalization +@using BTCPayServer.Plugins.Altcoins; @using BTCPayServer.Services @using BTCPayServer.Services.Altcoins.Monero.Payments @using BTCPayServer.Services.Altcoins.Monero.UI @inject DisplayFormatter DisplayFormatter @model IEnumerable +@inject TransactionLinkProviders TransactionLinkProviders @{ var payments = Model.Where(entity => entity.GetPaymentMethodId().PaymentType == MoneroPaymentType.Instance).Select(payment => @@ -26,7 +28,7 @@ m.TransactionId = onChainPaymentData.TransactionId; m.ReceivedTime = payment.ReceivedTime; - m.TransactionLink = string.Format(CultureInfo.InvariantCulture, payment.Network.BlockExplorerLink, m.TransactionId); + m.TransactionLink = TransactionLinkProviders.GetTransactionLink(payment.GetPaymentMethodId(), onChainPaymentData.TransactionId); return m; }).ToList(); } diff --git a/BTCPayServer/Views/Shared/Zcash/ViewZcashLikePaymentData.cshtml b/BTCPayServer/Views/Shared/Zcash/ViewZcashLikePaymentData.cshtml index 24f6ec9f1..74518bc94 100644 --- a/BTCPayServer/Views/Shared/Zcash/ViewZcashLikePaymentData.cshtml +++ b/BTCPayServer/Views/Shared/Zcash/ViewZcashLikePaymentData.cshtml @@ -1,10 +1,12 @@ @using System.Globalization +@using BTCPayServer.Plugins.Altcoins; @using BTCPayServer.Components.TruncateCenter @using BTCPayServer.Services @using BTCPayServer.Services.Altcoins.Zcash.Payments @using BTCPayServer.Services.Altcoins.Zcash.UI @inject DisplayFormatter DisplayFormatter @model IEnumerable +@inject TransactionLinkProviders TransactionLinkProviders @{ var payments = Model.Where(entity => entity.GetPaymentMethodId().PaymentType == ZcashPaymentType.Instance).Select(payment => @@ -27,7 +29,7 @@ m.TransactionId = onChainPaymentData.TransactionId; m.ReceivedTime = payment.ReceivedTime; - m.TransactionLink = string.Format(CultureInfo.InvariantCulture, payment.Network.BlockExplorerLink, m.TransactionId); + m.TransactionLink = TransactionLinkProviders.GetTransactionLink(payment.GetPaymentMethodId(), onChainPaymentData.TransactionId); return m; }).ToList(); } diff --git a/BTCPayServer/Views/UIServer/Policies.cshtml b/BTCPayServer/Views/UIServer/Policies.cshtml index cad67a27f..d3667e9fd 100644 --- a/BTCPayServer/Views/UIServer/Policies.cshtml +++ b/BTCPayServer/Views/UIServer/Policies.cshtml @@ -1,11 +1,12 @@ +@using BTCPayServer.Payments; @using BTCPayServer.Services @using BTCPayServer.Services.Mails; @model BTCPayServer.Services.PoliciesSettings @inject SettingsRepository _SettingsRepository -@inject BTCPayNetworkProvider BTCPayNetworkProvider +@inject TransactionLinkProviders TransactionLinkProviders @{ ViewData.SetActivePage(ServerNavPages.Policies); - var networks = BTCPayNetworkProvider.GetAll().ToArray(); + var linkProviders = TransactionLinkProviders.ToArray(); }

@ViewData["Title"]

@@ -185,23 +186,28 @@ }

Block Explorers

- @for (var i = 0; i < networks.Count(); i++) + + @for (var lpi = 0; lpi < linkProviders.Length; lpi++) { - var network = networks.ElementAt(i); - var existingOverride = Model.BlockExplorerLinks?.SingleOrDefault(tuple => tuple.CryptoCode.Equals(network.CryptoCode, StringComparison.InvariantCultureIgnoreCase)); - var linkValue = existingOverride?.Link ?? network.BlockExplorerLinkDefault; - if (Model.BlockExplorerLinks.Count < i + 1) + var pmi = linkProviders[lpi].Key; + var defaultLink = linkProviders[lpi].Value.BlockExplorerLinkDefault; + var existingOverride = Model.BlockExplorerLinks?.SingleOrDefault(tuple => PaymentMethodId.Parse(tuple.CryptoCode) == pmi); + if (existingOverride is null) { - Model.BlockExplorerLinks.Add(new PoliciesSettings.BlockExplorerOverrideItem { CryptoCode = network.CryptoCode, Link = network.BlockExplorerLinkDefault }); + existingOverride = new PoliciesSettings.BlockExplorerOverrideItem { CryptoCode = pmi.ToStringNormalized(), Link = null }; + Model.BlockExplorerLinks ??= new (); + Model.BlockExplorerLinks.Add(existingOverride); } -
+ var i = Model.BlockExplorerLinks.IndexOf(existingOverride); + var linkValue = existingOverride.Link ?? defaultLink; +
- +
- +
}