Skip to content

Commit

Permalink
Explorer demo cleanup (MystenLabs#2367)
Browse files Browse the repository at this point in the history
* remove special demo name handling

* remove more number[] handling in explorer

* lint changes

* replace old AddressOwner code

* lint changes

* fix mock data for new object owner

* lint changes

* Update ObjectResultType.tsx

* move isOwnerStr function

* lint changes

* add SingleOwner

* lint changes

* remove anyvec and old comment

* add singleowner to TS sdk types

* remove redundant typedef in getOwnerStr

* lint changes

* Update DefaultRpcClient.ts

* Update index.guard.ts
  • Loading branch information
Stella Cannefax authored Jun 21, 2022
1 parent 1a57bbe commit 9746a53
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 216 deletions.
6 changes: 3 additions & 3 deletions explorer/client/src/components/displaybox/DisplayBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

import { useState, useCallback, useEffect } from 'react';

import { processDisplayValue } from '../../utils/stringUtils';
import { transformURL } from '../../utils/stringUtils';

import styles from './DisplayBox.module.css';

function DisplayBox({ display }: { display: string | { bytes: number[] } }) {
function DisplayBox({ display }: { display: string }) {
const [hasDisplayLoaded, setHasDisplayLoaded] = useState(false);
const [hasFailedToLoad, setHasFailedToLoad] = useState(false);

Expand Down Expand Up @@ -47,7 +47,7 @@ function DisplayBox({ display }: { display: string | { bytes: number[] } }) {
className={styles.imagebox}
style={imageStyle}
alt="NFT"
src={processDisplayValue(display)}
src={transformURL(display)}
onLoad={handleImageLoad}
onError={handleImageFail}
/>
Expand Down
4 changes: 2 additions & 2 deletions explorer/client/src/components/ownedobjects/OwnedObjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from '../../utils/static/searchUtil';
import {
handleCoinType,
processDisplayValue,
transformURL,
trimStdLibPrefix,
} from '../../utils/stringUtils';
import DisplayBox from '../displaybox/DisplayBox';
Expand Down Expand Up @@ -137,7 +137,7 @@ function OwnedObjectAPI({ id, byAddress }: { id: string; byAddress: boolean }) {
Type: objType,
_isCoin: Coin.isCoin(resp),
display: url
? processDisplayValue(url)
? transformURL(url)
: undefined,
balance: balanceValue,
};
Expand Down
148 changes: 15 additions & 133 deletions explorer/client/src/pages/object-result/ObjectLoaded.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ import OwnedObjects from '../../components/ownedobjects/OwnedObjects';
import TxForID from '../../components/transactions-for-id/TxForID';
import codestyle from '../../styles/bytecode.module.css';
import theme from '../../styles/theme.module.css';
import { type AddressOwner } from '../../utils/api/DefaultRpcClient';
import { parseImageURL } from '../../utils/objectUtils';
import {
asciiFromNumberBytes,
trimStdLibPrefix,
} from '../../utils/stringUtils';
import { getOwnerStr, parseImageURL } from '../../utils/objectUtils';
import { trimStdLibPrefix } from '../../utils/stringUtils';
import { type DataType } from './ObjectResultType';

import styles from './ObjectResult.module.css';
Expand Down Expand Up @@ -55,142 +51,25 @@ function ObjectLoaded({ data }: { data: DataType }) {
const checkIsPropertyType = (value: any) =>
['number', 'string'].includes(typeof value);

//TODO - a backend convention on how owned objects are labelled and how values are stored
//This would facilitate refactoring the below and stopping bugs when a variant is missed:
const addrOwnerPattern = /^AddressOwner\(k#/;
const endParensPattern = /\){1}$/;

//TODO - improve move code handling:
// const isMoveVecType = (value: { vec?: [] }) => Array.isArray(value?.vec);
// TODO - merge / replace with other version of same thing
const stdLibRe = /0x2::/;
const prepObjTypeValue = (typeString: string) =>
typeString.replace(stdLibRe, '');

const extractOwnerData = (owner: string | AddressOwner): string => {
switch (typeof owner) {
case 'string':
if (addrOwnerPattern.test(owner)) {
let ownerId = getAddressOwnerId(owner);
return ownerId ? ownerId : '';
}
const singleOwnerPattern = /SingleOwner\(k#(.*)\)/;
const result = singleOwnerPattern.exec(owner);
return result ? result[1] : '';
case 'object':
if ('AddressOwner' in owner) {
let ownerId = extractAddressOwner(owner.AddressOwner);
return ownerId ? ownerId : '';
}
return '';
default:
return '';
}
};
const getAddressOwnerId = (addrOwner: string): string | null => {
if (
!addrOwnerPattern.test(addrOwner) ||
!endParensPattern.test(addrOwner)
)
return null;

let str = addrOwner.replace(addrOwnerPattern, '');
return str.replace(endParensPattern, '');
};

const extractAddressOwner = (addrOwner: number[]): string | null => {
if (addrOwner.length !== 20) {
console.log('address owner byte length must be 20');
return null;
}

return asciiFromNumberBytes(addrOwner);
};
type SuiIdBytes = { bytes: number[] };

function handleSpecialDemoNameArrays(data: {
name?: string;
player_name?: SuiIdBytes | string;
monster_name?: SuiIdBytes | string;
farm_name?: SuiIdBytes | string;
}): string {
let bytesObj: SuiIdBytes = { bytes: [] };

if ('player_name' in data) {
bytesObj = data.player_name as SuiIdBytes;
const ascii = asciiFromNumberBytes(bytesObj.bytes);
delete data.player_name;
return ascii;
} else if ('monster_name' in data) {
bytesObj = data.monster_name as SuiIdBytes;
const ascii = asciiFromNumberBytes(bytesObj.bytes);
delete data.monster_name;
return ascii;
} else if ('farm_name' in data) {
bytesObj = data.farm_name as SuiIdBytes;
const ascii = asciiFromNumberBytes(bytesObj.bytes);
delete data.farm_name;
return ascii;
} else if ('name' in data) {
return data['name'] as string;
} else {
bytesObj = { bytes: [] };
}

return asciiFromNumberBytes(bytesObj.bytes);
}

function toHexString(byteArray: number[]): string {
return (
'0x' +
Array.prototype.map
.call(byteArray, (byte) => {
return ('0' + (byte & 0xff).toString(16)).slice(-2);
})
.join('')
);
}

function processName(name: string | undefined) {
// hardcode a friendly name for gas for now
const gasTokenTypeStr = 'Coin::Coin<0x2::GAS::GAS>';
const gasTokenId = '0000000000000000000000000000000000000003';
if (data.objType === gasTokenTypeStr && data.id === gasTokenId)
return 'GAS';

if (!name) {
return handleSpecialDemoNameArrays(data.data.contents);
}
}

function processOwner(owner: any) {
if (typeof owner === 'object' && 'AddressOwner' in owner) {
return toHexString(owner.AddressOwner);
}

return owner;
}

const viewedData = {
...data,
objType: trimStdLibPrefix(data.objType),
name: processName(data.name),
tx_digest:
data.data.tx_digest && typeof data.data.tx_digest === 'object'
? toHexString(data.data.tx_digest as number[])
: data.data.tx_digest,
owner: processOwner(data.owner),
name: data.name,
tx_digest: data.data.tx_digest,
owner: getOwnerStr(data.owner),
url: parseImageURL(data.data.contents),
};

//TO DO remove when have distinct name field under Description
const nameKeyValue = Object.entries(viewedData.data?.contents)
.filter(([key, _]) => /name/i.test(key))
.filter(([key, _]) => key === 'name')
.map(([_, value]) => value);

const properties = Object.entries(viewedData.data?.contents)
//TO DO: remove when have distinct 'name' field in Description
.filter(([key, _]) => !/name/i.test(key))
.filter(([key, _]) => key !== 'name')
.filter(([_, value]) => checkIsPropertyType(value));

const descriptionTitle =
Expand Down Expand Up @@ -288,14 +167,17 @@ function ObjectLoaded({ data }: { data: DataType }) {
<div>Owner</div>
<div id="owner">
<Longtext
text={extractOwnerData(data.owner)}
text={
typeof viewedData.owner ===
'string'
? viewedData.owner
: typeof viewedData.owner
}
category="unknown"
// TODO: make this more elegant
isLink={
extractOwnerData(data.owner) !==
viewedData.owner !==
'Immutable' &&
extractOwnerData(data.owner) !==
'Shared'
viewedData.owner !== 'Shared'
}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion explorer/client/src/pages/object-result/ObjectResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
const DATATYPE_DEFAULT: DataType = {
id: '',
category: '',
owner: '',
owner: 'Immutable',
version: '',
objType: '',
data: {
Expand Down
17 changes: 2 additions & 15 deletions explorer/client/src/pages/object-result/ObjectResultType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ import {
getObjectPreviousTransactionDigest,
} from '@mysten/sui.js';

import { type AddressOwner } from '../../utils/api/DefaultRpcClient';
import { parseObjectType } from '../../utils/objectUtils';

import type { GetObjectDataResponse, ObjectOwner } from '@mysten/sui.js';

export type DataType = {
id: string;
category?: string;
owner: string | AddressOwner;
owner: ObjectOwner | { SingleOwner: string };
version: string;
readonly?: string;
objType: string;
Expand Down Expand Up @@ -52,7 +51,7 @@ export function translate(o: GetObjectDataResponse): DataType {
id: getObjectId(o),
version: getObjectVersion(o)!.toString(),
objType: parseObjectType(o),
owner: parseOwner(getObjectOwner(o)!),
owner: getObjectOwner(o)!,
data: {
contents: getObjectFields(o) ?? getMovePackageContent(o)!,
tx_digest: getObjectPreviousTransactionDigest(o),
Expand All @@ -76,15 +75,3 @@ export function translate(o: GetObjectDataResponse): DataType {
}
}
}

function parseOwner(owner: ObjectOwner): string {
let result = '';
if (typeof owner === 'string') {
result = owner;
} else if ('AddressOwner' in owner) {
result = owner['AddressOwner'];
} else {
result = owner['ObjectOwner'];
}
return `SingleOwner(k#${result})`;
}
13 changes: 3 additions & 10 deletions explorer/client/src/utils/api/DefaultRpcClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,11 @@ import { deduplicate } from '../searchUtil';
import { getEndpoint, Network } from './rpcSetting';

import type {
CertifiedTransaction,
TransactionEffectsResponse,
GetTxnDigestsResponse,
TransactionEffectsResponse,
CertifiedTransaction,
} from '@mysten/sui.js';

// TODO: Remove these types with SDK types
export type AddressBytes = number[];
export type AddressOwner = { AddressOwner: AddressBytes };

export type AnyVec = { vec: any[] };
export type JsonBytes = { bytes: number[] };

export { Network, getEndpoint };

export const DefaultRpcClient = (network: Network | string) =>
Expand All @@ -41,7 +34,7 @@ export const getDataOnTxDigests = (
.then((txEffs: TransactionEffectsResponse[]) => {
return (
txEffs
.map((txEff, i) => {
.map((txEff) => {
const [seq, digest] = transactions.filter(
(transactionId) =>
transactionId[1] ===
Expand Down
15 changes: 14 additions & 1 deletion explorer/client/src/utils/objectUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { getObjectType, getMoveObjectType } from '@mysten/sui.js';
import {
getObjectType,
getMoveObjectType,
type ObjectOwner,
} from '@mysten/sui.js';

import type { GetObjectDataResponse } from '@mysten/sui.js';

Expand All @@ -26,3 +30,12 @@ export function parseObjectType(data: GetObjectDataResponse): string {
}
return 'unknown';
}

export function getOwnerStr(owner: ObjectOwner | string): string {
if (typeof owner === 'object') {
if ('AddressOwner' in owner) return owner.AddressOwner;
if ('ObjectOwner' in owner) return owner.ObjectOwner;
if ('SingleOwner' in owner) return owner.SingleOwner;
}
return owner;
}
Loading

0 comments on commit 9746a53

Please sign in to comment.