listen to all contract events with alerts

This commit is contained in:
Eric 2024-06-04 17:38:13 +10:00
parent 1cfc90a1bf
commit 62b25b46ee
No known key found for this signature in database
14 changed files with 716 additions and 253 deletions

2
.gitignore vendored
View File

@ -29,3 +29,5 @@ coverage
*.tsbuildinfo
*.key
codex-setup
codex-data

View File

@ -1,36 +1,186 @@
<script setup>
import { onMounted } from 'vue'
import { useEventsStore } from './stores/events'
import { onMounted, ref } from 'vue'
import { useEventsStore } from '@/stores/events'
import { RouterView } from 'vue-router'
import Balance from './components/Balance.vue'
import BlockNumber from './components/BlockNumber.vue'
import AppNav from './components/AppNav.vue'
import Balance from '@/components/Balance.vue'
import BlockNumber from '@/components/BlockNumber.vue'
import AppNav from '@/components/AppNav.vue'
import ContractEventAlerts from '@/components/ContractEventAlerts.vue'
import { initDrawers } from 'flowbite'
const alerts = ref([])
const id = ref(0)
const eventsStore = useEventsStore()
function addAlert(type, event, state) {
alerts.value.push({
id: event + '123456' + (1234567890 + ++id.value),
type,
event,
blockNumber: 123456,
requestId: 1234567890 + ++id.value,
state
})
}
function addSlotAlert(type, event, state) {
alerts.value.push({
id: event + '123456' + (1234567890 + ++id.value),
type,
event,
blockNumber: 123456,
requestId: 1234567890 + ++id.value,
slotIdx: 1,
state
})
}
onMounted(async () => {
initDrawers()
await eventsStore.fetchPastEvents()
function onStorageRequested(blockNumber, requestId, request, state) {
alert('storage requested')
alerts.value.push({
type: 'info',
event: 'StorageRequested',
blockNumber,
requestId,
state
})
}
await eventsStore.listenForNewEvents(onStorageRequested)
function onRequestFulfilled(blockNumber, requestId) {
alerts.value.push({
type: 'success',
event: 'RequestStarted',
blockNumber,
requestId,
state: 'Fulfilled'
})
}
function onRequestCancelled(blockNumber, requestId) {
alerts.value.push({
type: 'danger',
event: 'RequestCancelled',
blockNumber,
requestId,
state: 'Cancelled'
})
}
function onRequestFailed(blockNumber, requestId) {
alerts.value.push({
type: 'danger',
event: 'RequestFailed',
blockNumber,
requestId,
state: 'Failed'
})
}
function onRequestFinished(blockNumber, requestId) {
alerts.value.push({
type: 'info',
event: 'RequestFinished',
blockNumber,
requestId,
state: 'Finished'
})
}
function onSlotFreed(blockNumber, requestId, slotIdx) {
alerts.value.push({
type: 'warning',
event: 'SlotFreed',
blockNumber,
requestId,
slotIdx,
state: 'Freed'
})
}
function onSlotFilled(blockNumber, requestId, slotIdx) {
alerts.value.push({
type: 'info',
event: 'SlotFilled',
blockNumber,
requestId,
slotIdx,
state: 'Filled'
})
}
await eventsStore.listenForNewEvents(
onStorageRequested,
onRequestFulfilled,
onRequestCancelled,
onRequestFailed,
onRequestFinished,
onSlotFreed,
onSlotFilled
)
})
</script>
<template>
<header>
<AppNav />
</header>
<RouterView class="max-w-screen-xl mx-auto" />
<footer>
<Balance />
<BlockNumber />
</footer>
<button
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
type="button"
@click="addAlert('success', 'RequestFulfilled', 'Fulfilled')"
>
success alert
</button>
<button
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
type="button"
@click="addAlert('warning', 'SlotFreed', 'Freed')"
>
warning alert
</button>
<button
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
type="button"
@click="addAlert('danger', 'RequestFailed', 'Failed')"
>
danger alert
</button>
<button
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
type="button"
@click="addAlert('info', 'RequestFinished', 'Finished')"
>
info alert
</button>
<button
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
type="button"
@click="addSlotAlert('info', 'SlotFreed', 'Freed')"
>
info alert - Slot
</button>
<div class="flex flex-col h-screen min-w-96">
<header class="w-full text-center border-b p-4">
<AppNav />
</header>
<main>
<div class="mx-auto max-w-screen-xl">
<ContractEventAlerts v-model="alerts"></ContractEventAlerts>
<RouterView class="flex-auto p-4" />
</div>
</main>
<footer class="w-full text-center border-t p-4 mt-4">
<Balance />
<BlockNumber />
</footer>
</div>
</template>
<style scoped>
header,
footer,
main {
@apply min-w-96;
}
header,
footer {
@apply bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-600;
}
</style>
<!-- <style scoped>
header {
line-height: 1.5;

View File

@ -1,10 +1,13 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_274_4287)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.7001 32.7386C19.7705 32.7792 19.8502 32.8001 19.9306 32.8001C20.0111 32.8001 20.188 32.7225 20.188 32.7225L30.85 26.581C30.8555 26.5783 30.8632 26.5744 30.8706 26.5701C30.942 26.5295 31.0002 26.4707 31.0406 26.4008C31.0819 26.3302 31.1036 26.25 31.1036 26.1685C31.1036 26.1588 31.1032 26.1499 31.1028 26.1432V13.8597C31.1036 13.8486 31.1036 13.8387 31.1036 13.8337L31.1036 13.8324C31.1036 13.7507 31.0818 13.671 31.0413 13.6009C31.0008 13.5302 30.9421 13.4718 30.872 13.4313C30.8644 13.4268 30.8564 13.4225 30.8484 13.4186L20.1868 7.27756C20.179 7.27228 20.1714 7.26767 20.165 7.26389L20.1644 7.26354C20.0937 7.22255 20.0136 7.20151 19.9325 7.20151H19.9306C19.8495 7.20151 19.77 7.22295 19.701 7.26233C19.692 7.26733 19.6837 7.27257 19.6762 7.27763L9.01204 13.4202C9.00655 13.4229 8.99886 13.4269 8.99144 13.4311C8.92049 13.4717 8.86173 13.531 8.82123 13.6011C8.78067 13.6712 8.75879 13.7509 8.75879 13.8327C8.75879 13.8425 8.75919 13.8513 8.75956 13.858V26.1419C8.75876 26.153 8.75878 26.1629 8.75879 26.1679L8.75879 26.1692C8.75879 26.2508 8.78058 26.3312 8.82193 26.4018C8.86238 26.4712 8.92065 26.5296 8.98909 26.5693L8.99047 26.5701L8.99187 26.5708C9.00023 26.5754 9.00781 26.5793 9.01357 26.5822L19.6768 32.7241C19.6818 32.7275 19.6906 32.7332 19.7001 32.7386ZM30.8023 26.4503C30.7969 26.4533 30.7908 26.4564 30.7847 26.4594C30.788 26.4578 30.7915 26.4561 30.7946 26.4544C30.7973 26.4531 30.7999 26.4517 30.8023 26.4503ZM30.9649 26.1472C30.9651 26.1495 30.9652 26.152 30.9653 26.1545C30.9655 26.1589 30.9657 26.1636 30.9657 26.1685C30.9657 26.167 30.9657 26.1655 30.9656 26.164C30.9655 26.158 30.9652 26.1523 30.9649 26.1472ZM20.3983 26.9771L24.3592 29.2549L20.3951 31.538L20.3983 26.9771ZM15.5034 29.2548L19.4645 26.9769L19.4676 31.538L15.5034 29.2548ZM25.7528 23.8924L29.7137 26.1701L25.7497 28.4532L25.7528 23.8924ZM20.3984 25.3628V20.8084L24.3514 23.0856L20.3984 25.3628ZM15.0439 22.2784V17.724L18.9969 20.0012L15.0439 22.2784ZM20.3984 19.1932V14.6388L24.3514 16.916L20.3984 19.1932ZM19.4649 13.0247L15.5038 10.7468L19.468 8.4636L19.4649 13.0247ZM10.1491 26.1701L14.1131 28.4532L14.11 23.8921L10.1491 26.1701ZM24.8194 23.8927L24.8225 28.4527L20.8658 26.1705L24.8194 23.8927ZM15.0438 23.8927L15.0406 28.4527L18.9974 26.1705L15.0438 23.8927ZM26.2198 23.0856L30.178 20.8025V25.3687L26.2198 23.0856ZM9.68483 20.8025V25.3687L13.643 23.0856L9.68483 20.8025ZM15.5111 23.085L19.4644 25.3624V20.8076L15.5111 23.085ZM29.7125 20.0004L25.7529 17.7227V22.2781L29.7125 20.0004ZM10.1503 20.0008L14.1099 22.2785V17.7231L10.1503 20.0008ZM24.8189 17.7232V22.278L20.8656 20.0006L24.8189 17.7232ZM30.178 14.6329V19.1991L26.2198 16.916L30.178 14.6329ZM13.643 16.916L9.68483 19.1991V14.6329L13.643 16.916ZM19.4644 14.6384V19.1928L15.5114 16.9156L19.4644 14.6384ZM29.7141 13.8315L25.7497 11.5482L25.7528 16.1095L29.7141 13.8315ZM14.1135 11.5484L14.1104 16.1095L10.1491 13.8315L14.1135 11.5484ZM24.8225 11.5489L24.8194 16.1089L20.8658 13.8311L24.8225 11.5489ZM18.9974 13.8311L15.0438 16.1089L15.0406 11.5489L18.9974 13.8311ZM24.3596 10.7467L20.3951 8.46359L20.3983 13.0247L24.3596 10.7467Z" fill="black"/>
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="40" height="40" viewBox="0 0 500 500" xml:space="preserve">
<desc>Created with Fabric.js 5.3.0</desc>
<defs>
<clipPath id="clip0_274_4287">
<rect width="40" height="40" fill="white"/>
</clipPath>
</defs>
</svg>
<g transform="matrix(18.7905006391 0 0 18.7905006391 250 250)" id="PNGEf3DUMBcP031ZM94Ql" clip-path="url(#CLIPPATH_11)" >
<clipPath id="CLIPPATH_11" >
<rect id="clip0_274_4287" x="-20" y="-20" rx="0" ry="0" width="40" height="40" />
</clipPath>
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: evenodd; opacity: 1;" transform=" translate(-19.9311937003, -20.000805)" d="M 19.7001 32.7386 C 19.7705 32.7792 19.8502 32.8001 19.9306 32.8001 C 20.0111 32.8001 20.188 32.7225 20.188 32.7225 L 30.85 26.581 C 30.8555 26.5783 30.8632 26.5744 30.8706 26.5701 C 30.942 26.5295 31.0002 26.4707 31.0406 26.4008 C 31.0819 26.3302 31.1036 26.25 31.1036 26.1685 C 31.1036 26.1588 31.1032 26.1499 31.1028 26.1432 L 31.1028 13.8597 C 31.1036 13.8486 31.1036 13.8387 31.1036 13.8337 L 31.1036 13.8324 C 31.1036 13.7507 31.0818 13.671 31.0413 13.6009 C 31.0008 13.5302 30.9421 13.4718 30.872 13.4313 C 30.8644 13.4268 30.8564 13.4225 30.8484 13.4186 L 20.1868 7.27756 C 20.179 7.27228 20.1714 7.26767 20.165 7.26389 L 20.1644 7.26354 C 20.0937 7.22255 20.0136 7.20151 19.9325 7.20151 L 19.9306 7.20151 C 19.8495 7.20151 19.77 7.22295 19.701 7.26233 C 19.692 7.26733 19.6837 7.27257 19.6762 7.27763 L 9.01204 13.4202 C 9.00655 13.4229 8.99886 13.4269 8.99144 13.4311 C 8.92049 13.4717 8.86173 13.531 8.82123 13.6011 C 8.78067 13.6712 8.75879 13.7509 8.75879 13.8327 C 8.75879 13.8425 8.75919 13.8513 8.75956 13.858 L 8.75956 26.1419 C 8.75876 26.153 8.75878 26.1629 8.75879 26.1679 L 8.75879 26.1692 C 8.75879 26.2508 8.78058 26.3312 8.82193 26.4018 C 8.86238 26.4712 8.92065 26.5296 8.98909 26.5693 L 8.99047 26.5701 L 8.99187 26.5708 C 9.00023 26.5754 9.00781 26.5793 9.01357 26.5822 L 19.6768 32.7241 C 19.6818 32.7275 19.6906 32.7332 19.7001 32.7386 Z M 30.8023 26.4503 C 30.7969 26.4533 30.7908 26.4564 30.7847 26.4594 C 30.788 26.4578 30.7915 26.4561 30.7946 26.4544 C 30.7973 26.4531 30.7999 26.4517 30.8023 26.4503 Z M 30.9649 26.1472 C 30.9651 26.1495 30.9652 26.152 30.9653 26.1545 C 30.9655 26.1589 30.9657 26.1636 30.9657 26.1685 C 30.9657 26.167 30.9657 26.1655 30.9656 26.164 C 30.9655 26.158 30.9652 26.1523 30.9649 26.1472 Z M 20.3983 26.9771 L 24.3592 29.2549 L 20.3951 31.538 L 20.3983 26.9771 Z M 15.5034 29.2548 L 19.4645 26.9769 L 19.4676 31.538 L 15.5034 29.2548 Z M 25.7528 23.8924 L 29.7137 26.1701 L 25.7497 28.4532 L 25.7528 23.8924 Z M 20.3984 25.3628 L 20.3984 20.8084 L 24.3514 23.0856 L 20.3984 25.3628 Z M 15.0439 22.2784 L 15.0439 17.724 L 18.9969 20.0012 L 15.0439 22.2784 Z M 20.3984 19.1932 L 20.3984 14.6388 L 24.3514 16.916 L 20.3984 19.1932 Z M 19.4649 13.0247 L 15.5038 10.7468 L 19.468 8.4636 L 19.4649 13.0247 Z M 10.1491 26.1701 L 14.1131 28.4532 L 14.11 23.8921 L 10.1491 26.1701 Z M 24.8194 23.8927 L 24.8225 28.4527 L 20.8658 26.1705 L 24.8194 23.8927 Z M 15.0438 23.8927 L 15.0406 28.4527 L 18.9974 26.1705 L 15.0438 23.8927 Z M 26.2198 23.0856 L 30.178 20.8025 L 30.178 25.3687 L 26.2198 23.0856 Z M 9.68483 20.8025 L 9.68483 25.3687 L 13.643 23.0856 L 9.68483 20.8025 Z M 15.5111 23.085 L 19.4644 25.3624 L 19.4644 20.8076 L 15.5111 23.085 Z M 29.7125 20.0004 L 25.7529 17.7227 L 25.7529 22.2781 L 29.7125 20.0004 Z M 10.1503 20.0008 L 14.1099 22.2785 L 14.1099 17.7231 L 10.1503 20.0008 Z M 24.8189 17.7232 L 24.8189 22.278 L 20.8656 20.0006 L 24.8189 17.7232 Z M 30.178 14.6329 L 30.178 19.1991 L 26.2198 16.916 L 30.178 14.6329 Z M 13.643 16.916 L 9.68483 19.1991 L 9.68483 14.6329 L 13.643 16.916 Z M 19.4644 14.6384 L 19.4644 19.1928 L 15.5114 16.9156 L 19.4644 14.6384 Z M 29.7141 13.8315 L 25.7497 11.5482 L 25.7528 16.1095 L 29.7141 13.8315 Z M 14.1135 11.5484 L 14.1104 16.1095 L 10.1491 13.8315 L 14.1135 11.5484 Z M 24.8225 11.5489 L 24.8194 16.1089 L 20.8658 13.8311 L 24.8225 11.5489 Z M 18.9974 13.8311 L 15.0438 16.1089 L 15.0406 11.5489 L 18.9974 13.8311 Z M 24.3596 10.7467 L 20.3951 8.46359 L 20.3983 13.0247 L 24.3596 10.7467 Z" stroke-linecap="round" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,10 +1,13 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_291_2793)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.7001 32.7386C19.7705 32.7792 19.8502 32.8001 19.9306 32.8001C20.0111 32.8001 20.188 32.7226 20.188 32.7226L30.85 26.581C30.8555 26.5783 30.8632 26.5744 30.8706 26.5702C30.942 26.5296 31.0002 26.4707 31.0406 26.4008C31.0819 26.3303 31.1036 26.25 31.1036 26.1685C31.1036 26.1588 31.1032 26.1499 31.1028 26.1432V13.8597C31.1036 13.8486 31.1036 13.8387 31.1036 13.8337L31.1036 13.8324C31.1036 13.7507 31.0818 13.671 31.0413 13.6009C31.0008 13.5302 30.9421 13.4718 30.872 13.4313C30.8644 13.4269 30.8564 13.4225 30.8484 13.4186L20.1868 7.27759C20.179 7.27231 20.1714 7.2677 20.165 7.26392L20.1644 7.26357C20.0937 7.22258 20.0136 7.20154 19.9325 7.20154H19.9306C19.8495 7.20154 19.77 7.22298 19.701 7.26236C19.692 7.26736 19.6837 7.2726 19.6762 7.27766L9.01204 13.4202C9.00655 13.423 8.99886 13.4269 8.99144 13.4311C8.92049 13.4717 8.86173 13.5311 8.82123 13.6011C8.78067 13.6712 8.75879 13.751 8.75879 13.8328C8.75879 13.8425 8.75919 13.8514 8.75956 13.858V26.1419C8.75876 26.153 8.75878 26.1629 8.75879 26.1679L8.75879 26.1693C8.75879 26.2509 8.78058 26.3312 8.82193 26.4019C8.86238 26.4712 8.92065 26.5297 8.98909 26.5693L8.99047 26.5701L8.99187 26.5709C9.00023 26.5755 9.00781 26.5793 9.01357 26.5822L19.6768 32.7242C19.6818 32.7275 19.6906 32.7333 19.7001 32.7386ZM30.8023 26.4503C30.7969 26.4534 30.7908 26.4564 30.7847 26.4595C30.788 26.4578 30.7915 26.4561 30.7946 26.4545C30.7973 26.4531 30.7999 26.4517 30.8023 26.4503ZM30.9649 26.1472C30.9651 26.1495 30.9652 26.152 30.9653 26.1545C30.9655 26.159 30.9657 26.1637 30.9657 26.1685C30.9657 26.167 30.9657 26.1655 30.9656 26.164C30.9655 26.1581 30.9652 26.1524 30.9649 26.1472ZM20.3983 26.9772L24.3592 29.2549L20.3951 31.538L20.3983 26.9772ZM15.5034 29.2548L19.4645 26.977L19.4676 31.538L15.5034 29.2548ZM25.7528 23.8924L29.7137 26.1701L25.7497 28.4532L25.7528 23.8924ZM20.3984 25.3628V20.8084L24.3514 23.0856L20.3984 25.3628ZM15.0439 22.2784V17.724L18.9969 20.0012L15.0439 22.2784ZM20.3984 19.1932V14.6389L24.3514 16.916L20.3984 19.1932ZM19.4649 13.0247L15.5038 10.7468L19.468 8.46363L19.4649 13.0247ZM10.1491 26.1701L14.1131 28.4532L14.11 23.8922L10.1491 26.1701ZM24.8194 23.8928L24.8225 28.4527L20.8658 26.1705L24.8194 23.8928ZM15.0438 23.8928L15.0406 28.4527L18.9974 26.1705L15.0438 23.8928ZM26.2198 23.0856L30.178 20.8025V25.3687L26.2198 23.0856ZM9.68483 20.8025V25.3687L13.643 23.0856L9.68483 20.8025ZM15.5111 23.085L19.4644 25.3624V20.8077L15.5111 23.085ZM29.7125 20.0004L25.7529 17.7227V22.2782L29.7125 20.0004ZM10.1503 20.0008L14.1099 22.2786V17.7231L10.1503 20.0008ZM24.8189 17.7233V22.278L20.8656 20.0006L24.8189 17.7233ZM30.178 14.6329V19.1992L26.2198 16.916L30.178 14.6329ZM13.643 16.916L9.68483 19.1992V14.6329L13.643 16.916ZM19.4644 14.6385V19.1928L15.5114 16.9157L19.4644 14.6385ZM29.7141 13.8315L25.7497 11.5482L25.7528 16.1095L29.7141 13.8315ZM14.1135 11.5484L14.1104 16.1095L10.1491 13.8315L14.1135 11.5484ZM24.8225 11.549L24.8194 16.1089L20.8658 13.8312L24.8225 11.549ZM18.9974 13.8312L15.0438 16.1089L15.0406 11.549L18.9974 13.8312ZM24.3596 10.7467L20.3951 8.46362L20.3983 13.0247L24.3596 10.7467Z" fill="white"/>
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="40" height="40" viewBox="0 0 40 40" xml:space="preserve">
<desc>Created with Fabric.js 5.3.0</desc>
<defs>
<clipPath id="clip0_291_2793">
<rect width="40" height="40" fill="white"/>
</clipPath>
</defs>
</svg>
<g transform="matrix(1.5013909761 0 0 1.5013930471 19.9928088364 19.9918065482)" id="YHAMhE6BLCgysRYRdkMJc" clip-path="url(#CLIPPATH_2)" >
<clipPath id="CLIPPATH_2" >
<rect id="clip0_291_2793" x="-20" y="-20" rx="0" ry="0" width="40" height="40" />
</clipPath>
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: evenodd; opacity: 1;" transform=" translate(-19.9311937003, -20.00082)" d="M 19.7001 32.7386 C 19.7705 32.7792 19.8502 32.8001 19.9306 32.8001 C 20.0111 32.8001 20.188 32.7226 20.188 32.7226 L 30.85 26.581 C 30.8555 26.5783 30.8632 26.5744 30.8706 26.5702 C 30.942 26.5296 31.0002 26.4707 31.0406 26.4008 C 31.0819 26.3303 31.1036 26.25 31.1036 26.1685 C 31.1036 26.1588 31.1032 26.1499 31.1028 26.1432 L 31.1028 13.8597 C 31.1036 13.8486 31.1036 13.8387 31.1036 13.8337 L 31.1036 13.8324 C 31.1036 13.7507 31.0818 13.671 31.0413 13.6009 C 31.0008 13.5302 30.9421 13.4718 30.872 13.4313 C 30.8644 13.4269 30.8564 13.4225 30.8484 13.4186 L 20.1868 7.27759 C 20.179 7.27231 20.1714 7.2677 20.165 7.26392 L 20.1644 7.26357 C 20.0937 7.22258 20.0136 7.20154 19.9325 7.20154 L 19.9306 7.20154 C 19.8495 7.20154 19.77 7.22298 19.701 7.26236 C 19.692 7.26736 19.6837 7.2726 19.6762 7.27766 L 9.01204 13.4202 C 9.00655 13.423 8.99886 13.4269 8.99144 13.4311 C 8.92049 13.4717 8.86173 13.5311 8.82123 13.6011 C 8.78067 13.6712 8.75879 13.751 8.75879 13.8328 C 8.75879 13.8425 8.75919 13.8514 8.75956 13.858 L 8.75956 26.1419 C 8.75876 26.153 8.75878 26.1629 8.75879 26.1679 L 8.75879 26.1693 C 8.75879 26.2509 8.78058 26.3312 8.82193 26.4019 C 8.86238 26.4712 8.92065 26.5297 8.98909 26.5693 L 8.99047 26.5701 L 8.99187 26.5709 C 9.00023 26.5755 9.00781 26.5793 9.01357 26.5822 L 19.6768 32.7242 C 19.6818 32.7275 19.6906 32.7333 19.7001 32.7386 Z M 30.8023 26.4503 C 30.7969 26.4534 30.7908 26.4564 30.7847 26.4595 C 30.788 26.4578 30.7915 26.4561 30.7946 26.4545 C 30.7973 26.4531 30.7999 26.4517 30.8023 26.4503 Z M 30.9649 26.1472 C 30.9651 26.1495 30.9652 26.152 30.9653 26.1545 C 30.9655 26.159 30.9657 26.1637 30.9657 26.1685 C 30.9657 26.167 30.9657 26.1655 30.9656 26.164 C 30.9655 26.1581 30.9652 26.1524 30.9649 26.1472 Z M 20.3983 26.9772 L 24.3592 29.2549 L 20.3951 31.538 L 20.3983 26.9772 Z M 15.5034 29.2548 L 19.4645 26.977 L 19.4676 31.538 L 15.5034 29.2548 Z M 25.7528 23.8924 L 29.7137 26.1701 L 25.7497 28.4532 L 25.7528 23.8924 Z M 20.3984 25.3628 L 20.3984 20.8084 L 24.3514 23.0856 L 20.3984 25.3628 Z M 15.0439 22.2784 L 15.0439 17.724 L 18.9969 20.0012 L 15.0439 22.2784 Z M 20.3984 19.1932 L 20.3984 14.6389 L 24.3514 16.916 L 20.3984 19.1932 Z M 19.4649 13.0247 L 15.5038 10.7468 L 19.468 8.46363 L 19.4649 13.0247 Z M 10.1491 26.1701 L 14.1131 28.4532 L 14.11 23.8922 L 10.1491 26.1701 Z M 24.8194 23.8928 L 24.8225 28.4527 L 20.8658 26.1705 L 24.8194 23.8928 Z M 15.0438 23.8928 L 15.0406 28.4527 L 18.9974 26.1705 L 15.0438 23.8928 Z M 26.2198 23.0856 L 30.178 20.8025 L 30.178 25.3687 L 26.2198 23.0856 Z M 9.68483 20.8025 L 9.68483 25.3687 L 13.643 23.0856 L 9.68483 20.8025 Z M 15.5111 23.085 L 19.4644 25.3624 L 19.4644 20.8077 L 15.5111 23.085 Z M 29.7125 20.0004 L 25.7529 17.7227 L 25.7529 22.2782 L 29.7125 20.0004 Z M 10.1503 20.0008 L 14.1099 22.2786 L 14.1099 17.7231 L 10.1503 20.0008 Z M 24.8189 17.7233 L 24.8189 22.278 L 20.8656 20.0006 L 24.8189 17.7233 Z M 30.178 14.6329 L 30.178 19.1992 L 26.2198 16.916 L 30.178 14.6329 Z M 13.643 16.916 L 9.68483 19.1992 L 9.68483 14.6329 L 13.643 16.916 Z M 19.4644 14.6385 L 19.4644 19.1928 L 15.5114 16.9157 L 19.4644 14.6385 Z M 29.7141 13.8315 L 25.7497 11.5482 L 25.7528 16.1095 L 29.7141 13.8315 Z M 14.1135 11.5484 L 14.1104 16.1095 L 10.1491 13.8315 L 14.1135 11.5484 Z M 24.8225 11.549 L 24.8194 16.1089 L 20.8658 13.8312 L 24.8225 11.549 Z M 18.9974 13.8312 L 15.0438 16.1089 L 15.0406 11.549 L 18.9974 13.8312 Z M 24.3596 10.7467 L 20.3951 8.46362 L 20.3983 13.0247 L 24.3596 10.7467 Z" stroke-linecap="round" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -9,73 +9,71 @@ onMounted(() => {
</script>
<template>
<nav
class="bg-white dark:bg-gray-900 fixed w-full z-20 top-0 start-0 border-b border-gray-200 dark:border-gray-600"
>
<div class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4">
<a href="https://codex.storage/" class="flex items-center space-x-3 rtl:space-x-reverse">
<img src="../assets/logo.svg" class="h-8 hidden dark:inline" alt="Codex Logo" />
<img src="../assets/logo-black.svg" class="h-8 inline dark:hidden" alt="Codex Logo" />
<span class="self-center text-2xl font-semibold whitespace-nowrap dark:text-white"
>Codex</span
>
</a>
<div class="flex md:order-2 space-x-3 md:space-x-0 rtl:space-x-reverse">
<button
type="button"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Instructions
</button>
<button
data-collapse-toggle="navbar-sticky"
type="button"
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
aria-controls="navbar-sticky"
aria-expanded="false"
>
<span class="sr-only">Open main menu</span>
<svg
class="w-5 h-5"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 17 14"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M1 1h15M1 7h15M1 13h15"
/>
</svg>
</button>
</div>
<div
class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1"
id="navbar-sticky"
<nav class="mx-auto max-w-screen-xl flex flex-wrap items-center justify-between">
<!-- <div class=""> -->
<a href="https://codex.storage/" class="flex items-center rtl:space-x-reverse">
<img src="../assets/logo.svg" class="h-8 hidden dark:inline" alt="Codex Logo" />
<img src="../assets/logo-black.svg" class="h-8 inline dark:hidden" alt="Codex Logo" />
<span class="self-center ml-3 text-2xl font-semibold whitespace-nowrap dark:text-white"
>Codex</span
>
<ul
class="flex flex-col p-4 md:p-0 mt-4 font-medium border border-gray-100 rounded-lg bg-gray-50 md:space-x-8 rtl:space-x-reverse md:flex-row md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700"
</a>
<div class="flex md:order-2 space-x-3 md:space-x-0 rtl:space-x-reverse">
<button
type="button"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Instructions
</button>
<button
data-collapse-toggle="navbar-sticky"
type="button"
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
aria-controls="navbar-sticky"
aria-expanded="false"
>
<span class="sr-only">Open main menu</span>
<svg
class="w-5 h-5"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 17 14"
>
<li>
<RouterLink
class="router-link block py-2 px-3 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500"
to="/"
>Requests</RouterLink
>
</li>
<li>
<RouterLink
class="router-link block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 md:dark:hover:text-blue-500 dark:text-white dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
to="/slots"
>Slots</RouterLink
>
</li>
</ul>
</div>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M1 1h15M1 7h15M1 13h15"
/>
</svg>
</button>
</div>
<div
class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1"
id="navbar-sticky"
>
<ul
class="flex flex-col p-4 md:p-0 mt-4 font-medium border border-gray-100 rounded-lg bg-gray-50 md:space-x-8 rtl:space-x-reverse md:flex-row md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700"
>
<li>
<RouterLink
class="router-link block py-2 px-3 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500"
to="/"
>Requests</RouterLink
>
</li>
<li>
<RouterLink
class="router-link block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 md:dark:hover:text-blue-500 dark:text-white dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
to="/slots"
>Slots</RouterLink
>
</li>
</ul>
</div>
<!-- </div> -->
</nav>
</template>
@ -87,4 +85,4 @@ nav a.router-link-exact-active {
/* color: var(--color-text); */
@apply text-white bg-blue-700 md:bg-transparent md:text-blue-700 md:p-0 dark:text-white md:dark:text-blue-500;
}
</style>
</style>

