diff --git a/src/components/account/NftsTable.vue b/src/components/account/NftsTable.vue new file mode 100644 index 000000000..be493b890 --- /dev/null +++ b/src/components/account/NftsTable.vue @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + {{props.row.serial_number}} + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/token/NftHolderTable.vue b/src/components/token/NftHolderTable.vue index 3f0bec162..3aa5bf249 100644 --- a/src/components/token/NftHolderTable.vue +++ b/src/components/token/NftHolderTable.vue @@ -34,15 +34,13 @@ v-model:current-page="currentPage" :per-page="perPage" @page-change="onPageChange" - @cell-click="handleClick" + @cell-click="handleClick" :hoverable="true" :narrowed="true" :striped="true" :mobile-breakpoint="ORUGA_MOBILE_BREAKPOINT" - style="cursor: pointer" - aria-current-label="Current page" aria-next-label="Next page" aria-page-label="Page" @@ -56,7 +54,7 @@ - + @@ -93,7 +91,7 @@ import BlobValue from "@/components/values/BlobValue.vue"; import {ORUGA_MOBILE_BREAKPOINT} from '@/App.vue'; import EmptyTable from "@/components/EmptyTable.vue"; import {NftHolderTableController} from "@/components/token/NftHolderTableController"; -import {routeManager} from "@/router"; +import { routeManager } from "@/router"; export default defineComponent({ name: 'NftHolderTable', @@ -111,11 +109,21 @@ export default defineComponent({ const isTouchDevice = inject('isTouchDevice', false) const isMediumScreen = inject('isMediumScreen', true) - const handleClick = (n: Nft, c: unknown, i: number, ci: number, event: MouseEvent) => { + const handleClick = ( + n: Nft, + c: unknown, + i: number, + ci: number, + event: MouseEvent, + ) => { if (n.token_id && n.serial_number) { - routeManager.routeToSerial(n.token_id, n.serial_number, event.ctrlKey || event.metaKey) + routeManager.routeToSerial( + n.token_id, + n.serial_number, + event.ctrlKey || event.metaKey, + ); } - } + }; return { isTouchDevice, @@ -127,7 +135,7 @@ export default defineComponent({ onPageChange: props.controller.onPageChange, perPage: props.controller.pageSize as Ref, ORUGA_MOBILE_BREAKPOINT, - handleClick + handleClick, } } }); @@ -135,5 +143,7 @@ export default defineComponent({ - + + + \ No newline at end of file diff --git a/src/components/transaction/NftTransactionAnalyzer.ts b/src/components/transaction/NftTransactionAnalyzer.ts index 5888e8516..feb4b753f 100644 --- a/src/components/transaction/NftTransactionAnalyzer.ts +++ b/src/components/transaction/NftTransactionAnalyzer.ts @@ -18,30 +18,30 @@ * */ -import { computed, ComputedRef, ref, Ref, watch, WatchStopHandle } from "vue"; +import {computed, ComputedRef, ref, Ref, watch, WatchStopHandle} from "vue" import { NftTransactionTransfer, TokenRelationship, TransactionType, -} from "@/schemas/HederaSchemas"; -import { EntityDescriptor } from "@/utils/EntityDescriptor"; -import { normalizeTransactionId } from "@/utils/TransactionID"; -import { TokenRelationshipCache } from "@/utils/cache/TokenRelationshipCache"; +} from "@/schemas/HederaSchemas" +import {EntityDescriptor} from "@/utils/EntityDescriptor" +import {normalizeTransactionId} from "@/utils/TransactionID" +import {TokenRelationshipCache} from "@/utils/cache/TokenRelationshipCache" export class NftTransactionAnalyzer { - public readonly transaction: Ref; + public readonly transaction: Ref public readonly entityDescriptor = ref( EntityDescriptor.DEFAULT_ENTITY_DESCRIPTOR, - ); - public readonly tokenRelationships: Ref = ref([]); - private readonly watchHandles: WatchStopHandle[] = []; + ) + public readonly tokenRelationships: Ref = ref([]) + private readonly watchHandles: WatchStopHandle[] = [] // // Public // public constructor(transaction: Ref) { - this.transaction = transaction; + this.transaction = transaction } public mount(): void { @@ -49,47 +49,47 @@ export class NftTransactionAnalyzer { watch(this.transaction, this.transactionDidChange, { immediate: true, }), - ); + ) } public unmount(): void { - this.watchHandles.map((wh) => wh()); - this.watchHandles.splice(0); + this.watchHandles.map((wh) => wh()) + this.watchHandles.splice(0) } public readonly consensusTimestamp = computed( () => this.transaction.value?.consensus_timestamp ?? null, - ); + ) public readonly transactionType = computed( () => this.transaction.value?.type ?? null, - ); + ) public readonly entityId = computed( () => this.transaction.value?.sender_account_id ?? null, - ); + ) public readonly formattedTransactionId: ComputedRef = computed(() => { - const transaction_id = this.transaction.value?.transaction_id; + const transaction_id = this.transaction.value?.transaction_id return transaction_id ? normalizeTransactionId(transaction_id, true) - : null; - }); + : null + }) public readonly isTokenAssociation = computed( () => this.transactionType.value === TransactionType.TOKENASSOCIATE, - ); + ) public readonly tokens = computed(() => { - const result: string[] = []; + const result: string[] = [] for (const r of this.tokenRelationships.value) { if (r.token_id) { - result.push(r.token_id); + result.push(r.token_id) } } - return result; - }); + return result + }) // // Private @@ -104,29 +104,29 @@ export class NftTransactionAnalyzer { ) { const r = await TokenRelationshipCache.instance.lookup( this.entityId.value, - ); + ) this.tokenRelationships.value = this.filterTokenRelationships( r ?? [], this.consensusTimestamp.value, - ); + ) } else { - this.tokenRelationships.value = []; + this.tokenRelationships.value = [] } } else { - this.tokenRelationships.value = []; + this.tokenRelationships.value = [] } - }; + } private filterTokenRelationships( relationships: TokenRelationship[], createdTimestamp: string, ): TokenRelationship[] { - const result: TokenRelationship[] = []; + const result: TokenRelationship[] = [] for (const r of relationships) { if (r.created_timestamp === createdTimestamp && r.token_id) { - result.push(r); + result.push(r) } } - return result; + return result } } diff --git a/src/components/transaction/NftTransactionSummary.vue b/src/components/transaction/NftTransactionSummary.vue index 748500dca..73384d284 100644 --- a/src/components/transaction/NftTransactionSummary.vue +++ b/src/components/transaction/NftTransactionSummary.vue @@ -23,30 +23,30 @@ - - - - {{ transaction?.sender_account_id }} - + + + + {{ transaction?.sender_account_id }} + - + {{ " ( + " + additionalTokensNumber + " more )" }} - - - - + + + + @@ -60,25 +60,25 @@ import { onBeforeUnmount, onMounted, PropType, -} from "vue"; +} from "vue" import { NftTransactionTransfer, TransactionType, -} from "@/schemas/HederaSchemas"; -import { makeSummaryLabel } from "@/utils/TransactionTools"; -import NftTransferGraphSection from "@/components/transfer_graphs/NftTransferGraphSection.vue"; -import TokenExtra from "@/components/values/TokenExtra.vue"; -import { NftTransactionAnalyzer } from "./NftTransactionAnalyzer"; +} from "@/schemas/HederaSchemas" +import {makeSummaryLabel} from "@/utils/TransactionTools" +import NftTransferGraphSection from "@/components/transfer_graphs/NftTransferGraphSection.vue" +import TokenExtra from "@/components/values/TokenExtra.vue" +import {NftTransactionAnalyzer} from "./NftTransactionAnalyzer" const GRAPH_TRANSACTION_TYPES = [ TransactionType.CRYPTOTRANSFER, TransactionType.TOKENBURN, TransactionType.TOKENMINT, -]; +] export default defineComponent({ name: "NftTransactionSummary", - components: { TokenExtra, NftTransferGraphSection }, + components: {TokenExtra, NftTransferGraphSection}, props: { transaction: Object as PropType, }, @@ -88,22 +88,22 @@ export default defineComponent({ return ( props.transaction?.type && GRAPH_TRANSACTION_TYPES.indexOf(props.transaction.type) != -1 - ); - }); + ) + }) const transactionAnalyzer = new NftTransactionAnalyzer( computed(() => props.transaction ?? null), - ); - onMounted(() => transactionAnalyzer.mount()); - onBeforeUnmount(() => transactionAnalyzer.unmount()); + ) + onMounted(() => transactionAnalyzer.mount()) + onBeforeUnmount(() => transactionAnalyzer.unmount()) const additionalTokensNumber = computed(() => Math.max(0, transactionAnalyzer.tokens.value.length - 1), - ); + ) const transactionDetail = computed(() => { - return props.transaction; - }); + return props.transaction + }) return { shouldGraph, @@ -114,13 +114,13 @@ export default defineComponent({ makeSummaryLabel, TransactionType, transactionDetail, - }; + } }, -}); +}) - + diff --git a/src/components/transaction/NftTransactionTable.vue b/src/components/transaction/NftTransactionTable.vue index 93de2f296..0adddfa64 100644 --- a/src/components/transaction/NftTransactionTable.vue +++ b/src/components/transaction/NftTransactionTable.vue @@ -23,60 +23,60 @@ - + + + + + + + + {{ makeTypeLabel(props.row.type) }} + + + + + - - - - - - - - {{ makeTypeLabel(props.row.type) }} - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -91,21 +91,21 @@ import { inject, PropType, Ref, -} from "vue"; +} from "vue" import { NftTransactionTransfer, Transaction, TransactionType, -} from "@/schemas/HederaSchemas"; -import NftTransactionSummary from "@/components/transaction/NftTransactionSummary.vue"; -import TimestampValue from "@/components/values/TimestampValue.vue"; -import TransactionLabel from "@/components/values/TransactionLabel.vue"; -import { makeTypeLabel } from "@/utils/TransactionTools"; -import { routeManager } from "@/router"; -import { ORUGA_MOBILE_BREAKPOINT } from "@/App.vue"; -import EmptyTable from "@/components/EmptyTable.vue"; -import InnerSenderEVMAddress from "@/components/values/InnerSenderEVMAddress.vue"; -import { NftTransactionTableController } from "./NftTransactionTableController"; +} from "@/schemas/HederaSchemas" +import NftTransactionSummary from "@/components/transaction/NftTransactionSummary.vue" +import TimestampValue from "@/components/values/TimestampValue.vue" +import TransactionLabel from "@/components/values/TransactionLabel.vue" +import {makeTypeLabel} from "@/utils/TransactionTools" +import {routeManager} from "@/router" +import {ORUGA_MOBILE_BREAKPOINT} from "@/App.vue" +import EmptyTable from "@/components/EmptyTable.vue" +import InnerSenderEVMAddress from "@/components/values/InnerSenderEVMAddress.vue" +import {NftTransactionTableController} from "./NftTransactionTableController" export default defineComponent({ name: "NftTransactionTable", @@ -127,15 +127,15 @@ export default defineComponent({ }, setup(props) { - const isTouchDevice = inject("isTouchDevice", false); - const isMediumScreen = inject("isMediumScreen", true); + const isTouchDevice = inject("isTouchDevice", false) + const isMediumScreen = inject("isMediumScreen", true) const showingEthereumTransactions = computed(() => { return ( props.controller.transactionType.value === TransactionType.ETHEREUMTRANSACTION - ); - }); + ) + }) const handleClick = ( t: Transaction, @@ -144,15 +144,19 @@ export default defineComponent({ ci: number, event: MouseEvent, ) => { - routeManager.routeToTransaction(t, event.ctrlKey || event.metaKey); - }; + routeManager.routeToTransaction(t, event.ctrlKey || event.metaKey) + } + + const transactions = computed(() => { + return props.controller.rows.value.filter(el => + !props.controller.transactionType.value || el.type === props.controller.transactionType.value + ) + }) return { isTouchDevice, isMediumScreen, - transactions: props.controller.rows as ComputedRef< - NftTransactionTransfer[] - >, + transactions: transactions, loading: props.controller.loading as ComputedRef, total: props.controller.totalRowCount as ComputedRef, currentPage: props.controller.currentPage as Ref, @@ -162,7 +166,7 @@ export default defineComponent({ handleClick, makeTypeLabel, ORUGA_MOBILE_BREAKPOINT, - }; + } }, -}); +}) diff --git a/src/components/transaction/NftTransactionTableController.ts b/src/components/transaction/NftTransactionTableController.ts index e9a14d511..76d6b50b2 100644 --- a/src/components/transaction/NftTransactionTableController.ts +++ b/src/components/transaction/NftTransactionTableController.ts @@ -22,22 +22,22 @@ import { KeyOperator, SortOrder, TableController, -} from "@/utils/table/TableController"; +} from "@/utils/table/TableController" import { NftTransactionTransfer, NftTransactionHistory, -} from "@/schemas/HederaSchemas"; -import { ComputedRef, ref, Ref, watch, WatchStopHandle } from "vue"; -import axios from "axios"; -import { LocationQuery, Router } from "vue-router"; -import { fetchStringQueryParam } from "@/utils/RouteManager"; +} from "@/schemas/HederaSchemas" +import {ComputedRef, ref, Ref, watch, WatchStopHandle} from "vue" +import axios from "axios" +import {LocationQuery, Router} from "vue-router" +import {fetchStringQueryParam} from "@/utils/RouteManager" export class NftTransactionTableController extends TableController< NftTransactionTransfer, string > { - private readonly tokenId: Ref; - private readonly serialNumber: Ref; + private readonly tokenId: Ref + private readonly serialNumber: Ref // // Public @@ -60,17 +60,17 @@ export class NftTransactionTableController extends TableController< 100, pageParamName, keyParamName, - ); - this.tokenId = tokenId; - this.serialNumber = serialNumber; + ) + this.tokenId = tokenId + this.serialNumber = serialNumber this.watchAndReload([ this.transactionType, this.tokenId, this.serialNumber, - ]); + ]) } - public readonly transactionType: Ref = ref(""); + public readonly transactionType: Ref = ref("") // // TableController @@ -83,78 +83,74 @@ export class NftTransactionTableController extends TableController< limit: number, ): Promise { if (this.tokenId.value === null || this.serialNumber.value === null) { - return Promise.resolve(null); + return Promise.resolve(null) } const params = {} as { - limit: number; - order: string; - transactiontype: string | undefined; - timestamp: string | undefined; - }; - params.limit = limit; - params.order = order; - - if (this.transactionType.value != "") { - params.transactiontype = this.transactionType.value; + limit: number + order: string + timestamp: string | undefined } + params.limit = limit + params.order = order + if (consensusTimestamp !== null) { - params.timestamp = operator + ":" + consensusTimestamp; + params.timestamp = operator + ":" + consensusTimestamp } const r = await axios.get( `api/v1/tokens/${this.tokenId.value}/nfts/${this.serialNumber.value}/transactions`, - { params: params }, - ); - return r.data.transactions ?? []; + {params: params}, + ) + return r.data.transactions ?? [] } public keyFor(row: NftTransactionTransfer): string { - return row.consensus_timestamp ?? ""; + return row.consensus_timestamp ?? "" } public keyFromString(s: string): string | null { - return s; + return s } public stringFromKey(key: string): string { - return key; + return key } public mount(): void { // Must be done before calling mount() - this.transactionType.value = this.fetchTransactionTypeParam(); - super.mount(); + this.transactionType.value = this.fetchTransactionTypeParam() + super.mount() this.watchTransactionTypeHandle = watch(this.transactionType, () => this.updateRouteQuery(), - ); + ) } public unmount(): void { if (this.watchTransactionTypeHandle !== null) { - this.watchTransactionTypeHandle(); + this.watchTransactionTypeHandle() } - this.watchTransactionTypeHandle = null; - super.unmount(); + this.watchTransactionTypeHandle = null + super.unmount() } protected makeRouteQuery(): LocationQuery { - const result = super.makeRouteQuery(); + const result = super.makeRouteQuery() if (this.transactionType.value != "") { result[this.typeParamName] = - this.transactionType.value.toLowerCase(); + this.transactionType.value.toLowerCase() } else { - delete result[this.typeParamName]; + delete result[this.typeParamName] } - return result; + return result } // // Private // - private readonly typeParamName = "type"; - private watchTransactionTypeHandle: WatchStopHandle | null = null; + private readonly typeParamName = "type" + private watchTransactionTypeHandle: WatchStopHandle | null = null public fetchTransactionTypeParam(): string { return ( @@ -162,6 +158,6 @@ export class NftTransactionTableController extends TableController< this.typeParamName, this.router.currentRoute.value, )?.toUpperCase() ?? "" - ); + ) } } diff --git a/src/components/transaction/TransactionFilterSelect.vue b/src/components/transaction/TransactionFilterSelect.vue index aad250f43..976e9913d 100644 --- a/src/components/transaction/TransactionFilterSelect.vue +++ b/src/components/transaction/TransactionFilterSelect.vue @@ -23,13 +23,15 @@ - - - - {{ makeFilterLabel(f) }} - - - + + + + + {{ makeFilterLabel(f) }} + + + + @@ -37,53 +39,62 @@ - + diff --git a/src/components/transaction/TransactionTableControllerXL.ts b/src/components/transaction/TransactionTableControllerXL.ts index ce9de6acc..e96f12a4f 100644 --- a/src/components/transaction/TransactionTableControllerXL.ts +++ b/src/components/transaction/TransactionTableControllerXL.ts @@ -18,153 +18,120 @@ * */ -import { - KeyOperator, - SortOrder, - TableController, -} from "@/utils/table/TableController"; -import { Transaction, TransactionResponse } from "@/schemas/HederaSchemas"; -import { ComputedRef, ref, Ref, watch, WatchStopHandle } from "vue"; -import axios, { AxiosResponse } from "axios"; -import { LocationQuery, Router } from "vue-router"; -import { fetchStringQueryParam } from "@/utils/RouteManager"; - -export class TransactionTableControllerXL extends TableController< - Transaction, - string -> { - private readonly entityId: Ref; - private readonly accountIdMandatory: boolean; +import {KeyOperator, SortOrder, TableController} from "@/utils/table/TableController"; +import {Transaction, TransactionResponse} from "@/schemas/HederaSchemas"; +import {ComputedRef, ref, Ref, watch, WatchStopHandle} from "vue"; +import axios, {AxiosResponse} from "axios"; +import {LocationQuery, Router} from "vue-router"; +import {fetchStringQueryParam} from "@/utils/RouteManager"; + + +export class TransactionTableControllerXL extends TableController { + + private readonly accountId: Ref + private readonly accountIdMandatory: boolean // // Public // - public constructor( - router: Router, - entityId: Ref, - pageSize: ComputedRef, - accountIdMandatory: boolean, - pageParamName = "p", - keyParamName = "k", - ) { - super( - router, - pageSize, - 10 * pageSize.value, - 5000, - 10, - 100, - pageParamName, - keyParamName, - ); - this.entityId = entityId; - this.accountIdMandatory = accountIdMandatory; - this.watchAndReload([this.transactionType, this.entityId]); + public constructor(router: Router, + accountId: Ref, + pageSize: ComputedRef, + accountIdMandatory: boolean, + pageParamName = "p", keyParamName= "k") { + super(router, pageSize, 10 * pageSize.value, 5000, 10, 100, + pageParamName, keyParamName); + this.accountId = accountId + this.accountIdMandatory = accountIdMandatory + this.watchAndReload([this.transactionType, this.accountId]) } - public readonly transactionType: Ref = ref(""); + public readonly transactionType: Ref = ref("") // // TableController // - public async load( - consensusTimestamp: string | null, - operator: KeyOperator, - order: SortOrder, - limit: number, - ): Promise { - let result: Promise; + public async load(consensusTimestamp: string | null, operator: KeyOperator, + order: SortOrder, limit: number): Promise { + let result: Promise - if (this.accountIdMandatory && this.entityId.value === null) { - result = Promise.resolve(null); + if (this.accountIdMandatory && this.accountId.value === null) { + result = Promise.resolve(null) } else { const params = {} as { - limit: number; - order: string; - "account.id": string | undefined; - transactiontype: string | undefined; - timestamp: string | undefined; - }; - params.limit = limit; - params.order = order; - if (this.entityId.value !== null) { - params["account.id"] = this.entityId.value; + limit: number + order: string + "account.id": string | undefined + transactiontype: string | undefined + timestamp: string | undefined + } + params.limit = limit + params.order = order + if (this.accountId.value !== null) { + params["account.id"] = this.accountId.value } if (this.transactionType.value != "") { - params.transactiontype = this.transactionType.value; + params.transactiontype = this.transactionType.value } if (consensusTimestamp !== null) { - params.timestamp = operator + ":" + consensusTimestamp; + params.timestamp = operator + ":" + consensusTimestamp + } + const cb = (r: AxiosResponse): Promise => { + return Promise.resolve(r.data.transactions ?? []) } - const cb = ( - r: AxiosResponse, - ): Promise => { - return Promise.resolve(r.data.transactions ?? []); - }; - result = axios - .get("api/v1/transactions", { - params: params, - }) - .then(cb); + result = axios.get("api/v1/transactions", {params: params}).then(cb) } - return result; + return result } public keyFor(row: Transaction): string { - return row.consensus_timestamp ?? ""; + return row.consensus_timestamp ?? "" } public keyFromString(s: string): string | null { - return s; + return s } public stringFromKey(key: string): string { - return key; + return key } public mount(): void { - this.transactionType.value = this.fetchTransactionTypeParam(); // Must be done before calling mount() - super.mount(); - this.watchTransactionTypeHandle = watch(this.transactionType, () => - this.updateRouteQuery(), - ); + this.transactionType.value = this.fetchTransactionTypeParam() // Must be done before calling mount() + super.mount() + this.watchTransactionTypeHandle = watch(this.transactionType, () => this.updateRouteQuery()) } public unmount(): void { if (this.watchTransactionTypeHandle !== null) { - this.watchTransactionTypeHandle(); + this.watchTransactionTypeHandle() } this.watchTransactionTypeHandle = null; - super.unmount(); + super.unmount() } protected makeRouteQuery(): LocationQuery { - const result = super.makeRouteQuery(); + const result = super.makeRouteQuery() if (this.transactionType.value != "") { - result[this.typeParamName] = - this.transactionType.value.toLowerCase(); + result[this.typeParamName] = this.transactionType.value.toLowerCase() } else { - delete result[this.typeParamName]; + delete(result[this.typeParamName]) } - return result; + return result } // // Private // - private readonly typeParamName = "type"; - private watchTransactionTypeHandle: WatchStopHandle | null = null; + private readonly typeParamName = "type" + private watchTransactionTypeHandle: WatchStopHandle|null = null public fetchTransactionTypeParam(): string { - return ( - fetchStringQueryParam( - this.typeParamName, - this.router.currentRoute.value, - )?.toUpperCase() ?? "" - ); + return fetchStringQueryParam(this.typeParamName, this.router.currentRoute.value)?.toUpperCase() ?? "" } + } diff --git a/src/components/transfer_graphs/NftDetailsTransferGraph.vue b/src/components/transfer_graphs/NftDetailsTransferGraph.vue index 87d1be066..e7e75b59f 100644 --- a/src/components/transfer_graphs/NftDetailsTransferGraph.vue +++ b/src/components/transfer_graphs/NftDetailsTransferGraph.vue @@ -143,8 +143,6 @@ export default defineComponent({ }), ); - console.log(nftTransferLayout); - watch( () => props.transaction, () => { diff --git a/src/components/transfer_graphs/NftTransferGraphSection.vue b/src/components/transfer_graphs/NftTransferGraphSection.vue index ea31c5f85..c09957efd 100644 --- a/src/components/transfer_graphs/NftTransferGraphSection.vue +++ b/src/components/transfer_graphs/NftTransferGraphSection.vue @@ -23,14 +23,14 @@ - + v-bind:transaction="transaction" + v-bind:compact="compact" + /> @@ -38,9 +38,9 @@ - - - - - - diff --git a/src/pages/AccountBalances.vue b/src/pages/AccountBalances.vue index 775007e7f..d9068771c 100644 --- a/src/pages/AccountBalances.vue +++ b/src/pages/AccountBalances.vue @@ -36,6 +36,16 @@ + + + NFTs owned by + {{ accountId }} + + + + + + @@ -53,12 +63,15 @@ import BalanceTable from "@/components/account/BalanceTable.vue"; import DashboardCard from "@/components/DashboardCard.vue"; import Footer from "@/components/Footer.vue"; import {BalanceCache} from "@/utils/cache/BalanceCache"; +import { NftByAccountCache } from "@/utils/cache/NftByAccountCache"; +import NftsTable from "@/components/account/NftsTable.vue"; export default defineComponent({ name: 'AccountBalances', components: { + NftsTable, Footer, DashboardCard, BalanceTable @@ -77,18 +90,31 @@ export default defineComponent({ // balanceLookup // const balanceLookup = BalanceCache.instance.makeLookup(computed(() => props.accountId ?? null)) - onMounted(() => balanceLookup.mount()) - onBeforeUnmount(() => balanceLookup.unmount()) + const nftsLookup = NftByAccountCache.instance.makeLookup(computed(() => props.accountId ?? null)) + onMounted(() => { + balanceLookup.mount() + nftsLookup.mount() + }) + onBeforeUnmount(() => { + balanceLookup.unmount() + nftsLookup.mount() + }) const tokenBalances = computed(() => { const allBalances = balanceLookup.entity.value?.balances return allBalances && allBalances.length >= 1 ? allBalances[0].tokens : [] }) + const nfts = computed(() => { + const allNfts = nftsLookup.entity.value?.nfts + return allNfts + }) + return { isSmallScreen, isTouchDevice, tokenBalances, + nfts } } }); diff --git a/src/pages/NftDetails.vue b/src/pages/NftDetails.vue index 464d45eb0..07183ddf5 100644 --- a/src/pages/NftDetails.vue +++ b/src/pages/NftDetails.vue @@ -23,381 +23,124 @@ - - - - - Serial Number - - {{ serialNumber }} - - - - Token ID: - - - - - {{ normalizedTokenId ?? "" }} - - - -{{ tokenChecksum }} - - - - - EVM Address: - - - - - - - - - - - - - - - - - Name - - - - - - Symbol - - - - - - Memo - - - - - - - Expires at - - - - - - - - - Auto Renew Period - - - - - - - - - Auto Renew Account - - - - - - - - Freeze Default - - - - - - Pause Status - - - - - - - - - - Treasury Account - - - - - - Created at - - - - - - Modified at - - - - - - Total Supply - - - - - - Initial Supply - - - - - - Max Supply - - - Infinite - - - - - - Decimals - - - - - - - - - - Token Keys - - - - - Admin Key - - - - - - KYC Key - - - - - - Freeze Key - - - - - - Wipe Key - - - - - - - - - Supply Key - - - - - - Fee Schedule Key - - - - - - Pause Key - - - - - - - - - - - - - Recent Transactions - - - - - - - - - - - - - - - - - - - + + + + Serial Number {{ serialNumber }} + + {{ symbol }} + + + + + + + + + + Token ID + + + + + + Account ID + + + + + + Created Timestamp + + + + + + Delegating Spender + + + + + + Metadata + + + + + + Modified Timestamp + + + + + + Spender ID + + + + + + + + + + + Recent Transactions + + + + + + + + + + + + + + + + + + + @@ -413,60 +156,42 @@ import { onMounted, ref, watch, -} from "vue"; -import { useRouter } from "vue-router"; -import router, { routeManager } from "@/router"; -import KeyValue from "@/components/values/KeyValue.vue"; -import TimestampValue from "@/components/values/TimestampValue.vue"; -import DurationValue from "@/components/values/DurationValue.vue"; -import DashboardCard from "@/components/DashboardCard.vue"; -import BlobValue from "@/components/values/BlobValue.vue"; -import TokenAmount from "@/components/values/TokenAmount.vue"; -import Footer from "@/components/Footer.vue"; -import MetaMaskImport from "@/components/token/MetaMaskImport.vue"; -import { EntityID } from "@/utils/EntityID"; -import Property from "@/components/Property.vue"; -import NotificationBanner from "@/components/NotificationBanner.vue"; -import PlayPauseButton from "@/components/PlayPauseButton.vue"; -import { TokenBalanceTableController } from "@/components/token/TokenBalanceTableController"; -import AccountLink from "@/components/values/AccountLink.vue"; -import StringValue from "@/components/values/StringValue.vue"; -import TokenCustomFees from "@/components/token/TokenCustomFees.vue"; -import EVMAddress from "@/components/values/EVMAddress.vue"; +} from "vue" +import router, {routeManager} from "@/router" +import TimestampValue from "@/components/values/TimestampValue.vue" +import DashboardCard from "@/components/DashboardCard.vue" +import BlobValue from "@/components/values/BlobValue.vue" +import Footer from "@/components/Footer.vue" +import {EntityID} from "@/utils/EntityID" +import Property from "@/components/Property.vue" +import NotificationBanner from "@/components/NotificationBanner.vue" +import PlayPauseButton from "@/components/PlayPauseButton.vue" +import AccountLink from "@/components/values/AccountLink.vue" +import {NftBySerialCache} from "@/utils/cache/NftBySerialCache" +import ContractResultsSection from "@/components/contracts/ContractResultsSection.vue" +import NftTransactionTable from "@/components/transaction/NftTransactionTable.vue" +import {NftTransactionTableController} from "@/components/transaction/NftTransactionTableController" +import TransactionFilterSelect from "@/components/transaction/TransactionFilterSelect.vue" import { makeTokenSymbol } from "@/schemas/HederaUtils"; import { TokenInfoCache } from "@/utils/cache/TokenInfoCache"; -import { TokenInfoAnalyzer } from "@/components/token/TokenInfoAnalyzer"; -import ContractResultsSection from "@/components/contracts/ContractResultsSection.vue"; -import InfoTooltip from "@/components/InfoTooltip.vue"; -import Copyable from "@/components/Copyable.vue"; -import NftTransactionTable from "@/components/transaction/NftTransactionTable.vue"; -import { NftTransactionTableController } from "@/components/transaction/NftTransactionTableController"; -import TransactionFilterSelect from "@/components/transaction/TransactionFilterSelect.vue"; +import TokenLink from "@/components/values/TokenLink.vue"; export default defineComponent({ name: "NftDetails", components: { - Copyable, - InfoTooltip, - ContractResultsSection, - EVMAddress, - TokenCustomFees, - PlayPauseButton, - StringValue, - AccountLink, - NotificationBanner, - Property, - MetaMaskImport, - Footer, - BlobValue, - DashboardCard, - TimestampValue, - DurationValue, - TokenAmount, - KeyValue, - NftTransactionTable, - TransactionFilterSelect, + TokenLink, + ContractResultsSection, + PlayPauseButton, + AccountLink, + NotificationBanner, + Property, + BlobValue, + DashboardCard, + TimestampValue, + NftTransactionTable, + TransactionFilterSelect, + Footer, }, props: { @@ -482,69 +207,62 @@ export default defineComponent({ }, setup(props) { - const isSmallScreen = inject("isSmallScreen", true); - const isMediumScreen = inject("isMediumScreen", true); - const isTouchDevice = inject("isTouchDevice", false); + const isSmallScreen = inject("isSmallScreen", true) + const isMediumScreen = inject("isMediumScreen", true) + const isTouchDevice = inject("isTouchDevice", false) const normalizedTokenId = computed(() => { const result = EntityID.parse(props.tokenId) ?? - EntityID.fromAddress(props.tokenId); - return result !== null ? result.toString() : null; - }); - const validEntityId = computed(() => normalizedTokenId.value != null); + EntityID.fromAddress(props.tokenId) + return result !== null ? result.toString() : null + }) + const validEntityId = computed(() => normalizedTokenId.value != null) - const tokenLookup = - TokenInfoCache.instance.makeLookup(normalizedTokenId); - onMounted(() => tokenLookup.mount()); - onBeforeUnmount(() => tokenLookup.unmount()); + const tokenLookup = TokenInfoCache.instance.makeLookup(normalizedTokenId) + onMounted(() => tokenLookup.mount()) + onBeforeUnmount(() => tokenLookup.unmount()) - const tokenAnalyzer = new TokenInfoAnalyzer(tokenLookup.entity); + const symbol = computed(() => makeTokenSymbol(tokenLookup.entity.value, 256)) - const displaySymbol = computed(() => - makeTokenSymbol(tokenLookup.entity.value, 256), - ); + const serialNumber = ref(props.serialNumber) + const nftLookup = NftBySerialCache.instance.makeLookup( + normalizedTokenId, + serialNumber, + ) + onMounted(() => nftLookup.mount()) + onBeforeUnmount(() => nftLookup.unmount()) const notification = computed(() => { - let result; + let result if (!validEntityId.value) { - result = "Invalid token ID: " + props.tokenId; - } else if (tokenLookup.entity.value == null) { - if (tokenLookup.isLoaded()) { + result = "Invalid token ID: " + props.tokenId + } else if (nftLookup.entity.value == null) { + if (nftLookup.isLoaded()) { result = - "Token with ID " + props.tokenId + " was not found"; + "Token with ID " + props.tokenId + " was not found" } else { - result = null; + result = null } - } else if (tokenLookup.entity.value?.deleted) { - result = "Token is deleted"; + } else if (nftLookup.entity.value?.deleted) { + result = "Token is deleted" } else { - result = null; + result = null } - return result; - }); + return result + }) - const showTokenDetails = (tokenId: string) => { - routeManager.routeToToken(tokenId); - }; + const shownftDetails = (tokenId: string) => { + routeManager.routeToToken(tokenId) + } - const perPage = computed(() => (isMediumScreen ? 10 : 5)); + const perPage = computed(() => (isMediumScreen ? 10 : 5)) // // TokenBalanceTableController // - const serialNumber = ref(props.serialNumber); - const tokenId = ref(props.tokenId); - const fungibleTokenId = computed(() => - tokenAnalyzer.isFungible.value ? normalizedTokenId.value : null, - ); - const tokenBalanceTableController = new TokenBalanceTableController( - useRouter(), - fungibleTokenId, - perPage, - ); - onMounted(() => tokenBalanceTableController.mount()); - onBeforeUnmount(() => tokenBalanceTableController.unmount()); + + const tokenId = ref(props.tokenId) // // TransactionTableController @@ -556,63 +274,55 @@ export default defineComponent({ perPage, "p1", "k1", - ); + ) - let mounted = false; + let mounted = false onMounted(() => { - mounted = true; + mounted = true if (serialNumber.value !== null) { - transactionTableController.mount(); + transactionTableController.mount() } - }); + }) onBeforeUnmount(() => { - mounted = false; + mounted = false if (serialNumber.value !== null) { - transactionTableController.unmount(); + transactionTableController.unmount() } - }); + }) watch(serialNumber, () => { if (mounted) { if (serialNumber.value !== null) { - transactionTableController.mount(); + transactionTableController.mount() } else { - transactionTableController.unmount(); + transactionTableController.unmount() } } - }); + }) return { isSmallScreen, isMediumScreen, isTouchDevice, - displaySymbol, - analyzer: tokenAnalyzer, - tokenInfo: tokenLookup.entity, - isNft: tokenAnalyzer.isNft, - isFungible: tokenAnalyzer.isFungible, - hasCustomFees: tokenAnalyzer.hasCustomFees, - tokenChecksum: tokenAnalyzer.tokenChecksum, + nftInfo: nftLookup.entity, validEntityId, normalizedTokenId, notification, - showTokenDetails, + shownftDetails, parseBigIntString, - ethereumAddress: tokenAnalyzer.ethereumAddress, - tokenSymbol: tokenAnalyzer.tokenSymbol, - tokenBalanceTableController, transactionTableController, - }; + symbol + } }, -}); +}) function parseBigIntString(s: string | undefined): bigint | undefined { - let result: bigint | undefined; + let result: bigint | undefined try { - result = s ? BigInt(s) : undefined; + result = s ? BigInt(s) : undefined } catch { - result = undefined; + result = undefined } - return result; + return result } diff --git a/src/schemas/HederaSchemas.ts b/src/schemas/HederaSchemas.ts index 0590daed0..3b3702a7d 100644 --- a/src/schemas/HederaSchemas.ts +++ b/src/schemas/HederaSchemas.ts @@ -22,89 +22,89 @@ // Account // --------------------------------------------------------------------------------------------------------------------- -import { EntityID } from "@/utils/EntityID"; -import { makeDefaultNodeDescription } from "@/schemas/HederaUtils"; +import {EntityID} from "@/utils/EntityID"; +import {makeDefaultNodeDescription} from "@/schemas/HederaUtils"; export interface AccountsResponse { - accounts: AccountInfo[] | undefined; - links: Links | undefined; + accounts: AccountInfo[] | undefined + links: Links | undefined } export interface AccountInfo { - account: string | null; // Network entity ID in the format of shard.realm.num - auto_renew_period: number | null; - balance: Balance | null; - created_timestamp: string | null; - deleted: boolean | null; - expiry_timestamp: string | null; - key: Key | null; - max_automatic_token_associations: number | null; - memo: string | null; - receiver_sig_required: boolean | null; - alias: string | null; // RFC4648 no-padding base32 encoded account alias - ethereum_nonce: number | null; - evm_address: string | null; // A network entity encoded as an EVM address in hex. - decline_reward: boolean | null; // Whether the account declines receiving a staking reward - staked_account_id: string | null; // The account to which this account is staking - staked_node_id: number | null; // The id of the node to which this account is staking - stake_period_start: string | null; // The staking period during which either the staking settings for this account - // changed (such as starting staking or changing stakedNode) or the most recent - // reward was earned, whichever is later. If this account is not currently - // staked to a node, then the value is null - pending_reward: number | undefined; // The pending reward in tinybars the account will receive in the next - // reward payout. Note the value is updated at the end of each staking period - // and there may be delay to reflect the changes in the past staking period. + account: string | null // Network entity ID in the format of shard.realm.num + auto_renew_period: number | null + balance: Balance | null + created_timestamp: string | null + deleted: boolean | null + expiry_timestamp: string | null + key : Key | null + max_automatic_token_associations: number | null + memo: string | null + receiver_sig_required: boolean | null + alias: string | null // RFC4648 no-padding base32 encoded account alias + ethereum_nonce: number | null + evm_address: string | null // A network entity encoded as an EVM address in hex. + decline_reward: boolean | null // Whether the account declines receiving a staking reward + staked_account_id: string | null // The account to which this account is staking + staked_node_id: number | null // The id of the node to which this account is staking + stake_period_start : string | null // The staking period during which either the staking settings for this account + // changed (such as starting staking or changing stakedNode) or the most recent + // reward was earned, whichever is later. If this account is not currently + // staked to a node, then the value is null + pending_reward: number | undefined // The pending reward in tinybars the account will receive in the next + // reward payout. Note the value is updated at the end of each staking period + // and there may be delay to reflect the changes in the past staking period. } export interface AccountBalanceTransactions extends AccountInfo { - transactions?: Array; - links?: Links; + transactions?: Array + links?: Links } export interface Balance { - timestamp: string | null; - balance: number | null; - tokens: TokenBalance[]; + timestamp: string | null + balance: number | null + tokens: TokenBalance[] } export interface TokenBalance { - token_id: string | null; // Network entity ID in the format of shard.realm.num - balance: number; + token_id: string | null // Network entity ID in the format of shard.realm.num + balance: number } export interface TokenRelationshipResponse { - tokens: Array; - links: Links; + tokens: Array, + links: Links } export interface TokenRelationship { - automatic_association: boolean; - balance: number; - created_timestamp: string; - freeze_status: string; // [ NOT_APPLICABLE, FROZEN, UNFROZEN ] - kyc_status: string; // [ NOT_APPLICABLE, GRANTED, REVOKED ] - token_id: string | null; + automatic_association: boolean, + balance: number, + created_timestamp: string, + freeze_status: string, // [ NOT_APPLICABLE, FROZEN, UNFROZEN ] + kyc_status: string, // [ NOT_APPLICABLE, GRANTED, REVOKED ] + token_id: string | null, } export interface CryptoAllowancesResponse { - allowances: Array; - links: Links; + allowances: Array, + links: Links } export interface CryptoAllowance { - amount_granted: number; // The granted amount of the spender's allowance in tinybars. - owner: string | null; // Network entity ID in the format of shard.realm.num - spender: string | null; // Network entity ID in the format of shard.realm.num - timestamp: TimestampRange; + amount_granted: number, // The granted amount of the spender's allowance in tinybars. + owner: string | null, // Network entity ID in the format of shard.realm.num + spender: string | null, // Network entity ID in the format of shard.realm.num + timestamp: TimestampRange } export interface TokenAllowancesResponse { - allowances: Array; - links: Links; + allowances: Array, + links: Links } export interface TokenAllowance extends CryptoAllowance { - token_id: string | null; // Network entity ID in the format of shard.realm.num + token_id: string | null, // Network entity ID in the format of shard.realm.num } // --------------------------------------------------------------------------------------------------------------------- @@ -112,15 +112,15 @@ export interface TokenAllowance extends CryptoAllowance { // --------------------------------------------------------------------------------------------------------------------- export interface BalancesResponse { - timestamp: string | null | undefined; - balances: Array | undefined; - links: Links | undefined; + timestamp: string | null | undefined + balances: Array | undefined + links: Links | undefined } export interface AccountBalance { - account: string | null; // Network entity ID in the format of shard.realm.num - balance: number; - tokens: Array; + account: string | null // Network entity ID in the format of shard.realm.num + balance: number + tokens: Array } // --------------------------------------------------------------------------------------------------------------------- @@ -128,17 +128,17 @@ export interface AccountBalance { // --------------------------------------------------------------------------------------------------------------------- export interface TransactionResponse { - transactions: Array | undefined; - links: Links | undefined; + transactions: Array | undefined + links: Links | undefined } export interface NftTransactionHistory { - transactions: Array | undefined; - links: Links | undefined; + transactions: Array | undefined + links: Links | undefined } export interface TransactionByIdResponse { - transactions: Array | undefined; + transactions: Array | undefined } export interface Transaction { @@ -165,13 +165,13 @@ export interface Transaction { } export interface NftTransactionTransfer { - consensus_timestamp: string | undefined; - nonce: number | undefined; - transaction_id: string | undefined; - type: TransactionType | undefined; - is_approval: false; - receiver_account_id: string | null | undefined; // account ID in the format of shard.realm.num - sender_account_id: string | null | undefined; // account ID in the format of shard.realm.num + consensus_timestamp: string | undefined + nonce: number | undefined + transaction_id: string | undefined + type: TransactionType | undefined + is_approval: false + receiver_account_id: string | null | undefined // account ID in the format of shard.realm.num + sender_account_id: string | null | undefined // account ID in the format of shard.realm.num } export interface TransactionDetail extends Transaction { @@ -180,52 +180,54 @@ export interface TransactionDetail extends Transaction { assessed_custom_fees: CustomFee[] } + export interface NftTransfer { - is_approval: boolean; - receiver_account_id: string | null | undefined; // Network entity ID in the format of shard.realm.num - sender_account_id: string | null | undefined; // Network entity ID in the format of shard.realm.num - serial_number: number; - token_id: string | null; // Network entity ID in the format of shard.realm.num} + receiver_account_id: string | null | undefined // Network entity ID in the format of shard.realm.num + sender_account_id: string | null | undefined // Network entity ID in the format of shard.realm.num + is_approval: boolean + serial_number: number + token_id: string | null // Network entity ID in the format of shard.realm.num} } export function compareNftTransfer(t1: NftTransfer, t2: NftTransfer): number { - let result = compareString(t1.sender_account_id, t2.sender_account_id); + + let result = compareString(t1.sender_account_id, t2.sender_account_id) if (result == 0) { - result = compareString(t1.token_id, t2.token_id); + result = compareString(t1.token_id, t2.token_id) } if (result == 0) { - result = compareString(t1.receiver_account_id, t2.receiver_account_id); + result = compareString(t1.receiver_account_id, t2.receiver_account_id) } if (result == 0) { - result = compareNumber(t1.serial_number, t2.serial_number); + result = compareNumber(t1.serial_number, t2.serial_number) } - return result; + return result } export interface Transfer { - account: string | null; // Network entity ID in the format of shard.realm.num - amount: number; - is_approval: boolean | undefined; + account: string | null // Network entity ID in the format of shard.realm.num + amount: number + is_approval: boolean | undefined } export interface TokenTransfer extends Transfer { - token_id: string | null; // Network entity ID in the format of shard.realm.num + token_id: string | null // Network entity ID in the format of shard.realm.num } export interface StakingRewardTransfer { - account: string | null; // Network entity ID in the format of shard.realm.num - amount: number; + account: string | null // Network entity ID in the format of shard.realm.num + amount: number } export interface CustomFee { - amount: number | undefined; - collector_account_id: string | undefined; // Network entity ID in the format of shard.realm.num - effective_payer_account_ids: string[] | undefined; - token_id: string | null | undefined; // Network entity ID in the format of shard.realm.num + amount: number | undefined + collector_account_id: string | undefined // Network entity ID in the format of shard.realm.num + effective_payer_account_ids: string[] | undefined + token_id: string | null | undefined // Network entity ID in the format of shard.realm.num } export enum TransactionType { @@ -273,169 +275,135 @@ export enum TransactionType { UNCHECKEDSUBMIT = "UNCHECKEDSUBMIT", ETHEREUMTRANSACTION = "ETHEREUMTRANSACTION", NODESTAKEUPDATE = "NODESTAKEUPDATE", - UTILPRNG = "UTILPRNG", + UTILPRNG = "UTILPRNG" } export enum TransactionResult { SUCCESS = "success", - FAILURE = "fail", + FAILURE = "fail" } -export function compareTransferByAccount( - t1: Transfer | StakingRewardTransfer, - t2: Transfer | StakingRewardTransfer, -): number { - let result: number; - const account1 = t1.account; - const account2 = t2.account; +export function compareTransferByAccount(t1: Transfer | StakingRewardTransfer, t2: Transfer | StakingRewardTransfer): number { + let result: number + const account1 = t1.account + const account2 = t2.account if (account1 != null && account2 != null) { - const accountId1 = EntityID.parse(account1); - const accountId2 = EntityID.parse(account2); + const accountId1 = EntityID.parse(account1) + const accountId2 = EntityID.parse(account2) if (accountId1 != null && accountId2 != null) { - result = accountId1.compareAccountID(accountId2); + result = accountId1.compareAccountID(accountId2) } else { result = account1.localeCompare(account2); } - } else if (account1 != null) { - result = +1; + } else if (account1 != null){ + result = +1 } else if (account2 != null) { - result = -1; + result = -1 } else { - result = 0; + result = 0 } - return result; + return result } -export function compareTokenTransferByTokenId( - t1: TokenTransfer, - t2: TokenTransfer, -): number { - return compareString(t1.token_id, t2.token_id); +export function compareTokenTransferByTokenId(t1: TokenTransfer, t2: TokenTransfer): number { + return compareString(t1.token_id, t2.token_id) } + // --------------------------------------------------------------------------------------------------------------------- // Token // --------------------------------------------------------------------------------------------------------------------- export interface TokensResponse { - tokens: Token[] | undefined; - links: Links | undefined; + tokens: Token[] | undefined + links: Links | undefined } export interface Token { - token_id: string | null; - symbol: string; - admin_key: Key | null; - type: string; + token_id: string | null + symbol: string + admin_key: Key | null + type: string } export interface TokenInfo { - admin_key: Key | null; - auto_renew_account: string | null; // Network entity ID in the format of shard.realm.num - auto_renew_period: number | null; - created_timestamp: string; - decimals: string; - deleted: boolean | null; - expiry_timestamp: string | null; - fee_schedule_key: Key | null; - freeze_default: boolean; - freeze_key: Key | null; - initial_supply: string; - kyc_key: Key | null; - max_supply: string; - modified_timestamp: string; - name: string; - memo: string; - pause_key: Key | null; - pause_status: string; // NOT_APPLICABLE, PAUSED, UNPAUSED - supply_key: Key | null; - supply_type: string; // FINITE, INFINITE - symbol: string; - token_id: string | null; // Network entity ID in the format of shard.realm.num - total_supply: string; - treasury_account_id: string | null; // Network entity ID in the format of shard.realm.num - type: string; // FUNGIBLE_COMMON, NON_FUNGIBLE_UNIQUE - wipe_key: Key | null; - custom_fees: CustomFees; -} - -export interface NftInfo { - admin_key: Key | null; - auto_renew_account: string | null; // Network entity ID in the format of shard.realm.num - auto_renew_period: number | null; - created_timestamp: string; - decimals: string; - deleted: boolean | null; - expiry_timestamp: string | null; - fee_schedule_key: Key | null; - freeze_default: boolean; - freeze_key: Key | null; - initial_supply: string; - kyc_key: Key | null; - max_supply: string; - modified_timestamp: string; - name: string; - memo: string; - pause_key: Key | null; - pause_status: string; // NOT_APPLICABLE, PAUSED, UNPAUSED - supply_key: Key | null; - supply_type: string; // FINITE, INFINITE - symbol: string; - token_id: string | null; // Network entity ID in the format of shard.realm.num - total_supply: string; - treasury_account_id: string | null; // Network entity ID in the format of shard.realm.num - type: string; // FUNGIBLE_COMMON, NON_FUNGIBLE_UNIQUE - wipe_key: Key | null; - custom_fees: CustomFees; + + admin_key: Key | null + auto_renew_account: string | null // Network entity ID in the format of shard.realm.num + auto_renew_period: number | null + created_timestamp: string + decimals: string + deleted: boolean | null + expiry_timestamp: string | null + fee_schedule_key: Key | null + freeze_default: boolean + freeze_key: Key | null + initial_supply: string + kyc_key: Key | null + max_supply: string + modified_timestamp: string + name: string + memo: string + pause_key: Key | null + pause_status: string // NOT_APPLICABLE, PAUSED, UNPAUSED + supply_key: Key | null + supply_type: string // FINITE, INFINITE + symbol: string + token_id: string | null // Network entity ID in the format of shard.realm.num + total_supply: string + treasury_account_id: string | null // Network entity ID in the format of shard.realm.num + type: string // FUNGIBLE_COMMON, NON_FUNGIBLE_UNIQUE + wipe_key: Key | null + custom_fees: CustomFees } export interface CustomFees { - created_timestamp: string | undefined; - fixed_fees: FixedFee[] | undefined; // Network entity ID in the format of shard.realm.num - fractional_fees: FractionalFee[] | undefined; - royalty_fees: RoyaltyFee[] | null | undefined; // Network entity ID in the format of shard.realm.num + created_timestamp: string | undefined + fixed_fees: FixedFee[] | undefined // Network entity ID in the format of shard.realm.num + fractional_fees: FractionalFee[] | undefined + royalty_fees: RoyaltyFee[] | null | undefined // Network entity ID in the format of shard.realm.num } export interface FixedFee { - amount: number | undefined; - collector_account_id: string | undefined; // Network entity ID in the format of shard.realm.num - denominating_token_id: string | undefined; // Network entity ID in the format of shard.realm.num + amount: number | undefined + collector_account_id: string | undefined // Network entity ID in the format of shard.realm.num + denominating_token_id: string | undefined // Network entity ID in the format of shard.realm.num } export interface FractionalFee { - amount: FractionAmount | undefined; - collector_account_id: string | undefined; // Network entity ID in the format of shard.realm.num - denominating_token_id: string | undefined; // Network entity ID in the format of shard.realm.num - maximum: number | undefined; - mininum: number | undefined; - net_of_transfers: boolean | undefined; + amount: FractionAmount | undefined + collector_account_id: string | undefined // Network entity ID in the format of shard.realm.num + denominating_token_id: string | undefined // Network entity ID in the format of shard.realm.num + maximum: number | undefined + mininum: number | undefined + net_of_transfers: boolean | undefined } export interface RoyaltyFee { - amount: FractionAmount | undefined; - collector_account_id: string | undefined; // Network entity ID in the format of shard.realm.num - fallback_fee: FallbackFee | undefined; // Network entity ID in the format of shard.realm.num + amount: FractionAmount | undefined + collector_account_id: string | undefined // Network entity ID in the format of shard.realm.num + fallback_fee: FallbackFee | undefined // Network entity ID in the format of shard.realm.num } export interface FallbackFee { - amount: number | undefined; - denominating_token_id: string | undefined; // Network entity ID in the format of shard.realm.num + amount: number | undefined + denominating_token_id: string | undefined // Network entity ID in the format of shard.realm.num } export interface FractionAmount { - numerator: number | undefined; - denominator: number | undefined; + numerator: number | undefined + denominator: number | undefined } export interface TokenBalancesResponse { - timestamp: string | null | undefined; - balances: TokenDistribution[] | undefined; - links: Links | undefined; + timestamp: string | null | undefined + balances: TokenDistribution[] | undefined + links: Links | undefined } export interface TokenDistribution { - account: string | null; // Network entity ID in the format of shard.realm.num - balance: number; + account: string | null // Network entity ID in the format of shard.realm.num + balance: number } // --------------------------------------------------------------------------------------------------------------------- @@ -443,18 +411,20 @@ export interface TokenDistribution { // --------------------------------------------------------------------------------------------------------------------- export interface Nfts { - nfts: Nft[] | undefined; - links: Links | undefined; + nfts: Nft[] | undefined + links: Links | undefined } export interface Nft { - account_id: string | null | undefined; // Network entity ID in the format of shard.realm.num - created_timestamp: string | null | undefined; - deleted: boolean; - metadata: string | undefined; - modified_timestamp: string | null | undefined; - serial_number: number | undefined; - token_id: string | null | undefined; // Network entity ID in the format of shard.realm.num + account_id: string | null | undefined // Network entity ID in the format of shard.realm.num + created_timestamp: string | null | undefined + delegating_spender: string | null | undefined + deleted: boolean + metadata: string | undefined + modified_timestamp: string | null | undefined + serial_number: number | undefined + spender_id: string | null | undefined + token_id: string | null | undefined // Network entity ID in the format of shard.realm.num } // --------------------------------------------------------------------------------------------------------------------- @@ -462,31 +432,31 @@ export interface Nft { // --------------------------------------------------------------------------------------------------------------------- export interface TopicMessagesResponse { - messages: Array | undefined; - links: Links | undefined; + messages: Array | undefined + links: Links | undefined } export interface TopicMessage { - chunk_info: ChunkInfo | null; - consensus_timestamp: string; - topic_id: string | null; - message: string; - running_hash: string; - running_hash_version: number; - sequence_number: number; + chunk_info: ChunkInfo | null, + consensus_timestamp: string, + topic_id: string | null, + message: string, + running_hash: string, + running_hash_version: number, + sequence_number: number } export interface ChunkInfo { - initial_transaction_id: TransactionId; - number: number; - total: number; + initial_transaction_id: TransactionId, + number: number, + total: number } export interface TransactionId { - account_id: string | null; - nonce: number | null; - scheduled: boolean | null; - transaction_valid_start: string; + account_id: string | null, + nonce: number | null, + scheduled: boolean | null, + transaction_valid_start: string } // --------------------------------------------------------------------------------------------------------------------- @@ -494,132 +464,133 @@ export interface TransactionId { // --------------------------------------------------------------------------------------------------------------------- export interface ContractsResponse { - contracts: Contract[] | undefined; - links: Links | undefined; + contracts: Contract[] | undefined + links: Links | undefined } export interface Contract { - admin_key: Key | null; - auto_renew_account: string | null; // Network entity ID in the format of shard.realm.num - auto_renew_period: number | null; - contract_id: string | null; // Network entity ID in the format of shard.realm.num - created_timestamp: string | null; - deleted: boolean; - evm_address: string; - expiration_timestamp: string | null; - file_id: string | null | undefined; // Network entity ID in the format of shard.realm.num - max_automatic_token_associations: number | null; - memo: string; - nonce: number | undefined; - obtainer_id: string | null; // Network entity ID in the format of shard.realm.num - permanent_removal: boolean | null; - proxy_account_id: string | null; // Network entity ID in the format of shard.realm.num - timestamp: TimestampRange; // timestamp range the entity is valid for + + admin_key: Key | null + auto_renew_account: string | null // Network entity ID in the format of shard.realm.num + auto_renew_period: number | null + contract_id: string | null // Network entity ID in the format of shard.realm.num + created_timestamp: string | null + deleted: boolean + evm_address: string + expiration_timestamp: string | null + file_id: string | null | undefined // Network entity ID in the format of shard.realm.num + max_automatic_token_associations: number | null + memo: string + nonce: number | undefined + obtainer_id: string | null // Network entity ID in the format of shard.realm.num + permanent_removal: boolean | null + proxy_account_id: string | null // Network entity ID in the format of shard.realm.num + timestamp: TimestampRange // timestamp range the entity is valid for } export interface ContractResponse extends Contract { - bytecode: string | null; - runtime_bytecode: string | null; + bytecode: string | null + runtime_bytecode: string | null } export interface TimestampRange { - from: string | undefined; // The inclusive from timestamp in seconds - to: string | null | undefined; // The exclusive to timestamp in seconds + from: string | undefined // The inclusive from timestamp in seconds + to: string | null | undefined // The exclusive to timestamp in seconds } export interface ContractResultsResponse { - results: Array | undefined; - links: Links | undefined; + results: Array | undefined + links: Links | undefined } export interface ContractResult { - amount: number | null; - bloom: string | null; - call_result: string | null; - contract_id: string | null; - created_contract_ids: Array | null; - error_message: string | null; - from: string; - function_parameters: string; - gas_limit: number; - gas_used: number | null; - hash: string | null; - result: string; - status: string; - timestamp: string; - to: string | null; + amount: number | null + bloom: string | null + call_result: string | null + contract_id: string | null + created_contract_ids: Array | null + error_message: string | null + from: string + function_parameters: string + gas_limit: number + gas_used: number | null + hash: string | null + result: string + status: string + timestamp: string + to: string | null } export interface ContractResultDetails extends ContractResult { - access_list: string | null; - block_gas_used: number | null; // integer - block_hash: string | null; - block_number: number | null; // integer - chain_id: string | null; - gas_price: string | null; - logs: ContractResultLog[]; - max_fee_per_gas: string | null; - max_priority_fee_per_gas: string | null; - nonce: number | null; // integer - r: string | null; - s: string | null; - state_changes: ContractResultStateChange[]; - transaction_index: number | null; // integer - type: number | null; // The type of the wrapped ethereum transaction, 0 (Pre-Eip1559) or 2 (Post-Eip1559) - v: number | null; + access_list: string | null + block_gas_used: number | null // integer + block_hash: string | null + block_number: number | null // integer + chain_id: string | null + gas_price: string | null + logs: ContractResultLog[] + max_fee_per_gas: string | null + max_priority_fee_per_gas: string | null + nonce: number | null // integer + r: string | null + s: string | null + state_changes: ContractResultStateChange[] + transaction_index: number | null // integer + type: number | null // The type of the wrapped ethereum transaction, 0 (Pre-Eip1559) or 2 (Post-Eip1559) + v: number | null } export interface ContractResultLog { - address: string | undefined; - bloom: string | null | undefined; - contract_id: string | null | undefined; - data: string | null | undefined; - index: number | undefined; // integer - topics: string[] | undefined; + address: string | undefined + bloom: string | null | undefined + contract_id: string | null | undefined + data: string | null | undefined + index: number | undefined // integer + topics: string[] | undefined } export interface ContractResultStateChange { - address: string | undefined; - contract_id: string | null | undefined; - slot: string | undefined; - value_read: string | undefined; - value_written: string | null | undefined; + address: string | undefined + contract_id: string | null | undefined + slot: string | undefined + value_read: string | undefined + value_written: string | null | undefined } export interface ContractActionsResponse { - actions: Array | undefined; - links: Links | undefined; + actions: Array | undefined + links: Links | undefined } export interface ContractAction { - call_depth: number | undefined; - call_operation_type: string | undefined; - call_type: string | undefined; - caller: string | null | undefined; // Network entity ID in the format of shard.realm.num - caller_type: string | undefined; // enum EntityType - from: string | undefined; - gas: number | undefined; - gas_used: number | undefined; - index: number | undefined; - input: string | null | undefined; - recipient: string | null | undefined; - recipient_type: string | null | undefined; // enum EntityType - result_data: string | null | undefined; - result_data_type: string | undefined; // enum ResultDataType - timestamp: string | undefined; - to: string | null | undefined; - value: number | undefined; + call_depth: number | undefined, + call_operation_type: string | undefined, + call_type: string | undefined, + caller: string | null | undefined, // Network entity ID in the format of shard.realm.num + caller_type: string | undefined, // enum EntityType + from: string | undefined, + gas: number | undefined, + gas_used: number | undefined, + index: number | undefined, + input: string | null | undefined, + recipient: string | null | undefined, + recipient_type: string | null | undefined, // enum EntityType + result_data: string | null | undefined, + result_data_type: string | undefined, // enum ResultDataType + timestamp: string | undefined, + to: string | null | undefined, + value: number | undefined } export enum EntityType { ACCOUNT = "ACCOUNT", - CONTRACT = "CONTRACT", + CONTRACT = "CONTRACT" } export enum ResultDataType { OUTPUT = "OUTPUT", REVERT_REASON = "REVERT_REASON", - ERROR = "ERROR", + ERROR = "ERROR" } // --------------------------------------------------------------------------------------------------------------------- @@ -627,106 +598,92 @@ export enum ResultDataType { // --------------------------------------------------------------------------------------------------------------------- export interface NetworkNodesResponse { - nodes: NetworkNode[] | undefined; - links: Links | undefined; + nodes: NetworkNode[] | undefined + links: Links | undefined } export interface NetworkNode { - description: string | null | undefined; - file_id: string | null | undefined; // Network entity ID in the format of shard.realm.num - memo: string | undefined; - node_id: number | undefined; - node_account_id: string | null | undefined; // Network entity ID in the format of shard.realm.num - node_cert_hash: string | null | undefined; - public_key: string | null | undefined; // hex encoded X509 RSA public key used to sign stream files - service_endpoints: ServiceEndPoint[] | undefined; - timestamp: TimestampRange | undefined; - max_stake: number | null; // The maximum stake (rewarded or not rewarded) this node can have as consensus weight - min_stake: number | null; // The minimum stake (rewarded or not rewarded) this node must reach before having non-zero consensus weight - stake: number | null; // The node consensus weight at the beginning of the staking period - stake_not_rewarded: number | null; // The sum (balance + stakedToMe) for all accounts staked to this node with declineReward=true at the beginning of the staking period - stake_rewarded: number | null; // The sum (balance + staked) for all accounts staked to the node that are not declining rewards at the beginning of the staking period - staking_period: TimestampRange | null; - reward_rate_start: number | null; + description: string | null | undefined + file_id: string | null | undefined // Network entity ID in the format of shard.realm.num + memo: string | undefined + node_id: number | undefined + node_account_id: string | null | undefined // Network entity ID in the format of shard.realm.num + node_cert_hash: string | null | undefined + public_key: string | null | undefined // hex encoded X509 RSA public key used to sign stream files + service_endpoints: ServiceEndPoint[] | undefined + timestamp: TimestampRange | undefined + max_stake: number | null // The maximum stake (rewarded or not rewarded) this node can have as consensus weight + min_stake: number | null // The minimum stake (rewarded or not rewarded) this node must reach before having non-zero consensus weight + stake: number | null // The node consensus weight at the beginning of the staking period + stake_not_rewarded: number | null // The sum (balance + stakedToMe) for all accounts staked to this node with declineReward=true at the beginning of the staking period + stake_rewarded: number | null // The sum (balance + staked) for all accounts staked to the node that are not declining rewards at the beginning of the staking period + staking_period: TimestampRange | null + reward_rate_start: number | null } export interface ServiceEndPoint { - ip_address_v4: string; - port: number; + ip_address_v4: string + port: number } export function makeShortNodeDescription(description: string): string { - const separator = description.indexOf("|") ?? -1; - return separator !== -1 - ? description.slice(0, separator) ?? null - : description; + const separator = description.indexOf('|') ?? -1 + return (separator !== -1) ? (description.slice(0, separator) ?? null) : description } export function makeNodeSelectorDescription(node: NetworkNode): string { const percentFormatter = new Intl.NumberFormat("en-US", { - style: "percent", - maximumFractionDigits: 1, - }); - const unclampedStakeAmount = - (node.stake_rewarded ?? 0) + (node.stake_not_rewarded ?? 0); - const percentMin = node.min_stake - ? unclampedStakeAmount / node.min_stake - : 0; - const percentMax = node.max_stake - ? (node.stake_rewarded ?? 0) / node.max_stake - : 0; - - let result = - node.node_id + - " - " + - (node.description ?? makeDefaultNodeDescription(node.node_id ?? null)); + style: 'percent', + maximumFractionDigits: 1 + }) + const unclampedStakeAmount = (node.stake_rewarded ?? 0) + (node.stake_not_rewarded ?? 0) + const percentMin = node.min_stake ? unclampedStakeAmount / node.min_stake : 0 + const percentMax = node.max_stake ? (node.stake_rewarded ?? 0) / node.max_stake : 0 + + let result = node.node_id + + ' - ' + + (node.description ?? makeDefaultNodeDescription(node.node_id ?? null)) if (percentMin !== 0 && percentMin < 1) { - result += - " - Not Rewarding (total stake is " + - percentFormatter.format(percentMin) + - " of min)"; + result += " - Not Rewarding (total stake is " + percentFormatter.format(percentMin) + " of min)" } else if (percentMax !== 0) { - result += - " - Rewarding (staked for reward is " + - percentFormatter.format(percentMax) + - " of max)"; + result += " - Rewarding (staked for reward is " + percentFormatter.format(percentMax) + " of max)" } - return result; + return result } // --------------------------------------------------------------------------------------------------------------------- // Network // --------------------------------------------------------------------------------------------------------------------- -export interface NetworkExchangeRateSetResponse { - current_rate: ExchangeRate; - next_rate: ExchangeRate; - timestamp: string; +export interface NetworkExchangeRateSetResponse{ + current_rate: ExchangeRate, + next_rate: ExchangeRate, + timestamp: string } export interface ExchangeRate { - cent_equivalent: number; - expiration_time: number; - hbar_equivalent: number; + cent_equivalent: number, + expiration_time: number, + hbar_equivalent: number } export interface NetworkSupplyResponse { - released_supply: string | undefined; // The network's released supply of hbars in tinybars - timestamp: string | undefined; // The consensus timestamp at which the released supply was valid - total_supply: string | undefined; // The network's total supply of hbars in tinybars + released_supply: string | undefined // The network's released supply of hbars in tinybars + timestamp: string | undefined // The consensus timestamp at which the released supply was valid + total_supply: string | undefined // The network's total supply of hbars in tinybars } -export interface NetworkStake { - max_staking_reward_rate_per_hbar: number; - node_reward_fee_fraction: number; - stake_total: number; - staking_period: TimestampRange; - staking_period_duration: number; - staking_periods_stored: number; - staking_reward_fee_fraction: number; - staking_reward_rate: number; - staking_start_threshold: number; +export interface NetworkStake { + max_staking_reward_rate_per_hbar: number, + node_reward_fee_fraction: number, + stake_total: number, + staking_period: TimestampRange, + staking_period_duration: number, + staking_periods_stored: number, + staking_reward_fee_fraction: number, + staking_reward_rate: number, + staking_start_threshold: number } // --------------------------------------------------------------------------------------------------------------------- @@ -734,26 +691,26 @@ export interface NetworkStake { // --------------------------------------------------------------------------------------------------------------------- export interface BlocksResponse { - blocks: Array | undefined; - links: Links | undefined; + blocks: Array | undefined + links: Links | undefined } export interface Block { - count: number | undefined; // integer - minimum 0 - gas_used: number | null | undefined; // integer - minimum 0 - hapi_version: string | undefined; - hash: string | undefined; - logs_bloom: string | null | undefined; // pattern ^0x[0-9a-fA-F]{512}$ - name: string | undefined; - number: number | undefined; - previous_hash: string | undefined; - size: number | null | undefined; // integer - timestamp: TimestampRange | undefined; + count: number | undefined // integer - minimum 0 + gas_used: number | null | undefined // integer - minimum 0 + hapi_version: string | undefined + hash: string | undefined + logs_bloom: string | null | undefined // pattern ^0x[0-9a-fA-F]{512}$ + name: string | undefined + number: number | undefined + previous_hash: string | undefined + size: number | null | undefined // integer + timestamp: TimestampRange | undefined } export interface TimestampRange { - from: string | undefined; // pattern: ^\d{1,10}(\.\d{1,9})?$ - to: string | null | undefined; // pattern: ^\d{1,10}(\.\d{1,9})?$ + from: string | undefined // pattern: ^\d{1,10}(\.\d{1,9})?$ + to: string | null | undefined // pattern: ^\d{1,10}(\.\d{1,9})?$ } // --------------------------------------------------------------------------------------------------------------------- @@ -761,14 +718,14 @@ export interface TimestampRange { // --------------------------------------------------------------------------------------------------------------------- export interface StakingRewardsResponse { - rewards: Array | undefined; - links: Links | undefined; + rewards: Array | undefined + links: Links | undefined } export interface StakingReward { - account_id: string | null; - amount: number; - timestamp: string; + account_id: string|null + amount: number + timestamp: string } // --------------------------------------------------------------------------------------------------------------------- @@ -776,68 +733,62 @@ export interface StakingReward { // --------------------------------------------------------------------------------------------------------------------- export interface Key { - _type: KeyType | undefined; - key: string | undefined; + _type: KeyType | undefined + key: string | undefined } export enum KeyType { ECDSA_SECP256K1 = "ECDSA_SECP256K1", ED25519 = "ED25519", - ProtobufEncoded = "ProtobufEncoded", + ProtobufEncoded = "ProtobufEncoded" } export interface Links { - next: string | null | undefined; + next: string | null | undefined } -export const infiniteDuration = 31556888202959784; +export const infiniteDuration = 31556888202959784 // --------------------------------------------------------------------------------------------------------------------- // Private // --------------------------------------------------------------------------------------------------------------------- -function compareString( - s1: string | null | undefined, - s2: string | null | undefined, -): number { - let result: number; +function compareString(s1: string|null|undefined, s2: string|null|undefined): number { + let result: number if (s1 && s2) { - result = s1.localeCompare(s2); + result = s1.localeCompare(s2) } else if (s1) { // s2 is null or undefined - result = +1; + result = +1 } else if (s2) { // s1 is null or undefined - result = -1; + result = -1 } else { - result = 0; + result = 0 } - return result; + return result } -function compareNumber( - n1: number | null | undefined, - n2: number | null | undefined, -): number { - let result: number; +function compareNumber(n1: number|null|undefined, n2: number|null|undefined): number { + let result: number if (n1 && n2) { if (n1 < n2) { - result = -1; + result = -1 } else if (n1 > n2) { - result = +1; + result = +1 } else { - result = 0; + result = 0 } } else if (n1) { // n2 is null or undefined - result = +1; + result = +1 } else if (n2) { // n1 is null or undefined - result = -1; + result = -1 } else { - result = 0; + result = 0 } - return result; + return result } diff --git a/src/utils/RouteManager.ts b/src/utils/RouteManager.ts index c0dadb8ef..2aafda40c 100644 --- a/src/utils/RouteManager.ts +++ b/src/utils/RouteManager.ts @@ -268,14 +268,17 @@ export class RouteManager { } public makeRouteToSerial(tokenId: string, serialNumber: number): RouteLocationRaw { - return { name: 'NftDetails', params: { tokenId: tokenId, serialNumber: serialNumber, network: this.currentNetwork.value }} + return { + name: 'NftDetails', + params: {tokenId: tokenId, serialNumber: serialNumber, network: this.currentNetwork.value} + } } public routeToSerial(tokenId: string, serialNumber: number, newTab = false): Promise { let result: Promise if (newTab) { - const routeData = this.router.resolve(this.makeRouteToSerial(tokenId, serialNumber)); - window.open(routeData.href, '_blank'); + const routeData = this.router.resolve(this.makeRouteToSerial(tokenId, serialNumber)) + window.open(routeData.href, '_blank') result = Promise.resolve() } else { result = this.router.push(this.makeRouteToSerial(tokenId, serialNumber)) diff --git a/src/utils/TransactionTools.ts b/src/utils/TransactionTools.ts index 04b933f9b..567682c78 100644 --- a/src/utils/TransactionTools.ts +++ b/src/utils/TransactionTools.ts @@ -18,31 +18,26 @@ * */ -import { - StakingRewardTransfer, - Transaction, - TransactionType, - Transfer, -} from "@/schemas/HederaSchemas"; -import { TransactionID } from "@/utils/TransactionID"; +import {StakingRewardTransfer, Transaction, TransactionType, Transfer} from "@/schemas/HederaSchemas"; +import {TransactionID} from "@/utils/TransactionID"; export function makeSummaryLabel(row: Transaction): string { - let result: string; - let netAmount: number; + let result: string + let netAmount: number switch (row.name) { case TransactionType.CRYPTOTRANSFER: netAmount = computeNetAmount(row.transfers, row.charged_tx_fee); - result = makeTransferLabel(row, netAmount); - break; + result = makeTransferLabel(row, netAmount) + break case TransactionType.CONSENSUSCREATETOPIC: case TransactionType.CONSENSUSDELETETOPIC: case TransactionType.CONSENSUSUPDATETOPIC: - result = row.entity_id ? "Topic ID: " + row.entity_id : ""; - break; + result = row.entity_id ? "Topic ID: " + row.entity_id : "" + break case TransactionType.CONSENSUSSUBMITMESSAGE: - result = formatMemo(row.memo_base64 ?? ""); - break; + result = formatMemo(row.memo_base64 ?? "") + break case TransactionType.CRYPTOCREATEACCOUNT: case TransactionType.CRYPTODELETE: case TransactionType.CRYPTOUPDATEACCOUNT: @@ -54,8 +49,8 @@ export function makeSummaryLabel(row: Transaction): string { case TransactionType.TOKENUNFREEZE: case TransactionType.CRYPTOADDLIVEHASH: case TransactionType.CRYPTODELETELIVEHASH: - result = row.entity_id ? "Account ID: " + row.entity_id : ""; - break; + result = row.entity_id ? "Account ID: " + row.entity_id : "" + break case TransactionType.TOKENBURN: case TransactionType.TOKENMINT: case TransactionType.TOKENCREATION: @@ -65,96 +60,97 @@ export function makeSummaryLabel(row: Transaction): string { case TransactionType.TOKENUNPAUSE: case TransactionType.TOKENUPDATE: case TransactionType.TOKENWIPE: - result = row.entity_id ? "Token ID: " + row.entity_id : ""; - break; + result = row.entity_id ? "Token ID: " + row.entity_id : "" + break case TransactionType.CONTRACTCREATEINSTANCE: case TransactionType.CONTRACTDELETEINSTANCE: case TransactionType.CONTRACTUPDATEINSTANCE: case TransactionType.CONTRACTCALL: - result = row.entity_id ? "Contract ID: " + row.entity_id : ""; - break; + result = row.entity_id ? "Contract ID: " + row.entity_id : "" + break case TransactionType.FILECREATE: case TransactionType.FILEUPDATE: case TransactionType.FILEDELETE: case TransactionType.FILEAPPEND: - result = row.entity_id ? "File ID: " + row.entity_id : ""; - break; + result = row.entity_id ? "File ID: " + row.entity_id : "" + break case TransactionType.SCHEDULECREATE: case TransactionType.SCHEDULEDELETE: case TransactionType.SCHEDULESIGN: - result = row.entity_id ? "Schedule ID: " + row.entity_id : ""; - break; + result = row.entity_id ? "Schedule ID: " + row.entity_id : "" + break case TransactionType.CRYPTOAPPROVEALLOWANCE: case TransactionType.CRYPTODELETEALLOWANCE: - result = formatMemo(row.memo_base64 ?? ""); - break; + result = formatMemo(row.memo_base64 ?? "") + break default: - result = ""; - break; + result = "" + break } - return result; + return result } function makeTransferLabel(row: Transaction, netAmount: number): string { - const TREASURY = "0.0.98"; - let result: string; - let fromAccount = null; - let toAccount = null; - let foundTreasury = false; - let nbFrom = 0; + const TREASURY = "0.0.98" + let result: string + let fromAccount = null + let toAccount = null + let foundTreasury = false + let nbFrom = 0 if (netAmount > 0 && row.transfers !== undefined) { for (const t of row.transfers) { if (t.amount < 0) { - fromAccount = t.account; - nbFrom++; + fromAccount = t.account + nbFrom++ if (Math.abs(t.amount) == netAmount) { - break; + break } } } for (const t of row.transfers) { if (t.amount > 0) { if (t.amount == netAmount) { - toAccount = t.account; - break; + toAccount = t.account + break } else if (t.account == TREASURY) { - foundTreasury = true; + foundTreasury = true } } } if (fromAccount && toAccount) { - result = fromAccount + " \u2192 " + toAccount; + result = fromAccount + " \u2192 " + toAccount } else if (nbFrom == 1 && foundTreasury) { - result = fromAccount + " \u2192 " + TREASURY; + result = fromAccount + " \u2192 " + TREASURY } else { - result = ""; + result = "" } } else { - result = ""; + result = "" } - return result; + return result } export function showPositiveNetAmount(row: Transaction): boolean { - let result: boolean; + let result: boolean - const netAmount = computeNetAmount(row.transfers, row.charged_tx_fee); + const netAmount = computeNetAmount(row.transfers, row.charged_tx_fee) switch (row.name) { case TransactionType.CRYPTOTRANSFER: - result = true; - break; + result = true + break default: - result = netAmount > 0; + result = netAmount > 0 } - return result; + return result } export function makeTypeLabel(type: TransactionType | undefined): string { - let result: string; + let result: string switch (type) { + case TransactionType.CONSENSUSCREATETOPIC: result = "HCS Create Topic"; break; @@ -165,46 +161,46 @@ export function makeTypeLabel(type: TransactionType | undefined): string { result = "HCS Delete Topic"; break; case TransactionType.CONSENSUSSUBMITMESSAGE: - result = "HCS Submit Message"; + result = "HCS Submit Message" break; case TransactionType.CONTRACTCALL: - result = "Contract Call"; + result = "Contract Call" break; case TransactionType.CONTRACTDELETEINSTANCE: - result = "Contract Delete"; + result = "Contract Delete" break; case TransactionType.CONTRACTCREATEINSTANCE: - result = "Contract Create"; + result = "Contract Create" break; case TransactionType.CONTRACTUPDATEINSTANCE: - result = "Contract Update"; + result = "Contract Update" break; case TransactionType.CRYPTOADDLIVEHASH: - result = "Crypto Add Live Hash"; + result = "Crypto Add Live Hash" break; case TransactionType.CRYPTOCREATEACCOUNT: - result = "Crypto Create Account"; + result = "Crypto Create Account" break; case TransactionType.CRYPTODELETE: - result = "Crypto Delete Account"; + result = "Crypto Delete Account" break; case TransactionType.CRYPTOUPDATEACCOUNT: - result = "Crypto Update Account"; + result = "Crypto Update Account" break; case TransactionType.CRYPTODELETELIVEHASH: - result = "Crypto Delete Live Hash"; - break; + result = "Crypto Delete Live Hash" + break case TransactionType.CRYPTOTRANSFER: - result = "Crypto Transfer"; - break; + result = "Crypto Transfer" + break case TransactionType.CRYPTOAPPROVEALLOWANCE: - result = "Crypto Approve Allowance"; - break; + result = "Crypto Approve Allowance" + break case TransactionType.CRYPTODELETEALLOWANCE: - result = "Crypto Delete Allowance"; - break; + result = "Crypto Delete Allowance" + break case TransactionType.FILECREATE: result = "File Create"; @@ -303,22 +299,22 @@ export function makeTypeLabel(type: TransactionType | undefined): string { break; default: - result = type ?? "?"; - break; + result = type ?? "?" + break } - return result.toUpperCase(); + return result.toUpperCase() } export function makeOperatorAccountLabel(transaction: Transaction): string { - let result: string | null; + let result: string | null const transactionId = transaction.transaction_id; if (transactionId != null) { - result = TransactionID.makePayerID(transactionId) ?? "?"; + result = TransactionID.makePayerID(transactionId) ?? "?" } else { - result = "?"; + result = "?" } - return result; + return result } export function isSuccessfulResult(transactionResult: string): boolean { @@ -328,68 +324,62 @@ export function isSuccessfulResult(transactionResult: string): boolean { } function formatMemo(memo64: string): string { - let result: string; + let result: string try { - result = atob(memo64); + result = atob(memo64) } catch { - result = memo64; + result = memo64 } - return result; + return result } -export function computeNetAmount( - transfers: Transfer[] | undefined, - transactionFee: number | undefined, -): number { - let result = 0; +export function computeNetAmount(transfers: Transfer[] | undefined, transactionFee: number | undefined): number { + let result = 0 if (transfers !== undefined) { for (const t of transfers) { if (t.amount > 0) { - result += t.amount; + result += t.amount } } } - result -= transactionFee ?? 0; - return result; + result -= transactionFee ?? 0 + return result } -export function makeNetOfRewards( - transfers: Transfer[] | undefined, - rewards: StakingRewardTransfer[] | undefined, -): Transfer[] { - let result = Array(); - let totalRewardAmount = 0; +export function makeNetOfRewards(transfers: Transfer[] | undefined, rewards: StakingRewardTransfer[] | undefined): Transfer[] { + let result = Array() + let totalRewardAmount = 0 if (transfers && rewards && transfers.length > 0 && rewards.length > 0) { for (const r of rewards) { - totalRewardAmount += r.amount; + totalRewardAmount += r.amount } - let netAmount: number; + let netAmount: number for (const t of transfers) { if (t.account === "0.0.800") { - netAmount = t.amount + totalRewardAmount; + netAmount = t.amount + totalRewardAmount } else { - netAmount = t.amount; + netAmount = t.amount for (const r of rewards) { if (t.account == r.account) { if (t.amount < 0) { - netAmount = t.amount + r.amount; + netAmount = t.amount + r.amount } else { - netAmount = t.amount - r.amount; + netAmount = t.amount - r.amount } - break; + break } } } result.push({ amount: netAmount, account: t.account, - is_approval: t.is_approval, - }); + is_approval: t.is_approval + }) } } else { - result = transfers ?? []; + result = transfers ?? [] } - return result; + return result } diff --git a/src/utils/cache/NftByAccountCache.ts b/src/utils/cache/NftByAccountCache.ts new file mode 100644 index 000000000..1240183a7 --- /dev/null +++ b/src/utils/cache/NftByAccountCache.ts @@ -0,0 +1,50 @@ +/*- + * + * Hedera Mirror Node Explorer + * + * Copyright (C) 2021 - 2022 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { Nft, Nfts } from "@/schemas/HederaSchemas"; +import axios from "axios" +import {SerialCache} from "./base/SerialCache" +import {Ref, ref} from "vue" +import {Lookup} from "./base/EntityCache" + +export class NftByAccountCache extends SerialCache { + public static readonly instance = new NftByAccountCache() + + // + // Cache + // + + protected async load(accountId: string): Promise { + let result: Promise + try { + const response = await axios.get( + `api/v1/accounts/${accountId}/nfts`, + ) + result = Promise.resolve(response.data) + } catch (error) { + if (axios.isAxiosError(error) && error.response?.status == 404) { + result = Promise.resolve(null) + } else { + throw error + } + } + return result + } +}
- Recent Transactions -
+ Recent Transactions +