Compare commits

..
Author SHA1 Message Date
Dexter 7c81c5f895 fix: provider not showing up 2023-01-24 19:42:19 +01:00
mattrussell36 898d3a329f chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:42:19 +01:00
Matthew Russell 90b38478ae chore: add cypress files to ignore list and use glob ignore option (#2700) 2023-01-24 19:42:19 +01:00
Radosław Szpiech f1b8d613bf chore: fix skip cache typo in workflow (#2715) 2023-01-24 19:42:19 +01:00
Dexter Edwards e3c8e0359f feat: splash loader more central (#2707) 2023-01-24 19:42:19 +01:00
96fcd285f5 chore: move token's web3 url connector to web3 lib (#2655)
Co-authored-by: Dexter <dexter.edwards93@gmail.com>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2023-01-24 19:42:19 +01:00
Bartłomiej Głownia e82e4f91ac feat: call update with null data from useDataProvider hook on variables change (#2689) 2023-01-24 19:38:48 +01:00
Dexter Edwards 127467bdd0 fix: calculation of required stake (#2687) 2023-01-24 19:38:48 +01:00
Art 0e87d7acbc chore: consolidate persisted order entries (#2673) 2023-01-24 19:38:48 +01:00
Dexter Edwards 45ae5cd781 fix: adjust route strcuture (#2708) 2023-01-24 19:38:48 +01:00
Radosław Szpiech f837ed37f2 chore: correct runner name (#2710) 2023-01-24 19:38:48 +01:00
mattrussell36 904bdc11a9 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
Dexter Edwards 594eb0aa28 fix: show error message correctly (#2705) 2023-01-24 19:38:48 +01:00
Joe Tsang 284756decc test(#2639): e2e view public key tests (#2688) 2023-01-24 19:38:48 +01:00
mattrussell36 3b88fd6926 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 99f16e9882 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 c27edced16 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 d91b100d42 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
Edd 906fc2a241 fix(explorer): add correct tendermint websocket url
Fairground block explorer seems subtly broken (block count not increasing) because this value is incorrect
2023-01-24 19:38:48 +01:00
mattrussell36 92d6999c1f chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 43f46aa94a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 2c5cc66706 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 9fa2ee6351 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 1c3dd1daf6 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 bb2f7fa33c chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 5433b7ee01 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 49117bf9d5 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 871c6907ac chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:48 +01:00
mattrussell36 eca2005c44 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:47 +01:00
botond fd5454faf5 chore: bump wallet client (#2662) 2023-01-24 19:38:47 +01:00
mattrussell36 c9feb63b9a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:47 +01:00
mattrussell36 33f50ea8dc chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-24 19:38:47 +01:00
Radosław Szpiech d52577f2e6 chore: simplify cypress workflows (#2677) 2023-01-24 19:38:47 +01:00
Dariusz Majcherczyk 22dc12149b chore: e2e test for deposit and withdrawal 2023-01-24 19:09:35 +01:00
Dariusz Majcherczyk 9442fe2012 chore: added local provider env for e2e tests 2023-01-20 08:50:37 +01:00
Dexter 8c19d99b6b chore: remove env vars from env file 2023-01-20 08:50:37 +01:00
Dexter 0d9c0e396c fix: provider not showing up 2023-01-20 08:50:37 +01:00
asiaznik 9f88c7e031 chore: ported token's web3 url connector to web3 lib 2023-01-20 08:50:37 +01:00
132 changed files with 1557 additions and 2159 deletions
-2
View File
@@ -40,12 +40,10 @@ jobs:
- name: See affected apps
run: |
affected=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)
echo -n "Affected projects: $affected"
projects=""
if [[ $affected == *"token"* ]]; then projects+='"token-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects+='"explorer-e2e" '; fi
if [[ -z "$projects" ]]; then projects+='"token-e2e" "trading-e2e" "explorer-e2e" '; fi
projects=${projects%?}
projects=[${projects// /,}]
echo PROJECTS=$projects >> $GITHUB_ENV
@@ -2,5 +2,16 @@ query ExplorerSettlementAssetForMarket($id: ID!) {
market(id: $id) {
id
decimalPlaces
tradableInstrument {
instrument {
product {
... on Future {
settlementAsset {
decimals
}
}
}
}
}
}
}
@@ -8,7 +8,7 @@ export type ExplorerSettlementAssetForMarketQueryVariables = Types.Exact<{
}>;
export type ExplorerSettlementAssetForMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number } | null };
export type ExplorerSettlementAssetForMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
export const ExplorerSettlementAssetForMarketDocument = gql`
@@ -16,6 +16,17 @@ export const ExplorerSettlementAssetForMarketDocument = gql`
market(id: $id) {
id
decimalPlaces
tradableInstrument {
instrument {
product {
... on Future {
settlementAsset {
decimals
}
}
}
}
}
}
}
`;
@@ -91,7 +91,7 @@ describe('LiquidityProvisionDetails component', () => {
expect(res.getByTestId('SIDE_SELL-40-1')).toBeInTheDocument();
expect(res.getByText('-1')).toBeInTheDocument();
expect(res.getByText('Best Bid')).toBeInTheDocument();
expect(res.getByText('40%')).toBeInTheDocument();
expect(res.getByText('40% (normalised from: 20%)')).toBeInTheDocument();
});
it('handles a missing offset gracefully (should not happen)', () => {
@@ -125,7 +125,7 @@ describe('LiquidityProvisionDetails component', () => {
);
// Row test ids and keys are based on the side, reference and proportion - and that proportion is scaled
expect(res.getByTestId('SIDE_SELL-40-1')).toBeInTheDocument();
expect(res.getByText('40%')).toBeInTheDocument();
expect(res.getByText('40% (normalised from: 20%)')).toBeInTheDocument();
expect(res.getByText('-')).toBeInTheDocument();
});
});
@@ -67,7 +67,11 @@ export function LiquidityProvisionDetailsRow({
<td className="text-center">
{order.reference ? LiquidityReferenceLabel[order.reference] : '-'}
</td>
<td className="text-center">{proportion}%</td>
<td className="text-center">
{proportion === order.proportion
? `${proportion}%`
: `${proportion}% (normalised from: ${order.proportion}%)`}{' '}
</td>
</TableRow>
);
}
@@ -13,6 +13,15 @@ const decimalsMock: ExplorerSettlementAssetForMarketQuery = {
id: '123',
__typename: 'Market',
decimalPlaces: 5,
tradableInstrument: {
instrument: {
product: {
settlementAsset: {
decimals: 5,
},
},
},
},
},
};
@@ -36,7 +36,7 @@ export function LiquidityProvisionOffset({
}
/**
* Does the work of formatting the number now we have the market decimal places.
* Does the work of formatting the number now we have the settlement decimal places.
* If no market data is assigned (i.e. during loading, or if the market doesn't exist)
* this function will return the unformatted number
*
@@ -49,7 +49,9 @@ export function getFormattedOffset(
offset: string,
data?: ExplorerSettlementAssetForMarketQuery
) {
const decimals = data?.market?.decimalPlaces;
const decimals =
data?.market?.tradableInstrument.instrument.product.settlementAsset
.decimals;
if (!decimals) {
return offset;
@@ -203,7 +203,7 @@ describe('LiquidityProvisionDetails component', () => {
};
const res = renderComponent(mock);
expect(res.getByText('45%')).toBeInTheDocument();
expect(res.getByText('55%')).toBeInTheDocument();
expect(res.getByText('45% (normalised from: 25%)')).toBeInTheDocument();
expect(res.getByText('55% (normalised from: 30%)')).toBeInTheDocument();
});
});
@@ -1,45 +0,0 @@
import { render } from '@testing-library/react';
import { JSONOracleData, parseData } from './data-submission-json-oracle';
describe('JSONOracleData', () => {
it('renders a code block if there is a payload that is base64 encoded', () => {
const p = 'eyJwcmljZXMuRVRIOTkudmFsdWUiOiAiMTMwNTAwMDAwMCJ9';
const screen = render(<JSONOracleData payload={p} />);
expect(screen.getByTestId('json-code')).toBeInTheDocument();
});
it('renders an error if b64 decoding fails', () => {
const p = 'not-encoded';
const screen = render(<JSONOracleData payload={p} />);
expect(
screen.getByText('Awaiting Block Explorer transaction details')
).toBeInTheDocument();
});
});
describe('Parse JSON oracle data', () => {
it('returns null for an invalid b64 string', () => {
expect(parseData('🤷')).toBeNull();
});
it('returns null for a string that looks like an object', () => {
expect(parseData('{}')).toBeNull();
});
it('returns null for null', () => {
expect(parseData(null as unknown as string)).toBeNull();
});
it('returns a string for b64 encoded data', () => {
const res = parseData('dGVzdCA9IHRydWU=');
expect(typeof res).toEqual('string');
expect(res).toEqual('test = true');
});
it('returns a string for b64 encoded json, without any extra parsing', () => {
const res = parseData('eyJ0ZXN0Ijp0cnVlfQ==');
expect(typeof res).toEqual('string');
expect(res).toEqual('{"test":true}');
});
});
@@ -1,40 +0,0 @@
import { t } from '@vegaprotocol/react-helpers';
interface JSONOracleDataProps {
payload: string;
}
/**
* Renders a JSON oracle. Given the shape could be any valid JSON,
* this doesn't try to do anything smart - it just renders the message
*/
export const JSONOracleData = ({ payload }: JSONOracleDataProps) => {
const decodedSubmission = parseData(payload);
if (!decodedSubmission) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<section>
<code data-testid="json-code">{decodedSubmission}</code>
</section>
);
};
/**
* Safely parses the JSON Oracle payload
*
* @param payload base64 encoded JSON
* @returns Object or null
*/
export function parseData(payload: string) {
try {
if (!payload || typeof payload !== 'string') {
throw new Error('Not a string');
}
return atob(payload);
} catch (e) {
return null;
}
}
@@ -1,58 +0,0 @@
import { render } from '@testing-library/react';
import { OpenOracleData, parseData } from './data-submission-open-oracle';
describe('OpenOracleData', () => {
it('renders a table if there is data', () => {
const p =
'eyJtZXNzYWdlcyI6IFsiMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA2M2M3ZTMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNGYxZjM4ZWEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjcwNzI2OTYzNjU3MzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDI1NDQzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCJdLCAicHJpY2VzIjogeyJFVEgiOiIxMjMifSwgInNpZ25hdHVyZXMiOiBbIjB4N2U0Nzc2OWEyNzI5NzIwN2Q5ZTIyMmM3YTY2YjBlYzk3Njg4MWY3NmVkYjg5OGFhYzQ5OTRlZWYwOTc4MmI3NGUxMGE5MTJmZWQ1Y2E3NmFlN2U3NzVjOWZiOTBjZGE4ZjhkMDhlNzUyOTE1NzQ2ZTY2OGE1ZWM3OWRmOTZmNmQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDFjIl0sICJ0aW1lc3RhbXAiOiAiMTIzIn0=';
const screen = render(<OpenOracleData payload={p} />);
expect(screen.getByTestId('decoded-payload')).toBeInTheDocument();
expect(screen.getByText('ETH')).toBeInTheDocument();
expect(screen.getByText('123')).toBeInTheDocument();
});
it('renders an error if decoding fails', () => {
const p = 'not-encoded';
const screen = render(<OpenOracleData payload={p} />);
expect(
screen.getByText('Awaiting Block Explorer transaction details')
).toBeInTheDocument();
});
});
describe('Parse Open oracle data', () => {
it('returns null for an invalid b64 string', () => {
expect(parseData('🤷')).toBeNull();
});
it('returns null for a string that looks like an object', () => {
expect(parseData('{}')).toBeNull();
});
it('returns null for null', () => {
expect(parseData(null as unknown as string)).toBeNull();
});
it('returns a string for b64 encoded data', () => {
const res = parseData('dGVzdCA9IHRydWU=');
expect(res).toBeNull();
});
it('returns null if the parsed object does not look like te right shape', () => {
// Encoded: {"test":true}
const res = parseData('eyJ0ZXN0Ijp0cnVlfQ==');
expect(res).toBeNull();
});
it('returns an object if the payload parses and looks fine', () => {
// Encoded: {"messages": [], "prices": {}, "signatures": [], "timestamp": "123"}
const res = parseData(
'eyJtZXNzYWdlcyI6IFtdLCAicHJpY2VzIjoge30sICJzaWduYXR1cmVzIjogW10sICJ0aW1lc3RhbXAiOiAiMTIzIn0='
);
expect(typeof res.prices).toEqual('object');
expect(Array.isArray(res.messages)).toBeTruthy();
expect(Array.isArray(res.signatures)).toBeTruthy();
});
});
@@ -1,64 +0,0 @@
import { t } from '@vegaprotocol/react-helpers';
import { NestedDataList } from '../../../nested-data-list';
import { OpenOraclePrices } from './open-oracle/open-oracle-prices';
interface OpenOracleDataProps {
payload: string;
}
/**
* Decodes Open Oracle data based on it's main parts:
* - messages
* - signatures
* - prices
*/
export const OpenOracleData = ({ payload }: OpenOracleDataProps) => {
const decodedSubmission = parseData(payload);
if (!decodedSubmission) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const date = decodedSubmission.timestamp;
const formattedDate = new Date(date * 1000).toLocaleString();
return (
<section>
<span>{formattedDate}</span>
<code>
<OpenOraclePrices
prices={decodedSubmission.prices}
messages={decodedSubmission.messages}
signatures={decodedSubmission.signatures}
/>
</code>
<details data-testid="decoded-payload">
<summary>{t('Decoded payload')}</summary>
<NestedDataList data={decodedSubmission} />
</details>
</section>
);
};
/**
* Safely parses the Open Oracle payload
*
* @param payload base64 encoded JSON
* @returns Object or null
*/
export function parseData(payload: string) {
try {
if (!payload || typeof payload !== 'string') {
throw new Error('Not a string');
}
const res = JSON.parse(atob(payload));
if (!res.prices || !res.messages || !res.signatures) {
throw new Error('Not an open oracle format message');
}
return res;
} catch (e) {
return null;
}
}
@@ -1,88 +0,0 @@
import { render } from '@testing-library/react';
import { OpenOraclePrices } from './open-oracle-prices';
import type { Price } from './open-oracle-prices';
describe('OpenOraclePrices', () => {
it('Will not render with no prices', () => {
const p = undefined as unknown as Price;
const m: string[] = [];
const s: string[] = [];
const screen = render(
<OpenOraclePrices prices={p} messages={m} signatures={s} />
);
expect(screen.container).toBeEmptyDOMElement();
});
it('Will not render with no messages', () => {
const m = undefined as unknown as string[];
const p: Price = {};
const s: string[] = [];
const screen = render(
<OpenOraclePrices prices={p} messages={m} signatures={s} />
);
expect(screen.container).toBeEmptyDOMElement();
});
it('will not render with no signatures', () => {
const s = undefined as unknown as string[];
const m: string[] = [];
const p: Price = {};
const screen = render(
<OpenOraclePrices prices={p} messages={m} signatures={s} />
);
expect(screen.container).toBeEmptyDOMElement();
});
it('will not render with mismatched prices/signatures', () => {
const p: Price = { ETH: '123' };
const m = ['0x123', '0x456'];
const s: string[] = [];
const screen = render(
<OpenOraclePrices prices={p} messages={m} signatures={s} />
);
expect(screen.container).toBeEmptyDOMElement();
});
it('will not render with mismatched signatures and messages', () => {
const p: Price = { ETH: '123', BTC: '12' };
const s = ['0xcac', '0xb33f'];
const m = ['0x1204o42c', '0xb3ddd3f', '0x9999'];
const screen = render(
<OpenOraclePrices prices={p} messages={m} signatures={s} />
);
expect(screen.container).toBeEmptyDOMElement();
});
it('renders a table when there are prices and signatures and messages', () => {
const p: Price = { ETH: '123', BTC: '12' };
const s = ['0xcac', '0xb33f'];
const m = ['0x120442c', '0xb3ddd3f'];
const screen = render(
<OpenOraclePrices prices={p} messages={m} signatures={s} />
);
expect(screen.getByTestId('openoracleprices')).toBeInTheDocument();
// Table headings
expect(screen.getByText('Asset')).toBeInTheDocument();
expect(screen.getByText('Price')).toBeInTheDocument();
expect(screen.getByText('Signature')).toBeInTheDocument();
expect(screen.getByText('Message')).toBeInTheDocument();
// Disabled - see vegaprotocol/frontend-monorepo#/2726
// expect(screen.getByText('Signer')).toBeInTheDocument();
// One row per asset
expect(screen.getByText('ETH')).toBeInTheDocument();
expect(screen.getByText('123')).toBeInTheDocument();
expect(screen.getByText('0xcac')).toBeInTheDocument();
expect(screen.getByText('0xb33f')).toBeInTheDocument();
// Does not test signer element for this row
expect(screen.getByText('BTC')).toBeInTheDocument();
expect(screen.getByText('12')).toBeInTheDocument();
expect(screen.getByText('0x120442c')).toBeInTheDocument();
expect(screen.getByText('0xb3ddd3f')).toBeInTheDocument();
// Does not test signer element for this row
});
});
@@ -1,132 +0,0 @@
import { t } from '@vegaprotocol/react-helpers';
import { CopyWithTooltip } from '@vegaprotocol/ui-toolkit';
import { TableRow } from '../../../../table';
import { TruncateInline } from '../../../../truncate/truncate';
import { utils } from 'ethers';
export type Price = {
[key: string]: string;
};
interface OpenOraclePricesProps {
prices: Price;
signatures: string[];
messages: string[];
}
/**
* Open Oracle price table, showing the entries in this
* decoded message
*
* Notes:
* - Signer is derived by recovering the address from the
* signature and the message. This is currently disabled
* as the implementation is incorrect
*/
export function OpenOraclePrices({
prices,
messages,
signatures,
}: OpenOraclePricesProps) {
if (
!prices ||
!messages ||
!signatures ||
Object.keys(prices).length !== messages.length ||
signatures.length !== messages.length
) {
return null;
}
return (
<table data-testid="openoracleprices">
<thead>
<TableRow modifier="bordered">
<th>{t('Asset')}</th>
<th className="text-right">{t('Price')}</th>
<th>{t('Signature')}</th>
<th>{t('Message')}</th>
{/* <th>{t('Signer')}</th> */}
</TableRow>
</thead>
<tbody>
{Object.keys(prices).map((k: string, i: number) => {
if (k && prices[k]) {
const message = messages[i];
const signature = signatures[i];
return (
<OpenOraclePrice
key={`price-${i}`}
asset={k}
value={prices[k]}
message={message}
signature={signature}
/>
);
} else {
return null;
}
})}
</tbody>
</table>
);
}
type OpenOraclePriceProps = {
asset: string;
value: string;
message: string;
signature: string;
};
export function OpenOraclePrice({
asset,
value,
signature,
message,
}: OpenOraclePriceProps) {
// const addr = getAddressFromMessageAndSignature(message, signature);
return (
<TableRow modifier="bordered" key={`${asset}`}>
<td className="px-4">{asset}</td>
<td className="px-4 text-right">{value}</td>
<td className="px-4">
<CopyWithTooltip text={signature}>
<button>
<TruncateInline text={signature} startChars={5} endChars={5} />
</button>
</CopyWithTooltip>
</td>
<td className="px-4">
<CopyWithTooltip text={message}>
<button>
<TruncateInline text={message} startChars={5} endChars={5} />
</button>
</CopyWithTooltip>
</td>
{/*<td className="px-4">
<CopyWithTooltip text={message}>
<button>
<TruncateInline text={addr} startChars={5} endChars={5} />
</button>
</CopyWithTooltip>
</td> */}
</TableRow>
);
}
export function getAddressFromMessageAndSignature(
message: string,
signature: string
) {
try {
const m = utils.hashMessage(utils.arrayify(utils.keccak256(message)));
const s = utils.splitSignature(
signature.slice(0, 130) + signature.slice(-2)
);
return utils.recoverAddress(m, s);
} catch (e) {
return '-';
}
}
@@ -1,55 +0,0 @@
import { t } from '@vegaprotocol/react-helpers';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableWithTbody } from '../../table';
import type { components } from '../../../../types/explorer';
import { OpenOracleData } from './oracle-data/data-submission-open-oracle';
import { JSONOracleData } from './oracle-data/data-submission-json-oracle';
export type OracleSubmissionSource =
components['schemas']['OracleDataSubmissionOracleSource'];
interface TxDetailsDataSubmissionProps {
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
blockData: TendermintBlocksResponse | undefined;
}
/**
* Someone cancelled an order
*/
export const TxDetailsDataSubmission = ({
txData,
pubKey,
blockData,
}: TxDetailsDataSubmissionProps) => {
if (!txData || !txData.command.oracleDataSubmission) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const type: OracleSubmissionSource =
txData.command.oracleDataSubmission.source;
if (!type) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const payload = txData.command.oracleDataSubmission.payload;
return (
<>
<TableWithTbody className="mb-8">
<TxDetailsShared
txData={txData}
pubKey={pubKey}
blockData={blockData}
/>
</TableWithTbody>
{type === 'ORACLE_SOURCE_OPEN_ORACLE' ? (
<OpenOracleData payload={payload} />
) : (
<JSONOracleData payload={payload} />
)}
</>
);
};
@@ -19,7 +19,6 @@ import { TxDetailsUndelegate } from './tx-undelegation';
import { TxDetailsLiquiditySubmission } from './tx-liquidity-submission';
import { TxDetailsLiquidityAmendment } from './tx-liquidity-amend';
import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel';
import { TxDetailsDataSubmission } from './tx-data-submission';
interface TxDetailsWrapperProps {
txData: BlockExplorerTransactionResult | undefined;
@@ -83,8 +82,6 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
switch (txData.type) {
case 'Submit Order':
return TxDetailsOrder;
case 'Submit Oracle Data':
return TxDetailsDataSubmission;
case 'Cancel Order':
return TxDetailsOrderCancel;
case 'Amend Order':
@@ -27,7 +27,7 @@ export const TxDetailsLiquidityCancellation = ({
pubKey,
blockData,
}: TxDetailsLiquidityCancellationProps) => {
if (!txData || !txData.command.liquidityProvisionCancellation) {
if (!txData || !txData.command.liquidityProvisionAmendment) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
@@ -10,6 +10,7 @@ import {
formatNumberPercentage,
t,
toBigNum,
getDateTimeFormat,
} from '@vegaprotocol/react-helpers';
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
import type * as Schema from '@vegaprotocol/types';
@@ -30,7 +31,6 @@ import { HealthBar } from '../../health-bar';
import { HealthDialog } from '../../health-dialog';
import { Status } from '../../status';
import { formatDistanceToNow } from 'date-fns';
import { getExpiryDate } from '@vegaprotocol/react-helpers';
export const MarketList = () => {
const { data, error, loading } = useMarketsLiquidity();
@@ -299,20 +299,17 @@ export const MarketList = () => {
/>
<AgGridColumn
headerName={t('Closing Time')}
field="tradableInstrument.instrument.metadata.tags"
field="proposal.terms.closingDatetime"
headerTooltip={t('Closing time of the market')}
valueFormatter={({
data,
}: VegaValueFormatterParams<Market, ''>) => {
let expiry;
if (data?.tradableInstrument.instrument.metadata.tags) {
expiry = getExpiryDate(
data?.tradableInstrument.instrument.metadata.tags,
data?.marketTimestamps.close,
data?.state
);
}
return expiry ? expiry : '-';
value,
}: VegaValueFormatterParams<
Market,
'proposal.terms.closingDatetime'
>) => {
return value
? getDateTimeFormat().format(new Date(value).getTime())
: '-';
}}
/>
</Grid>
+32 -98
View File
@@ -5,7 +5,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297",
"total_removed": "0",
"locked_amount": "74258.786503446150969076",
"locked_amount": "74614.7487514014739871627",
"deposits": [
{
"amount": "86666.297",
@@ -71,7 +71,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500",
"total_removed": "0",
"locked_amount": "1727.2674374236875",
"locked_amount": "1747.860227157102",
"deposits": [
{
"amount": "2500",
@@ -450,7 +450,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "74191.034704360551619635",
"locked_amount": "74546.672181553510075935",
"deposits": [
{
"amount": "129999.45",
@@ -516,7 +516,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600",
"total_removed": "0",
"locked_amount": "37687.78451293759754",
"locked_amount": "37944.8998795027944",
"deposits": [
{
"amount": "10000",
@@ -709,7 +709,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "3201.987252663623",
"locked_amount": "3222.523623795028",
"deposits": [
{
"amount": "5000",
@@ -920,7 +920,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "97499.58",
"total_removed": "0",
"locked_amount": "15996.695460391807156518",
"locked_amount": "16345.542696388554157101",
"deposits": [
{
"amount": "97499.58",
@@ -953,7 +953,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "135173.4239508",
"total_removed": "98230.390980249184455396",
"locked_amount": "21864.72098009665615105475826",
"locked_amount": "22341.53492574140235843834708",
"deposits": [
{
"amount": "135173.4239508",
@@ -999,7 +999,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "32499.86",
"total_removed": "0",
"locked_amount": "6729.5335320322971613732",
"locked_amount": "6876.287539946593035582",
"deposits": [
{
"amount": "32499.86",
@@ -1032,7 +1032,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "10833.29",
"total_removed": "0",
"locked_amount": "2190.3978628288399953154",
"locked_amount": "2238.1648683377590511606",
"deposits": [
{
"amount": "10833.29",
@@ -1065,7 +1065,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "22749.93",
"total_removed": "0",
"locked_amount": "8188.196427781414655436",
"locked_amount": "8366.760162941752814571",
"deposits": [
{
"amount": "6500",
@@ -1203,8 +1203,8 @@
"tranche_start": "2022-11-01T00:00:00.000Z",
"tranche_end": "2023-05-01T00:00:00.000Z",
"total_added": "22500",
"total_removed": "3539.640404325",
"locked_amount": "11777.70200276243025",
"total_removed": "3338.59298265",
"locked_amount": "11964.06106123388625",
"deposits": [
{
"amount": "7500",
@@ -1228,11 +1228,6 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x63c8fb032e621103aa45aa0cba24fdedc19f9640271b6d59058b576a00862340"
},
{
"amount": "201.047421675",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xbca53bb0a17ad84f130058da0d3773b8a649ec4270702b3541d75fcbeba5899a"
},
{
"amount": "286.3317219",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -1293,12 +1288,6 @@
"tranche_id": 33,
"tx": "0x63c8fb032e621103aa45aa0cba24fdedc19f9640271b6d59058b576a00862340"
},
{
"amount": "201.047421675",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 33,
"tx": "0xbca53bb0a17ad84f130058da0d3773b8a649ec4270702b3541d75fcbeba5899a"
},
{
"amount": "286.3317219",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -1343,8 +1332,8 @@
}
],
"total_tokens": "7500",
"withdrawn_tokens": "3539.640404325",
"remaining_tokens": "3960.359595675"
"withdrawn_tokens": "3338.59298265",
"remaining_tokens": "4161.40701735"
},
{
"address": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1",
@@ -1369,7 +1358,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "928642.9598472029154",
"locked_amount": "673633.855453009978788326",
"locked_amount": "681601.673289015032543106",
"deposits": [
{
"amount": "1852091.69",
@@ -1721,7 +1710,7 @@
"tranche_end": "2023-02-01T00:00:00.000Z",
"total_added": "42500",
"total_removed": "24434.0787288",
"locked_amount": "1326.9861488526576875",
"locked_amount": "1673.2583849134443",
"deposits": [
{
"amount": "12500",
@@ -33097,7 +33086,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "441714.6865497406814",
"locked_amount": "1059642.026162241096318288545",
"locked_amount": "1071885.69354993468475576716",
"deposits": [
{
"amount": "1998.95815",
@@ -34377,8 +34366,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "545472.50137003958740452",
"locked_amount": "9057110.1748913212147136818156133914679643",
"total_removed": "544810.37930337016827952",
"locked_amount": "9100525.4333294991121317413486608148229251",
"deposits": [
{
"amount": "16249.93",
@@ -34977,11 +34966,6 @@
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
"tx": "0x7deb028bfbd706c2281d6344cca117acc153a35ad68dd9a58f3ad7867f643d37"
},
{
"amount": "662.122066669419125",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x6d913b124af23621f8b97087a51d4cd912c6a8d9cca325cb756b56d4970f3f62"
},
{
"amount": "434.254023685890375",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -36510,12 +36494,6 @@
"tranche_id": 2,
"tx": "0x2221aafeab49a64ec0b85aa53438b6c66a06eff11fee7ab0a254f33657e47aab"
},
{
"amount": "662.122066669419125",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0x6d913b124af23621f8b97087a51d4cd912c6a8d9cca325cb756b56d4970f3f62"
},
{
"amount": "434.254023685890375",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -37532,8 +37510,8 @@
}
],
"total_tokens": "259998.8875",
"withdrawn_tokens": "111222.20209807200725",
"remaining_tokens": "148776.68540192799275"
"withdrawn_tokens": "110560.080031402588125",
"remaining_tokens": "149438.807468597411875"
},
{
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
@@ -39668,8 +39646,8 @@
"tranche_start": "2021-11-05T00:00:00.000Z",
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "3706973.15022981060693393",
"locked_amount": "2640021.056974879537814880156060444",
"total_removed": "3705868.24629153380213143",
"locked_amount": "2680101.746355963103585199029496367",
"deposits": [
{
"amount": "129284.449",
@@ -39958,16 +39936,6 @@
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
"tx": "0x77247f5a8850ad76c194b1e7481ddf61b1106a3f9df35117b7e146bd70c66616"
},
{
"amount": "645.31140451891061",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0xe96d96d780f7aec7b2e42a190a91993ac93bb61d74b12ff72e87c0ee4a2e2712"
},
{
"amount": "459.5925337578941925",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0xc1e8ef457dbeb52bd2d02aefd418a9a67bd17f016c1ca6a1e80716d86ce3c132"
},
{
"amount": "12758.73908063512839093",
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
@@ -42734,18 +42702,6 @@
"tranche_id": 3,
"tx": "0x074c8b4e60fda9e8dba220410f5a5805076e763589315992ca70db527a0bc674"
},
{
"amount": "645.31140451891061",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0xe96d96d780f7aec7b2e42a190a91993ac93bb61d74b12ff72e87c0ee4a2e2712"
},
{
"amount": "459.5925337578941925",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0xc1e8ef457dbeb52bd2d02aefd418a9a67bd17f016c1ca6a1e80716d86ce3c132"
},
{
"amount": "762.7902369187144135",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -45058,8 +45014,8 @@
}
],
"total_tokens": "359123.469575",
"withdrawn_tokens": "293815.097748589450163",
"remaining_tokens": "65308.371826410549837"
"withdrawn_tokens": "292710.1938103126453605",
"remaining_tokens": "66413.2757646873546395"
},
{
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
@@ -46370,7 +46326,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303",
"total_removed": "2622261.560853924298939789",
"locked_amount": "726184.882785013826953223512050056",
"locked_amount": "742021.005565470993478249377386312",
"deposits": [
{
"amount": "552496.6455",
@@ -48265,7 +48221,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "29683.1054262326685",
"locked_amount": "167906.33621746181228223152663622",
"locked_amount": "169846.415302828370245964120040588",
"deposits": [
{
"amount": "3000",
@@ -76659,7 +76615,7 @@
"tranche_start": "2021-12-05T00:00:00.000Z",
"tranche_end": "2022-06-05T00:00:00.000Z",
"total_added": "171288.42",
"total_removed": "63646.1049690697989",
"total_removed": "63445.7249006422989",
"locked_amount": "0",
"deposits": [
{
@@ -80904,16 +80860,6 @@
"user": "0x4fD63682E3e6803e2F3805D0c40Fcb7a37c5e7c4",
"tx": "0x591b81e6f118be1436cede9763019b99a33594f029716341adb45d6710b66ca6"
},
{
"amount": "99.7195512825",
"user": "0x01a66CdA5D3212D3Ac9f9ff837eE4e4833E52895",
"tx": "0xcaab4c813b9ce156921f1a8cc3193f20d9f2b397e66e774233c13e64475b1853"
},
{
"amount": "100.660517145",
"user": "0xC343fD1a1dd3F8D5412b2bae1c3A4a0482029f63",
"tx": "0xd6c9e31ca9abc4832ba4d6345ddeefbc3ab947b9c48ad834e2002d790642db22"
},
{
"amount": "50",
"user": "0x300A831523b53112F5CF8B802D85EC48a8CB7dcC",
@@ -96566,12 +96512,6 @@
}
],
"withdrawals": [
{
"amount": "99.7195512825",
"user": "0x01a66CdA5D3212D3Ac9f9ff837eE4e4833E52895",
"tranche_id": 6,
"tx": "0xcaab4c813b9ce156921f1a8cc3193f20d9f2b397e66e774233c13e64475b1853"
},
{
"amount": "150.2804487175",
"user": "0x01a66CdA5D3212D3Ac9f9ff837eE4e4833E52895",
@@ -96580,8 +96520,8 @@
}
],
"total_tokens": "250",
"withdrawn_tokens": "250",
"remaining_tokens": "0"
"withdrawn_tokens": "150.2804487175",
"remaining_tokens": "99.7195512825"
},
{
"address": "0x6b671cfa2619790c861Fd3b4B3cb3aE5A78ee3fC",
@@ -96609,12 +96549,6 @@
}
],
"withdrawals": [
{
"amount": "100.660517145",
"user": "0xC343fD1a1dd3F8D5412b2bae1c3A4a0482029f63",
"tranche_id": 6,
"tx": "0xd6c9e31ca9abc4832ba4d6345ddeefbc3ab947b9c48ad834e2002d790642db22"
},
{
"amount": "149.339482855",
"user": "0xC343fD1a1dd3F8D5412b2bae1c3A4a0482029f63",
@@ -96623,8 +96557,8 @@
}
],
"total_tokens": "250",
"withdrawn_tokens": "250",
"remaining_tokens": "0"
"withdrawn_tokens": "149.339482855",
"remaining_tokens": "100.660517145"
},
{
"address": "0x9a25025F722305b4336CcD7E67995E691A12426E",
-1
View File
@@ -11,7 +11,6 @@ NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
#Test configuration variables
CYPRESS_FAIRGROUND=false
-1
View File
@@ -14,7 +14,6 @@ NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit suppl
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
#Test configuration variables
CYPRESS_FAIRGROUND=false
-1
View File
@@ -8,4 +8,3 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
+1 -2
View File
@@ -8,5 +8,4 @@ NX_ETHERSCAN_URL=https://etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
NX_DELEGATIONS_PAGINATION=50
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
-1
View File
@@ -8,4 +8,3 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://mirror.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_DELEGATIONS_PAGINATION=50
-1
View File
@@ -5,4 +5,3 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://sta
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
-1
View File
@@ -5,4 +5,3 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://sta
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
-1
View File
@@ -6,4 +6,3 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
-1
View File
@@ -9,4 +9,3 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
@@ -7,13 +7,13 @@ fragment WalletDelegationFields on Delegation {
epoch
}
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
query Delegations($partyId: ID!) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
...WalletDelegationFields
@@ -7,7 +7,6 @@ export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount
export type DelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -24,13 +23,13 @@ export const WalletDelegationFieldsFragmentDoc = gql`
}
`;
export const DelegationsDocument = gql`
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
query Delegations($partyId: ID!) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
...WalletDelegationFields
@@ -77,7 +76,6 @@ export const DelegationsDocument = gql`
* const { data, loading, error } = useDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
@@ -0,0 +1,92 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } };
export type DelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type DelegationsQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } } } } | null> | null } | null } | null };
export const WalletDelegationFieldsFragmentDoc = gql`
fragment WalletDelegationFields on Delegation {
amount
node {
id
name
}
epoch
}
`;
export const DelegationsDocument = gql`
query Delegations($partyId: ID!) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection {
edges {
node {
...WalletDelegationFields
}
}
}
stakingSummary {
currentStakeAvailable
}
accountsConnection {
edges {
node {
asset {
name
id
decimals
symbol
source {
__typename
... on ERC20 {
contractAddress
}
}
}
type
balance
}
}
}
}
}
${WalletDelegationFieldsFragmentDoc}`;
/**
* __useDelegationsQuery__
*
* To run a query within a React component, call `useDelegationsQuery` and pass it any options that fit your needs.
* When your component renders, `useDelegationsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useDelegationsQuery(baseOptions: Apollo.QueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
}
export function useDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
}
export type DelegationsQueryHookResult = ReturnType<typeof useDelegationsQuery>;
export type DelegationsLazyQueryHookResult = ReturnType<typeof useDelegationsLazyQuery>;
export type DelegationsQueryResult = Apollo.QueryResult<DelegationsQuery, DelegationsQueryVariables>;
+5 -13
View File
@@ -4,7 +4,6 @@ import keyBy from 'lodash/keyBy';
import uniq from 'lodash/uniq';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { ENV } from '../../config';
import noIcon from '../../images/token-no-icon.png';
import vegaBlack from '../../images/vega_black.png';
@@ -24,18 +23,18 @@ import type {
DelegationsQuery,
DelegationsQueryVariables,
WalletDelegationFieldsFragment,
} from './__generated__/Delegations';
import { DelegationsDocument } from './__generated__/Delegations';
} from './__generated___/Delegations';
import { DelegationsDocument } from './__generated___/Delegations';
export const usePollForDelegations = () => {
const { token: vegaToken } = useContracts();
const {
appState: { decimals },
} = useAppState();
const { t } = useTranslation();
const { pubKey } = useVegaWallet();
const client = useApolloClient();
const { delegationsPagination } = ENV;
const [delegations, setDelegations] = React.useState<
WalletDelegationFieldsFragment[]
>([]);
@@ -63,14 +62,7 @@ export const usePollForDelegations = () => {
client
.query<DelegationsQuery, DelegationsQueryVariables>({
query: DelegationsDocument,
variables: {
partyId: pubKey,
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
variables: { partyId: pubKey },
fetchPolicy: 'network-only',
})
.then((res) => {
@@ -215,7 +207,7 @@ export const usePollForDelegations = () => {
clearInterval(interval);
mounted = false;
};
}, [delegationsPagination, client, decimals, pubKey, t, vegaToken.address]);
}, [client, decimals, pubKey, t, vegaToken.address]);
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
};
-1
View File
@@ -64,7 +64,6 @@ export const ENV = {
docsUrl: windowOrDefault('NX_VEGA_DOCS_URL'),
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
flags: {
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
@@ -1,5 +1,5 @@
import BigNumber from 'bignumber.js';
import { create } from 'zustand';
import create from 'zustand';
import type { UserTrancheBalance } from '../../contexts/app-state/app-state-context';
export interface AssociationBreakdown {
@@ -20,24 +20,6 @@ query Proposal($proposalId: ID!) {
... on NewMarket {
decimalPlaces
metadata
lpPriceRange
riskParameters {
... on LogNormalRiskModel {
riskAversionParameter
tau
params {
mu
r
sigma
}
}
... on SimpleRiskModel {
params {
factorLong
factorShort
}
}
}
instrument {
name
code
@@ -50,7 +32,6 @@ query Proposal($proposalId: ID!) {
quantum
}
quoteName
dataSourceSpecForSettlementData {
sourceType {
... on DataSourceDefinitionInternal {
File diff suppressed because one or more lines are too long
@@ -20,7 +20,7 @@ fragment DelegationFields on Delegation {
epoch
}
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
query Rewards($partyId: ID!) {
party(id: $partyId) {
id
rewardsConnection {
@@ -30,7 +30,7 @@ query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
}
}
}
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
...DelegationFields
+3 -5
View File
@@ -9,7 +9,6 @@ export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: stri
export type RewardsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -40,7 +39,7 @@ export const DelegationFieldsFragmentDoc = gql`
}
`;
export const RewardsDocument = gql`
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
query Rewards($partyId: ID!) {
party(id: $partyId) {
id
rewardsConnection {
@@ -50,7 +49,7 @@ export const RewardsDocument = gql`
}
}
}
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
...DelegationFields
@@ -83,7 +82,6 @@ ${DelegationFieldsFragmentDoc}`;
* const { data, loading, error } = useRewardsQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
@@ -97,4 +95,4 @@ export function useRewardsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<Re
}
export type RewardsQueryHookResult = ReturnType<typeof useRewardsQuery>;
export type RewardsLazyQueryHookResult = ReturnType<typeof useRewardsLazyQuery>;
export type RewardsQueryResult = Apollo.QueryResult<RewardsQuery, RewardsQueryVariables>;
export type RewardsQueryResult = Apollo.QueryResult<RewardsQuery, RewardsQueryVariables>;
@@ -0,0 +1,98 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type RewardFieldsFragment = { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } };
export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number };
export type RewardsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardsConnection?: { __typename?: 'RewardsConnection', edges?: Array<{ __typename?: 'RewardEdge', node: { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } } | null> | null } | null, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } } };
export const RewardFieldsFragmentDoc = gql`
fragment RewardFields on Reward {
rewardType
asset {
id
symbol
}
party {
id
}
epoch {
id
}
amount
percentageOfTotal
receivedAt
}
`;
export const DelegationFieldsFragmentDoc = gql`
fragment DelegationFields on Delegation {
amount
epoch
}
`;
export const RewardsDocument = gql`
query Rewards($partyId: ID!) {
party(id: $partyId) {
id
rewardsConnection {
edges {
node {
...RewardFields
}
}
}
delegationsConnection {
edges {
node {
...DelegationFields
}
}
}
}
epoch {
id
timestamps {
start
end
expiry
}
}
}
${RewardFieldsFragmentDoc}
${DelegationFieldsFragmentDoc}`;
/**
* __useRewardsQuery__
*
* To run a query within a React component, call `useRewardsQuery` and pass it any options that fit your needs.
* When your component renders, `useRewardsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useRewardsQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useRewardsQuery(baseOptions: Apollo.QueryHookOptions<RewardsQuery, RewardsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<RewardsQuery, RewardsQueryVariables>(RewardsDocument, options);
}
export function useRewardsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<RewardsQuery, RewardsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<RewardsQuery, RewardsQueryVariables>(RewardsDocument, options);
}
export type RewardsQueryHookResult = ReturnType<typeof useRewardsQuery>;
export type RewardsLazyQueryHookResult = ReturnType<typeof useRewardsLazyQuery>;
export type RewardsQueryResult = Apollo.QueryResult<RewardsQuery, RewardsQueryVariables>;
@@ -9,7 +9,7 @@ import type {
RewardsQuery,
RewardFieldsFragment,
DelegationFieldsFragment,
} from './__generated__/Rewards';
} from './__generated___/Rewards';
import {
formatNumber,
removePaginationWrapper,
@@ -4,7 +4,6 @@ import { formatDistance } from 'date-fns';
import Duration from 'duration-js';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { ENV } from '../../../config';
import { EpochCountdown } from '../../../components/epoch-countdown';
import { Heading } from '../../../components/heading';
@@ -16,7 +15,7 @@ import {
import { RewardInfo } from './reward-info';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { useNetworkParams, NetworkParams } from '@vegaprotocol/react-helpers';
import { useRewardsQuery } from './__generated__/Rewards';
import { useRewardsQuery } from './__generated___/Rewards';
export const RewardsPage = () => {
const { t } = useTranslation();
@@ -25,16 +24,8 @@ export const RewardsPage = () => {
openVegaWalletDialog: store.openVegaWalletDialog,
}));
const { appDispatch } = useAppState();
const { delegationsPagination } = ENV;
const { data, loading, error } = useRewardsQuery({
variables: {
partyId: pubKey || '',
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const { params } = useNetworkParams([
@@ -6,10 +6,10 @@ fragment StakingDelegationsFields on Delegation {
epoch
}
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
query PartyDelegations($partyId: ID!) {
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
...StakingDelegationsFields
@@ -23,13 +23,13 @@ fragment StakingNodeFields on Node {
}
}
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
query Staking($partyId: ID!) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
amount
@@ -7,7 +7,6 @@ export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amou
export type PartyDelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -23,10 +22,10 @@ export const StakingDelegationsFieldsFragmentDoc = gql`
}
`;
export const PartyDelegationsDocument = gql`
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
query PartyDelegations($partyId: ID!) {
party(id: $partyId) {
id
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
...StakingDelegationsFields
@@ -53,7 +52,6 @@ export const PartyDelegationsDocument = gql`
* const { data, loading, error } = usePartyDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
+2 -4
View File
@@ -7,7 +7,6 @@ export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name:
export type StakingQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -40,13 +39,13 @@ export const StakingNodeFieldsFragmentDoc = gql`
}
`;
export const StakingDocument = gql`
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
query Staking($partyId: ID!) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
delegationsConnection(pagination: $delegationsPagination) {
delegationsConnection {
edges {
node {
amount
@@ -95,7 +94,6 @@ export const StakingDocument = gql`
* const { data, loading, error } = useStakingQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
@@ -0,0 +1,68 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } };
export type PartyDelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PartyDelegationsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string } };
export const StakingDelegationsFieldsFragmentDoc = gql`
fragment StakingDelegationsFields on Delegation {
amount
node {
id
}
epoch
}
`;
export const PartyDelegationsDocument = gql`
query PartyDelegations($partyId: ID!) {
party(id: $partyId) {
id
delegationsConnection {
edges {
node {
...StakingDelegationsFields
}
}
}
}
epoch {
id
}
}
${StakingDelegationsFieldsFragmentDoc}`;
/**
* __usePartyDelegationsQuery__
*
* To run a query within a React component, call `usePartyDelegationsQuery` and pass it any options that fit your needs.
* When your component renders, `usePartyDelegationsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = usePartyDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function usePartyDelegationsQuery(baseOptions: Apollo.QueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
}
export function usePartyDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
}
export type PartyDelegationsQueryHookResult = ReturnType<typeof usePartyDelegationsQuery>;
export type PartyDelegationsLazyQueryHookResult = ReturnType<typeof usePartyDelegationsLazyQuery>;
export type PartyDelegationsQueryResult = Apollo.QueryResult<PartyDelegationsQuery, PartyDelegationsQueryVariables>;
@@ -0,0 +1,110 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } };
export type StakingQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type StakingQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string, totalNodes: number, inactiveNodes: number, uptime: number } | null };
export const StakingNodeFieldsFragmentDoc = gql`
fragment StakingNodeFields on Node {
id
name
pubkey
infoUrl
location
ethereumAddress
stakedByOperator
stakedByDelegates
stakedTotal
pendingStake
epochData {
total
offline
online
}
rankingScore {
rankingScore
stakeScore
performanceScore
votingPower
status
}
}
`;
export const StakingDocument = gql`
query Staking($partyId: ID!) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
delegationsConnection {
edges {
node {
amount
epoch
node {
id
}
}
}
}
}
epoch {
id
timestamps {
start
end
expiry
}
}
nodesConnection {
edges {
node {
...StakingNodeFields
}
}
}
nodeData {
stakedTotal
totalNodes
inactiveNodes
uptime
}
}
${StakingNodeFieldsFragmentDoc}`;
/**
* __useStakingQuery__
*
* To run a query within a React component, call `useStakingQuery` and pass it any options that fit your needs.
* When your component renders, `useStakingQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useStakingQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useStakingQuery(baseOptions: Apollo.QueryHookOptions<StakingQuery, StakingQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
}
export function useStakingLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StakingQuery, StakingQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
}
export type StakingQueryHookResult = ReturnType<typeof useStakingQuery>;
export type StakingLazyQueryHookResult = ReturnType<typeof useStakingLazyQuery>;
export type StakingQueryResult = Apollo.QueryResult<StakingQuery, StakingQueryVariables>;
+1 -1
View File
@@ -20,7 +20,7 @@ import NodeContainer from './nodes-container';
import { useAppState } from '../../../contexts/app-state/app-state-context';
import { Heading, SubHeading } from '../../../components/heading';
import Routes from '../../routes';
import type { StakingQuery } from './__generated__/Staking';
import type { StakingQuery } from './__generated___/Staking';
import type { PreviousEpochQuery } from '../__generated___/PreviousEpoch';
interface StakingNodeProps {
@@ -1,14 +1,14 @@
import { ENV } from '../../../config';
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useRefreshValidators } from '../../../hooks/use-refresh-validators';
import { useStakingQuery } from './__generated___/Staking';
import { SplashLoader } from '../../../components/splash-loader';
import { useStakingQuery } from './__generated__/Staking';
import { usePreviousEpochQuery } from '../__generated___/PreviousEpoch';
import type { ReactElement } from 'react';
import type { StakingQuery } from './__generated__/Staking';
import type { StakingQuery } from './__generated___/Staking';
import type { PreviousEpochQuery } from '../__generated___/PreviousEpoch';
import { useRefreshValidators } from '../../../hooks/use-refresh-validators';
// TODO should only request a single node. When migrating from deprecated APIs we should address this.
@@ -23,20 +23,12 @@ export const NodeContainer = ({
}: {
data?: StakingQuery;
previousEpochData?: PreviousEpochQuery;
}) => ReactElement;
}) => React.ReactElement;
}) => {
const { t } = useTranslation();
const { pubKey } = useVegaWallet();
const { delegationsPagination } = ENV;
const { data, loading, error, refetch } = useStakingQuery({
variables: {
partyId: pubKey || '',
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
variables: { partyId: pubKey || '' },
});
const { data: previousEpochData } = usePreviousEpochQuery({
variables: {
@@ -3,8 +3,7 @@ import * as Sentry from '@sentry/react';
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { ENV } from '../../../config';
import { usePartyDelegationsLazyQuery } from './__generated__/PartyDelegations';
import { usePartyDelegationsLazyQuery } from './__generated___/PartyDelegations';
import { TokenInput } from '../../../components/token-input';
import { useAppState } from '../../../contexts/app-state/app-state-context';
import { useSearchParams } from '../../../hooks/use-search-params';
@@ -74,7 +73,6 @@ export const StakingForm = ({
const [error, setError] = useState<Error | null>(null);
const [isDialogVisible, setIsDialogVisible] = useState(false);
const { t } = useTranslation();
const { delegationsPagination } = ENV;
const [action, setAction] = React.useState<StakeAction>(
params.action as StakeAction
);
@@ -149,11 +147,6 @@ export const StakingForm = ({
const [delegationSearch, { data }] = usePartyDelegationsLazyQuery({
variables: {
partyId: pubKey,
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
fetchPolicy: 'network-only',
});
@@ -25,7 +25,7 @@ import {
getUnnormalisedVotingPower,
} from '../shared';
import type { ReactNode } from 'react';
import type { StakingNodeFieldsFragment } from './__generated__/Staking';
import type { StakingNodeFieldsFragment } from './__generated___/Staking';
import type { PreviousEpochQuery } from '../__generated___/PreviousEpoch';
const statuses = {
+1 -1
View File
@@ -1,6 +1,6 @@
import type ethers from 'ethers';
import type { GetState, SetState } from 'zustand';
import { create } from 'zustand';
import create from 'zustand';
export interface TxData {
tx: ethers.ContractTransaction;
@@ -1,13 +1,10 @@
import { connectEthereumWallet } from '../support/ethereum-wallet';
import { selectAsset } from '../support/helpers';
const assetSelectField = 'select[name="asset"]';
const toAddressField = 'input[name="to"]';
const amountField = 'input[name="amount"]';
const formFieldError = 'input-error-text';
const ASSET_EURO = 1;
describe('deposit form validation', { tags: '@smoke' }, () => {
before(() => {
cy.mockWeb3Provider();
@@ -46,8 +43,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
it('invalid amount', () => {
// Deposit amount smaller than minimum viable for selected asset
// Select an amount so that we have a known decimal places value to work with
selectAsset(ASSET_EURO);
cy.get(assetSelectField).select('Euro');
cy.get(amountField)
.clear()
.type('0.00000000000000000000000000000000001')
@@ -161,14 +161,6 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
);
});
it('liquidity price range displayed', () => {
cy.getByTestId(marketTitle).contains('Liquidity price range').click();
validateMarketDataRow(0, 'Liquidity Price Range', '2.00%');
validateMarketDataRow(1, 'LP Volume Min', '0.05634 tBTC');
validateMarketDataRow(2, 'LP Volume Max', '0.05864 tBTC');
});
it('oracle displayed', () => {
cy.getByTestId(marketTitle).contains('Oracle').click();
@@ -1,15 +1,14 @@
import { connectEthereumWallet } from '../support/ethereum-wallet';
import { selectAsset } from '../support/helpers';
const formFieldError = 'input-error-text';
const toAddressField = 'input[name="to"]';
const assetSelectField = 'select[name="asset"]';
const amountField = 'input[name="amount"]';
const useMaximumAmount = 'use-maximum';
const submitWithdrawBtn = 'submit-withdrawal';
const ethAddressValue = Cypress.env('ETHEREUM_WALLET_ADDRESS');
const ASSET_SEPOLIA_TBTC = 2;
const ASSET_EURO = 1;
const asset1Name = 'Sepolia tBTC';
const asset2Name = 'Euro';
describe('withdraw form validation', { tags: '@smoke' }, () => {
before(() => {
@@ -41,7 +40,7 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
cy.get(toAddressField).should('have.value', ethAddressValue);
});
it('min amount', () => {
selectAsset(ASSET_SEPOLIA_TBTC);
selectAsset(asset1Name);
cy.get(amountField).clear().type('0');
cy.getByTestId(submitWithdrawBtn).click();
cy.get('[data-testid="input-error-text"]').should(
@@ -50,7 +49,7 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
);
});
it('max amount', () => {
selectAsset(ASSET_EURO); // Will be above maximum because the vega wallet doesn't have any collateral
selectAsset(asset2Name); // Will be above maximum because the vega wallet doesn't have any collateral
cy.get(amountField).clear().type('1001', { delay: 100 });
cy.getByTestId(submitWithdrawBtn).click();
cy.get('[data-testid="input-error-text"]').should(
@@ -60,7 +59,7 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
});
it('can set amount using use maximum button', () => {
selectAsset(ASSET_SEPOLIA_TBTC);
selectAsset(asset1Name);
cy.getByTestId(useMaximumAmount).click();
cy.get(amountField).should('have.value', '1000.00000');
});
@@ -88,7 +87,7 @@ describe('withdraw actions', { tags: '@regression' }, () => {
});
it('triggers transaction when submitted', () => {
selectAsset(ASSET_SEPOLIA_TBTC);
selectAsset(asset1Name);
cy.getByTestId('BALANCE_AVAILABLE_label').should(
'contain.text',
'Balance available'
@@ -112,3 +111,12 @@ describe('withdraw actions', { tags: '@regression' }, () => {
it.skip('creates a withdrawal on submit'); // Needs capsule
it.skip('creates a withdrawal on submit and prompts to complete withdrawal'); // Needs capsule
});
const selectAsset = (assetName: string) => {
cy.get(assetSelectField).select(assetName);
// The asset only gets set once the queries (getWithdrawThreshold, getDelay)
// against the Ethereum change resolve, we should fix this but for now just force
// some wait time
// eslint-disable-next-line
cy.wait(100);
};
-11
View File
@@ -1,11 +0,0 @@
export const selectAsset = (assetIndex: number) => {
cy.log(`selecting asset: ${assetIndex}`);
cy.getByTestId('select-asset').click();
cy.get('[data-testid="rich-select-option"]').eq(assetIndex).click();
// The asset only gets set once the queries (getWithdrawThreshold, getDelay)
// against the Ethereum change resolve, we should fix this but for now just force
// some wait time
// eslint-disable-next-line
cy.wait(100);
};
+3
View File
@@ -8,3 +8,6 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
@@ -2,11 +2,8 @@ import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
import { MarketProposalNotification } from '@vegaprotocol/governance';
import {
getExpiryDate,
getMarketExpiryDate,
t,
} from '@vegaprotocol/react-helpers';
import { getExpiryDate, getMarketExpiryDate } from '@vegaprotocol/market-info';
import { t } from '@vegaprotocol/react-helpers';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
import {
ColumnKind,
@@ -128,14 +125,7 @@ type ExpiryLabelProps = {
};
const ExpiryLabel = ({ market }: ExpiryLabelProps) => {
const content =
market && market.tradableInstrument.instrument.metadata.tags
? getExpiryDate(
market.tradableInstrument.instrument.metadata.tags,
market.marketTimestamps.close,
market.state
)
: '-';
const content = market ? getExpiryDate(market) : '-';
return <div data-testid="trading-expiry">{content}</div>;
};
@@ -139,19 +139,16 @@ const AccountHistoryManager = ({
<div className="h-full w-full flex flex-col gap-8">
<div className="w-full flex flex-col-reverse lg:flex-row items-start lg:items-center justify-between gap-4 px-2">
<div className="flex items-center gap-4 shrink-0">
<DropdownMenu
trigger={
<DropdownMenuTrigger>
{accountType
? `${
AccountTypeMapping[
accountType as keyof typeof Schema.AccountType
]
} Account`
: t('Select account type')}
</DropdownMenuTrigger>
}
>
<DropdownMenu>
<DropdownMenuTrigger>
{accountType
? `${
AccountTypeMapping[
accountType as keyof typeof Schema.AccountType
]
} Account`
: t('Select account type')}
</DropdownMenuTrigger>
<DropdownMenuContent>
{[
Schema.AccountType.ACCOUNT_TYPE_GENERAL,
@@ -167,13 +164,10 @@ const AccountHistoryManager = ({
))}
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
{asset ? asset.symbol : t('Select asset')}
</DropdownMenuTrigger>
}
>
<DropdownMenu>
<DropdownMenuTrigger>
{asset ? asset.symbol : t('Select asset')}
</DropdownMenuTrigger>
<DropdownMenuContent>
{assets.map((a) => (
<DropdownMenuItem key={a.id} onClick={() => setAsset(a)}>
+2 -2
View File
@@ -43,8 +43,8 @@ export const HeaderStat = ({
testId?: string;
}) => {
const itemClass =
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-default text-neutral-500 dark:text-neutral-400';
const itemHeading = 'text-black dark:text-white';
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-default';
const itemHeading = 'text-neutral-500 dark:text-neutral-400';
return (
<div data-testid={testId} className={itemClass}>
@@ -3,7 +3,6 @@ import { VegaWalletContext } from '@vegaprotocol/wallet';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletConnectButton } from './vega-wallet-connect-button';
import { truncateByChars } from '@vegaprotocol/react-helpers';
import userEvent from '@testing-library/user-event';
const mockUpdateDialogOpen = jest.fn();
jest.mock('@vegaprotocol/wallet', () => ({
@@ -32,7 +31,7 @@ it('Not connected', () => {
expect(mockUpdateDialogOpen).toHaveBeenCalled();
});
it('Connected', async () => {
it('Connected', () => {
const pubKey = { publicKey: '123456__123456', name: 'test' };
render(
generateJsx({
@@ -43,6 +42,6 @@ it('Connected', async () => {
const button = screen.getByTestId('manage-vega-wallet');
expect(button).toHaveTextContent(truncateByChars(pubKey.publicKey));
userEvent.click(button);
fireEvent.click(button);
expect(mockUpdateDialogOpen).not.toHaveBeenCalled();
});
@@ -142,21 +142,15 @@ export const VegaWalletConnectButton = () => {
return (
<>
<div className="hidden lg:block">
<DropdownMenu
open={dropdownOpen}
trigger={
<DropdownMenuTrigger
data-testid="manage-vega-wallet"
onClick={() => setDropdownOpen((curr) => !curr)}
>
{activeKey && (
<span className="uppercase">{activeKey.name}</span>
)}
{': '}
{truncateByChars(pubKey)}
</DropdownMenuTrigger>
}
>
<DropdownMenu open={dropdownOpen}>
<DropdownMenuTrigger
data-testid="manage-vega-wallet"
onClick={() => setDropdownOpen((curr) => !curr)}
>
{activeKey && <span className="uppercase">{activeKey.name}</span>}
{': '}
{truncateByChars(pubKey)}
</DropdownMenuTrigger>
<DropdownMenuContent
onInteractOutside={() => setDropdownOpen(false)}
>
@@ -1,4 +1,3 @@
import type { ReactNode } from 'react';
import { useAssetsDataProvider } from '@vegaprotocol/assets';
import { ETHERSCAN_TX, useEtherscanLink } from '@vegaprotocol/environment';
import { formatNumber, t, toBigNum } from '@vegaprotocol/react-helpers';
@@ -19,59 +18,60 @@ const intentMap: { [s in EthTxStatus]: Intent } = {
Requested: Intent.Warning,
Pending: Intent.Warning,
Error: Intent.Danger,
Complete: Intent.Warning,
Complete: Intent.Success,
Confirmed: Intent.Success,
};
const isWithdrawTransaction = (tx: EthStoredTxState) =>
tx.methodName === 'withdraw_asset';
const isDepositTransaction = (tx: EthStoredTxState) =>
tx.methodName === 'withdraw_asset';
const EthTransactionDetails = ({ tx }: { tx: EthStoredTxState }) => {
const { data: assets } = useAssetsDataProvider();
if (!assets) return null;
const { data } = useAssetsDataProvider();
if (!data) return null;
const isWithdraw = isWithdrawTransaction(tx);
const isDeposit = isDepositTransaction(tx);
const ETH_WITHDRAW =
tx.methodName === 'withdraw_asset' && tx.args.length > 2 && tx.assetId;
const ETH_DEPOSIT =
tx.methodName === 'deposit_asset' && tx.args.length > 2 && tx.assetId;
let label = '';
if (ETH_WITHDRAW) label = t('Withdraw');
if (ETH_DEPOSIT) label = t('Deposit');
if (ETH_WITHDRAW || ETH_DEPOSIT) {
const asset = data.find((a) => a.id === tx.assetId);
let assetInfo: ReactNode;
if ((isWithdraw || isDeposit) && tx.args.length > 2 && tx.assetId) {
const asset = assets.find((a) => a.id === tx.assetId);
if (asset) {
let label = '';
if (isWithdraw) label = t('Withdraw');
if (isDeposit) label = t('Deposit');
assetInfo = (
const num = formatNumber(
toBigNum(tx.args[1], asset.decimals),
asset.decimals
);
const details = (
<div className="mt-[5px]">
<span className="font-mono text-xs p-1 bg-gray-100 rounded">
{label}{' '}
{formatNumber(toBigNum(tx.args[1], asset.decimals), asset.decimals)}{' '}
{asset.symbol}
{label} {num} {asset.symbol}
</span>
</div>
);
return (
<>
{details}
{tx.requiresConfirmation &&
[EthTxStatus.Pending].includes(tx.status) && (
<div className="mt-[10px]">
<span className="font-mono text-xs">
{t('Awaiting confirmations')}{' '}
{`(${tx.confirmations}/${tx.requiredConfirmations})`}
</span>
<ProgressBar
value={(tx.confirmations / tx.requiredConfirmations) * 100}
intent={Intent.Warning}
/>
</div>
)}
</>
);
}
}
return (
<>
{assetInfo}
{tx.status === EthTxStatus.Pending && (
<div className="mt-[10px]">
<span className="font-mono text-xs">
{t('Awaiting confirmations')}{' '}
{`(${tx.confirmations}/${tx.requiredConfirmations})`}
</span>
<ProgressBar
value={(tx.confirmations / tx.requiredConfirmations) * 100}
intent={Intent.Warning}
/>
</div>
)}
</>
);
return null;
};
type EthTxToastContentProps = {
@@ -93,11 +93,21 @@ const EthTxRequestedToastContent = ({ tx }: EthTxToastContentProps) => {
};
const EthTxPendingToastContent = ({ tx }: EthTxToastContentProps) => {
const etherscanLink = useEtherscanLink();
return (
<div>
<h3 className="font-bold">{t('Awaiting confirmation')}</h3>
<p>{t('Please wait for your transaction to be confirmed')}</p>
<EtherscanLink tx={tx} />
{tx.txHash && (
<p className="break-all">
<ExternalLink
href={etherscanLink(ETHERSCAN_TX.replace(':hash', tx.txHash))}
rel="noreferrer"
>
{t('View on Etherscan')}
</ExternalLink>
</p>
)}
<EthTransactionDetails tx={tx} />
</div>
);
@@ -120,43 +130,22 @@ const EthTxErrorToastContent = ({ tx }: EthTxToastContentProps) => {
);
};
const EtherscanLink = ({ tx }: EthTxToastContentProps) => {
const etherscanLink = useEtherscanLink();
return tx.txHash ? (
<p className="break-all">
<ExternalLink
href={etherscanLink(ETHERSCAN_TX.replace(':hash', tx.txHash))}
rel="noreferrer"
>
{t('View on Etherscan')}
</ExternalLink>
</p>
) : null;
};
const EthTxConfirmedToastContent = ({ tx }: EthTxToastContentProps) => {
const etherscanLink = useEtherscanLink();
return (
<div>
<h3 className="font-bold">{t('Transaction confirmed')}</h3>
<p>{t('Your transaction has been confirmed')}</p>
<EtherscanLink tx={tx} />
<EthTransactionDetails tx={tx} />
</div>
);
};
const EthTxCompletedToastContent = ({ tx }: EthTxToastContentProps) => {
const isDeposit = isDepositTransaction(tx);
return (
<div>
<h3 className="font-bold">
{t('Processing')} {isDeposit && 'deposit'}
</h3>
<p>
{t('Your transaction has been completed.')}
{isDeposit && t('Waiting for deposit confirmation')}
</p>
<EtherscanLink tx={tx} />
<h3 className="font-bold">{t('Transaction completed')}</h3>
<p>{t('Your transaction has been completed')}</p>
{tx.txHash && (
<p className="break-all">
<ExternalLink
href={etherscanLink(ETHERSCAN_TX.replace(':hash', tx.txHash))}
rel="noreferrer"
>
{t('View on Etherscan')}
</ExternalLink>
</p>
)}
<EthTransactionDetails tx={tx} />
</div>
);
@@ -178,10 +167,10 @@ export const useEthereumTransactionToasts = () => {
if (tx.status === EthTxStatus.Pending) {
content = <EthTxPendingToastContent tx={tx} />;
}
if (tx.status === EthTxStatus.Complete) {
content = <EthTxCompletedToastContent tx={tx} />;
}
if (tx.status === EthTxStatus.Confirmed) {
if (
tx.status === EthTxStatus.Confirmed ||
tx.status === EthTxStatus.Complete
) {
content = <EthTxConfirmedToastContent tx={tx} />;
}
if (tx.status === EthTxStatus.Error) {
@@ -192,7 +181,7 @@ export const useEthereumTransactionToasts = () => {
id: `eth-${tx.id}`,
intent: intentMap[tx.status],
onClose: () => dismissEthTransaction(tx.id),
loader: [EthTxStatus.Pending, EthTxStatus.Complete].includes(tx.status),
loader: tx.status === EthTxStatus.Pending,
content,
};
},
@@ -95,7 +95,7 @@ const Details = ({
title?: string;
}) => (
<div className="pt-[5px]" data-testid="vega-tx-details" title={title}>
<div className="font-mono text-xs p-2 bg-neutral-100 rounded dark:bg-neutral-700 dark:text-white">
<div className="font-mono text-xs p-2 bg-neutral-100 rounded">
{children}
</div>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
import { LocalStorage } from '@vegaprotocol/react-helpers';
import { create } from 'zustand';
import create from 'zustand';
import produce from 'immer';
interface GlobalStore {
@@ -9,23 +9,26 @@ export const useMarketAccountBalance = (marketId: string) => {
const { pubKey } = useVegaWallet();
const [accountBalance, setAccountBalance] = useState<string>('');
const [accountDecimals, setAccountDecimals] = useState<number | null>(null);
const variables = useMemo(() => {
return { partyId: pubKey || '' };
}, [pubKey]);
const update = useCallback(
({ data }: { data: Account[] | null }) => {
const account = getMarketAccount({ accounts: data, marketId });
if (account?.balance) {
if (accountBalance !== account?.balance) {
setAccountBalance(account?.balance || '');
}
if (account?.asset.decimals) {
if (accountDecimals !== account?.asset.decimals) {
setAccountDecimals(account?.asset.decimals || null);
}
return true;
},
[marketId]
[accountBalance, accountDecimals, marketId]
);
useDataProvider({
dataProvider: accountsDataProvider,
variables: { partyId: pubKey || '' },
variables,
skip: !pubKey || !marketId,
update,
});
+2 -3
View File
@@ -14,7 +14,6 @@ import { onError } from '@apollo/client/link/error';
import { RetryLink } from '@apollo/client/link/retry';
import ApolloLinkTimeout from 'apollo-link-timeout';
import type { GraphQLErrors } from '@apollo/client/errors';
import { localLoggerFactory } from '@vegaprotocol/react-helpers';
const isBrowser = typeof window !== 'undefined';
@@ -69,12 +68,12 @@ export function createClient(base?: string, cacheConfig?: InMemoryCacheConfig) {
if (graphQLErrors) {
graphQLErrors.forEach((e) => {
if (e.extensions && e.extensions['type'] !== NOT_FOUND) {
localLoggerFactory({ application: 'apollo-client' }).error(e);
console.log(e);
}
});
}
if (networkError) {
localLoggerFactory({ application: 'apollo-client' }).error(networkError);
console.log(networkError);
}
});
+1 -1
View File
@@ -1,7 +1,7 @@
import { t } from '@vegaprotocol/react-helpers';
import { useAssetsDataProvider } from './assets-data-provider';
import { Button, Dialog, Icon, Splash } from '@vegaprotocol/ui-toolkit';
import { create } from 'zustand';
import create from 'zustand';
import { AssetDetailsTable } from './asset-details-table';
import { AssetProposalNotification } from '@vegaprotocol/governance';
+12 -20
View File
@@ -60,13 +60,10 @@ export const CandlesChartContainer = ({
return (
<div className="h-full flex flex-col">
<div className="px-4 py-2 flex flex-row flex-wrap gap-4">
<DropdownMenu
trigger={
<DropdownMenuTrigger>
{t(`Interval: ${intervalLabels[interval]}`)}
</DropdownMenuTrigger>
}
>
<DropdownMenu>
<DropdownMenuTrigger>
{t(`Interval: ${intervalLabels[interval]}`)}
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuRadioGroup
value={interval}
@@ -87,13 +84,10 @@ export const CandlesChartContainer = ({
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
<Icon name={chartTypeIcon.get(chartType) as IconName} />
</DropdownMenuTrigger>
}
>
<DropdownMenu>
<DropdownMenuTrigger>
<Icon name={chartTypeIcon.get(chartType) as IconName} />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuRadioGroup
value={chartType}
@@ -110,9 +104,8 @@ export const CandlesChartContainer = ({
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu
trigger={<DropdownMenuTrigger>{t('Overlays')}</DropdownMenuTrigger>}
>
<DropdownMenu>
<DropdownMenuTrigger>{t('Overlays')}</DropdownMenuTrigger>
<DropdownMenuContent>
{Object.values(Overlay).map((overlay) => (
<DropdownMenuCheckboxItem
@@ -135,9 +128,8 @@ export const CandlesChartContainer = ({
))}
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu
trigger={<DropdownMenuTrigger>{t('Studies')}</DropdownMenuTrigger>}
>
<DropdownMenu>
<DropdownMenuTrigger>{t('Studies')}</DropdownMenuTrigger>
<DropdownMenuContent>
{Object.values(Study).map((study) => (
<DropdownMenuCheckboxItem
@@ -0,0 +1,181 @@
import {
StakingBridge,
Token,
TokenVesting,
TokenFaucetable,
CollateralBridge,
} from '@vegaprotocol/smart-contracts';
import { ethers, Wallet } from 'ethers';
const vegaWalletContainer = '[data-testid="vega-wallet"]';
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
const vegaTokenAddress = Cypress.env('vegaTokenAddress');
const ethWalletPubKey = Cypress.env('ethWalletPublicKey');
const ethStakingBridgeContractAddress = Cypress.env(
'ethStakingBridgeContractAddress'
);
const ethProviderUrl = Cypress.env('ethProviderUrl');
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;
const transactionTimeout = '90000';
const Erc20BridgeAddress = '0x9708FF7510D4A7B9541e1699d15b53Ecb1AFDc54';
before('Vega wallet teardown prep', function () {
cy.wrap(new ethers.providers.JsonRpcProvider({ url: ethProviderUrl }), {
log: false,
}).as('provider');
cy.wrap(Wallet.fromMnemonic(vegaWalletMnemonic, getAccount(0)).privateKey, {
log: false,
}).then((privateKey) => {
cy.wrap(new Wallet(privateKey, this.provider), { log: false }).as('signer');
});
cy.get('@signer', { log: false }).then((signer) => {
cy.wrap(new StakingBridge(ethStakingBridgeContractAddress, signer), {
log: false,
}).as('stakingBridgeContract');
cy.wrap(new TokenVesting(vegaTokenContractAddress, signer), {
log: false,
}).as('vestingContract');
});
});
Cypress.Commands.add('deposit_asset', function (assetEthAddress) {
cy.get('@signer', { log: false }).then((signer) => {
// Approve asset
cy.wrap(
new TokenFaucetable(assetEthAddress, signer).approve(
Erc20BridgeAddress,
'10000000000'
)
)
.then((tx) => {
cy.wait_for_transaction(tx);
})
.then(() => {
cy.wrap(new CollateralBridge(Erc20BridgeAddress, signer), {
log: false,
}).then((bridge) => {
// Deposit asset into vega wallet
cy.wrap(
bridge.deposit_asset(
assetEthAddress,
'1000000000',
'0x' + vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
).then((tx) => {
cy.wait_for_transaction(tx);
});
});
});
});
});
Cypress.Commands.add('faucet_asset', function (assetEthAddress) {
cy.get('@signer', { log: false }).then((signer) => {
cy.wrap(new TokenFaucetable(assetEthAddress, signer), { log: false }).then(
(token) => {
cy.wrap(token.faucet(), {
timeout: transactionTimeout,
log: false,
}).then((tx) => {
cy.wait_for_transaction(tx);
});
}
);
});
});
Cypress.Commands.add('vega_wallet_teardown', function () {
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance)
.first()
.invoke('text')
.then((balance) => {
if (balance != '0.00') {
cy.vega_wallet_teardown_vesting(this.vestingContract);
cy.vega_wallet_teardown_staking(this.stakingBridgeContract);
}
});
cy.get('[data-testid="associated-amount"]', { timeout: 30000 }).should(
'contain.text',
'0.00'
);
});
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance, { timeout: transactionTimeout }).should(
'contain',
'0.00',
{ timeout: transactionTimeout }
);
});
});
Cypress.Commands.add(
'vega_wallet_set_specified_approval_amount',
function (resetAmount) {
cy.highlight(`Setting token approval amount to ${resetAmount}`);
cy.wrap(new Token(vegaTokenAddress, this.signer), { log: false }).then(
(token) => {
cy.wrap(
token.approve(
ethStakingBridgeContractAddress,
resetAmount.concat('000000000000000000')
),
{ timeout: transactionTimeout, log: false }
).then((tx) => {
cy.wait_for_transaction(tx);
});
}
);
}
);
Cypress.Commands.add(
'vega_wallet_teardown_staking',
(stakingBridgeContract) => {
cy.highlight('Tearing down staking tokens from vega wallet if present');
cy.wrap(
stakingBridgeContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
{
timeout: transactionTimeout,
log: false,
}
).then((stake_amount) => {
if (String(stake_amount) != '0') {
cy.wrap(
stakingBridgeContract.remove_stake(stake_amount, vegaWalletPubKey),
{ timeout: transactionTimeout, log: false }
).then((tx) => {
cy.wait_for_transaction(tx);
});
}
});
}
);
Cypress.Commands.add('vega_wallet_teardown_vesting', (vestingContract) => {
cy.highlight('Tearing down vesting tokens from vega wallet if present');
cy.wrap(vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey), {
timeout: transactionTimeout,
log: false,
}).then((vesting_amount) => {
if (String(vesting_amount) != '0') {
cy.wrap(vestingContract.remove_stake(vesting_amount, vegaWalletPubKey), {
timeout: transactionTimeout,
log: false,
}).then((tx) => {
cy.wait_for_transaction(tx);
});
}
});
});
Cypress.Commands.add('wait_for_transaction', (tx) => {
cy.wrap(tx.wait(1).catch(cy.log), { timeout: transactionTimeout });
});
@@ -15,6 +15,7 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
import { InputError } from '@vegaprotocol/ui-toolkit';
import { useOrderMarginValidation } from '../../hooks/use-order-margin-validation';
import { MarginWarning } from '../deal-ticket-validation/margin-warning';
import { usePersistedOrderStore } from '../../hooks/use-persisted-order';
import {
getDefaultOrder,
validateMarketState,
@@ -26,10 +27,6 @@ import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error';
import { SummaryValidationType } from '../../constants';
import { useHasNoBalance } from '../../hooks/use-has-no-balance';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import {
usePersistedOrderStore,
usePersistedOrderStoreSubscription,
} from '@vegaprotocol/orders';
export type TransactionStatus = 'default' | 'pending';
@@ -46,13 +43,13 @@ export type DealTicketFormFields = OrderSubmissionBody['orderSubmission'] & {
export const DealTicket = ({ market, submit }: DealTicketProps) => {
const { pubKey } = useVegaWallet();
// const [persistedOrder, setPersistedOrder] = usePersistedOrder(market);
const { getPersistedOrder, setPersistedOrder } = usePersistedOrderStore(
(store) => ({
getPersistedOrder: store.getOrder,
setPersistedOrder: store.setOrder,
})
);
const {
register,
control,
@@ -61,23 +58,11 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
setError,
clearErrors,
formState: { errors },
setValue,
} = useForm<DealTicketFormFields>({
defaultValues: getPersistedOrder(market.id) || getDefaultOrder(market),
});
const order = watch();
watch((orderData) => {
setPersistedOrder(orderData as DealTicketFormFields);
});
usePersistedOrderStoreSubscription(market.id, (storedOrder) => {
if (order.price !== storedOrder.price) {
setValue('price', storedOrder.price);
}
});
const marketStateError = validateMarketState(market.data.marketState);
const hasNoBalance = useHasNoBalance(
market.tradableInstrument.instrument.product.settlementAsset.id
@@ -105,6 +90,9 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
errors.summary?.type,
]);
// When order state changes persist it in local storage
useEffect(() => setPersistedOrder(order), [order, setPersistedOrder]);
const onSubmit = useCallback(
(order: OrderSubmissionBody['orderSubmission']) => {
if (!pubKey) {
@@ -0,0 +1,43 @@
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import produce from 'immer';
import create from 'zustand';
import { persist } from 'zustand/middleware';
type OrderData = OrderSubmissionBody['orderSubmission'] | null;
type PersistedOrderStore = {
orders: OrderData[];
getOrder: (marketId: string) => OrderData | undefined;
setOrder: (order: OrderData) => void;
clear: () => void;
};
export const usePersistedOrderStore = create(
persist<PersistedOrderStore>(
(set, get) => ({
orders: [],
getOrder: (marketId) => {
const persisted = get().orders.find((o) => o?.marketId === marketId);
return persisted;
},
setOrder: (order) => {
set(
produce((store: PersistedOrderStore) => {
const persisted = store.orders.find(
(o) => o?.marketId === order?.marketId
);
if (persisted) {
Object.assign(persisted, order);
} else {
store.orders.push(order);
}
})
);
},
clear: () => set({ orders: [] }),
}),
{
name: 'VEGA_DEAL_TICKET_ORDER_STORE',
}
)
);
+1 -1
View File
@@ -1,4 +1,4 @@
import { create } from 'zustand';
import create from 'zustand';
import { t } from '@vegaprotocol/react-helpers';
import type { Intent } from '@vegaprotocol/ui-toolkit';
import { Dialog } from '@vegaprotocol/ui-toolkit';
+13 -21
View File
@@ -16,8 +16,7 @@ import {
Icon,
Input,
InputError,
RichSelect,
Option,
Select,
} from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useWeb3React } from '@web3-react/core';
@@ -172,29 +171,22 @@ export const DepositForm = ({
},
}}
render={({ field }) => (
<RichSelect
data-testid="select-asset"
id={field.name}
name={field.name}
onValueChange={(value) => {
onSelectAsset(value);
field.onChange(value);
<Select
id="asset"
{...field}
onChange={(e) => {
field.onChange(e);
onSelectAsset(e.target.value);
}}
placeholder={t('Please select an asset')}
value={selectedAsset?.id}
hasError={Boolean(errors.asset?.message)}
value={selectedAsset?.id || ''}
>
<option value="">{t('Please select')}</option>
{assets.filter(isAssetTypeERC20).map((a) => (
<Option key={a.id} value={a.id}>
<div className="flex flex-col items-start">
<span>{a.name}</span>
<span className="text-[10px] font-mono">
<span className="text-gray-500">{a.id} -</span> {a.symbol}
</span>
</div>
</Option>
<option key={a.id} value={a.id}>
{a.name}
</option>
))}
</RichSelect>
</Select>
)}
/>
{errors.asset?.message && (
@@ -96,18 +96,13 @@ export const NetworkSwitcher = () => {
const menuRef = useRef<HTMLButtonElement | null>(null);
return (
<DropdownMenu
open={isOpen}
onOpenChange={handleOpen}
trigger={
<DropdownMenuTrigger
ref={menuRef}
className="flex justify-between items-center"
>
{envTriggerMapping[VEGA_ENV]}
</DropdownMenuTrigger>
}
>
<DropdownMenu open={isOpen} onOpenChange={handleOpen}>
<DropdownMenuTrigger
ref={menuRef}
className="flex justify-between items-center"
>
{envTriggerMapping[VEGA_ENV]}
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
style={{ minWidth: `${menuRef.current?.offsetWidth || 290}px` }}
@@ -31,6 +31,8 @@ import {
getTargetStake,
} from './utils/liquidity-utils';
import type { Provider, LiquidityProvisionMarket } from './utils';
import { proposalsListDataProvider } from '@vegaprotocol/governance';
import type { Proposal } from '@vegaprotocol/types';
export interface FeeLevels {
commitmentAmount: number;
@@ -44,13 +46,7 @@ export type Market = MarketWithData &
dayVolume: string;
liquidityCommitted: number;
volumeChange: string;
tradableInstrument?: {
instrument?: {
metadata?: {
tags?: string[] | null;
};
};
};
proposal?: Proposal;
};
export interface Markets {
@@ -70,7 +66,8 @@ const getData = (
export const addData = (
markets: (MarketWithData & MarketWithCandles)[],
marketsCandles24hAgo: MarketCandles[],
marketsLiquidity: LiquidityProvisionMarket[]
marketsLiquidity: LiquidityProvisionMarket[],
proposals: Proposal[]
) => {
return markets.map((market) => {
const dayVolume = calcDayVolume(market.candles);
@@ -83,6 +80,9 @@ export const addData = (
marketsLiquidity
) as Provider[];
const proposalForMarket =
proposals && proposals.find((p) => p.id === market.id);
return {
...market,
dayVolume,
@@ -90,6 +90,7 @@ export const addData = (
liquidityCommitted: sumLiquidityCommitted(liquidityProviders),
feeLevels: getFeeLevels(liquidityProviders) || [],
target: getTargetStake(market.id, marketsLiquidity),
proposal: proposalForMarket,
};
});
};
@@ -113,12 +114,14 @@ const liquidityProvisionProvider = makeDerivedDataProvider<Markets, never>(
interval: Schema.Interval.INTERVAL_I1D,
}),
liquidityMarketsProvider,
proposalsListDataProvider,
],
(parts) => {
const data = addData(
parts[0] as (MarketWithData & MarketWithCandles)[],
parts[1] as MarketCandles[],
parts[2] as LiquidityProvisionMarket[]
parts[2] as LiquidityProvisionMarket[],
parts[3] as Proposal[]
);
return { markets: data };
}
@@ -56,6 +56,7 @@ describe('market depth provider update', () => {
];
expect(update(data, delta.slice(0, 1), reload)).toBe(data);
expect(update(data, delta.slice(1, 2), reload)).toBe(data);
expect(mockCaptureException).toBeCalledTimes(2);
});
it('restarts and captureException when there is gap in updates', () => {
@@ -24,6 +24,11 @@ export const update: Update<
continue;
}
if (BigInt(delta.sequenceNumber) <= BigInt(data.depth.sequenceNumber)) {
captureException(
new Error(
`Sequence number from delta is lower or equal to last sequenceNumber for ${data.id}, ${delta.sequenceNumber} <= ${data.depth.sequenceNumber}, update skipped`
)
);
return data;
}
if (delta.previousSequenceNumber !== data.depth.sequenceNumber) {
@@ -1,7 +1,7 @@
import throttle from 'lodash/throttle';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { Orderbook } from './orderbook';
import { addDecimal, useDataProvider } from '@vegaprotocol/react-helpers';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { marketDepthProvider } from './market-depth-provider';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import type { MarketData } from '@vegaprotocol/market-list';
@@ -16,7 +16,6 @@ import {
mapMarketData,
} from './orderbook-data';
import type { OrderbookData } from './orderbook-data';
import { usePersistedOrderStore } from '@vegaprotocol/orders';
interface OrderbookManagerProps {
marketId: string;
@@ -123,7 +122,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
marketDataRef.current = marketData;
useEffect(() => {
const throttleRunner = updateOrderbookData.current;
const throttleRunnner = updateOrderbookData.current;
if (!marketDataRef.current) {
return;
}
@@ -140,7 +139,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
setOrderbookData(dataRef.current);
return () => {
throttleRunner.cancel();
throttleRunnner.cancel();
};
}, [data, marketData, resolution]);
@@ -149,8 +148,6 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
flush();
}, [resolution, flush]);
const updatePrice = usePersistedOrderStore((store) => store.updatePrice);
return (
<AsyncRenderer
loading={loading || marketDataLoading || marketLoading}
@@ -163,12 +160,6 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
positionDecimalPlaces={market?.positionDecimalPlaces ?? 0}
resolution={resolution}
onResolutionChange={(resolution: number) => setResolution(resolution)}
onClick={(price?: string | number) => {
if (price) {
const priceValue = addDecimal(price, market?.decimalPlaces ?? 0);
updatePrice(marketId, priceValue);
}
}}
/>
</AsyncRenderer>
);
@@ -21,7 +21,6 @@ interface OrderbookRowProps {
price: string;
relativeAsk?: number;
relativeBid?: number;
onClick?: (price?: string | number) => void;
}
export const OrderbookRow = React.memo(
@@ -38,7 +37,6 @@ export const OrderbookRow = React.memo(
price,
relativeAsk,
relativeBid,
onClick,
}: OrderbookRowProps) => {
return (
<>
@@ -59,7 +57,6 @@ export const OrderbookRow = React.memo(
<PriceCell
testId={`price-${price}`}
value={BigInt(price)}
onClick={() => onClick && onClick(price)}
valueFormatted={addDecimalsFormatNumber(price, decimalPlaces)}
/>
<CumulativeVol
+11 -13
View File
@@ -22,7 +22,7 @@ import {
import * as Schema from '@vegaprotocol/types';
import { OrderbookRow } from './orderbook-row';
import { createRow, getPriceLevel } from './orderbook-data';
import { Checkbox, Icon, Splash } from '@vegaprotocol/ui-toolkit';
import { Icon, Splash } from '@vegaprotocol/ui-toolkit';
import type { OrderbookData, OrderbookRowData } from './orderbook-data';
interface OrderbookProps extends OrderbookData {
@@ -30,7 +30,6 @@ interface OrderbookProps extends OrderbookData {
positionDecimalPlaces: number;
resolution: number;
onResolutionChange: (resolution: number) => void;
onClick?: (price?: string | number) => void;
fillGaps?: boolean;
}
@@ -280,7 +279,6 @@ export const Orderbook = ({
resolution,
fillGaps: initialFillGaps,
onResolutionChange,
onClick,
}: OrderbookProps) => {
const { theme } = useThemeSwitcher();
const scrollElement = useRef<HTMLDivElement>(null);
@@ -535,7 +533,6 @@ export const Orderbook = ({
<OrderbookRow
key={data.price}
price={(BigInt(data.price) / BigInt(resolution)).toString()}
onClick={onClick}
decimalPlaces={decimalPlaces - Math.log10(resolution)}
positionDecimalPlaces={positionDecimalPlaces}
bid={data.bid}
@@ -638,18 +635,19 @@ export const Orderbook = ({
</div>
<div
className="absolute bottom-0 grid grid-cols-4 gap-2 border-t-[1px] border-default mt-2 z-10 bg-white dark:bg-black w-full"
style={{ gridAutoRows: '20px' }}
style={{ gridAutoRows: '17px' }}
ref={footerElement}
>
<div className="col-span-2">
<Checkbox
name="empty-prices"
checked={fillGaps}
onCheckedChange={() => setFillGaps((curr) => !curr)}
label={
<span className="text-xs">{t('Show prices with no orders')}</span>
}
/>
<label className="flex items-center whitespace-nowrap overflow-hidden text-ellipsis">
<input
className="mr-1"
type="checkbox"
checked={fillGaps}
onChange={() => setFillGaps(!fillGaps)}
/>
{t('Show prices with no orders')}
</label>
</div>
<div className="col-start-3">
<select
+1
View File
@@ -1,2 +1,3 @@
export * from './market-expires';
export * from './market-info';
export * from './fees-breakdown';
@@ -0,0 +1 @@
export * from './market-expires';
@@ -3,7 +3,8 @@ import React from 'react';
import { MarketExpires } from './market-expires';
jest.mock('./format', () => ({
jest.mock('@vegaprotocol/react-helpers', () => ({
t: jest.fn().mockImplementation((text) => text),
getDateTimeFormat: () =>
Intl.DateTimeFormat('en-GB', {
year: 'numeric',
@@ -15,10 +16,6 @@ jest.mock('./format', () => ({
}),
}));
jest.mock('./i18n', () => ({
t: jest.fn().mockImplementation((text) => text),
}));
describe('MarketExpires', () => {
describe('should properly parse different tags', () => {
it('settlement:date', () => {
@@ -1,7 +1,7 @@
import { t } from './i18n';
import { getDateTimeFormat } from './format';
import { getDateTimeFormat, t } from '@vegaprotocol/react-helpers';
import { isValid, parseISO } from 'date-fns';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
import { MarketState } from '@vegaprotocol/types';
export const getMarketExpiryDate = (
@@ -36,13 +36,12 @@ export const getMarketExpiryDateFormatted = (
return null;
};
export const getExpiryDate = (
tags: ReadonlyArray<string> | null,
close: string | null,
state: MarketState
): string => {
const metadataExpiryDate = getMarketExpiryDate(tags);
const marketTimestampCloseDate = close && new Date(close);
export const getExpiryDate = (market: SingleMarketFieldsFragment): string => {
const metadataExpiryDate = getMarketExpiryDate(
market.tradableInstrument.instrument.metadata.tags
);
const marketTimestampCloseDate =
market.marketTimestamps.close && new Date(market.marketTimestamps.close);
let content = null;
if (!metadataExpiryDate) {
content = marketTimestampCloseDate
@@ -51,8 +50,8 @@ export const getExpiryDate = (
} else {
const isExpired =
Date.now() - metadataExpiryDate.valueOf() > 0 &&
(state === MarketState.STATE_TRADING_TERMINATED ||
state === MarketState.STATE_SETTLED);
(market.state === MarketState.STATE_TRADING_TERMINATED ||
market.state === MarketState.STATE_SETTLED);
if (isExpired) {
content = marketTimestampCloseDate
? `Expired on ${getDateTimeFormat().format(marketTimestampCloseDate)}`
@@ -5,7 +5,6 @@ query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
positionDecimalPlaces
state
tradingMode
lpPriceRange
proposal {
id
rationale {
@@ -59,7 +58,6 @@ query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
id
}
markPrice
midPrice
bestBidVolume
bestOfferVolume
bestStaticBidVolume
@@ -10,7 +10,7 @@ export type MarketInfoQueryVariables = Types.Exact<{
}>;
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, data?: { __typename?: 'MarketData', markPrice: string, midPrice: string, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, bestBidPrice: string, bestOfferPrice: string, trigger: Types.AuctionTrigger, openInterest: string, suppliedStake?: string | null, targetStake?: string | null, marketValueProxy: string, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, candlesConnection?: { __typename?: 'CandleDataConnection', edges?: Array<{ __typename?: 'CandleEdge', node: { __typename?: 'Candle', volume: string } } | null> | null } | null, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, data?: { __typename?: 'MarketData', markPrice: string, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, bestBidPrice: string, bestOfferPrice: string, trigger: Types.AuctionTrigger, openInterest: string, suppliedStake?: string | null, targetStake?: string | null, marketValueProxy: string, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, candlesConnection?: { __typename?: 'CandleDataConnection', edges?: Array<{ __typename?: 'CandleEdge', node: { __typename?: 'Candle', volume: string } } | null> | null } | null, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
export const MarketInfoDocument = gql`
@@ -21,7 +21,6 @@ export const MarketInfoDocument = gql`
positionDecimalPlaces
state
tradingMode
lpPriceRange
proposal {
id
rationale {
@@ -75,7 +74,6 @@ export const MarketInfoDocument = gql`
id
}
markPrice
midPrice
bestBidVolume
bestOfferVolume
bestStaticBidVolume
@@ -2,9 +2,7 @@ import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import { totalFeesPercentage } from '@vegaprotocol/market-list';
import {
addDecimalsFormatNumber,
formatNumber,
formatNumberPercentage,
removePaginationWrapper,
t,
useDataProvider,
@@ -23,12 +21,10 @@ import pick from 'lodash/pick';
import { useMemo } from 'react';
import { generatePath, Link } from 'react-router-dom';
import { getMarketExpiryDateFormatted } from '../market-expires';
import { MarketInfoTable } from './info-key-value-table';
import { marketInfoDataProvider } from './market-info-data-provider';
import {
TokenLinks,
getMarketExpiryDateFormatted,
} from '@vegaprotocol/react-helpers';
import { TokenLinks } from '@vegaprotocol/react-helpers';
import type { MarketInfoQuery } from './__generated__/MarketInfo';
import { MarketProposalNotification } from '@vegaprotocol/governance';
@@ -186,9 +182,6 @@ export const Info = ({ market, onSelect }: InfoProps) => {
state: Schema.MarketStateMapping[market.state],
};
const assetDecimals =
market.tradableInstrument.instrument.product.settlementAsset.decimals;
const marketSpecPanels = [
{
title: t('Key details'),
@@ -202,7 +195,9 @@ export const Info = ({ market, onSelect }: InfoProps) => {
Schema.MarketTradingModeMapping[keyDetails.tradingMode],
marketDecimalPlaces: market.decimalPlaces,
positionDecimalPlaces: market.positionDecimalPlaces,
settlementAssetDecimalPlaces: assetDecimals,
settlementAssetDecimalPlaces:
market.tradableInstrument.instrument.product.settlementAsset
.decimals,
}}
/>
),
@@ -300,7 +295,10 @@ export const Info = ({ market, onSelect }: InfoProps) => {
/>
<MarketInfoTable
data={{ referencePrice: trigger.referencePrice }}
decimalPlaces={assetDecimals}
decimalPlaces={
market?.tradableInstrument.instrument.product?.settlementAsset
.decimals
}
/>
</>
),
@@ -326,7 +324,10 @@ export const Info = ({ market, onSelect }: InfoProps) => {
suppliedStake: market.data && market.data?.suppliedStake,
marketValueProxy: market.data && market.data.marketValueProxy,
}}
decimalPlaces={assetDecimals}
decimalPlaces={
market.tradableInstrument.instrument.product.settlementAsset
.decimals
}
assetSymbol={assetSymbol}
>
<Link
@@ -339,36 +340,6 @@ export const Info = ({ market, onSelect }: InfoProps) => {
</MarketInfoTable>
),
},
{
title: t('Liquidity price range'),
content: (
<MarketInfoTable
data={{
liquidityPriceRange: formatNumberPercentage(
new BigNumber(market.lpPriceRange).times(100)
),
LPVolumeMin:
market.data?.midPrice &&
`${addDecimalsFormatNumber(
new BigNumber(1)
.minus(market.lpPriceRange)
.times(market.data.midPrice)
.toString(),
market.decimalPlaces
)} ${assetSymbol}`,
LPVolumeMax:
market.data?.midPrice &&
`${addDecimalsFormatNumber(
new BigNumber(1)
.plus(market.lpPriceRange)
.times(market.data.midPrice)
.toString(),
market.decimalPlaces
)} ${assetSymbol}`,
}}
></MarketInfoTable>
),
},
{
title: t('Oracle'),
content: (
@@ -398,7 +369,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
content: (
<div className="">
<ExternalLink
className="mb-2 w-full"
className="mb-2"
href={generatePath(TokenLinks.PROPOSAL_PAGE, {
tokenUrl: VEGA_TOKEN_URL,
proposalId: market.proposal?.id || '',
@@ -412,7 +383,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
{t('View governance proposal')}
</ExternalLink>
<ExternalLink
className="w-full"
className="mt-2"
href={generatePath(TokenLinks.UPDATE_PROPOSAL_PAGE, {
tokenUrl: VEGA_TOKEN_URL,
})}
@@ -92,14 +92,12 @@ export const marketInfoQuery = (
short: '0.008571790367285281',
long: '0.008508132993273576',
},
lpPriceRange: '0.02',
data: {
__typename: 'MarketData',
market: {
__typename: 'Market',
id: '54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
},
midPrice: '5749',
markPrice: '5749',
suppliedStake: '56767',
marketValueProxy: '677678',
@@ -98,7 +98,4 @@ export const tooltipMapping: Record<string, ReactNode> = {
`The market's liquidity requirement which is derived from the maximum open interest observed over a rolling time window.`
),
suppliedStake: t('The current amount of liquidity supplied for this market.'),
liquidityPriceRange: t(
`Percentage move up and down from the mid price, which specifies the range of price levels over which automated liquidity provision orders will be deployed.`
),
};
@@ -245,7 +245,7 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
colId="amend"
headerName=""
field="status"
minWidth={100}
minWidth={150}
type="rightAligned"
cellRenderer={({ data, node }: VegaICellRendererParams<Order>) => {
return data && isOrderAmendable(data) ? (
-1
View File
@@ -4,4 +4,3 @@ export * from './use-order-cancel';
export * from './use-order-submit';
export * from './use-order-edit';
export * from './use-order-event';
export * from './use-persisted-order';
@@ -1,78 +0,0 @@
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import produce from 'immer';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
import isEqual from 'lodash/isEqual';
import { useEffect } from 'react';
type OrderData = OrderSubmissionBody['orderSubmission'] | null;
type PersistedOrderStore = {
orders: OrderData[];
getOrder: (marketId: string) => OrderData | undefined;
setOrder: (order: OrderData) => void;
clear: () => void;
updatePrice: (marketId: string, price: string) => void;
};
export const usePersistedOrderStore = create<PersistedOrderStore>()(
persist(
subscribeWithSelector((set, get) => ({
orders: [],
getOrder: (marketId: string) => {
const current = get() as PersistedOrderStore;
const persisted = current.orders.find((o) => o?.marketId === marketId);
return persisted;
},
setOrder: (order: OrderData) => {
set(
produce((store: PersistedOrderStore) => {
const persisted = store.orders.find(
(o) => o?.marketId === order?.marketId
);
if (persisted) {
if (!isEqual(persisted, order)) {
Object.assign(persisted, order);
} else {
// NOOP
}
} else {
store.orders.push(order);
}
})
);
},
clear: () => set({ orders: [] }),
updatePrice: (marketId: string, price: string) =>
set(
produce((store: PersistedOrderStore) => {
const persisted = store.orders.find(
(o) => o?.marketId === marketId
);
if (persisted) {
persisted.price = price;
}
})
),
})),
{
name: 'VEGA_DEAL_TICKET_ORDER_STORE',
}
)
);
export const usePersistedOrderStoreSubscription = (
marketId: string,
onOrderChange: (order: NonNullable<OrderData>) => void
) => {
const selector = (state: PersistedOrderStore) =>
state.orders.find((o) => o?.marketId === marketId);
const action = (storedOrder: OrderData | undefined) => {
if (storedOrder) {
onOrderChange(storedOrder);
}
};
const unsubscribe = usePersistedOrderStore.subscribe(selector, action);
useEffect(() => () => unsubscribe(), [unsubscribe]);
};
+7 -4
View File
@@ -1,4 +1,4 @@
import { useCallback, useState } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { marginsDataProvider } from './margin-data-provider';
@@ -22,16 +22,19 @@ const getMarketMarginPosition = ({
export const useMarketMargin = (marketId: string) => {
const { pubKey } = useVegaWallet();
const [marginLevel, setMarginLevel] = useState<string>('');
const variables = useMemo(() => {
return { partyId: pubKey || '' };
}, [pubKey]);
const update = useCallback(
({ data }: { data: MarginsQuery['party'] | null }) => {
const marginMarketPosition = getMarketMarginPosition({ data, marketId });
if (marginMarketPosition?.maintenanceLevel) {
if (marginLevel !== marginMarketPosition?.maintenanceLevel) {
setMarginLevel(marginMarketPosition?.maintenanceLevel || '');
}
return true;
},
[setMarginLevel, marketId]
[marginLevel, setMarginLevel, marketId]
);
useDataProvider<
@@ -39,7 +42,7 @@ export const useMarketMargin = (marketId: string) => {
MarginsSubscriptionSubscription['margins']
>({
dataProvider: marginsDataProvider,
variables: { partyId: pubKey || '' },
variables,
skip: !pubKey || !marketId,
update,
});
@@ -1,4 +1,4 @@
import { useCallback, useState } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { positionsDataProvider } from './positions-data-providers';
import { useDataProvider } from '@vegaprotocol/react-helpers';
@@ -22,15 +22,18 @@ const getMarketPosition = ({
export const useMarketPositionOpenVolume = (marketId: string) => {
const { pubKey } = useVegaWallet();
const [openVolume, setOpenVolume] = useState<string>('');
const variables = useMemo(() => {
return { partyId: pubKey || '' };
}, [pubKey]);
const update = useCallback(
({ data }: { data: PositionsQuery['party'] | undefined }) => {
const position = getMarketPosition({ data, marketId });
if (position?.openVolume) {
if (openVolume !== position?.openVolume) {
setOpenVolume(position?.openVolume || '');
}
return true;
},
[setOpenVolume, marketId]
[openVolume, setOpenVolume, marketId]
);
useDataProvider<
@@ -38,7 +41,7 @@ export const useMarketPositionOpenVolume = (marketId: string) => {
PositionsSubscriptionSubscription['positions']
>({
dataProvider: positionsDataProvider,
variables: { partyId: pubKey || '' },
variables,
skip: !pubKey || !marketId,
update,
});
-1
View File
@@ -12,4 +12,3 @@ export * from './use-theme-switcher';
export * from './use-storybook-theme-observer';
export * from './use-yesterday';
export * from './use-previous';
export * from './use-logger';
@@ -1,27 +0,0 @@
import { useRef } from 'react';
import { BrowserTracing } from '@sentry/tracing';
import * as Sentry from '@sentry/browser';
import type { LocalLogger } from '../lib/local-logger';
import { localLoggerFactory } from '../lib/local-logger';
interface Props {
dsn?: string;
application?: string;
tags?: string[];
}
export const useLogger = ({ dsn, ...props }: Props) => {
const logger = useRef<LocalLogger | null>(null);
if (!logger.current) {
logger.current = localLoggerFactory(props);
if (dsn) {
Sentry.init({
dsn,
integrations: [new BrowserTracing()],
tracesSampleRate: 1,
defaultIntegrations: false,
});
}
}
return logger.current;
};
@@ -1,4 +1,4 @@
import { create } from 'zustand';
import create from 'zustand';
import { LocalStorage } from '../lib/storage';
const THEME_STORAGE_KEY = 'theme';
-2
View File
@@ -16,5 +16,3 @@ export * from './lib/is-asset-erc20';
export * from './lib/remove-pagination-wrapper';
export * from './lib/__generated__/ChainId';
export * from './lib/data-grid';
export * from './lib/local-logger';
export * from './lib/market-expires';
+2 -21
View File
@@ -4,12 +4,11 @@ export interface IPriceCellProps {
value: number | bigint | null | undefined;
valueFormatted: string;
testId?: string;
onClick?: (price?: string | number) => void;
}
export const PriceCell = memo(
forwardRef<HTMLSpanElement, IPriceCellProps>(
({ value, valueFormatted, testId, onClick }: IPriceCellProps, ref) => {
({ value, valueFormatted, testId }: IPriceCellProps, ref) => {
if (!isNumeric(value)) {
return (
<span data-testid="price" ref={ref}>
@@ -21,25 +20,7 @@ export const PriceCell = memo(
const valueSplit: string[] = decimalSeparator
? valueFormatted.split(decimalSeparator).map((v) => `${v}`)
: [`${value}`];
return onClick ? (
<button
onClick={() => onClick(value)}
className="hover:dark:bg-neutral-800 hover:bg-neutral-200"
>
<span
ref={ref}
className="font-mono relative text-black dark:text-white whitespace-nowrap overflow-hidden text-ellipsis text-right rtl-dir"
data-testid={testId || 'price'}
title={valueFormatted}
>
{valueSplit[0]}
{valueSplit[1] ? decimalSeparator : null}
{valueSplit[1] ? (
<span className="opacity-60">{valueSplit[1]}</span>
) : null}
</span>
</button>
) : (
return (
<span
ref={ref}
className="font-mono relative text-black dark:text-white whitespace-nowrap overflow-hidden text-ellipsis text-right rtl-dir"

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