Compare commits

..
111 changed files with 1002 additions and 1376 deletions
@@ -3,6 +3,7 @@ import {
StakingBridge,
Token,
TokenVesting,
TokenFaucetable,
CollateralBridge,
} from '@vegaprotocol/smart-contracts';
import { ethers, Wallet } from 'ethers';
@@ -40,7 +41,7 @@ export async function depositAsset(
decimalPlaces: number
) {
// Approve asset
const faucet = new Token(assetEthAddress, signer);
const faucet = new TokenFaucetable(assetEthAddress, signer);
cy.wrap(
faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)),
{
@@ -61,7 +62,7 @@ export async function depositAsset(
}
export async function faucetAsset(assetEthAddress: string) {
const faucet = new Token(assetEthAddress, signer);
const faucet = new TokenFaucetable(assetEthAddress, signer);
await promiseWithTimeout(faucet.faucet(), 10 * 60 * 1000, 'faucet asset');
}
@@ -1,14 +1,23 @@
import { Button } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next';
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
import {
AppStateActionType,
useAppState,
} from '../../contexts/app-state/app-state-context';
export const EthConnectPrompt = () => {
const { t } = useTranslation();
const { open } = useWeb3ConnectStore();
const { appDispatch } = useAppState();
return (
<Button
variant="default"
onClick={open}
onClick={() =>
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
fill={true}
data-testid="connect-to-eth-btn"
>
@@ -2,7 +2,10 @@ import { Button } from '@vegaprotocol/ui-toolkit';
import { useWeb3React } from '@web3-react/core';
import type { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
import {
AppStateActionType,
useAppState,
} from '../../contexts/app-state/app-state-context';
export const EthWalletContainer = ({
children,
@@ -11,12 +14,21 @@ export const EthWalletContainer = ({
}) => {
const { account } = useWeb3React();
const { t } = useTranslation();
const { open } = useWeb3ConnectStore();
const { appDispatch } = useAppState();
if (!account) {
return (
<div className="w-full text-center">
<Button onClick={open}>{t('connectEthWallet')}</Button>
<Button
onClick={() =>
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
>
{t('connectEthWallet')}
</Button>
</div>
);
}
@@ -27,11 +27,7 @@ import {
import { Loader } from '@vegaprotocol/ui-toolkit';
import colors from 'tailwindcss/colors';
import { useBalances } from '../../lib/balances/balances-store';
import {
useEthereumConfig,
useWeb3ConnectStore,
useWeb3Disconnect,
} from '@vegaprotocol/web3';
import { useEthereumConfig, useWeb3Disconnect } from '@vegaprotocol/web3';
import { getChainName } from '@vegaprotocol/web3';
const removeLeadingAddressSymbol = (key: string) => {
@@ -193,7 +189,6 @@ export const EthWallet = () => {
const pendingTxs = usePendingTransactions();
const disconnect = useWeb3Disconnect(connector);
const { config } = useEthereumConfig();
const { open } = useWeb3ConnectStore();
return (
<WalletCard>
@@ -238,7 +233,12 @@ export const EthWallet = () => {
) : (
<Button
fill={true}
onClick={open}
onClick={() =>
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
data-testid="connect-to-eth-wallet-button"
>
{t('connectEthWalletToAssociate')}
@@ -25,26 +25,20 @@ export function Web3Connector({
connectors,
chainId,
}: Web3ConnectorProps) {
const { open, close, isOpen } = useWeb3ConnectStore();
const { appState, appDispatch } = useAppState();
const setDialogOpen = useCallback(
(isOpen: boolean) => {
if (isOpen) {
open();
} else {
close();
}
appDispatch({ type: AppStateActionType.SET_ETH_WALLET_OVERLAY, isOpen });
},
[open, close]
[appDispatch]
);
const appChainId = Number(chainId);
return (
<>
<Web3Content appChainId={appChainId}>{children}</Web3Content>
<Web3ConnectDialog
connectors={connectors}
dialogOpen={isOpen}
dialogOpen={appState.ethConnectOverlay}
setDialogOpen={setDialogOpen}
desiredChainId={appChainId}
/>
@@ -34,6 +34,9 @@ export interface AppState {
/** Whether or not the manage VEGA wallet overlay is open */
vegaWalletManageOverlay: boolean;
/** Whether or not the connect to Ethereum wallet overlay is open */
ethConnectOverlay: boolean;
/** Whether or not the transaction modal is open */
transactionOverlay: boolean;
/**
@@ -54,6 +57,7 @@ export enum AppStateActionType {
REFRESH_BALANCES,
SET_VEGA_WALLET_OVERLAY,
SET_VEGA_WALLET_MANAGE_OVERLAY,
SET_ETH_WALLET_OVERLAY,
SET_DRAWER,
REFRESH_ASSOCIATED_BALANCES,
SET_ASSOCIATION_BREAKDOWN,
@@ -77,6 +81,10 @@ export type AppStateAction =
type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY;
isOpen: boolean;
}
| {
type: AppStateActionType.SET_ETH_WALLET_OVERLAY;
isOpen: boolean;
}
| {
type: AppStateActionType.SET_DRAWER;
isOpen: boolean;
@@ -16,6 +16,7 @@ const initialAppState: AppState = {
totalSupply: new BigNumber(0),
vegaWalletOverlay: false,
vegaWalletManageOverlay: false,
ethConnectOverlay: false,
transactionOverlay: false,
bannerMessage: '',
disconnectNotice: false,
@@ -44,6 +45,12 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState {
vegaWalletOverlay: action.isOpen ? false : state.vegaWalletOverlay,
};
}
case AppStateActionType.SET_ETH_WALLET_OVERLAY: {
return {
...state,
ethConnectOverlay: action.isOpen,
};
}
case AppStateActionType.SET_DRAWER: {
return {
...state,
@@ -53,6 +53,7 @@ const mockAppState: AppState = {
totalSupply: new BigNumber(65000000),
vegaWalletOverlay: false,
vegaWalletManageOverlay: false,
ethConnectOverlay: false,
transactionOverlay: false,
bannerMessage: '',
disconnectNotice: false,
@@ -16,6 +16,7 @@ const mockAppState: AppState = {
totalSupply: mockTotalSupply,
vegaWalletOverlay: false,
vegaWalletManageOverlay: false,
ethConnectOverlay: false,
transactionOverlay: false,
bannerMessage: '',
disconnectNotice: false,
@@ -79,24 +79,7 @@ export const generateEpochIndividualRewardsList = ({
epoch?.rewards.push(asset);
}
if (!asset.rewardTypes[rewardType]) {
asset.rewardTypes[rewardType] = { amount, percentageOfTotal };
} else {
const previousAmount = asset.rewardTypes[rewardType]?.amount;
const previousPercentageOfTotal =
asset.rewardTypes[rewardType]?.percentageOfTotal;
asset.rewardTypes[rewardType] = {
amount: previousAmount
? new BigNumber(previousAmount).plus(amount).toString()
: amount,
percentageOfTotal: previousPercentageOfTotal
? new BigNumber(previousPercentageOfTotal)
.plus(percentageOfTotal)
.toString()
: percentageOfTotal,
};
}
asset.rewardTypes[rewardType] = { amount, percentageOfTotal };
// totalAmount is the sum of all rewardTypes amounts
asset.totalAmount = Object.values(asset.rewardTypes).reduce(
@@ -131,20 +131,25 @@ export const ConsensusValidatorsTable = ({
const gridRef = useRef<AgGridReact | null>(null);
const thirdOfTotalStake = useMemo(
() => new BigNumber(totalStake).dividedBy(3),
[totalStake]
);
const nodes = useMemo(() => {
if (!data) return [];
let canonisedNodes = data
.sort((a, b) => {
const aVotingPower = new BigNumber(a.rankingScore.votingPower);
const bVotingPower = new BigNumber(b.rankingScore.votingPower);
return bVotingPower.minus(aVotingPower).toNumber();
const aStakedTotal = new BigNumber(a.stakedTotal);
const bStakedTotal = new BigNumber(b.stakedTotal);
return bStakedTotal.minus(aStakedTotal).toNumber();
})
.map((node, index) => {
const votingPowerRanking = index + 1;
const stakedTotalRanking = index + 1;
return {
...node,
votingPowerRanking,
stakedTotalRanking,
};
})
.map(
@@ -157,7 +162,7 @@ export const ConsensusValidatorsTable = ({
stakedTotal,
rankingScore: { stakeScore, votingPower },
pendingStake,
votingPowerRanking,
stakedTotalRanking,
stakedByUser,
pendingUserStake,
userStakeShare,
@@ -175,7 +180,7 @@ export const ConsensusValidatorsTable = ({
return {
id,
[ValidatorFields.RANKING_INDEX]: votingPowerRanking,
[ValidatorFields.RANKING_INDEX]: stakedTotalRanking,
[ValidatorFields.VALIDATOR]: {
avatarUrl: logo,
name,
@@ -236,16 +241,12 @@ export const ConsensusValidatorsTable = ({
return canonisedNodes;
}
// The point of identifying and hiding the group that could halt the network
// is that we assume the top 1/3 of stake is held by considerably less than
// 1/3 of the validators and we really want people not to stake any more to
// that group, because we want to make it require as many difference
// validators to collude as possible to halt the network, so we hide them.
const { topThird, remaining } = canonisedNodes.reduce(
(acc, node) => {
if (acc.cumulativeScore < 100 / 3) {
acc.cumulativeScore += parseFloat(
node[ValidatorFields.NORMALISED_VOTING_POWER]
if (acc.cumulativeScore.isLessThan(thirdOfTotalStake)) {
const prev = acc.cumulativeScore;
acc.cumulativeScore = prev.plus(
new BigNumber(node[ValidatorFields.STAKE])
);
acc.topThird.push(node);
return acc;
@@ -253,61 +254,70 @@ export const ConsensusValidatorsTable = ({
acc.remaining.push(node);
return acc;
},
{ topThird: [], remaining: [], cumulativeScore: 0 } as {
{ topThird: [], remaining: [], cumulativeScore: new BigNumber(0) } as {
topThird: CanonisedConsensusNodeProps[];
remaining: CanonisedConsensusNodeProps[];
cumulativeScore: number;
cumulativeScore: BigNumber;
}
);
// We need to combine the top third of validators into a single node, this
// way the combined values can be passed to AG grid so that the combined cell's
// values are correct for ordering.
const combinedTopThird = topThird.reduce((acc, node) => {
const {
[ValidatorFields.STAKE]: stake,
[ValidatorFields.STAKE_SHARE]: stakeShare,
[ValidatorFields.PENDING_STAKE]: pendingStake,
[ValidatorFields.NORMALISED_VOTING_POWER]: normalisedVotingPower,
[ValidatorFields.TOTAL_PENALTIES]: totalPenalties,
} = node;
const combinedTopThird = topThird.reduce(
(acc, node) => {
const {
[ValidatorFields.STAKE]: stake,
[ValidatorFields.STAKE_SHARE]: stakeShare,
[ValidatorFields.PENDING_STAKE]: pendingStake,
[ValidatorFields.NORMALISED_VOTING_POWER]: normalisedVotingPower,
[ValidatorFields.TOTAL_PENALTIES]: totalPenalties,
} = node;
const {
[ValidatorFields.STAKE]: accStake,
[ValidatorFields.STAKE_SHARE]: accStakeShare,
[ValidatorFields.PENDING_STAKE]: accPendingStake,
[ValidatorFields.NORMALISED_VOTING_POWER]: accNormalisedVotingPower,
[ValidatorFields.TOTAL_PENALTIES]: accTotalPenalties,
} = acc;
const {
[ValidatorFields.STAKE]: accStake,
[ValidatorFields.STAKE_SHARE]: accStakeShare,
[ValidatorFields.PENDING_STAKE]: accPendingStake,
[ValidatorFields.NORMALISED_VOTING_POWER]: accNormalisedVotingPower,
[ValidatorFields.TOTAL_PENALTIES]: accTotalPenalties,
} = acc;
return {
...acc,
[ValidatorFields.STAKE]: toBigNum(accStake, decimals)
.plus(toBigNum(stake, decimals))
.toString(),
[ValidatorFields.STAKE_SHARE]: formatNumberPercentage(
new BigNumber(parseFloat(accStakeShare)).plus(
new BigNumber(parseFloat(stakeShare))
return {
...acc,
[ValidatorFields.STAKE]: new BigNumber(accStake)
.plus(new BigNumber(stake))
.toString(),
[ValidatorFields.STAKE_SHARE]: formatNumberPercentage(
new BigNumber(parseFloat(accStakeShare)).plus(
new BigNumber(parseFloat(stakeShare))
),
2
),
2
),
[ValidatorFields.PENDING_STAKE]: toBigNum(accPendingStake, decimals)
.plus(toBigNum(pendingStake, decimals))
.toString(),
[ValidatorFields.NORMALISED_VOTING_POWER]: formatNumberPercentage(
new BigNumber(parseFloat(accNormalisedVotingPower)).plus(
new BigNumber(parseFloat(normalisedVotingPower))
[ValidatorFields.PENDING_STAKE]: toBigNum(accPendingStake, decimals)
.plus(toBigNum(pendingStake, decimals))
.toString(),
[ValidatorFields.NORMALISED_VOTING_POWER]: formatNumberPercentage(
new BigNumber(parseFloat(accNormalisedVotingPower)).plus(
new BigNumber(parseFloat(normalisedVotingPower))
),
2
),
2
),
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
new BigNumber(parseFloat(accTotalPenalties)).plus(
new BigNumber(parseFloat(totalPenalties))
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
new BigNumber(parseFloat(accTotalPenalties)).plus(
new BigNumber(parseFloat(totalPenalties))
),
2
),
2
),
};
});
};
},
{
[ValidatorFields.STAKE]: '0',
[ValidatorFields.STAKE_SHARE]: '0',
[ValidatorFields.PENDING_STAKE]: '0',
[ValidatorFields.NORMALISED_VOTING_POWER]: '0',
[ValidatorFields.TOTAL_PENALTIES]: '0',
}
);
return [
{
@@ -322,6 +332,7 @@ export const ConsensusValidatorsTable = ({
decimals,
hideTopThird,
previousEpochData,
thirdOfTotalStake,
totalStake,
validatorsView,
]);
@@ -352,6 +363,7 @@ export const ConsensusValidatorsTable = ({
headerTooltip: t('StakeDescription').toString(),
cellRenderer: TotalStakeRenderer,
width: 120,
sort: 'desc',
},
{
field: ValidatorFields.PENDING_STAKE,
@@ -373,7 +385,6 @@ export const ConsensusValidatorsTable = ({
headerTooltip: t('NormalisedVotingPowerDescription').toString(),
cellRenderer: VotingPowerRenderer,
width: 200,
sort: 'desc',
},
{
field: ValidatorFields.TOTAL_PENALTIES,
@@ -57,16 +57,16 @@ export const StandbyPendingValidatorsTable = ({
return data
.sort((a, b) => {
const aVotingPower = new BigNumber(a.rankingScore.votingPower);
const bVotingPower = new BigNumber(b.rankingScore.votingPower);
return bVotingPower.minus(aVotingPower).toNumber();
const aStakedTotal = new BigNumber(a.stakedTotal);
const bStakedTotal = new BigNumber(b.stakedTotal);
return bStakedTotal.minus(aStakedTotal).toNumber();
})
.map((node, index) => {
const votingPowerRanking = index + 1;
const stakedTotalRanking = index + 1;
return {
...node,
votingPowerRanking,
stakedTotalRanking,
};
})
.map(
@@ -79,7 +79,7 @@ export const StandbyPendingValidatorsTable = ({
stakedTotal,
rankingScore: { stakeScore },
pendingStake,
votingPowerRanking,
stakedTotalRanking,
stakedByUser,
pendingUserStake,
userStakeShare,
@@ -125,7 +125,7 @@ export const StandbyPendingValidatorsTable = ({
return {
id,
[ValidatorFields.RANKING_INDEX]: votingPowerRanking,
[ValidatorFields.RANKING_INDEX]: stakedTotalRanking,
[ValidatorFields.VALIDATOR]: {
avatarUrl,
name,
@@ -166,7 +166,7 @@ export const StandbyPendingValidatorsTable = ({
: undefined,
[ValidatorFields.PENDING_USER_STAKE]: pendingUserStake,
[ValidatorFields.USER_STAKE_SHARE]: userStakeShare
? formatNumberPercentage(new BigNumber(userStakeShare))
? formatNumberPercentage(new BigNumber(userStakeShare), 2)
: undefined,
};
}
@@ -210,6 +210,7 @@ export const StandbyPendingValidatorsTable = ({
headerTooltip: t('StakeDescription').toString(),
cellRenderer: TotalStakeRenderer,
width: 120,
sort: 'desc',
},
{
field: ValidatorFields.PENDING_STAKE,
@@ -233,7 +234,6 @@ export const StandbyPendingValidatorsTable = ({
}),
cellRenderer: StakeNeededForPromotionRenderer,
width: 210,
sort: 'asc',
},
{
field: ValidatorFields.TOTAL_PENALTIES,
@@ -1,4 +1,3 @@
import { useEffect, useState } from 'react';
import { ENV } from '../../../config';
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
@@ -29,7 +28,6 @@ export const NodeContainer = ({
const { t } = useTranslation();
const { pubKey } = useVegaWallet();
const { delegationsPagination } = ENV;
const { data, loading, error, refetch } = useStakingQuery({
variables: {
partyId: pubKey || '',
@@ -40,20 +38,6 @@ export const NodeContainer = ({
: undefined,
},
});
const [isRefetching, setIsRefetching] = useState(false);
useEffect(() => {
if (error && error.message.includes('failed to get party for ID')) {
setIsRefetching(true);
// The API errors if there is a pubkey, but it hasn't interacted with the
// chain before. In that case, retry the query with empty pubKey
refetch({
partyId: '',
}).finally(() => setIsRefetching(false));
}
}, [error, refetch, delegationsPagination]);
const { data: previousEpochData } = usePreviousEpochQuery({
variables: {
epochId: (Number(data?.epoch.id) - 1).toString(),
@@ -63,7 +47,7 @@ export const NodeContainer = ({
useRefreshAfterEpoch(data?.epoch.timestamps.expiry, refetch);
if (error && !isRefetching) {
if (error) {
return (
<Callout intent={Intent.Danger} title={t('Something went wrong')}>
<pre>
@@ -75,7 +59,7 @@ export const NodeContainer = ({
);
}
if (loading || isRefetching) {
if (loading) {
return (
<Splash>
<SplashLoader />
+20 -42
View File
@@ -82,7 +82,7 @@
"tranche_end": "2023-05-20T00:00:00.000Z",
"total_added": "19242.125",
"total_removed": "2249.511113406525",
"locked_amount": "2401.96952025462936594125",
"locked_amount": "2882.3396685956788223",
"deposits": [
{
"amount": "188",
@@ -5011,7 +5011,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297",
"total_removed": "0",
"locked_amount": "48140.1269815871359888489",
"locked_amount": "48317.9555821159337784424",
"deposits": [
{
"amount": "86666.297",
@@ -5077,7 +5077,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500",
"total_removed": "0",
"locked_amount": "216.275564713064575",
"locked_amount": "226.563135938135925",
"deposits": [
{
"amount": "2500",
@@ -5110,7 +5110,7 @@
"tranche_end": "2023-11-01T00:00:00.000Z",
"total_added": "15000.000000000000015",
"total_removed": "0",
"locked_amount": "13756.37454710145001375637454710145",
"locked_amount": "13817.4290458937205138174290458937205",
"deposits": [
{
"amount": "1.5e-14",
@@ -5218,7 +5218,7 @@
"tranche_end": "2023-09-01T00:00:00.000Z",
"total_added": "17500",
"total_removed": "0",
"locked_amount": "10247.473203502416",
"locked_amount": "10318.7034520933965",
"deposits": [
{
"amount": "12500",
@@ -5484,8 +5484,8 @@
"tranche_start": "2023-02-01T00:00:00.000Z",
"tranche_end": "2023-08-01T00:00:00.000Z",
"total_added": "37500",
"total_removed": "18500.56159815",
"locked_amount": "15900.17840699815875",
"total_removed": "18302.01762945",
"locked_amount": "16055.344536525477375",
"deposits": [
{
"amount": "7500",
@@ -5504,11 +5504,6 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x0a46fa3cc0154727ae4c7abca97bd7e26e6835018f96cf3a3860a9fcc791b9a4"
},
{
"amount": "198.5439687",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xc25a025176872981def8433ef0982ba306737aaf2cf0867f2259fd19492af2b5"
},
{
"amount": "164.727209925",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -5693,12 +5688,6 @@
"tranche_id": 34,
"tx": "0x0a46fa3cc0154727ae4c7abca97bd7e26e6835018f96cf3a3860a9fcc791b9a4"
},
{
"amount": "198.5439687",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 34,
"tx": "0xc25a025176872981def8433ef0982ba306737aaf2cf0867f2259fd19492af2b5"
},
{
"amount": "164.727209925",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -5881,8 +5870,8 @@
}
],
"total_tokens": "7500",
"withdrawn_tokens": "4290.80292735",
"remaining_tokens": "3209.19707265"
"withdrawn_tokens": "4092.25895865",
"remaining_tokens": "3407.74104135"
},
{
"address": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
@@ -5926,7 +5915,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "48096.20517293948430816",
"locked_amount": "48273.871527245545831062",
"deposits": [
{
"amount": "129999.45",
@@ -5959,7 +5948,7 @@
"tranche_end": "2024-04-01T00:00:00.000Z",
"total_added": "54144.7663",
"total_removed": "0",
"locked_amount": "47449.8785431340723146965",
"locked_amount": "47560.67340809499170700618",
"deposits": [
{
"amount": "54144.7663",
@@ -5992,7 +5981,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600",
"total_removed": "0",
"locked_amount": "18821.995357686454604",
"locked_amount": "18950.4428716387644",
"deposits": [
{
"amount": "10000",
@@ -6185,7 +6174,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "1695.1350837138507",
"locked_amount": "1705.394469812278",
"deposits": [
{
"amount": "5000",
@@ -7254,7 +7243,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "1709370.7872515768348",
"locked_amount": "88996.7980509664211246026",
"locked_amount": "92977.2929017097590512412",
"deposits": [
{
"amount": "1852091.69",
@@ -41126,7 +41115,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "715655.108029600523393",
"locked_amount": "161258.417939562670358424702",
"locked_amount": "167375.052664041820091539864",
"deposits": [
{
"amount": "1998.95815",
@@ -42518,8 +42507,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "885240.49984321970795352",
"locked_amount": "5871499.5818745175664760343676677342903488",
"total_removed": "883053.81009036878182852",
"locked_amount": "5893188.77588203421147062714280689633630716",
"deposits": [
{
"amount": "16249.93",
@@ -43053,11 +43042,6 @@
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
"tx": "0xc8835acd2e148eeaacde2a0df0ecad19c22717c7c51b207fdeac9a1af3f98c88"
},
{
"amount": "2186.689752850926125",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xb048cb2dcdfc30508770a3a112ddbacd63210f740cc887559660522bd506612c"
},
{
"amount": "10150.87581603206683",
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
@@ -45244,12 +45228,6 @@
"tranche_id": 2,
"tx": "0x989d22d5ba66353cb132b5643100a99e78133e5d40aef1ac91ed6ab0a2290299"
},
{
"amount": "2186.689752850926125",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0xb048cb2dcdfc30508770a3a112ddbacd63210f740cc887559660522bd506612c"
},
{
"amount": "913.910324501590625",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -46806,8 +46784,8 @@
}
],
"total_tokens": "259998.8875",
"withdrawn_tokens": "163472.318146307289625",
"remaining_tokens": "96526.569353692710375"
"withdrawn_tokens": "161285.6283934563635",
"remaining_tokens": "98713.2591065436365"
},
{
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
@@ -59350,7 +59328,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "44796.7287294743416",
"locked_amount": "25552.318114939110235126642617948",
"locked_amount": "26521.533851207463842098954743804",
"deposits": [
{
"amount": "3000",
@@ -7,9 +7,6 @@ const marketTitle = 'accordion-title';
const externalLink = 'external-link';
const accordionContent = 'accordion-content';
const providerName = 'provider-name';
const oracleBannerStatus = 'oracle-banner-status';
const oracleBannerDialogTrigger = 'oracle-banner-dialog-trigger';
const oracleFullProfile = 'oracle-full-profile';
describe('market info is displayed', { tags: '@smoke' }, () => {
beforeEach(() => {
@@ -32,11 +29,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
it('show oracle banner', () => {
cy.getByTestId(marketTitle).contains('Oracle').click();
cy.getByTestId(oracleBannerStatus).should('contain.text', 'COMPROMISED');
cy.getByTestId(oracleBannerDialogTrigger)
.should('contain.text', 'Show more')
.click();
cy.getByTestId(oracleFullProfile).should('exist');
cy.getByTestId('oracle-status').should('contain.text', 'COMPROMISED');
});
it('current fees displayed', () => {
@@ -291,58 +291,12 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
.should('have.text', '200.00');
});
it('must see a pegged order - ask', () => {
updateOrder({
id: orderId,
side: Schema.Side.SIDE_BUY,
peggedOrder: {
__typename: 'PeggedOrder',
reference: Schema.PeggedReference.PEGGED_REFERENCE_BEST_ASK,
offset: '250000',
},
});
cy.get(`[row-id=${orderId}]`)
.find('[col-id="type"]')
.should('have.text', 'Ask - 2.50 Peg limit');
});
it('must see a pegged order - bid', () => {
updateOrder({
id: orderId,
side: Schema.Side.SIDE_SELL,
peggedOrder: {
__typename: 'PeggedOrder',
reference: Schema.PeggedReference.PEGGED_REFERENCE_BEST_BID,
offset: '100',
},
});
cy.get(`[row-id=${orderId}]`)
.find('[col-id="type"]')
.should('have.text', 'Bid + 0.001 Peg limit');
});
it('must see a pegged order - mid', () => {
updateOrder({
id: orderId,
side: Schema.Side.SIDE_SELL,
peggedOrder: {
__typename: 'PeggedOrder',
reference: Schema.PeggedReference.PEGGED_REFERENCE_MID,
offset: '0.5',
},
});
cy.get(`[row-id=${orderId}]`)
.find('[col-id="type"]')
.should('have.text', 'Mid + 0.00001 Peg limit');
});
it('for market typy must not see a price for active or parked orders', () => {
// 7003-MORD-005
updateOrder({
id: orderId,
type: Schema.OrderType.TYPE_MARKET,
status: Schema.OrderStatus.STATUS_PARKED,
peggedOrder: null,
});
cy.get(`[row-id=${orderId}]`)
.find('[col-id="price"]')
@@ -383,7 +337,6 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
updateOrder({
id: orderId,
status: Schema.OrderStatus.STATUS_ACTIVE,
peggedOrder: {},
liquidityProvisionId: '6536',
});
cy.get(`[row-id=${orderId}]`)
+1 -1
View File
@@ -1,7 +1,7 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types';
import type { CyHttpMessages } from 'cypress/types/net-stubbing';
import type { Provider, Status } from '@vegaprotocol/market-info';
import type { Provider, Status } from '@vegaprotocol/oracles';
import {
accountsQuery,
assetQuery,
-6
View File
@@ -1,6 +0,0 @@
function ReactMarkdown({ children }) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
}
export default ReactMarkdown;
@@ -13,7 +13,7 @@ import { memo, useState } from 'react';
import type { ReactNode, ComponentProps } from 'react';
import { DepthChartContainer } from '@vegaprotocol/market-depth';
import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
import { OracleBanner } from '@vegaprotocol/market-info';
import { OracleBanner } from '../../components/banner';
import {
Tab,
LocalStoragePersistTabs as Tabs,
@@ -6,8 +6,8 @@ import { MarketState } from '@vegaprotocol/types';
import { subDays } from 'date-fns';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/market-info';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/market-info';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/oracles';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/oracles';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import type {
@@ -2,8 +2,8 @@ import { render, screen } from '@testing-library/react';
import type { Property } from '@vegaprotocol/types';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/market-info';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/market-info';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/oracles';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/oracles';
import type { SettlementPriceCellProps } from './settlement-price-cell';
import { SettlementPriceCell } from './settlement-price-cell';
@@ -1,6 +1,6 @@
import { DApp, EXPLORER_ORACLE, useLinks } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { useOracleSpecBindingData } from '@vegaprotocol/market-info';
import { useOracleSpecBindingData } from '@vegaprotocol/oracles';
import { Link } from '@vegaprotocol/ui-toolkit';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
+1
View File
@@ -1 +1,2 @@
export * from './announcement-banner';
export * from './oracle-banner';
@@ -0,0 +1,45 @@
import { t } from '@vegaprotocol/i18n';
import { useMarketOracle } from '@vegaprotocol/market-info';
import ReactMarkdown from 'react-markdown';
import { Intent, NotificationBanner } from '@vegaprotocol/ui-toolkit';
const oracleStatuses = {
UNKNOWN: t(
"This public key's proofs have not been verified yet, or no proofs have been provided yet."
),
GOOD: t("This public key's proofs have been verified."),
SUSPICIOUS: t(
'This public key is suspected to be acting in bad faith, pending investigation.'
),
MALICIOUS: t('This public key has been observed acting in bad faith.'),
RETIRED: t('This public key is no longer in use.'),
COMPROMISED: t(
'This public key is no longer in the control of its original owners.'
),
};
export const OracleBanner = ({ marketId }: { marketId: string }) => {
const oracle = useMarketOracle(marketId);
if (!oracle || oracle.status === 'GOOD') {
return null;
}
return (
<NotificationBanner intent={Intent.Danger}>
<div>
Oracle status for this market is{' '}
<span data-testId="oracle-status">{oracle.status}</span>.{' '}
{oracleStatuses[oracle.status]}
</div>
{oracle.status_reason ? (
<ReactMarkdown
className="react-markdown-container"
skipHtml={true}
disallowedElements={['img']}
linkTarget="_blank"
>
{oracle.status_reason}
</ReactMarkdown>
) : null}
</NotificationBanner>
);
};
+2 -2
View File
@@ -12,13 +12,13 @@ export * from '../fills/src/lib/fills.mock';
export * from '../proposals/src/lib/proposals-data-provider/proposals.mock';
export * from '../ledger/src/lib/ledger-entries.mock';
export * from '../market-depth/src/lib/market-depth.mock';
export * from '../market-info/src/lib/components/market-info/market-info.mock';
export * from '../market-info/src/components/market-info/market-info.mock';
export * from '../market-list/src/lib/market-candles.mock';
export * from '../market-list/src/lib/market-data.mock';
export * from '../market-list/src/lib/markets-candles.mock';
export * from '../market-list/src/lib/markets-data.mock';
export * from '../market-list/src/lib/markets.mock';
export * from '../market-info/src/lib/oracle-spec-data-connection.mock';
export * from '../oracles/src/lib/oracle-spec-data-connection.mock';
export * from '../orders/src/lib/components/order-data-provider/orders.mock';
export * from '../positions/src/lib/positions.mock';
export * from '../network-parameters/src/network-params.mock';
-6
View File
@@ -1,6 +0,0 @@
function ReactMarkdown({ children }) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
}
export default ReactMarkdown;
+4 -1
View File
@@ -36,7 +36,10 @@ export const DepositManager = ({
const bridgeContract = useBridgeContract();
const closeDepositDialog = useDepositDialog((state) => state.close);
const { getBalances, reset, balances } = useDepositBalances(asset);
const { getBalances, reset, balances } = useDepositBalances(
asset,
isFaucetable
);
// Set up approve transaction
const approve = useSubmitApproval(asset, getBalances);
@@ -28,9 +28,13 @@ const initialState: DepositBalances = {
* Hook which fetches all the balances required for depositing
* whenever the asset changes in the form
*/
export const useDepositBalances = (asset: Asset | undefined) => {
export const useDepositBalances = (
asset: Asset | undefined,
isFaucetable: boolean
) => {
const tokenContract = useTokenContract(
isAssetTypeERC20(asset) ? asset.source.contractAddress : undefined
isAssetTypeERC20(asset) ? asset.source.contractAddress : undefined,
isFaucetable
);
const bridgeContract = useBridgeContract();
const getAllowance = useGetAllowance(tokenContract, asset);
+2 -1
View File
@@ -20,7 +20,8 @@ export const useSubmitApproval = (
});
const { config } = useEthereumConfig();
const contract = useTokenContract(
isAssetTypeERC20(asset) ? asset.source.contractAddress : undefined
isAssetTypeERC20(asset) ? asset.source.contractAddress : undefined,
true
);
// When tx is confirmed refresh balances
+2 -1
View File
@@ -18,7 +18,8 @@ export const useSubmitFaucet = (
return state.transactions.find((t) => t?.id === id);
});
const contract = useTokenContract(
isAssetTypeERC20(asset) ? asset.source.contractAddress : undefined
isAssetTypeERC20(asset) ? asset.source.contractAddress : undefined,
true
);
// When tx is confirmed refresh balances
-6
View File
@@ -1,6 +0,0 @@
function ReactMarkdown({ children }) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
}
export default ReactMarkdown;
-31
View File
@@ -39,37 +39,6 @@
"passWithNoTests": true
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"config": {
"configFolder": "libs/market-info/.storybook"
}
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/react",
"outputPath": "dist/storybook/market-info",
"config": {
"configFolder": "libs/market-info/.storybook"
}
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-spec": {
"executor": "@nrwl/workspace:run-commands",
"outputs": [],
@@ -2,6 +2,3 @@ export * from './market-info';
export * from './last-24h-price-change';
export * from './last-24h-volume';
export * from './fees-breakdown';
export * from './oracle-basic-profile';
export * from './oracle-full-profile';
export * from './oracle-banner';
@@ -5,7 +5,7 @@ import {
} from '@vegaprotocol/types';
import { DataSourceProof } from './market-info-panels';
jest.mock('../../hooks/use-oracle-markets', () => ({
jest.mock('@vegaprotocol/oracles', () => ({
useOracleMarkets: () => [],
}));
@@ -35,7 +35,7 @@ describe('DataSourceProof', () => {
providers: [],
type: 'termination' as const,
};
render(<DataSourceProof dataSourceSpecId={''} {...props} />);
render(<DataSourceProof id={''} {...props} />);
expect(
screen.getByText('No oracle proof for termination')
).toBeInTheDocument();
@@ -88,7 +88,7 @@ describe('DataSourceProof', () => {
],
type: 'settlementData' as const,
};
render(<DataSourceProof dataSourceSpecId={''} {...props} />);
render(<DataSourceProof id={''} {...props} />);
expect(
screen.getByText('No oracle proof for settlement data')
).toBeInTheDocument();
@@ -128,7 +128,7 @@ describe('DataSourceProof', () => {
providers: [],
type: 'termination' as const,
};
render(<DataSourceProof dataSourceSpecId={''} {...props} />);
render(<DataSourceProof id={''} {...props} />);
expect(screen.getByText('Internal conditions')).toBeInTheDocument();
expect(
screen.getByText(
@@ -26,13 +26,13 @@ import type { DataSourceDefinition, SignerKind } from '@vegaprotocol/types';
import { ConditionOperatorMapping } from '@vegaprotocol/types';
import { MarketTradingModeMapping } from '@vegaprotocol/types';
import { useEnvironment } from '@vegaprotocol/environment';
import type { Provider } from '../../oracle-schema';
import type { Provider } from '@vegaprotocol/oracles';
import { OracleProfileTitle, OracleFullProfile } from '@vegaprotocol/oracles';
import {
OracleBasicProfile,
OracleProfileTitle,
OracleFullProfile,
} from '../../components';
import { useOracleProofs, useOracleMarkets } from '../../hooks';
useOracleProofs,
useOracleMarkets,
} from '@vegaprotocol/oracles';
import { useDataProvider } from '@vegaprotocol/data-provider';
type PanelProps = Pick<
@@ -478,7 +478,7 @@ export const OracleInfoPanel = ({
}
providers={data}
type={type}
dataSourceSpecId={dataSourceSpecId}
id={dataSourceSpecId}
/>
<ExternalLink
data-testid="oracle-spec-links"
@@ -500,12 +500,12 @@ export const DataSourceProof = ({
data,
providers,
type,
dataSourceSpecId,
id,
}: {
data: DataSourceDefinition;
providers: Provider[] | undefined;
type: 'settlementData' | 'termination';
dataSourceSpecId: string;
id: string;
}) => {
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
const signers = data.sourceType.sourceType.signers || [];
@@ -523,7 +523,7 @@ export const DataSourceProof = ({
providers={providers}
signer={signer}
type={type}
dataSourceSpecId={dataSourceSpecId}
id={id}
/>
);
})}
@@ -554,12 +554,12 @@ const OracleLink = ({
providers,
signer,
type,
dataSourceSpecId,
id,
}: {
providers: Provider[];
signer: SignerKind;
type: 'settlementData' | 'termination';
dataSourceSpecId: string;
id: string;
}) => {
const signerProviders = providers.filter((p) => {
if (signer.__typename === 'PubKey') {
@@ -590,11 +590,7 @@ const OracleLink = ({
return (
<div>
{signerProviders.map((provider) => (
<OracleProfile
key={dataSourceSpecId}
provider={provider}
dataSourceSpecId={dataSourceSpecId}
/>
<OracleProfile key={id} provider={provider} id={id} />
))}
</div>
);
@@ -615,46 +611,35 @@ const NoOracleProof = ({
);
};
export const OracleDialog = ({
const OracleProfile = ({
provider,
dataSourceSpecId,
open,
onChange,
id,
}: {
dataSourceSpecId: string;
provider: Provider;
open: boolean;
onChange?: (isOpen: boolean) => void;
id: string;
}) => {
const [dialogOpen, setDialogOpen] = useState(false);
const oracleMarkets = useOracleMarkets(provider);
return (
<Dialog
title={<OracleProfileTitle provider={provider} />}
aria-labelledby="oracle-proof-dialog"
open={open}
onChange={onChange}
>
<OracleFullProfile
<div key={provider.name}>
<OracleBasicProfile
provider={provider}
dataSourceSpecId={dataSourceSpecId}
onClick={() => setDialogOpen(!dialogOpen)}
markets={oracleMarkets}
/>
</Dialog>
);
};
const OracleProfile = (props: {
provider: Provider;
dataSourceSpecId: string;
}) => {
const [open, onChange] = useState(false);
return (
<div key={props.provider.name}>
<OracleBasicProfile
provider={props.provider}
onClick={() => onChange(!open)}
/>
<OracleDialog {...props} open={open} onChange={onChange} />
<Dialog
title={<OracleProfileTitle provider={provider} />}
open={dialogOpen}
onChange={() => setDialogOpen(!dialogOpen)}
aria-labelledby="oracle-proof-dialog"
>
<OracleFullProfile
provider={provider}
id={id}
key={id}
markets={oracleMarkets}
/>
</Dialog>
</div>
);
};
+1
View File
@@ -0,0 +1 @@
export * from './use-market-oracle';
@@ -1,13 +1,12 @@
import { renderHook } from '@testing-library/react';
import { useMarketOracle } from './use-market-oracle';
import type { MarketInfoQuery } from '../components/market-info/__generated__/MarketInfo';
import type { Provider } from '../oracle-schema';
import type { Provider } from '@vegaprotocol/oracles';
const ORACLE_PROOFS_URL = 'ORACLE_PROOFS_URL';
const address = 'address';
const key = 'key';
const dataSourceSpecId = 'dataSourceSpecId';
const mockEnvironment = jest.fn(() => ({ ORACLE_PROOFS_URL }));
const mockDataProvider = jest.fn<
@@ -19,7 +18,6 @@ const mockDataProvider = jest.fn<
instrument: {
product: {
dataSourceSpecForSettlementData: {
id: dataSourceSpecId,
data: {
sourceType: {
__typename: 'DataSourceDefinitionExternal',
@@ -59,7 +57,7 @@ jest.mock('@vegaprotocol/data-provider', () => ({
useDataProvider: jest.fn((args) => mockDataProvider()),
}));
jest.mock('./use-oracle-proofs', () => ({
jest.mock('@vegaprotocol/oracles', () => ({
useOracleProofs: jest.fn((args) => mockOracleProofs()),
}));
@@ -102,8 +100,7 @@ describe('useMarketOracle', () => {
data,
});
const { result } = renderHook(() => useMarketOracle(marketId));
expect(result.current?.dataSourceSpecId).toBe(dataSourceSpecId);
expect(result.current?.provider).toBe(data[1]);
expect(result.current).toBe(data[1].oracle);
});
it('returns oracle matching by public_key', () => {
@@ -131,7 +128,6 @@ describe('useMarketOracle', () => {
data,
});
const { result } = renderHook(() => useMarketOracle(marketId));
expect(result.current?.dataSourceSpecId).toBe(dataSourceSpecId);
expect(result.current?.provider).toBe(data[1]);
expect(result.current).toBe(data[1].oracle);
});
});
@@ -1,5 +1,5 @@
import { useEnvironment } from '@vegaprotocol/environment';
import { useOracleProofs } from './use-oracle-proofs';
import { useOracleProofs } from '@vegaprotocol/oracles';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { marketInfoProvider } from '../components/market-info/market-info-data-provider';
import { useMemo } from 'react';
@@ -15,11 +15,10 @@ export const useMarketOracle = (marketId: string) => {
if (!data || !marketInfo) {
return undefined;
}
const dataSourceSpec =
const dataSource =
marketInfo.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData;
const { data: dataSource, id: dataSourceSpecId } = dataSourceSpec;
const provider = data.find((provider) =>
.dataSourceSpecForSettlementData.data;
return data.find((provider) =>
provider.proofs.some((proof) => {
if (
proof.type === 'eth_address' &&
@@ -43,10 +42,6 @@ export const useMarketOracle = (marketId: string) => {
}
return false;
})
);
if (provider) {
return { provider, dataSourceSpecId };
}
return undefined;
)?.oracle;
}, [data, marketInfo]);
};
+2 -1
View File
@@ -1 +1,2 @@
export * from './lib';
export * from './components';
export * from './hooks';
@@ -1 +0,0 @@
export * from './oracle-banner';
@@ -1,53 +0,0 @@
import { useState } from 'react';
import { t } from '@vegaprotocol/i18n';
import { useMarketOracle } from '../../hooks';
import {
Intent,
NotificationBanner,
ButtonLink,
} from '@vegaprotocol/ui-toolkit';
import { OracleDialog } from '../market-info';
export const oracleStatuses = {
UNKNOWN: t(
"This public key's proofs have not been verified yet, or no proofs have been provided yet."
),
GOOD: t("This public key's proofs have been verified."),
SUSPICIOUS: t(
'This public key is suspected to be acting in bad faith, pending investigation.'
),
MALICIOUS: t('This public key has been observed acting in bad faith.'),
RETIRED: t('This public key is no longer in use.'),
COMPROMISED: t(
'This public key is no longer in the control of its original owners.'
),
};
export const OracleBanner = ({ marketId }: { marketId: string }) => {
const [open, onChange] = useState(false);
const oracle = useMarketOracle(marketId);
if (!oracle || oracle.provider.oracle.status === 'GOOD') {
return null;
}
const { provider } = oracle;
return (
<>
<OracleDialog open={open} onChange={onChange} {...oracle} />
<NotificationBanner intent={Intent.Danger}>
<div>
Oracle status for this market is{' '}
<span data-testid="oracle-banner-status">
{provider.oracle.status}
</span>
. {oracleStatuses[provider.oracle.status]}{' '}
<ButtonLink
onClick={() => onChange(!open)}
data-testid="oracle-banner-dialog-trigger"
>
{t('Show more')}
</ButtonLink>
</div>
</NotificationBanner>
</>
);
};
+3
View File
@@ -1,4 +1,7 @@
import '@testing-library/jest-dom';
import 'jest-canvas-mock';
import ResizeObserver from 'resize-observer-polyfill';
import { defaultFallbackInView } from 'react-intersection-observer';
defaultFallbackInView(true);
global.ResizeObserver = ResizeObserver;
-3
View File
@@ -19,9 +19,6 @@
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./.storybook/tsconfig.json"
}
]
}
+1 -5
View File
@@ -6,7 +6,7 @@
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/next/typings/image.d.ts"
"../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": [
"**/*.spec.ts",
@@ -17,10 +17,6 @@
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"**/*.stories.ts",
"**/*.stories.js",
"**/*.stories.jsx",
"**/*.stories.tsx",
"jest.config.ts"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
+1 -3
View File
@@ -15,8 +15,6 @@
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts",
"jest.config.ts",
"../../index.d.ts",
"src/lib/use-oracle-spec-binding-data.spec.tsx"
"jest.config.ts"
]
}
+12
View File
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nrwl/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
+18
View File
@@ -0,0 +1,18 @@
{
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "__generated__", "__generated___"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
+7
View File
@@ -0,0 +1,7 @@
# oracles
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test oracles` to execute the unit tests via [Jest](https://jestjs.io).
+11
View File
@@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: 'oracles',
preset: '../../jest.preset.js',
transform: {
'^.+\\.[tj]sx?$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/oracles',
setupFilesAfterEnv: ['./src/setup-tests.ts'],
};
+4
View File
@@ -0,0 +1,4 @@
{
"name": "@vegaprotocol/oracles",
"version": "0.0.1"
}
+81
View File
@@ -0,0 +1,81 @@
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/oracles/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nrwl/web:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/oracles",
"tsConfig": "libs/oracles/tsconfig.lib.json",
"project": "libs/oracles/package.json",
"entryFile": "libs/oracles/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/oracles/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/oracles/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/oracles"],
"options": {
"jestConfig": "libs/oracles/jest.config.ts",
"passWithNoTests": true
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"config": {
"configFolder": "libs/oracles/.storybook"
}
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/react",
"outputPath": "dist/storybook/oracles",
"config": {
"configFolder": "libs/oracles/.storybook"
}
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-spec": {
"executor": "@nrwl/workspace:run-commands",
"outputs": [],
"options": {
"command": "yarn tsc --project ./libs/oracles/tsconfig.spec.json"
}
}
}
}
+1
View File
@@ -0,0 +1 @@
export * from './lib';
+2
View File
@@ -0,0 +1,2 @@
export * from './oracle-basic-profile';
export * from './oracle-full-profile';
@@ -31,11 +31,7 @@ describe('OracleFullProfile', () => {
it('should render successfully', () => {
const component = (
<OracleFullProfile
provider={testProvider}
dataSourceSpecId={''}
markets={[]}
/>
<OracleFullProfile provider={testProvider} id={''} markets={[]} />
);
expect(component).toBeTruthy();
});
@@ -44,7 +40,7 @@ describe('OracleFullProfile', () => {
render(
<OracleFullProfile
provider={testProvider}
dataSourceSpecId={'oracle-id'}
id={'oracle-id'}
markets={[]}
/>
);
@@ -7,7 +7,7 @@ export default {
} as Meta;
const Template: Story = (args) => (
<OracleFullProfile provider={args['provider']} dataSourceSpecId="4578" />
<OracleFullProfile provider={args['provider']} id="4578" />
);
export const OraclePrimary = Template.bind({});
@@ -2,19 +2,19 @@ import { t } from '@vegaprotocol/i18n';
import type { Provider } from '../../oracle-schema';
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
import {
ButtonLink,
ExternalLink,
Icon,
Intent,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { oracleStatuses } from '../oracle-banner';
import type { IconName } from '@blueprintjs/icons';
import classNames from 'classnames';
import { getLinkIcon, getVerifiedStatusIcon } from '../oracle-basic-profile';
import { useEnvironment } from '@vegaprotocol/environment';
import type { OracleMarketSpecFieldsFragment } from '../../__generated__/OracleMarketsSpec';
import ReactMarkdown from 'react-markdown';
import { useState } from 'react';
export const OracleProfileTitle = ({ provider }: { provider: Provider }) => {
const { icon, intent } = getVerifiedStatusIcon(provider);
@@ -49,35 +49,18 @@ export const OracleProfileTitle = ({ provider }: { provider: Provider }) => {
);
};
const OracleStatus = ({ oracle }: { oracle: Provider['oracle'] }) => (
<div>
{t(`Oracle status`)}: {oracle.status}. {oracleStatuses[oracle.status]}
{oracle.status_reason ? (
<div>
<ReactMarkdown
className="react-markdown-container"
skipHtml={true}
disallowedElements={['img']}
linkTarget="_blank"
>
{oracle.status_reason}
</ReactMarkdown>
</div>
) : null}
</div>
);
export const OracleFullProfile = ({
provider,
dataSourceSpecId,
id,
markets: oracleMarkets,
}: {
provider: Provider;
dataSourceSpecId: string;
id: string;
markets?: OracleMarketSpecFieldsFragment[] | undefined;
}) => {
const { message } = getVerifiedStatusIcon(provider);
const { VEGA_EXPLORER_URL } = useEnvironment();
const [showMore, setShowMore] = useState(false);
const links = provider.proofs
.filter((proof) => proof.format === 'url' && proof.available === true)
@@ -88,24 +71,30 @@ export const OracleFullProfile = ({
}));
return (
<div className="flex flex-col text-sm" data-testid="oracle-full-profile">
<div className="flex flex-col text-sm">
<div className="dark:text-vega-light-300 text-vega-dark-300">
{provider.oracle.status !== 'GOOD' ? (
<div className="mb-2">
<OracleStatus oracle={provider.oracle} />
</div>
) : null}
<div className="mb-2">{message}</div>
<div className="mb-2">
<ReactMarkdown
className="react-markdown-container"
skipHtml={true}
disallowedElements={['img']}
linkTarget="_blank"
>
<p className=" pb-2">{message}</p>
{!showMore && (
<p className="pb-2">
{provider.description_markdown.slice(0, 100)}
{'... '}
<span className="ml-2">
<ButtonLink onClick={() => setShowMore(!showMore)}>
Read more
</ButtonLink>
</span>
</p>
)}
{showMore && (
<p className="pb-2">
{provider.description_markdown}
</ReactMarkdown>
</div>
<span className="ml-2">
<ButtonLink onClick={() => setShowMore(!showMore)}>
Show less
</ButtonLink>
</span>
</p>
)}
</div>
<div className="grid grid-cols-2 gap-6">
<div className="col-span-1">
@@ -143,9 +132,9 @@ export const OracleFullProfile = ({
<p className="dark:text-vega-light-300 text-vega-dark-300 uppercase">
{t('Details')}
</p>
{dataSourceSpecId && (
{id && (
<ExternalLink
href={`${VEGA_EXPLORER_URL}/oracles/${dataSourceSpecId}`}
href={`${VEGA_EXPLORER_URL}/oracles/${id}`}
data-testid="block-explorer-link"
>
{t('Block explorer')}
@@ -1,4 +1,3 @@
export * from './use-market-oracle';
export * from './use-oracle-markets';
export * from './use-oracle-proofs';
export * from './use-oracle-spec-binding-data';
+4
View File
@@ -0,0 +1,4 @@
import '@testing-library/jest-dom';
import ResizeObserver from 'resize-observer-polyfill';
global.ResizeObserver = ResizeObserver;
+27
View File
@@ -0,0 +1,27 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./.storybook/tsconfig.json"
}
]
}
+27
View File
@@ -0,0 +1,27 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/next/typings/image.d.ts"
],
"exclude": [
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"**/*.stories.ts",
"**/*.stories.js",
"**/*.stories.jsx",
"**/*.stories.tsx",
"jest.config.ts"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

Some files were not shown because too many files have changed in this diff Show More