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