View File

@ -1,7 +1,7 @@
<script setup>
import { inject, ref, onMounted } from 'vue'
import { initModals } from 'flowbite'
import SpinnerLoading from './SpinnerLoading.vue'
import SpinnerLoading from '@/components/SpinnerLoading.vue'
const codexApi = inject('codexApi')
const loading = ref(false)
@ -25,21 +25,6 @@ const props = defineProps({
},
alt: String
})
// var imgSrc = ""
// var error = ""
// if (state == "New" || state == "Started"){
// try {
// let res = await codexApi.download(cid)
// try{
// const blob = await res.blob()
// imgSrc = URL.createObjectURL(blob)
// } catch (e) {
// error = `not an image (error: ${error.message})`
// }
// } catch(error) {
// error = `failed to download cid data: ${error}`
// }
// }
onMounted(async () => {
loading.value = true
@ -69,11 +54,7 @@ onMounted(async () => {
<template>
<div class="text-center">
<SpinnerLoading v-if="loading" />
<div
v-else-if="error"
v-bind="$attrs"
class="dark:bg-orange-700 dark:text-orange-200"
>
<div v-else-if="error" v-bind="$attrs" class="dark:bg-orange-700 dark:text-orange-200">
<svg
class="text-red-500 fill-red-100 dark:text-white"
aria-hidden="true"

View File

@ -0,0 +1,23 @@
<script setup>
import { onMounted } from 'vue'
import { initDismisses } from 'flowbite'
import AlertWithContent from '@/components/alerts/AlertWithContent.vue'
const alerts = defineModel()
onMounted(() => {
initDismisses()
})
</script>
<template>
<div
v-for="{ event, blockNumber, requestId, slotIdx, state, type } in alerts"
:key="event + blockNumber + requestId"
>
<AlertWithContent :id="event + blockNumber + requestId" :title="event" :type="type"
><p>request {{ requestId }} at block {{ blockNumber }}</p>
<p v-if="slotIdx">Slot index: {{ slotIdx }}</p>
<p>State: {{ state }}</p></AlertWithContent
>
</div>
</template>

View File

@ -1,5 +1,5 @@
<script setup>
import {useCounterStore} from '../stores/counter'
import { useCounterStore } from '@/stores/counter'
import { ref, onMounted } from 'vue'
useCounterStore()
@ -13,4 +13,4 @@ const pElementRef = ref(null)
<button @click="_pStores.counter.increment">
{{ _pStores.counter.count }}
</button>
</template>
</template>

View File

@ -1,7 +1,7 @@
<script setup>
import { onMounted } from 'vue'
import { initModals } from 'flowbite'
import { useEventsStore } from '../stores/events'
import { useEventsStore } from '@/stores/events'
import { storeToRefs } from 'pinia'
const eventsStore = useEventsStore()
@ -20,7 +20,7 @@ const eventsStore = useEventsStore()
// let state = requestState[stateIdx]
// var imgSrc = ""
// var error = ""
// if (state == "New" || state == "Started"){
// if (state == "New" || state == "Fulfilled"){
// try {
// let res = await codexApi.download(cid)
// try{
@ -116,7 +116,7 @@ const { requests } = storeToRefs(eventsStore)
<div>CID: {{ request[2][0] }}</div>
<div>RequestID: {{ requestId }}</div>
<div>State: {{ state }}</div>
<CodexImage v-if="state == 'New' || state == 'Started'" cid="cid" />
<CodexImage v-if="state == 'New' || state == 'Fulfilled'" cid="cid" />
<!-- <div v-if="error">{{error}}</div>
<img v-else-if="imgSrc" :src="imgSrc" width="100%"/> -->
</li>

View File

@ -1,9 +1,9 @@
<script setup>
import { inject, ref, onMounted, computed } from 'vue'
import { initModals } from 'flowbite'
import { useEventsStore } from '../stores/events'
import { useEventsStore } from '@/stores/events'
import { storeToRefs } from 'pinia'
import CodexImage from './CodexImage.vue'
import CodexImage from '@/components/CodexImage.vue'
import { shortHex } from '@/utils/ids'
const eventsStore = useEventsStore()
@ -12,7 +12,7 @@ const { requests } = storeToRefs(eventsStore)
function getStateColour(state) {
if (state === 'New') {
return 'bg-yellow-200'
} else if (state === 'Started') {
} else if (state === 'Fulfilled') {
return 'bg-green-500'
} else {
return 'bg-red-500'
@ -21,19 +21,9 @@ function getStateColour(state) {
</script>
<template>
<!-- <ul class="requests">
<li v-for="([requestId, { request, state }], idx) in requests" :key="{ requestId }">
{{ idx }}.
<div>CID: {{ request[2][0] }}</div>
<div>RequestID: {{ requestId }}</div>
<div>State: {{ state }}</div>
<CodexImage v-if="state == 'New' || state == 'Started'" cid="request[2][0]" />
</li>
</ul> -->
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
<div>
<div
class="flex items-center justify-between flex-column md:flex-row flex-wrap space-y-4 md:space-y-0 py-4 bg-white dark:bg-gray-900"
class="flex items-center justify-between flex-column md:flex-row flex-wrap space-y-4 md:space-y-0 py-4 px-6 bg-white dark:bg-gray-900"
>
<div>
<button
@ -129,59 +119,61 @@ function getStateColour(state) {
/>
</div>
</div>
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">RequestID</th>
<th scope="col" class="px-6 py-3">CID</th>
<th scope="col" class="px-6 py-3">State</th>
<th scope="col" class="px-6 py-3">Action</th>
</tr>
</thead>
<tbody>
<tr
v-for="([requestId, { request, state }], idx) in requests"
:key="{ requestId }"
class="bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-600"
>
<th
scope="row"
class="flex items-center px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white"
<div class="relative overflow-x-auto overflow-y-auto max-h-screen shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">RequestID</th>
<th scope="col" class="px-6 py-3">CID</th>
<th scope="col" class="px-6 py-3">State</th>
<th scope="col" class="px-6 py-3">Action</th>
</tr>
</thead>
<tbody>
<tr
v-for="([requestId, { request, state }], idx) in requests"
:key="{ requestId }"
class="bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-600"
>
<CodexImage
:local-only="!['New', 'Started'].includes(state)"
:cid="request[2][0]"
class="w-10 h-10 rounded-full mt-1"
/>
<!-- class="w-10 h-10 rounded-full"
src="/docs/images/people/profile-picture-4.jpg"
alt="Jese image"
/> -->
<div class="ps-3">
<div class="text-base font-semibold">{{ shortHex(requestId) }}</div>
<div class="font-normal text-gray-500">leslie@flowbite.com</div>
</div>
</th>
<td class="px-6 py-4">{{ shortHex(request[2][0]) }}</td>
<td class="px-6 py-4">
<div class="flex items-center">
<div :class="`h-2.5 w-2.5 rounded-full ${getStateColour(state)} me-2`"></div>
{{ state }}
</div>
</td>
<td class="px-6 py-4">
<!-- Modal toggle -->
<a
href="#"
type="button"
data-modal-show="editUserModal"
class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>Edit user</a
<th
scope="row"
class="flex items-center px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white"
>
</td>
</tr>
</tbody>
</table>
<CodexImage
:local-only="!['New', 'Fulfilled'].includes(state)"
:cid="request[2][0]"
class="w-10 h-10 rounded-full mt-1"
/>
<!-- class="w-10 h-10 rounded-full"
src="/docs/images/people/profile-picture-4.jpg"
alt="Jese image"
/> -->
<div class="ps-3">
<div class="text-base font-semibold">{{ shortHex(requestId) }}</div>
<div class="font-normal text-gray-500">leslie@flowbite.com</div>
</div>
</th>
<td class="px-6 py-4">{{ shortHex(request[2][0]) }}</td>
<td class="px-6 py-4">
<div class="flex items-center">
<div :class="`h-2.5 w-2.5 rounded-full ${getStateColour(state)} me-2`"></div>
{{ state }}
</div>
</td>
<td class="px-6 py-4">
<!-- Modal toggle -->
<a
href="#"
type="button"
data-modal-show="editUserModal"
class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>Edit user</a
>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Edit user modal -->
<div
id="editUserModal"
@ -194,7 +186,7 @@ function getStateColour(state) {
<form class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<!-- Modal header -->
<div class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600">
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">Edit user</h3>
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">Details</h3>
<button
type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"

View File

@ -0,0 +1,206 @@
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { initDismisses } from 'flowbite'
const props = defineProps({
id: {
type: String,
required: true
},
type: {
type: String,
default() {
return 'info'
},
validator(value, props) {
// The value must match one of these strings
return ['success', 'warning', 'danger', 'info'].includes(value)
}
},
title: {
type: String,
required: true
},
btnMoreText: {
type: String,
default: 'View more'
},
btnMoreUrl: {
type: URL,
required: true
}
})
const theme = reactive({
bubble: [
'text-blue-800',
'border-blue-300',
'bg-blue-50',
'dark:text-blue-400',
'dark:border-blue-800',
'dark:bg-gray-800'
],
btnMore: [
'bg-blue-800',
'hover:bg-blue-900',
'focus:ring-blue-300',
'dark:bg-blue-600',
'dark:hover:bg-blue-700',
'dark:focus:ring-blue-800'
],
btnDismiss: [
'text-blue-800',
'border-blue-800',
'hover:bg-blue-900',
'focus:ring-blue-300',
'dark:text-blue-400',
'dark:border-blue-600',
'dark:hover:bg-blue-700',
'dark:focus:ring-blue-800'
]
})
onMounted(() => {
initDismisses()
switch (props.type) {
case 'success':
theme.bubble = [
'text-green-800',
'border-green-300',
'bg-green-50',
'dark:text-green-400',
'dark:border-green-800',
'dark:bg-gray-800'
]
theme.btnMore = [
'bg-green-800',
'hover:bg-green-900',
'focus:ring-green-300',
'dark:bg-green-600',
'dark:hover:bg-green-700',
'dark:focus:ring-green-800'
]
theme.btnDismiss = [
'text-green-800',
'border-green-800',
'hover:bg-green-900',
'focus:ring-green-300',
'dark:text-green-400',
'dark:border-green-600',
'dark:hover:bg-green-700',
'dark:focus:ring-green-800'
]
break
case 'danger':
theme.bubble = [
'text-red-800',
'border-red-300',
'bg-red-50',
'dark:text-red-400',
'dark:border-red-800',
'dark:bg-gray-800'
]
theme.btnMore = [
'bg-red-800',
'hover:bg-red-900',
'focus:ring-red-300',
'dark:bg-red-600',
'dark:hover:bg-red-700',
'dark:focus:ring-red-800'
]
theme.btnDismiss = [
'text-red-800',
'border-red-800',
'hover:bg-red-900',
'focus:ring-red-300',
'dark:text-red-400',
'dark:border-red-600',
'dark:hover:bg-red-700',
'dark:focus:ring-red-800'
]
break
case 'warning':
theme.bubble = [
'text-yellow-800',
'border-yellow-300',
'bg-yellow-50',
'dark:text-yellow-400',
'dark:border-yellow-800',
'dark:bg-gray-800'
]
theme.btnMore = [
'bg-yellow-800',
'hover:bg-yellow-900',
'focus:ring-yellow-300',
'dark:bg-yellow-600',
'dark:hover:bg-yellow-700',
'dark:focus:ring-yellow-800'
]
theme.btnDismiss = [
'text-yellow-800',
'border-yellow-800',
'hover:bg-yellow-900',
'focus:ring-yellow-300',
'dark:text-yellow-400',
'dark:border-yellow-600',
'dark:hover:bg-yellow-700',
'dark:focus:ring-yellow-800'
]
break
}
})
</script>
<template>
<div :id="id" class="p-4 mt-4 mb-4 border rounded-lg" :class="theme.bubble" role="alert">
<div class="flex items-center">
<svg
class="flex-shrink-0 w-4 h-4 me-2"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"
/>
</svg>
<span class="sr-only">Info</span>
<h3 class="text-lg font-medium">{{ title }}</h3>
</div>
<div class="mt-2 mb-4 text-sm">
<slot></slot>
</div>
<div class="flex">
<a
href="{{ btnMoreUrl }}"
class="text-white focus:ring-4 focus:outline-none font-medium rounded-lg text-xs px-3 py-1.5 me-2 text-center inline-flex items-center"
:class="theme.btnMore"
>
<svg
class="me-2 h-3 w-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 14"
>
<path
d="M10 0C4.612 0 0 5.336 0 7c0 1.742 3.546 7 10 7 6.454 0 10-5.258 10-7 0-1.664-4.612-7-10-7Zm0 10a3 3 0 1 1 0-6 3 3 0 0 1 0 6Z"
/>
</svg>
{{ btnMoreText }}
</a>
<button
type="button"
class="bg-transparent border hover:text-white focus:ring-4 focus:outline-none font-medium rounded-lg text-xs px-3 py-1.5 text-center dark:hover:text-white"
:class="theme.btnDismiss"
:data-dismiss-target="'#' + id"
aria-label="Close"
>
Dismiss
</button>
</div>
</div>
</template>

View File

@ -2,27 +2,33 @@ import { ref, computed, inject } from 'vue'
import { defineStore } from 'pinia'
import { slotId } from '../utils/ids'
export const useEventsStore = defineStore('events', () => {
const marketplace = inject('marketplace')
let {StorageRequested, SlotFilled} = marketplace.filters
const requests = ref(new Map()) // key: requestId, val: {request, state}
const slots = ref(new Map()) // key: slotId, val: {requestId, slotIdx, state}
const blockNumbers = ref(new Set()) // includes blocks that had events
const storageRequestedEvents = ref([]) // {blockNumber, requestId}
const slotFilledEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
const slotFreedEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
const requestStartedEvents = ref([]) // {blockNumber, requestId}
const requestCancelledEvents = ref([]) // {blockNumber, requestId}
const requestFailedEvents = ref([]) // {blockNumber, requestId}
const requestFinishedEvents = ref([]) // {blockNumber, requestId}
const ethProvider = inject('ethProvider')
let {
StorageRequested,
RequestFulfilled,
RequestCancelled,
RequestFailed,
SlotFilled,
SlotFreed
} = marketplace.filters
const requests = ref(new Map()) // key: requestId, val: {request, state, slots: [{slotId, slotIdx, state}]}
// const slots = ref(new Map()) // key: slotId, val: {requestId, slotIdx, state}
// const blockNumbers = ref(new Set()) // includes blocks that had events
// const storageRequestedEvents = ref([]) // {blockNumber, requestId}
// const slotFilledEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
// const slotFreedEvents = ref([]) // {blockNumber, requestId, slotIdx, slotId}
// const requestFulfilledEvents = ref([]) // {blockNumber, requestId}
// const requestCancelledEvents = ref([]) // {blockNumber, requestId}
// const requestFailedEvents = ref([]) // {blockNumber, requestId}
// const requestFinishedEvents = ref([]) // {blockNumber, requestId}
const loading = ref(false)
// onStorageRequested => add request to requests ref
// onStorageRequested => add request to requests ref, along with slots
// => add to storageRequestedEvents {blockNumber, requestId}
// => add request slots to slots ref
// => add blockNumber to blockNumbers
// onRequestStarted => update requests[requestId].state with marketplace.getRequestState(requestId)
// onRequestFulfilled => update requests[requestId].state with marketplace.getRequestState(requestId)
// => add to requestStartedEvents {blockNumber, requestId}
// => add blockNumber to blockNumbers
// onRequestCancelled => update requests[requestId].state with marketplace.getRequestState(requestId)
@ -34,18 +40,18 @@ export const useEventsStore = defineStore('events', () => {
// onRequestFinished => update requests[requestId].state with marketplace.getRequestState(requestId)
// => add to requestFinishedEvents {blockNumber, requestId}
// => add blockNumber to blockNumbers
// onSlotFilled => update slots[slotId].state with getSlotState
// onSlotFilled => update request.slots[slotId].state with getSlotState
// => add to slotFilledEvents {blockNumber, slotId, slotIdx}
// => add blockNumber to blockNumbers
// onSlotFreed => update slots[slotId].state with getSlotState
// => add to slotFreedEvents {blockNumber, slotId, slotIdx}
// => add blockNumber to blockNumbers
const requestState = [
"New", // [default] waiting to fill slots
"Started", // all slots filled, accepting regular proofs
"Cancelled", // not enough slots filled before expiry
"Finished", // successfully completed
"Failed" // too many nodes have failed to provide proofs, data lost
'New', // [default] waiting to fill slots
'Fulfilled', // all slots filled, accepting regular proofs
'Cancelled', // not enough slots filled before expiry
'Finished', // successfully completed
'Failed' // too many nodes have failed to provide proofs, data lost
]
const getRequestState = async (requestId) => {
@ -53,57 +59,157 @@ export const useEventsStore = defineStore('events', () => {
return requestState[stateIdx]
}
const storageRequested = async (blockNumber, requestId, request, state) => {
requests.value.set(requestId, {request, state})
storageRequestedEvents.value.push({blockNumber, requestId})
const getSlots = async (requestId, request) => {
// storageRequestedEvents.value.push({ blockNumber, requestId })
let ask = request[1]
let numSlots = ask[0]
for (let i=0; i<numSlots; i++){
let slots = []
for (let i = 0; i < numSlots; i++) {
let id = slotId(requestId, i)
let state = await marketplace.slotState(id)
slots.value.set(id, {requestId, slotIdx: i, state})
slots.push({ slotId: id, slotIdx: i, state })
}
blockNumbers.value.add(blockNumber)
return slots
// blockNumbers.value.add(blockNumber)
}
async function fetchPastEvents() {
// query past events
loading.value = true
try {
let requests = (await marketplace.queryFilter(StorageRequested))
requests.forEach(async (event) => {
let {requestId, ask, expiry} = event.args
let {blockNumber} = event
let pastRequests = await marketplace.queryFilter(StorageRequested)
pastRequests.forEach(async (event) => {
let { requestId, ask, expiry } = event.args
// let { blockNumber } = event
let request = await marketplace.getRequest(requestId)
let state = await getRequestState(requestId)
storageRequested(blockNumber, requestId, request, state)
let slots = getSlots(requestId, request)
requests.value.set(requestId, {
request,
state,
slots,
requestFinishedId: null
})
})
} catch (error) {
console.error(`failed to load past contract events: ${error.message}`)
} finally {
loading.value = false
}
// let slotsFilled = (await marketplace.queryFilter(SlotFilled))
// slotsFilled.forEach(async (event) => {
// let {requestId, slotIdx} = event.args
// let {blockNumber} = event
// let request = await marketplace.getRequest(requestId)
// let state = await getRequestState(requestId)
// storageRequested(blockNumber, requestId, request, state)
// })
}
async function listenForNewEvents(onStorageRequested) {
function updateRequestState(requestId, newState) {
let { request, state, slots, requestFinishedId } = requests.value.get(requestId)
state = newState
requests.value.set(requestId, { request, state, slots, requestFinishedId })
}
function updateRequestFinishedId(requestId, newRequestFinishedId) {
let { request, state, slots, requestFinishedId } = requests.value.get(requestId)
requestFinishedId = newRequestFinishedId
requests.value.set(requestId, { request, state, slots, requestFinishedId })
}
function updateRequestSlotState(requestId, slotIdx, newState) {
let { request, state, slots, requestFinishedId } = requests.value.get(requestId)
slots = slots.map((slot) => {
if (slot.slotIdx == slotIdx) {
slot.state = newState
}
})
requests.value.set(requestId, { request, state, slots, requestFinishedId })
}
function waitForRequestFinished(requestId, duration, onRequestFinished) {
return setTimeout(async () => {
updateRequestState(requestId, 'Finished')
updateRequestFinishedId(requestId, null)
if (onRequestFinished) {
let blockNumber = await ethProvider.getBlockNumber()
onRequestFinished(blockNumber, requestId)
}
}, duration)
}
function cancelWaitForRequestFinished(requestId) {
let { requestFinishedId } = requests.value.get(requestId)
if (requestFinishedId) {
clearTimeout(requestFinishedId)
}
}
async function listenForNewEvents(
onStorageRequested,
onRequestFulfilled,
onRequestCancelled,
onRequestFailed,
onRequestFinished,
onSlotFreed,
onSlotFilled
) {
marketplace.on(StorageRequested, async (requestId, ask, expiry, event) => {
let {blockNumber} = event
let { blockNumber } = event
let request = await marketplace.getRequest(requestId)
let state = await getRequestState(requestId)
storageRequested(blockNumber, requestId, request, state)
if (onStorageRequested) { // callback
let slots = getSlots(requestId, request)
requests.value.set(requestId, { request, state, slots, requestFinishedId: null })
// callback
if (onStorageRequested) {
onStorageRequested(blockNumber, requestId, request, state)
}
})
marketplace.on(RequestFulfilled, async (requestId, event) => {
let requestOnChain = await marketplace.getRequest(requestId)
let ask = requestOnChain[1]
let duration = ask[1]
// set request state to finished at the end of the request -- there's no
// other way to know when a request finishes
console.log('request ', requestOnChain)
let requestFinishedId = waitForRequestFinished(requestId, duration, onRequestFinished)
updateRequestState(requestId, 'Fulfilled')
updateRequestFinishedId(requestId, requestFinishedId)
let { blockNumber } = event
if (onRequestFulfilled) {
onRequestFulfilled(blockNumber, requestId)
}
})
marketplace.on(RequestCancelled, async (requestId, event) => {
updateRequestState(requestId, 'Cancelled')
let { blockNumber } = event
if (onRequestCancelled) {
onRequestCancelled(blockNumber, requestId)
}
})
marketplace.on(RequestFailed, async (requestId, event) => {
updateRequestState(requestId, 'Failed')
cancelWaitForRequestFinished(requestId)
let { blockNumber } = event
if (onRequestFailed) {
onRequestFailed(blockNumber, requestId)
}
})
marketplace.on(SlotFreed, async (requestId, slotIdx, event) => {
updateRequestSlotState(requestId, slotIdx, 'Freed')
let { blockNumber } = event
if (onSlotFreed) {
onSlotFreed(blockNumber, requestId, slotIdx)
}
})
marketplace.on(SlotFilled, async (requestId, slotIdx, event) => {
updateRequestSlotState(requestId, slotIdx, 'Filled')
let { blockNumber } = event
if (onSlotFilled) {
onSlotFilled(blockNumber, requestId, slotIdx)
}
})
}
// const eventsByBlock = computed(() =>)
@ -114,17 +220,17 @@ export const useEventsStore = defineStore('events', () => {
return {
requests,
slots,
blockNumbers,
storageRequestedEvents,
slotFilledEvents,
slotFreedEvents,
requestStartedEvents,
requestCancelledEvents,
requestFailedEvents,
requestFinishedEvents,
// slots,
// blockNumbers,
// storageRequestedEvents,
// slotFilledEvents,
// slotFreedEvents,
// requestStartedEvents,
// requestCancelledEvents,
// requestFailedEvents,
// requestFinishedEvents,
fetchPastEvents,
listenForNewEvents,
loading
}
}
})

View File

@ -1,7 +1,7 @@
<script setup>
import { storeToRefs } from 'pinia'
import { useEventsStore } from '../stores/events'
import StorageRequests from '../components/StorageRequests.vue'
import { useEventsStore } from '@/stores/events'
import StorageRequests from '@/components/StorageRequests.vue'
import SkeletonLoading from '@/components/SkeletonLoading.vue'
const eventsStore = useEventsStore()
@ -9,8 +9,8 @@ const { loading } = storeToRefs(eventsStore)
</script>
<template>
<main>
<div>
<SkeletonLoading v-if="loading" type="image" />
<StorageRequests v-else />
</main>
</div>
</template>

View File

@ -1,10 +1,9 @@
<script setup>
import Slots from '../components/Slots.vue'
import Slots from '@/components/Slots.vue'
</script>
<template>
<main>
<Slots/>
</main>
<div>
<Slots />
</div>
</template>