mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Liquid & Liquid Assets Support (#1118)
This commit is contained in:
committed by
Nicolas Dorier
parent
0485a9178d
commit
4d7480db15
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Bitcoin",
|
DisplayName = "Bitcoin",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/tx/{0}" : "https://blockstream.info/testnet/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/tx/{0}" : "https://blockstream.info/testnet/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "bitcoin",
|
UriScheme = "bitcoin",
|
||||||
CryptoImagePath = "imlegacy/bitcoin.svg",
|
CryptoImagePath = "imlegacy/bitcoin.svg",
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "BGold",
|
DisplayName = "BGold",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://explorer.bitcoingold.org/insight/tx/{0}/" : "https://test-explorer.bitcoingold.org/insight/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://explorer.bitcoingold.org/insight/tx/{0}/" : "https://test-explorer.bitcoingold.org/insight/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "bitcoingold",
|
UriScheme = "bitcoingold",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Bitcoinplus",
|
DisplayName = "Bitcoinplus",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://chainz.cryptoid.info/xbc/tx.dws?{0}" : "https://chainz.cryptoid.info/xbc/tx.dws?{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://chainz.cryptoid.info/xbc/tx.dws?{0}" : "https://chainz.cryptoid.info/xbc/tx.dws?{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "bitcoinplus",
|
UriScheme = "bitcoinplus",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Bitcore",
|
DisplayName = "Bitcore",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://insight.bitcore.cc/tx/{0}" : "https://insight.bitcore.cc/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://insight.bitcore.cc/tx/{0}" : "https://insight.bitcore.cc/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "bitcore",
|
UriScheme = "bitcore",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ namespace BTCPayServer
|
|||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
||||||
? "https://insight.dash.org/insight/tx/{0}"
|
? "https://insight.dash.org/insight/tx/{0}"
|
||||||
: "https://testnet-insight.dashevo.org/insight/tx/{0}",
|
: "https://testnet-insight.dashevo.org/insight/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "dash",
|
UriScheme = "dash",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Dogecoin",
|
DisplayName = "Dogecoin",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://dogechain.info/tx/{0}" : "https://dogechain.info/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://dogechain.info/tx/{0}" : "https://dogechain.info/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "dogecoin",
|
UriScheme = "dogecoin",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Feathercoin",
|
DisplayName = "Feathercoin",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://explorer.feathercoin.com/tx/{0}" : "https://explorer.feathercoin.com/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://explorer.feathercoin.com/tx/{0}" : "https://explorer.feathercoin.com/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "feathercoin",
|
UriScheme = "feathercoin",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ namespace BTCPayServer
|
|||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
||||||
? "https://chainz.cryptoid.info/grs/tx.dws?{0}.htm"
|
? "https://chainz.cryptoid.info/grs/tx.dws?{0}.htm"
|
||||||
: "https://chainz.cryptoid.info/grs-test/tx.dws?{0}.htm",
|
: "https://chainz.cryptoid.info/grs-test/tx.dws?{0}.htm",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "groestlcoin",
|
UriScheme = "groestlcoin",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ namespace BTCPayServer
|
|||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
||||||
? "https://live.blockcypher.com/ltc/tx/{0}/"
|
? "https://live.blockcypher.com/ltc/tx/{0}/"
|
||||||
: "http://explorer.litecointools.com/tx/{0}",
|
: "http://explorer.litecointools.com/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "litecoin",
|
UriScheme = "litecoin",
|
||||||
CryptoImagePath = "imlegacy/litecoin.svg",
|
CryptoImagePath = "imlegacy/litecoin.svg",
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Monacoin",
|
DisplayName = "Monacoin",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://mona.insight.monaco-ex.org/insight/tx/{0}" : "https://testnet-mona.insight.monaco-ex.org/insight/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://mona.insight.monaco-ex.org/insight/tx/{0}" : "https://testnet-mona.insight.monaco-ex.org/insight/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "monacoin",
|
UriScheme = "monacoin",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Polis",
|
DisplayName = "Polis",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://insight.polispay.org/tx/{0}" : "https://insight.polispay.org/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://insight.polispay.org/tx/{0}" : "https://insight.polispay.org/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "polis",
|
UriScheme = "polis",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Ufo",
|
DisplayName = "Ufo",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://chainz.cryptoid.info/ufo/tx.dws?{0}" : "https://chainz.cryptoid.info/ufo/tx.dws?{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://chainz.cryptoid.info/ufo/tx.dws?{0}" : "https://chainz.cryptoid.info/ufo/tx.dws?{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "ufo",
|
UriScheme = "ufo",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace BTCPayServer
|
|||||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||||
DisplayName = "Viacoin",
|
DisplayName = "Viacoin",
|
||||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://explorer.viacoin.org/tx/{0}" : "https://explorer.viacoin.org/tx/{0}",
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://explorer.viacoin.org/tx/{0}" : "https://explorer.viacoin.org/tx/{0}",
|
||||||
NBitcoinNetwork = nbxplorerNetwork.NBitcoinNetwork,
|
|
||||||
NBXplorerNetwork = nbxplorerNetwork,
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
UriScheme = "viacoin",
|
UriScheme = "viacoin",
|
||||||
DefaultRateRules = new[]
|
DefaultRateRules = new[]
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ namespace BTCPayServer
|
|||||||
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(networkType);
|
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(networkType);
|
||||||
NetworkType = networkType;
|
NetworkType = networkType;
|
||||||
InitBitcoin();
|
InitBitcoin();
|
||||||
|
InitLiquid();
|
||||||
|
InitLiquidAssets();
|
||||||
InitLitecoin();
|
InitLitecoin();
|
||||||
InitBitcore();
|
InitBitcore();
|
||||||
InitDogecoin();
|
InitDogecoin();
|
||||||
@@ -93,6 +95,12 @@ namespace BTCPayServer
|
|||||||
[Obsolete("To use only for legacy stuff")]
|
[Obsolete("To use only for legacy stuff")]
|
||||||
public BTCPayNetwork BTC => GetNetwork<BTCPayNetwork>("BTC");
|
public BTCPayNetwork BTC => GetNetwork<BTCPayNetwork>("BTC");
|
||||||
|
|
||||||
|
public void Add(BTCPayNetwork network)
|
||||||
|
{
|
||||||
|
if (network.NBitcoinNetwork == null)
|
||||||
|
return;
|
||||||
|
Add(network as BTCPayNetworkBase);
|
||||||
|
}
|
||||||
public void Add(BTCPayNetworkBase network)
|
public void Add(BTCPayNetworkBase network)
|
||||||
{
|
{
|
||||||
_Networks.Add(network.CryptoCode.ToUpperInvariant(), network);
|
_Networks.Add(network.CryptoCode.ToUpperInvariant(), network);
|
||||||
@@ -109,7 +117,7 @@ namespace BTCPayServer
|
|||||||
}
|
}
|
||||||
public BTCPayNetworkBase GetNetwork(string cryptoCode)
|
public BTCPayNetworkBase GetNetwork(string cryptoCode)
|
||||||
{
|
{
|
||||||
return GetNetwork<BTCPayNetworkBase>(cryptoCode);
|
return GetNetwork<BTCPayNetworkBase>(cryptoCode.ToUpperInvariant());
|
||||||
}
|
}
|
||||||
public T GetNetwork<T>(string cryptoCode) where T: BTCPayNetworkBase
|
public T GetNetwork<T>(string cryptoCode) where T: BTCPayNetworkBase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
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 == NetworkType.Mainnet ? ElementsParams<Liquid>.PeggedAssetId: ElementsParams<Liquid.LiquidRegtest>.PeggedAssetId,
|
||||||
|
CryptoCode = "LBTC",
|
||||||
|
NetworkCryptoCode = "LBTC",
|
||||||
|
DisplayName = "Liquid Bitcoin",
|
||||||
|
DefaultRateRules = new[]
|
||||||
|
{
|
||||||
|
"LBTC_X = LBTC_BTC * BTC_X",
|
||||||
|
"LBTC_BTC = 1",
|
||||||
|
},
|
||||||
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/liquid/tx/{0}" : "https://blockstream.info/testnet/liquid/tx/{0}",
|
||||||
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
|
UriScheme = "liquidnetwork",
|
||||||
|
CryptoImagePath = "imlegacy/liquid.svg",
|
||||||
|
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||||
|
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
|
||||||
|
SupportRBF = true,
|
||||||
|
//https://github.com/spesmilo/electrum/blob/11733d6bc271646a00b69ff07657119598874da4/electrum/constants.py
|
||||||
|
ElectrumMapping = NetworkType == NetworkType.Mainnet
|
||||||
|
? new Dictionary<uint, DerivationType>()
|
||||||
|
{
|
||||||
|
{0x0488b21eU, DerivationType.Legacy }, // xpub
|
||||||
|
{0x049d7cb2U, DerivationType.SegwitP2SH }, // ypub
|
||||||
|
{0x4b24746U, DerivationType.Segwit }, //zpub
|
||||||
|
}
|
||||||
|
: new Dictionary<uint, DerivationType>()
|
||||||
|
{
|
||||||
|
{0x043587cfU, DerivationType.Legacy},
|
||||||
|
{0x044a5262U, DerivationType.SegwitP2SH},
|
||||||
|
{0x045f1cf6U, DerivationType.Segwit}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NBitcoin;
|
||||||
|
using NBXplorer;
|
||||||
|
|
||||||
|
namespace BTCPayServer
|
||||||
|
{
|
||||||
|
public partial class BTCPayNetworkProvider
|
||||||
|
{
|
||||||
|
public void InitLiquidAssets()
|
||||||
|
{
|
||||||
|
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LBTC");
|
||||||
|
Add(new ElementsBTCPayNetwork()
|
||||||
|
{
|
||||||
|
CryptoCode = "USDt",
|
||||||
|
NetworkCryptoCode = "LBTC",
|
||||||
|
DefaultRateRules = new[]
|
||||||
|
{
|
||||||
|
"USDT_UST = 1",
|
||||||
|
"USDT_X = USDT_BTC * BTC_X",
|
||||||
|
"USDT_BTC = bitfinex(UST_BTC)",
|
||||||
|
},
|
||||||
|
AssetId = new uint256("ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2"),
|
||||||
|
DisplayName = "Tether USD",
|
||||||
|
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/liquid/tx/{0}" : "https://blockstream.info/testnet/liquid/tx/{0}",
|
||||||
|
NBXplorerNetwork = nbxplorerNetwork,
|
||||||
|
UriScheme = "liquidnetwork",
|
||||||
|
CryptoImagePath = "imlegacy/liquid-tether.svg",
|
||||||
|
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||||
|
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
|
||||||
|
SupportRBF = true,
|
||||||
|
//https://github.com/spesmilo/electrum/blob/11733d6bc271646a00b69ff07657119598874da4/electrum/constants.py
|
||||||
|
ElectrumMapping = NetworkType == NetworkType.Mainnet
|
||||||
|
? new Dictionary<uint, DerivationType>()
|
||||||
|
{
|
||||||
|
{0x0488b21eU, DerivationType.Legacy }, // xpub
|
||||||
|
{0x049d7cb2U, DerivationType.SegwitP2SH }, // ypub
|
||||||
|
{0x4b24746U, DerivationType.Segwit }, //zpub
|
||||||
|
}
|
||||||
|
: new Dictionary<uint, DerivationType>()
|
||||||
|
{
|
||||||
|
{0x043587cfU, DerivationType.Legacy},
|
||||||
|
{0x044a5262U, DerivationType.SegwitP2SH},
|
||||||
|
{0x045f1cf6U, DerivationType.Segwit}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
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 WalletSupported { get; set; } = false;
|
||||||
|
public int Divisibility { get; set; } = 8;
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
|
using NBXplorer.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace BTCPayServer
|
namespace BTCPayServer
|
||||||
@@ -46,7 +47,7 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
public class BTCPayNetwork:BTCPayNetworkBase
|
public class BTCPayNetwork:BTCPayNetworkBase
|
||||||
{
|
{
|
||||||
public Network NBitcoinNetwork { get; set; }
|
public Network NBitcoinNetwork { get { return NBXplorerNetwork?.NBitcoinNetwork; } }
|
||||||
public NBXplorer.NBXplorerNetwork NBXplorerNetwork { get; set; }
|
public NBXplorer.NBXplorerNetwork NBXplorerNetwork { get; set; }
|
||||||
public bool SupportRBF { get; internal set; }
|
public bool SupportRBF { get; internal set; }
|
||||||
public string LightningImagePath { get; set; }
|
public string LightningImagePath { get; set; }
|
||||||
@@ -55,6 +56,8 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
public Dictionary<uint, DerivationType> ElectrumMapping = new Dictionary<uint, DerivationType>();
|
public Dictionary<uint, DerivationType> ElectrumMapping = new Dictionary<uint, DerivationType>();
|
||||||
|
|
||||||
|
public virtual bool WalletSupported { get; set; } = true;
|
||||||
|
|
||||||
public int MaxTrackedConfirmation { get; internal set; } = 6;
|
public int MaxTrackedConfirmation { get; internal set; } = 6;
|
||||||
public string UriScheme { get; internal set; }
|
public string UriScheme { get; internal set; }
|
||||||
public KeyPath GetRootKeyPath(DerivationType type)
|
public KeyPath GetRootKeyPath(DerivationType type)
|
||||||
@@ -100,6 +103,14 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
return NBXplorerNetwork.Serializer.ToString(obj);
|
return NBXplorerNetwork.Serializer.ToString(obj);
|
||||||
}
|
}
|
||||||
|
public virtual IEnumerable<(MatchedOutput matchedOutput, OutPoint outPoint)> GetValidOutputs(NewTransactionEvent evtOutputs)
|
||||||
|
{
|
||||||
|
return evtOutputs.Outputs.Select(output =>
|
||||||
|
{
|
||||||
|
var outpoint = new OutPoint(evtOutputs.TransactionData.TransactionHash, output.Index);
|
||||||
|
return (output, outpoint);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class BTCPayNetworkBase
|
public abstract class BTCPayNetworkBase
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uri LTCNBXplorerUri { get; set; }
|
public Uri LTCNBXplorerUri { get; set; }
|
||||||
|
public Uri LBTCNBXplorerUri { get; set; }
|
||||||
|
|
||||||
public Uri ServerUri
|
public Uri ServerUri
|
||||||
{
|
{
|
||||||
@@ -93,6 +94,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
public bool MockRates { get; set; } = true;
|
public bool MockRates { get; set; } = true;
|
||||||
|
|
||||||
|
public List<string> Chains { get; set; } = new List<string>(){"BTC", "LTC"};
|
||||||
public async Task StartAsync()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(_Directory))
|
if (!Directory.Exists(_Directory))
|
||||||
@@ -109,20 +111,33 @@ namespace BTCPayServer.Tests
|
|||||||
config.AppendLine($"bind=0.0.0.0");
|
config.AppendLine($"bind=0.0.0.0");
|
||||||
}
|
}
|
||||||
config.AppendLine($"port={Port}");
|
config.AppendLine($"port={Port}");
|
||||||
config.AppendLine($"chains=btc,ltc");
|
config.AppendLine($"chains={string.Join(',', Chains)}");
|
||||||
|
if (Chains.Contains("BTC", StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
config.AppendLine($"btc.explorer.url={NBXplorerUri.AbsoluteUri}");
|
||||||
|
config.AppendLine($"btc.explorer.cookiefile=0");
|
||||||
|
config.AppendLine($"btc.lightning={IntegratedLightning.AbsoluteUri}");
|
||||||
|
var localLndBackupFile = Path.Combine(_Directory, "walletunlock.json");
|
||||||
|
File.Copy(TestUtils.GetTestDataFullPath("LndSeedBackup/walletunlock.json"), localLndBackupFile, true);
|
||||||
|
config.AppendLine($"btc.external.lndseedbackup={localLndBackupFile}");
|
||||||
|
}
|
||||||
|
|
||||||
config.AppendLine($"btc.explorer.url={NBXplorerUri.AbsoluteUri}");
|
if (Chains.Contains("LTC", StringComparer.OrdinalIgnoreCase))
|
||||||
config.AppendLine($"btc.explorer.cookiefile=0");
|
{
|
||||||
|
config.AppendLine($"ltc.explorer.url={LTCNBXplorerUri.AbsoluteUri}");
|
||||||
|
config.AppendLine($"ltc.explorer.cookiefile=0");
|
||||||
|
}
|
||||||
|
if (Chains.Contains("LBTC", StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
config.AppendLine($"lbtc.explorer.url={LBTCNBXplorerUri.AbsoluteUri}");
|
||||||
|
config.AppendLine($"lbtc.explorer.cookiefile=0");
|
||||||
|
}
|
||||||
config.AppendLine("allow-admin-registration=1");
|
config.AppendLine("allow-admin-registration=1");
|
||||||
config.AppendLine($"ltc.explorer.url={LTCNBXplorerUri.AbsoluteUri}");
|
|
||||||
config.AppendLine($"ltc.explorer.cookiefile=0");
|
|
||||||
config.AppendLine($"btc.lightning={IntegratedLightning.AbsoluteUri}");
|
|
||||||
config.AppendLine($"torrcfile={TestUtils.GetTestDataFullPath("Tor/torrc")}");
|
config.AppendLine($"torrcfile={TestUtils.GetTestDataFullPath("Tor/torrc")}");
|
||||||
config.AppendLine($"debuglog=debug.log");
|
config.AppendLine($"debuglog=debug.log");
|
||||||
|
|
||||||
var localLndBackupFile = Path.Combine(_Directory, "walletunlock.json");
|
|
||||||
File.Copy(TestUtils.GetTestDataFullPath("LndSeedBackup/walletunlock.json"), localLndBackupFile, true);
|
|
||||||
config.AppendLine($"btc.external.lndseedbackup={localLndBackupFile}");
|
|
||||||
if (!string.IsNullOrEmpty(SSHPassword) && string.IsNullOrEmpty(SSHKeyFile))
|
if (!string.IsNullOrEmpty(SSHPassword) && string.IsNullOrEmpty(SSHKeyFile))
|
||||||
config.AppendLine($"sshpassword={SSHPassword}");
|
config.AppendLine($"sshpassword={SSHPassword}");
|
||||||
if (!string.IsNullOrEmpty(SSHKeyFile))
|
if (!string.IsNullOrEmpty(SSHKeyFile))
|
||||||
@@ -231,6 +246,16 @@ namespace BTCPayServer.Tests
|
|||||||
BidAsk = new BidAsk(0.004m)
|
BidAsk = new BidAsk(0.004m)
|
||||||
});
|
});
|
||||||
rateProvider.Providers.Add("bittrex", bittrex);
|
rateProvider.Providers.Add("bittrex", bittrex);
|
||||||
|
|
||||||
|
|
||||||
|
var bitfinex = new MockRateProvider();
|
||||||
|
bitfinex.ExchangeRates.Add(new Rating.ExchangeRate()
|
||||||
|
{
|
||||||
|
Exchange = "bitfinex",
|
||||||
|
CurrencyPair = CurrencyPair.Parse("UST_BTC"),
|
||||||
|
BidAsk = new BidAsk(0.000136m)
|
||||||
|
});
|
||||||
|
rateProvider.Providers.Add("bitfinex", bitfinex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
124
BTCPayServer.Tests/ElementsTests.cs
Normal file
124
BTCPayServer.Tests/ElementsTests.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Configuration;
|
||||||
|
using BTCPayServer.Controllers;
|
||||||
|
using BTCPayServer.Models.WalletViewModels;
|
||||||
|
using BTCPayServer.Services.Wallets;
|
||||||
|
using BTCPayServer.Tests.Logging;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Configuration.Memory;
|
||||||
|
using NBitcoin;
|
||||||
|
using NBitcoin.RPC;
|
||||||
|
using NBitpayClient;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Tests
|
||||||
|
{
|
||||||
|
public class ElementsTests
|
||||||
|
{
|
||||||
|
|
||||||
|
public const int TestTimeout = 60_000;
|
||||||
|
public ElementsTests(ITestOutputHelper helper)
|
||||||
|
{
|
||||||
|
Logs.Tester = new XUnitLog(helper) { Name = "Tests" };
|
||||||
|
Logs.LogProvider = new XUnitLogProvider(helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task OnlyShowSupportedWallets()
|
||||||
|
{
|
||||||
|
using (var tester = ServerTester.Create())
|
||||||
|
{
|
||||||
|
tester.PayTester.Chains.Add("LBTC");
|
||||||
|
await tester.StartAsync();
|
||||||
|
await tester.EnsureChannelsSetup();
|
||||||
|
var user = tester.NewAccount();
|
||||||
|
user.GrantAccess();
|
||||||
|
user.RegisterDerivationScheme("LBTC");
|
||||||
|
user.RegisterDerivationScheme("BTC");
|
||||||
|
user.RegisterDerivationScheme("USDT");
|
||||||
|
|
||||||
|
Assert.Single(Assert.IsType<ListWalletsViewModel>(Assert.IsType<ViewResult>(await user.GetController<WalletsController>().ListWallets()).Model).Wallets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Fast", "Fast")]
|
||||||
|
public void LoadSubChainsAlways()
|
||||||
|
{
|
||||||
|
var options = new BTCPayServerOptions();
|
||||||
|
options.LoadArgs(new ConfigurationRoot(new List<IConfigurationProvider>()
|
||||||
|
{
|
||||||
|
new MemoryConfigurationProvider(new MemoryConfigurationSource()
|
||||||
|
{
|
||||||
|
InitialData = new[]
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("chains", "usdt"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
Assert.NotNull(options.NetworkProvider.GetNetwork("LBTC"));
|
||||||
|
Assert.NotNull(options.NetworkProvider.GetNetwork("USDT"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ElementsAssetsAreHandledCorrectly()
|
||||||
|
{
|
||||||
|
using (var tester = ServerTester.Create())
|
||||||
|
{
|
||||||
|
tester.PayTester.Chains.Add("LBTC");
|
||||||
|
await tester.StartAsync();
|
||||||
|
var user = tester.NewAccount();
|
||||||
|
user.GrantAccess();
|
||||||
|
user.RegisterDerivationScheme("LBTC");
|
||||||
|
user.RegisterDerivationScheme("USDT");
|
||||||
|
|
||||||
|
//no tether on our regtest, lets create it and set it
|
||||||
|
var tether = tester.NetworkProvider.GetNetwork<ElementsBTCPayNetwork>("USDT");
|
||||||
|
var lbtc = tester.NetworkProvider.GetNetwork<ElementsBTCPayNetwork>("LBTC");
|
||||||
|
var issueAssetResult = await tester.LBTCExplorerNode.SendCommandAsync("issueasset", 100000, 0);
|
||||||
|
tether.AssetId = uint256.Parse(issueAssetResult.Result["asset"].ToString());
|
||||||
|
((ElementsBTCPayNetwork)tester.PayTester.GetService<BTCPayWalletProvider>().GetWallet("USDT").Network)
|
||||||
|
.AssetId = tether.AssetId;
|
||||||
|
Logs.Tester.LogInformation($"Asset is {tether.AssetId}");
|
||||||
|
Assert.Equal(tether.AssetId, tester.NetworkProvider.GetNetwork<ElementsBTCPayNetwork>("USDT").AssetId);
|
||||||
|
Assert.Equal(tether.AssetId, ((ElementsBTCPayNetwork)tester.PayTester.GetService<BTCPayWalletProvider>().GetWallet("USDT").Network).AssetId);
|
||||||
|
//test: register 2 assets on the same elements network and make sure paying an invoice on one does not affect the other in any way
|
||||||
|
var invoice = await user.BitPay.CreateInvoiceAsync(new Invoice(0.1m, "BTC"));
|
||||||
|
Assert.Equal(2, invoice.SupportedTransactionCurrencies.Count);
|
||||||
|
var ci = invoice.CryptoInfo.Single(info => info.CryptoCode.Equals("LBTC"));
|
||||||
|
//1 lbtc = 1 btc
|
||||||
|
Assert.Equal(1, ci.Rate);
|
||||||
|
var star = await tester.LBTCExplorerNode.SendCommandAsync("sendtoaddress", ci.Address,ci.Due, "", "", false, true,
|
||||||
|
1, "UNSET", lbtc.AssetId);
|
||||||
|
|
||||||
|
TestUtils.Eventually(() =>
|
||||||
|
{
|
||||||
|
var localInvoice = user.BitPay.GetInvoice(invoice.Id, Facade.Merchant);
|
||||||
|
Assert.Equal("paid", localInvoice.Status);
|
||||||
|
Assert.Single(localInvoice.CryptoInfo.Single(info => info.CryptoCode.Equals("LBTC")).Payments);
|
||||||
|
});
|
||||||
|
|
||||||
|
invoice = await user.BitPay.CreateInvoiceAsync(new Invoice(0.1m, "BTC"));
|
||||||
|
|
||||||
|
ci = invoice.CryptoInfo.Single(info => info.CryptoCode.Equals("USDT"));
|
||||||
|
Assert.Equal(2, invoice.SupportedTransactionCurrencies.Count);
|
||||||
|
star = await tester.LBTCExplorerNode.SendCommandAsync("sendtoaddress", ci.Address, ci.Due, "", "", false, true,
|
||||||
|
1, "UNSET", tether.AssetId);
|
||||||
|
|
||||||
|
TestUtils.Eventually(() =>
|
||||||
|
{
|
||||||
|
var localInvoice = user.BitPay.GetInvoice(invoice.Id, Facade.Merchant);
|
||||||
|
Assert.Equal("paid", localInvoice.Status);
|
||||||
|
Assert.Single(localInvoice.CryptoInfo.Single(info => info.CryptoCode.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)).Payments);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,9 +47,11 @@ namespace BTCPayServer.Tests
|
|||||||
ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork);
|
ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork);
|
||||||
ExplorerNode.ScanRPCCapabilities();
|
ExplorerNode.ScanRPCCapabilities();
|
||||||
LTCExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_LTCRPCCONNECTION", "server=http://127.0.0.1:43783;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork<BTCPayNetwork>("LTC").NBitcoinNetwork);
|
LTCExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_LTCRPCCONNECTION", "server=http://127.0.0.1:43783;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork<BTCPayNetwork>("LTC").NBitcoinNetwork);
|
||||||
|
LBTCExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_LBTCRPCCONNECTION", "server=http://127.0.0.1:19332;liquid:liquid")), NetworkProvider.GetNetwork<BTCPayNetwork>("LBTC").NBitcoinNetwork);
|
||||||
|
|
||||||
ExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_BTCNBXPLORERURL", "http://127.0.0.1:32838/")));
|
ExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_BTCNBXPLORERURL", "http://127.0.0.1:32838/")));
|
||||||
LTCExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork<BTCPayNetwork>("LTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_LTCNBXPLORERURL", "http://127.0.0.1:32838/")));
|
LTCExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork<BTCPayNetwork>("LTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_LTCNBXPLORERURL", "http://127.0.0.1:32838/")));
|
||||||
|
LBTCExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork<BTCPayNetwork>("LBTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_LBTCNBXPLORERURL", "http://127.0.0.1:32838/")));
|
||||||
|
|
||||||
var btc = NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork;
|
var btc = NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork;
|
||||||
CustomerLightningD = LightningClientFactory.CreateClient(GetEnvironment("TEST_CUSTOMERLIGHTNINGD", "type=clightning;server=tcp://127.0.0.1:30992/"), btc);
|
CustomerLightningD = LightningClientFactory.CreateClient(GetEnvironment("TEST_CUSTOMERLIGHTNINGD", "type=clightning;server=tcp://127.0.0.1:30992/"), btc);
|
||||||
@@ -61,8 +63,10 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
PayTester = new BTCPayServerTester(Path.Combine(_Directory, "pay"))
|
PayTester = new BTCPayServerTester(Path.Combine(_Directory, "pay"))
|
||||||
{
|
{
|
||||||
|
|
||||||
NBXplorerUri = ExplorerClient.Address,
|
NBXplorerUri = ExplorerClient.Address,
|
||||||
LTCNBXplorerUri = LTCExplorerClient.Address,
|
LTCNBXplorerUri = LTCExplorerClient.Address,
|
||||||
|
LBTCNBXplorerUri = LTCExplorerClient.Address,
|
||||||
TestDatabase = Enum.Parse<TestDatabases>(GetEnvironment("TESTS_DB", TestDatabases.Postgres.ToString()), true),
|
TestDatabase = Enum.Parse<TestDatabases>(GetEnvironment("TESTS_DB", TestDatabases.Postgres.ToString()), true),
|
||||||
Postgres = GetEnvironment("TESTS_POSTGRES", "User ID=postgres;Host=127.0.0.1;Port=39372;Database=btcpayserver"),
|
Postgres = GetEnvironment("TESTS_POSTGRES", "User ID=postgres;Host=127.0.0.1;Port=39372;Database=btcpayserver"),
|
||||||
MySQL = GetEnvironment("TESTS_MYSQL", "User ID=root;Host=127.0.0.1;Port=33036;Database=btcpayserver"),
|
MySQL = GetEnvironment("TESTS_MYSQL", "User ID=root;Host=127.0.0.1;Port=33036;Database=btcpayserver"),
|
||||||
@@ -77,6 +81,7 @@ namespace BTCPayServer.Tests
|
|||||||
PayTester.SSHConnection = GetEnvironment("TESTS_SSHCONNECTION", "root@127.0.0.1:21622");
|
PayTester.SSHConnection = GetEnvironment("TESTS_SSHCONNECTION", "root@127.0.0.1:21622");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool Dockerized
|
public bool Dockerized
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
@@ -148,12 +153,15 @@ namespace BTCPayServer.Tests
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RPCClient LBTCExplorerNode { get; set; }
|
||||||
|
|
||||||
public ExplorerClient ExplorerClient
|
public ExplorerClient ExplorerClient
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
public ExplorerClient LTCExplorerClient { get; set; }
|
public ExplorerClient LTCExplorerClient { get; set; }
|
||||||
|
public ExplorerClient LBTCExplorerClient { get; set; }
|
||||||
|
|
||||||
HttpClient _Http = new HttpClient();
|
HttpClient _Http = new HttpClient();
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace BTCPayServer.Tests
|
|||||||
SupportedNetwork = parent.NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
SupportedNetwork = parent.NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
||||||
var store = parent.PayTester.GetController<StoresController>(UserId, StoreId);
|
var store = parent.PayTester.GetController<StoresController>(UserId, StoreId);
|
||||||
ExtKey = new ExtKey().GetWif(SupportedNetwork.NBitcoinNetwork);
|
ExtKey = new ExtKey().GetWif(SupportedNetwork.NBitcoinNetwork);
|
||||||
DerivationScheme = new DerivationStrategyFactory(SupportedNetwork.NBitcoinNetwork).Parse(ExtKey.Neuter().ToString() + (segwit ? "" : "-[legacy]"));
|
DerivationScheme = SupportedNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(ExtKey.Neuter().ToString() + (segwit ? "" : "-[legacy]"));
|
||||||
await store.AddDerivationScheme(StoreId, new DerivationSchemeViewModel()
|
await store.AddDerivationScheme(StoreId, new DerivationSchemeViewModel()
|
||||||
{
|
{
|
||||||
DerivationScheme = DerivationScheme.ToString(),
|
DerivationScheme = DerivationScheme.ToString(),
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ namespace BTCPayServer.Tests
|
|||||||
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
||||||
});
|
});
|
||||||
InvoiceEntity invoiceEntity = new InvoiceEntity();
|
InvoiceEntity invoiceEntity = new InvoiceEntity();
|
||||||
|
invoiceEntity.Networks = networkProvider;
|
||||||
invoiceEntity.Payments = new System.Collections.Generic.List<PaymentEntity>();
|
invoiceEntity.Payments = new System.Collections.Generic.List<PaymentEntity>();
|
||||||
invoiceEntity.ProductInformation = new ProductInformation() {Price = 100};
|
invoiceEntity.ProductInformation = new ProductInformation() {Price = 100};
|
||||||
PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary();
|
PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary();
|
||||||
@@ -172,12 +173,15 @@ namespace BTCPayServer.Tests
|
|||||||
invoiceEntity.Payments.Add(
|
invoiceEntity.Payments.Add(
|
||||||
new PaymentEntity()
|
new PaymentEntity()
|
||||||
{
|
{
|
||||||
|
|
||||||
Accounted = true,
|
Accounted = true,
|
||||||
CryptoCode = "BTC",
|
CryptoCode = "BTC",
|
||||||
NetworkFee = 0.00000100m
|
NetworkFee = 0.00000100m,
|
||||||
|
Network = networkProvider.GetNetwork("BTC"),
|
||||||
}
|
}
|
||||||
.SetCryptoPaymentData(new BitcoinLikePaymentData()
|
.SetCryptoPaymentData(new BitcoinLikePaymentData()
|
||||||
{
|
{
|
||||||
|
Network = networkProvider.GetNetwork("BTC"),
|
||||||
Output = new TxOut() {Value = Money.Coins(0.00151263m)}
|
Output = new TxOut() {Value = Money.Coins(0.00151263m)}
|
||||||
}));
|
}));
|
||||||
accounting = btc.Calculate();
|
accounting = btc.Calculate();
|
||||||
@@ -186,10 +190,12 @@ namespace BTCPayServer.Tests
|
|||||||
{
|
{
|
||||||
Accounted = true,
|
Accounted = true,
|
||||||
CryptoCode = "BTC",
|
CryptoCode = "BTC",
|
||||||
NetworkFee = 0.00000100m
|
NetworkFee = 0.00000100m,
|
||||||
|
Network = networkProvider.GetNetwork("BTC")
|
||||||
}
|
}
|
||||||
.SetCryptoPaymentData(new BitcoinLikePaymentData()
|
.SetCryptoPaymentData(new BitcoinLikePaymentData()
|
||||||
{
|
{
|
||||||
|
Network = networkProvider.GetNetwork("BTC"),
|
||||||
Output = new TxOut() {Value = accounting.Due}
|
Output = new TxOut() {Value = accounting.Due}
|
||||||
}));
|
}));
|
||||||
accounting = btc.Calculate();
|
accounting = btc.Calculate();
|
||||||
@@ -258,6 +264,7 @@ namespace BTCPayServer.Tests
|
|||||||
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
||||||
});
|
});
|
||||||
var entity = new InvoiceEntity();
|
var entity = new InvoiceEntity();
|
||||||
|
entity.Networks = networkProvider;
|
||||||
#pragma warning disable CS0618
|
#pragma warning disable CS0618
|
||||||
entity.Payments = new System.Collections.Generic.List<PaymentEntity>();
|
entity.Payments = new System.Collections.Generic.List<PaymentEntity>();
|
||||||
entity.SetPaymentMethod(new PaymentMethod()
|
entity.SetPaymentMethod(new PaymentMethod()
|
||||||
@@ -317,6 +324,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(Money.Coins(1.3m), accounting.TotalDue);
|
Assert.Equal(Money.Coins(1.3m), accounting.TotalDue);
|
||||||
|
|
||||||
entity = new InvoiceEntity();
|
entity = new InvoiceEntity();
|
||||||
|
entity.Networks = networkProvider;
|
||||||
entity.ProductInformation = new ProductInformation() {Price = 5000};
|
entity.ProductInformation = new ProductInformation() {Price = 5000};
|
||||||
PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary();
|
PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary();
|
||||||
paymentMethods.Add(
|
paymentMethods.Add(
|
||||||
@@ -445,6 +453,7 @@ namespace BTCPayServer.Tests
|
|||||||
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
||||||
});
|
});
|
||||||
var entity = new InvoiceEntity();
|
var entity = new InvoiceEntity();
|
||||||
|
entity.Networks = networkProvider;
|
||||||
#pragma warning disable CS0618
|
#pragma warning disable CS0618
|
||||||
entity.Payments = new List<PaymentEntity>();
|
entity.Payments = new List<PaymentEntity>();
|
||||||
entity.SetPaymentMethod(new PaymentMethod()
|
entity.SetPaymentMethod(new PaymentMethod()
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ services:
|
|||||||
- "32838"
|
- "32838"
|
||||||
environment:
|
environment:
|
||||||
NBXPLORER_NETWORK: regtest
|
NBXPLORER_NETWORK: regtest
|
||||||
NBXPLORER_CHAINS: "btc,ltc"
|
NBXPLORER_CHAINS: "btc,ltc,lbtc"
|
||||||
NBXPLORER_BTCRPCURL: http://bitcoind:43782/
|
NBXPLORER_BTCRPCURL: http://bitcoind:43782/
|
||||||
NBXPLORER_BTCNODEENDPOINT: bitcoind:39388
|
NBXPLORER_BTCNODEENDPOINT: bitcoind:39388
|
||||||
NBXPLORER_BTCRPCUSER: ceiwHEbqWI83
|
NBXPLORER_BTCRPCUSER: ceiwHEbqWI83
|
||||||
@@ -93,12 +93,17 @@ services:
|
|||||||
NBXPLORER_LTCNODEENDPOINT: litecoind:39388
|
NBXPLORER_LTCNODEENDPOINT: litecoind:39388
|
||||||
NBXPLORER_LTCRPCUSER: ceiwHEbqWI83
|
NBXPLORER_LTCRPCUSER: ceiwHEbqWI83
|
||||||
NBXPLORER_LTCRPCPASSWORD: DwubwWsoo3
|
NBXPLORER_LTCRPCPASSWORD: DwubwWsoo3
|
||||||
|
NBXPLORER_LBTCRPCURL: "http://elementsd-liquid:19332/"
|
||||||
|
NBXPLORER_LBTCNODEENDPOINT: "elementsd-liquid:19444"
|
||||||
|
NBXPLORER_LBTCRPCUSER: "liquid"
|
||||||
|
NBXPLORER_LBTCRPCPASSWORD: "liquid"
|
||||||
NBXPLORER_BIND: 0.0.0.0:32838
|
NBXPLORER_BIND: 0.0.0.0:32838
|
||||||
NBXPLORER_VERBOSE: 1
|
NBXPLORER_VERBOSE: 1
|
||||||
NBXPLORER_NOAUTH: 1
|
NBXPLORER_NOAUTH: 1
|
||||||
links:
|
links:
|
||||||
- bitcoind
|
- bitcoind
|
||||||
- litecoind
|
- litecoind
|
||||||
|
- elementsd-liquid
|
||||||
|
|
||||||
|
|
||||||
bitcoind:
|
bitcoind:
|
||||||
@@ -215,6 +220,34 @@ services:
|
|||||||
expose:
|
expose:
|
||||||
- "43782" # RPC
|
- "43782" # RPC
|
||||||
- "39388" # P2P
|
- "39388" # P2P
|
||||||
|
|
||||||
|
elementsd-liquid:
|
||||||
|
restart: always
|
||||||
|
container_name: btcpayserver_elementsd_liquid
|
||||||
|
image: btcpayserver/elements:0.18.1.1-1
|
||||||
|
environment:
|
||||||
|
ELEMENTS_CHAIN: elementsregtest
|
||||||
|
ELEMENTS_EXTRA_ARGS: |
|
||||||
|
mainchainrpcport=43782
|
||||||
|
mainchainrpchost=bitcoind
|
||||||
|
mainchainrpcuser=liquid
|
||||||
|
mainchainrpcpassword=liquid
|
||||||
|
rpcport=19332
|
||||||
|
rpcbind=0.0.0.0:19332
|
||||||
|
rpcauth=liquid:c8bf1a8961d97f224cb21224aaa8235d$$402f4a8907683d057b8c58a42940b6e54d1638322a42986ae28ebb844e603ae6
|
||||||
|
port=19444
|
||||||
|
whitelist=0.0.0.0/0
|
||||||
|
validatepegin=0
|
||||||
|
initialfreecoins=210000000000000
|
||||||
|
con_dyna_deploy_start=99999999999
|
||||||
|
expose:
|
||||||
|
- "19332"
|
||||||
|
- "19444"
|
||||||
|
ports:
|
||||||
|
- "19332:19332"
|
||||||
|
- "19444:19444"
|
||||||
|
volumes:
|
||||||
|
- "elementsd_liquid_datadir:/data"
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:9.6.5
|
image: postgres:9.6.5
|
||||||
@@ -287,6 +320,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
sshd_datadir:
|
sshd_datadir:
|
||||||
bitcoin_datadir:
|
bitcoin_datadir:
|
||||||
|
elementsd_liquid_datadir:
|
||||||
customer_lightningd_datadir:
|
customer_lightningd_datadir:
|
||||||
merchant_lightningd_datadir:
|
merchant_lightningd_datadir:
|
||||||
lightning_charge_datadir:
|
lightning_charge_datadir:
|
||||||
|
|||||||
@@ -85,9 +85,17 @@ namespace BTCPayServer.Configuration
|
|||||||
throw new ConfigException($"You need to run BTCPayServer with the run.sh or run.ps1 script");
|
throw new ConfigException($"You need to run BTCPayServer with the run.sh or run.ps1 script");
|
||||||
|
|
||||||
var supportedChains = conf.GetOrDefault<string>("chains", "btc")
|
var supportedChains = conf.GetOrDefault<string>("chains", "btc")
|
||||||
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(t => t.ToUpperInvariant());
|
.Select(t => t.ToUpperInvariant()).ToList();
|
||||||
NetworkProvider = new BTCPayNetworkProvider(NetworkType).Filter(supportedChains.ToArray());
|
|
||||||
|
var networkProvider = new BTCPayNetworkProvider(NetworkType);
|
||||||
|
var filtered = networkProvider.Filter(supportedChains.ToArray());
|
||||||
|
var elementsBased = filtered.GetAll().OfType<ElementsBTCPayNetwork>();
|
||||||
|
var parentChains = elementsBased.Select(network => network.NetworkCryptoCode.ToUpperInvariant()).Distinct();
|
||||||
|
var allSubChains = networkProvider.GetAll().OfType<ElementsBTCPayNetwork>()
|
||||||
|
.Where(network => parentChains.Contains(network.NetworkCryptoCode)).Select(network => network.CryptoCode);
|
||||||
|
supportedChains.AddRange(allSubChains);
|
||||||
|
NetworkProvider = networkProvider.Filter(supportedChains.ToArray());
|
||||||
foreach (var chain in supportedChains)
|
foreach (var chain in supportedChains)
|
||||||
{
|
{
|
||||||
if (NetworkProvider.GetNetwork<BTCPayNetworkBase>(chain) == null)
|
if (NetworkProvider.GetNetwork<BTCPayNetworkBase>(chain) == null)
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ namespace BTCPayServer.Controllers
|
|||||||
var getxpubResult = new GetXPubs();
|
var getxpubResult = new GetXPubs();
|
||||||
getxpubResult.ExtPubKey = await hw.GetExtPubKey(network, k, normalOperationTimeout.Token);
|
getxpubResult.ExtPubKey = await hw.GetExtPubKey(network, k, normalOperationTimeout.Token);
|
||||||
var segwit = network.NBitcoinNetwork.Consensus.SupportSegwit;
|
var segwit = network.NBitcoinNetwork.Consensus.SupportSegwit;
|
||||||
var derivation = new DerivationStrategyFactory(network.NBitcoinNetwork).CreateDirectDerivationStrategy(getxpubResult.ExtPubKey, new DerivationStrategyOptions()
|
var derivation = network.NBXplorerNetwork.DerivationStrategyFactory.CreateDirectDerivationStrategy(getxpubResult.ExtPubKey, new DerivationStrategyOptions()
|
||||||
{
|
{
|
||||||
ScriptPubKeyType = segwit ? ScriptPubKeyType.SegwitP2SH : ScriptPubKeyType.Legacy
|
ScriptPubKeyType = segwit ? ScriptPubKeyType.SegwitP2SH : ScriptPubKeyType.Legacy
|
||||||
});
|
});
|
||||||
@@ -374,7 +374,8 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IActionResult ShowAddresses(DerivationSchemeViewModel vm, DerivationSchemeSettings strategy)
|
private IActionResult
|
||||||
|
ShowAddresses(DerivationSchemeViewModel vm, DerivationSchemeSettings strategy)
|
||||||
{
|
{
|
||||||
vm.DerivationScheme = strategy.AccountDerivation.ToString();
|
vm.DerivationScheme = strategy.AccountDerivation.ToString();
|
||||||
var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit);
|
var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit);
|
||||||
@@ -386,8 +387,11 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
var keyPath = deposit.GetKeyPath((uint)i);
|
var keyPath = deposit.GetKeyPath((uint)i);
|
||||||
var rootedKeyPath = vm.GetAccountKeypath()?.Derive(keyPath);
|
var rootedKeyPath = vm.GetAccountKeypath()?.Derive(keyPath);
|
||||||
var address = line.Derive((uint)i);
|
var derivation = line.Derive((uint)i);
|
||||||
vm.AddressSamples.Add((keyPath.ToString(), address.ScriptPubKey.GetDestinationAddress(strategy.Network.NBitcoinNetwork).ToString(), rootedKeyPath));
|
var address = strategy.Network.NBXplorerNetwork.CreateAddress(strategy.AccountDerivation,
|
||||||
|
line.KeyPathTemplate.GetKeyPath((uint)i),
|
||||||
|
derivation.ScriptPubKey).ToString();
|
||||||
|
vm.AddressSamples.Add((keyPath.ToString(), address, rootedKeyPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm.Confirmation = true;
|
vm.Confirmation = true;
|
||||||
|
|||||||
@@ -479,12 +479,12 @@ namespace BTCPayServer.Controllers
|
|||||||
store
|
store
|
||||||
.GetSupportedPaymentMethods(_NetworkProvider)
|
.GetSupportedPaymentMethods(_NetworkProvider)
|
||||||
.OfType<DerivationSchemeSettings>()
|
.OfType<DerivationSchemeSettings>()
|
||||||
.ToDictionary(c => c.Network.CryptoCode);
|
.ToDictionary(c => c.Network.CryptoCode.ToUpperInvariant());
|
||||||
|
|
||||||
var lightningByCryptoCode = store
|
var lightningByCryptoCode = store
|
||||||
.GetSupportedPaymentMethods(_NetworkProvider)
|
.GetSupportedPaymentMethods(_NetworkProvider)
|
||||||
.OfType<LightningSupportedPaymentMethod>()
|
.OfType<LightningSupportedPaymentMethod>()
|
||||||
.ToDictionary(c => c.CryptoCode);
|
.ToDictionary(c => c.CryptoCode.ToUpperInvariant());
|
||||||
|
|
||||||
foreach (var paymentMethodId in _paymentMethodHandlerDictionary.Distinct().SelectMany(handler => handler.GetSupportedPaymentMethods()))
|
foreach (var paymentMethodId in _paymentMethodHandlerDictionary.Distinct().SelectMany(handler => handler.GetSupportedPaymentMethods()))
|
||||||
{
|
{
|
||||||
@@ -492,9 +492,11 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
case BitcoinPaymentType _:
|
case BitcoinPaymentType _:
|
||||||
var strategy = derivationByCryptoCode.TryGet(paymentMethodId.CryptoCode);
|
var strategy = derivationByCryptoCode.TryGet(paymentMethodId.CryptoCode);
|
||||||
|
var network = _NetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode);
|
||||||
vm.DerivationSchemes.Add(new StoreViewModel.DerivationScheme()
|
vm.DerivationSchemes.Add(new StoreViewModel.DerivationScheme()
|
||||||
{
|
{
|
||||||
Crypto = paymentMethodId.CryptoCode,
|
Crypto = paymentMethodId.CryptoCode,
|
||||||
|
WalletSupported = network.WalletSupported,
|
||||||
Value = strategy?.ToPrettyString() ?? string.Empty,
|
Value = strategy?.ToPrettyString() ?? string.Empty,
|
||||||
WalletId = new WalletId(store.Id, paymentMethodId.CryptoCode),
|
WalletId = new WalletId(store.Id, paymentMethodId.CryptoCode),
|
||||||
Enabled = !excludeFilters.Match(paymentMethodId) && strategy != null
|
Enabled = !excludeFilters.Match(paymentMethodId) && strategy != null
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ namespace BTCPayServer.Controllers
|
|||||||
.Select(d => ((Wallet: _walletProvider.GetWallet(d.Network),
|
.Select(d => ((Wallet: _walletProvider.GetWallet(d.Network),
|
||||||
DerivationStrategy: d.AccountDerivation,
|
DerivationStrategy: d.AccountDerivation,
|
||||||
Network: d.Network)))
|
Network: d.Network)))
|
||||||
.Where(_ => _.Wallet != null)
|
.Where(_ => _.Wallet != null && _.Network.WalletSupported)
|
||||||
.Select(_ => (Wallet: _.Wallet,
|
.Select(_ => (Wallet: _.Wallet,
|
||||||
Store: s,
|
Store: s,
|
||||||
Balance: GetBalanceString(_.Wallet, _.DerivationStrategy),
|
Balance: GetBalanceString(_.Wallet, _.DerivationStrategy),
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using System;
|
using NBitcoin;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NBitcoin;
|
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
|
using NBXplorer.DerivationStrategy;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using static BTCPayServer.Data.PaymentRequestData;
|
using static BTCPayServer.Data.PaymentRequestData;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using BTCPayServer.Security;
|
|||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
|
using NBXplorer.DerivationStrategy;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace BTCPayServer.Data
|
namespace BTCPayServer.Data
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace BTCPayServer
|
|||||||
if (type == DerivationType.Legacy)
|
if (type == DerivationType.Legacy)
|
||||||
return new DirectDerivationStrategy(extPubKey) { Segwit = false };
|
return new DirectDerivationStrategy(extPubKey) { Segwit = false };
|
||||||
if (type == DerivationType.SegwitP2SH)
|
if (type == DerivationType.SegwitP2SH)
|
||||||
return new DerivationStrategyFactory(Network).Parse(extPubKey.ToString() + "-[p2sh]");
|
return BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(extPubKey.ToString() + "-[p2sh]");
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = new DerivationStrategyFactory(Network).Parse(str);
|
var result = BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(str);
|
||||||
return FindMatch(hintedLabels, result);
|
return FindMatch(hintedLabels, result);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -150,12 +150,11 @@ namespace BTCPayServer
|
|||||||
str = $"{str}-[{label}]";
|
str = $"{str}-[{label}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
return FindMatch(hintedLabels, new DerivationStrategyFactory(Network).Parse(str));
|
return FindMatch(hintedLabels, BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DerivationStrategyBase FindMatch(HashSet<string> hintLabels, DerivationStrategyBase result)
|
private DerivationStrategyBase FindMatch(HashSet<string> hintLabels, DerivationStrategyBase result)
|
||||||
{
|
{
|
||||||
var facto = new DerivationStrategyFactory(Network);
|
|
||||||
var firstKeyPath = new KeyPath("0/0");
|
var firstKeyPath = new KeyPath("0/0");
|
||||||
if (HintScriptPubKey == null)
|
if (HintScriptPubKey == null)
|
||||||
return result;
|
return result;
|
||||||
@@ -169,7 +168,7 @@ namespace BTCPayServer
|
|||||||
resultNoLabels = string.Join('-', resultNoLabels.Split('-').Where(p => !IsLabel(p)));
|
resultNoLabels = string.Join('-', resultNoLabels.Split('-').Where(p => !IsLabel(p)));
|
||||||
foreach (var labels in ItemCombinations(hintLabels.ToList()))
|
foreach (var labels in ItemCombinations(hintLabels.ToList()))
|
||||||
{
|
{
|
||||||
var hinted = facto.Parse(resultNoLabels + '-' + string.Join('-', labels.Select(l => $"[{l}]").ToArray()));
|
var hinted = BtcPayNetwork.NBXplorerNetwork.DerivationStrategyFactory.Parse(resultNoLabels + '-' + string.Join('-', labels.Select(l => $"[{l}]").ToArray()));
|
||||||
if (HintScriptPubKey == hinted.GetDerivation(firstKeyPath).ScriptPubKey)
|
if (HintScriptPubKey == hinted.GetDerivation(firstKeyPath).ScriptPubKey)
|
||||||
return hinted;
|
return hinted;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace BTCPayServer
|
|||||||
throw new ArgumentNullException(nameof(network));
|
throw new ArgumentNullException(nameof(network));
|
||||||
if (derivationStrategy == null)
|
if (derivationStrategy == null)
|
||||||
throw new ArgumentNullException(nameof(derivationStrategy));
|
throw new ArgumentNullException(nameof(derivationStrategy));
|
||||||
var result = new NBXplorer.DerivationStrategy.DerivationStrategyFactory(network.NBitcoinNetwork).Parse(derivationStrategy);
|
var result = network.NBXplorerNetwork.DerivationStrategyFactory.Parse(derivationStrategy);
|
||||||
return new DerivationSchemeSettings(result, network) { AccountOriginal = derivationStrategy.Trim() };
|
return new DerivationSchemeSettings(result, network) { AccountOriginal = derivationStrategy.Trim() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,23 +33,24 @@ namespace BTCPayServer
|
|||||||
Logs.Configuration.LogInformation($"{setting.CryptoCode}: Cookie file is {(setting.CookieFile ?? "not set")}");
|
Logs.Configuration.LogInformation($"{setting.CryptoCode}: Cookie file is {(setting.CookieFile ?? "not set")}");
|
||||||
if (setting.ExplorerUri != null)
|
if (setting.ExplorerUri != null)
|
||||||
{
|
{
|
||||||
_Clients.TryAdd(setting.CryptoCode, CreateExplorerClient(httpClientFactory.CreateClient(nameof(ExplorerClientProvider)), _NetworkProviders.GetNetwork<BTCPayNetwork>(setting.CryptoCode), setting.ExplorerUri, setting.CookieFile));
|
_Clients.TryAdd(setting.CryptoCode.ToUpperInvariant(), CreateExplorerClient(httpClientFactory.CreateClient(nameof(ExplorerClientProvider)), _NetworkProviders.GetNetwork<BTCPayNetwork>(setting.CryptoCode), setting.ExplorerUri, setting.CookieFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExplorerClient CreateExplorerClient(HttpClient httpClient, BTCPayNetwork n, Uri uri, string cookieFile)
|
private static ExplorerClient CreateExplorerClient(HttpClient httpClient, BTCPayNetwork n, Uri uri, string cookieFile)
|
||||||
{
|
{
|
||||||
var explorer = new ExplorerClient(n.NBXplorerNetwork, uri);
|
|
||||||
|
var explorer = n.NBXplorerNetwork.CreateExplorerClient(uri);
|
||||||
explorer.SetClient(httpClient);
|
explorer.SetClient(httpClient);
|
||||||
if (cookieFile == null)
|
if (cookieFile == null)
|
||||||
{
|
{
|
||||||
Logs.Configuration.LogWarning($"{n.CryptoCode}: Not using cookie authentication");
|
Logs.Configuration.LogWarning($"{explorer.CryptoCode}: Not using cookie authentication");
|
||||||
explorer.SetNoAuth();
|
explorer.SetNoAuth();
|
||||||
}
|
}
|
||||||
if(!explorer.SetCookieAuth(cookieFile))
|
if(!explorer.SetCookieAuth(cookieFile))
|
||||||
{
|
{
|
||||||
Logs.Configuration.LogWarning($"{n.CryptoCode}: Using cookie auth against NBXplorer, but {cookieFile} is not found");
|
Logs.Configuration.LogWarning($"{explorer.CryptoCode}: Using cookie auth against NBXplorer, but {cookieFile} is not found");
|
||||||
}
|
}
|
||||||
return explorer;
|
return explorer;
|
||||||
}
|
}
|
||||||
@@ -61,7 +62,7 @@ namespace BTCPayServer
|
|||||||
var network = _NetworkProviders.GetNetwork<BTCPayNetwork>(cryptoCode);
|
var network = _NetworkProviders.GetNetwork<BTCPayNetwork>(cryptoCode);
|
||||||
if (network == null)
|
if (network == null)
|
||||||
return null;
|
return null;
|
||||||
_Clients.TryGetValue(network.CryptoCode, out ExplorerClient client);
|
_Clients.TryGetValue(network.NBXplorerNetwork.CryptoCode, out ExplorerClient client);
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +80,7 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
public bool IsAvailable(string cryptoCode)
|
public bool IsAvailable(string cryptoCode)
|
||||||
{
|
{
|
||||||
|
cryptoCode = cryptoCode.ToUpperInvariant();
|
||||||
return _Clients.ContainsKey(cryptoCode) && _Dashboard.IsFullySynched(cryptoCode, out var unused);
|
return _Clients.ContainsKey(cryptoCode) && _Dashboard.IsFullySynched(cryptoCode, out var unused);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +89,7 @@ namespace BTCPayServer
|
|||||||
var network = _NetworkProviders.GetNetwork<BTCPayNetwork>(cryptoCode);
|
var network = _NetworkProviders.GetNetwork<BTCPayNetwork>(cryptoCode);
|
||||||
if (network == null)
|
if (network == null)
|
||||||
return null;
|
return null;
|
||||||
if (_Clients.ContainsKey(network.CryptoCode))
|
if (_Clients.ContainsKey(network.NBXplorerNetwork.CryptoCode))
|
||||||
return network;
|
return network;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -96,7 +98,7 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
foreach (var net in _NetworkProviders.GetAll().OfType<BTCPayNetwork>())
|
foreach (var net in _NetworkProviders.GetAll().OfType<BTCPayNetwork>())
|
||||||
{
|
{
|
||||||
if (_Clients.TryGetValue(net.CryptoCode, out ExplorerClient explorer))
|
if (_Clients.TryGetValue(net.NBXplorerNetwork.CryptoCode, out ExplorerClient explorer))
|
||||||
{
|
{
|
||||||
yield return (net, explorer);
|
yield return (net, explorer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
using NBXplorer;
|
||||||
|
|
||||||
namespace BTCPayServer
|
namespace BTCPayServer
|
||||||
{
|
{
|
||||||
@@ -11,19 +14,27 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
case Money money:
|
case Money money:
|
||||||
return money.ToDecimal(MoneyUnit.BTC);
|
return money.ToDecimal(MoneyUnit.BTC);
|
||||||
// case MoneyBag mb:
|
case MoneyBag mb:
|
||||||
// return mb.Select(money => money.GetValue(network)).Sum();
|
return mb.Select(money => money.GetValue(network)).Sum();
|
||||||
// case AssetMoney assetMoney:
|
case AssetMoney assetMoney:
|
||||||
// if (network is ElementsBTCPayNetwork elementsBTCPayNetwork)
|
if (network is ElementsBTCPayNetwork elementsBTCPayNetwork)
|
||||||
// {
|
{
|
||||||
// return elementsBTCPayNetwork.AssetId == assetMoney.AssetId
|
return elementsBTCPayNetwork.AssetId == assetMoney.AssetId
|
||||||
// ? new Money(assetMoney.Quantity)
|
? Convert(assetMoney.Quantity, elementsBTCPayNetwork.Divisibility)
|
||||||
// : Money.Zero;
|
: 0;
|
||||||
// }
|
}
|
||||||
// throw new NotSupportedException("IMoney type not supported");
|
throw new NotSupportedException("IMoney type not supported");
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException("IMoney type not supported");
|
throw new NotSupportedException("IMoney type not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static decimal Convert(long sats, int divisibility = 8)
|
||||||
|
{
|
||||||
|
var amt = sats.ToString(CultureInfo.InvariantCulture).PadLeft(divisibility, '0');
|
||||||
|
amt = amt.Length == divisibility ? $"0.{amt}" : amt.Insert(amt.Length - divisibility, ".");
|
||||||
|
|
||||||
|
return decimal.Parse(amt, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
public void Publish(BTCPayNetworkBase network, NBXplorerState state, StatusResult status, string error)
|
public void Publish(BTCPayNetworkBase network, NBXplorerState state, StatusResult status, string error)
|
||||||
{
|
{
|
||||||
var summary = new NBXplorerSummary() { Network = network, State = state, Status = status, Error = error };
|
var summary = new NBXplorerSummary() { Network = network, State = state, Status = status, Error = error };
|
||||||
_Summaries.AddOrUpdate(network.CryptoCode, summary, (k, v) => summary);
|
_Summaries.AddOrUpdate(network.CryptoCode.ToUpperInvariant(), summary, (k, v) => summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsFullySynched()
|
public bool IsFullySynched()
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace BTCPayServer.ModelBinders
|
|||||||
var network = networkProvider.GetNetwork<BTCPayNetwork>(cryptoCode ?? "BTC");
|
var network = networkProvider.GetNetwork<BTCPayNetwork>(cryptoCode ?? "BTC");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var data = new DerivationStrategyFactory(network.NBitcoinNetwork).Parse(key);
|
var data =network.NBXplorerNetwork.DerivationStrategyFactory.Parse(key);
|
||||||
if (!bindingContext.ModelType.IsInstanceOfType(data))
|
if (!bindingContext.ModelType.IsInstanceOfType(data))
|
||||||
{
|
{
|
||||||
throw new FormatException("Invalid destination type");
|
throw new FormatException("Invalid destination type");
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
public string Crypto { get; set; }
|
public string Crypto { get; set; }
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
public WalletId WalletId { get; set; }
|
public WalletId WalletId { get; set; }
|
||||||
|
public bool WalletSupported { get; set; }
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
public BitcoinLikePaymentData(TxOut txout, OutPoint outpoint, bool rbf)
|
|
||||||
|
public BitcoinLikePaymentData(BitcoinAddress address, IMoney value, OutPoint outpoint, bool rbf)
|
||||||
{
|
{
|
||||||
|
Address = address;
|
||||||
|
Value = value;
|
||||||
Outpoint = outpoint;
|
Outpoint = outpoint;
|
||||||
Output = txout;
|
|
||||||
ConfirmationCount = 0;
|
ConfirmationCount = 0;
|
||||||
RBF = rbf;
|
RBF = rbf;
|
||||||
}
|
}
|
||||||
@@ -36,7 +38,18 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
public int ConfirmationCount { get; set; }
|
public int ConfirmationCount { get; set; }
|
||||||
public bool RBF { get; set; }
|
public bool RBF { get; set; }
|
||||||
public decimal NetworkFee { get; set; }
|
public decimal NetworkFee { get; set; }
|
||||||
|
public BitcoinAddress Address { get; set; }
|
||||||
|
public IMoney Value { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public Script ScriptPubKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Address?.ScriptPubKey ?? Output.ScriptPubKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is set to true if the payment was created before CryptoPaymentData existed in BTCPayServer
|
/// This is set to true if the payment was created before CryptoPaymentData existed in BTCPayServer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -54,7 +67,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
|
|
||||||
public decimal GetValue()
|
public decimal GetValue()
|
||||||
{
|
{
|
||||||
return Output.Value.ToDecimal(MoneyUnit.BTC);
|
return Value?.GetValue(Network as BTCPayNetwork)??Output.Value.ToDecimal(MoneyUnit.BTC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PaymentCompleted(PaymentEntity entity)
|
public bool PaymentCompleted(PaymentEntity entity)
|
||||||
@@ -85,7 +98,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
|
|
||||||
public BitcoinAddress GetDestination()
|
public BitcoinAddress GetDestination()
|
||||||
{
|
{
|
||||||
return Output.ScriptPubKey.GetDestinationAddress(((BTCPayNetwork)Network).NBitcoinNetwork);
|
return Address?? Output.ScriptPubKey.GetDestinationAddress(((BTCPayNetwork)Network).NBitcoinNetwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
string CryptoPaymentData.GetDestination()
|
string CryptoPaymentData.GetDestination()
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ using NBitcoin;
|
|||||||
using NBXplorer.Models;
|
using NBXplorer.Models;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
|
using NBitcoin.Altcoins.Elements;
|
||||||
|
|
||||||
#if NETCOREAPP21
|
#if NETCOREAPP21
|
||||||
using IHostApplicationLifetime = Microsoft.AspNetCore.Hosting.IApplicationLifetime;
|
using IHostApplicationLifetime = Microsoft.AspNetCore.Hosting.IApplicationLifetime;
|
||||||
@@ -148,16 +149,15 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
break;
|
break;
|
||||||
case NBXplorer.Models.NewTransactionEvent evt:
|
case NBXplorer.Models.NewTransactionEvent evt:
|
||||||
wallet.InvalidateCache(evt.DerivationStrategy);
|
wallet.InvalidateCache(evt.DerivationStrategy);
|
||||||
foreach (var output in evt.Outputs)
|
foreach (var output in network.GetValidOutputs(evt))
|
||||||
{
|
{
|
||||||
foreach (var txCoin in evt.TransactionData.Transaction.Outputs.AsCoins()
|
var key = output.Item1.ScriptPubKey.Hash + "#" + network.CryptoCode.ToUpperInvariant();
|
||||||
.Where(o => o.ScriptPubKey == output.ScriptPubKey))
|
|
||||||
{
|
|
||||||
var key = output.ScriptPubKey.Hash + "#" + network.CryptoCode;
|
|
||||||
var invoice = (await _InvoiceRepository.GetInvoicesFromAddresses(new [] {key})).FirstOrDefault();
|
var invoice = (await _InvoiceRepository.GetInvoicesFromAddresses(new [] {key})).FirstOrDefault();
|
||||||
if (invoice != null)
|
if (invoice != null)
|
||||||
{
|
{
|
||||||
var paymentData = new BitcoinLikePaymentData(txCoin.TxOut, txCoin.Outpoint, evt.TransactionData.Transaction.RBF);
|
var address = network.NBXplorerNetwork.CreateAddress(evt.DerivationStrategy,
|
||||||
|
output.Item1.KeyPath, output.Item1.ScriptPubKey);
|
||||||
|
var paymentData = new BitcoinLikePaymentData(address, output.matchedOutput.Value, output.outPoint, evt.TransactionData.Transaction.RBF);
|
||||||
var alreadyExist = GetAllBitcoinPaymentData(invoice).Where(c => c.GetPaymentId() == paymentData.GetPaymentId()).Any();
|
var alreadyExist = GetAllBitcoinPaymentData(invoice).Where(c => c.GetPaymentId() == paymentData.GetPaymentId()).Any();
|
||||||
if (!alreadyExist)
|
if (!alreadyExist)
|
||||||
{
|
{
|
||||||
@@ -170,7 +170,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
await UpdatePaymentStates(wallet, invoice.Id);
|
await UpdatePaymentStates(wallet, invoice.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -316,7 +316,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
return new TransactionConflicts(conflictsByOutpoint.Where(c => c.Value.Transactions.Count > 1).Select(c => c.Value));
|
return new TransactionConflicts(conflictsByOutpoint.Where(c => c.Value.Transactions.Count > 1).Select(c => c.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<int> FindPaymentViaPolling(BTCPayWallet wallet, BTCPayNetworkBase network)
|
private async Task<int> FindPaymentViaPolling(BTCPayWallet wallet, BTCPayNetwork network)
|
||||||
{
|
{
|
||||||
int totalPayment = 0;
|
int totalPayment = 0;
|
||||||
var invoices = await _InvoiceRepository.GetPendingInvoices();
|
var invoices = await _InvoiceRepository.GetPendingInvoices();
|
||||||
@@ -333,14 +333,18 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
if (!invoice.Support(cryptoId))
|
if (!invoice.Support(cryptoId))
|
||||||
continue;
|
continue;
|
||||||
var coins = (await wallet.GetUnspentCoins(strategy))
|
var coins = (await wallet.GetUnspentCoins(strategy))
|
||||||
.Where(c => invoice.AvailableAddressHashes.Contains(c.Coin.ScriptPubKey.Hash.ToString() + cryptoId))
|
.Where(c => invoice.AvailableAddressHashes.Contains(c.ScriptPubKey.Hash.ToString() + cryptoId))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
foreach (var coin in coins.Where(c => !alreadyAccounted.Contains(c.Coin.Outpoint)))
|
foreach (var coin in coins.Where(c => !alreadyAccounted.Contains(c.OutPoint)))
|
||||||
{
|
{
|
||||||
var transaction = await wallet.GetTransactionAsync(coin.Coin.Outpoint.Hash);
|
var transaction = await wallet.GetTransactionAsync(coin.OutPoint.Hash);
|
||||||
var paymentData = new BitcoinLikePaymentData(coin.Coin.TxOut, coin.Coin.Outpoint, transaction.Transaction.RBF);
|
|
||||||
|
var address = network.NBXplorerNetwork.CreateAddress(strategy, coin.KeyPath, coin.ScriptPubKey);
|
||||||
|
var paymentData = new BitcoinLikePaymentData(address, coin.Value, coin.OutPoint,
|
||||||
|
transaction.Transaction.RBF);
|
||||||
|
|
||||||
var payment = await _InvoiceRepository.AddPayment(invoice.Id, coin.Timestamp, paymentData, network).ConfigureAwait(false);
|
var payment = await _InvoiceRepository.AddPayment(invoice.Id, coin.Timestamp, paymentData, network).ConfigureAwait(false);
|
||||||
alreadyAccounted.Add(coin.Coin.Outpoint);
|
alreadyAccounted.Add(coin.OutPoint);
|
||||||
if (payment != null)
|
if (payment != null)
|
||||||
{
|
{
|
||||||
invoice = await ReceivedPayment(wallet, invoice, payment, strategy);
|
invoice = await ReceivedPayment(wallet, invoice, payment, strategy);
|
||||||
@@ -369,7 +373,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
var paymentMethod = invoice.GetPaymentMethod(wallet.Network, PaymentTypes.BTCLike);
|
var paymentMethod = invoice.GetPaymentMethod(wallet.Network, PaymentTypes.BTCLike);
|
||||||
if (paymentMethod != null &&
|
if (paymentMethod != null &&
|
||||||
paymentMethod.GetPaymentMethodDetails() is BitcoinLikeOnChainPaymentMethod btc &&
|
paymentMethod.GetPaymentMethodDetails() is BitcoinLikeOnChainPaymentMethod btc &&
|
||||||
btc.GetDepositAddress(wallet.Network.NBitcoinNetwork).ScriptPubKey == paymentData.Output.ScriptPubKey &&
|
btc.GetDepositAddress(wallet.Network.NBitcoinNetwork).ScriptPubKey == paymentData.ScriptPubKey &&
|
||||||
paymentMethod.Calculate().Due > Money.Zero)
|
paymentMethod.Calculate().Due > Money.Zero)
|
||||||
{
|
{
|
||||||
var address = await wallet.ReserveAddressAsync(strategy);
|
var address = await wallet.ReserveAddressAsync(strategy);
|
||||||
|
|||||||
@@ -21,9 +21,14 @@ namespace BTCPayServer.Payments
|
|||||||
public override string ToPrettyString() => "On-Chain";
|
public override string ToPrettyString() => "On-Chain";
|
||||||
public override string GetId() => "BTCLike";
|
public override string GetId() => "BTCLike";
|
||||||
|
|
||||||
public override CryptoPaymentData DeserializePaymentData(string str)
|
public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str)
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject<BitcoinLikePaymentData>(str);
|
return ((BTCPayNetwork) network).ToObject<BitcoinLikePaymentData>(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData)
|
||||||
|
{
|
||||||
|
return ((BTCPayNetwork) network).ToString(paymentData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
||||||
|
|||||||
@@ -19,10 +19,14 @@ namespace BTCPayServer.Payments
|
|||||||
|
|
||||||
public override string ToPrettyString() => "Off-Chain";
|
public override string ToPrettyString() => "Off-Chain";
|
||||||
public override string GetId() => "LightningLike";
|
public override string GetId() => "LightningLike";
|
||||||
|
public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str)
|
||||||
public override CryptoPaymentData DeserializePaymentData(string str)
|
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject<Payments.Lightning.LightningLikePaymentData>(str);
|
return ((BTCPayNetwork) network).ToObject<LightningLikePaymentData>(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData)
|
||||||
|
{
|
||||||
|
return ((BTCPayNetwork) network).ToString(paymentData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ namespace BTCPayServer.Payments
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract string GetId();
|
public abstract string GetId();
|
||||||
public abstract CryptoPaymentData DeserializePaymentData(string str);
|
public abstract CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str);
|
||||||
|
public abstract string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData);
|
||||||
public abstract IPaymentMethodDetails DeserializePaymentMethodDetails(string str);
|
public abstract IPaymentMethodDetails DeserializePaymentMethodDetails(string str);
|
||||||
public abstract ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value);
|
public abstract ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value);
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
"BTCPAY_HttpsUseDefaultCertificate": "true",
|
"BTCPAY_HttpsUseDefaultCertificate": "true",
|
||||||
"BTCPAY_BUNDLEJSCSS": "false",
|
"BTCPAY_BUNDLEJSCSS": "false",
|
||||||
"BTCPAY_LTCEXPLORERURL": "http://127.0.0.1:32838/",
|
"BTCPAY_LTCEXPLORERURL": "http://127.0.0.1:32838/",
|
||||||
|
"BTCPAY_LBTCEXPLORERURL": "http://127.0.0.1:32838/",
|
||||||
"BTCPAY_BTCLIGHTNING": "type=charge;server=http://127.0.0.1:54938/;api-token=foiewnccewuify",
|
"BTCPAY_BTCLIGHTNING": "type=charge;server=http://127.0.0.1:54938/;api-token=foiewnccewuify",
|
||||||
"BTCPAY_BTCEXTERNALLNDGRPC": "type=lnd-grpc;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true",
|
"BTCPAY_BTCEXTERNALLNDGRPC": "type=lnd-grpc;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true",
|
||||||
"BTCPAY_BTCEXTERNALLNDREST": "type=lnd-rest;server=https://lnd:lnd@127.0.0.1:53280/lnd-rest/btc/;allowinsecure=true",
|
"BTCPAY_BTCEXTERNALLNDREST": "type=lnd-rest;server=https://lnd:lnd@127.0.0.1:53280/lnd-rest/btc/;allowinsecure=true",
|
||||||
@@ -43,7 +44,7 @@
|
|||||||
"BTCPAY_ALLOW-ADMIN-REGISTRATION": "true",
|
"BTCPAY_ALLOW-ADMIN-REGISTRATION": "true",
|
||||||
"BTCPAY_DISABLE-REGISTRATION": "false",
|
"BTCPAY_DISABLE-REGISTRATION": "false",
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
"BTCPAY_CHAINS": "btc,ltc",
|
"BTCPAY_CHAINS": "btc,lbtc",
|
||||||
"BTCPAY_POSTGRES": "User ID=postgres;Host=127.0.0.1;Port=39372;Database=btcpayserver",
|
"BTCPAY_POSTGRES": "User ID=postgres;Host=127.0.0.1;Port=39372;Database=btcpayserver",
|
||||||
"BTCPAY_EXTERNALSERVICES": "totoservice:totolink;",
|
"BTCPAY_EXTERNALSERVICES": "totoservice:totolink;",
|
||||||
"BTCPAY_SSHCONNECTION": "root@127.0.0.1:21622",
|
"BTCPAY_SSHCONNECTION": "root@127.0.0.1:21622",
|
||||||
|
|||||||
@@ -14,12 +14,14 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments
|
|||||||
public override string GetId()=> "MoneroLike";
|
public override string GetId()=> "MoneroLike";
|
||||||
|
|
||||||
|
|
||||||
public override CryptoPaymentData DeserializePaymentData(string str)
|
public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str)
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma warning disable CS0618
|
|
||||||
return JsonConvert.DeserializeObject<MoneroLikePaymentData>(str);
|
return JsonConvert.DeserializeObject<MoneroLikePaymentData>(str);
|
||||||
#pragma warning restore CS0618
|
}
|
||||||
|
|
||||||
|
public override string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData)
|
||||||
|
{
|
||||||
|
return JsonConvert.SerializeObject(paymentData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
||||||
|
|||||||
@@ -562,8 +562,6 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
return paymentMethods;
|
return paymentMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
Network Dummy = Network.Main;
|
|
||||||
|
|
||||||
public void SetPaymentMethod(PaymentMethod paymentMethod)
|
public void SetPaymentMethod(PaymentMethod paymentMethod)
|
||||||
{
|
{
|
||||||
var dict = GetPaymentMethods();
|
var dict = GetPaymentMethods();
|
||||||
@@ -969,7 +967,7 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paymentData = GetPaymentMethodId().PaymentType.DeserializePaymentData(CryptoPaymentData);
|
paymentData = GetPaymentMethodId().PaymentType.DeserializePaymentData(Network,CryptoPaymentData);
|
||||||
paymentData.Network = Network;
|
paymentData.Network = Network;
|
||||||
if (paymentData is BitcoinLikePaymentData bitcoin)
|
if (paymentData is BitcoinLikePaymentData bitcoin)
|
||||||
{
|
{
|
||||||
@@ -991,7 +989,7 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
///
|
///
|
||||||
}
|
}
|
||||||
CryptoPaymentDataType = cryptoPaymentData.GetPaymentType().ToString();
|
CryptoPaymentDataType = cryptoPaymentData.GetPaymentType().ToString();
|
||||||
CryptoPaymentData = JsonConvert.SerializeObject(cryptoPaymentData);
|
CryptoPaymentData = GetPaymentMethodId().PaymentType.SerializePaymentData(Network,cryptoPaymentData);
|
||||||
#pragma warning restore CS0618
|
#pragma warning restore CS0618
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ using NBitpayClient;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.DataEncoders;
|
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Query;
|
using Microsoft.EntityFrameworkCore.Query;
|
||||||
@@ -21,7 +20,10 @@ using BTCPayServer.Models.InvoicingModels;
|
|||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
|
using NBitcoin.Altcoins;
|
||||||
|
using NBitcoin.Altcoins.Elements;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Encoders = NBitcoin.DataEncoders.Encoders;
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Invoices
|
namespace BTCPayServer.Services.Invoices
|
||||||
{
|
{
|
||||||
@@ -707,7 +709,7 @@ retry:
|
|||||||
PaymentData data = new PaymentData
|
PaymentData data = new PaymentData
|
||||||
{
|
{
|
||||||
Id = paymentData.GetPaymentId(),
|
Id = paymentData.GetPaymentId(),
|
||||||
Blob = ToBytes(entity, network),
|
Blob = ToBytes(entity, entity.Network),
|
||||||
InvoiceDataId = invoiceId,
|
InvoiceDataId = invoiceId,
|
||||||
Accounted = accounted
|
Accounted = accounted
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,9 +18,12 @@ namespace BTCPayServer.Services.Wallets
|
|||||||
{
|
{
|
||||||
public class ReceivedCoin
|
public class ReceivedCoin
|
||||||
{
|
{
|
||||||
public Coin Coin { get; set; }
|
public Script ScriptPubKey { get; set; }
|
||||||
|
public OutPoint OutPoint { get; set; }
|
||||||
public DateTimeOffset Timestamp { get; set; }
|
public DateTimeOffset Timestamp { get; set; }
|
||||||
public KeyPath KeyPath { get; set; }
|
public KeyPath KeyPath { get; set; }
|
||||||
|
public IMoney Value { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
public class NetworkCoins
|
public class NetworkCoins
|
||||||
{
|
{
|
||||||
@@ -71,7 +74,8 @@ namespace BTCPayServer.Services.Wallets
|
|||||||
await _Client.TrackAsync(derivationStrategy).ConfigureAwait(false);
|
await _Client.TrackAsync(derivationStrategy).ConfigureAwait(false);
|
||||||
pathInfo = await _Client.GetUnusedAsync(derivationStrategy, DerivationFeature.Deposit, 0, true).ConfigureAwait(false);
|
pathInfo = await _Client.GetUnusedAsync(derivationStrategy, DerivationFeature.Deposit, 0, true).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
return pathInfo.ScriptPubKey.GetDestinationAddress(Network.NBitcoinNetwork);
|
|
||||||
|
return pathInfo.Address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(BitcoinAddress, KeyPath)> GetChangeAddressAsync(DerivationStrategyBase derivationStrategy)
|
public async Task<(BitcoinAddress, KeyPath)> GetChangeAddressAsync(DerivationStrategyBase derivationStrategy)
|
||||||
@@ -173,9 +177,11 @@ namespace BTCPayServer.Services.Wallets
|
|||||||
.GetUnspentUTXOs()
|
.GetUnspentUTXOs()
|
||||||
.Select(c => new ReceivedCoin()
|
.Select(c => new ReceivedCoin()
|
||||||
{
|
{
|
||||||
Coin = c.AsCoin(derivationStrategy),
|
|
||||||
KeyPath = c.KeyPath,
|
KeyPath = c.KeyPath,
|
||||||
Timestamp = c.Timestamp
|
Value = c.Value,
|
||||||
|
Timestamp = c.Timestamp,
|
||||||
|
OutPoint = c.Outpoint,
|
||||||
|
ScriptPubKey = c.ScriptPubKey
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace BTCPayServer.Services.Wallets
|
|||||||
var explorerClient = _Client.GetExplorerClient(network.CryptoCode);
|
var explorerClient = _Client.GetExplorerClient(network.CryptoCode);
|
||||||
if (explorerClient == null)
|
if (explorerClient == null)
|
||||||
continue;
|
continue;
|
||||||
_Wallets.Add(network.CryptoCode, new BTCPayWallet(explorerClient, new MemoryCache(_Options), network));
|
_Wallets.Add(network.CryptoCode.ToUpperInvariant(), new BTCPayWallet(explorerClient, new MemoryCache(_Options), network));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ namespace BTCPayServer.Services.Wallets
|
|||||||
{
|
{
|
||||||
if (cryptoCode == null)
|
if (cryptoCode == null)
|
||||||
throw new ArgumentNullException(nameof(cryptoCode));
|
throw new ArgumentNullException(nameof(cryptoCode));
|
||||||
_Wallets.TryGetValue(cryptoCode, out var result);
|
_Wallets.TryGetValue(cryptoCode.ToUpperInvariant(), out var result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@
|
|||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:right">
|
<td style="text-align:right">
|
||||||
@if(!string.IsNullOrWhiteSpace(scheme.Value))
|
@if(!string.IsNullOrWhiteSpace(scheme.Value) && scheme.WalletSupported)
|
||||||
{
|
{
|
||||||
<a asp-action="WalletTransactions" asp-controller="Wallets" asp-route-walletId="@scheme.WalletId">Wallet</a><span> - </span>
|
<a asp-action="WalletTransactions" asp-controller="Wallets" asp-route-walletId="@scheme.WalletId">Wallet</a><span> - </span>
|
||||||
}
|
}
|
||||||
|
|||||||
1
BTCPayServer/wwwroot/imlegacy/liquid-tether.svg
Normal file
1
BTCPayServer/wwwroot/imlegacy/liquid-tether.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000" width="2000" height="2000"><path d="M1000,0c552.26,0,1000,447.74,1000,1000S1552.24,2000,1000,2000,0,1552.38,0,1000,447.68,0,1000,0" fill="#53ae94"/><path d="M1123.42,866.76V718H1463.6V491.34H537.28V718H877.5V866.64C601,879.34,393.1,934.1,393.1,999.7s208,120.36,484.4,133.14v476.5h246V1132.8c276-12.74,483.48-67.46,483.48-133s-207.48-120.26-483.48-133m0,225.64v-0.12c-6.94.44-42.6,2.58-122,2.58-63.48,0-108.14-1.8-123.88-2.62v0.2C633.34,1081.66,451,1039.12,451,988.22S633.36,894.84,877.62,884V1050.1c16,1.1,61.76,3.8,124.92,3.8,75.86,0,114-3.16,121-3.8V884c243.8,10.86,425.72,53.44,425.72,104.16s-182,93.32-425.72,104.18" fill="#fff"/></svg>
|
||||||
|
After Width: | Height: | Size: 704 B |
34
BTCPayServer/wwwroot/imlegacy/liquid.svg
Normal file
34
BTCPayServer/wwwroot/imlegacy/liquid.svg
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="46px" height="46px" viewBox="0 0 46 46" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>nav_liquid</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<polygon id="path-1" points="0.0158064742 0.0331955923 14.9692374 0.0331955923 14.9692374 23.1732438 0.0158064742 23.1732438"></polygon>
|
||||||
|
<polygon id="path-3" points="0 0.00852524856 15.3983916 0.00852524856 15.3983916 24.9311295 0 24.9311295"></polygon>
|
||||||
|
</defs>
|
||||||
|
<g id="nav_liquid" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="Group-7">
|
||||||
|
<circle id="Oval" fill="#0E726B" fill-rule="nonzero" cx="23" cy="23" r="23"></circle>
|
||||||
|
<g id="Group-13" transform="translate(8.000000, 8.000000)">
|
||||||
|
<path d="M6.89588843,9.41403581 C6.2560124,10.6619008 5.85174242,11.995854 5.69430441,13.3789807 C5.64210055,13.8386915 5.97364325,14.2552893 6.43376722,14.3077686 C6.46613636,14.311281 6.4982989,14.3131405 6.52956612,14.3131405 C6.53858815,14.3131405 6.54754132,14.3129339 6.55642562,14.3126584 C6.96896006,14.2992287 7.31524105,13.9793939 7.36200413,13.5686501 C7.49623278,12.3875207 7.84189394,11.2473003 8.38927686,10.1796694 C9.59113636,7.83476584 11.6381749,6.09695592 14.1532576,5.28641873 C16.6684091,4.47588154 19.3447176,4.69158402 21.6893457,5.89358127 C22.1315634,6.12030303 22.5589738,6.38118457 22.9598691,6.66926997 C23.3358333,6.93869146 23.8611777,6.85260331 24.1308747,6.47725895 C24.4007782,6.10143251 24.314759,5.57608815 23.9390014,5.3061157 C23.4701997,4.96947658 22.9709573,4.66472452 22.4551171,4.40026171 C16.7832851,1.49282369 9.80339532,3.74213499 6.89588843,9.41403581" id="Fill-1" fill="#FFFFFF"></path>
|
||||||
|
<g id="Group-5" transform="translate(2.479339, 0.035675)">
|
||||||
|
<mask id="mask-2" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Clip-4"></g>
|
||||||
|
<path d="M2.68554408,22.6742769 C2.9097865,22.9886708 3.26977273,23.1732438 3.65475895,23.1732438 C3.66777548,23.1732438 3.68079201,23.1730372 3.69387741,23.172624 C3.92803719,23.1649793 4.1532438,23.0887397 4.34525482,22.9518939 C4.87934573,22.5708333 5.00386364,21.8262741 4.62280303,21.2923209 C2.31178375,18.0525826 1.76130165,13.8956956 3.15028237,10.1728306 C4.83148072,5.66532369 9.02376722,2.61897383 13.8305165,2.41167355 C14.4860262,2.38343664 14.9963567,1.82716942 14.9681198,1.17165978 C14.9401584,0.52303719 14.3899518,0.0144283747 13.7404339,0.0337121212 L13.7281061,0.0341942149 C7.96412534,0.282679063 2.93685262,3.93591598 0.920599174,9.34108127 C-0.744896694,13.8057507 -0.0851170799,18.790186 2.68554408,22.6742769" id="Fill-3" fill="#FFFFFF" mask="url(#mask-2)"></path>
|
||||||
|
</g>
|
||||||
|
<g id="Group-8" transform="translate(0.000000, 5.889669)">
|
||||||
|
<mask id="mask-4" fill="white">
|
||||||
|
<use xlink:href="#path-3"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Clip-7"></g>
|
||||||
|
<path d="M14.6429477,23.2208678 C8.29411846,22.5359504 3.19763085,17.7794766 1.96092287,11.3850551 C1.29294766,7.93181818 1.85782369,4.34586777 3.55169421,1.28774105 C3.77903581,0.877203857 3.63564738,0.353719008 3.23206612,0.120798898 C3.03674931,0.00805785124 2.80975207,-0.0210055096 2.59336088,0.0391873278 C2.37428375,0.1 2.19232782,0.244214876 2.08096419,0.445316804 C0.190399449,3.85853994 -0.440247934,7.86060606 0.305206612,11.7141185 C1.68557851,18.8517906 7.37655647,24.1613636 14.4666391,24.9265152 C14.4958402,24.9296143 14.5255234,24.9311295 14.5552755,24.9311295 C14.5647107,24.9311295 14.574146,24.9309917 14.5835813,24.9306474 C15.0021074,24.9169421 15.3504545,24.5870523 15.3937741,24.1633609 C15.4421212,23.693595 15.1052755,23.2708678 14.6429477,23.2208678" id="Fill-6" fill="#FFFFFF" mask="url(#mask-4)"></path>
|
||||||
|
</g>
|
||||||
|
<path d="M20.8919766,26.3926377 C19.749759,26.7185331 18.5809573,26.888781 17.4175275,26.8986295 C14.4131887,26.9374036 11.5654614,25.9904339 9.18729339,24.1626102 C9.00988292,24.0258333 8.78977273,23.9663292 8.56766529,23.9952548 C8.34514463,24.0241804 8.14727961,24.1382989 8.01043388,24.3163981 C7.7286157,24.6832025 7.79769284,25.2109573 8.16449725,25.4929132 C10.7931474,27.5135744 13.9281336,28.5781749 17.2434917,28.5781749 C17.3085055,28.5781749 17.3740014,28.5778306 17.4391529,28.5770041 C17.539084,28.575489 17.6386708,28.5732163 17.7383264,28.5700482 L17.7383953,28.5700482 C18.965668,28.5301722 20.1815771,28.3406405 21.352376,28.0067562 C21.7973485,27.879759 22.0560262,27.4144008 21.9290978,26.9694284 C21.8028581,26.5263843 21.3379132,26.2675689 20.8919766,26.3926377" id="Fill-9" fill="#FFFFFF"></path>
|
||||||
|
<path d="M24.8857576,23.2102686 C24.7049036,22.8923623 24.2990496,22.7803788 23.9807989,22.9608196 C22.2428512,23.9473209 19.8861708,24.5384366 17.3449862,24.6251446 C16.9661295,24.6380234 16.6778375,24.9022796 16.659449,25.2535193 C16.6428512,25.5714256 16.8549725,25.8571006 17.1637879,25.9327204 L17.1638567,25.9327204 C17.203595,25.9425 17.2449862,25.9486983 17.2877548,25.9511088 C17.4449862,25.9593044 17.6055923,25.9633678 17.7691598,25.9633678 C19.9498072,25.9633678 22.6442287,25.2461501 24.6361019,24.1155028 C24.7903719,24.0280372 24.9012534,23.8856818 24.9484298,23.7146074 C24.9955372,23.5437397 24.973292,23.3646763 24.8857576,23.2102686" id="Fill-11" fill="#FFFFFF"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.5 KiB |
Reference in New Issue
Block a user