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
-
- ) : (
-
- )}
-
- );
- }
- return ;
+ return (
+
+ {!hasDisplayLoaded && (
+
+ Please wait for display to load
+
+ )}
+ {hasFailedToLoad ? (
+
+ No Image was Found
+
+ ) : (
+
+ )}
+
+ );
}
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 (
-
- );
- }
-
- 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 (
+
+ );
+ }
+
+ 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==