Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ts-sdk, explorer): improve object type truncation #3750

Merged
merged 9 commits into from
Nov 4, 2024
4 changes: 2 additions & 2 deletions apps/explorer/src/components/ui/InternalLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Modifications Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { formatAddress, formatDigest } from '@iota/iota-sdk/utils';
import { formatAddress, formatDigest, formatType } from '@iota/iota-sdk/utils';
import { type ReactNode } from 'react';

import { Link, type LinkProps } from '~/components/ui';
Expand Down Expand Up @@ -48,6 +48,6 @@ export const CheckpointSequenceLink = createInternalLink('checkpoint', 'sequence
export const AddressLink = createInternalLink('address', 'address', (addressOrNs) =>
formatAddress(addressOrNs),
);
export const ObjectLink = createInternalLink('object', 'objectId', formatAddress);
export const ObjectLink = createInternalLink('object', 'objectId', formatType);
export const TransactionLink = createInternalLink('txblock', 'digest', formatDigest);
export const ValidatorLink = createInternalLink('validator', 'address', formatAddress);
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import { TableCellBase, TableCellText } from '@iota/apps-ui-kit';
import type { ColumnDef } from '@tanstack/react-table';

import { parseObjectType, trimStdLibPrefix } from '~/lib';
import { ObjectVideoImage, ObjectLink } from '~/components';
import type { IotaObjectResponse } from '@iota/iota-sdk/client';
import { formatAddress, formatType } from '@iota/iota-sdk/utils';
import { ObjectLink, ObjectVideoImage } from '~/components';
import { useResolveVideo } from '~/hooks';
import { formatAddress } from '@iota/iota-sdk/utils';
import { parseObjectType, trimStdLibPrefix } from '~/lib';

function Asset({ object }: { object: IotaObjectResponse }) {
const video = useResolveVideo(object);
Expand Down Expand Up @@ -56,7 +56,7 @@ export function generateObjectListColumns(): ColumnDef<IotaObjectResponse>[] {
cell({ row: { original: object } }) {
const objectId = object?.data?.objectId;
if (!objectId) return null;
const type = trimStdLibPrefix(parseObjectType(object));
const type = formatType(trimStdLibPrefix(parseObjectType(object)));
return (
<TableCellBase>
<ObjectLink objectId={objectId} label={type}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { IotaTransactionBlockKind, IotaTransactionBlockResponse } from '@io
import { TableCellBase, TableCellText } from '@iota/apps-ui-kit';
import type { ColumnDef } from '@tanstack/react-table';
import { AddressLink, TransactionLink } from '../../../components/ui';
import { formatAddress, NANOS_PER_IOTA } from '@iota/iota-sdk/utils';
import { formatAddress, formatDigest, NANOS_PER_IOTA } from '@iota/iota-sdk/utils';
import { getElapsedTime } from '~/pages/epochs/utils';

/**
Expand All @@ -25,7 +25,7 @@ export function generateTransactionsTableColumns(): ColumnDef<IotaTransactionBlo
<TableCellBase>
<TransactionLink
digest={digest}
label={<TableCellText>{formatAddress(digest)}</TableCellText>}
label={<TableCellText>{formatDigest(digest)}</TableCellText>}
/>
</TableCellBase>
);
Expand Down
6 changes: 3 additions & 3 deletions apps/explorer/src/pages/object-result/views/ObjectView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CoinFormat, useFormatCoin } from '@iota/core';
import { type IotaObjectResponse, type ObjectOwner } from '@iota/iota-sdk/client';
import {
formatAddress,
formatDigest,
IOTA_TYPE_ARG,
normalizeStructTag,
parseStructTag,
Expand Down Expand Up @@ -113,12 +114,11 @@ function TypeCard({ objectType }: TypeCardCardProps): JSX.Element {
};

const normalizedStructTag = normalizeStructTag(structTag);

return (
<DisplayStats
label="Type"
value={
<ObjectLink objectId={`${address}?module=${module}`}>
<ObjectLink objectId={`${address}?module=${module}`} label={normalizedStructTag}>
{normalizedStructTag}
</ObjectLink>
}
Expand All @@ -144,7 +144,7 @@ function LastTxBlockCard({ digest }: LastTxBlockCardProps): JSX.Element {
return (
<DisplayStats
label="Last Transaction Block Digest"
value={<TransactionLink digest={digest}>{formatAddress(digest)}</TransactionLink>}
value={<TransactionLink digest={digest}>{formatDigest(digest)}</TransactionLink>}
/>
);
}
Expand Down
13 changes: 13 additions & 0 deletions sdk/typescript/src/utils/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Modifications Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { isValidIotaAddress, isValidIotaObjectId, IOTA_ADDRESS_LENGTH } from './iota-types.js';

const ELLIPSIS = '\u{2026}';

export function formatAddress(address: string) {
Expand All @@ -18,3 +20,14 @@ export function formatDigest(digest: string) {
// Use 10 first characters
return `${digest.slice(0, 10)}${ELLIPSIS}`;
}

export function formatType(type: string) {
const objectAddressPattern = new RegExp(`0x[a-fA-F0-9]{${IOTA_ADDRESS_LENGTH * 2}}`, 'g');
const matches = type.match(objectAddressPattern) ?? [];
for (const match of matches) {
if (isValidIotaAddress(match) || isValidIotaObjectId(match)) {
type = type.replace(match, formatAddress(match));
}
}
return type;
}
2 changes: 1 addition & 1 deletion sdk/typescript/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Modifications Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export { formatAddress, formatDigest } from './format.js';
export { formatAddress, formatDigest, formatType } from './format.js';
export {
isValidIotaAddress,
isValidIotaObjectId,
Expand Down
19 changes: 19 additions & 0 deletions sdk/typescript/test/unit/format.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { describe, expect, it } from 'vitest';
import { formatType } from '../../src/utils';

describe('Formatters', () => {
it('formatType formats correctly', async () => {
const typeClock = '0x2::clock::Clock';
expect(formatType(typeClock), '0x0000…0002::clock::Clock');

const typeCoolCoin =
'0x2::coin::Coin<0x2e0b8d1e74947a2d97121bc7b7981eaff1f32911d15c5e0921fdd08cf61f445b::cool_coin::COOL_COIN>';
expect(
formatType(typeCoolCoin),
'0x0000…0002::coin::Coin<x2e0b8d…445b::cool_coin::COOL_COIN>',
);
});
});
Loading