Skip to content

Commit

Permalink
Merge branch 'develop' into tooling-explorer/add-computation-cost-burned
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 authored Feb 28, 2025
2 parents 09f6cfb + ce71d01 commit 3a1cdda
Show file tree
Hide file tree
Showing 16 changed files with 381 additions and 123 deletions.
2 changes: 1 addition & 1 deletion apps/apps-backend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"paths": {
"@iota/core/enums/*": ["./../core/src/enums/*"],
"@iota/core/enums/*": ["./../core/src/enums/*"]
}
}
}
4 changes: 4 additions & 0 deletions apps/explorer/src/lib/constants/evm.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export const EVM_ADDRESS_LENGTH = 44;
3 changes: 3 additions & 0 deletions apps/explorer/src/lib/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export * from './validator.types';
3 changes: 3 additions & 0 deletions apps/explorer/src/lib/types/validator.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { type IotaValidatorSummary } from '@iota/iota-sdk/client';

export type IotaValidatorSummaryExtended = IotaValidatorSummary & { isPending?: boolean };
11 changes: 0 additions & 11 deletions apps/explorer/src/lib/ui/utils/generateValidatorsTableColumns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,6 @@ export function generateValidatorsTableColumns({
highlightValidatorName,
}: generateValidatorsTableColumnsArgs): ColumnDef<IotaValidatorSummaryExtended>[] {
let columns: ColumnDef<IotaValidatorSummaryExtended>[] = [
{
header: '#',
id: 'number',
cell({ row }) {
return (
<TableCellBase>
<TableCellText>{row.index + 1}</TableCellText>
</TableCellBase>
);
},
},
{
header: 'Name',
id: 'name',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

import { KeyValueInfo, TitleSize } from '@iota/apps-ui-kit';
import { type IotaCallArg } from '@iota/iota-sdk/client';
import { toHEX } from '@iota/iota-sdk/utils';
import { isValidIotaAddress, toHEX } from '@iota/iota-sdk/utils';
import { ProgrammableTxnBlockCard, AddressLink, ObjectLink, CollapsibleCard } from '~/components';
import { useBreakpoint } from '~/hooks';
import { EVM_ADDRESS_LENGTH } from '~/lib/constants/evm.constants';

const REGEX_NUMBER = /^\d+$/;

Expand Down Expand Up @@ -71,10 +72,22 @@ export function InputsCard({ inputs }: InputsCardProps): JSX.Element | null {
// Silent error
}

let parsedAddress: string | null = null;
try {
if (parsedVector) {
const hex = toHEX(new Uint8Array(parsedVector));
if (hex.length == EVM_ADDRESS_LENGTH || isValidIotaAddress(hex)) {
parsedAddress = hex;
}
}
} catch (_) {
// Silent error
}

if (parsedUtf) {
renderValue = parsedUtf;
} else if (parsedVector) {
renderValue = toHEX(new Uint8Array(parsedVector));
} else if (parsedAddress) {
renderValue = parsedAddress;
} else {
renderValue = stringValue;
}
Expand Down
40 changes: 31 additions & 9 deletions apps/explorer/src/pages/validators/Validators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import { type JSX, useMemo } from 'react';
import {
roundFloat,
useFormatCoin,
formatPercentageDisplay,
useGetDynamicFields,
useGetValidatorsApy,
useGetValidatorsEvents,
useMultiGetObjects,
} from '@iota/core';
import {
Badge,
BadgeType,
DisplayStats,
DisplayStatsSize,
DisplayStatsType,
Expand All @@ -29,7 +32,7 @@ import { Warning } from '@iota/apps-ui-icons';
import { useQuery } from '@tanstack/react-query';
import { useEnhancedRpcClient } from '~/hooks';
import { sanitizePendingValidators } from '~/lib';
import { normalizeIotaAddress } from '@iota/iota-sdk/utils';
import { IOTA_TYPE_ARG, normalizeIotaAddress } from '@iota/iota-sdk/utils';

function ValidatorPageResult(): JSX.Element {
const { data, isPending, isSuccess, isError } = useIotaClientQuery('getLatestIotaSystemState');
Expand Down Expand Up @@ -60,6 +63,9 @@ function ValidatorPageResult(): JSX.Element {
const sanitizePendingValidatorsData = sanitizePendingValidators(pendingValidatorsData);

const { data: validatorsApy } = useGetValidatorsApy();
const { data: totalSupplyData } = useIotaClientQuery('getTotalSupply', {
coinType: IOTA_TYPE_ARG,
});

const totalStaked = useMemo(() => {
if (!data) return 0;
Expand Down Expand Up @@ -105,12 +111,19 @@ function ValidatorPageResult(): JSX.Element {
const lastEpochRewardOnAllValidators =
epochData?.data[0].endOfEpochInfo?.totalStakeRewardsDistributed;

const sortedValidators = activeValidatorsData?.sort(() => 0.5 - Math.random());
const stakingRatio = (() => {
let ratio = null;
if (totalSupplyData?.value && totalStaked) {
const totalSupplyValue = Number(totalSupplyData.value);
ratio = Number(((totalStaked / totalSupplyValue) * 100).toFixed(2));
}
return formatPercentageDisplay(ratio);
})();

const tableData = data
? Number(data.pendingActiveValidatorsSize) > 0
? sortedValidators?.concat(sanitizePendingValidatorsData)
: sortedValidators
? activeValidatorsData?.concat(sanitizePendingValidatorsData)
: activeValidatorsData
: [];

const tableColumns = useMemo(() => {
Expand All @@ -121,7 +134,6 @@ function ValidatorPageResult(): JSX.Element {
rollingAverageApys: validatorsApy || null,
highlightValidatorName: true,
includeColumns: [
'#',
'Name',
'Stake',
'Proposed next Epoch gas price',
Expand All @@ -147,9 +159,9 @@ function ValidatorPageResult(): JSX.Element {
'The combined IOTA staked by validators and delegators on the network to support validation and generate rewards.',
},
{
title: 'Participation',
value: '--',
tooltipText: 'Coming soon',
title: 'Staking Ratio',
value: stakingRatio,
tooltipText: 'The ratio of the total staked IOTA to the total supply of IOTA.',
},
{
title: 'Last Epoch Rewards',
Expand Down Expand Up @@ -196,7 +208,17 @@ function ValidatorPageResult(): JSX.Element {
))}
</div>
<Panel>
<Title title="All Validators" />
<Title
title="All Validators"
supportingElement={
<span className="ml-1">
<Badge
type={BadgeType.PrimarySoft}
label={sortedValidators?.length.toString()}
/>
</span>
}
/>
<div className="p-md">
<ErrorBoundary>
{(isPending || validatorsEventsLoading) && (
Expand Down
113 changes: 113 additions & 0 deletions crates/iota-graphql-e2e-tests/tests/objects/wrap_unwrap.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
processed 14 tasks

init:
A: object(0,0)

task 1, lines 6-30:
//# publish
created: object(1,0)
mutated: object(0,1)
gas summary: computation_cost: 1000000, computation_cost_burned: 1000000, storage_cost: 5624000, storage_rebate: 0, non_refundable_storage_fee: 0

task 2, lines 32-34:
//# programmable --sender A --inputs @A
//> 0: P0::m::foo();
//> TransferObjects([Result(0)], Input(0))
created: object(2,0)
mutated: object(0,0)
gas summary: computation_cost: 1000000, computation_cost_burned: 1000000, storage_cost: 2196400, storage_rebate: 0, non_refundable_storage_fee: 0

task 3, lines 36-38:
//# programmable --sender A --inputs @A object(2,0)
//> 0: P0::m::from_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))
created: object(3,0)
mutated: object(0,0)
wrapped: object(2,0)
gas summary: computation_cost: 1000000, computation_cost_burned: 1000000, storage_cost: 2439600, storage_rebate: 2196400, non_refundable_storage_fee: 0

task 4, lines 40-42:
//# programmable --sender A --inputs @A object(3,0)
//> 0: P0::m::into_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))
mutated: object(0,0)
unwrapped: object(2,0)
deleted: object(3,0)
gas summary: computation_cost: 1000000, computation_cost_burned: 1000000, storage_cost: 2196400, storage_rebate: 2439600, non_refundable_storage_fee: 0

task 5, line 44:
//# create-checkpoint
Checkpoint created: 1

task 6, lines 46-54:
//# run-graphql
Response: {
"data": {
"object1": {
"digest": "kfqgxZwi4o2rX6KEbFLC9v2vzyt3oBAjTVGrZ4C4h9v"
},
"object2": {
"digest": null
}
}
}

task 7, lines 56-58:
//# programmable --sender A --inputs @A
//> 0: P0::m::foo();
//> TransferObjects([Result(0)], Input(0))
created: object(7,0)
mutated: object(0,0)
gas summary: computation_cost: 1000000, computation_cost_burned: 1000000, storage_cost: 2196400, storage_rebate: 980400, non_refundable_storage_fee: 0

task 8, lines 60-62:
//# programmable --sender A --inputs @A object(7,0)
//> 0: P0::m::from_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))
created: object(8,0)
mutated: object(0,0)
wrapped: object(7,0)
gas summary: computation_cost: 1000000, computation_cost_burned: 1000000, storage_cost: 2439600, storage_rebate: 2196400, non_refundable_storage_fee: 0

task 9, line 64:
//# create-checkpoint
Checkpoint created: 2

task 10, lines 66-74:
//# run-graphql
Response: {
"data": {
"object1": {
"digest": null
},
"object2": {
"digest": "d27G5A3VoWJfmErshZcy4evrzjBzjAT8cwYzpztVhLw"
}
}
}

task 11, lines 76-78:
//# programmable --sender A --inputs @A object(8,0)
//> 0: P0::m::into_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))
mutated: object(0,0)
unwrapped: object(7,0)
deleted: object(8,0)
gas summary: computation_cost: 1000000, computation_cost_burned: 1000000, storage_cost: 2196400, storage_rebate: 2439600, non_refundable_storage_fee: 0

task 12, line 80:
//# create-checkpoint
Checkpoint created: 3

task 13, lines 82-90:
//# run-graphql
Response: {
"data": {
"object1": {
"digest": "5JRDDVvrZJ1xrPmSA9ML1KgxCsgRJUSt87gDoob2V7aU"
},
"object2": {
"digest": null
}
}
}
91 changes: 91 additions & 0 deletions crates/iota-graphql-e2e-tests/tests/objects/wrap_unwrap.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) Mysten Labs, Inc.
// Modifications Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

//# init --protocol-version 3 --addresses P0=0x0 --accounts A --simulator

//# publish
module P0::m {
public struct Foo has key, store {
id: UID,
}

public struct Bar has key, store {
id: UID,
foo: Foo,
}

public fun foo(ctx: &mut TxContext): Foo {
Foo { id: object::new(ctx) }
}

public fun from_foo(foo: Foo, ctx: &mut TxContext): Bar {
Bar { id: object::new(ctx), foo }
}

public fun into_foo(bar: Bar): Foo {
let Bar { id, foo } = bar;
object::delete(id);
foo
}
}

//# programmable --sender A --inputs @A
//> 0: P0::m::foo();
//> TransferObjects([Result(0)], Input(0))

//# programmable --sender A --inputs @A object(2,0)
//> 0: P0::m::from_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))

//# programmable --sender A --inputs @A object(3,0)
//> 0: P0::m::into_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))

//# create-checkpoint

//# run-graphql
{
object1: object(address: "@{obj_2_0}") {
digest
}
object2: object(address: "@{obj_3_0}") {
digest
}
}

//# programmable --sender A --inputs @A
//> 0: P0::m::foo();
//> TransferObjects([Result(0)], Input(0))

//# programmable --sender A --inputs @A object(7,0)
//> 0: P0::m::from_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))

//# create-checkpoint

//# run-graphql
{
object1: object(address: "@{obj_7_0}") {
digest
}
object2: object(address: "@{obj_8_0}") {
digest
}
}

//# programmable --sender A --inputs @A object(8,0)
//> 0: P0::m::into_foo(Input(1));
//> TransferObjects([Result(0)], Input(0))

//# create-checkpoint

//# run-graphql
{
object1: object(address: "@{obj_7_0}") {
digest
}
object2: object(address: "@{obj_8_0}") {
digest
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
DROP VIEW IF EXISTS network_metrics CASCADE;
DROP VIEW IF EXISTS real_time_tps CASCADE;
DROP TABLE IF EXISTS epoch_peak_tps;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP VIEW IF EXISTS network_metrics CASCADE;
Loading

0 comments on commit 3a1cdda

Please sign in to comment.