Skip to content

Commit

Permalink
Merge branch 'feat/add-validation-tab' of github.com:iotaledger/explo…
Browse files Browse the repository at this point in the history
…rer into feat/add-validation-tab
  • Loading branch information
brancoder committed Feb 26, 2024
2 parents 77e905d + 5fb6494 commit a9c006a
Show file tree
Hide file tree
Showing 24 changed files with 475 additions and 14 deletions.
4 changes: 2 additions & 2 deletions api/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "explorer-api",
"description": "API for Tangle Explorer",
"version": "3.3.4-rc.1",
"version": "3.3.4",
"author": "Martyn Janes <[email protected]>",
"repository": {
"type": "git",
Expand Down
5 changes: 5 additions & 0 deletions api/src/models/api/nova/ISearchResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ export interface ISearchResponse extends IResponse {
* Nft id if it was found.
*/
nftId?: string;

/**
* Transaction included block.
*/
transactionBlock?: Block;
}
11 changes: 11 additions & 0 deletions api/src/models/api/nova/ITransactionDetailsRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface ITransactionDetailsRequest {
/**
* The network to search on.
*/
network: string;

/**
* The transaction id to get the details for.
*/
transactionId: string;
}
11 changes: 11 additions & 0 deletions api/src/models/api/nova/ITransactionDetailsResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* eslint-disable import/no-unresolved */
/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
import { Block } from "@iota/sdk-nova";
import { IResponse } from "./IResponse";

export interface ITransactionDetailsResponse extends IResponse {
/**
* Transaction included block.
*/
block?: Block;
}
6 changes: 6 additions & 0 deletions api/src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ export const routes: IRoute[] = [
folder: "nova/account/foundries",
func: "get",
},
{
path: "/nova/transaction/:network/:transactionId",
method: "get",
folder: "nova/transaction",
func: "get",
},
{
path: "/nova/account/congestion/:network/:accountId",
method: "get",
Expand Down
30 changes: 30 additions & 0 deletions api/src/routes/nova/transaction/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ServiceFactory } from "../../../factories/serviceFactory";
import { ITransactionDetailsRequest } from "../../../models/api/nova/ITransactionDetailsRequest";
import { ITransactionDetailsResponse } from "../../../models/api/nova/ITransactionDetailsResponse";
import { IConfiguration } from "../../../models/configuration/IConfiguration";
import { NOVA } from "../../../models/db/protocolVersion";
import { NetworkService } from "../../../services/networkService";
import { NovaApiService } from "../../../services/nova/novaApiService";
import { ValidationHelper } from "../../../utils/validationHelper";

/**
* Find the object from the network.
* @param config The configuration.
* @param request The request.
* @returns The response.
*/
export async function get(config: IConfiguration, request: ITransactionDetailsRequest): Promise<ITransactionDetailsResponse> {
const networkService = ServiceFactory.get<NetworkService>("network");
const networks = networkService.networkNames();
ValidationHelper.oneOf(request.network, networks, "network");
ValidationHelper.string(request.transactionId, "transactionId");

const networkConfig = networkService.get(request.network);

if (networkConfig.protocolVersion !== NOVA) {
return {};
}

const novaApiService = ServiceFactory.get<NovaApiService>(`api-service-${networkConfig.network}`);
return novaApiService.transactionIncludedBlock(request.transactionId);
}
25 changes: 25 additions & 0 deletions api/src/services/nova/novaApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { INftDetailsResponse } from "../../models/api/nova/INftDetailsResponse";
import { IOutputDetailsResponse } from "../../models/api/nova/IOutputDetailsResponse";
import { IRewardsResponse } from "../../models/api/nova/IRewardsResponse";
import { ISearchResponse } from "../../models/api/nova/ISearchResponse";
import { ITransactionDetailsResponse } from "../../models/api/nova/ITransactionDetailsResponse";
import { INetwork } from "../../models/db/INetwork";
import { HexHelper } from "../../utils/hexHelper";
import { SearchExecutor } from "../../utils/nova/searchExecutor";
Expand Down Expand Up @@ -87,6 +88,30 @@ export class NovaApiService {
}
}

/**
* Get the transaction included block.
* @param transactionId The transaction id to get the details.
* @returns The item details.
*/
public async transactionIncludedBlock(transactionId: string): Promise<ITransactionDetailsResponse> {
transactionId = HexHelper.addPrefix(transactionId);
try {
const block = await this.client.getIncludedBlock(transactionId);

if (!block) {
return { error: `Couldn't find block from transaction id ${transactionId}` };
}
if (block && Object.keys(block).length > 0) {
return {
block,
};
}
} catch (e) {
logger.error(`Failed fetching block with transaction id ${transactionId}. Cause: ${e}`);
return { error: "Block fetch failed." };
}
}

