Skip to content

Commit

Permalink
feat: transactions live sync (#466)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukeromanowicz authored Aug 24, 2023
1 parent 3e33b8e commit ec703ce
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 13 deletions.
43 changes: 36 additions & 7 deletions src/pages/transactions/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
</template>
</page-header>

<template v-if="!isLoading">
<transaction-general-panel
v-if="transactionDetails"
class="transaction-details__panel"
:transaction-details="transactionDetails"/>
<loader-panel
v-if="isLoading"
class="transaction-details__panel"/>
<transaction-general-panel
v-else-if="transactionDetails"
class="transaction-details__panel"
:transaction-details="transactionDetails"/>

<template v-if="!isSyncing">
<transaction-type-panel
v-if="transactionTypeData"
class="transaction-details__panel"
Expand All @@ -32,9 +35,11 @@

<script setup>
import { storeToRefs } from 'pinia'
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'
import TransactionGeneralPanel from '@/components/TransactionGeneralPanel'
import PageHeader from '@/components/PageHeader'
import { useTransactionDetailsStore } from '@/stores/transactionDetails'
import { useWebSocket } from '@/stores/webSocket'
import { transactionsHints } from '@/utils/hints/transactionsHints'
import TransactionTypePanel from '@/components/TransactionTypePanel'
import TransactionPointersPanel from '@/components/TransactionPointersPanel'
Expand All @@ -44,11 +49,17 @@ const {
transactionDetails,
transactionTypeData,
} = storeToRefs(transactionDetailsStore)
const { fetchTransactionDetails } = transactionDetailsStore
const {
fetchTransactionDetails,
} = transactionDetailsStore
const route = useRoute()
const { subscribedTransactionId } = storeToRefs(useWebSocket())
const { isLoading } = useLoading()
await fetchTransactionDetails(route.params.id)
const isSyncing = computed(() => isLoading.value || !transactionTypeData.value)
try {
await fetchTransactionDetails(route.params.id)
} catch (error) {
Expand All @@ -64,6 +75,24 @@ try {
throw error
}
if (process.client && !transactionTypeData.value) {
subscribedTransactionId.value = route.params.id
onBeforeRouteUpdate(
(_to, _from, next) => {
subscribedTransactionId.value = null
next()
},
)
onBeforeRouteLeave(
(_to, _from, next) => {
subscribedTransactionId.value = null
next()
},
)
}
</script>
<style scoped>
Expand Down
13 changes: 8 additions & 5 deletions src/stores/transactionDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ export const useTransactionDetailsStore = defineStore('transactionDetails', () =
}

async function fetchTransactionTypeData(transactionId) {
const isCurrentKeyblock = blockHeight.value - rawTransactionDetails.value.blockHeight === 0

if (!isCurrentKeyblock) {
try {
const { data: transactionData } = await axios.get(`${MIDDLEWARE_URL}/v2/txs/${transactionId}`)

if (transactionData.tx.channelId) {
Expand All @@ -50,8 +48,8 @@ export const useTransactionDetailsStore = defineStore('transactionDetails', () =
}

transactionTypeData.value = transactionData.tx
} else {
transactionTypeData.value = rawTransactionDetails.value.tx
} catch {
transactionTypeData.value = null
}
}

Expand All @@ -70,11 +68,16 @@ export const useTransactionDetailsStore = defineStore('transactionDetails', () =
transactionTypeData.value = null
}

function updateTransactionTypeData(websocketMessage) {
transactionTypeData.value = websocketMessage.tx
}

return {
contractId,
transactionDetails,
transactionTypeData,
fetchTransactionDetails,
fetchContractIdByAccountId,
updateTransactionTypeData,
}
})
29 changes: 28 additions & 1 deletion src/stores/webSocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import { defineStore } from 'pinia'
import { useRuntimeConfig } from 'nuxt/app'
import camelcaseKeysDeep from 'camelcase-keys-deep'
import { useRecentBlocksStore } from '@/stores/recentBlocks'
import { useTransactionDetailsStore } from '@/stores/transactionDetails'

export const useWebSocket = defineStore('webSocket', () => {
const { WEBSOCKET_URL } = useRuntimeConfig().public
const { processSocketMessage } = useRecentBlocksStore()
const { updateTransactionTypeData } = useTransactionDetailsStore()

const webSocket = shallowRef()
const isSubscribedToKeyblockDetails = ref(false)
const subscribedTransactionId = ref(null)

watch(isSubscribedToKeyblockDetails, newValue => {
if (!webSocket.value || webSocket.value.readyState !== WebSocket.OPEN) {
Expand All @@ -22,6 +25,18 @@ export const useWebSocket = defineStore('webSocket', () => {
}
})

watch(subscribedTransactionId, (newTransactionId, oldTransactionId) => {
if (!webSocket.value || webSocket.value.readyState !== WebSocket.OPEN) {
return
}

if (newTransactionId) {
webSocket.value.send(`{"op":"Subscribe", "source": "mdw", "payload": "${newTransactionId}"}`)
} else {
webSocket.value.send(`{"op":"Unsubscribe", "source": "mdw", "payload": "${oldTransactionId}"}`)
}
})

function initializeWebSocket() {
webSocket.value = new WebSocket(WEBSOCKET_URL)

Expand All @@ -42,6 +57,10 @@ export const useWebSocket = defineStore('webSocket', () => {
webSocket.value.send('{"op":"Subscribe", "source": "node", "payload": "MicroBlocks"}')
}

if (subscribedTransactionId.value) {
webSocket.value.send(`{"op":"Subscribe", "source": "node", "payload": "${subscribedTransactionId.value}"}`)
}

webSocket.value.onmessage = event => {
processWebSocketData(event.data)
}
Expand All @@ -52,11 +71,19 @@ export const useWebSocket = defineStore('webSocket', () => {
return
}
const parsedData = camelcaseKeysDeep(JSON.parse(data))
await processSocketMessage(parsedData)
const isSpecificEntityMessage = parsedData.subscription === 'Object'
const isSubscribedTransactionMessage = parsedData.payload?.hash === subscribedTransactionId.value

if (isSpecificEntityMessage && isSubscribedTransactionMessage) {
updateTransactionTypeData(parsedData.payload)
} else {
await processSocketMessage(parsedData)
}
}

return {
isSubscribedToKeyblockDetails,
subscribedTransactionId,
initializeWebSocket,
}
})

0 comments on commit ec703ce

Please sign in to comment.