diff --git a/NBXplorer.Client/ExplorerClient.cs b/NBXplorer.Client/ExplorerClient.cs index 26b309723..78d5f0281 100644 --- a/NBXplorer.Client/ExplorerClient.cs +++ b/NBXplorer.Client/ExplorerClient.cs @@ -726,7 +726,7 @@ private FormattableString GetBasePath(TrackedSource trackedSource) { DerivationSchemeTrackedSource dsts => $"v1/cryptos/{CryptoCode}/derivations/{dsts.DerivationStrategy}", AddressTrackedSource asts => $"v1/cryptos/{CryptoCode}/addresses/{asts.Address}", - WalletTrackedSource wts => $"v1/cryptos/{CryptoCode}/wallets/{wts.WalletId}", + GroupTrackedSource wts => $"v1/cryptos/{CryptoCode}/groups/{wts.GroupId}", _ => $"v1/cryptos/{CryptoCode}/tracked-sources/{trackedSource}" }; } diff --git a/NBXplorer.Client/Models/TrackedSource.cs b/NBXplorer.Client/Models/TrackedSource.cs index 5dcebe50b..398fc4f2c 100644 --- a/NBXplorer.Client/Models/TrackedSource.cs +++ b/NBXplorer.Client/Models/TrackedSource.cs @@ -26,9 +26,9 @@ public static bool TryParse(string str, out TrackedSource trackedSource, NBXplor return false; trackedSource = addressTrackedSource; } - else if (strSpan.StartsWith("WALLET:".AsSpan(), StringComparison.Ordinal)) + else if (strSpan.StartsWith("GROUP:".AsSpan(), StringComparison.Ordinal)) { - if (!WalletTrackedSource.TryParse(strSpan, out var walletTrackedSource)) + if (!GroupTrackedSource.TryParse(strSpan, out var walletTrackedSource)) return false; trackedSource = walletTrackedSource; } @@ -103,25 +103,25 @@ public static TrackedSource Parse(string str, NBXplorerNetwork network) } } - public class WalletTrackedSource : TrackedSource + public class GroupTrackedSource : TrackedSource { - public string WalletId { get; } + public string GroupId { get; } - public WalletTrackedSource(string walletId) + public GroupTrackedSource(string groupId) { - WalletId = walletId; + GroupId = groupId; } - public static bool TryParse(ReadOnlySpan strSpan, out WalletTrackedSource walletTrackedSource) + public static bool TryParse(ReadOnlySpan trackedSource, out GroupTrackedSource walletTrackedSource) { - if (strSpan == null) - throw new ArgumentNullException(nameof(strSpan)); + if (trackedSource == null) + throw new ArgumentNullException(nameof(trackedSource)); walletTrackedSource = null; - if (!strSpan.StartsWith("WALLET:".AsSpan(), StringComparison.Ordinal)) + if (!trackedSource.StartsWith("GROUP:".AsSpan(), StringComparison.Ordinal)) return false; try { - walletTrackedSource = new WalletTrackedSource(strSpan.Slice("WALLET:".Length).ToString()); + walletTrackedSource = new GroupTrackedSource(trackedSource.Slice("GROUP:".Length).ToString()); return true; } catch { return false; } @@ -129,11 +129,16 @@ public static bool TryParse(ReadOnlySpan strSpan, out WalletTrackedSource public override string ToString() { - return "WALLET:" + WalletId; + return "GROUP:" + GroupId; } public override string ToPrettyString() { - return WalletId; + return GroupId; + } + + public static GroupTrackedSource Parse(string trackedSource) + { + return TryParse(trackedSource, out var g) ? g : throw new FormatException("Invalid group tracked source format"); } } diff --git a/NBXplorer/Backends/Postgres/PostgresRepository.cs b/NBXplorer/Backends/Postgres/PostgresRepository.cs index c76a86b9f..e7d5c0295 100644 --- a/NBXplorer/Backends/Postgres/PostgresRepository.cs +++ b/NBXplorer/Backends/Postgres/PostgresRepository.cs @@ -207,10 +207,10 @@ internal WalletKey GetWalletKey(DerivationStrategyBase strategy) m.Add(new JProperty("derivation", new JValue(strategy.ToString()))); return new WalletKey(hash, m.ToString(Formatting.None)); } - WalletKey GetWalletKey(WalletTrackedSource walletTrackedSource) + WalletKey GetWalletKey(GroupTrackedSource groupTrackedSource) { - var m = new JObject { new JProperty("type", new JValue("Wallet")) }; - var res = new WalletKey(walletTrackedSource.WalletId, m.ToString(Formatting.None)); + var m = new JObject { new JProperty("type", new JValue("NBXv1-Group")) }; + var res = new WalletKey($"G:" + groupTrackedSource.GroupId, m.ToString(Formatting.None)); return res; } WalletKey GetWalletKey(IDestination destination) @@ -231,12 +231,12 @@ internal WalletKey GetWalletKey(TrackedSource source) { DerivationSchemeTrackedSource derivation => GetWalletKey(derivation.DerivationStrategy), AddressTrackedSource addr => GetWalletKey(addr.Address), - WalletTrackedSource wallet => GetWalletKey(wallet), + GroupTrackedSource group => GetWalletKey(group), _ => throw new NotSupportedException(source.GetType().ToString()) }; } - internal TrackedSource GetTrackedSource(WalletKey walletKey) + internal TrackedSource TryGetTrackedSource(WalletKey walletKey) { var metadata = JObject.Parse(walletKey.metadata); if (metadata.TryGetValue("type", StringComparison.OrdinalIgnoreCase, out JToken typeJToken) && @@ -257,8 +257,8 @@ internal TrackedSource GetTrackedSource(WalletKey walletKey) case "NBXv1-Address": var address = metadata["address"].Value(); return new AddressTrackedSource(BitcoinAddress.Create(address, Network.NBitcoinNetwork)); - case "Wallet": - return new WalletTrackedSource(walletKey.wid); + case "NBXv1-Group": + return new GroupTrackedSource(walletKey.wid[2..]); // Skip "G:" } } @@ -489,7 +489,7 @@ async Task> GetKeyInformations( var rows = await connection.QueryAsync($@" SELECT ts.code, ts.script, ts.addr, ts.derivation, ts.keypath, ts.redeem{additionalColumn}, ts.wallet_id, - w.metadata->>'type' AS wallet_type + w.metadata->>'type' AS wallet_metadata FROM unnest(@records) AS r (script), LATERAL ( SELECT code, script, wallet_id, addr, descriptor_metadata->>'derivation' derivation, @@ -507,21 +507,21 @@ JOIN wallets w USING(wallet_id)", // This might be the case for a derivation added by a different indexer if (r.derivation is not null && r.keypath is null) continue; - var addr = GetAddress(r); + BitcoinAddress addr = GetAddress(r); bool isExplicit = r.derivation is null; bool isDescriptor = !isExplicit; var script = Script.FromHex(r.script); - var derivationStrategy = r.derivation is not null ? Network.DerivationStrategyFactory.Parse(r.derivation) : null; + DerivationStrategyBase derivationStrategy = r.derivation is not null ? Network.DerivationStrategyFactory.Parse(r.derivation) : null; var keypath = r.keypath is not null ? KeyPath.Parse(r.keypath) : null; var redeem = (string)r.redeem; - string walletType = r.wallet_type; - string walletId = r.wallet_id; - - var trackedSource = derivationStrategy is not null - ? new DerivationSchemeTrackedSource(derivationStrategy) - : walletType == "Wallet" - ? walletId is null ? (TrackedSource)null : new WalletTrackedSource(walletId) - : new AddressTrackedSource(addr); + string walletMetadata = r.wallet_metadata; + string wid = r.wallet_id; + if (wid is null || walletMetadata is null) + continue; + var walletKey = new WalletKey(wid, walletMetadata); + var trackedSource = TryGetTrackedSource(walletKey); + if (trackedSource is null) + continue; var ki = Network.IsElement && r.blindingKey is not null ? new LiquidKeyPathInformation() { diff --git a/NBXplorer/Controllers/CommonRoutes.cs b/NBXplorer/Controllers/CommonRoutes.cs index c33773fd6..2d93020f7 100644 --- a/NBXplorer/Controllers/CommonRoutes.cs +++ b/NBXplorer/Controllers/CommonRoutes.cs @@ -6,7 +6,7 @@ public static class CommonRoutes public const string BaseDerivationEndpoint = $"{BaseCryptoEndpoint}/derivations"; public const string DerivationEndpoint = $"{BaseCryptoEndpoint}/derivations/{{derivationScheme}}"; public const string AddressEndpoint = $"{BaseCryptoEndpoint}/addresses/{{address}}"; - public const string WalletEndpoint = $"{BaseCryptoEndpoint}/wallets/{{walletId}}"; + public const string GroupEndpoint = $"{BaseCryptoEndpoint}/groups/{{groupId}}"; public const string TrackedSourceEndpoint = $"{BaseCryptoEndpoint}/tracked-sources/{{trackedSource}}"; public const string TransactionsPath = "transactions/{txId?}"; } \ No newline at end of file diff --git a/NBXplorer/Controllers/MainController.cs b/NBXplorer/Controllers/MainController.cs index 0bb861a54..b947d0a97 100644 --- a/NBXplorer/Controllers/MainController.cs +++ b/NBXplorer/Controllers/MainController.cs @@ -505,7 +505,7 @@ private bool HasTxIndex(string cryptoCode) [HttpPost] [Route($"{CommonRoutes.DerivationEndpoint}")] [Route($"{CommonRoutes.AddressEndpoint}")] - [Route($"{CommonRoutes.WalletEndpoint}")] + [Route($"{CommonRoutes.GroupEndpoint}")] [Route($"{CommonRoutes.TrackedSourceEndpoint}")] public async Task TrackWallet( TrackedSourceContext trackedSourceContext, @@ -560,7 +560,7 @@ private GenerateAddressQuery GenerateAddressQuery(TrackWalletRequest request, De [HttpGet] [Route($"{CommonRoutes.DerivationEndpoint}/{CommonRoutes.TransactionsPath}")] [Route($"{CommonRoutes.AddressEndpoint}/{CommonRoutes.TransactionsPath}")] - [Route($"{CommonRoutes.WalletEndpoint}/{CommonRoutes.TransactionsPath}")] + [Route($"{CommonRoutes.GroupEndpoint}/{CommonRoutes.TransactionsPath}")] [Route($"{CommonRoutes.TrackedSourceEndpoint}/{CommonRoutes.TransactionsPath}")] public async Task GetTransactions( TrackedSourceContext trackedSourceContext, diff --git a/NBXplorer/Controllers/PostgresMainController.cs b/NBXplorer/Controllers/PostgresMainController.cs index ed1322b97..70f48c0f3 100644 --- a/NBXplorer/Controllers/PostgresMainController.cs +++ b/NBXplorer/Controllers/PostgresMainController.cs @@ -22,7 +22,7 @@ namespace NBXplorer.Controllers [PostgresImplementationActionConstraint(true)] [Route($"v1/{CommonRoutes.DerivationEndpoint}")] [Route($"v1/{CommonRoutes.AddressEndpoint}")] - [Route($"v1/{CommonRoutes.WalletEndpoint}")] + [Route($"v1/{CommonRoutes.GroupEndpoint}")] [Route($"v1/{CommonRoutes.TrackedSourceEndpoint}")] [Authorize] public class PostgresMainController : Controller, IUTXOService diff --git a/NBXplorer/Controllers/TrackedSourceContext.cs b/NBXplorer/Controllers/TrackedSourceContext.cs index 035a06883..c4dd0bdb2 100644 --- a/NBXplorer/Controllers/TrackedSourceContext.cs +++ b/NBXplorer/Controllers/TrackedSourceContext.cs @@ -51,7 +51,7 @@ public Task BindModelAsync(ModelBindingContext bindingContext) var addressValue = bindingContext.ValueProvider.GetValue("address").FirstValue; var derivationSchemeValue = bindingContext.ValueProvider.GetValue("derivationScheme").FirstValue; derivationSchemeValue ??= bindingContext.ValueProvider.GetValue("extPubKey").FirstValue; - var walletIdValue = bindingContext.ValueProvider.GetValue("walletId").FirstValue; + var groupIdValue = bindingContext.ValueProvider.GetValue("groupId").FirstValue; var trackedSourceValue = bindingContext.ValueProvider.GetValue("trackedSource").FirstValue; var networkProvider = bindingContext.HttpContext.RequestServices.GetService(); @@ -82,7 +82,7 @@ public Task BindModelAsync(ModelBindingContext bindingContext) ThrowRpcUnavailableException(); } - var ts = GetTrackedSource(derivationSchemeValue, addressValue, walletIdValue, + var ts = GetTrackedSource(derivationSchemeValue, addressValue, groupIdValue, trackedSourceValue, network); if (ts is null && requirements?.RequireTrackedSource is true) @@ -117,7 +117,7 @@ public static void ThrowRpcUnavailableException() throw new NBXplorerError(400, "rpc-unavailable", $"The RPC interface is currently not available.").AsException(); } - public static TrackedSource GetTrackedSource(string derivationScheme, string address, string walletId, + public static TrackedSource GetTrackedSource(string derivationScheme, string address, string groupId, string trackedSource, NBXplorerNetwork network) { if (trackedSource != null) @@ -126,8 +126,8 @@ public static TrackedSource GetTrackedSource(string derivationScheme, string add return new AddressTrackedSource(BitcoinAddress.Create(address, network.NBitcoinNetwork)); if (derivationScheme != null) return new DerivationSchemeTrackedSource(network.DerivationStrategyFactory.Parse(derivationScheme)); - if (walletId != null) - return new WalletTrackedSource(walletId); + if (groupId != null) + return new GroupTrackedSource(groupId); return null; } } diff --git a/NBXplorer/TrackedTransaction.cs b/NBXplorer/TrackedTransaction.cs index a079747ba..4a3a2036c 100644 --- a/NBXplorer/TrackedTransaction.cs +++ b/NBXplorer/TrackedTransaction.cs @@ -151,7 +151,7 @@ public IEnumerable GetReceivedOutputs() Output: o, KeyPath: KnownKeyPathMapping.TryGet(o.TxOut.ScriptPubKey), Address: KnownKeyPathInformation.TryGet(o.TxOut.ScriptPubKey)?.Address)) - .Where(o => o.KeyPath != null || o.Output.TxOut.ScriptPubKey == (TrackedSource as IDestination)?.ScriptPubKey || TrackedSource is WalletTrackedSource) + .Where(o => o.KeyPath != null || o.Output.TxOut.ScriptPubKey == (TrackedSource as IDestination)?.ScriptPubKey || TrackedSource is GroupTrackedSource) .Select(o => new MatchedOutput() { Index = o.Index,