diff --git a/api/package-lock.json b/api/package-lock.json index 452f23b80..ceb57cdad 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -1,12 +1,12 @@ { "name": "explorer-api", - "version": "3.3.8-rc.2", + "version": "3.3.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "explorer-api", - "version": "3.3.8-rc.2", + "version": "3.3.8", "license": "Apache-2.0", "dependencies": { "@google-cloud/logging-winston": "^6.0.0", diff --git a/api/package.json b/api/package.json index c7890f7a9..d4cacd410 100644 --- a/api/package.json +++ b/api/package.json @@ -1,7 +1,7 @@ { "name": "explorer-api", "description": "API for Tangle Explorer", - "version": "3.3.8-rc.2", + "version": "3.3.8", "author": "Martyn Janes ", "repository": { "type": "git", diff --git a/api/src/utils/stardust/associatedOutputsHelper.ts b/api/src/utils/stardust/associatedOutputsHelper.ts index 6674c9618..592e184a4 100644 --- a/api/src/utils/stardust/associatedOutputsHelper.ts +++ b/api/src/utils/stardust/associatedOutputsHelper.ts @@ -214,7 +214,9 @@ export class AssociatedOutputsHelper { // remove expired basic outputs from basic address associations if they exist const expiredIds = this.associationToOutputIds.get(AssociationType.BASIC_ADDRESS_EXPIRED); const filteredOutputIds = outputIds.filter((id) => !expiredIds?.includes(id)); - associations.push({ type, outputIds: filteredOutputIds.reverse() }); + if (filteredOutputIds.length > 0) { + associations.push({ type, outputIds: filteredOutputIds.reverse() }); + } } else if ( type === AssociationType.NFT_ADDRESS && this.associationToOutputIds.get(AssociationType.NFT_ADDRESS_EXPIRED)?.length > 0 @@ -222,7 +224,9 @@ export class AssociatedOutputsHelper { // remove expired nft outputs from nft address associations if they exist const expiredIds = this.associationToOutputIds.get(AssociationType.NFT_ADDRESS_EXPIRED); const filteredOutputIds = outputIds.filter((id) => !expiredIds?.includes(id)); - associations.push({ type, outputIds: filteredOutputIds.reverse() }); + if (filteredOutputIds.length > 0) { + associations.push({ type, outputIds: filteredOutputIds.reverse() }); + } } else { associations.push({ type, outputIds: outputIds.reverse() }); } diff --git a/api/src/utils/stardust/searchExecutor.ts b/api/src/utils/stardust/searchExecutor.ts index 9b142557e..b61d16220 100644 --- a/api/src/utils/stardust/searchExecutor.ts +++ b/api/src/utils/stardust/searchExecutor.ts @@ -53,7 +53,7 @@ export class SearchExecutor { this.apiService .milestoneDetailsById(searchQuery.milestoneId) .then((milestoneDetails) => { - if (milestoneDetails) { + if (milestoneDetails.blockId) { promisesResult = { milestone: milestoneDetails, }; @@ -139,7 +139,7 @@ export class SearchExecutor { this.apiService .aliasDetails(searchQuery.aliasId) .then((aliasOutputs) => { - if (aliasOutputs) { + if (aliasOutputs.aliasDetails) { promisesResult = { aliasId: searchQuery.aliasId, did: searchQuery.did, @@ -162,7 +162,7 @@ export class SearchExecutor { this.apiService .nftDetails(searchQuery.nftId) .then((nftOutputs) => { - if (nftOutputs) { + if (nftOutputs.nftDetails) { promisesResult = { nftId: searchQuery.nftId, }; diff --git a/client/Dockerfile b/client/Dockerfile index ab398864e..3a8d776d3 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -24,6 +24,9 @@ RUN echo 'server {\ }\ }' > /etc/nginx/sites-available/default +# Set Content-Type so streaming compilation works +RUN mv ./nginx/wasm.conf /etc/nginx/conf.d/wasm.conf + # Running required steps to prepare the web app prod build RUN npm install RUN npm run build diff --git a/client/nginx/wasm.conf b/client/nginx/wasm.conf new file mode 100644 index 000000000..b5f4f5e4c --- /dev/null +++ b/client/nginx/wasm.conf @@ -0,0 +1,4 @@ +types { + # Set Content-Type so streaming compilation works + application/wasm wasm; +} diff --git a/client/package-lock.json b/client/package-lock.json index b51fd320d..d257b6c3e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "explorer-client", - "version": "3.3.8-rc.2", + "version": "3.3.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "explorer-client", - "version": "3.3.8-rc.2", + "version": "3.3.8", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/client/package.json b/client/package.json index 6cf566abb..15c124b88 100644 --- a/client/package.json +++ b/client/package.json @@ -1,7 +1,7 @@ { "name": "explorer-client", "description": "Tangle Explorer UI", - "version": "3.3.8-rc.2", + "version": "3.3.8", "author": "Martyn Janes ", "type": "module", "repository": { diff --git a/client/src/app/routes.tsx b/client/src/app/routes.tsx index 4c9a80667..763f898db 100644 --- a/client/src/app/routes.tsx +++ b/client/src/app/routes.tsx @@ -31,7 +31,8 @@ import StardustBlock from "./routes/stardust/Block"; import StardustFoundry from "./routes/stardust/Foundry"; import { Landing as StardustLanding } from "./routes/stardust/landing/Landing"; import NovaLanding from "./routes/nova/landing/Landing"; -import NftRedirectRoute from "./routes/stardust/NftRedirectRoute"; +import NftRedirectRouteStardust from "./routes/stardust/NftRedirectRoute"; +import NftRedirectRouteNova from "./routes/nova/NftRedirectRoute"; import StardustOutputList from "./routes/stardust/OutputList"; import StardustOutputPage from "./routes/stardust/OutputPage"; import NovaBlockPage from "./routes/nova/Block"; @@ -169,7 +170,7 @@ const buildAppRoutes = (protocolVersion: string, withNetworkContext: (wrappedCom , , , - , + , , , , @@ -189,6 +190,7 @@ const buildAppRoutes = (protocolVersion: string, withNetworkContext: (wrappedCom , , , + , , , , diff --git a/client/src/app/routes/nova/NftRedirectRoute.tsx b/client/src/app/routes/nova/NftRedirectRoute.tsx new file mode 100644 index 000000000..1d3778d73 --- /dev/null +++ b/client/src/app/routes/nova/NftRedirectRoute.tsx @@ -0,0 +1,36 @@ +import { AddressType } from "@iota/sdk-wasm-nova/web"; +import React from "react"; +import { Redirect, RouteComponentProps } from "react-router-dom"; +import { AddressHelper } from "~helpers/nova/addressHelper"; +import { useNetworkInfoNova } from "~/helpers/nova/networkInfo"; + +interface NftRedirectRouteProps { + /** + * The network. + */ + network: string; + + /** + * The nftId to redirect. + */ + nftId: string; +} + +const ADDRESS_ROUTE = "addr"; + +const NftRedirectRoute: React.FC> = ({ + match: { + params: { network, nftId }, + }, +}) => { + const { bech32Hrp } = useNetworkInfoNova((s) => s.networkInfo); + const nftAddress = AddressHelper.buildAddress(bech32Hrp, nftId, AddressType.Nft); + const redirectState = { + addressDetails: nftAddress, + }; + const routeParam = nftAddress.bech32; + const redirect = `/${network}/${ADDRESS_ROUTE}/${routeParam}`; + return ; +}; + +export default NftRedirectRoute; diff --git a/client/src/helpers/stardust/hooks/useAddressBalance.ts b/client/src/helpers/stardust/hooks/useAddressBalance.ts index 3887ddf5c..d97ae6db7 100644 --- a/client/src/helpers/stardust/hooks/useAddressBalance.ts +++ b/client/src/helpers/stardust/hooks/useAddressBalance.ts @@ -1,10 +1,12 @@ import { AddressType, AliasOutput, NftOutput } from "@iota/sdk-wasm-stardust/web"; -import { useEffect, useState } from "react"; +import { useContext, useEffect, useState } from "react"; +import NetworkContext from "~/app/context/NetworkContext"; import { IBech32AddressDetails } from "~/models/api/IBech32AddressDetails"; import { ServiceFactory } from "~factories/serviceFactory"; import { useIsMounted } from "~helpers/hooks/useIsMounted"; import { STARDUST } from "~models/config/protocolVersion"; import { StardustApiClient } from "~services/stardust/stardustApiClient"; +import { TransactionsHelper } from "../transactionsHelper"; /** * Fetch the address balance @@ -23,6 +25,7 @@ export function useAddressBalance( const [balance, setBalance] = useState(null); const [availableBalance, setAvailableBalance] = useState(null); const [isLoading, setIsLoading] = useState(true); + const { rentStructure } = useContext(NetworkContext); useEffect(() => { setIsLoading(true); @@ -33,28 +36,27 @@ export function useAddressBalance( // eslint-disable-next-line no-void void (async () => { const response = await apiClient.addressBalanceChronicle({ network, address }); - - if (response?.totalBalance !== undefined && isMounted) { - let totalBalance = response.totalBalance; - let availableBalance = response.availableBalance ?? 0; + if (isMounted) { + let totalBalance = 0; + let availableBalance = null; + if (response?.totalBalance !== undefined) { + totalBalance = response.totalBalance; + availableBalance = response.availableBalance ?? 0; + } else { + // Fallback balance from iotajs (node) + const addressDetailsWithBalance = await apiClient.addressBalance({ network, address }); + if (addressDetailsWithBalance && isMounted) { + totalBalance = Number(addressDetailsWithBalance.balance); + } + } if (output) { - totalBalance = Number(totalBalance) + Number(output.amount); - availableBalance = Number(availableBalance) + Number(output.amount); + const outputBalance = Number(output.amount); + const outputStorageDeposit = TransactionsHelper.computeStorageDeposit([output], rentStructure); + totalBalance = Number(totalBalance ?? 0) + outputBalance; + availableBalance = Number(availableBalance ?? 0) + outputBalance - outputStorageDeposit; } setBalance(totalBalance); - setAvailableBalance(availableBalance > 0 ? availableBalance : null); - } else if (isMounted) { - // Fallback balance from iotajs (node) - const addressDetailsWithBalance = await apiClient.addressBalance({ network, address }); - - if (addressDetailsWithBalance && isMounted) { - let totalBalance = Number(addressDetailsWithBalance.balance); - if (output) { - totalBalance = Number(totalBalance) + Number(output.amount); - } - setBalance(totalBalance); - setAvailableBalance(null); - } + setAvailableBalance(availableBalance); } })(); } else { diff --git a/client/src/helpers/stardust/transactionsHelper.ts b/client/src/helpers/stardust/transactionsHelper.ts index 7faf53674..4895f93ca 100644 --- a/client/src/helpers/stardust/transactionsHelper.ts +++ b/client/src/helpers/stardust/transactionsHelper.ts @@ -178,8 +178,7 @@ export class TransactionsHelper { } sortedOutputs = [...outputs, ...remainderOutputs]; - this.sortInputsAndOuputsByIndex(sortedOutputs); - this.sortInputsAndOuputsByIndex(inputs); + this.sortOuputsByIndex(sortedOutputs); } return { inputs, unlocks, outputs: sortedOutputs, unlockAddresses, transferTotal }; @@ -189,7 +188,7 @@ export class TransactionsHelper { * Sort inputs and outputs in assending order by index. * @param items Inputs or Outputs. */ - public static sortInputsAndOuputsByIndex(items: IInput[] | IOutput[]) { + public static sortOuputsByIndex(items: IOutput[]) { // eslint-disable-next-line @typescript-eslint/no-explicit-any items.sort((a: any, b: any) => { const firstIndex: string = a.id ? a.id.slice(-4) : a.outputId.slice(-4); diff --git a/package.json b/package.json index de8005ff5..a57d9ae71 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "explorer", "description": "Tangle Explorer", - "version": "3.3.8-rc.2", + "version": "3.3.8", "scripts": { "setup:client": "cd client && npm install && npm run postinstall", "setup:api": "cd api && npm install && npm run build-compile && npm run build-config",