/**
* Get the output details.
* @param outputId The output id to get the details.
Expand Down
15 changes: 15 additions & 0 deletions api/src/utils/nova/searchExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ export class SearchExecutor {
);
}

if (searchQuery.transactionId) {
promises.push(
this.executeQuery(
this.apiService.transactionIncludedBlock(searchQuery.transactionId),
(response) => {
promisesResult = {
transactionBlock: response.block,
error: response.error || response.message,
};
},
"Transaction included block fetch failed",
),
);
}

await Promise.any(promises).catch((_) => {});

if (promisesResult !== null) {
Expand Down
4 changes: 2 additions & 2 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "explorer-client",
"description": "Tangle Explorer UI",
"version": "3.3.4-rc.1",
"version": "3.3.4",
"author": "Martyn Janes <[email protected]>",
"type": "module",
"repository": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classNames from "classnames";
import { TRANSACTION_FAILURE_REASON_STRINGS, Transaction, TransactionMetadata } from "@iota/sdk-wasm-nova/web";
import { TRANSACTION_FAILURE_REASON_STRINGS, Transaction, TransactionMetadata, Utils } from "@iota/sdk-wasm-nova/web";
import React from "react";
import "./TransactionMetadataSection.scss";
import Spinner from "../../../Spinner";
Expand All @@ -14,7 +14,7 @@ interface TransactionMetadataSectionProps {
}

const TransactionMetadataSection: React.FC<TransactionMetadataSectionProps> = ({ transaction, transactionMetadata, metadataError }) => {
const { name: network } = useNetworkInfoNova((s) => s.networkInfo);
const { name: network, bech32Hrp } = useNetworkInfoNova((s) => s.networkInfo);

return (
<div className="section metadata-section">
Expand Down Expand Up @@ -73,7 +73,7 @@ const TransactionMetadataSection: React.FC<TransactionMetadataSectionProps> = ({
<div className="value code highlight margin-b-t" key={idx}>
<TruncatedId
id={allotment.accountId}
link={`/${network}/account/${allotment.accountId}`}
link={`/${network}/addr/${Utils.accountIdToBech32(allotment.accountId, bech32Hrp)}`}
showCopyButton
/>
</div>
Expand Down
2 changes: 2 additions & 0 deletions client/src/app/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import NftRedirectRoute from "./routes/stardust/NftRedirectRoute";
import StardustOutputList from "./routes/stardust/OutputList";
import StardustOutputPage from "./routes/stardust/OutputPage";
import NovaBlockPage from "./routes/nova/Block";
import NovaTransactionPage from "./routes/nova/TransactionPage";
import NovaOutputPage from "./routes/nova/OutputPage";
import NovaSearch from "./routes/nova/Search";
import StardustSearch from "./routes/stardust/Search";
Expand Down Expand Up @@ -178,6 +179,7 @@ const buildAppRoutes = (protocolVersion: string, withNetworkContext: (wrappedCom
<Route path="/:network/block/:blockId" key={keys.next().value} component={NovaBlockPage} />,
<Route path="/:network/output/:outputId" key={keys.next().value} component={NovaOutputPage} />,
<Route path="/:network/search/:query?" key={keys.next().value} component={NovaSearch} />,
<Route path="/:network/transaction/:transactionId" key={keys.next().value} component={NovaTransactionPage} />,
];

return (
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/routes/nova/OutputPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const OutputPage: React.FC<RouteComponentProps<OutputPageProps>> = ({
<div className="section--data">
<div className="label">Transaction ID</div>
<div className="value code highlight row middle">
<TruncatedId id={transactionId} showCopyButton />
<TruncatedId id={transactionId} link={`/${network}/transaction/${transactionId}`} showCopyButton />
</div>
</div>
)}
Expand Down
3 changes: 1 addition & 2 deletions client/src/app/routes/nova/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,8 @@ const Search: React.FC<RouteComponentProps<SearchRouteProps>> = (props) => {
} else if (response.output) {
route = "output";
routeParam = response.output.metadata.outputId;
} else if (response.transactionId) {
} else if (response.transactionBlock) {
route = "transaction";
routeParam = response.transactionId;
} else if (response.foundryId) {
route = "foundry";
routeParam = response.foundryId;
Expand Down
71 changes: 71 additions & 0 deletions client/src/app/routes/nova/TransactionPage.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@import "../../../scss/fonts";
@import "../../../scss/mixins";
@import "../../../scss/media-queries";
@import "../../../scss/variables";

.transaction-page {
display: flex;
flex-direction: column;

.wrapper {
display: flex;
justify-content: center;

.inner {
display: flex;
flex: 1;
flex-direction: column;
max-width: $desktop-width;
margin: 40px 25px;

@include desktop-down {
flex: unset;
width: 100%;
max-width: 100%;
margin: 40px 24px;
padding-right: 24px;
padding-left: 24px;

> .row {
flex-direction: column;
}
}

@include tablet-down {
margin: 28px 0;
}

.transation-page--header {
display: flex;
align-items: center;
justify-content: space-between;
}

.section {
padding-top: 44px;

.section--header {
margin-top: 44px;
}
}

.link {
@include font-size(14px);

max-width: 100%;
color: var(--link-color);
font-family: $ibm-plex-mono;
font-weight: normal;
letter-spacing: 0.02em;
line-height: 20px;
}
}

.section--data {
.amount-transacted {
@include font-size(15px);
font-weight: 700;
}
}
}
}
Loading

0 comments on commit a9c006a

Please sign in to comment.