Skip to content

Commit

Permalink
Merge branch 'develop' into devx/fix-ctf-css
Browse files Browse the repository at this point in the history
  • Loading branch information
vivekjain23 authored Nov 26, 2024
2 parents 3f0f5a1 + 3742d78 commit 9c65520
Show file tree
Hide file tree
Showing 111 changed files with 1,362 additions and 545 deletions.
5 changes: 0 additions & 5 deletions .github/workflows/_rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@ on:
inputs:
isRust:
type: boolean
secrets:
SSH_PRIVATE_KEY_IOTA_CI:
required: true
SSH_GITHUB_KNOWN_HOSTS:
required: true

env:
CARGO_TERM_COLOR: always
Expand Down
10 changes: 6 additions & 4 deletions apps/core/src/components/Inputs/SendTokenFormInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface SendTokenInputProps {
onActionClick: () => Promise<void>;
isMaxActionDisabled?: boolean;
name: string;
isPayAllIota: boolean;
}

export function SendTokenFormInput({
Expand All @@ -30,6 +31,7 @@ export function SendTokenFormInput({
onActionClick,
isMaxActionDisabled,
name,
isPayAllIota,
}: SendTokenInputProps) {
const { values, setFieldValue, isSubmitting, validateField } = useFormikContext<TokenForm>();
const { data: gasBudgetEstimation } = useGasBudgetEstimation({
Expand All @@ -38,7 +40,7 @@ export function SendTokenFormInput({
activeAddress,
to: to,
amount: values.amount,
isPayAllIota: values.isPayAllIota,
isPayAllIota,
});
const [formattedGasBudgetEstimation, gasToken] = useFormatCoin(
gasBudgetEstimation,
Expand All @@ -61,8 +63,8 @@ export function SendTokenFormInput({

// gasBudgetEstimation should change when the amount above changes
useEffect(() => {
setFieldValue('gasBudgetEst', formattedGasBudgetEstimation, false);
}, [formattedGasBudgetEstimation, setFieldValue, values.amount]);
setFieldValue('gasBudgetEst', gasBudgetEstimation, false);
}, [gasBudgetEstimation, setFieldValue, values.amount]);

return (
<Input
Expand All @@ -74,7 +76,7 @@ export function SendTokenFormInput({
placeholder="0.00"
label="Send Amount"
suffix={` ${symbol}`}
prefix={values.isPayAllIota ? '~ ' : undefined}
prefix={isPayAllIota ? '~ ' : undefined}
allowNegative={false}
errorMessage={errorMessage}
amountCounter={!errorMessage ? (coins ? gasAmount : '--') : undefined}
Expand Down
7 changes: 3 additions & 4 deletions apps/core/src/components/coin/CoinIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
// SPDX-License-Identifier: Apache-2.0

import React from 'react';
import { useCoinMetadata } from '../../hooks';
import { useCoinMetadata, ImageIcon, ImageIconSize } from '../../';
import { IotaLogoMark } from '@iota/ui-icons';
import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
import { ImageIcon, ImageIconSize } from '../icon';
import cx from 'clsx';

interface NonIotaCoinProps {
Expand All @@ -18,7 +17,7 @@ interface NonIotaCoinProps {
function NonIotaCoin({ coinType, size = ImageIconSize.Full, rounded }: NonIotaCoinProps) {
const { data: coinMeta } = useCoinMetadata(coinType);
return (
<div className="flex h-full w-full items-center justify-center rounded-full bg-neutral-96 dark:bg-neutral-92">
<div className="flex h-full w-full items-center justify-center rounded-full bg-neutral-96 dark:bg-neutral-12">
<ImageIcon
src={coinMeta?.iconUrl}
label={coinMeta?.name || coinType}
Expand Down Expand Up @@ -47,7 +46,7 @@ export function CoinIcon({

return coinType === IOTA_TYPE_ARG ? (
<Component {...coinWrapperProps}>
<div className={cx(size, 'text-neutral-10')}>
<div className={cx(size, 'text-neutral-10 dark:text-neutral-92')}>
<IotaLogoMark className="h-full w-full" />
</div>
</Component>
Expand Down
9 changes: 2 additions & 7 deletions apps/core/src/components/coin/CoinItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,8 @@ export function CoinItem({
return (
<Card type={CardType.Default} onClick={onClick}>
<CardImage type={ImageType.BgTransparent}>
<div className="flex h-10 w-10 items-center justify-center rounded-full">
<CoinIcon
coinType={coinType}
rounded
size={ImageIconSize.Small}
hasCoinWrapper
/>
<div className="flex h-10 w-10 items-center justify-center rounded-full border border-shader-neutral-light-8 text-neutral-10 dark:text-neutral-92">
<CoinIcon coinType={coinType} rounded size={ImageIconSize.Small} />
</div>
</CardImage>
<CardBody
Expand Down
2 changes: 1 addition & 1 deletion apps/core/src/components/coin/CoinSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function CoinSelectOption({
hasCoinWrapper={hasCoinWrapper}
/>
</div>
<span className="text-body-lg text-neutral-10">
<span className="text-body-lg text-neutral-10 dark:text-neutral-92">
{isIota ? (coinMeta?.name || '').toUpperCase() : coinMeta?.name || symbol}
</span>
</div>
Expand Down
5 changes: 2 additions & 3 deletions apps/core/src/components/icon/ImageIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ function FallBackAvatar({ str, rounded, size = ImageIconSize.Large }: FallBackAv
return (
<div
className={cn(
'flex items-center justify-center bg-neutral-96 bg-gradient-to-r capitalize text-neutral-10 dark:bg-neutral-92 dark:text-primary-100',
{ 'rounded-full': rounded, 'rounded-lg': !rounded },
size,
'flex h-full w-full items-center justify-center bg-neutral-96 bg-gradient-to-r capitalize text-neutral-10 dark:bg-neutral-12 dark:text-neutral-92',
{ 'rounded-full': rounded },
generateTextSize(size),
)}
>
Expand Down
4 changes: 2 additions & 2 deletions apps/core/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export * from './KioskClientProvider';

export * from './coin';
export * from './icon';
export * from './Inputs';
export * from './QR';

export * from './providers';
51 changes: 51 additions & 0 deletions apps/core/src/components/providers/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { PropsWithChildren, useState, useEffect, useCallback } from 'react';
import { Theme } from '../../enums';
import { ThemeContext } from '../../contexts';

interface ThemeProviderProps {
appId: string;
}

export function ThemeProvider({ children, appId }: PropsWithChildren<ThemeProviderProps>) {
const storageKey = `theme_${appId}`;

const getSystemTheme = () =>
window.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.Dark : Theme.Light;

const getInitialTheme = () => {
if (typeof window === 'undefined') {
return Theme.System;
} else {
const storedTheme = localStorage?.getItem(storageKey);
return storedTheme ? (storedTheme as Theme) : Theme.System;
}
};

const [theme, setTheme] = useState<Theme>(getInitialTheme);

const applyTheme = useCallback((currentTheme: Theme) => {
const selectedTheme = currentTheme === Theme.System ? getSystemTheme() : currentTheme;
const documentElement = document.documentElement.classList;
documentElement.toggle(Theme.Dark, selectedTheme === Theme.Dark);
documentElement.toggle(Theme.Light, selectedTheme === Theme.Light);
}, []);

useEffect(() => {
if (typeof window === 'undefined') return;

localStorage.setItem(storageKey, theme);
applyTheme(theme);

if (theme === Theme.System) {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)');
const handleSystemThemeChange = () => applyTheme(Theme.System);
systemTheme.addEventListener('change', handleSystemThemeChange);
return () => systemTheme.removeEventListener('change', handleSystemThemeChange);
}
}, [theme, applyTheme, storageKey]);

return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export * from './StakeDetailsDialog';
export * from './KioskClientProvider';
export * from './ThemeProvider';
3 changes: 3 additions & 0 deletions apps/core/src/constants/staking.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ export const UNSTAKING_REQUEST_EVENT = '0x3::validator::UnstakingRequestEvent';

export const DELEGATED_STAKES_QUERY_STALE_TIME = 10_000;
export const DELEGATED_STAKES_QUERY_REFETCH_INTERVAL = 30_000;

export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE = 2;
export const NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS = 1;
15 changes: 15 additions & 0 deletions apps/core/src/contexts/ThemeContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { createContext } from 'react';
import { Theme } from '../enums';

export interface ThemeContextType {
theme: Theme;
setTheme: (theme: Theme) => void;
}

export const ThemeContext = createContext<ThemeContextType>({
theme: Theme.Light,
setTheme: () => {},
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export * from './views';
export * from './ThemeContext';
File renamed without changes.
3 changes: 2 additions & 1 deletion apps/core/src/enums/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export * from './ExplorerLinkType';
export * from './theme.enums';
export * from './explorer-link-type.enums';
8 changes: 8 additions & 0 deletions apps/core/src/enums/theme.enums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export enum Theme {
Light = 'light',
Dark = 'dark',
System = 'system',
}
1 change: 0 additions & 1 deletion apps/core/src/forms/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@
export type TokenForm = {
amount: string;
to: string;
isPayAllIota: boolean;
gasBudgetEst: string;
};
1 change: 1 addition & 0 deletions apps/core/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ export * from './useGasBudgetEstimation';
export * from './useTransactionData';
export * from './useGetStakingValidatorDetails';
export * from './useCursorPagination';
export * from './useTheme';

export * from './stake';
2 changes: 2 additions & 0 deletions apps/core/src/hooks/stake/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
export * from './useGetDelegatedStake';
export * from './useTotalDelegatedRewards';
export * from './useTotalDelegatedStake';
export * from './useValidatorInfo';
export * from './useStakeTxnInfo';
52 changes: 52 additions & 0 deletions apps/core/src/hooks/stake/useStakeTxnInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import {
useGetTimeBeforeEpochNumber,
useTimeAgo,
TimeUnit,
NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE,
NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS,
} from '../../';

export function useStakeTxnInfo(startEpoch?: string | number) {
const startEarningRewardsEpoch =
Number(startEpoch || 0) + NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_STARTS;

const redeemableRewardsEpoch =
Number(startEpoch || 0) + NUM_OF_EPOCH_BEFORE_STAKING_REWARDS_REDEEMABLE;

const { data: timeBeforeStakeRewardsStarts } =
useGetTimeBeforeEpochNumber(startEarningRewardsEpoch);
const timeBeforeStakeRewardsStartsAgo = useTimeAgo({
timeFrom: timeBeforeStakeRewardsStarts,
shortedTimeLabel: false,
shouldEnd: true,
maxTimeUnit: TimeUnit.ONE_HOUR,
});
const stakedRewardsStartEpoch =
timeBeforeStakeRewardsStarts > 0
? `in ${timeBeforeStakeRewardsStartsAgo}`
: startEpoch
? `Epoch #${Number(startEarningRewardsEpoch)}`
: '--';

const { data: timeBeforeStakeRewardsRedeemable } =
useGetTimeBeforeEpochNumber(redeemableRewardsEpoch);
const timeBeforeStakeRewardsRedeemableAgo = useTimeAgo({
timeFrom: timeBeforeStakeRewardsRedeemable,
shortedTimeLabel: false,
shouldEnd: true,
maxTimeUnit: TimeUnit.ONE_HOUR,
});
const timeBeforeStakeRewardsRedeemableAgoDisplay =
timeBeforeStakeRewardsRedeemable > 0
? `in ${timeBeforeStakeRewardsRedeemableAgo}`
: startEpoch
? `Epoch #${Number(redeemableRewardsEpoch)}`
: '--';

return {
stakedRewardsStartEpoch,
timeBeforeStakeRewardsRedeemableAgoDisplay,
};
}
50 changes: 50 additions & 0 deletions apps/core/src/hooks/stake/useValidatorInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import { useIotaClientQuery } from '@iota/dapp-kit';
import { useGetValidatorsApy } from '../';

export function useValidatorInfo({ validatorAddress }: { validatorAddress: string }) {
const {
data: system,
isPending: isPendingValidators,
isError: errorValidators,
} = useIotaClientQuery('getLatestIotaSystemState');
const { data: rollingAverageApys } = useGetValidatorsApy();

const validatorSummary =
system?.activeValidators.find((validator) => validator.iotaAddress === validatorAddress) ||
null;

const currentEpoch = Number(system?.epoch || 0);

const stakingPoolActivationEpoch = Number(validatorSummary?.stakingPoolActivationEpoch || 0);

// flag as new validator if the validator was activated in the last epoch
// for genesis validators, this will be false
const newValidator = currentEpoch - stakingPoolActivationEpoch <= 1 && currentEpoch !== 0;

// flag if the validator is at risk of being removed from the active set
const isAtRisk = system?.atRiskValidators.some((item) => item[0] === validatorAddress);

const { apy, isApyApproxZero } = rollingAverageApys?.[validatorAddress] ?? {
apy: null,
};

const commission = validatorSummary ? Number(validatorSummary.commissionRate) / 100 : 0;

return {
system,
isPendingValidators,
errorValidators,

currentEpoch,
validatorSummary,
name: validatorSummary?.name || '',
stakingPoolActivationEpoch,
commission,
newValidator,
isAtRisk,
apy,
isApyApproxZero,
};
}
1 change: 1 addition & 0 deletions apps/core/src/hooks/useGetStakingValidatorDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export function useGetStakingValidatorDetails({
return {
epoch: Number(system?.epoch) || 0,
totalStake: totalStakeFormatted,
totalStakeOriginal: totalStake,
totalValidatorsStake: totalValidatorsStakeFormatted,
totalStakePercentage,
validatorApy,
Expand Down
12 changes: 12 additions & 0 deletions apps/core/src/hooks/useTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import { useContext } from 'react';
import { ThemeContext, ThemeContextType } from '../contexts';

export const useTheme = (): ThemeContextType => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
2 changes: 2 additions & 0 deletions apps/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ export * from './components';
export * from './utils';
export * from './hooks';
export * from './constants';
export * from './contexts';
export * from './enums';
export * from './forms';
Loading

0 comments on commit 9c65520

Please sign in to comment.