diff --git a/NBXplorer.Client/Models/NewBlockEvent.cs b/NBXplorer.Client/Models/NewBlockEvent.cs index 312bd858..1292927c 100644 --- a/NBXplorer.Client/Models/NewBlockEvent.cs +++ b/NBXplorer.Client/Models/NewBlockEvent.cs @@ -24,6 +24,8 @@ public uint256 PreviousBlockHash public long Confirmations { get; set; } + public DateTimeOffset BlockTime { get; set; } + [JsonIgnore] public override string EventType => "newblock"; diff --git a/NBXplorer.Tests/UnitTest1.cs b/NBXplorer.Tests/UnitTest1.cs index 78a42a17..51d0e2cf 100644 --- a/NBXplorer.Tests/UnitTest1.cs +++ b/NBXplorer.Tests/UnitTest1.cs @@ -2066,8 +2066,9 @@ public async Task CanUseWebSockets(bool legacyAPI) Assert.True(blockEvent.EventId != 0); Assert.Equal(expectedBlockId, blockEvent.Hash); Assert.NotEqual(0, blockEvent.Height); - + Assert.NotEqual(default, blockEvent.BlockTime); Assert.Equal(1, blockEvent.Confirmations); + Assert.NotEqual(default, blockEvent.BlockTime); legacy?.ListenDerivationSchemes(new[] { pubkey }); await tester.SendToAddressAsync(tester.AddressOf(pubkey, "0/1"), Money.Coins(1.0m)); @@ -2470,6 +2471,7 @@ public async Task CanUseWebSocketsOnAddress(bool legacyAPI) var blockEvent = await WaitBlock(connected, expectedBlockId, Cancel); Assert.Equal(expectedBlockId, blockEvent.Hash); Assert.NotEqual(0, blockEvent.Height); + Assert.NotEqual(default, blockEvent.BlockTime); legacy?.ListenTrackedSources(new[] { pubkey }); tester.SendToAddress(pubkey.Address, Money.Coins(1.0m)); diff --git a/NBXplorer/Backend/Indexer.cs b/NBXplorer/Backend/Indexer.cs index 1d12b83d..ff99a9b3 100644 --- a/NBXplorer/Backend/Indexer.cs +++ b/NBXplorer/Backend/Indexer.cs @@ -448,14 +448,14 @@ private async Task SaveMatches(DbConnectionHelper conn, Block block, SlimChained var seenAt = State == BitcoinDWaiterState.NBXplorerSynching ? block.Header.BlockTime : DateTimeOffset.UtcNow; - await SaveMatches(conn, block.Transactions, slimChainedBlock, true, seenAt); + await SaveMatches(conn, block.Transactions, slimChainedBlock, true, seenAt, block.Header.BlockTime); EventAggregator.Publish(new RawBlockEvent(block, this.Network), true); lastIndexedBlock = slimChainedBlock; } SlimChainedBlock _NodeTip; - private async Task SaveMatches(DbConnectionHelper conn, List transactions, SlimChainedBlock slimChainedBlock, bool fireEvents, DateTimeOffset? seenAt = null) + private async Task SaveMatches(DbConnectionHelper conn, List transactions, SlimChainedBlock slimChainedBlock, bool fireEvents, DateTimeOffset? seenAt = null, DateTimeOffset? blockTime = null) { foreach (var tx in transactions) tx.PrecomputeHash(false, true); @@ -480,7 +480,8 @@ private async Task SaveMatches(DbConnectionHelper conn, List transa Hash = slimChainedBlock.Hash, Height = slimChainedBlock.Height, PreviousBlockHash = slimChainedBlock.Previous, - Confirmations = confirmations + Confirmations = confirmations, + BlockTime = blockTime ?? now }; await Repository.SaveEvent(conn, blockEvent); EventAggregator.Publish(blockEvent); diff --git a/NBXplorer/wwwroot/api.json b/NBXplorer/wwwroot/api.json index 6a7fadb8..4c9e1981 100644 --- a/NBXplorer/wwwroot/api.json +++ b/NBXplorer/wwwroot/api.json @@ -844,6 +844,11 @@ "type": "integer", "description": "Number of confirmations (typically 1 for a new block).", "example": 1 + }, + "blockTime": { + "type": "string", + "format": "date-time", + "description": "Timestamp of the block as reported by the block header." } } },