diff --git a/client/package.json b/client/package.json index 2d268fb..211e9d4 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "bitfeed-client", - "version": "2.3.1", + "version": "2.3.2", "scripts": { "build": "rollup -c", "dev": "rollup -c -w", diff --git a/client/src/components/BlockInfo.svelte b/client/src/components/BlockInfo.svelte index 9625d98..a7ddce2 100644 --- a/client/src/components/BlockInfo.svelte +++ b/client/src/components/BlockInfo.svelte @@ -359,7 +359,7 @@
Fee rate: { numberFormat.format(tx.feerate.toFixed(2)) } sats/vbyte
Fee: { numberFormat.format(tx.fee) } sats
+ {:else if !tx.coinbase && tx.fee == null} +Fee rate: unavailable
+Fee: unavailable
{/if}Total value: { formatBTC(tx.value) } diff --git a/client/src/controllers/TxController.js b/client/src/controllers/TxController.js index 2cb6b3f..4f796bd 100644 --- a/client/src/controllers/TxController.js +++ b/client/src/controllers/TxController.js @@ -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() diff --git a/client/src/models/BitcoinTx.js b/client/src/models/BitcoinTx.js index 5a340bb..340916e 100644 --- a/client/src/models/BitcoinTx.js +++ b/client/src/models/BitcoinTx.js @@ -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 } diff --git a/server/lib/mempool.ex b/server/lib/mempool.ex index 928bf4e..8faade9 100644 --- a/server/lib/mempool.ex +++ b/server/lib/mempool.ex @@ -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 diff --git a/server/lib/protocol/transaction.ex b/server/lib/protocol/transaction.ex index a21d33c..914f066 100644 --- a/server/lib/protocol/transaction.ex +++ b/server/lib/protocol/transaction.ex @@ -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 diff --git a/server/mix.exs b/server/mix.exs index 0a2e071..23bec32 100644 --- a/server/mix.exs +++ b/server/mix.exs @@ -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(),