diff --git a/explorer/client/package.json b/explorer/client/package.json index 366714fb1a73e..0d089cdc7f51f 100644 --- a/explorer/client/package.json +++ b/explorer/client/package.json @@ -13,7 +13,6 @@ "@types/react": "^17.0.39", "@types/react-dom": "^17.0.11", "autoprefixer": "^10.4.2", - "concurrently": "^7.0.0", "eslint-config-prettier": "^8.3.0", "jest-puppeteer": "^6.1.0", "onchange": "^7.1.0", @@ -29,14 +28,11 @@ "typescript": "^4.5.5" }, "dependencies": { - "ace-builds": "^1.4.14", "classnames": "^2.3.1", "react": "^17.0.2", - "react-ace": "^9.5.0", "react-dom": "^17.0.2", "react-router-dom": "^6.2.1", "@mysten/sui.js": "file:../../sdk/typescript", - "swr": "^1.2.2", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/explorer/client/src/__tests__/e2e.test.ts b/explorer/client/src/__tests__/e2e.test.ts index 703c84233dece..5ae14cd848e8a 100644 --- a/explorer/client/src/__tests__/e2e.test.ts +++ b/explorer/client/src/__tests__/e2e.test.ts @@ -102,96 +102,9 @@ describe('End-to-end Tests', () => { }); }); - // TODO - rewrite this test to use the new transaction data and state object - /* - describe('Transaction Results', () => { - //Specific to transaction tests: - const successTransactionID = 'txCreateSuccess'; - const failTransactionID = 'txFails'; - const pendingTransactionID = 'txSendPending'; - const missingDataTransactionID = 'txMissingData'; - - const checkStatus = async ( - page: any, - expected: 'success' | 'pending' | 'fail' - ) => { - const actual = await page.$eval( - '#transactionStatus', - (el: any) => el.textContent - ); - expect(actual).toBe(expected); - }; - - it('can be searched', async () => { - await page.goto(BASE_URL); - await searchText(page, successTransactionID); - const el = await page.$('#transactionID'); - const value = await page.evaluate((el: any) => el.textContent, el); - expect(value.trim()).toBe(successTransactionID); - }); - - it('can be reached through URL', async () => { - await page.goto(BASE_URL); - await page.goto(`${BASE_URL}/transactions/${successTransactionID}`); - const el = await page.$('#transactionID'); - const value = await page.evaluate((el: any) => el.textContent, el); - expect(value.trim()).toBe(successTransactionID); - }); - it('has correct structure', async () => { - await page.goto(`${BASE_URL}/transactions/${successTransactionID}`); - - const labels = [ - 'Transaction ID', - 'Status', - 'From', - 'Event', - 'Object', - 'To', - ]; - - for (let i = 1; i <= labels.length; i++) { - const value = await page.$eval( - `div#textResults > div:nth-child(${i}) > div:nth-child(1)`, - (el: any) => el.textContent - ); - expect(value.trim()).toBe(labels[i - 1]); - } - }); - - it('can be a success', async () => { - await page.goto(`${BASE_URL}/transactions/${successTransactionID}`); - await checkStatus(page, 'success'); - }); - - it('can be pending', async () => { - await page.goto(`${BASE_URL}/transactions/${pendingTransactionID}`); - await checkStatus(page, 'pending'); - }); - it('can fail', async () => { - await page.goto(`${BASE_URL}/transactions/${failTransactionID}`); - await checkStatus(page, 'fail'); - }); - it('can have missing data', async () => { - await page.goto( - `${BASE_URL}/transactions/${missingDataTransactionID}` - ); - await expectErrorResult(page); - }); - }); -*/ describe('Object Results', () => { const successObjectID = 'CollectionObject'; const problemObjectID = 'ProblemObject'; - const readOnlyObject = 'ComponentObject'; - const notReadOnlyObject = 'CollectionObject'; - - const checkStatus = async (page: any, expected: 'True' | 'False') => { - const actual = await page.$eval( - '#readOnlyStatus', - (el: any) => el.textContent - ); - expect(actual).toBe(expected); - }; it('can be searched', async () => { await page.goto(BASE_URL); @@ -208,34 +121,7 @@ describe('End-to-end Tests', () => { const value = await page.evaluate((el: any) => el.textContent, el); expect(value.trim()).toBe(successObjectID); }); - it('has correct structure', async () => { - await page.goto(`${BASE_URL}/objects/${successObjectID}`); - - const labels = [ - 'Object ID', - 'Version', - 'Read Only?', - 'Type', - 'Owner', - ]; - - for (let i = 1; i <= labels.length; i++) { - const value = await page.$eval( - `div#descriptionResults > div:nth-child(${i}) > div:nth-child(1)`, - (el: any) => el.textContent - ); - expect(value.trim()).toBe(labels[i - 1]); - } - }); - it('can be read only', async () => { - await page.goto(`${BASE_URL}/objects/${readOnlyObject}`); - await checkStatus(page, 'True'); - }); - it('can be not read only', async () => { - await page.goto(`${BASE_URL}/objects/${notReadOnlyObject}`); - await checkStatus(page, 'False'); - }); it('can have missing data', async () => { await page.goto(`${BASE_URL}/objects/${problemObjectID}`); await expectErrorResult(page); @@ -259,25 +145,51 @@ describe('End-to-end Tests', () => { const value = await page.evaluate((el: any) => el.textContent, el); expect(value.trim()).toBe(successAddressID); }); - it('has correct structure', async () => { - await page.goto(`${BASE_URL}/addresses/${successAddressID}`); - - const labels = ['Address', 'Owned Objects']; - - for (let i = 1; i <= labels.length; i++) { - const value = await page.$eval( - `div#textResults > div:nth-child(${i}) > div:nth-child(1)`, - (el: any) => el.textContent - ); - expect(value.trim()).toBe(labels[i - 1]); - } - }); it('displays error when no objects', async () => { await page.goto(`${BASE_URL}/objects/${noObjectsAddressID}`); await expectErrorResult(page); }); }); - describe('Enables clicking links to', () => { + + describe('Transaction Results', () => { + const successID = 'Da4vHc9IwbvOYblE8LnrVsqXwryt2Kmms+xnJ7Zx5E4='; + it('can be searched', async () => { + await page.goto(BASE_URL); + await searchText(page, successID); + const el = await page.$('#transactionID'); + const value = await page.evaluate((el: any) => el.textContent, el); + expect(value.trim()).toBe(successID); + }); + + it('can be reached through URL', async () => { + await page.goto(`${BASE_URL}/transactions/${successID}`); + const el = await page.$('#transactionID'); + const value = await page.evaluate((el: any) => el.textContent, el); + expect(value.trim()).toBe(successID); + }); + it('can go to object and back', async () => { + const objectID = '7bc832ec31709638cd8d9323e90edf332gff4389'; + await page.goto(`${BASE_URL}/transactions/${successID}`); + + //Go to Object + const objectLink = await page.$( + 'div#txview > div:nth-child(4) > div:nth-child(2)' + ); + await objectLink.click(); + const el = await page.$('#objectID'); + const value = await page.evaluate((x: any) => x.textContent, el); + expect(value.trim()).toBe(objectID); + + //Go back to Transaction + const lastTransactionLink = await page.$('#lasttxID > a'); + await lastTransactionLink.click(); + const el2 = await page.$('#transactionID'); + const value2 = await page.evaluate((x: any) => x.textContent, el2); + expect(value2.trim()).toBe(successID); + }); + }); + + describe('Owned Objects have links that enable', () => { const navigationTemplate = async ( page: any, parentValue: string, @@ -315,7 +227,7 @@ describe('End-to-end Tests', () => { ); expect(parentText.trim()).toBe(parentValue); }; - it('go from address to object and back', async () => { + it('going from address to object and back', async () => { await navigationTemplate( page, 'receiverAddress', @@ -324,10 +236,10 @@ describe('End-to-end Tests', () => { 1 ); }); - it('go from object to child object and back', async () => { + it('going from object to child object and back', async () => { await navigationTemplate(page, 'player2', 'objects', 'Image1', 1); }); - it('go from parent to broken image object and back', async () => { + it('going from parent to broken image object and back', async () => { const parentValue = 'ObjectWBrokenChild'; await page.goto(`${BASE_URL}/objects/${parentValue}`); diff --git a/explorer/client/src/components/displaybox/DisplayBox.tsx b/explorer/client/src/components/displaybox/DisplayBox.tsx index 8a4d335bcc422..2d4a615d9a9ed 100644 --- a/explorer/client/src/components/displaybox/DisplayBox.tsx +++ b/explorer/client/src/components/displaybox/DisplayBox.tsx @@ -7,43 +7,7 @@ import { processDisplayValue } from '../../utils/stringUtils'; import styles from './DisplayBox.module.css'; -//TO DO - display smart contract info; see mock_data.json for example smart contract data -//import 'ace-builds/src-noconflict/theme-github'; -//import AceEditor from 'react-ace'; - -function SmartContractBox({ - display, -}: { - display: string | { bytes: number[] }; -}) { - return ( -
- Displaying Smart Contracts Not yet Supported -
- ); - /* - return ( -
- -
- ); - */ -} - -function DisplayBox({ - display, - tag, -}: { - display: string | { bytes: number[] }; - tag: 'imageURL' | 'moveScript'; -}) { +function DisplayBox({ display }: { display: string | { bytes: number[] } }) { const [hasDisplayLoaded, setHasDisplayLoaded] = useState(false); const [hasFailedToLoad, setHasFailedToLoad] = useState(false); @@ -66,37 +30,30 @@ function DisplayBox({ [setHasFailedToLoad] ); - if (tag === 'moveScript') { - return ; - } - - if (tag === 'imageURL') { - return ( -
- {!hasDisplayLoaded && ( -
- Please wait for display to load -
- )} - {hasFailedToLoad ? ( -
- No Image was Found -
- ) : ( - NFT - )} -
- ); - } - return
; + return ( +
+ {!hasDisplayLoaded && ( +
+ Please wait for display to load +
+ )} + {hasFailedToLoad ? ( +
+ No Image was Found +
+ ) : ( + NFT + )} +
+ ); } export default DisplayBox; diff --git a/explorer/client/src/components/ownedobjects/OwnedObjects.tsx b/explorer/client/src/components/ownedobjects/OwnedObjects.tsx index 57072fe00ee3f..8f02b906e9023 100644 --- a/explorer/client/src/components/ownedobjects/OwnedObjects.tsx +++ b/explorer/client/src/components/ownedobjects/OwnedObjects.tsx @@ -6,6 +6,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { DefaultRpcClient as rpc } from '../../utils/api/DefaultRpcClient'; +import { IS_STATIC_ENV } from '../../utils/envUtil'; import { parseImageURL, parseObjectType } from '../../utils/objectUtils'; import { navigateWithUnknown } from '../../utils/searchUtil'; import { @@ -41,13 +42,8 @@ const IS_COIN_TYPE = (typeDesc: string): boolean => /::Coin::/.test(typeDesc); const lastRowHas2Elements = (itemList: any[]): boolean => itemList.length % 3 === 2; -function OwnedObject({ id }: { id: string }) { - if (process.env.REACT_APP_DATA === 'static') { - return ; - } else { - return ; - } -} +const OwnedObject = ({ id }: { id: string }) => + IS_STATIC_ENV ? : ; function OwnedObjectStatic({ id }: { id: string }) { const objects = findOwnedObjectsfromID(id); @@ -357,18 +353,7 @@ function OwnedObjectView({ results }: { results: resultType }) { > {entryObj.display !== undefined && (
- +
)} {Object.entries(entryObj).map(([key, value], index2) => ( diff --git a/explorer/client/src/components/transaction-card/RecentTxCard.tsx b/explorer/client/src/components/transaction-card/RecentTxCard.tsx index a4b2d505d536c..5a977a197065a 100644 --- a/explorer/client/src/components/transaction-card/RecentTxCard.tsx +++ b/explorer/client/src/components/transaction-card/RecentTxCard.tsx @@ -15,6 +15,8 @@ import { Link } from 'react-router-dom'; import Longtext from '../../components/longtext/Longtext'; import theme from '../../styles/theme.module.css'; import { DefaultRpcClient as rpc } from '../../utils/api/DefaultRpcClient'; +import { IS_STATIC_ENV } from '../../utils/envUtil'; +import { getAllMockTransaction } from '../../utils/static/searchUtil'; import ErrorResult from '../error-result/ErrorResult'; import type { @@ -111,54 +113,11 @@ function truncate(fullStr: string, strLen: number, separator: string) { ); } -function LatestTxCard() { - const [isLoaded, setIsLoaded] = useState(false); - const [results, setResults] = useState(initState); - useEffect(() => { - let isMounted = true; - getRecentTransactions(15) - .then((resp: any) => { - if (isMounted) { - setIsLoaded(true); - } - setResults({ - loadState: 'loaded', - latestTx: resp, - }); - }) - .catch((err) => { - setResults({ - ...initState, - loadState: 'fail', - }); - setIsLoaded(false); - }); - - return () => { - isMounted = false; - }; - }, []); - if (results.loadState === 'pending') { - return ( -
-
Loading...
-
- ); - } - - if (!isLoaded && results.loadState === 'fail') { - return ( - - ); - } - - if (results.loadState === 'loaded' && !results.latestTx.length) { - return ; - } - +function LatestTxView({ + results, +}: { + results: { loadState: string; latestTx: TxnData[] }; +}) { return (
@@ -234,4 +193,71 @@ function LatestTxCard() { ); } +function LatestTxCardStatic() { + const latestTx = getAllMockTransaction().map((tx) => ({ + ...tx, + status: tx.status as ExecutionStatusType, + kind: tx.kind as TransactionKindName, + })); + const results = { + loadState: 'loaded', + latestTx: latestTx, + }; + return ; +} + +function LatestTxCardAPI() { + const [isLoaded, setIsLoaded] = useState(false); + const [results, setResults] = useState(initState); + useEffect(() => { + let isMounted = true; + getRecentTransactions(15) + .then((resp: any) => { + if (isMounted) { + setIsLoaded(true); + } + setResults({ + loadState: 'loaded', + latestTx: resp, + }); + }) + .catch((err) => { + setResults({ + ...initState, + loadState: 'fail', + }); + setIsLoaded(false); + }); + + return () => { + isMounted = false; + }; + }, []); + if (results.loadState === 'pending') { + return ( +
+
Loading...
+
+ ); + } + + if (!isLoaded && results.loadState === 'fail') { + return ( + + ); + } + + if (results.loadState === 'loaded' && !results.latestTx.length) { + return ; + } + + return ; +} + +const LatestTxCard = () => + IS_STATIC_ENV ? : ; + export default LatestTxCard; diff --git a/explorer/client/src/components/transaction-card/TransactionCard.module.css b/explorer/client/src/components/transaction-card/TransactionCard.module.css deleted file mode 100644 index 3d10db513b499..0000000000000 --- a/explorer/client/src/components/transaction-card/TransactionCard.module.css +++ /dev/null @@ -1,81 +0,0 @@ -div.txcard { - @apply bg-white px-6 pt-0 pb-0 bg-center rounded-lg shadow-md border-2 border-coolGray-400 - font-sans break-all tracking-tight font-semibold block pl-0 pr-0 m-auto mt-0 mb-10; - @apply pr-0 pl-0 w-full block !important; -} - -div.columnheader > div { - @apply font-sans text-white; -} - -div.txcardgrid { - @apply grid md:grid-cols-3 sm:grid-cols-1 gap-2 border-0 pt-3 pb-3 md:pl-8 md:pr-8 pl-4 pr-4 items-center; -} - -div.txcardgrid:nth-child(2n + 1) { - @apply bg-[#f6f6f6]; -} - -.listitems .sublist > div { - @apply break-all break-words max-w-[84vw] overflow-auto; -} - -div.txcardgrid:first-child { - @apply bg-offblack rounded-none items-center pt-5 pb-5 font-black shadow-md border-2 border-coolGray-400; -} - -div.txcardgrid > div:first-child { - @apply col-span-1 font-normal w-[90vw]; -} - -div.txcardgrid > div:last-child { - @apply border-none; -} - -div.txcardgridlarge { - @apply font-mono break-all tracking-tight font-normal md:block col-span-2 max-w-[84vw]; -} - -div.status-success { - @apply text-green-600; -} - -div.status-fail { - @apply text-red-300; -} - -div.status-pending { - @apply text-orange-300; -} - -div.action-create { - @apply bg-lime-300; -} - -div.action-mutate { - @apply bg-blue-300; -} - -div.grouped { - @apply border-transparent !important; -} - -ul.listitems { - @apply list-none p-0 m-0; -} - -.listitems .list { - @apply mt-5 list-none p-0 max-w-[84vw]; -} - -.listitems .list:first-child { - @apply mt-0; -} - -.listitems .sublist { - @apply mt-2 list-none p-0 md:flex grid gap-2 pr-0 max-w-[84vw]; -} - -div.sublist .sublistlabel { - @apply w-28 flex-none; -} diff --git a/explorer/client/src/pages/object-result/ObjectLoaded.tsx b/explorer/client/src/pages/object-result/ObjectLoaded.tsx index 6305d76f0fbd5..21351e54d28d3 100644 --- a/explorer/client/src/pages/object-result/ObjectLoaded.tsx +++ b/explorer/client/src/pages/object-result/ObjectLoaded.tsx @@ -196,7 +196,7 @@ function ObjectLoaded({ data }: { data: DataType }) {
{viewedData.url !== '' && (
- +
)}
Last Transaction ID
-
+
{ } if (objID !== undefined) { - if (process.env.REACT_APP_DATA !== 'static') { - return ; - } else { - return ; - } + return IS_STATIC_ENV ? ( + + ) : ( + + ); } return ; diff --git a/explorer/client/src/pages/transaction-result/TransactionResult.module.css b/explorer/client/src/pages/transaction-result/TransactionResult.module.css index 813dfd8f646f9..48d664fa586a0 100644 --- a/explorer/client/src/pages/transaction-result/TransactionResult.module.css +++ b/explorer/client/src/pages/transaction-result/TransactionResult.module.css @@ -1,36 +1,69 @@ -div.status-success, -div.status-fail, -div.status-pending, -div.action-create, -div.action-mutate, -div.action-delete { - @apply h-[1.5rem] p-2; +.txdetailsbg { + @apply bg-[#f8f8f8]; +} + +div.txcard { + @apply bg-white px-6 pt-0 pb-0 bg-center rounded-lg shadow-md border-2 border-coolGray-400 + font-sans break-all tracking-tight font-semibold block pl-0 pr-0 m-auto mt-0 mb-10; + @apply pr-0 pl-0 w-full block !important; +} + +div.columnheader > div { + @apply font-sans text-white; +} + +div.txcardgrid { + @apply grid md:grid-cols-3 sm:grid-cols-1 gap-2 border-0 pt-3 pb-3 md:pl-8 md:pr-8 pl-4 pr-4 items-center; +} + +div.txcardgrid:nth-child(2n + 1) { + @apply bg-[#f6f6f6]; +} + +.listitems .sublist > div { + @apply break-all break-words max-w-[84vw] overflow-auto; +} + +div.txcardgrid:first-child { + @apply bg-offblack rounded-none items-center pt-5 pb-5 font-black shadow-md border-2 border-coolGray-400; +} + +div.txcardgrid > div:first-child { + @apply col-span-1 font-normal w-[90vw]; +} + +div.txcardgrid > div:last-child { + @apply border-none; +} + +div.txcardgridlarge { + @apply font-mono break-all tracking-tight font-normal md:block col-span-2 max-w-[84vw]; } div.status-success { - @apply bg-green-300; + @apply text-green-600; } div.status-fail { - @apply bg-red-300; + @apply text-red-300; } -div.status-pending { - @apply bg-orange-300; +ul.listitems { + @apply list-none p-0 m-0; } -div.action-create { - @apply bg-lime-300; +.listitems .list { + @apply mt-5 list-none p-0 max-w-[84vw]; } -div.action-mutate { - @apply bg-blue-300; +.listitems .list:first-child { + @apply mt-0; } -div.action-delete { - @apply bg-orange-300; +.listitems .sublist { + @apply mt-2 list-none p-0 md:flex grid gap-2 pr-0 max-w-[84vw]; } -.txdetailsbg { - @apply bg-[#f8f8f8]; +div.sublist .sublistlabel { + @apply w-28 flex-none; } diff --git a/explorer/client/src/pages/transaction-result/TransactionResult.tsx b/explorer/client/src/pages/transaction-result/TransactionResult.tsx index b86ccc0c66479..9bb5b66008f13 100644 --- a/explorer/client/src/pages/transaction-result/TransactionResult.tsx +++ b/explorer/client/src/pages/transaction-result/TransactionResult.tsx @@ -9,12 +9,15 @@ import { } from '@mysten/sui.js'; import cl from 'classnames'; import { useEffect, useState } from 'react'; -import { useParams } from 'react-router-dom'; +import { useLocation, useParams } from 'react-router-dom'; import ErrorResult from '../../components/error-result/ErrorResult'; -import TransactionCard from '../../components/transaction-card/TransactionCard'; import theme from '../../styles/theme.module.css'; import { DefaultRpcClient as rpc } from '../../utils/api/DefaultRpcClient'; +import { IS_STATIC_ENV } from '../../utils/envUtil'; +import { findDataFromID } from '../../utils/static/searchUtil'; +import { type DataType } from './TransactionResultType'; +import TransactionView from './TransactionView'; import type { CertifiedTransaction, @@ -64,8 +67,6 @@ const initState: TxnState = { created: [], }; -const useRealData = process.env.REACT_APP_DATA !== 'static'; -// if dev fetch data from mock_data.json function fetchTransactionData( txId: string | undefined ): Promise { @@ -73,10 +74,6 @@ function fetchTransactionData( if (!txId) { throw new Error('No Txid found'); } - if (!useRealData) { - throw new Error('Method not implemented for mock data.'); - } - return rpc .getTransactionWithEffects(txId) .then((txEff: TransactionEffectsResponse) => txEff); @@ -95,32 +92,37 @@ const getCreatedOrMutatedData = ( : []; }; -function TransactionResult() { - const { id } = useParams(); - const [showTxState, setTxState] = useState(initState); +const transformTransactionResponse = ( + txObj: TransactionEffectsResponse, + id: string +) => { + const executionStatus = txObj.effects.status; + const status = getExecutionStatusType(executionStatus); + const details = getExecutionDetails(executionStatus); + return { + ...txObj.certificate, + status, + gasFee: getTotalGasUsed(executionStatus), + txError: + 'error' in details + ? details.error[Object.keys(details.error)[0]].error + : '', + txId: id, + loadState: 'loaded', + mutated: getCreatedOrMutatedData(txObj.effects, 'mutated'), + created: getCreatedOrMutatedData(txObj.effects, 'created'), + }; +}; +const TransactionResultAPI = ({ id }: { id: string }) => { + const [showTxState, setTxState] = useState(initState); useEffect(() => { if (id == null) { return; } fetchTransactionData(id) .then((txObj) => { - const executionStatus = txObj.effects.status; - const status = getExecutionStatusType(executionStatus); - const details = getExecutionDetails(executionStatus); - setTxState({ - ...txObj.certificate, - status, - gasFee: getTotalGasUsed(executionStatus), - txError: - 'error' in details - ? details.error[Object.keys(details.error)[0]].error - : '', - txId: id, - loadState: 'loaded', - mutated: getCreatedOrMutatedData(txObj.effects, 'mutated'), - created: getCreatedOrMutatedData(txObj.effects, 'created'), - }); + setTxState(transformTransactionResponse(txObj, id)); }) .catch((err) => { console.log('Error fetching transaction data', err); @@ -135,39 +137,83 @@ function TransactionResult() { if (showTxState.loadState === 'pending') { return (
-
Loading...
+
Loading...
); } - // For Batch transactions show error - // TODO update Error screen and account for Batch transactions if ( - !id || - showTxState.loadState === 'fail' || - getSingleTransactionKind(showTxState.data) == null + id && + showTxState.loadState === 'loaded' && + getSingleTransactionKind(showTxState.data) !== null ) { - return ( - - ); + return ; } + // For Batch transactions show error + // TODO update Error screen and account for Batch transactions + return ( + + ); +}; + +const TransactionResultStatic = ({ id }: { id: string }) => { + const entry = findDataFromID(id, undefined); + + return ( + + ); +}; + +const TransactionResultLoaded = ({ txData }: { txData: DataType }) => { return (

Transaction Details

- {showTxState.loadState === 'loaded' && ( - - )} +
); +}; + +function TransactionResult() { + const { id } = useParams(); + const { state } = useLocation(); + + const checkStateHasData = ( + state: any + ): state is { data: TransactionEffectsResponse } => { + return state !== null && 'data' in state; + }; + + const checkIsString = (value: any): value is string => + typeof value === 'string'; + + if (checkStateHasData(state) && id) { + return ( + + ); + } + + if (checkIsString(id)) { + return IS_STATIC_ENV ? ( + + ) : ( + + ); + } + + return ; } export default TransactionResult; diff --git a/explorer/client/src/pages/transaction-result/TransactionResultType.tsx b/explorer/client/src/pages/transaction-result/TransactionResultType.tsx new file mode 100644 index 0000000000000..1f6a1ed35a089 --- /dev/null +++ b/explorer/client/src/pages/transaction-result/TransactionResultType.tsx @@ -0,0 +1,18 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import type { + CertifiedTransaction, + ExecutionStatusType, + RawObjectRef, +} from '@mysten/sui.js'; + +export type DataType = CertifiedTransaction & { + loadState: string; + txId: string; + status: ExecutionStatusType; + gasFee: number; + txError: string; + mutated: RawObjectRef[]; + created: RawObjectRef[]; +}; diff --git a/explorer/client/src/components/transaction-card/TransactionCard.tsx b/explorer/client/src/pages/transaction-result/TransactionView.tsx similarity index 96% rename from explorer/client/src/components/transaction-card/TransactionCard.tsx rename to explorer/client/src/pages/transaction-result/TransactionView.tsx index d0fe95083f782..d1713fdad9a4a 100644 --- a/explorer/client/src/components/transaction-card/TransactionCard.tsx +++ b/explorer/client/src/pages/transaction-result/TransactionView.tsx @@ -11,6 +11,7 @@ import { Buffer } from 'buffer'; import cl from 'classnames'; import Longtext from '../../components/longtext/Longtext'; +import { type DataType } from './TransactionResultType'; import type { CertifiedTransaction, @@ -20,7 +21,7 @@ import type { RawObjectRef, } from '@mysten/sui.js'; -import styles from './TransactionCard.module.css'; +import styles from './TransactionResult.module.css'; type TxDataProps = CertifiedTransaction & { status: ExecutionStatusType; @@ -31,7 +32,7 @@ type TxDataProps = CertifiedTransaction & { }; // Generate an Arr of Obj with Label and Value -// TODO rewrite to use sue.js, verify tx types and dynamically generate list +// TODO rewrite to use sui.js, verify tx types and dynamically generate list function formatTxResponse(tx: TxDataProps, txId: string) { // Todo add batch kind const txKindName = getTransactionKind(tx.data); @@ -191,24 +192,12 @@ function formatByTransactionKind( } } -type Props = { - txdata: CertifiedTransaction & { - loadState: string; - txId: string; - status: ExecutionStatusType; - gasFee: number; - txError: string; - mutated: RawObjectRef[]; - created: RawObjectRef[]; - }; -}; - -function TransactionCard({ txdata }: Props) { +function TransactionView({ txdata }: { txdata: DataType }) { return ( <> {txdata && ( -
-
+
+
{formatTxResponse(txdata, txdata.txId).map( (itm: any, index: number) => (
{itm.list ? (
    @@ -358,4 +352,4 @@ function TransactionCard({ txdata }: Props) { ); } -export default TransactionCard; +export default TransactionView; diff --git a/explorer/client/src/utils/api/searchUtil.ts b/explorer/client/src/utils/api/searchUtil.ts index 167f0c385cc88..de73af55ceda2 100644 --- a/explorer/client/src/utils/api/searchUtil.ts +++ b/explorer/client/src/utils/api/searchUtil.ts @@ -29,10 +29,12 @@ export const navigateWithUnknown = async ( }; }); - const txDetailsPromise = rpc.getTransaction(input).then((data) => ({ - category: 'transactions', - data: data, - })); + const txDetailsPromise = rpc + .getTransactionWithEffects(input) + .then((data) => ({ + category: 'transactions', + data: data, + })); return ( Promise.any([objInfoPromise, addrPromise, txDetailsPromise]) diff --git a/explorer/client/src/utils/envUtil.ts b/explorer/client/src/utils/envUtil.ts new file mode 100644 index 0000000000000..69686993b57c0 --- /dev/null +++ b/explorer/client/src/utils/envUtil.ts @@ -0,0 +1,4 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +export const IS_STATIC_ENV = process.env.REACT_APP_DATA === 'static'; diff --git a/explorer/client/src/utils/static/latest_transactions.json b/explorer/client/src/utils/static/latest_transactions.json new file mode 100644 index 0000000000000..5c4f3d93d9dcd --- /dev/null +++ b/explorer/client/src/utils/static/latest_transactions.json @@ -0,0 +1,22 @@ +{ + "data": [ + { + "From": "senderAddress", + "To": "receiverAddress", + "kind": "Transfer", + "seq": 7787, + "status": "Success", + "txGas": 41, + "txId": "Da4vHc9IwbvOYblE8LnrVsqXwryt2Kmms+xnJ7Zx5E4=" + }, + { + "From": "senderAddress", + "To": "receiverAddress", + "kind": "Transfer", + "seq": 7787, + "status": "Failure", + "txGas": 41, + "txId": "GHTP9gcFmF5KTspnz3KxXjvSH8Bx0jv68KFhdqfpdK8=" + } + ] +} diff --git a/explorer/client/src/utils/static/mock_data.json b/explorer/client/src/utils/static/mock_data.json index 8edb0921d5e56..f29489e448200 100644 --- a/explorer/client/src/utils/static/mock_data.json +++ b/explorer/client/src/utils/static/mock_data.json @@ -263,7 +263,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -284,7 +283,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -305,7 +303,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -326,7 +323,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -347,7 +343,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -368,7 +363,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -389,7 +383,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -410,7 +403,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -432,6 +424,7 @@ "readonly": "true", "objType": "0x2::Coin::Coin<0x2::USD::USD>", "data": { + "tx_digest": "Da4vHc9IwbvOYblE8LnrVsqXwryt2Kmms+xnJ7Zx5E4=", "contents": { "id": {}, "balance": 100 @@ -503,8 +496,7 @@ }, "id": {}, "level": 0, - "lore": "Customizable with Decoration Cosmetics", - "contract_id": { "bytes": "smartContract" } + "lore": "Customizable with Decoration Cosmetics" } } }, @@ -516,7 +508,6 @@ "readonly": "true", "objType": "0x2::Cosmetic::Plant", "name": "Oncidium croesus", - "contract_id": { "bytes": "smartContract" }, "data": { "contents": { "display": "https://sui-explorer-test-image.s3.amazonaws.com/testImage.png", @@ -624,6 +615,7 @@ "ethAddress": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", "ethTokenId": "8937", "data": { + "tx_digest": "Da4vHc9IwbvOYblE8LnrVsqXwryt2Kmms+xnJ7Zx5E4=", "contents": { "display": "https://lh3.googleusercontent.com/xcPvABPQX6sG4Wwg1FsD-ztMUZwp6NeZQLTWX1PfiWvti9cFfDXw5gxvBhg6S4B5Q4CFiZV4nWGRQnzfL0YJpL_yWVgHVZ_DOFSM=w600", "background": "Orange", @@ -635,24 +627,6 @@ } } }, - - { - "id": "smartContract", - "category": "object", - "owner": "SingleOwner(k#senderAddress)", - "version": "1", - "readonly": false, - "objType": "0x2::SmartContract::SmartContract", - "data": { - "contents": { - "display": { - "category": "moveScript", - "data": "/// Example of a game character with basic attributes, inventory, and\n/// associated logic.\nmodule Examples::Hero {\n use Examples::TrustedCoin::EXAMPLE;\n use FastX::Address::{Self, Address};\n use FastX::Coin::{Self, Coin};\n use FastX::Event;\n use FastX::ID::{Self, ID, IDBytes};\n use FastX::Math;\n use FastX::Transfer;\n use FastX::TxContext::{Self, TxContext};\n use Std::Option::{Self, Option};\n\n /// Our hero!\n struct Hero has key, store {\n id: ID,\n /// Hit points. If they go to zero, the hero can't do anything\n hp: u64,\n /// Experience of the hero. Begins at zero\n experience: u64,\n /// The hero's minimal inventory\n sword: Option,\n }\n\n /// The hero's trusty sword\n struct Sword has key, store {\n id: ID,\n /// Constant set at creation. Acts as a multiplier on sword's strength.\n /// Swords with high magic are rarer (because they cost more).\n magic: u64,\n /// Sword grows in strength as we use it\n strength: u64,\n }\n\n /// For healing wounded heroes\n struct Potion has key, store {\n id: ID,\n /// Effectivenss of the potion\n potency: u64\n }\n\n /// A creature that the hero can slay to level up\n struct Boar has key {\n id: ID,\n /// Hit points before the boar is slain\n hp: u64,\n /// Strength of this particular boar\n strength: u64\n }\n\n /// Capability conveying the authority to create boars and potions\n struct GameAdmin has key {\n id: ID,\n /// Total number of boars the admin has created\n boars_created: u64,\n /// Total number of potions the admin has created\n potions_created: u64\n }\n\n /// Event emitted each time a Hero slays a Boar\n struct BoarSlainEvent has copy, drop {\n /// Address of the user that slayed the boar\n slayer_address: Address,\n /// ID of the Hero that slayed the boar\n hero: IDBytes,\n /// ID of the now-deceased boar\n boar: IDBytes,\n }\n\n /// Address of the admin account that receives payment for swords\n const ADMIN: vector = vector[189, 215, 127, 86, 129, 189, 1, 4, 90, 106, 17, 10, 123, 200, 40, 18, 34, 173, 240, 91, 213, 72, 183, 249, 213, 210, 39, 181, 105, 254, 59, 163];\n /// Upper bound on player's HP\n const MAX_HP: u64 = 1000;\n /// Upper bound on how magical a sword can be\n const MAX_MAGIC: u64 = 10;\n /// Minimum amount you can pay for a sword\n const MIN_SWORD_COST: u64 = 100;\n\n // TODO: proper error codes\n /// The boar won the battle\n const EBOAR_WON: u64 = 0;\n /// The hero is too tired to fight\n const EHERO_TIRED: u64 = 1;\n /// Trying to initialize from a non-admin account\n const ENOT_ADMIN: u64 = 2;\n /// Not enough money to purchase the given item\n const EINSUFFICIENT_FUNDS: u64 = 3;\n /// Trying to remove a sword, but the hero does not have one\n const ENO_SWORD: u64 = 4;\n /// Assertion errors for testing\n const ASSERT_ERR: u64 = 5;\n\n // --- Initialization\n\n /// Create the `GameAdmin` capability and hand it off to the admin\n /// authenticator\n fun init(ctx: &mut TxContext) {\n let admin = admin();\n // ensure this is being initialized by the expected admin authenticator\n assert!(&TxContext::get_signer_address(ctx) == &admin, ENOT_ADMIN);\n Transfer::transfer(\n GameAdmin {\n id: TxContext::new_id(ctx),\n boars_created: 0,\n potions_created: 0\n },\n admin\n )\n }\n\n // --- Gameplay ---\n\n /// Slay the `boar` with the `hero`'s sword, get experience.\n /// Aborts if the hero has 0 HP or is not strong enough to slay the boar\n public fun slay(hero: &mut Hero, boar: Boar, ctx: &mut TxContext) {\n let Boar { id: boar_id, strength: boar_strength, hp } = boar;\n let hero_strength = hero_strength(hero);\n let boar_hp = hp;\n let hero_hp = hero.hp;\n // attack the boar with the sword until its HP goes to zero\n while (boar_hp > hero_strength) {\n // first, the hero attacks\n boar_hp = boar_hp - hero_strength;\n // then, the boar gets a turn to attack. if the boar would kill\n // the hero, abort--we can't let the boar win!\n assert!(hero_hp >= boar_strength , EBOAR_WON);\n hero_hp = hero_hp - boar_strength;\n\n };\n // hero takes their licks\n hero.hp = hero_hp;\n // hero gains experience proportional to the boar, sword grows in\n // strength by one (if hero is using a sword)\n hero.experience = hero.experience + hp;\n if (Option::is_some(&hero.sword)) {\n level_up_sword(Option::borrow_mut(&mut hero.sword), 1)\n };\n // let the world know about the hero's triumph by emitting an event!\n Event::emit(BoarSlainEvent {\n slayer_address: TxContext::get_signer_address(ctx),\n hero: *ID::get_inner(&hero.id),\n boar: *ID::get_inner(&boar_id),\n });\n ID::delete(boar_id);\n\n }\n\n /// Strength of the hero when attacking\n public fun hero_strength(hero: &Hero): u64 {\n // a hero with zero HP is too tired to fight\n if (hero.hp == 0) {\n return 0\n };\n\n let sword_strength = if (Option::is_some(&hero.sword)) {\n sword_strength(Option::borrow(&hero.sword))\n } else {\n // hero can fight without a sword, but will not be very strong\n 0\n };\n // hero is weaker if he has lower HP\n (hero.experience * hero.hp) + sword_strength\n }\n\n fun level_up_sword(sword: &mut Sword, amount: u64) {\n sword.strength = sword.strength + amount\n }\n\n /// Strength of a sword when attacking\n public fun sword_strength(sword: &Sword): u64 {\n sword.magic + sword.strength\n }\n\n // --- Inventory ---\n\n /// Heal the weary hero with a potion\n public fun heal(hero: &mut Hero, potion: Potion) {\n let Potion { id, potency } = potion;\n ID::delete(id);\n let new_hp = hero.hp + potency;\n // cap hero's HP at MAX_HP to avoid int overflows\n hero.hp = Math::min(new_hp, MAX_HP)\n }\n\n /// Add `new_sword` to the hero's inventory and return the old sword\n /// (if any)\n public fun equip_sword(hero: &mut Hero, new_sword: Sword): Option {\n Option::swap_or_fill(&mut hero.sword, new_sword)\n }\n\n /// Disarm the hero by returning their sword.\n /// Aborts if the hero does not have a sword.\n public fun remove_sword(hero: &mut Hero): Sword {\n assert!(Option::is_some(&hero.sword), ENO_SWORD);\n Option::extract(&mut hero.sword)\n }\n\n // --- Object creation ---\n\n /// It all starts with the sword. Anyone can buy a sword, and proceeds go\n /// to the admin. Amount of magic in the sword depends on how much you pay\n /// for it.\n public fun create_sword(\n payment: Coin,\n ctx: &mut TxContext\n ): Sword {\n let value = Coin::value(&payment);\n // ensure the user pays enough for the sword\n assert!(value >= MIN_SWORD_COST, EINSUFFICIENT_FUNDS);\n // pay the admin for ths sword\n Transfer::transfer(payment, admin());\n\n // magic of the sword is proportional to the amount you paid, up to\n // a max. one can only imbue a sword with so much magic\n let magic = (value - MIN_SWORD_COST) / MIN_SWORD_COST;\n Sword {\n id: TxContext::new_id(ctx),\n magic: Math::min(magic, MAX_MAGIC),\n strength: 1\n }\n }\n\n public fun acquire_hero(payment: Coin, ctx: &mut TxContext) {\n let sword = create_sword(payment, ctx);\n let hero = create_hero(sword, ctx);\n Transfer::transfer(hero, TxContext::get_signer_address(ctx))\n }\n\n /// Anyone can create a hero if they have a sword. All heros start with the\n /// same attributes.\n public fun create_hero(sword: Sword, ctx: &mut TxContext): Hero {\n Hero {\n id: TxContext::new_id(ctx),\n hp: 100,\n experience: 0,\n sword: Option::some(sword),\n }\n }\n\n /// Admin can create a potion with the given `potency` for `recipient`\n public fun send_potion(\n potency: u64,\n player: Address,\n admin: &mut GameAdmin,\n ctx: &mut TxContext\n ) {\n admin.potions_created = admin.potions_created + 1;\n // send potion to the designated player\n Transfer::transfer(\n Potion { id: TxContext::new_id(ctx), potency },\n player\n )\n }\n\n /// Admin can create a boar with the given attributes for `recipient`\n public fun send_boar(\n admin: &mut GameAdmin,\n hp: u64,\n strength: u64,\n player: vector,\n ctx: &mut TxContext\n ) {\n admin.boars_created = admin.boars_created + 1;\n // send boars to the designated player\n Transfer::transfer(\n Boar { id: TxContext::new_id(ctx), hp, strength },\n Address::new(player)\n )\n }\n\n fun admin(): Address {\n Address::new(ADMIN)\n }\n\n // --- Testing functions ---\n fun assert_hero_strength(hero: &Hero, strength: u64, _: &mut TxContext) {\n assert!(hero_strength(hero) == strength, ASSERT_ERR);\n }\n\n}\n" - } - } - } - }, - { "id": "37196de8502e6d80e6a31fba1a5d6986cc018805", "category": "object", @@ -879,6 +853,181 @@ "display": "https://geniteam-video-images.s3.amazonaws.com/562949953421312_Rune_Fire.png" } } + }, + { + "id": "Da4vHc9IwbvOYblE8LnrVsqXwryt2Kmms+xnJ7Zx5E4=", + "category": "transaction", + "certificate": { + "data": { + "kind": { + "Single": { + "Transfer": { + "recipient": "receiverAddress", + "object_ref": [ + "7bc832ec31709638cd8d9323e90edf332gff4389", + 1, + "cqYpJFiXpjT5cSBjF7S1QxWaub6PUBkgiV1vZoIk9/E=" + ] + } + } + }, + "sender": "senderAddress", + "gas_payment": [ + "standaloneObject", + 5633, + "ipBwvC8OECrp2pjJsGsZTJiYiAkv6wH6bi5ANpADsYw=" + ], + "gas_budget": 1000 + }, + "tx_signature": "mdLFHZQ+gqG+ngtditQc3cQj782RCl2ozUiSBHikk2P5UqHvtRErlU7E6lLpMukaGURh31jaf2rL9nzpRqEMANRj4Rx5FZRehqwrctiLgZDPrY/3tI5+uJLCdaXPCj6C", + "auth_sign_info": { + "epoch": 0, + "signatures": [ + [ + "g56Z+LA/D1Vj1s2cw54QqM9IOtJ3Wuy7knAxNwkl704=", + "1il+2r4GMQPkEfvPvdPgeVl2LxnzFj/Ej5dvJz7A35WiuzW6uBmgCe7Xs2LNU4f2LvhDH1IwWV47tddVH02jAg==" + ], + [ + "FYTvK2d9b16WtX2sJ0TpJ4qiThF8e/1qwAv0PBEpx/0=", + "z7/SzBHZT/nh26oZfKAC2vX9Js087KnNcp0CsDKTsIIdsnB8hYHmJD5AdQNnc7Omiey7nt9VaP7h7rNfohmWDQ==" + ], + [ + "icr9ch7rGxNIPV+wloUA54ED6BRrRe2zDZN4HZRtCus=", + "FOxgPYxPAzuKhthRk81LrestfShW/sc0Namo8y1eweSDUXyaagjhl8WWnstfhIunrxdnQz98EOTUxXiLFfT7AA==" + ] + ] + } + }, + "effects": { + "status": { + "Success": { + "gas_cost": { + "computation_cost": 41, + "storage_cost": 30, + "storage_rebate": 30 + } + } + }, + "shared_objects": [], + "transaction_digest": "Da4vHc9IwbvOYblE8LnrVsqXwryt2Kmms+xnJ7Zx5E4=", + "created": [], + "mutated": [ + [ + [ + "7bc832ec31709638cd8d9323e90edf332gff4389", + 2, + "A6HE1BDkN8360mzg4WtRUliiE8HE/7mtZC3MNRFwFWc=" + ], + { + "AddressOwner": "3aa29bad2ea941491da6e8eff55167987dd3de8d" + } + ], + [ + [ + "standaloneObject", + 5634, + "oCajXdK8h9s3aKl2A+ifHxn3y8YTJyagL+eLT0vvHP0=" + ], + { + "AddressOwner": "813ec1ab1e1797c79d1e1fcbebebc27a1fd21f07" + } + ] + ], + "unwrapped": [], + "deleted": [], + "wrapped": [], + "gas_object": [ + [ + "standaloneObject", + 5634, + "oCajXdK8h9s3aKl2A+ifHxn3y8YTJyagL+eLT0vvHP0=" + ], + { + "AddressOwner": "813ec1ab1e1797c79d1e1fcbebebc27a1fd21f07" + } + ], + "events": [], + "dependencies": [ + "1klAsrCDeDvf7tokZzAhzJhz8uQHlQa4c7pxR77te78=", + "/5e4BE6M+xgCAgplpecVX+DUBW91eF5OwGpwvflx6II=" + ] + } + }, + + { + "id": "GHTP9gcFmF5KTspnz3KxXjvSH8Bx0jv68KFhdqfpdK8=", + "category": "transaction", + "certificate": { + "data": { + "kind": { + "Single": { + "Transfer": { + "recipient": "receiverAddress", + "object_ref": [ + "7bc832ec31709638cd8d9323e90edf332gff4389", + 1, + "cqYpJFiXpjT5cSBjF7S1QxWaub6PUBkgiV1vZoIk9/E=" + ] + } + } + }, + "sender": "senderAddress", + "gas_payment": [ + "standaloneObject", + 5633, + "ipBwvC8OECrp2pjJsGsZTJiYiAkv6wH6bi5ANpADsYw=" + ], + "gas_budget": 1000 + }, + "tx_signature": "mdLFHZQ+gqG+ngtditQc3cQj782RCl2ozUiSBHikk2P5UqHvtRErlU7E6lLpMukaGURh31jaf2rL9nzpRqEMANRj4Rx5FZRehqwrctiLgZDPrY/3tI5+uJLCdaXPCj6C", + "auth_sign_info": { + "epoch": 0, + "signatures": [ + [ + "g56Z+LA/D1Vj1s2cw54QqM9IOtJ3Wuy7knAxNwkl704=", + "1il+2r4GMQPkEfvPvdPgeVl2LxnzFj/Ej5dvJz7A35WiuzW6uBmgCe7Xs2LNU4f2LvhDH1IwWV47tddVH02jAg==" + ], + [ + "FYTvK2d9b16WtX2sJ0TpJ4qiThF8e/1qwAv0PBEpx/0=", + "z7/SzBHZT/nh26oZfKAC2vX9Js087KnNcp0CsDKTsIIdsnB8hYHmJD5AdQNnc7Omiey7nt9VaP7h7rNfohmWDQ==" + ], + [ + "icr9ch7rGxNIPV+wloUA54ED6BRrRe2zDZN4HZRtCus=", + "FOxgPYxPAzuKhthRk81LrestfShW/sc0Namo8y1eweSDUXyaagjhl8WWnstfhIunrxdnQz98EOTUxXiLFfT7AA==" + ] + ] + } + }, + "effects": { + "status": { + "Failure": { + "error": { + "someError": { + "error": "something went wrong" + } + } + } + }, + "shared_objects": [], + "transaction_digest": "GHTP9gcFmF5KTspnz3KxXjvSH8Bx0jv68KFhdqfpdK8=", + "created": [], + "mutated": [], + "unwrapped": [], + "deleted": [], + "wrapped": [], + "gas_object": [ + [ + "standaloneObject", + 5634, + "oCajXdK8h9s3aKl2A+ifHxn3y8YTJyagL+eLT0vvHP0=" + ], + { + "AddressOwner": "813ec1ab1e1797c79d1e1fcbebebc27a1fd21f07" + } + ], + "events": [], + "dependencies": [] + } } ] } diff --git a/explorer/client/src/utils/static/searchUtil.ts b/explorer/client/src/utils/static/searchUtil.ts index 93625f66bbdd5..a537f6826932d 100644 --- a/explorer/client/src/utils/static/searchUtil.ts +++ b/explorer/client/src/utils/static/searchUtil.ts @@ -1,7 +1,8 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import mockObjectData from './mock_data.json'; +import latestTxData from './latest_transactions.json'; +import mockData from './mock_data.json'; import mockOwnedObjectData from './owned_object.json'; const navigateWithUnknown = async (input: string, navigate: Function) => { @@ -22,9 +23,16 @@ const navigateWithUnknown = async (input: string, navigate: Function) => { const findDataFromID = (targetID: string | undefined, state: any) => state?.category !== undefined ? state - : mockObjectData.data.find(({ id }) => id === targetID); + : mockData.data.find(({ id }) => id === targetID); const findOwnedObjectsfromID = (targetID: string | undefined) => mockOwnedObjectData?.data?.find(({ id }) => id === targetID)?.objects; -export { findDataFromID, navigateWithUnknown, findOwnedObjectsfromID }; +const getAllMockTransaction = () => latestTxData.data; + +export { + findDataFromID, + navigateWithUnknown, + findOwnedObjectsfromID, + getAllMockTransaction, +}; diff --git a/explorer/client/yarn.lock b/explorer/client/yarn.lock index 7482d6981b0cc..2fa5a7e1e0595 100644 --- a/explorer/client/yarn.lock +++ b/explorer/client/yarn.lock @@ -2354,11 +2354,6 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -ace-builds@^1.4.13, ace-builds@^1.4.14: - version "1.4.14" - resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.4.14.tgz#2c41ccbccdd09e665d3489f161a20baeb3a3c852" - integrity sha512-NBOQlm9+7RBqRqZwimpgquaLeTJFayqb9UEPtTkpC3TkkwDnlsT/TwsCC0svjt9kEZ6G9mH5AEOHSz6Q/HrzQQ== - acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -3294,20 +3289,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concurrently@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.1.0.tgz#477b49b8cfc630bb491f9b02e9ed7fb7bff02942" - integrity sha512-Bz0tMlYKZRUDqJlNiF/OImojMB9ruKUz6GCfmhFnSapXgPe+3xzY4byqoKG9tUZ7L2PGEUjfLPOLfIX3labnmw== - dependencies: - chalk "^4.1.0" - date-fns "^2.16.1" - lodash "^4.17.21" - rxjs "^6.6.3" - spawn-command "^0.0.2-1" - supports-color "^8.1.0" - tree-kill "^1.2.2" - yargs "^16.2.0" - confusing-browser-globals@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" @@ -3644,11 +3625,6 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date-fns@^2.16.1: - version "2.28.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2" - integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw== - debug@2.6.9, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3795,11 +3771,6 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== -diff-match-patch@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" - integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw== - diff-sequences@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" @@ -6450,16 +6421,6 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -7830,7 +7791,7 @@ prompts@^2.0.1, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -7944,17 +7905,6 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" -react-ace@^9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-9.5.0.tgz#b6c32b70d404dd821a7e01accc2d76da667ff1f7" - integrity sha512-4l5FgwGh6K7A0yWVMQlPIXDItM4Q9zzXRqOae8KkCl6MkOob7sC1CzHxZdOGvV+QioKWbX2p5HcdOVUv6cAdSg== - dependencies: - ace-builds "^1.4.13" - diff-match-patch "^1.0.5" - lodash.get "^4.4.2" - lodash.isequal "^4.5.0" - prop-types "^15.7.2" - react-app-polyfill@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7" @@ -8369,13 +8319,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^6.6.3: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - rxjs@^7.5.4: version "7.5.5" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" @@ -8699,11 +8642,6 @@ sourcemap-codec@^1.4.8: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== -spawn-command@^0.0.2-1: - version "0.0.2-1" - resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" - integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= - spawnd@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/spawnd/-/spawnd-6.0.2.tgz#a2631cab24ce5e3525e720af4058f10a0905147c" @@ -9066,7 +9004,7 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.0.0, supports-color@^8.1.0: +supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -9128,11 +9066,6 @@ svgo@^2.7.0: picocolors "^1.0.0" stable "^0.1.8" -swr@^1.2.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8" - integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw== - symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -9355,7 +9288,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==