Skip to content

Commit

Permalink
Transaction Events Tab (MystenLabs#3596)
Browse files Browse the repository at this point in the history
* add beginning event types

* lint changes

* add the rest of the event types

* lint changes

* suieventtype -> suievent

* get event types compiling on frontend

* lint changes

* move event types to TS sdk

* eventTypes -> events

* export type guards for event types

* move SuiEvent to ts sdk

* lint changes

* update moveEvent type

* Update mock_data.json

* add itemfieldstitle style

* make package and transaction module non optional on moveEvent

* move event display types to eventDisplay.tsx

* remove newObject debug warn

* remove new object event log

* add basic TransferObject event display

* lint changes

* add object and address content display helpers

* lint changes

* handle null event data

* lint changes

* move eventToDisplay function

* lint changes

* add display support for publish events

* lint changes

* add support for deleteObject event display

* lint changes

* add epochChange & checkpoint event display

* lint changes

* progress on one-line sender->recipient

* lint change

* remove extra debug log

* truncate from->to addresses in events

* tweak sender, recipient labels

* add Event display types

* unlink publish package event field

* add contentLine event display helper

* add contentLine display helper

* Update eventDisplay.tsx

* move eventContent->Link[] mapping to function

* lint changes

* add event titles list to transactions

* hide left event column on narrower screens

* lint changes

* add missing licenses

* max event sidebar text grayer

* don't mutate object provided via props

* lint changes

* remove excess console.log

* remove console.log

* remove ternary

* remove console.log
  • Loading branch information
Stella Cannefax authored Aug 11, 2022
1 parent db66b03 commit c5ec447
Show file tree
Hide file tree
Showing 11 changed files with 547 additions and 10 deletions.
226 changes: 226 additions & 0 deletions explorer/client/src/components/events/eventDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import {
isMoveEvent,
isNewObjectEvent,
isTransferObjectEvent,
isDeleteObjectEvent,
isPublishEvent,
} from '@mysten/sui.js';

import { isBigIntOrNumber } from '../../utils/numberUtil';
import { getOwnerStr } from '../../utils/objectUtils';
import { truncate } from '../../utils/stringUtils';

import type { Category } from '../../pages/transaction-result/TransactionResultType';
import type { Link } from '../table/TableCard';
import type {
MoveEvent,
NewObjectEvent,
ObjectId,
SuiAddress,
SuiEvent,
TransferObjectEvent,
DeleteObjectEvent,
PublishEvent,
} from '@mysten/sui.js';

export type ContentItem = {
label: string;
value: string;
monotypeClass: boolean;
link?: boolean;
category?: Category;
};

export type EventDisplayData = {
top: {
title: string;
content: (ContentItem | ContentItem[])[];
};
fields?: {
title: string;
// css class name to apply to the 'Fields' sub-header
titleStyle?: string;
content: (ContentItem | ContentItem[])[];
};
};

function addressContent(label: string, addr: SuiAddress) {
return {
label: label,
value: addr,
link: true,
category: 'addresses' as Category,
monotypeClass: true,
};
}

function objectContent(label: string, id: ObjectId) {
return {
label: label,
value: id,
link: true,
category: 'objects' as Category,
monotypeClass: true,
};
}

function fieldsContent(fields: { [key: string]: any }) {
return Object.keys(fields).map((k) => {
return {
label: k,
value: fields[k].toString(),
monotypeClass: true,
};
});
}

function contentLine(
label: string,
value: string,
monotypeClass: boolean = false
) {
return {
label,
value,
monotypeClass,
};
}

export function moveEventDisplay(event: MoveEvent): EventDisplayData {
return {
top: {
title: 'Move Event',
content: [
contentLine('Type', event.type, true),
addressContent('Sender', event.sender as string),
contentLine('BCS', event.bcs, true),
],
},
fields: {
title: 'Fields',
titleStyle: 'itemfieldstitle',
content: fieldsContent(event.fields),
},
};
}

export function newObjectEventDisplay(event: NewObjectEvent): EventDisplayData {
const packMod = `${event.packageId}::${event.transactionModule}`;

return {
top: {
title: 'New Object',
content: [
contentLine('Module', packMod, true),
[
addressContent('', event.sender),
addressContent('', getOwnerStr(event.recipient)),
],
],
},
};
}

export function transferObjectEventDisplay(
event: TransferObjectEvent
): EventDisplayData {
return {
top: {
title: 'Transfer Object',
content: [
contentLine('Type', event.type, true),
objectContent('Object ID', event.objectId),
contentLine('Version', event.version.toString()),
[
addressContent('', event.sender),
addressContent('', getOwnerStr(event.recipient)),
],
],
},
};
}

export function getAddressesLinks(item: ContentItem[]): Link[] {
return item.map((content) => {
return {
url: content.value,
name: truncate(content.value, 20),
copy: false,
category: content.category,
isLink: true,
} as Link;
});
}

export function deleteObjectEventDisplay(
event: DeleteObjectEvent
): EventDisplayData {
const packMod = `${event.packageId}::${event.transactionModule}`;
return {
top: {
title: 'Delete Object',
content: [
contentLine('Module', packMod, true),
objectContent('Object ID', event.objectId),
addressContent('Sender', event.sender),
],
},
};
}

export function publishEventDisplay(event: PublishEvent): EventDisplayData {
return {
top: {
title: 'Publish',
content: [
addressContent('Sender', event.sender),
contentLine('Package', event.packageId, true),
],
},
};
}

export function bigintDisplay(
title: string,
label: string,
value: bigint
): EventDisplayData {
return {
top: {
title: title,
content: [contentLine(label, value.toString())],
},
};
}

export function eventToDisplay(event: SuiEvent) {
if ('moveEvent' in event && isMoveEvent(event.moveEvent))
return moveEventDisplay(event.moveEvent);

if ('newObject' in event && isNewObjectEvent(event.newObject))
return newObjectEventDisplay(event.newObject);

if (
'transferObject' in event &&
isTransferObjectEvent(event.transferObject)
)
return transferObjectEventDisplay(event.transferObject);

if ('deleteObject' in event && isDeleteObjectEvent(event.deleteObject))
return deleteObjectEventDisplay(event.deleteObject);

if ('publish' in event && isPublishEvent(event.publish))
return publishEventDisplay(event.publish);

// TODO - once epoch and checkpoint pages exist, make these links
if ('epochChange' in event && isBigIntOrNumber(event.epochChange))
return bigintDisplay('Epoch Change', 'Epoch ID', event.epochChange);

if ('checkpoint' in event && isBigIntOrNumber(event.checkpoint))
return bigintDisplay('Checkpoint', 'Sequence #', event.checkpoint);

return null;
}
4 changes: 2 additions & 2 deletions explorer/client/src/components/table/TableCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Category =
| 'ethAddress'
| 'unknown';

type Link = {
export type Link = {
url: string;
name?: string;
copy?: boolean;
Expand Down Expand Up @@ -56,7 +56,7 @@ type TxType = {
| TxStatus;
};

function TxAddresses({ content }: { content: Link[] }) {
export function TxAddresses({ content }: { content: Link[] }) {
return (
<section className={styles.addresses}>
{content.map((itm, idx) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,35 @@
@apply block md:grid grid-cols-1 md:grid-cols-1 gap-0 md:gap-3;
}

.txevents {
@apply grid grid-cols-5;
}

.eventtitle {
@apply pl-2 text-gray-600;
}

.eventtitle:hover {
@apply bg-blue-100 cursor-pointer;

border-radius: 6px;
}

.txeventsleft {
@apply col-span-1 hidden md:block;

margin-top: 12.5%;
line-height: 200%;
margin-right: 5%;
border-right: 1px solid #f0f1f2;
}

.txeventsright {
@apply col-span-5 md:col-span-4 overflow-y-scroll;

height: 100vh; /* enables scrolling list independtly of page */
}

.txcomponent {
@apply pt-4 pb-4;
}
Expand Down Expand Up @@ -38,6 +67,10 @@
@apply border-b-[1px] border-[#f0f1f2] pb-1 pt-1;
}

.itemfieldstitle {
@apply border-b-[1px] border-[#f0f1f2] text-sm pb-1 pt-1;
}

.itemviewcontent {
@apply mb-2 mt-2;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
ExecutionStatusType,
TransactionEffects,
SuiObjectRef,
SuiEvent,
} from '@mysten/sui.js';

type TxnState = CertifiedTransaction & {
Expand All @@ -38,6 +39,7 @@ type TxnState = CertifiedTransaction & {
txError: string;
mutated: SuiObjectRef[];
created: SuiObjectRef[];
events?: SuiEvent[];
timestamp_ms: number | null;
};
// TODO: update state to include Call types
Expand All @@ -63,6 +65,7 @@ const initState: TxnState = {
timestamp_ms: 0,
mutated: [],
created: [],
events: [],
};

function fetchTransactionData(
Expand Down Expand Up @@ -114,6 +117,7 @@ const transformTransactionResponse = (
loadState: 'loaded',
mutated: getCreatedOrMutatedData(txObj.effects, 'mutated'),
created: getCreatedOrMutatedData(txObj.effects, 'created'),
events: txObj.effects.events,
timestamp_ms: txObj.timestamp_ms,
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
CertifiedTransaction,
ExecutionStatusType,
SuiObjectRef,
SuiEvent,
} from '@mysten/sui.js';

export type DataType = CertifiedTransaction & {
Expand All @@ -15,6 +16,7 @@ export type DataType = CertifiedTransaction & {
txError: string;
mutated: SuiObjectRef[];
created: SuiObjectRef[];
events?: SuiEvent[];
timestamp_ms: number | null;
};

Expand Down
Loading

0 comments on commit c5ec447

Please sign in to comment.