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

[explorer] Fix smart contract rendering #1778

Merged
merged 3 commits into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions explorer/client/src/components/ownedobjects/OwnedObjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

import React, { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { getObjectExistsResponse } from 'sui.js';
import { getObjectContent, getObjectExistsResponse } from 'sui.js';

import { DefaultRpcClient as rpc } from '../../utils/api/DefaultRpcClient';
import { parseImageURL } from '../../utils/objectUtils';
import { parseImageURL, parseObjectType } from '../../utils/objectUtils';
import { navigateWithUnknown } from '../../utils/searchUtil';
import {
findDataFromID,
Expand Down Expand Up @@ -82,16 +82,16 @@ function OwnedObjectAPI({ id }: { id: string }) {
.map(
(resp) => {
const info = getObjectExistsResponse(resp)!;
const contents = getObjectContent(resp);
const url = parseImageURL(info.object);
const balanceValue = (
typeof info.object.contents.fields
.balance === 'number'
? info.object.contents.fields.balance
typeof contents?.fields.balance === 'number'
? contents.fields.balance
: undefined
) as number;
return {
id: info.objectRef.objectId,
Type: info.object.contents.type,
Type: parseObjectType(info),
display: url
? processDisplayValue(url)
: undefined,
Expand Down
8 changes: 7 additions & 1 deletion explorer/client/src/pages/object-result/ObjectLoaded.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,13 @@ function ObjectLoaded({ data }: { data: DataType }) {
<Longtext
text={extractOwnerData(data.owner)}
category="unknown"
isLink={true}
// TODO: make this more elegant
isLink={
extractOwnerData(data.owner) !==
'Immutable' &&
extractOwnerData(data.owner) !==
'Shared'
}
/>
</div>
</div>
Expand Down
10 changes: 7 additions & 3 deletions explorer/client/src/pages/object-result/ObjectResultType.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { getMovePackageContent, getObjectContent, getObjectType } from 'sui.js';

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

import type {
Expand Down Expand Up @@ -47,16 +49,18 @@ export function translate(o: GetObjectInfoResponse): DataType {
case 'Exists': {
const {
objectRef: { objectId, version },
object: { contents, owner, tx_digest },
object: { owner, tx_digest },
} = details as ObjectExistsInfo;

return {
id: objectId,
version: version.toString(),
objType: contents['type'],
objType: getObjectType(o)!,
owner: parseOwner(owner),
data: {
contents: contents.fields,
contents:
getObjectContent(o)?.fields ??
getMovePackageContent(o)!,
tx_digest,
},
};
Expand Down
13 changes: 13 additions & 0 deletions explorer/client/src/utils/objectUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import type { ObjectExistsInfo } from 'sui.js';

export function parseImageURL(data: any): string {
if (data?.contents?.url?.fields) {
return data.contents.url.fields['url'];
Expand All @@ -11,3 +13,14 @@ export function parseImageURL(data: any): string {
}
return '';
}

export function parseObjectType(data: ObjectExistsInfo): string {
// TODO: define better naming and typing here
if (data.objectType === 'movePackage') {
return 'Move Package';
}
if (data.objectType === 'moveObject') {
return data.object.contents.type;
}
return 'unknown';
}
16 changes: 14 additions & 2 deletions sdk/typescript/src/index.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Generated type guards for "index.ts".
* WARNING: Do not manually change this file.
*/
import { Ed25519KeypairData, Keypair, PublicKeyInitData, PublicKeyData, SignedTransaction, TransactionResponse, TransferTransaction, TxnDataSerializer, TransactionDigest, SuiAddress, ObjectOwner, ObjectRef, ObjectContentField, ObjectContentFields, ObjectContent, SuiObject, ObjectExistsInfo, ObjectNotExistsInfo, ObjectStatus, ObjectType, GetOwnedObjectRefsResponse, GetObjectInfoResponse, ObjectDigest, ObjectId, SequenceNumber, RawObjectRef, Transfer, RawAuthoritySignInfo, TransactionKindName, SingleTransactionKind, TransactionKind, TransactionData, EpochId, AuthorityQuorumSignInfo, CertifiedTransaction, GasCostSummary, ExecutionStatusType, ExecutionStatus, ExecutionStatusDetail, OwnedObjectRef, TransactionEffects, TransactionEffectsResponse, GatewayTxSeqNumber, GetTxnDigestsResponse, MoveModulePublish, Event, StructTag, MoveTypeTag, MoveCall, MoveCallArg, EmptySignInfo, AuthorityName, AuthoritySignature } from "./index";
import { Ed25519KeypairData, Keypair, PublicKeyInitData, PublicKeyData, SignedTransaction, TransactionResponse, TransferTransaction, TxnDataSerializer, TransactionDigest, SuiAddress, ObjectOwner, ObjectRef, ObjectContentField, ObjectContentFields, ObjectContent, MovePackageContent, SuiObject, ObjectExistsInfo, ObjectNotExistsInfo, ObjectStatus, ObjectType, GetOwnedObjectRefsResponse, GetObjectInfoResponse, ObjectDigest, ObjectId, SequenceNumber, RawObjectRef, Transfer, RawAuthoritySignInfo, TransactionKindName, SingleTransactionKind, TransactionKind, TransactionData, EpochId, AuthorityQuorumSignInfo, CertifiedTransaction, GasCostSummary, ExecutionStatusType, ExecutionStatus, ExecutionStatusDetail, OwnedObjectRef, TransactionEffects, TransactionEffectsResponse, GatewayTxSeqNumber, GetTxnDigestsResponse, MoveModulePublish, Event, StructTag, MoveTypeTag, MoveCall, MoveCallArg, EmptySignInfo, AuthorityName, AuthoritySignature } from "./index";
import { BN } from "bn.js";

export function isEd25519KeypairData(obj: any, _argumentName?: string): obj is Ed25519KeypairData {
Expand Down Expand Up @@ -163,12 +163,24 @@ export function isObjectContent(obj: any, _argumentName?: string): obj is Object
)
}

export function isMovePackageContent(obj: any, _argumentName?: string): obj is MovePackageContent {
return (
(obj !== null &&
typeof obj === "object" ||
typeof obj === "function") &&
Object.entries<any>(obj)
.every(([key, value]) => (isTransactionResponse(value) as boolean &&
isTransactionResponse(key) as boolean))
)
}

export function isSuiObject(obj: any, _argumentName?: string): obj is SuiObject {
return (
(obj !== null &&
typeof obj === "object" ||
typeof obj === "function") &&
isObjectContent(obj.contents) as boolean &&
(isObjectContent(obj.contents) as boolean ||
isMovePackageContent(obj.contents) as boolean) &&
isObjectOwner(obj.owner) as boolean &&
isTransactionResponse(obj.tx_digest) as boolean
)
Expand Down
32 changes: 30 additions & 2 deletions sdk/typescript/src/types/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ export type ObjectContent = {
type: string;
};

export type MovePackageContent = Record<string, string>;

export type SuiObject = {
contents: ObjectContent;
contents: ObjectContent | MovePackageContent;
owner: ObjectOwner;
tx_digest: TransactionDigest;
};
Expand Down Expand Up @@ -69,8 +71,34 @@ export function getObjectExistsResponse(
: (resp.details as ObjectExistsInfo);
}

export function getObjectType(
resp: GetObjectInfoResponse
): 'moveObject' | 'movePackage' | undefined {
return getObjectExistsResponse(resp)?.objectType;
}

export function getObjectContent(
resp: GetObjectInfoResponse
): ObjectContent | undefined {
return getObjectExistsResponse(resp)?.object.contents;
const existsInfo = getObjectExistsResponse(resp);
if (existsInfo == null) {
return undefined;
}
const { object, objectType } = existsInfo;
return objectType === 'moveObject'
? (object.contents as ObjectContent)
: undefined;
}

export function getMovePackageContent(
resp: GetObjectInfoResponse
): MovePackageContent | undefined {
const existsInfo = getObjectExistsResponse(resp);
if (existsInfo == null) {
return undefined;
}
const { object, objectType } = existsInfo;
return objectType === 'movePackage'
? (object.contents as MovePackageContent)
: undefined;
}
19 changes: 19 additions & 0 deletions sdk/typescript/test/mocks/data/objects.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,24 @@
"tx_digest": "vU/KG88bjX8VgdNtflBjNUFNZAqYv2qMCwP9S0+tQRc="
}
}
},

"move_package": {
"status": "Exists",
"details": {
"objectRef": {
"objectId": "8070e826b3668a048a59a095de23ec26491ca2d9",
"version": 1,
"digest": "mpvRbMifZveAfw0wnss0EwtUhc0XgeTvQWO5V0vG790="
},
"objectType": "movePackage",
"object": {
"contents": {
"M1": "// Move bytecode v5\nmodule 8070e826b3668a048a59a095de23ec26491ca2d9.M1 {\nstruct Forge has store, key {\n\tid: VersionedID,\n\tswords_created: u64\n}\nstruct Sword has store, key {\n\tid: VersionedID,\n\tmagic: u64,\n\tstrength: u64\n}\n\ninit(loc0: &mut TxContext) {\nB0:\n\t0: CopyLoc[0](Arg0: &mut TxContext)\n\t1: Call[6](new_id(&mut TxContext): VersionedID)\n\t2: LdU64(0)\n\t3: Pack[0](Forge)\n\t4: StLoc[1](loc0: Forge)\n\t5: MoveLoc[1](loc0: Forge)\n\t6: MoveLoc[0](Arg0: &mut TxContext)\n\t7: FreezeRef\n\t8: Call[7](sender(&TxContext): address)\n\t9: Call[0](transfer<Forge>(Forge, address))\n\t10: Ret\n}\npublic magic(): u64 {\nB0:\n\t0: MoveLoc[0](Arg0: &Sword)\n\t1: ImmBorrowField[0](Sword.magic: u64)\n\t2: ReadRef\n\t3: Ret\n}\npublic strength(): u64 {\nB0:\n\t0: MoveLoc[0](Arg0: &Sword)\n\t1: ImmBorrowField[1](Sword.strength: u64)\n\t2: ReadRef\n\t3: Ret\n}\npublic(script) sword_create(loc0: &mut Forge) {\nB0:\n\t0: MoveLoc[4](Arg4: &mut TxContext)\n\t1: Call[6](new_id(&mut TxContext): VersionedID)\n\t2: MoveLoc[1](Arg1: u64)\n\t3: MoveLoc[2](Arg2: u64)\n\t4: Pack[1](Sword)\n\t5: StLoc[5](loc0: Sword)\n\t6: MoveLoc[5](loc0: Sword)\n\t7: MoveLoc[3](Arg3: address)\n\t8: Call[1](transfer<Sword>(Sword, address))\n\t9: CopyLoc[0](Arg0: &mut Forge)\n\t10: ImmBorrowField[2](Forge.swords_created: u64)\n\t11: ReadRef\n\t12: LdU64(1)\n\t13: Add\n\t14: MoveLoc[0](Arg0: &mut Forge)\n\t15: MutBorrowField[2](Forge.swords_created: u64)\n\t16: WriteRef\n\t17: Ret\n}\npublic(script) sword_transfer() {\nB0:\n\t0: MoveLoc[0](Arg0: Sword)\n\t1: MoveLoc[1](Arg1: address)\n\t2: Call[1](transfer<Sword>(Sword, address))\n\t3: Ret\n}\npublic swords_created(): u64 {\nB0:\n\t0: MoveLoc[0](Arg0: &Forge)\n\t1: ImmBorrowField[2](Forge.swords_created: u64)\n\t2: ReadRef\n\t3: Ret\n}\n}"
},
"owner": "Immutable",
"tx_digest": "Zy76499PkX9Rm4DEWEj5o1NSnLWqu/700Xfx+bd4qSc="
}
}
}
}
5 changes: 4 additions & 1 deletion sdk/typescript/test/types/objects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ describe('Test Objects Definition', () => {
it('Test against different object definitions', () => {
validate('coin');
validate('example_nft');
validate('move_package');
});
});

function validate(key: 'coin' | 'example_nft'): GetObjectInfoResponse {
function validate(
key: 'coin' | 'example_nft' | 'move_package'
): GetObjectInfoResponse {
const data = mockObjectData[key];
expect(isGetObjectInfoResponse(data)).toBeTruthy();
return data as GetObjectInfoResponse;
Expand Down