From e57427def3df5faeb24c7ad508f8cc8b6910cbfd Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Thu, 13 Nov 2025 16:04:33 +0100 Subject: [PATCH 1/5] Fix event ordering --- src/explorer/Transaction.vue | 8 ++++---- src/state/transactions.ts | 34 +++++++++++++++------------------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/explorer/Transaction.vue b/src/explorer/Transaction.vue index cb50c88..9e9aa2c 100644 --- a/src/explorer/Transaction.vue +++ b/src/explorer/Transaction.vue @@ -316,22 +316,22 @@ watch(

Events

-
+
- Event #{{ index + 1 }}: {{ event.name }} + Event #{{ event.event_index }}: {{ event.name }} - Block: {{ event.block_hash }} + Block {{ event.block_height }} -- {{ event.block_hash }}
{{
                                 JSON.stringify(event.metadata, null, 2)
                             }}
- +
diff --git a/src/state/transactions.ts b/src/state/transactions.ts index 89e7717..c567ec6 100644 --- a/src/state/transactions.ts +++ b/src/state/transactions.ts @@ -1,4 +1,4 @@ -import { getNetworkIndexerApiUrl, network } from "@/state/network"; +import { getNetworkIndexerApiUrl } from "@/state/network"; export type HyliOutput = { blobs: number[]; @@ -23,6 +23,8 @@ export type BlobInfo = { export type EventInfo = { name: string; block_hash: string; + block_height: number; + event_index: number; metadata?: Record; }; @@ -129,24 +131,18 @@ export class TransactionStore { `${getNetworkIndexerApiUrl(this.network)}/v1/indexer/transaction/hash/${tx.tx_hash}/events?no_cache=${Date.now()}`, ); const eventsData = await eventsResponse.json(); - // Preserve block_hash and other metadata when flattening events - // Retrocompatibility - if (network.value === "first-testnet") - tx.events = eventsData.flatMap((eventEntry: { block_hash: string; events: Omit[] }) => - (eventEntry.events || []).map((event) => ({ - ...event, - block_hash: eventEntry.block_hash, - })), - ); - else { - tx.events = eventsData.flatMap((eventEntry: { block_hash: string; events: Omit[] }) => - (eventEntry.events || []).map((event) => ({ - name: Object.keys(event)[0], - metadata: (event as any)[Object.keys(event)[0]][1], // Common format -> get the actual meat of the event - block_hash: eventEntry.block_hash, - })), - ); - } + console.log(eventsData); + + const events = eventsData.flatMap((eventEntry: { block_hash: string; block_height: number; events: any[] }) => + (eventEntry.events || []).map((event) => ({ + name: Object.keys(event)[0], + metadata: (event as any)[Object.keys(event)[0]], + block_hash: eventEntry.block_hash, + block_height: eventEntry.block_height, + event_index: event.event_index || 0, + })), + ); + tx.events = events.sort((a: EventInfo, b: EventInfo) => a.event_index - b.event_index); } } From fc28139ab8898d194017f3bd5bc3e6f480fd48e4 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Thu, 13 Nov 2025 17:57:43 +0100 Subject: [PATCH 2/5] remove debug line --- src/state/transactions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/state/transactions.ts b/src/state/transactions.ts index c567ec6..e10b472 100644 --- a/src/state/transactions.ts +++ b/src/state/transactions.ts @@ -131,7 +131,6 @@ export class TransactionStore { `${getNetworkIndexerApiUrl(this.network)}/v1/indexer/transaction/hash/${tx.tx_hash}/events?no_cache=${Date.now()}`, ); const eventsData = await eventsResponse.json(); - console.log(eventsData); const events = eventsData.flatMap((eventEntry: { block_hash: string; block_height: number; events: any[] }) => (eventEntry.events || []).map((event) => ({ From 7b28c3192078cc47693ca4090fac5d2d84fe2822 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Thu, 13 Nov 2025 18:24:57 +0100 Subject: [PATCH 3/5] Improve event messages --- src/explorer/Transaction.vue | 3 +- src/services/eventProcessor.ts | 427 +++++++++++++++++++++++++++++++++ src/state/transactions.ts | 21 +- 3 files changed, 442 insertions(+), 9 deletions(-) create mode 100644 src/services/eventProcessor.ts diff --git a/src/explorer/Transaction.vue b/src/explorer/Transaction.vue index 9e9aa2c..2e48d7e 100644 --- a/src/explorer/Transaction.vue +++ b/src/explorer/Transaction.vue @@ -9,6 +9,7 @@ import { useRoute, useRouter } from "vue-router"; import type { TransactionInfo } from "@/state/transactions"; import type { ProofInfo } from "@/state/proofs"; import { decodeBlobData } from "@/explorer/utils/blobDecoder"; +import { TxEventProcessor } from "@/services/eventProcessor"; const route = useRoute(); const router = useRouter(); @@ -329,7 +330,7 @@ watch(
{{
-                                JSON.stringify(event.metadata, null, 2)
+                                TxEventProcessor.processEvent(event)
                             }}
diff --git a/src/services/eventProcessor.ts b/src/services/eventProcessor.ts new file mode 100644 index 0000000..ee814e7 --- /dev/null +++ b/src/services/eventProcessor.ts @@ -0,0 +1,427 @@ +/** + * Event processor for handling Rust TxEvent variants + * Maps complex Rust event structures to readable JavaScript objects + */ + +import { EventInfo } from "@/state/transactions"; + +export interface ProcessedEvent { + type: string; + txHash?: string; + laneId?: string; + sequenceNumber?: number; + contractName?: string; + programId?: string; + error?: string; + blobIndex?: number; + success?: boolean; + reason?: string; + additionalData?: Record; +} + +export class TxEventProcessor { + /** + * Process a raw event metadata object based on the event name + */ + static processEvent(event: EventInfo): ProcessedEvent { + const { event_name: eventName, metadata } = event; + if (!metadata) { + return { type: eventName }; + } + switch (eventName) { + case 'RejectedBlobTransaction': + return this.processRejectedBlobTransaction(metadata); + + case 'DuplicateBlobTransaction': + return this.processDuplicateBlobTransaction(metadata); + + case 'SequencedBlobTransaction': + return this.processSequencedBlobTransaction(metadata); + + case 'SequencedProofTransaction': + return this.processSequencedProofTransaction(metadata); + + case 'Settled': + return this.processSettled(metadata); + + case 'SettledAsFailed': + return this.processSettledAsFailed(metadata); + + case 'TimedOut': + return this.processTimedOut(metadata); + + case 'TxError': + return this.processTxError(metadata); + + case 'NewProof': + return this.processNewProof(metadata); + + case 'BlobSettled': + return this.processBlobSettled(metadata); + + case 'ContractDeleted': + return this.processContractDeleted(metadata); + + case 'ContractRegistered': + return this.processContractRegistered(metadata); + + case 'ContractStateUpdated': + return this.processContractStateUpdated(metadata); + + case 'ContractProgramIdUpdated': + return this.processContractProgramIdUpdated(metadata); + + case 'ContractTimeoutWindowUpdated': + return this.processContractTimeoutWindowUpdated(metadata); + + default: + return { + type: eventName, + additionalData: metadata + }; + } + } + + private static processRejectedBlobTransaction(metadata: Record): ProcessedEvent { + // RejectedBlobTransaction(&'a TxHash, &'a LaneId, u32, &'a BlobTransaction, &'a Arc) + return { + type: 'RejectedBlobTransaction', + txHash: this.extractTxHash(metadata, 0), + laneId: this.extractLaneId(metadata, 1), + reason: 'Transaction rejected during blob processing', + additionalData: { + context: this.extractTxContext(metadata, 4) + } + }; + } + + private static processDuplicateBlobTransaction(metadata: Record): ProcessedEvent { + // DuplicateBlobTransaction(&'a TxHash) + return { + type: 'DuplicateBlobTransaction', + txHash: this.extractTxHash(metadata, 0), + reason: 'Duplicate blob transaction detected' + }; + } + + private static processSequencedBlobTransaction(metadata: Record): ProcessedEvent { + // SequencedBlobTransaction(&'a TxHash, &'a LaneId, u32, &'a BlobTransaction, &'a Arc) + return { + type: 'SequencedBlobTransaction', + txHash: this.extractTxHash(metadata, 0), + laneId: this.extractLaneId(metadata, 1), + additionalData: { + // context: this.extractTxContext(metadata, 4) + } + }; + } + + private static processSequencedProofTransaction(metadata: Record): ProcessedEvent { + // SequencedProofTransaction(&'a TxHash, &'a LaneId, u32, &'a VerifiedProofTransaction) + return { + type: 'SequencedProofTransaction', + txHash: this.extractTxHash(metadata, 0), + laneId: this.extractLaneId(metadata, 1), + additionalData: { + } + }; + } + + private static processSettled(metadata: Record): ProcessedEvent { + // Settled(&'a TxHash, &'a UnsettledBlobTransaction) + return { + type: 'Settled', + txHash: this.extractTxHash(metadata, 0), + additionalData: { + } + }; + } + + private static processSettledAsFailed(metadata: Record): ProcessedEvent { + // SettledAsFailed(&'a TxHash, &'a UnsettledBlobTransaction, &'a str) + return { + type: 'SettledAsFailed', + txHash: this.extractTxHash(metadata, 0), + error: this.extractString(metadata, 2), + additionalData: { + } + }; + } + + private static processTimedOut(metadata: Record): ProcessedEvent { + // TimedOut(&'a TxHash, &'a UnsettledBlobTransaction) + return { + type: 'TimedOut', + txHash: this.extractTxHash(metadata, 0), + reason: 'Transaction timed out', + additionalData: { + unsettledBlobTransaction: this.extractUnsettledBlobTransaction(metadata, 1) + } + }; + } + + private static processTxError(metadata: Record): ProcessedEvent { + // TxError(&'a TxHash, &'a str) + return { + type: 'TxError', + txHash: this.extractTxHash(metadata, 0), + error: this.extractString(metadata, 1) + }; + } + + private static processNewProof(metadata: Record): ProcessedEvent { + // NewProof(&'a TxHash, &'a Blob, BlobIndex, &'a (ProgramId, Verifier, TxHash, HyliOutput), usize) + // const hyliOutputTuple = this.extractTuple(metadata, 3); + return { + type: 'NewProof', + txHash: this.extractTxHash(metadata, 0), + blobIndex: this.extractBlobIndex(metadata, 2), + additionalData: { + // blob: this.extractBlob(metadata, 1), + // verifier: hyliOutputTuple?.[1], + // relatedTxHash: hyliOutputTuple?.[2], + // hyliOutput: hyliOutputTuple?.[3], + // proofIndex: this.extractUsize(metadata, 4) + } + }; + } + + private static processBlobSettled(metadata: Record): ProcessedEvent { + // BlobSettled(&'a TxHash, &'a UnsettledBlobTransaction, &'a Blob, BlobIndex, Option<&'a (ProgramId, Verifier, TxHash, HyliOutput)>, usize) + // const hyliOutputTuple = this.extractOptionalTuple(metadata, 4); + return { + type: 'BlobSettled', + txHash: this.extractTxHash(metadata, 0), + blobIndex: this.extractBlobIndex(metadata, 3), + additionalData: { + // unsettledBlobTransaction: this.extractUnsettledBlobTransaction(metadata, 1), + // blob: this.extractBlob(metadata, 2), + // verifier: hyliOutputTuple?.[1], + // relatedTxHash: hyliOutputTuple?.[2], + // hyliOutput: hyliOutputTuple?.[3], + // proofIndex: this.extractUsize(metadata, 5) + } + }; + } + + private static processContractDeleted(metadata: Record): ProcessedEvent { + // ContractDeleted(&'a TxHash, &'a ContractName) + return { + type: 'ContractDeleted', + txHash: this.extractTxHash(metadata, 0), + contractName: this.extractContractName(metadata, 1), + }; + } + + private static processContractRegistered(metadata: Record): ProcessedEvent { + // ContractRegistered(&'a TxHash, &'a ContractName, &'a Contract, &'a Option>) + return { + type: 'ContractRegistered', + txHash: this.extractTxHash(metadata, 0), + contractName: this.extractContractName(metadata, 1), + additionalData: { + contract: this.extractContract(metadata, 2), + initData: this.extractOptionalBytes(metadata, 3) + } + }; + } + + private static processContractStateUpdated(metadata: Record): ProcessedEvent { + // ContractStateUpdated(&'a TxHash, &'a ContractName, &'a Contract, &'a StateCommitment) + return { + type: 'ContractStateUpdated', + txHash: this.extractTxHash(metadata, 0), + contractName: this.extractContractName(metadata, 1), + additionalData: { + contract: this.extractContract(metadata, 2), + stateCommitment: this.extractStateCommitment(metadata, 3) + } + }; + } + + private static processContractProgramIdUpdated(metadata: Record): ProcessedEvent { + // ContractProgramIdUpdated(&'a TxHash, &'a ContractName, &'a Contract, &'a ProgramId) + return { + type: 'ContractProgramIdUpdated', + txHash: this.extractTxHash(metadata, 0), + contractName: this.extractContractName(metadata, 1), + programId: this.extractProgramId(metadata, 3), + additionalData: { + contract: this.extractContract(metadata, 2) + } + }; + } + + private static processContractTimeoutWindowUpdated(metadata: Record): ProcessedEvent { + // ContractTimeoutWindowUpdated(&'a TxHash, &'a ContractName, &'a Contract, &'a TimeoutWindow) + return { + type: 'ContractTimeoutWindowUpdated', + txHash: this.extractTxHash(metadata, 0), + contractName: this.extractContractName(metadata, 1), + additionalData: { + contract: this.extractContract(metadata, 2), + timeoutWindow: this.extractTimeoutWindow(metadata, 3) + } + }; + } + + // Helper methods for extracting typed data from metadata + private static extractTxHash(metadata: Record, index: number): string | undefined { + return metadata[index][1]?.toString(); + } + + private static extractLaneId(metadata: Record, index: number): string | undefined { + return metadata[index]?.toString(); + } + + private static extractUsize(metadata: Record, index: number): number | undefined { + const value = metadata[index]; + return typeof value === 'number' ? value : undefined; + } + + private static extractString(metadata: Record, index: number): string | undefined { + return metadata[index]?.toString(); + } + + private static extractContractName(metadata: Record, index: number): string | undefined { + return metadata[index]?.toString(); + } + + private static extractProgramId(metadata: Record, index: number): string | undefined { + return metadata[index]?.toString(); + } + + private static extractBlobIndex(metadata: Record, index: number): number | undefined { + const value = metadata[index]; + return typeof value === 'number' ? value : undefined; + } + + private static extractTxContext(metadata: Record, index: number): any { + return metadata[index]; + } + + private static extractVerifiedProofTransaction(metadata: Record, index: number): any { + return metadata[index]; + } + + private static extractUnsettledBlobTransaction(metadata: Record, index: number): any { + return metadata[index]; + } + + private static extractBlob(metadata: Record, index: number): any { + return metadata[index]; + } + + private static extractContract(metadata: Record, index: number): any { + return metadata[index]; + } + + private static extractStateCommitment(metadata: Record, index: number): any { + return metadata[index]; + } + + private static extractTimeoutWindow(metadata: Record, index: number): any { + return metadata[index]; + } + + private static extractTuple(metadata: Record, index: number): any[] | undefined { + const value = metadata[index]; + return Array.isArray(value) ? value : undefined; + } + + private static extractOptionalTuple(metadata: Record, index: number): any[] | undefined { + const value = metadata[index]; + return value && Array.isArray(value) ? value : undefined; + } + + private static extractOptionalBytes(metadata: Record, index: number): number[] | undefined { + const value = metadata[index]; + return value && Array.isArray(value) ? value : undefined; + } + + /** + * Get a human-readable description of the event + */ + static getEventDescription(processedEvent: ProcessedEvent): string { + switch (processedEvent.type) { + case 'RejectedBlobTransaction': + return `Blob transaction ${processedEvent.txHash} was rejected`; + + case 'DuplicateBlobTransaction': + return `Duplicate blob transaction detected: ${processedEvent.txHash}`; + + case 'SequencedBlobTransaction': + return `Blob transaction ${processedEvent.txHash} was successfully sequenced`; + + case 'SequencedProofTransaction': + return `Proof transaction ${processedEvent.txHash} was successfully sequenced`; + + case 'Settled': + return `Transaction ${processedEvent.txHash} was settled successfully`; + + case 'SettledAsFailed': + return `Transaction ${processedEvent.txHash} was settled as failed: ${processedEvent.error}`; + + case 'TimedOut': + return `Transaction ${processedEvent.txHash} timed out`; + + case 'TxError': + return `Transaction ${processedEvent.txHash} encountered an error: ${processedEvent.error}`; + + case 'NewProof': + return `New proof generated for transaction ${processedEvent.txHash}`; + + case 'BlobSettled': + return `Blob settled for transaction ${processedEvent.txHash}`; + + case 'ContractDeleted': + return `Contract ${processedEvent.contractName} was deleted`; + + case 'ContractRegistered': + return `Contract ${processedEvent.contractName} was registered`; + + case 'ContractStateUpdated': + return `State updated for contract ${processedEvent.contractName}`; + + case 'ContractProgramIdUpdated': + return `Program ID updated for contract ${processedEvent.contractName}`; + + case 'ContractTimeoutWindowUpdated': + return `Timeout window updated for contract ${processedEvent.contractName}`; + + default: + return `Event: ${processedEvent.type}`; + } + } + + /** + * Get the status/severity level of the event + */ + static getEventStatus(processedEvent: ProcessedEvent): 'success' | 'error' | 'warning' | 'info' { + if (processedEvent.success === false || processedEvent.error) { + return 'error'; + } + + switch (processedEvent.type) { + case 'RejectedBlobTransaction': + case 'DuplicateBlobTransaction': + return 'warning'; + + case 'SettledAsFailed': + case 'TimedOut': + case 'TxError': + return 'error'; + + case 'Settled': + case 'SequencedBlobTransaction': + case 'SequencedProofTransaction': + case 'NewProof': + case 'BlobSettled': + case 'ContractRegistered': + return 'success'; + + default: + return 'info'; + } + } +} \ No newline at end of file diff --git a/src/state/transactions.ts b/src/state/transactions.ts index e10b472..4557556 100644 --- a/src/state/transactions.ts +++ b/src/state/transactions.ts @@ -25,7 +25,8 @@ export type EventInfo = { block_hash: string; block_height: number; event_index: number; - metadata?: Record; + event_name: string; + metadata?: any; }; export type TransactionInfo = { @@ -133,13 +134,17 @@ export class TransactionStore { const eventsData = await eventsResponse.json(); const events = eventsData.flatMap((eventEntry: { block_hash: string; block_height: number; events: any[] }) => - (eventEntry.events || []).map((event) => ({ - name: Object.keys(event)[0], - metadata: (event as any)[Object.keys(event)[0]], - block_hash: eventEntry.block_hash, - block_height: eventEntry.block_height, - event_index: event.event_index || 0, - })), + (eventEntry.events || []).map((event) => { + const eventName = Object.keys(event).find(key => key !== 'event_index') || ''; + return { + name: eventName, + block_hash: eventEntry.block_hash, + block_height: eventEntry.block_height, + event_index: event.event_index || 0, + event_name: eventName, + metadata: event[eventName], + }; + }), ); tx.events = events.sort((a: EventInfo, b: EventInfo) => a.event_index - b.event_index); } From 7ca46e881fd44238d0df70da649d3c17912b9c70 Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Fri, 14 Nov 2025 09:59:40 +0100 Subject: [PATCH 4/5] wip --- src/services/eventProcessor.ts | 106 +++++---------------------------- 1 file changed, 16 insertions(+), 90 deletions(-) diff --git a/src/services/eventProcessor.ts b/src/services/eventProcessor.ts index ee814e7..bfd7e58 100644 --- a/src/services/eventProcessor.ts +++ b/src/services/eventProcessor.ts @@ -6,7 +6,7 @@ import { EventInfo } from "@/state/transactions"; export interface ProcessedEvent { - type: string; + type?: string; txHash?: string; laneId?: string; sequenceNumber?: number; @@ -85,7 +85,6 @@ export class TxEventProcessor { private static processRejectedBlobTransaction(metadata: Record): ProcessedEvent { // RejectedBlobTransaction(&'a TxHash, &'a LaneId, u32, &'a BlobTransaction, &'a Arc) return { - type: 'RejectedBlobTransaction', txHash: this.extractTxHash(metadata, 0), laneId: this.extractLaneId(metadata, 1), reason: 'Transaction rejected during blob processing', @@ -98,7 +97,6 @@ export class TxEventProcessor { private static processDuplicateBlobTransaction(metadata: Record): ProcessedEvent { // DuplicateBlobTransaction(&'a TxHash) return { - type: 'DuplicateBlobTransaction', txHash: this.extractTxHash(metadata, 0), reason: 'Duplicate blob transaction detected' }; @@ -107,11 +105,10 @@ export class TxEventProcessor { private static processSequencedBlobTransaction(metadata: Record): ProcessedEvent { // SequencedBlobTransaction(&'a TxHash, &'a LaneId, u32, &'a BlobTransaction, &'a Arc) return { - type: 'SequencedBlobTransaction', txHash: this.extractTxHash(metadata, 0), laneId: this.extractLaneId(metadata, 1), additionalData: { - // context: this.extractTxContext(metadata, 4) + context: this.extractTxContext(metadata, 4) } }; } @@ -119,7 +116,6 @@ export class TxEventProcessor { private static processSequencedProofTransaction(metadata: Record): ProcessedEvent { // SequencedProofTransaction(&'a TxHash, &'a LaneId, u32, &'a VerifiedProofTransaction) return { - type: 'SequencedProofTransaction', txHash: this.extractTxHash(metadata, 0), laneId: this.extractLaneId(metadata, 1), additionalData: { @@ -130,7 +126,6 @@ export class TxEventProcessor { private static processSettled(metadata: Record): ProcessedEvent { // Settled(&'a TxHash, &'a UnsettledBlobTransaction) return { - type: 'Settled', txHash: this.extractTxHash(metadata, 0), additionalData: { } @@ -140,7 +135,6 @@ export class TxEventProcessor { private static processSettledAsFailed(metadata: Record): ProcessedEvent { // SettledAsFailed(&'a TxHash, &'a UnsettledBlobTransaction, &'a str) return { - type: 'SettledAsFailed', txHash: this.extractTxHash(metadata, 0), error: this.extractString(metadata, 2), additionalData: { @@ -151,7 +145,6 @@ export class TxEventProcessor { private static processTimedOut(metadata: Record): ProcessedEvent { // TimedOut(&'a TxHash, &'a UnsettledBlobTransaction) return { - type: 'TimedOut', txHash: this.extractTxHash(metadata, 0), reason: 'Transaction timed out', additionalData: { @@ -163,7 +156,6 @@ export class TxEventProcessor { private static processTxError(metadata: Record): ProcessedEvent { // TxError(&'a TxHash, &'a str) return { - type: 'TxError', txHash: this.extractTxHash(metadata, 0), error: this.extractString(metadata, 1) }; @@ -171,35 +163,33 @@ export class TxEventProcessor { private static processNewProof(metadata: Record): ProcessedEvent { // NewProof(&'a TxHash, &'a Blob, BlobIndex, &'a (ProgramId, Verifier, TxHash, HyliOutput), usize) - // const hyliOutputTuple = this.extractTuple(metadata, 3); + const hyliOutputTuple = this.extractTuple(metadata, 3); return { - type: 'NewProof', txHash: this.extractTxHash(metadata, 0), blobIndex: this.extractBlobIndex(metadata, 2), additionalData: { - // blob: this.extractBlob(metadata, 1), - // verifier: hyliOutputTuple?.[1], - // relatedTxHash: hyliOutputTuple?.[2], - // hyliOutput: hyliOutputTuple?.[3], - // proofIndex: this.extractUsize(metadata, 4) + blob: this.extractBlob(metadata, 1), + verifier: hyliOutputTuple?.[1], + relatedTxHash: hyliOutputTuple?.[2], + hyliOutput: hyliOutputTuple?.[3], + proofIndex: this.extractUsize(metadata, 4) } }; } private static processBlobSettled(metadata: Record): ProcessedEvent { // BlobSettled(&'a TxHash, &'a UnsettledBlobTransaction, &'a Blob, BlobIndex, Option<&'a (ProgramId, Verifier, TxHash, HyliOutput)>, usize) - // const hyliOutputTuple = this.extractOptionalTuple(metadata, 4); + const hyliOutputTuple = this.extractOptionalTuple(metadata, 4); return { - type: 'BlobSettled', txHash: this.extractTxHash(metadata, 0), blobIndex: this.extractBlobIndex(metadata, 3), additionalData: { - // unsettledBlobTransaction: this.extractUnsettledBlobTransaction(metadata, 1), - // blob: this.extractBlob(metadata, 2), - // verifier: hyliOutputTuple?.[1], - // relatedTxHash: hyliOutputTuple?.[2], - // hyliOutput: hyliOutputTuple?.[3], - // proofIndex: this.extractUsize(metadata, 5) + unsettledBlobTransaction: this.extractUnsettledBlobTransaction(metadata, 1), + blob: this.extractBlob(metadata, 2), + verifier: hyliOutputTuple?.[1], + relatedTxHash: hyliOutputTuple?.[2], + hyliOutput: hyliOutputTuple?.[3], + proofIndex: this.extractUsize(metadata, 5) } }; } @@ -207,7 +197,6 @@ export class TxEventProcessor { private static processContractDeleted(metadata: Record): ProcessedEvent { // ContractDeleted(&'a TxHash, &'a ContractName) return { - type: 'ContractDeleted', txHash: this.extractTxHash(metadata, 0), contractName: this.extractContractName(metadata, 1), }; @@ -216,7 +205,6 @@ export class TxEventProcessor { private static processContractRegistered(metadata: Record): ProcessedEvent { // ContractRegistered(&'a TxHash, &'a ContractName, &'a Contract, &'a Option>) return { - type: 'ContractRegistered', txHash: this.extractTxHash(metadata, 0), contractName: this.extractContractName(metadata, 1), additionalData: { @@ -229,7 +217,6 @@ export class TxEventProcessor { private static processContractStateUpdated(metadata: Record): ProcessedEvent { // ContractStateUpdated(&'a TxHash, &'a ContractName, &'a Contract, &'a StateCommitment) return { - type: 'ContractStateUpdated', txHash: this.extractTxHash(metadata, 0), contractName: this.extractContractName(metadata, 1), additionalData: { @@ -242,7 +229,6 @@ export class TxEventProcessor { private static processContractProgramIdUpdated(metadata: Record): ProcessedEvent { // ContractProgramIdUpdated(&'a TxHash, &'a ContractName, &'a Contract, &'a ProgramId) return { - type: 'ContractProgramIdUpdated', txHash: this.extractTxHash(metadata, 0), contractName: this.extractContractName(metadata, 1), programId: this.extractProgramId(metadata, 3), @@ -255,7 +241,6 @@ export class TxEventProcessor { private static processContractTimeoutWindowUpdated(metadata: Record): ProcessedEvent { // ContractTimeoutWindowUpdated(&'a TxHash, &'a ContractName, &'a Contract, &'a TimeoutWindow) return { - type: 'ContractTimeoutWindowUpdated', txHash: this.extractTxHash(metadata, 0), contractName: this.extractContractName(metadata, 1), additionalData: { @@ -300,10 +285,6 @@ export class TxEventProcessor { return metadata[index]; } - private static extractVerifiedProofTransaction(metadata: Record, index: number): any { - return metadata[index]; - } - private static extractUnsettledBlobTransaction(metadata: Record, index: number): any { return metadata[index]; } @@ -339,61 +320,6 @@ export class TxEventProcessor { return value && Array.isArray(value) ? value : undefined; } - /** - * Get a human-readable description of the event - */ - static getEventDescription(processedEvent: ProcessedEvent): string { - switch (processedEvent.type) { - case 'RejectedBlobTransaction': - return `Blob transaction ${processedEvent.txHash} was rejected`; - - case 'DuplicateBlobTransaction': - return `Duplicate blob transaction detected: ${processedEvent.txHash}`; - - case 'SequencedBlobTransaction': - return `Blob transaction ${processedEvent.txHash} was successfully sequenced`; - - case 'SequencedProofTransaction': - return `Proof transaction ${processedEvent.txHash} was successfully sequenced`; - - case 'Settled': - return `Transaction ${processedEvent.txHash} was settled successfully`; - - case 'SettledAsFailed': - return `Transaction ${processedEvent.txHash} was settled as failed: ${processedEvent.error}`; - - case 'TimedOut': - return `Transaction ${processedEvent.txHash} timed out`; - - case 'TxError': - return `Transaction ${processedEvent.txHash} encountered an error: ${processedEvent.error}`; - - case 'NewProof': - return `New proof generated for transaction ${processedEvent.txHash}`; - - case 'BlobSettled': - return `Blob settled for transaction ${processedEvent.txHash}`; - - case 'ContractDeleted': - return `Contract ${processedEvent.contractName} was deleted`; - - case 'ContractRegistered': - return `Contract ${processedEvent.contractName} was registered`; - - case 'ContractStateUpdated': - return `State updated for contract ${processedEvent.contractName}`; - - case 'ContractProgramIdUpdated': - return `Program ID updated for contract ${processedEvent.contractName}`; - - case 'ContractTimeoutWindowUpdated': - return `Timeout window updated for contract ${processedEvent.contractName}`; - - default: - return `Event: ${processedEvent.type}`; - } - } - /** * Get the status/severity level of the event */ @@ -405,11 +331,11 @@ export class TxEventProcessor { switch (processedEvent.type) { case 'RejectedBlobTransaction': case 'DuplicateBlobTransaction': + case 'TxError': return 'warning'; case 'SettledAsFailed': case 'TimedOut': - case 'TxError': return 'error'; case 'Settled': From 21e1fc13d7bc6d31679151c7e50fbe9383716cfb Mon Sep 17 00:00:00 2001 From: maximilien-hyle Date: Fri, 14 Nov 2025 10:51:54 +0100 Subject: [PATCH 5/5] filter some data in event & better presentation --- src/explorer/Transaction.vue | 2 +- src/services/eventProcessor.ts | 21 ++++++++++++--------- src/state/transactions.ts | 17 +++++++++++------ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/explorer/Transaction.vue b/src/explorer/Transaction.vue index 2e48d7e..b54dbcb 100644 --- a/src/explorer/Transaction.vue +++ b/src/explorer/Transaction.vue @@ -319,7 +319,7 @@ watch(
- Event #{{ event.event_index }}: {{ event.name }} + {{ event.name }} , index: number): any { - return metadata[index]; + let blob = metadata[index]; + console.log(blob); + if (blob && blob.data) { + blob.data = Array.isArray(blob.data) + ? blob.data.map((byte: { toString: (arg0: number) => string; }) => byte.toString(16).padStart(2, '0')).join('') + : blob.data; + } + return blob; } private static extractContract(metadata: Record, index: number): any { diff --git a/src/state/transactions.ts b/src/state/transactions.ts index 4557556..4193fc0 100644 --- a/src/state/transactions.ts +++ b/src/state/transactions.ts @@ -24,8 +24,7 @@ export type EventInfo = { name: string; block_hash: string; block_height: number; - event_index: number; - event_name: string; + index: number; metadata?: any; }; @@ -135,18 +134,24 @@ export class TransactionStore { const events = eventsData.flatMap((eventEntry: { block_hash: string; block_height: number; events: any[] }) => (eventEntry.events || []).map((event) => { - const eventName = Object.keys(event).find(key => key !== 'event_index') || ''; + const eventName = Object.keys(event).find(key => key !== 'index') || ''; + console.log(event); return { name: eventName, block_hash: eventEntry.block_hash, block_height: eventEntry.block_height, - event_index: event.event_index || 0, - event_name: eventName, + index: event.index || 0, metadata: event[eventName], }; }), ); - tx.events = events.sort((a: EventInfo, b: EventInfo) => a.event_index - b.event_index); + tx.events = events.sort((a: EventInfo, b: EventInfo) => { + const heightDiff = (a.block_height ?? 0) - (b.block_height ?? 0); + if (heightDiff !== 0) { + return heightDiff; + } + return (a.index ?? 0) - (b.index ?? 0); + }); } }