From a8a945e77ec3787953378b6dcdccd73ea0c0836c Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 28 Apr 2022 19:45:07 -0600 Subject: [PATCH] Defer output spend loading --- .../src/components/TransactionOverlay.svelte | 59 +++++++++++++++++-- client/src/controllers/TxController.js | 2 - client/src/utils/search.js | 14 ++++- server/lib/router.ex | 2 +- 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/client/src/components/TransactionOverlay.svelte b/client/src/components/TransactionOverlay.svelte index 4d6db95..21a288b 100644 --- a/client/src/components/TransactionOverlay.svelte +++ b/client/src/components/TransactionOverlay.svelte @@ -8,7 +8,7 @@ import { formatCurrency } from '../utils/fx.js' import { hlToHex, mixColor, teal, purple } from '../utils/color.js' import { SPKToAddress } from '../utils/encodings.js' import api from '../utils/api.js' -import { searchTx, searchBlockHash, searchBlockHeight } from '../utils/search.js' +import { searchTx, searchBlockHash, searchBlockHeight, fetchSpends } from '../utils/search.js' import { fade } from 'svelte/transition' function onClose () { @@ -148,6 +148,23 @@ $: { } } +let spends +let loadingSpends = false +$: { + if ($detailTx && $detailTx.id) { + spends = null + loadSpends($detailTx.id) + } else { + spends = null + } +} + +async function loadSpends(txid, reload = false) { + if (!reload) loadingSpends = true + spends = await fetchSpends(txid) + loadingSpends = false +} + function calcSankeyLines(inputs, outputs, fee, value, totalHeight, svgWidth, flowWeight) { const total = fee + value const mergeOffset = (totalHeight - flowWeight) / 2 @@ -269,10 +286,10 @@ async function goToInput(e, input) { loading.decrement() } -async function goToOutput(e, output) { +async function goToSpend(e, spend) { e.preventDefault() loading.increment() - await searchTx(output.spend.txid, output.spend.vin) + await searchTx(spend.txid, spend.vin) loading.decrement() } @@ -475,7 +492,7 @@ async function goToBlock(e) { stroke-linejoin: miter; fill: white; fill-opacity: 0; - transition: fill-opacity 300ms; + transition: fill-opacity 300ms, stroke-opacity 300ms; } &.right { @@ -488,6 +505,16 @@ async function goToBlock(e) { fill-opacity: 1; } } + + &.loading { + .chevron .outline { + stroke-opacity: 0; + animation-name: svgpulse; + animation-delay: 500ms; + animation-duration: 2s; + animation-iteration-count: infinite; + } + } } } @@ -563,6 +590,20 @@ async function goToBlock(e) { } } } + + @keyframes svgpulse { + 0% { + fill-opacity: 0; + } + + 50% { + fill-opacity: 30% + } + + 100% { + fill-opacity: 0; + } + } @@ -701,8 +742,14 @@ async function goToBlock(e) {

{$detailTx.outputs.length} output{$detailTx.outputs.length > 1 ? 's' : ''} {#if $detailTx.fee}+ fee{/if}

{#each outputs as output}
clickItem(output)}> - {#if output.spend} - goToOutput(e, output)} class="put-link" transition:fade|local={{ duration: 200 }}> + {#if loadingSpends} + + + + + + {:else if spends[output.index]} + goToSpend(e, spends[output.index])} class="put-link" in:fade|local={{ duration: 200 }}> diff --git a/client/src/controllers/TxController.js b/client/src/controllers/TxController.js index ff018c7..67bc83c 100644 --- a/client/src/controllers/TxController.js +++ b/client/src/controllers/TxController.js @@ -422,8 +422,6 @@ export default class TxController { await searchTx(selected.id) loading.decrement() } else { - const spendResult = await fetchSpends(selected.id) - if (spendResult) selected = addSpends(selected, spendResult) urlPath.set(`/tx/${selected.id}`) detailTx.set(selected) overlay.set('tx') diff --git a/client/src/utils/search.js b/client/src/utils/search.js index 1027c22..4e343fb 100644 --- a/client/src/utils/search.js +++ b/client/src/utils/search.js @@ -175,7 +175,17 @@ async function fetchSpends (txid) { }) if (!response) throw new Error('null response') if (response.status == 200) { - return response.json() + const result = await response.json() + return result.map(output => { + if (output) { + return { + txid: output[0], + vin: output[1], + } + } else { + return null + } + }) } else { return null } @@ -207,9 +217,7 @@ export async function searchTx (txid, input, output) { } try { let searchResult = await fetchTx(txid) - const spendResult = await fetchSpends(txid) if (searchResult) { - if (spendResult) searchResult = addSpends(searchResult, spendResult) selectedTx.set(searchResult) detailTx.set(searchResult) overlay.set('tx') diff --git a/server/lib/router.ex b/server/lib/router.ex index 62cab64..d93606c 100644 --- a/server/lib/router.ex +++ b/server/lib/router.ex @@ -50,7 +50,7 @@ defmodule BitcoinStream.Router do match "/api/tx/:hash" do case get_tx(hash) do {:ok, tx} -> - put_resp_header(conn, "cache-control", "public, max-age=60, immutable") + put_resp_header(conn, "cache-control", "public, max-age=300, immutable") |> send_resp(200, tx) _ -> Logger.debug("Error getting tx hash");