mirror of
https://github.com/Retropex/bitfeed.git
synced 2025-05-13 03:30:47 +02:00
commit
48b346ec18
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bitfeed-client",
|
"name": "bitfeed-client",
|
||||||
"version": "2.3.1",
|
"version": "2.3.2",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"dev": "rollup -c -w",
|
"dev": "rollup -c -w",
|
||||||
|
@ -359,7 +359,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="data-row spacer"> </div>
|
<div class="data-row spacer"> </div>
|
||||||
<div class="data-row">
|
<div class="data-row">
|
||||||
<span class="data-field">Avg fee rate</span>
|
<span class="data-field">avg fee rate</span>
|
||||||
{#if block.fees != null}
|
{#if block.fees != null}
|
||||||
<span class="data-field">{ formatFee(block.avgFeerate) } sats/vbyte</span>
|
<span class="data-field">{ formatFee(block.avgFeerate) } sats/vbyte</span>
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -91,7 +91,7 @@ function expandAddresses(items, truncate) {
|
|||||||
})
|
})
|
||||||
if (truncate && items.length > 100) {
|
if (truncate && items.length > 100) {
|
||||||
const remainingCount = items.length - 100
|
const remainingCount = items.length - 100
|
||||||
const remainingValue = items.slice(100).reduce((acc, item) => { return acc + item.value }, 0)
|
const remainingValue = items.slice(100).reduce((acc, item) => { return acc + (item.value || 0) }, 0)
|
||||||
expanded.push({
|
expanded.push({
|
||||||
address: `+ ${remainingCount} more`,
|
address: `+ ${remainingCount} more`,
|
||||||
value: remainingValue,
|
value: remainingValue,
|
||||||
@ -173,10 +173,7 @@ function calcSankeyLines(inputs, outputs, fee, value, totalHeight, svgWidth, flo
|
|||||||
let maxXOffset = 0
|
let maxXOffset = 0
|
||||||
|
|
||||||
const inLines = inputs.map((input, index) => {
|
const inLines = inputs.map((input, index) => {
|
||||||
if (input.value == null) {
|
const weight = ((input.value || 0) / total) * flowWeight
|
||||||
return { line: [], weight: 0, index, total: inputs.length, in: true }
|
|
||||||
} else {
|
|
||||||
const weight = (input.value / total) * flowWeight
|
|
||||||
const height = ((index + 0.5) * rowHeight)
|
const height = ((index + 0.5) * rowHeight)
|
||||||
const step = (weight / 2)
|
const step = (weight / 2)
|
||||||
const line = []
|
const line = []
|
||||||
@ -202,7 +199,6 @@ function calcSankeyLines(inputs, outputs, fee, value, totalHeight, svgWidth, flo
|
|||||||
cumThick += weight
|
cumThick += weight
|
||||||
|
|
||||||
return { line, weight, index, total: inputs.length, in: true }
|
return { line, weight, index, total: inputs.length, in: true }
|
||||||
}
|
|
||||||
})
|
})
|
||||||
inLines.forEach(line => {
|
inLines.forEach(line => {
|
||||||
if (line.line.length) {
|
if (line.line.length) {
|
||||||
|
@ -166,6 +166,9 @@ function highlight () {
|
|||||||
{#if !tx.coinbase && tx.fee != null }
|
{#if !tx.coinbase && tx.fee != null }
|
||||||
<p class="field feerate">Fee rate: { numberFormat.format(tx.feerate.toFixed(2)) } sats/vbyte</p>
|
<p class="field feerate">Fee rate: { numberFormat.format(tx.feerate.toFixed(2)) } sats/vbyte</p>
|
||||||
<p class="field fee">Fee: { numberFormat.format(tx.fee) } sats</p>
|
<p class="field fee">Fee: { numberFormat.format(tx.fee) } sats</p>
|
||||||
|
{:else if !tx.coinbase && tx.fee == null}
|
||||||
|
<p class="field feerate">Fee rate: unavailable</p>
|
||||||
|
<p class="field fee">Fee: unavailable</p>
|
||||||
{/if}
|
{/if}
|
||||||
<p class="field value">
|
<p class="field value">
|
||||||
Total value: { formatBTC(tx.value) }
|
Total value: { formatBTC(tx.value) }
|
||||||
|
@ -417,7 +417,7 @@ export default class TxController {
|
|||||||
this.selectedTx = selected
|
this.selectedTx = selected
|
||||||
selectedTx.set(selected)
|
selectedTx.set(selected)
|
||||||
if (sameTx && selected) {
|
if (sameTx && selected) {
|
||||||
if (!selected.is_inflated) {
|
if (!selected.is_inflated || selected.is_partial) {
|
||||||
loading.increment()
|
loading.increment()
|
||||||
await searchTx(selected.id)
|
await searchTx(selected.id)
|
||||||
loading.decrement()
|
loading.decrement()
|
||||||
|
@ -49,10 +49,11 @@ export default class BitcoinTx {
|
|||||||
this.view = new TxView(this)
|
this.view = new TxView(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeData ({ version, inflated, preview, id, value, fee, vbytes, numInputs, inputs, outputs, time, block }, isCoinbase=false) {
|
mergeData ({ version, inflated, partial, preview, id, value, fee, vbytes, numInputs, inputs, outputs, time, block }, isCoinbase=false) {
|
||||||
this.setData({
|
this.setData({
|
||||||
version,
|
version,
|
||||||
inflated: this.is_inflated || inflated,
|
inflated: this.is_inflated || inflated,
|
||||||
|
partial: this.is_partial && partial,
|
||||||
preview: this.is_preview && preview,
|
preview: this.is_preview && preview,
|
||||||
id,
|
id,
|
||||||
value,
|
value,
|
||||||
@ -66,9 +67,10 @@ export default class BitcoinTx {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setData ({ version, inflated, preview, id, value, fee, vbytes, numInputs, inputs, outputs, time, block }, isCoinbase=false) {
|
setData ({ version, inflated, partial, preview, id, value, fee, vbytes, numInputs, inputs, outputs, time, block }, isCoinbase=false) {
|
||||||
this.version = version
|
this.version = version
|
||||||
this.is_inflated = !!inflated
|
this.is_inflated = !!inflated
|
||||||
|
this.is_partial = !!partial
|
||||||
this.is_preview = !!preview
|
this.is_preview = !!preview
|
||||||
this.id = id
|
this.id = id
|
||||||
this.pixelPosition = { x: 0, y: 0, r: 0}
|
this.pixelPosition = { x: 0, y: 0, r: 0}
|
||||||
@ -92,7 +94,7 @@ export default class BitcoinTx {
|
|||||||
|
|
||||||
// is a coinbase transaction?
|
// is a coinbase transaction?
|
||||||
this.isCoinbase = isCoinbase
|
this.isCoinbase = isCoinbase
|
||||||
if (this.isCoinbase || this.fee == null || this.fee < 0) {
|
if (this.isCoinbase || this.fee == null || this.fee < 0 || this.is_partial) {
|
||||||
this.fee = null
|
this.fee = null
|
||||||
this.feerate = null
|
this.feerate = null
|
||||||
}
|
}
|
||||||
|
@ -433,18 +433,20 @@ defmodule BitcoinStream.Mempool do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp sync_mempool_txns(pid, [next_chunk | rest], count) do
|
defp sync_mempool_txns(pid, [next_chunk | rest], count) do
|
||||||
|
:timer.sleep(250);
|
||||||
case sync_batch(pid, next_chunk) do
|
case sync_batch(pid, next_chunk) do
|
||||||
{:ok, batch_count} ->
|
{:ok, batch_count} ->
|
||||||
Logger.info("synced #{batch_count + count} mempool transactions");
|
Logger.info("synced #{batch_count + count} mempool transactions");
|
||||||
sync_mempool_txns(pid, rest, batch_count + count)
|
sync_mempool_txns(pid, rest, batch_count + count)
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
:failed
|
Logger.info("Failed to sync #{length(next_chunk)} mempool transactions");
|
||||||
|
sync_mempool_txns(pid, rest, count)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def sync_mempool_txns(pid, txns) do
|
def sync_mempool_txns(pid, txns) do
|
||||||
sync_mempool_txns(pid, Enum.chunk_every(txns, 100), 0)
|
sync_mempool_txns(pid, Enum.chunk_every(txns, 50), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ defmodule BitcoinStream.Protocol.Transaction do
|
|||||||
defstruct [
|
defstruct [
|
||||||
:version,
|
:version,
|
||||||
:inflated,
|
:inflated,
|
||||||
|
:partial,
|
||||||
:vbytes,
|
:vbytes,
|
||||||
:inputs,
|
:inputs,
|
||||||
:outputs,
|
:outputs,
|
||||||
@ -99,6 +100,7 @@ defmodule BitcoinStream.Protocol.Transaction do
|
|||||||
%__MODULE__{
|
%__MODULE__{
|
||||||
version: txn.version,
|
version: txn.version,
|
||||||
inflated: false,
|
inflated: false,
|
||||||
|
partial: true,
|
||||||
vbytes: txn.vbytes,
|
vbytes: txn.vbytes,
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
outputs: txn.outputs,
|
outputs: txn.outputs,
|
||||||
@ -163,27 +165,35 @@ defmodule BitcoinStream.Protocol.Transaction do
|
|||||||
:error
|
:error
|
||||||
end
|
end
|
||||||
|
|
||||||
defp inflate_inputs([], inflated, total, _fail_fast) do
|
defp inflate_inputs([], inflated, total, _fail_fast, false) do
|
||||||
{:ok, inflated, total}
|
{:ok, inflated, total}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp inflate_inputs([next_chunk | rest], inflated, total, fail_fast) do
|
defp inflate_inputs([], inflated, total, _fail_fast, true) do
|
||||||
|
{:failed, inflated, 0}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp inflate_inputs([next_chunk | rest], inflated, total, fail_fast, failed) do
|
||||||
|
if (failed) do
|
||||||
|
inflate_inputs(rest, inflated ++ next_chunk, total, fail_fast, true)
|
||||||
|
else
|
||||||
case inflate_batch(next_chunk, fail_fast) do
|
case inflate_batch(next_chunk, fail_fast) do
|
||||||
{:ok, inflated_chunk, chunk_total} ->
|
{:ok, inflated_chunk, chunk_total} ->
|
||||||
inflate_inputs(rest, inflated ++ inflated_chunk, total + chunk_total, fail_fast)
|
inflate_inputs(rest, inflated ++ inflated_chunk, total + chunk_total, fail_fast, false)
|
||||||
_ ->
|
_ ->
|
||||||
{:failed, inflated ++ next_chunk ++ rest, 0}
|
inflate_inputs(rest, inflated ++ next_chunk, total, fail_fast, true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def inflate_inputs([], nil, _fail_fast) do
|
def inflate_inputs([], nil, _fail_fast, _failed) do
|
||||||
{ :failed, nil, 0 }
|
{ :failed, nil, 0 }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Retrieves cached inputs if available,
|
# Retrieves cached inputs if available,
|
||||||
# otherwise inflates inputs in batches of up to 100
|
# otherwise inflates inputs in batches of up to 100
|
||||||
def inflate_inputs(_txid, inputs, fail_fast) do
|
def inflate_inputs(_txid, inputs, fail_fast) do
|
||||||
inflate_inputs(Enum.chunk_every(inputs, 100), [], 0, fail_fast)
|
inflate_inputs(Enum.chunk_every(inputs, 50), [], 0, fail_fast, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -4,7 +4,7 @@ defmodule BitcoinStream.MixProject do
|
|||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :bitcoin_stream,
|
app: :bitcoin_stream,
|
||||||
version: "2.3.1",
|
version: "2.3.2",
|
||||||
elixir: "~> 1.10",
|
elixir: "~> 1.10",
|
||||||
start_permanent: Mix.env() == :prod,
|
start_permanent: Mix.env() == :prod,
|
||||||
deps: deps(),
|
deps: deps(),
|
||||||
|
Loading…
Reference in New Issue
Block a user