Merge branch 'master' of github.com:vegaprotocol/frontend-monorepo
This commit is contained in:
commit
e6eda21a33
@ -5,12 +5,14 @@ Feature: Transactions Page
|
|||||||
When I navigate to the transactions page
|
When I navigate to the transactions page
|
||||||
Then transactions page is correctly displayed
|
Then transactions page is correctly displayed
|
||||||
|
|
||||||
|
@ignore
|
||||||
Scenario: Navigate to transaction details page
|
Scenario: Navigate to transaction details page
|
||||||
Given I am on the homepage
|
Given I am on the homepage
|
||||||
When I navigate to the transactions page
|
When I navigate to the transactions page
|
||||||
And I click on the top transaction
|
And I click on the top transaction
|
||||||
Then transaction details are displayed
|
Then transaction details are displayed
|
||||||
|
|
||||||
|
@ignore
|
||||||
Scenario: Navigate to transactions page using mobile
|
Scenario: Navigate to transactions page using mobile
|
||||||
Given I am on mobile and open the toggle menu
|
Given I am on mobile and open the toggle menu
|
||||||
When I navigate to the transactions page
|
When I navigate to the transactions page
|
||||||
|
@ -36,7 +36,12 @@ export const JumpTo = ({
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
className="max-w-[200px]"
|
className="max-w-[200px]"
|
||||||
/>
|
/>
|
||||||
<Button data-testid="go-submit" variant="secondary" type="submit">
|
<Button
|
||||||
|
data-testid="go-submit"
|
||||||
|
variant="secondary"
|
||||||
|
boxShadow={false}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
{t('Go')}
|
{t('Go')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,7 +75,12 @@ export const Search = () => {
|
|||||||
</InputError>
|
</InputError>
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<Button type="submit" variant="secondary" data-testid="search-button">
|
<Button
|
||||||
|
type="submit"
|
||||||
|
boxShadow={false}
|
||||||
|
variant="secondary"
|
||||||
|
data-testid="search-button"
|
||||||
|
>
|
||||||
{t('Search')}
|
{t('Search')}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -7,7 +7,6 @@ import { DealTicketSteps } from './deal-ticket-steps';
|
|||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { gql, useQuery } from '@apollo/client';
|
import { gql, useQuery } from '@apollo/client';
|
||||||
import { DealTicketBalance } from './deal-ticket-balance';
|
import { DealTicketBalance } from './deal-ticket-balance';
|
||||||
import * as React from 'react';
|
|
||||||
import type { PartyBalanceQuery } from './__generated__/PartyBalanceQuery';
|
import type { PartyBalanceQuery } from './__generated__/PartyBalanceQuery';
|
||||||
|
|
||||||
const tempEmptyText = <p>Please select a market from the markets page</p>;
|
const tempEmptyText = <p>Please select a market from the markets page</p>;
|
||||||
|
@ -35,7 +35,7 @@ export const DrawerToggle = ({
|
|||||||
}, [variant]);
|
}, [variant]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button variant="inline" className={classes} onClick={onToggle}>
|
<Button variant="inline-link" className={classes} onClick={onToggle}>
|
||||||
<Icon name={iconName as IconName} />
|
<Icon name={iconName as IconName} />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import produce from 'immer';
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import type {
|
import type {
|
||||||
@ -87,15 +88,16 @@ export const FILTERS_QUERY = gql`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const update = (
|
const update = (
|
||||||
draft: SimpleMarkets_markets[],
|
data: SimpleMarkets_markets[],
|
||||||
delta: SimpleMarketDataSub_marketData
|
delta: SimpleMarketDataSub_marketData
|
||||||
) => {
|
) =>
|
||||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
produce(data, (draft) => {
|
||||||
if (index !== -1) {
|
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||||
draft[index].data = delta;
|
if (index !== -1) {
|
||||||
}
|
draft[index].data = delta;
|
||||||
// @TODO - else push new market to draft
|
}
|
||||||
};
|
// @TODO - else push new market to draft
|
||||||
|
});
|
||||||
|
|
||||||
const getData = (responseData: SimpleMarkets) => responseData.markets;
|
const getData = (responseData: SimpleMarkets) => responseData.markets;
|
||||||
const getDelta = (
|
const getDelta = (
|
||||||
|
@ -101,7 +101,7 @@ const SimpleMarketList = () => {
|
|||||||
<div className="absolute right-16 top-1/2 -translate-y-1/2">
|
<div className="absolute right-16 top-1/2 -translate-y-1/2">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => onClick(market.id)}
|
onClick={() => onClick(market.id)}
|
||||||
variant="inline"
|
variant="inline-link"
|
||||||
prependIconName="chevron-right"
|
prependIconName="chevron-right"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,7 +70,7 @@ export default ({ steps }: StepperProps) => {
|
|||||||
{index === steps.length - 1 ? 'Finish' : 'Continue'}
|
{index === steps.length - 1 ? 'Finish' : 'Continue'}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="inline"
|
variant="inline-link"
|
||||||
disabled={index === 0}
|
disabled={index === 0}
|
||||||
onClick={handleBack}
|
onClick={handleBack}
|
||||||
>
|
>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||||
"total_added": "129999.45",
|
"total_added": "129999.45",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "125847.249906896297139465",
|
"locked_amount": "124661.013711767544930765",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "129999.45",
|
"amount": "129999.45",
|
||||||
@ -488,7 +488,7 @@
|
|||||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||||
"total_added": "97499.58",
|
"total_added": "97499.58",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "66666.63057997215661197",
|
"locked_amount": "65503.04337545080622283",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "97499.58",
|
"amount": "97499.58",
|
||||||
@ -521,7 +521,7 @@
|
|||||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||||
"total_added": "135173.4239508",
|
"total_added": "135173.4239508",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "91121.77448920241599915064844",
|
"locked_amount": "89531.35166557213976323285608",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "135173.4239508",
|
"amount": "135173.4239508",
|
||||||
@ -554,7 +554,7 @@
|
|||||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||||
"total_added": "32499.86",
|
"total_added": "32499.86",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "28045.500213863789588014",
|
"locked_amount": "27555.99917099787937361",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "32499.86",
|
"amount": "32499.86",
|
||||||
@ -587,7 +587,7 @@
|
|||||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||||
"total_added": "10833.29",
|
"total_added": "10833.29",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "9128.538172520424723312",
|
"locked_amount": "8969.210333073256934278",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "10833.29",
|
"amount": "10833.29",
|
||||||
@ -675,7 +675,7 @@
|
|||||||
"tranche_end": "2022-11-01T00:00:00.000Z",
|
"tranche_end": "2022-11-01T00:00:00.000Z",
|
||||||
"total_added": "22500",
|
"total_added": "22500",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "16079.77241847825975",
|
"locked_amount": "15468.3027626811615",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "15000",
|
"amount": "15000",
|
||||||
@ -761,7 +761,7 @@
|
|||||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||||
"total_added": "1939928.38",
|
"total_added": "1939928.38",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "1830956.520319353226245706",
|
"locked_amount": "1804379.69836047439128314",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "1852091.69",
|
"amount": "1852091.69",
|
||||||
@ -1776,8 +1776,8 @@
|
|||||||
"tranche_start": "2021-09-05T00:00:00.000Z",
|
"tranche_start": "2021-09-05T00:00:00.000Z",
|
||||||
"tranche_end": "2022-09-30T00:00:00.000Z",
|
"tranche_end": "2022-09-30T00:00:00.000Z",
|
||||||
"total_added": "60916.66666633337",
|
"total_added": "60916.66666633337",
|
||||||
"total_removed": "18323.723696937179372649",
|
"total_removed": "18705.279504739679372649",
|
||||||
"locked_amount": "15541.060867673757124652184217191",
|
"locked_amount": "14760.0056484630890178248654459722",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "2833.333333",
|
"amount": "2833.333333",
|
||||||
@ -1876,6 +1876,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "381.5558078025",
|
||||||
|
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||||
|
"tx": "0xdf5387ab07596bf2a4a608ea38d3f98f8020941f4fa7ad88f1ccd223669ac2c7"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "327.532400005",
|
"amount": "327.532400005",
|
||||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||||
@ -2591,6 +2596,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "381.5558078025",
|
||||||
|
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||||
|
"tranche_id": 13,
|
||||||
|
"tx": "0xdf5387ab07596bf2a4a608ea38d3f98f8020941f4fa7ad88f1ccd223669ac2c7"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "490.9767850775",
|
"amount": "490.9767850775",
|
||||||
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||||
@ -2635,8 +2646,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total_tokens": "4250",
|
"total_tokens": "4250",
|
||||||
"withdrawn_tokens": "2838.102475055",
|
"withdrawn_tokens": "3219.6582828575",
|
||||||
"remaining_tokens": "1411.897524945"
|
"remaining_tokens": "1030.3417171425"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xDFaF6D0a0102ea5e4688F95Eb22Dc353751a7563",
|
"address": "0xDFaF6D0a0102ea5e4688F95Eb22Dc353751a7563",
|
||||||
@ -3228,8 +3239,8 @@
|
|||||||
"tranche_id": 10,
|
"tranche_id": 10,
|
||||||
"tranche_start": "2021-07-15T23:37:11.000Z",
|
"tranche_start": "2021-07-15T23:37:11.000Z",
|
||||||
"tranche_end": "2021-07-15T23:37:11.000Z",
|
"tranche_end": "2021-07-15T23:37:11.000Z",
|
||||||
"total_added": "3653968.150000000000000001",
|
"total_added": "3710968.150000000000000001",
|
||||||
"total_removed": "3645778.640000000000000001",
|
"total_removed": "3702778.640000000000000001",
|
||||||
"locked_amount": "0",
|
"locked_amount": "0",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
@ -3242,6 +3253,11 @@
|
|||||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
"tx": "0x7b0e95e1914579c79eff111dd0df59e767321858e552cbd2a65e5f0ea8c60868"
|
"tx": "0x7b0e95e1914579c79eff111dd0df59e767321858e552cbd2a65e5f0ea8c60868"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "57000",
|
||||||
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
|
"tx": "0x66d007fc762ef9b7d2c0b57434295d06dfbafb9aeb5884cedc650f5f0c98d68f"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "40000",
|
"amount": "40000",
|
||||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
@ -3669,6 +3685,11 @@
|
|||||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
"tx": "0xc5ad7140387b5c2eeeae5c158d97a8df0d4c0bbae4a61b3c03c784f11272c89a"
|
"tx": "0xc5ad7140387b5c2eeeae5c158d97a8df0d4c0bbae4a61b3c03c784f11272c89a"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "57000",
|
||||||
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
|
"tx": "0x25c796bbfae4d91dca908b1ea7c50f6ea26b38d5350862b154a7963802bc3497"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "40000",
|
"amount": "40000",
|
||||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
@ -4041,6 +4062,12 @@
|
|||||||
"tranche_id": 10,
|
"tranche_id": 10,
|
||||||
"tx": "0x7b0e95e1914579c79eff111dd0df59e767321858e552cbd2a65e5f0ea8c60868"
|
"tx": "0x7b0e95e1914579c79eff111dd0df59e767321858e552cbd2a65e5f0ea8c60868"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "57000",
|
||||||
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
|
"tranche_id": 10,
|
||||||
|
"tx": "0x66d007fc762ef9b7d2c0b57434295d06dfbafb9aeb5884cedc650f5f0c98d68f"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "40000",
|
"amount": "40000",
|
||||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
@ -4127,6 +4154,12 @@
|
|||||||
"tranche_id": 10,
|
"tranche_id": 10,
|
||||||
"tx": "0xc5ad7140387b5c2eeeae5c158d97a8df0d4c0bbae4a61b3c03c784f11272c89a"
|
"tx": "0xc5ad7140387b5c2eeeae5c158d97a8df0d4c0bbae4a61b3c03c784f11272c89a"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "57000",
|
||||||
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
|
"tranche_id": 10,
|
||||||
|
"tx": "0x25c796bbfae4d91dca908b1ea7c50f6ea26b38d5350862b154a7963802bc3497"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "40000",
|
"amount": "40000",
|
||||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||||
@ -4194,8 +4227,8 @@
|
|||||||
"tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc"
|
"tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total_tokens": "507651",
|
"total_tokens": "564651",
|
||||||
"withdrawn_tokens": "507651",
|
"withdrawn_tokens": "564651",
|
||||||
"remaining_tokens": "0"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -5194,8 +5227,8 @@
|
|||||||
"tranche_start": "2021-09-03T00:00:00.000Z",
|
"tranche_start": "2021-09-03T00:00:00.000Z",
|
||||||
"tranche_end": "2022-09-03T00:00:00.000Z",
|
"tranche_end": "2022-09-03T00:00:00.000Z",
|
||||||
"total_added": "19455.000000000000000003",
|
"total_added": "19455.000000000000000003",
|
||||||
"total_removed": "5052.45813105178",
|
"total_removed": "5056.88782409978",
|
||||||
"locked_amount": "3864.17904680365295175059586415525114155",
|
"locked_amount": "3597.64752092846370375055476445966514475",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "75",
|
"amount": "75",
|
||||||
@ -8249,6 +8282,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "4.429693048",
|
||||||
|
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||||
|
"tx": "0xfbca378f6263977884e6eebc653c8d68f39b6c8eb6ce2f6668767ed63bfcc55b"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "8.25227042",
|
"amount": "8.25227042",
|
||||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||||
@ -13997,6 +14035,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "4.429693048",
|
||||||
|
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||||
|
"tranche_id": 11,
|
||||||
|
"tx": "0xfbca378f6263977884e6eebc653c8d68f39b6c8eb6ce2f6668767ed63bfcc55b"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "8.25227042",
|
"amount": "8.25227042",
|
||||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||||
@ -14053,8 +14097,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total_tokens": "200",
|
"total_tokens": "200",
|
||||||
"withdrawn_tokens": "157.871905124",
|
"withdrawn_tokens": "162.301598172",
|
||||||
"remaining_tokens": "42.128094876"
|
"remaining_tokens": "37.698401828"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x1775cc97E5c05Fde8b571ef75CA52d0A9ff19025",
|
"address": "0x1775cc97E5c05Fde8b571ef75CA52d0A9ff19025",
|
||||||
@ -14079,7 +14123,7 @@
|
|||||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||||
"total_added": "3732368.4671",
|
"total_added": "3732368.4671",
|
||||||
"total_removed": "74162.9780761646031",
|
"total_removed": "74162.9780761646031",
|
||||||
"locked_amount": "2838044.0251062046717742172",
|
"locked_amount": "2797204.7028220379638062054",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "1998.95815",
|
"amount": "1998.95815",
|
||||||
@ -14791,8 +14835,8 @@
|
|||||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||||
"total_added": "15788853.065470999700000001",
|
"total_added": "15788853.065470999700000001",
|
||||||
"total_removed": "5923.782558947259825",
|
"total_removed": "7926.7627792759659",
|
||||||
"locked_amount": "15284554.9536832239111747473350177541524737",
|
"locked_amount": "15140482.7365636033722263648641426217383077",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "16249.93",
|
"amount": "16249.93",
|
||||||
@ -15291,6 +15335,31 @@
|
|||||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
"tx": "0xb11f9f763196e40be412b1c6992f64d3a73b094833f57eb7783a050c64ec159d"
|
"tx": "0xb11f9f763196e40be412b1c6992f64d3a73b094833f57eb7783a050c64ec159d"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "605.52572395991115",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tx": "0x7bf7930893a08f0c18416bb3c9470c5671a1a10a9251d4ab5eb392ed90124a60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "460.287027070071975",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tx": "0xf2208f6e0a6d6b7f5e52e128632ac52b8473b408421318b9a28460aa19feca9c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "358.037173900154925",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tx": "0x2a92ef6c2eb5779e6219058a74210fcd461484d42d623dd06dcb9886683d7b50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "226.8137106757935",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tx": "0xcb5d0a1e6fdae5bed77fe2f8a29df14985d9f21d0e681416c618104b530fab36"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "352.316584722774525",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tx": "0xa79f7f3e6436a1f473f3beab9e0a5c8bc4f52b38ac7aedb8610a1a9a9c4a786c"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "2446.31552516990115",
|
"amount": "2446.31552516990115",
|
||||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
@ -15383,6 +15452,36 @@
|
|||||||
"tranche_id": 2,
|
"tranche_id": 2,
|
||||||
"tx": "0xb11f9f763196e40be412b1c6992f64d3a73b094833f57eb7783a050c64ec159d"
|
"tx": "0xb11f9f763196e40be412b1c6992f64d3a73b094833f57eb7783a050c64ec159d"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "605.52572395991115",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tranche_id": 2,
|
||||||
|
"tx": "0x7bf7930893a08f0c18416bb3c9470c5671a1a10a9251d4ab5eb392ed90124a60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "460.287027070071975",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tranche_id": 2,
|
||||||
|
"tx": "0xf2208f6e0a6d6b7f5e52e128632ac52b8473b408421318b9a28460aa19feca9c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "358.037173900154925",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tranche_id": 2,
|
||||||
|
"tx": "0x2a92ef6c2eb5779e6219058a74210fcd461484d42d623dd06dcb9886683d7b50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "226.8137106757935",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tranche_id": 2,
|
||||||
|
"tx": "0xcb5d0a1e6fdae5bed77fe2f8a29df14985d9f21d0e681416c618104b530fab36"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "352.316584722774525",
|
||||||
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
|
"tranche_id": 2,
|
||||||
|
"tx": "0xa79f7f3e6436a1f473f3beab9e0a5c8bc4f52b38ac7aedb8610a1a9a9c4a786c"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "2446.31552516990115",
|
"amount": "2446.31552516990115",
|
||||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||||
@ -15427,8 +15526,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total_tokens": "194999.1675",
|
"total_tokens": "194999.1675",
|
||||||
"withdrawn_tokens": "5923.782558947259825",
|
"withdrawn_tokens": "7926.7627792759659",
|
||||||
"remaining_tokens": "189075.384941052740175"
|
"remaining_tokens": "187072.4047207240341"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||||
@ -16832,8 +16931,8 @@
|
|||||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||||
"total_added": "14597706.0446472999",
|
"total_added": "14597706.0446472999",
|
||||||
"total_removed": "2068423.077146290360122272",
|
"total_removed": "2113641.840890679071831632",
|
||||||
"locked_amount": "8461771.6695419306722268828527521",
|
"locked_amount": "8328080.66510881884167481291924447",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "129284.449",
|
"amount": "129284.449",
|
||||||
@ -17047,6 +17146,41 @@
|
|||||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
"tx": "0xa7bccea82ef34f1943bc5243ef75909d8ae81c45e67862b9c68b0a7532edc833"
|
"tx": "0xa7bccea82ef34f1943bc5243ef75909d8ae81c45e67862b9c68b0a7532edc833"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "582.7808762737973505",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tx": "0xcdbefdbd89a68d401dd21553cded39ee57bb5a7c6f3203ed6971e625f90c8b9d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "539.09172135635481275",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tx": "0x091d995cd60f0a5a93eccb13e0ca0e39fc513c28c860bd5bc6369da3994a09d0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "845.684674761873869",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tx": "0xcb8ecc71a9024bab7454a33f6adf7bfcd0f25b3dc1919f92ca362a25b71f2a4d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "41515.95004024647383586",
|
||||||
|
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||||
|
"tx": "0xd950c34bf5f503998bddc8f9fdeb7cdc4ae1e76c5e9b1564795c306c2e8cad63"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "657.674387973356598",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tx": "0xd0f13de38f21ba54433885d7e3e3db7438b9bcc92dbd52a75e0b7f772018ab1c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "424.7645385693677305",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tx": "0x77d249279d8ea7554d19c557311687d57884b5e08537ac9574897ca58a13d880"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "652.81750520748751275",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tx": "0xc62ffa6bf5029422f44d9406972fc074b498e02f667a86ae9faba138b6cfd758"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "652.48254356494551875",
|
"amount": "652.48254356494551875",
|
||||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
@ -18629,6 +18763,42 @@
|
|||||||
"tranche_id": 3,
|
"tranche_id": 3,
|
||||||
"tx": "0xa7bccea82ef34f1943bc5243ef75909d8ae81c45e67862b9c68b0a7532edc833"
|
"tx": "0xa7bccea82ef34f1943bc5243ef75909d8ae81c45e67862b9c68b0a7532edc833"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "582.7808762737973505",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tranche_id": 3,
|
||||||
|
"tx": "0xcdbefdbd89a68d401dd21553cded39ee57bb5a7c6f3203ed6971e625f90c8b9d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "539.09172135635481275",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tranche_id": 3,
|
||||||
|
"tx": "0x091d995cd60f0a5a93eccb13e0ca0e39fc513c28c860bd5bc6369da3994a09d0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "845.684674761873869",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tranche_id": 3,
|
||||||
|
"tx": "0xcb8ecc71a9024bab7454a33f6adf7bfcd0f25b3dc1919f92ca362a25b71f2a4d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "657.674387973356598",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tranche_id": 3,
|
||||||
|
"tx": "0xd0f13de38f21ba54433885d7e3e3db7438b9bcc92dbd52a75e0b7f772018ab1c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "424.7645385693677305",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tranche_id": 3,
|
||||||
|
"tx": "0x77d249279d8ea7554d19c557311687d57884b5e08537ac9574897ca58a13d880"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "652.81750520748751275",
|
||||||
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
|
"tranche_id": 3,
|
||||||
|
"tx": "0xc62ffa6bf5029422f44d9406972fc074b498e02f667a86ae9faba138b6cfd758"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "652.48254356494551875",
|
"amount": "652.48254356494551875",
|
||||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||||
@ -19867,8 +20037,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total_tokens": "359123.469575",
|
"total_tokens": "359123.469575",
|
||||||
"withdrawn_tokens": "150390.162087073825163",
|
"withdrawn_tokens": "154092.9757912160630365",
|
||||||
"remaining_tokens": "208733.307487926174837"
|
"remaining_tokens": "205030.4937837839369635"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||||
@ -20055,6 +20225,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "41515.95004024647383586",
|
||||||
|
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||||
|
"tranche_id": 3,
|
||||||
|
"tx": "0xd950c34bf5f503998bddc8f9fdeb7cdc4ae1e76c5e9b1564795c306c2e8cad63"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "17786.1881146007542887",
|
"amount": "17786.1881146007542887",
|
||||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||||
@ -20261,8 +20437,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total_tokens": "1266324.603486",
|
"total_tokens": "1266324.603486",
|
||||||
"withdrawn_tokens": "497356.38070819243695426",
|
"withdrawn_tokens": "538872.33074843891079012",
|
||||||
"remaining_tokens": "768968.22277780756304574"
|
"remaining_tokens": "727452.27273756108920988"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xC5d9221EB9c28A69859264c0A2Fe0d3272228296",
|
"address": "0xC5d9221EB9c28A69859264c0A2Fe0d3272228296",
|
||||||
@ -20859,7 +21035,7 @@
|
|||||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||||
"total_added": "5778205.3912159303",
|
"total_added": "5778205.3912159303",
|
||||||
"total_removed": "1390546.591547348229906227",
|
"total_removed": "1390546.591547348229906227",
|
||||||
"locked_amount": "3026393.75946481397995019109643517",
|
"locked_amount": "2973571.63505682836710488797665665",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "552496.6455",
|
"amount": "552496.6455",
|
||||||
@ -21981,8 +22157,8 @@
|
|||||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||||
"total_added": "472355.6199999996",
|
"total_added": "472355.6199999996",
|
||||||
"total_removed": "0",
|
"total_removed": "34.173053016",
|
||||||
"locked_amount": "449704.29872935272705903095281584",
|
"locked_amount": "443233.07466590775804275636428212",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "3000",
|
"amount": "3000",
|
||||||
@ -28600,7 +28776,18 @@
|
|||||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "11.163032724",
|
||||||
|
"user": "0xF5037DDA4A660d67560200f45380FF8364e35540",
|
||||||
|
"tx": "0x0db96c68606a35c59786e3b1ff4f8e939a56af133709dd154718eb03138fe227"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "23.010020292",
|
||||||
|
"user": "0xD27929d68ac0E5fd5C919A5eb5968C1D06D3Fb83",
|
||||||
|
"tx": "0x8daf320262d0384cf5f9c290cc33721587beabd5e93026b3e9b76dc3fcd6659c"
|
||||||
|
}
|
||||||
|
],
|
||||||
"users": [
|
"users": [
|
||||||
{
|
{
|
||||||
"address": "0xD18ffAa4a1d16f9eD9d3BE4078738Eeda3f160FD",
|
"address": "0xD18ffAa4a1d16f9eD9d3BE4078738Eeda3f160FD",
|
||||||
@ -47113,10 +47300,17 @@
|
|||||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "23.010020292",
|
||||||
|
"user": "0xD27929d68ac0E5fd5C919A5eb5968C1D06D3Fb83",
|
||||||
|
"tranche_id": 5,
|
||||||
|
"tx": "0x8daf320262d0384cf5f9c290cc33721587beabd5e93026b3e9b76dc3fcd6659c"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "400",
|
"total_tokens": "400",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "23.010020292",
|
||||||
"remaining_tokens": "400"
|
"remaining_tokens": "376.989979708"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xF5037DDA4A660d67560200f45380FF8364e35540",
|
"address": "0xF5037DDA4A660d67560200f45380FF8364e35540",
|
||||||
@ -47128,10 +47322,17 @@
|
|||||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "11.163032724",
|
||||||
|
"user": "0xF5037DDA4A660d67560200f45380FF8364e35540",
|
||||||
|
"tranche_id": 5,
|
||||||
|
"tx": "0x0db96c68606a35c59786e3b1ff4f8e939a56af133709dd154718eb03138fe227"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "200",
|
"total_tokens": "200",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "11.163032724",
|
||||||
"remaining_tokens": "200"
|
"remaining_tokens": "188.836967276"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x2843a3A61C7a129e432455c02101Cec3fA428E60",
|
"address": "0x2843a3A61C7a129e432455c02101Cec3fA428E60",
|
||||||
@ -47635,7 +47836,7 @@
|
|||||||
"tranche_start": "2021-12-05T00:00:00.000Z",
|
"tranche_start": "2021-12-05T00:00:00.000Z",
|
||||||
"tranche_end": "2022-06-05T00:00:00.000Z",
|
"tranche_end": "2022-06-05T00:00:00.000Z",
|
||||||
"total_added": "171288.42",
|
"total_added": "171288.42",
|
||||||
"total_removed": "29185.5825162206377",
|
"total_removed": "32094.1716569431377",
|
||||||
"locked_amount": "0",
|
"locked_amount": "0",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
@ -51870,6 +52071,71 @@
|
|||||||
"user": "0x7fAA8d1Cb6Ab8A9fC039b66fe844575557389CD4",
|
"user": "0x7fAA8d1Cb6Ab8A9fC039b66fe844575557389CD4",
|
||||||
"tx": "0xb45e62f845fe45f11bb86fdffbc1af3e737573726b3c2c8cc6ba39ab8127369d"
|
"tx": "0xb45e62f845fe45f11bb86fdffbc1af3e737573726b3c2c8cc6ba39ab8127369d"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xEF5D4Be15019F9b972E54b6B904076617aDAfb1C",
|
||||||
|
"tx": "0x44d207a93bdb1ef457d5a31207d3ccbda3e9fce6528f3a6c0d04f9153e064a2a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "249.9",
|
||||||
|
"user": "0xcad0D46627628A8bAF524BF202669e8B9f04250f",
|
||||||
|
"tx": "0xa403d8af5a940c4abd4aadcc579e279218ae73b9c7fc3d7e4216d6aab5ba70eb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xEc925Fd72B46E2101D20686800343220c12Dedde",
|
||||||
|
"tx": "0xeaf8173b80d3ea3eb5c440a6edcc4fbf6d8624fa437203b66f6acb72d7462b5e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xbC10086CB362caE3071f2e09DF2aEE5265FdA238",
|
||||||
|
"tx": "0x1ea368a1c1f000d36d93627ccda127da12e4beade77d869aab7cadb7edfa354f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xDA83Ff6862ed0579248CEd14422C8B782732233b",
|
||||||
|
"tx": "0x7eb0ec3a5e3d8792b341881083f9046d550fdf0e92429b53bbdddfe439e83983"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x2b28Fd98804e19cFe8d46f2d729C2A5195339fA4",
|
||||||
|
"tx": "0xd8c87e89222f0fea8933a403cd39756c6721d1e3d86a0bb7747b428f50c7f790"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x0941FC05E3DA8d9dD29bCBB15F9FF3A16F342612",
|
||||||
|
"tx": "0xb3cffc52e62679835e65be5472f80bcfa949f7eb0c4c9948efc3271cca02fdae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "100",
|
||||||
|
"user": "0x4796314cC5bDa80Ee2E8b119004b1fc72Cfb1783",
|
||||||
|
"tx": "0xbfdbd5e3712968f2726e8dba1f226944cfa637f8738f25c3a5b12a1c6a8e7197"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xC26B3b40DC383d97B69Eedcd4E78a9e4eEb73499",
|
||||||
|
"tx": "0x2c9f57d5e697c29b67034cea8738939ec13b20b5a7d7fcb995fe83f16b4abf75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x9f6b5A46593b991dC78a0e1907a07517A1F80CC2",
|
||||||
|
"tx": "0x55b21517cf5fd148e596d9e4b63964ab1df82534fd76b6d9dc9d7cfd00971da0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x696971413b8Ae5342277AfeC16591271648B4FfF",
|
||||||
|
"tx": "0xa55b22bf465927c195b424ad7ea893c1c497da34290d5261be205c760fc11cf5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x8FC36B7695965Bc39BCB8a3679529f1825e472aE",
|
||||||
|
"tx": "0x7072667bf81811acda07177c1ace2edcfe19ce68711fa349ad94c1f8aa3d0b25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": "58.6891407225",
|
||||||
|
"user": "0xDD5730a33719083470e641cF0e4154Dd04D5738d",
|
||||||
|
"tx": "0x49bd6332008e65069aad8012f76f15f3dae19f664237b02f9152946297db812d"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "183.6335597275",
|
"amount": "183.6335597275",
|
||||||
"user": "0x690Fc36d52eD3f198F0eBDea1557333a1766f786",
|
"user": "0x690Fc36d52eD3f198F0eBDea1557333a1766f786",
|
||||||
@ -57843,10 +58109,17 @@
|
|||||||
"tx": "0x75de6ca47e0da361181d14aceb5d08e572754861465caa67a12b528886d55307"
|
"tx": "0x75de6ca47e0da361181d14aceb5d08e572754861465caa67a12b528886d55307"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "249.9",
|
||||||
|
"user": "0xcad0D46627628A8bAF524BF202669e8B9f04250f",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0xa403d8af5a940c4abd4aadcc579e279218ae73b9c7fc3d7e4216d6aab5ba70eb"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "249.9",
|
"total_tokens": "249.9",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "249.9",
|
||||||
"remaining_tokens": "249.9"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x783C204FfCC479cec7807C37480A4D4C77FB1F22",
|
"address": "0x783C204FfCC479cec7807C37480A4D4C77FB1F22",
|
||||||
@ -58384,6 +58657,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "58.6891407225",
|
||||||
|
"user": "0xDD5730a33719083470e641cF0e4154Dd04D5738d",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0x49bd6332008e65069aad8012f76f15f3dae19f664237b02f9152946297db812d"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"amount": "65.928596865",
|
"amount": "65.928596865",
|
||||||
"user": "0xDD5730a33719083470e641cF0e4154Dd04D5738d",
|
"user": "0xDD5730a33719083470e641cF0e4154Dd04D5738d",
|
||||||
@ -58398,8 +58677,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "191.3108592775",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "58.6891407225"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x243e23c83135cA0fed2F9f5dF9068dE644929433",
|
"address": "0x243e23c83135cA0fed2F9f5dF9068dE644929433",
|
||||||
@ -59330,10 +59609,17 @@
|
|||||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xEc925Fd72B46E2101D20686800343220c12Dedde",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0xeaf8173b80d3ea3eb5c440a6edcc4fbf6d8624fa437203b66f6acb72d7462b5e"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x08e9b80fCa090CB3E50d77964dc8777cD828253D",
|
"address": "0x08e9b80fCa090CB3E50d77964dc8777cD828253D",
|
||||||
@ -59570,10 +59856,17 @@
|
|||||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x2b28Fd98804e19cFe8d46f2d729C2A5195339fA4",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0xd8c87e89222f0fea8933a403cd39756c6721d1e3d86a0bb7747b428f50c7f790"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x61f908D9ee13a68983e5FECc8D9467232F5E9cB4",
|
"address": "0x61f908D9ee13a68983e5FECc8D9467232F5E9cB4",
|
||||||
@ -59630,10 +59923,17 @@
|
|||||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xDA83Ff6862ed0579248CEd14422C8B782732233b",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0x7eb0ec3a5e3d8792b341881083f9046d550fdf0e92429b53bbdddfe439e83983"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xbC10086CB362caE3071f2e09DF2aEE5265FdA238",
|
"address": "0xbC10086CB362caE3071f2e09DF2aEE5265FdA238",
|
||||||
@ -59645,10 +59945,17 @@
|
|||||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xbC10086CB362caE3071f2e09DF2aEE5265FdA238",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0x1ea368a1c1f000d36d93627ccda127da12e4beade77d869aab7cadb7edfa354f"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xEe3183EcE9ee7d73Fb7bA7F4eB262A2dE68C42B0",
|
"address": "0xEe3183EcE9ee7d73Fb7bA7F4eB262A2dE68C42B0",
|
||||||
@ -61749,10 +62056,17 @@
|
|||||||
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x9f6b5A46593b991dC78a0e1907a07517A1F80CC2",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0x55b21517cf5fd148e596d9e4b63964ab1df82534fd76b6d9dc9d7cfd00971da0"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x758E9AA35F2feA08aEc1613A0F0d9Ebe4d374152",
|
"address": "0x758E9AA35F2feA08aEc1613A0F0d9Ebe4d374152",
|
||||||
@ -61804,10 +62118,17 @@
|
|||||||
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x8FC36B7695965Bc39BCB8a3679529f1825e472aE",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0x7072667bf81811acda07177c1ace2edcfe19ce68711fa349ad94c1f8aa3d0b25"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x8186CDe8f7A2f95b50f847e2a3301c28bB61Fa8A",
|
"address": "0x8186CDe8f7A2f95b50f847e2a3301c28bB61Fa8A",
|
||||||
@ -62231,10 +62552,17 @@
|
|||||||
"tx": "0x9f916cf09e8a3c4ade0ffce5190db464d0a2b1dadba78e1ee7ba5d6e751d6148"
|
"tx": "0x9f916cf09e8a3c4ade0ffce5190db464d0a2b1dadba78e1ee7ba5d6e751d6148"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x0941FC05E3DA8d9dD29bCBB15F9FF3A16F342612",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0xb3cffc52e62679835e65be5472f80bcfa949f7eb0c4c9948efc3271cca02fdae"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x0a5688ed5b0b804db2ee18767476bb60598EC398",
|
"address": "0x0a5688ed5b0b804db2ee18767476bb60598EC398",
|
||||||
@ -63811,10 +64139,17 @@
|
|||||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0x696971413b8Ae5342277AfeC16591271648B4FfF",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0xa55b22bf465927c195b424ad7ea893c1c497da34290d5261be205c760fc11cf5"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xcbEca0abcc675A0F977c4Eb9a45bB4153C0246C3",
|
"address": "0xcbEca0abcc675A0F977c4Eb9a45bB4153C0246C3",
|
||||||
@ -63848,10 +64183,17 @@
|
|||||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xC26B3b40DC383d97B69Eedcd4E78a9e4eEb73499",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0x2c9f57d5e697c29b67034cea8738939ec13b20b5a7d7fcb995fe83f16b4abf75"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xd866082E19c9E36bcA4fA649d530166303B656f2",
|
"address": "0xd866082E19c9E36bcA4fA649d530166303B656f2",
|
||||||
@ -64126,10 +64468,17 @@
|
|||||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "250",
|
||||||
|
"user": "0xEF5D4Be15019F9b972E54b6B904076617aDAfb1C",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0x44d207a93bdb1ef457d5a31207d3ccbda3e9fce6528f3a6c0d04f9153e064a2a"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "250",
|
"total_tokens": "250",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "250",
|
||||||
"remaining_tokens": "250"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x660Bc2766867E1E19252ad30A413fe20d08A85c4",
|
"address": "0x660Bc2766867E1E19252ad30A413fe20d08A85c4",
|
||||||
@ -64156,10 +64505,17 @@
|
|||||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"withdrawals": [],
|
"withdrawals": [
|
||||||
|
{
|
||||||
|
"amount": "100",
|
||||||
|
"user": "0x4796314cC5bDa80Ee2E8b119004b1fc72Cfb1783",
|
||||||
|
"tranche_id": 6,
|
||||||
|
"tx": "0xbfdbd5e3712968f2726e8dba1f226944cfa637f8738f25c3a5b12a1c6a8e7197"
|
||||||
|
}
|
||||||
|
],
|
||||||
"total_tokens": "100",
|
"total_tokens": "100",
|
||||||
"withdrawn_tokens": "0",
|
"withdrawn_tokens": "100",
|
||||||
"remaining_tokens": "100"
|
"remaining_tokens": "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x351cc2560C870f01B099B106Be22C0073Fce10B2",
|
"address": "0x351cc2560C870f01B099B106Be22C0073Fce10B2",
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
"tranche_end": "2022-11-26T13:48:10.000Z",
|
"tranche_end": "2022-11-26T13:48:10.000Z",
|
||||||
"total_added": "100",
|
"total_added": "100",
|
||||||
"total_removed": "0",
|
"total_removed": "0",
|
||||||
"locked_amount": "43.033418949771685",
|
"locked_amount": "41.663429096905125",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "100",
|
"amount": "100",
|
||||||
@ -242,7 +242,7 @@
|
|||||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||||
"total_added": "1100",
|
"total_added": "1100",
|
||||||
"total_removed": "673.04388635",
|
"total_removed": "673.04388635",
|
||||||
"locked_amount": "336.1295630390665",
|
"locked_amount": "321.05967465753423",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "1000",
|
"amount": "1000",
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||||
"total_added": "1010.000000000000000001",
|
"total_added": "1010.000000000000000001",
|
||||||
"total_removed": "668.4622323651",
|
"total_removed": "668.4622323651",
|
||||||
"locked_amount": "308.628053335870150000305572330035515",
|
"locked_amount": "294.7911558219177930002918724315068493",
|
||||||
"deposits": [
|
"deposits": [
|
||||||
{
|
{
|
||||||
"amount": "1000",
|
"amount": "1000",
|
||||||
|
@ -1,29 +1,17 @@
|
|||||||
# React Environment Variables
|
|
||||||
# https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#expanding-environment-variables-in-env
|
|
||||||
|
|
||||||
# Netlify Environment Variables
|
|
||||||
# https://www.netlify.com/docs/continuous-deployment/#environment-variables
|
|
||||||
REACT_APP_VERSION=$npm_package_version
|
|
||||||
REACT_APP_REPOSITORY_URL=$REPOSITORY_URL
|
|
||||||
REACT_APP_BRANCH=$BRANCH
|
|
||||||
REACT_APP_PULL_REQUEST=$PULL_REQUEST
|
|
||||||
REACT_APP_HEAD=$HEAD
|
|
||||||
REACT_APP_COMMIT_REF=$COMMIT_REF
|
|
||||||
REACT_APP_CONTEXT=$CONTEXT
|
|
||||||
REACT_APP_REVIEW_ID=$REVIEW_ID
|
|
||||||
REACT_APP_INCOMING_HOOK_TITLE=$INCOMING_HOOK_TITLE
|
|
||||||
REACT_APP_INCOMING_HOOK_URL=$INCOMING_HOOK_URL
|
|
||||||
REACT_APP_INCOMING_HOOK_BODY=$INCOMING_HOOK_BODY
|
|
||||||
REACT_APP_URL=$URL
|
|
||||||
REACT_APP_DEPLOY_URL=$DEPLOY_URL
|
|
||||||
REACT_APP_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
|
|
||||||
|
|
||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_VEGA_ENV=TESTNET
|
NX_VEGA_ENV=TESTNET
|
||||||
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
|
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
|
||||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||||
NX_FAIRGROUND=false
|
NX_FAIRGROUND=false
|
||||||
|
NX_IS_NEW_BRIDGE_CONTRACT=true
|
||||||
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'
|
||||||
|
|
||||||
|
NX_VEGA_URL=http://localhost:3028/query
|
||||||
|
NX_VEGA_REST=http://localhost:3029
|
||||||
|
NX_ETHEREUM_CHAIN_ID=1440
|
||||||
|
NX_ETH_URL_CONNECT=1
|
||||||
|
NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
|
||||||
|
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
4
apps/token-e2e/src/data/vegaToken.json
Normal file
4
apps/token-e2e/src/data/vegaToken.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"tokenAddress": "0x67175Da1D5e966e40D11c4B2519392B2058373de",
|
||||||
|
"vestingContract": "0xF41bD86d462D36b997C0bbb4D97a0a3382f205B7"
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Using fixtures to represent data",
|
|
||||||
"email": "hello@cypress.io"
|
|
||||||
}
|
|
124
apps/token-e2e/src/integration/view/home.test.js
Normal file
124
apps/token-e2e/src/integration/view/home.test.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import navigation from '../../locators/navigation.locators';
|
||||||
|
import home from '../../locators/home.locators';
|
||||||
|
import vegaToken from '../../data/vegaToken.json';
|
||||||
|
|
||||||
|
context('Home Page - verify elements on page', function () {
|
||||||
|
before('visit token home page', function () {
|
||||||
|
cy.visit('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with wallets disconnected', function () {
|
||||||
|
before('wait for page to load', function () {
|
||||||
|
cy.get(navigation.section, { timeout: 10000 }).should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Navigation tabs', function () {
|
||||||
|
it('should have HOME tab', function () {
|
||||||
|
cy.get(navigation.section).within(() => {
|
||||||
|
cy.get(navigation.home).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have VESTING tab', function () {
|
||||||
|
cy.get(navigation.section).within(() => {
|
||||||
|
cy.get(navigation.vesting).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have STAKING tab', function () {
|
||||||
|
cy.get(navigation.section).within(() => {
|
||||||
|
cy.get(navigation.staking).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have REWARDS tab', function () {
|
||||||
|
cy.get(navigation.section).within(() => {
|
||||||
|
cy.get(navigation.rewards).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have WITHDRAW tab', function () {
|
||||||
|
cy.get(navigation.section).within(() => {
|
||||||
|
cy.get(navigation.withdraw).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have GOVERNANCE tab', function () {
|
||||||
|
cy.get(navigation.section).within(() => {
|
||||||
|
cy.get(navigation.governance).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('THE $VEGA TOKEN table', function () {
|
||||||
|
it('should have TOKEN ADDRESS', function () {
|
||||||
|
cy.get(home.tokenDetailsTable).within(() => {
|
||||||
|
cy.get(home.address)
|
||||||
|
.should('be.visible')
|
||||||
|
.invoke('text')
|
||||||
|
.should('be.equal', vegaToken.tokenAddress);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have VESTING CONTRACT', function () {
|
||||||
|
cy.get(home.tokenDetailsTable).within(() => {
|
||||||
|
cy.get(home.contract)
|
||||||
|
.should('be.visible')
|
||||||
|
.invoke('text')
|
||||||
|
.should('be.equal', vegaToken.vestingContract);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have TOTAL SUPPLY', function () {
|
||||||
|
cy.get(home.tokenDetailsTable).within(() => {
|
||||||
|
cy.get(home.totalSupply).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have CIRCULATING SUPPLY', function () {
|
||||||
|
cy.get(home.tokenDetailsTable).within(() => {
|
||||||
|
cy.get(home.circulatingSupply).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should have STAKED $VEGA', function () {
|
||||||
|
cy.get(home.tokenDetailsTable).within(() => {
|
||||||
|
cy.get(home.staked).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('links and buttons', function () {
|
||||||
|
it('should have TRANCHES link', function () {
|
||||||
|
cy.get(home.tranchesLink)
|
||||||
|
.should('be.visible')
|
||||||
|
.and('have.attr', 'href')
|
||||||
|
.and('equal', '/tranches');
|
||||||
|
});
|
||||||
|
it('should have REDEEM button', function () {
|
||||||
|
cy.get(home.redeemBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.parent()
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('equal', '/vesting');
|
||||||
|
});
|
||||||
|
it('should have GET VEGA WALLET link', function () {
|
||||||
|
cy.get(home.getVegaWalletLink)
|
||||||
|
.should('be.visible')
|
||||||
|
.and('have.attr', 'href')
|
||||||
|
.and('equal', 'https://vega.xyz/wallet');
|
||||||
|
});
|
||||||
|
it('should have ASSOCIATE VEGA TOKENS link', function () {
|
||||||
|
cy.get(home.associateVegaLink)
|
||||||
|
.should('be.visible')
|
||||||
|
.and('have.attr', 'href')
|
||||||
|
.and('equal', '/staking/associate');
|
||||||
|
});
|
||||||
|
it('should have STAKING button', function () {
|
||||||
|
cy.get(home.stakingBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.parent()
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('equal', '/staking');
|
||||||
|
});
|
||||||
|
it('should have GOVERNANCE button', function () {
|
||||||
|
cy.get(home.governanceBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.parent()
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('equal', '/governance');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
15
apps/token-e2e/src/locators/home.locators.js
Normal file
15
apps/token-e2e/src/locators/home.locators.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export default {
|
||||||
|
tokenDetailsTable: '.token-details',
|
||||||
|
address: '[data-testid="token-address"]',
|
||||||
|
contract: '[data-testid="token-contract"]',
|
||||||
|
totalSupply: '[data-testid="total-supply"]',
|
||||||
|
circulatingSupply: '[data-testid="circulating-supply"]',
|
||||||
|
staked: '[data-testid="staked"]',
|
||||||
|
|
||||||
|
tranchesLink: '[data-testid="tranches-link"]',
|
||||||
|
redeemBtn: '[data-testid="check-vesting-page-btn"]',
|
||||||
|
getVegaWalletLink: '[data-testid="get-vega-wallet-link"]',
|
||||||
|
associateVegaLink: '[data-testid="associate-vega-tokens-link-on-homepage"]',
|
||||||
|
stakingBtn: '[data-testid="staking-button-on-homepage"]',
|
||||||
|
governanceBtn: '[data-testid="governance-button-on-homepage"]',
|
||||||
|
};
|
9
apps/token-e2e/src/locators/navigation.locators.js
Normal file
9
apps/token-e2e/src/locators/navigation.locators.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export default {
|
||||||
|
section: 'nav',
|
||||||
|
home: '[href="/"]',
|
||||||
|
vesting: '[href="/vesting"]',
|
||||||
|
staking: '[href="/staking"]',
|
||||||
|
rewards: '[href="/rewards"]',
|
||||||
|
withdraw: '[href="/withdraw"]',
|
||||||
|
governance: '[href="/governance"]',
|
||||||
|
};
|
@ -1,23 +1,3 @@
|
|||||||
# React Environment Variables
|
|
||||||
# https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#expanding-environment-variables-in-env
|
|
||||||
|
|
||||||
# Netlify Environment Variables
|
|
||||||
# https://www.netlify.com/docs/continuous-deployment/#environment-variables
|
|
||||||
REACT_APP_VERSION=$npm_package_version
|
|
||||||
REACT_APP_REPOSITORY_URL=$REPOSITORY_URL
|
|
||||||
REACT_APP_BRANCH=$BRANCH
|
|
||||||
REACT_APP_PULL_REQUEST=$PULL_REQUEST
|
|
||||||
REACT_APP_HEAD=$HEAD
|
|
||||||
REACT_APP_COMMIT_REF=$COMMIT_REF
|
|
||||||
REACT_APP_CONTEXT=$CONTEXT
|
|
||||||
REACT_APP_REVIEW_ID=$REVIEW_ID
|
|
||||||
REACT_APP_INCOMING_HOOK_TITLE=$INCOMING_HOOK_TITLE
|
|
||||||
REACT_APP_INCOMING_HOOK_URL=$INCOMING_HOOK_URL
|
|
||||||
REACT_APP_INCOMING_HOOK_BODY=$INCOMING_HOOK_BODY
|
|
||||||
REACT_APP_URL=$URL
|
|
||||||
REACT_APP_DEPLOY_URL=$DEPLOY_URL
|
|
||||||
REACT_APP_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
|
|
||||||
|
|
||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_VEGA_ENV=TESTNET
|
NX_VEGA_ENV=TESTNET
|
||||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||||
|
17
apps/token/.env.capsule
Normal file
17
apps/token/.env.capsule
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# App configuration variables
|
||||||
|
NX_VEGA_ENV=TESTNET
|
||||||
|
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
|
||||||
|
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||||
|
NX_FAIRGROUND=false
|
||||||
|
NX_IS_NEW_BRIDGE_CONTRACT=true
|
||||||
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'
|
||||||
|
|
||||||
|
NX_VEGA_URL=http://localhost:3028/query
|
||||||
|
NX_VEGA_REST=http://localhost:3029
|
||||||
|
NX_ETHEREUM_CHAIN_ID=1440
|
||||||
|
NX_ETH_URL_CONNECT=1
|
||||||
|
NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
|
||||||
|
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
||||||
|
|
||||||
|
#Test configuration variables
|
||||||
|
CYPRESS_FAIRGROUND=false
|
@ -38,23 +38,19 @@ yarn nx run token:serve --env={env} # e.g. stagnet1
|
|||||||
|
|
||||||
There are a few different configuration options offered for this app:
|
There are a few different configuration options offered for this app:
|
||||||
|
|
||||||
| **Flag** | **Purpose** |
|
| **Flag** | **Purpose** |
|
||||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------- |
|
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `NX_APP_SENTRY_DSN` | The sentry endpoint to report to. Should be off in dev but set in live. |
|
| `NX_APP_SENTRY_DSN` | The sentry endpoint to report to. Should be off in dev but set in live. |
|
||||||
| `NX_APP_CHAIN` | The ETH chain for the app to work on. Should be mainnet for live, but ropsten for preview deploys. |
|
| `NX_APP_CHAIN` | The ETH chain for the app to work on. Should be mainnet for live, but ropsten for preview deploys. |
|
||||||
| `NX_APP_VEGA_URL` | The GraphQL query endpoint of a [Vega data node](https://github.com/vegaprotocol/networks#data-node) |
|
| `NX_APP_VEGA_URL` | The GraphQL query endpoint of a [Vega data node](https://github.com/vegaprotocol/networks#data-node) |
|
||||||
| `NX_APP_DEX_STAKING_DISABLED` | Disable the dex liquidity page an show a coming soon message |
|
| `NX_APP_DEX_STAKING_DISABLED` | Disable the dex liquidity page an show a coming soon message |
|
||||||
| `NX_APP_FAIRGROUND` | Change styling to be themed as the fairground version of the website |
|
| `NX_APP_FAIRGROUND` | Change styling to be themed as the fairground version of the website |
|
||||||
| `NX_APP_INFURA_ID` | Infura fallback for if the user does not have a web3 compatible browser |
|
| `NX_APP_INFURA_ID` | Infura fallback for if the user does not have a web3 compatible browser |
|
||||||
| `NX_APP_HOSTED_WALLET_ENABLED` | If the hosted wallet is enabled or not. If so then allow users to login using the hosted wallet |
|
| `NX_APP_HOSTED_WALLET_ENABLED` | If the hosted wallet is enabled or not. If so then allow users to login using the hosted wallet |
|
||||||
| `NX_APP_ENV` | Change network to connect to. When set to CUSTOM use CUSTOM\_\* vars for network parameters |
|
| `NX_APP_ENV` | Change network to connect to. When set to CUSTOM use CUSTOM\_\* vars for network parameters |
|
||||||
| `NX_CUSTOM_URLS` | When NX_APP_ENV=CUSTOM use these Data Node REST URLs, optional if CUSTOM_URLS_WITH_GRAPHQL is used. |
|
| `NX_ETH_URL_CONNECT` (optional) | If set to true the below two must also be set. This allows siging transactions in brower to allow to connect to a local ganache node through cypress |
|
||||||
| `NX_CUSTOM_URLS_WITH_GRAPHQL` | When NX_APP_ENV=CUSTOM use these Data Node GraphQL URLs, optional if CUSTOM_URLS is used. |
|
| `NX_ETH_WALLET_MNEMONIC` (optional) | The mnemonic to be used to sign transactions with in browser |
|
||||||
| `NX_CUSTOM_TOKEN_ADDRESS` | When NX_APP_ENV=CUSTOM specify Vega token address. |
|
| `NX_LOCAL_PROVIDER_URL` (optional) | The local node to use to send transaction to when signing in browser |
|
||||||
| `NX_CUSTOM_CLAIM_ADDRESS` | When NX_APP_ENV=CUSTOM specify Vega claim address. |
|
|
||||||
| `NX_CUSTOM_LOCKED_ADDRESS` | When NX_APP_ENV=CUSTOM specify Vega locked address. |
|
|
||||||
| `NX_CUSTOM_VESTING_ADDRESS` | When NX_APP_ENV=CUSTOM specify Vega vesting address. |
|
|
||||||
| `NX_CUSTOM_STAKING_BRIDGE` | When NX_APP_ENV=CUSTOM specify Vega staking bridge address. |
|
|
||||||
|
|
||||||
## Example configs:
|
## Example configs:
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { useWeb3React } from '@web3-react/core';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { getButtonClasses, Button } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AppStateActionType,
|
AppStateActionType,
|
||||||
@ -70,7 +71,7 @@ const AssociatedAmounts = ({
|
|||||||
rightLabel={t('notAssociated')}
|
rightLabel={t('notAssociated')}
|
||||||
leftColor={Colors.white.DEFAULT}
|
leftColor={Colors.white.DEFAULT}
|
||||||
rightColor={Colors.black.DEFAULT}
|
rightColor={Colors.black.DEFAULT}
|
||||||
light={true}
|
light={false}
|
||||||
/>
|
/>
|
||||||
{vestingAssociationByVegaKey.length ? (
|
{vestingAssociationByVegaKey.length ? (
|
||||||
<>
|
<>
|
||||||
@ -129,6 +130,7 @@ const ConnectedKey = () => {
|
|||||||
name="VEGA"
|
name="VEGA"
|
||||||
symbol="In vesting contract"
|
symbol="In vesting contract"
|
||||||
balance={totalInVestingContract}
|
balance={totalInVestingContract}
|
||||||
|
dark={true}
|
||||||
/>
|
/>
|
||||||
<LockedProgress
|
<LockedProgress
|
||||||
locked={totalLockedBalance}
|
locked={totalLockedBalance}
|
||||||
@ -136,7 +138,7 @@ const ConnectedKey = () => {
|
|||||||
total={totalVestedBalance.plus(totalLockedBalance)}
|
total={totalVestedBalance.plus(totalLockedBalance)}
|
||||||
leftLabel={t('Locked')}
|
leftLabel={t('Locked')}
|
||||||
rightLabel={t('Unlocked')}
|
rightLabel={t('Unlocked')}
|
||||||
light={true}
|
light={false}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -153,6 +155,7 @@ const ConnectedKey = () => {
|
|||||||
name="VEGA"
|
name="VEGA"
|
||||||
symbol="In Wallet"
|
symbol="In Wallet"
|
||||||
balance={walletWithAssociations}
|
balance={walletWithAssociations}
|
||||||
|
dark={true}
|
||||||
/>
|
/>
|
||||||
{!Object.keys(
|
{!Object.keys(
|
||||||
appState.associationBreakdown.stakingAssociations
|
appState.associationBreakdown.stakingAssociations
|
||||||
@ -163,15 +166,17 @@ const ConnectedKey = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<WalletCardActions>
|
<WalletCardActions>
|
||||||
<Link className="flex-1" to={`${Routes.STAKING}/associate`}>
|
<Link
|
||||||
<span className="flex items-center justify-center w-full text-center px-28 border h-28">
|
className={getButtonClasses('flex-1 mr-4', 'secondary')}
|
||||||
{t('associate')}
|
to={`${Routes.STAKING}/associate`}
|
||||||
</span>
|
>
|
||||||
|
{t('associate')}
|
||||||
</Link>
|
</Link>
|
||||||
<Link className="flex-1" to={`${Routes.STAKING}/disassociate`}>
|
<Link
|
||||||
<span className="flex items-center justify-center w-full px-28 border h-28">
|
className={getButtonClasses('flex-1 ml-4', 'secondary')}
|
||||||
{t('disassociate')}
|
to={`${Routes.STAKING}/disassociate`}
|
||||||
</span>
|
>
|
||||||
|
{t('disassociate')}
|
||||||
</Link>
|
</Link>
|
||||||
</WalletCardActions>
|
</WalletCardActions>
|
||||||
</>
|
</>
|
||||||
@ -185,7 +190,7 @@ export const EthWallet = () => {
|
|||||||
const pendingTxs = usePendingTransactions();
|
const pendingTxs = usePendingTransactions();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WalletCard>
|
<WalletCard dark={true}>
|
||||||
<WalletCardHeader>
|
<WalletCardHeader>
|
||||||
<h1 className="text-h3 uppercase">{t('ethereumKey')}</h1>
|
<h1 className="text-h3 uppercase">{t('ethereumKey')}</h1>
|
||||||
{account && (
|
{account && (
|
||||||
@ -203,7 +208,7 @@ export const EthWallet = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Loader size="small" forceTheme="light" />
|
<Loader size="small" forceTheme="dark" />
|
||||||
{t('pendingTransactions')}
|
{t('pendingTransactions')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -215,7 +220,8 @@ export const EthWallet = () => {
|
|||||||
{account ? (
|
{account ? (
|
||||||
<ConnectedKey />
|
<ConnectedKey />
|
||||||
) : (
|
) : (
|
||||||
<button
|
<Button
|
||||||
|
variant={'secondary'}
|
||||||
className="w-full px-28 border h-28"
|
className="w-full px-28 border h-28"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
appDispatch({
|
appDispatch({
|
||||||
@ -226,7 +232,7 @@ export const EthWallet = () => {
|
|||||||
data-test-id="connect-to-eth-wallet-button"
|
data-test-id="connect-to-eth-wallet-button"
|
||||||
>
|
>
|
||||||
{t('connectEthWalletToAssociate')}
|
{t('connectEthWalletToAssociate')}
|
||||||
</button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{account && (
|
{account && (
|
||||||
<WalletCardActions>
|
<WalletCardActions>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
import type { BigNumber } from '../../lib/bignumber';
|
import type { BigNumber } from '../../lib/bignumber';
|
||||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
const Colors = theme.colors;
|
const Colors = theme.colors;
|
||||||
|
|
||||||
@ -14,9 +14,10 @@ const ProgressContents = ({
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) => (
|
}) => (
|
||||||
<div
|
<div
|
||||||
className={`flex justify-between py-2 font-mono ${
|
className={classnames('flex justify-between py-2 font-mono', {
|
||||||
light ? 'gap-0 px-0 text-black' : 'gap-y-0 gap-x-4 px-4'
|
'gap-0 px-0 text-black': light,
|
||||||
}`}
|
'gap-y-0 gap-x-4': !light,
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
@ -25,17 +26,22 @@ const ProgressContents = ({
|
|||||||
const ProgressIndicator = ({
|
const ProgressIndicator = ({
|
||||||
bgColor,
|
bgColor,
|
||||||
side,
|
side,
|
||||||
|
light,
|
||||||
}: {
|
}: {
|
||||||
bgColor: string;
|
bgColor: string;
|
||||||
side: 'left' | 'right';
|
side: 'left' | 'right';
|
||||||
|
light: boolean;
|
||||||
}) => (
|
}) => (
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: bgColor,
|
backgroundColor: bgColor,
|
||||||
}}
|
}}
|
||||||
className={`inline-block w-12 h-12 border border-black ${
|
className={classnames('inline-block w-12 h-12 border', {
|
||||||
side === 'left' ? 'mr-8' : 'ml-8'
|
'mr-8': side === 'left',
|
||||||
}`}
|
'ml-8': side === 'right',
|
||||||
|
'border-black': light,
|
||||||
|
'border-white': !light,
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -64,6 +70,7 @@ export interface LockedProgressProps {
|
|||||||
leftColor?: string;
|
leftColor?: string;
|
||||||
rightColor?: string;
|
rightColor?: string;
|
||||||
light?: boolean;
|
light?: boolean;
|
||||||
|
decimals?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LockedProgress = ({
|
export const LockedProgress = ({
|
||||||
@ -73,8 +80,9 @@ export const LockedProgress = ({
|
|||||||
leftLabel,
|
leftLabel,
|
||||||
rightLabel,
|
rightLabel,
|
||||||
leftColor = Colors.vega.pink,
|
leftColor = Colors.vega.pink,
|
||||||
rightColor = Colors.green.DEFAULT,
|
rightColor = Colors.vega.green,
|
||||||
light = false,
|
light = false,
|
||||||
|
decimals = 2,
|
||||||
}: LockedProgressProps) => {
|
}: LockedProgressProps) => {
|
||||||
const lockedPercentage = React.useMemo(() => {
|
const lockedPercentage = React.useMemo(() => {
|
||||||
return locked.div(total).times(100);
|
return locked.div(total).times(100);
|
||||||
@ -85,26 +93,35 @@ export const LockedProgress = ({
|
|||||||
}, [total, unlocked]);
|
}, [total, unlocked]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border-x border-x-white">
|
<>
|
||||||
<div className={`flex ${light && 'border border-black'}`}>
|
<div
|
||||||
|
className={classnames('flex border', {
|
||||||
|
'border-black': light,
|
||||||
|
'border-white': !light,
|
||||||
|
})}
|
||||||
|
>
|
||||||
<ProgressBar percentage={lockedPercentage} bgColor={leftColor} />
|
<ProgressBar percentage={lockedPercentage} bgColor={leftColor} />
|
||||||
<ProgressBar percentage={unlockedPercentage} bgColor={rightColor} />
|
<ProgressBar percentage={unlockedPercentage} bgColor={rightColor} />
|
||||||
</div>
|
</div>
|
||||||
<ProgressContents light={light}>
|
<ProgressContents light={light}>
|
||||||
<span>
|
<span>
|
||||||
<ProgressIndicator bgColor={leftColor} side={'left'} />
|
<ProgressIndicator bgColor={leftColor} side={'left'} light={false} />
|
||||||
{leftLabel}
|
{leftLabel}
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{rightLabel}
|
{rightLabel}
|
||||||
<ProgressIndicator bgColor={rightColor} side={'right'} />
|
<ProgressIndicator
|
||||||
|
bgColor={rightColor}
|
||||||
|
side={'right'}
|
||||||
|
light={false}
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
</ProgressContents>
|
</ProgressContents>
|
||||||
|
|
||||||
<ProgressContents light={light}>
|
<ProgressContents light={light}>
|
||||||
<span>{formatNumber(locked, 2)}</span>
|
<span>{formatNumber(locked, decimals)}</span>
|
||||||
<span>{formatNumber(unlocked, 2)}</span>
|
<span>{formatNumber(unlocked, decimals)}</span>
|
||||||
</ProgressContents>
|
</ProgressContents>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -12,7 +12,7 @@ export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) {
|
|||||||
<div className="border-b border-white lg:grid lg:grid-rows-[auto_minmax(600px,_1fr)] lg:grid-cols-[1fr_450px]">
|
<div className="border-b border-white lg:grid lg:grid-rows-[auto_minmax(600px,_1fr)] lg:grid-cols-[1fr_450px]">
|
||||||
<Nav />
|
<Nav />
|
||||||
<main className="p-20">{children}</main>
|
<main className="p-20">{children}</main>
|
||||||
<aside className="hidden lg:block lg:col-start-2 lg:col-end-3 lg:row-start-1 lg: row-end-3 p-20 bg-banner bg-contain border-l border-white">
|
<aside className="hidden lg:block lg:col-start-2 lg:col-end-4 lg:row-start-1 lg: row-end-4 p-20 bg-banner bg-contain border-l border-white">
|
||||||
{sidebar.map((Component, i) => (
|
{sidebar.map((Component, i) => (
|
||||||
<section className="mb-20 last:mb-0" key={i}>
|
<section className="mb-20 last:mb-0" key={i}>
|
||||||
{Component}
|
{Component}
|
||||||
|
@ -180,15 +180,15 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<WalletCardActions>
|
<WalletCardActions>
|
||||||
<Link style={{ flex: 1 }} to={Routes.GOVERNANCE}>
|
<Link className="flex-1 pr-8" to={Routes.GOVERNANCE}>
|
||||||
<span className="flex items-center justify-center w-full px-28 border h-28 bg-white text-black">
|
<Button variant={'secondary'} className="w-full">
|
||||||
{t('governance')}
|
{t('governance')}
|
||||||
</span>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
<Link style={{ flex: 1 }} to={Routes.STAKING}>
|
<Link className="flex-1 pl-8" to={Routes.STAKING}>
|
||||||
<span className="flex items-center justify-center w-full px-28 border h-28 bg-white text-black">
|
<Button variant={'secondary'} className="w-full">
|
||||||
{t('staking')}
|
{t('staking')}
|
||||||
</span>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</WalletCardActions>
|
</WalletCardActions>
|
||||||
<VegaWalletAssetList accounts={accounts} />
|
<VegaWalletAssetList accounts={accounts} />
|
||||||
|
@ -55,6 +55,9 @@ export const ENV = {
|
|||||||
commit: windowOrDefault('NX_COMMIT_REF'),
|
commit: windowOrDefault('NX_COMMIT_REF'),
|
||||||
branch: windowOrDefault('NX_BRANCH'),
|
branch: windowOrDefault('NX_BRANCH'),
|
||||||
vegaUrl: windowOrDefault('NX_VEGA_URL'),
|
vegaUrl: windowOrDefault('NX_VEGA_URL'),
|
||||||
|
urlConnect: TRUTHY.includes(windowOrDefault('NX_ETH_URL_CONNECT')),
|
||||||
|
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
||||||
|
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
||||||
flags: {
|
flags: {
|
||||||
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
|
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
|
||||||
HOSTED_WALLET_ENABLED: TRUTHY.includes(
|
HOSTED_WALLET_ENABLED: TRUTHY.includes(
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
|
||||||
import mock from './tranches-mock';
|
import mock from './tranches-mock';
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
||||||
|
|
||||||
export function useTranches() {
|
export function useTranches() {
|
||||||
const { vesting } = useContracts();
|
|
||||||
const [tranches, setTranches] = React.useState<Tranche[] | null>(null);
|
const [tranches, setTranches] = React.useState<Tranche[] | null>(null);
|
||||||
const [error, setError] = React.useState<string | null>(null);
|
const [error, setError] = React.useState<string | null>(null);
|
||||||
|
|
||||||
@ -17,7 +15,7 @@ export function useTranches() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
run();
|
run();
|
||||||
}, [vesting]);
|
}, []);
|
||||||
|
|
||||||
return { tranches, error };
|
return { tranches, error };
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -7,23 +8,26 @@ import {
|
|||||||
import { useContracts } from '../contexts/contracts/contracts-context';
|
import { useContracts } from '../contexts/contracts/contracts-context';
|
||||||
|
|
||||||
export function useRefreshAssociatedBalances() {
|
export function useRefreshAssociatedBalances() {
|
||||||
const { appDispatch } = useAppState();
|
const {
|
||||||
|
appDispatch,
|
||||||
|
appState: { decimals },
|
||||||
|
} = useAppState();
|
||||||
const { staking, vesting } = useContracts();
|
const { staking, vesting } = useContracts();
|
||||||
|
|
||||||
return React.useCallback(
|
return React.useCallback(
|
||||||
async (ethAddress: string, vegaKey: string) => {
|
async (ethAddress: string, vegaKey: string) => {
|
||||||
const [walletAssociatedBalance, vestingAssociatedBalance] =
|
const [walletAssociatedBalance, vestingAssociatedBalance] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
staking.stakeBalance(ethAddress, `0x${vegaKey}`),
|
staking.stakeBalance(ethAddress, vegaKey),
|
||||||
vesting.stakeBalance(ethAddress, `0x${vegaKey}`),
|
vesting.stakeBalance(ethAddress, vegaKey),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
appDispatch({
|
appDispatch({
|
||||||
type: AppStateActionType.REFRESH_ASSOCIATED_BALANCES,
|
type: AppStateActionType.REFRESH_ASSOCIATED_BALANCES,
|
||||||
walletAssociatedBalance,
|
walletAssociatedBalance: toBigNum(walletAssociatedBalance, decimals),
|
||||||
vestingAssociatedBalance,
|
vestingAssociatedBalance: toBigNum(vestingAssociatedBalance, decimals),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[staking, vesting, appDispatch]
|
[staking, vesting, appDispatch, decimals]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -193,6 +193,7 @@
|
|||||||
"noGovernanceTokens": "You need some VEGA tokens to participate in governance",
|
"noGovernanceTokens": "You need some VEGA tokens to participate in governance",
|
||||||
"youVoted": "You voted",
|
"youVoted": "You voted",
|
||||||
"changeVote": "Change vote",
|
"changeVote": "Change vote",
|
||||||
|
"voteRequested": "Please confirm transaction in wallet",
|
||||||
"votePending": "Casting vote",
|
"votePending": "Casting vote",
|
||||||
"voteError": "Something went wrong, and your vote was not seen by the network",
|
"voteError": "Something went wrong, and your vote was not seen by the network",
|
||||||
"back": "back",
|
"back": "back",
|
||||||
@ -280,6 +281,7 @@
|
|||||||
"stakingHasAssociated": "You have {{tokens}} $VEGA tokens associated.",
|
"stakingHasAssociated": "You have {{tokens}} $VEGA tokens associated.",
|
||||||
"stakingAssociateMoreButton": "Associate more $VEGA tokens with wallet",
|
"stakingAssociateMoreButton": "Associate more $VEGA tokens with wallet",
|
||||||
"stakingDisassociateButton": "Disassociate $VEGA tokens from wallet",
|
"stakingDisassociateButton": "Disassociate $VEGA tokens from wallet",
|
||||||
|
"stakingConfirm": "Open you wallet app to confirm",
|
||||||
"associateButton": "Associate $VEGA tokens with wallet",
|
"associateButton": "Associate $VEGA tokens with wallet",
|
||||||
"nodeQueryFailed": "Could not get data for validator {{node}}",
|
"nodeQueryFailed": "Could not get data for validator {{node}}",
|
||||||
"stakeAddPendingTitle": "Adding {{amount}} $VEGA to validator {{node}}",
|
"stakeAddPendingTitle": "Adding {{amount}} $VEGA to validator {{node}}",
|
||||||
@ -540,5 +542,8 @@
|
|||||||
"numberOfAgainstVotes": "Number of votes against",
|
"numberOfAgainstVotes": "Number of votes against",
|
||||||
"yesPercentage": "Yes percentage",
|
"yesPercentage": "Yes percentage",
|
||||||
"noPercentage": "No percentage",
|
"noPercentage": "No percentage",
|
||||||
"proposalTerms": "Proposal terms"
|
"proposalTerms": "Proposal terms",
|
||||||
|
"currentlySetTo": "Currently set to ",
|
||||||
|
"pass": "Pass",
|
||||||
|
"fail": "Fail"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-black w-full h-full">
|
<html lang="en" class="dark bg-black w-full h-full">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="stylesheet" href="//static.vega.xyz/fonts.css" />
|
<link rel="stylesheet" href="//static.vega.xyz/fonts.css" />
|
||||||
|
150
apps/token/src/lib/url-connector.ts
Normal file
150
apps/token/src/lib/url-connector.ts
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
import { ethers, Wallet } from 'ethers';
|
||||||
|
import { Connector } from '@web3-react/types';
|
||||||
|
|
||||||
|
import { Eip1193Bridge } from '@ethersproject/experimental';
|
||||||
|
import type { ConnectionInfo } from '@ethersproject/web';
|
||||||
|
import type { Actions } from '@web3-react/types';
|
||||||
|
import { ENV } from '../config/env';
|
||||||
|
|
||||||
|
export class CustomizedBridge extends Eip1193Bridge {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
async sendAsync(...args: any) {
|
||||||
|
console.debug('sendAsync called', ...args);
|
||||||
|
return this.send(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
override async send(...args: any) {
|
||||||
|
console.debug('send called', ...args);
|
||||||
|
const isCallbackForm =
|
||||||
|
typeof args[0] === 'object' && typeof args[1] === 'function';
|
||||||
|
let callback;
|
||||||
|
let method;
|
||||||
|
let params;
|
||||||
|
if (isCallbackForm) {
|
||||||
|
callback = args[1];
|
||||||
|
method = args[0].method;
|
||||||
|
params = args[0].params;
|
||||||
|
} else {
|
||||||
|
method = args[0];
|
||||||
|
params = args[1];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Hacky, https://github.com/ethers-io/ethers.js/issues/1683#issuecomment-1016227588
|
||||||
|
|
||||||
|
// If from is present on eth_call it errors, removing it makes the library set
|
||||||
|
// from as the connected wallet which works fine
|
||||||
|
if (params && params.length && params[0].from && method === 'eth_call')
|
||||||
|
delete params[0].from;
|
||||||
|
let result;
|
||||||
|
// For sending a transaction if we call send it will error
|
||||||
|
// as it wants gasLimit in sendTransaction but hexlify sets the property gas
|
||||||
|
// to gasLimit which makes sensd transaction error.
|
||||||
|
// This has taken the code from the super method for sendTransaction and altered
|
||||||
|
// it slightly to make it work with the gas limit issues.
|
||||||
|
if (
|
||||||
|
params &&
|
||||||
|
params.length &&
|
||||||
|
params[0].from &&
|
||||||
|
method === 'eth_sendTransaction'
|
||||||
|
) {
|
||||||
|
// Hexlify will not take gas, must be gasLimit, set this property to be gasLimit
|
||||||
|
params[0].gasLimit = params[0].gas;
|
||||||
|
delete params[0].gas;
|
||||||
|
// If from is present on eth_sendTransaction it errors, removing it makes the library set
|
||||||
|
// from as the connected wallet which works fine
|
||||||
|
delete params[0].from;
|
||||||
|
const req = ethers.providers.JsonRpcProvider.hexlifyTransaction(
|
||||||
|
params[0]
|
||||||
|
);
|
||||||
|
// Hexlify sets the gasLimit property to be gas again and send transaction requires gasLimit
|
||||||
|
req['gasLimit'] = req['gas'];
|
||||||
|
delete req['gas'];
|
||||||
|
|
||||||
|
if (!this.signer) {
|
||||||
|
throw new Error('No signer');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the transaction
|
||||||
|
const tx = await this.signer.sendTransaction(req);
|
||||||
|
result = tx.hash;
|
||||||
|
} else {
|
||||||
|
// All other transactions the base class works for
|
||||||
|
result = await super.send(method, params);
|
||||||
|
}
|
||||||
|
console.debug('result received', method, params, result);
|
||||||
|
if (isCallbackForm) {
|
||||||
|
callback(null, { result });
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
if (isCallbackForm) {
|
||||||
|
callback(error, null);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type url = string | ConnectionInfo;
|
||||||
|
|
||||||
|
export class Url extends Connector {
|
||||||
|
/** {@inheritdoc Connector.provider} */
|
||||||
|
public override provider: Eip1193Bridge | undefined;
|
||||||
|
|
||||||
|
private eagerConnection?: Promise<void>;
|
||||||
|
private url: url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param url - An RPC url.
|
||||||
|
* @param connectEagerly - A flag indicating whether connection should be initiated when the class is constructed.
|
||||||
|
*/
|
||||||
|
constructor(actions: Actions, url: url, connectEagerly = false) {
|
||||||
|
super(actions);
|
||||||
|
|
||||||
|
if (connectEagerly && typeof window === 'undefined') {
|
||||||
|
throw new Error(
|
||||||
|
'connectEagerly = true is invalid for SSR, instead use the activate method in a useEffect'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.url = url;
|
||||||
|
|
||||||
|
if (connectEagerly) void this.activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async isomorphicInitialize() {
|
||||||
|
if (this.eagerConnection) return this.eagerConnection;
|
||||||
|
|
||||||
|
await (this.eagerConnection = import('@ethersproject/providers')
|
||||||
|
.then(({ JsonRpcProvider }) => JsonRpcProvider)
|
||||||
|
.then((JsonRpcProvider) => {
|
||||||
|
const provider = new JsonRpcProvider(this.url);
|
||||||
|
const privateKey = Wallet.fromMnemonic(
|
||||||
|
ENV.ethWalletMnemonic,
|
||||||
|
`m/44'/60'/0'/0/0`
|
||||||
|
).privateKey;
|
||||||
|
const signer = new Wallet(privateKey, provider);
|
||||||
|
this.provider = new CustomizedBridge(signer, provider);
|
||||||
|
this.actions.update({ accounts: [signer.address], chainId: 1440 });
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritdoc Connector.activate} */
|
||||||
|
public async activate(): Promise<void> {
|
||||||
|
this.actions.startActivation();
|
||||||
|
|
||||||
|
await this.isomorphicInitialize();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
const chainId = await this.provider!.request({ method: 'eth_chainId' });
|
||||||
|
this.actions.update({ chainId: Number(chainId) });
|
||||||
|
} catch (error) {
|
||||||
|
this.actions.reportError(error as Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,11 +3,18 @@ import type { Web3ReactHooks } from '@web3-react/core';
|
|||||||
import { initializeConnector } from '@web3-react/core';
|
import { initializeConnector } from '@web3-react/core';
|
||||||
import { MetaMask } from '@web3-react/metamask';
|
import { MetaMask } from '@web3-react/metamask';
|
||||||
import { WalletConnect } from '@web3-react/walletconnect';
|
import { WalletConnect } from '@web3-react/walletconnect';
|
||||||
|
import { Url } from './url-connector';
|
||||||
|
import type { Connector } from '@web3-react/types';
|
||||||
|
import { ENV } from '../config/env';
|
||||||
|
|
||||||
const [metamask, metamaskHooks] = initializeConnector<MetaMask>(
|
const [metamask, metamaskHooks] = initializeConnector<MetaMask>(
|
||||||
(actions) => new MetaMask(actions)
|
(actions) => new MetaMask(actions)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [urlConnector, urlHooks] = initializeConnector<Url>(
|
||||||
|
(actions) => new Url(actions, ENV.localProviderUrl)
|
||||||
|
);
|
||||||
|
|
||||||
export const createDefaultProvider = (providerUrl: string, chainId: number) => {
|
export const createDefaultProvider = (providerUrl: string, chainId: number) => {
|
||||||
return new ethers.providers.JsonRpcProvider(providerUrl, chainId);
|
return new ethers.providers.JsonRpcProvider(providerUrl, chainId);
|
||||||
};
|
};
|
||||||
@ -27,7 +34,8 @@ export const createConnectors = (providerUrl: string, chainId: number) => {
|
|||||||
[chainId]
|
[chainId]
|
||||||
);
|
);
|
||||||
return [
|
return [
|
||||||
|
ENV.urlConnect ? [urlConnector, urlHooks] : null,
|
||||||
[metamask, metamaskHooks],
|
[metamask, metamaskHooks],
|
||||||
[walletconnect, walletconnectHooks],
|
[walletconnect, walletconnectHooks],
|
||||||
] as [MetaMask | WalletConnect, Web3ReactHooks][];
|
].filter(Boolean) as [Connector, Web3ReactHooks][];
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,7 @@ export const TargetAddressMismatch = ({
|
|||||||
}}
|
}}
|
||||||
components={{
|
components={{
|
||||||
bold: <strong />,
|
bold: <strong />,
|
||||||
red: <span className={'text-red'} />,
|
red: <span className={'text-vega-red'} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
@ -43,7 +43,7 @@ const Contracts = () => {
|
|||||||
title={t('View address on Etherscan')}
|
title={t('View address on Etherscan')}
|
||||||
href={`${ETHERSCAN_URL}/address/${contract.address}`}
|
href={`${ETHERSCAN_URL}/address/${contract.address}`}
|
||||||
>
|
>
|
||||||
{config.collateral_bridge_contract.address}
|
{contract.address}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -58,7 +58,6 @@ const Contracts = () => {
|
|||||||
title={t('View address on Etherscan')}
|
title={t('View address on Etherscan')}
|
||||||
href={`${ETHERSCAN_URL}/address/${value}`}
|
href={`${ETHERSCAN_URL}/address/${value}`}
|
||||||
>
|
>
|
||||||
asdfasd
|
|
||||||
{value}
|
{value}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,30 +34,22 @@ export const CurrentProposalStatus = ({
|
|||||||
{ addSuffix: true }
|
{ addSuffix: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
if (proposal.state === ProposalState.Open && willPass) {
|
if (proposal.state === ProposalState.Open) {
|
||||||
return <StatusPass>{t('shouldPass')}</StatusPass>;
|
if (willPass) {
|
||||||
}
|
return (
|
||||||
|
<>
|
||||||
if (!participationMet) {
|
{t('currentlySetTo')}
|
||||||
return (
|
<StatusPass>{t('pass')}</StatusPass>
|
||||||
<>
|
</>
|
||||||
<span>{t('voteFailedReason')}</span>
|
);
|
||||||
<span className="current-proposal-status__fail">
|
} else {
|
||||||
{t('participationNotMet')}
|
return (
|
||||||
</span>
|
<>
|
||||||
<span> {daysClosedAgo}.</span>
|
{t('currentlySetTo')}
|
||||||
</>
|
<StatusFail>{t('fail')}</StatusFail>
|
||||||
);
|
</>
|
||||||
}
|
);
|
||||||
|
}
|
||||||
if (!majorityMet) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<span>{t('voteFailedReason')}</span>
|
|
||||||
<StatusFail>{t('majorityNotMet')}</StatusFail>
|
|
||||||
<span> {daysClosedAgo}.</span>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -65,6 +57,26 @@ export const CurrentProposalStatus = ({
|
|||||||
proposal.state === ProposalState.Declined ||
|
proposal.state === ProposalState.Declined ||
|
||||||
proposal.state === ProposalState.Rejected
|
proposal.state === ProposalState.Rejected
|
||||||
) {
|
) {
|
||||||
|
if (!participationMet) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span>{t('voteFailedReason')}</span>
|
||||||
|
<StatusFail>{t('participationNotMet')}</StatusFail>
|
||||||
|
<span> {daysClosedAgo}.</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!majorityMet) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span>{t('voteFailedReason')}</span>
|
||||||
|
<StatusFail>{t('majorityNotMet')}</StatusFail>
|
||||||
|
<span> {daysClosedAgo}.</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>{t('voteFailedReason')}</span>
|
<span>{t('voteFailedReason')}</span>
|
||||||
|
@ -17,6 +17,7 @@ export enum VoteState {
|
|||||||
NotCast = 'NotCast',
|
NotCast = 'NotCast',
|
||||||
Yes = 'Yes',
|
Yes = 'Yes',
|
||||||
No = 'No',
|
No = 'No',
|
||||||
|
Requested = 'Requested',
|
||||||
Pending = 'Pending',
|
Pending = 'Pending',
|
||||||
Failed = 'Failed',
|
Failed = 'Failed',
|
||||||
}
|
}
|
||||||
@ -69,7 +70,7 @@ export function useUserVote(
|
|||||||
}
|
}
|
||||||
}, [userVote]);
|
}, [userVote]);
|
||||||
|
|
||||||
// Start a starts a timeout of 30s to set a failed message if
|
// Starts a timeout of 30s to set a failed message if
|
||||||
// the vote is not seen by the time the callback is invoked
|
// the vote is not seen by the time the callback is invoked
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
@ -93,7 +94,7 @@ export function useUserVote(
|
|||||||
async function castVote(value: VoteValue) {
|
async function castVote(value: VoteValue) {
|
||||||
if (!proposalId || !keypair) return;
|
if (!proposalId || !keypair) return;
|
||||||
|
|
||||||
setVoteState(VoteState.Pending);
|
setVoteState(VoteState.Requested);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const variables = {
|
const variables = {
|
||||||
@ -105,6 +106,7 @@ export function useUserVote(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
await sendTx(variables);
|
await sendTx(variables);
|
||||||
|
setVoteState(VoteState.Pending);
|
||||||
|
|
||||||
// Now await vote via poll in parent component
|
// Now await vote via poll in parent component
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -124,6 +124,10 @@ export const VoteButtons = ({
|
|||||||
return <p>{cantVoteUI}</p>;
|
return <p>{cantVoteUI}</p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (voteState === VoteState.Requested) {
|
||||||
|
return <p>{t('voteRequested')}...</p>;
|
||||||
|
}
|
||||||
|
|
||||||
if (voteState === VoteState.Pending) {
|
if (voteState === VoteState.Pending) {
|
||||||
return <p>{t('votePending')}...</p>;
|
return <p>{t('votePending')}...</p>;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ export const VoteDetails = ({ proposal }: VoteDetailsProps) => {
|
|||||||
<span>
|
<span>
|
||||||
<CurrentProposalStatus proposal={proposal} />
|
<CurrentProposalStatus proposal={proposal} />
|
||||||
</span>
|
</span>
|
||||||
.
|
{'. '}
|
||||||
{proposal.state === ProposalState.Open ? daysLeft : null}
|
{proposal.state === ProposalState.Open ? daysLeft : null}
|
||||||
</p>
|
</p>
|
||||||
<table className="w-full font-normal mb-12">
|
<table className="w-full font-normal mb-12">
|
||||||
|
@ -24,6 +24,7 @@ export const ProposalsContainer = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { data, loading, error } = useQuery<Proposals, never>(PROPOSALS_QUERY, {
|
const { data, loading, error } = useQuery<Proposals, never>(PROPOSALS_QUERY, {
|
||||||
pollInterval: 5000,
|
pollInterval: 5000,
|
||||||
|
errorPolicy: 'ignore', // this is to get around some backend issues and should be removed in future
|
||||||
});
|
});
|
||||||
|
|
||||||
const proposals = React.useMemo(() => {
|
const proposals = React.useMemo(() => {
|
||||||
|
@ -52,7 +52,13 @@ const Home = ({ name }: RouteChildProps) => {
|
|||||||
<Trans
|
<Trans
|
||||||
i18nKey="Tokens are held in different <trancheLink>Tranches</trancheLink>. Each tranche has its own schedule for how the tokens are unlocked."
|
i18nKey="Tokens are held in different <trancheLink>Tranches</trancheLink>. Each tranche has its own schedule for how the tokens are unlocked."
|
||||||
components={{
|
components={{
|
||||||
trancheLink: <Link to={Routes.TRANCHES} />,
|
trancheLink: (
|
||||||
|
<Link
|
||||||
|
data-testid="tranches-link"
|
||||||
|
to={Routes.TRANCHES}
|
||||||
|
className="underline text-white"
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
@ -62,7 +68,7 @@ const Home = ({ name }: RouteChildProps) => {
|
|||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<Link to={Routes.VESTING}>
|
<Link to={Routes.VESTING}>
|
||||||
<Button variant="secondary" data-test-id="check-vesting-page-btn">
|
<Button variant="secondary" data-testid="check-vesting-page-btn">
|
||||||
{t('Check to see if you can redeem unlocked VEGA tokens')}
|
{t('Check to see if you can redeem unlocked VEGA tokens')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -81,7 +87,7 @@ const Home = ({ name }: RouteChildProps) => {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a
|
<a
|
||||||
data-test-id="get-vega-wallet-link"
|
data-testid="get-vega-wallet-link"
|
||||||
href={Links.WALLET_GUIDE}
|
href={Links.WALLET_GUIDE}
|
||||||
className="underline text-white"
|
className="underline text-white"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -90,8 +96,9 @@ const Home = ({ name }: RouteChildProps) => {
|
|||||||
{t('Get a Vega wallet')}
|
{t('Get a Vega wallet')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p data-test-id="associate-vega-tokens-link-on-homepage">
|
<p>
|
||||||
<Link
|
<Link
|
||||||
|
data-testid="associate-vega-tokens-link-on-homepage"
|
||||||
to={`${Routes.STAKING}/associate`}
|
to={`${Routes.STAKING}/associate`}
|
||||||
className="underline text-white"
|
className="underline text-white"
|
||||||
>
|
>
|
||||||
@ -110,7 +117,12 @@ const Home = ({ name }: RouteChildProps) => {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link to={Routes.STAKING}>
|
<Link to={Routes.STAKING}>
|
||||||
<Button variant="secondary">{t('Nominate a validator')}</Button>
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
data-testid="staking-button-on-homepage"
|
||||||
|
>
|
||||||
|
{t('Nominate a validator')}
|
||||||
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</HomeSection>
|
</HomeSection>
|
||||||
@ -125,7 +137,10 @@ const Home = ({ name }: RouteChildProps) => {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link to={Routes.GOVERNANCE}>
|
<Link to={Routes.GOVERNANCE}>
|
||||||
<Button variant="secondary">
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
data-testid="governance-button-on-homepage"
|
||||||
|
>
|
||||||
{t('View Governance proposals')}
|
{t('View Governance proposals')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -8,7 +8,6 @@ import { Link } from 'react-router-dom';
|
|||||||
import { EthConnectPrompt } from '../../components/eth-connect-prompt';
|
import { EthConnectPrompt } from '../../components/eth-connect-prompt';
|
||||||
import { SplashLoader } from '../../components/splash-loader';
|
import { SplashLoader } from '../../components/splash-loader';
|
||||||
import { useAppState } from '../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
|
||||||
import { useTranches } from '../../hooks/use-tranches';
|
import { useTranches } from '../../hooks/use-tranches';
|
||||||
import { Routes as RoutesConfig } from '../router-config';
|
import { Routes as RoutesConfig } from '../router-config';
|
||||||
import {
|
import {
|
||||||
@ -19,7 +18,6 @@ import {
|
|||||||
|
|
||||||
const RedemptionRouter = () => {
|
const RedemptionRouter = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { vesting } = useContracts();
|
|
||||||
const [state, dispatch] = React.useReducer(
|
const [state, dispatch] = React.useReducer(
|
||||||
redemptionReducer,
|
redemptionReducer,
|
||||||
initialRedemptionState
|
initialRedemptionState
|
||||||
@ -49,7 +47,7 @@ const RedemptionRouter = () => {
|
|||||||
if (account) {
|
if (account) {
|
||||||
run(account);
|
run(account);
|
||||||
}
|
}
|
||||||
}, [account, tranches, vesting]);
|
}, [account, tranches]);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
|
@ -76,6 +76,7 @@ export const TrancheItem = ({
|
|||||||
total={total}
|
total={total}
|
||||||
leftLabel={t('Locked')}
|
leftLabel={t('Locked')}
|
||||||
rightLabel={t('Unlocked')}
|
rightLabel={t('Unlocked')}
|
||||||
|
decimals={18}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="text-right" data-testid="tranche-item-footer">
|
<div className="text-right" data-testid="tranche-item-footer">
|
||||||
|
@ -12,7 +12,7 @@ import { useTransaction } from '../../../hooks/use-transaction';
|
|||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { AssociateInfo } from './associate-info';
|
import { AssociateInfo } from './associate-info';
|
||||||
import type { VegaKeyExtended } from '@vegaprotocol/wallet';
|
import type { VegaKeyExtended } from '@vegaprotocol/wallet';
|
||||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
import { removeDecimal, toBigNum } from '@vegaprotocol/react-helpers';
|
||||||
import type { EthereumConfig } from '@vegaprotocol/web3';
|
import type { EthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
|
||||||
export const WalletAssociate = ({
|
export const WalletAssociate = ({
|
||||||
@ -35,19 +35,18 @@ export const WalletAssociate = ({
|
|||||||
appDispatch,
|
appDispatch,
|
||||||
appState: { walletBalance, allowance, walletAssociatedBalance, decimals },
|
appState: { walletBalance, allowance, walletAssociatedBalance, decimals },
|
||||||
} = useAppState();
|
} = useAppState();
|
||||||
|
|
||||||
const { token } = useContracts();
|
const { token } = useContracts();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
state: approveState,
|
state: approveState,
|
||||||
perform: approve,
|
perform: approve,
|
||||||
dispatch: approveDispatch,
|
dispatch: approveDispatch,
|
||||||
} = useTransaction(() =>
|
} = useTransaction(() => {
|
||||||
token.approve(
|
return token.approve(
|
||||||
ethereumConfig.staking_bridge_contract.address,
|
ethereumConfig.staking_bridge_contract.address,
|
||||||
Number.MAX_SAFE_INTEGER.toString()
|
removeDecimal('1000000', decimals).toString()
|
||||||
)
|
);
|
||||||
);
|
});
|
||||||
|
|
||||||
// Once they have approved deposits then we need to refresh their allowance
|
// Once they have approved deposits then we need to refresh their allowance
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
} from '../../../components/staking-method-radio';
|
} from '../../../components/staking-method-radio';
|
||||||
import { TxState } from '../../../hooks/transaction-reducer';
|
import { TxState } from '../../../hooks/transaction-reducer';
|
||||||
import { useSearchParams } from '../../../hooks/use-search-params';
|
import { useSearchParams } from '../../../hooks/use-search-params';
|
||||||
|
import { useRefreshAssociatedBalances } from '../../../hooks/use-refresh-associated-balances';
|
||||||
import { ContractDisassociate } from './contract-disassociate';
|
import { ContractDisassociate } from './contract-disassociate';
|
||||||
import { DisassociateTransaction } from './disassociate-transaction';
|
import { DisassociateTransaction } from './disassociate-transaction';
|
||||||
import { useRemoveStake } from './hooks';
|
import { useRemoveStake } from './hooks';
|
||||||
@ -26,6 +27,7 @@ export const DisassociatePage = ({
|
|||||||
const [amount, setAmount] = React.useState<string>('');
|
const [amount, setAmount] = React.useState<string>('');
|
||||||
const [selectedStakingMethod, setSelectedStakingMethod] =
|
const [selectedStakingMethod, setSelectedStakingMethod] =
|
||||||
React.useState<StakingMethod | null>(params.method || null);
|
React.useState<StakingMethod | null>(params.method || null);
|
||||||
|
const refreshBalances = useRefreshAssociatedBalances();
|
||||||
|
|
||||||
// Clear the amount when the staking method changes
|
// Clear the amount when the staking method changes
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -38,6 +40,12 @@ export const DisassociatePage = ({
|
|||||||
perform: txPerform,
|
perform: txPerform,
|
||||||
} = useRemoveStake(address, amount, vegaKey.pub, selectedStakingMethod);
|
} = useRemoveStake(address, amount, vegaKey.pub, selectedStakingMethod);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (txState.txState === TxState.Complete) {
|
||||||
|
refreshBalances(address, vegaKey.pub);
|
||||||
|
}
|
||||||
|
}, [txState, refreshBalances, address, vegaKey.pub]);
|
||||||
|
|
||||||
if (txState.txState !== TxState.Default) {
|
if (txState.txState !== TxState.Default) {
|
||||||
return (
|
return (
|
||||||
<DisassociateTransaction
|
<DisassociateTransaction
|
||||||
|
@ -18,7 +18,14 @@ import type {
|
|||||||
import { StakeFailure } from './stake-failure';
|
import { StakeFailure } from './stake-failure';
|
||||||
import { StakePending } from './stake-pending';
|
import { StakePending } from './stake-pending';
|
||||||
import { StakeSuccess } from './stake-success';
|
import { StakeSuccess } from './stake-success';
|
||||||
import { Button, FormGroup, RadioGroup, Radio } from '@vegaprotocol/ui-toolkit';
|
import {
|
||||||
|
Button,
|
||||||
|
Callout,
|
||||||
|
FormGroup,
|
||||||
|
Intent,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import type {
|
import type {
|
||||||
DelegateSubmissionBody,
|
DelegateSubmissionBody,
|
||||||
@ -46,6 +53,7 @@ export const PARTY_DELEGATIONS_QUERY = gql`
|
|||||||
|
|
||||||
enum FormState {
|
enum FormState {
|
||||||
Default,
|
Default,
|
||||||
|
Requested,
|
||||||
Pending,
|
Pending,
|
||||||
Success,
|
Success,
|
||||||
Failure,
|
Failure,
|
||||||
@ -115,7 +123,7 @@ export const StakingForm = ({
|
|||||||
}, [action, availableStakeToAdd, availableStakeToRemove]);
|
}, [action, availableStakeToAdd, availableStakeToRemove]);
|
||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
setFormState(FormState.Pending);
|
setFormState(FormState.Requested);
|
||||||
const delegateInput: DelegateSubmissionBody = {
|
const delegateInput: DelegateSubmissionBody = {
|
||||||
pubKey: pubkey,
|
pubKey: pubkey,
|
||||||
propagate: true,
|
propagate: true,
|
||||||
@ -139,6 +147,7 @@ export const StakingForm = ({
|
|||||||
try {
|
try {
|
||||||
const command = action === Actions.Add ? delegateInput : undelegateInput;
|
const command = action === Actions.Add ? delegateInput : undelegateInput;
|
||||||
await sendTx(command);
|
await sendTx(command);
|
||||||
|
setFormState(FormState.Pending);
|
||||||
|
|
||||||
// await success via poll
|
// await success via poll
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -184,6 +193,12 @@ export const StakingForm = ({
|
|||||||
|
|
||||||
if (formState === FormState.Failure) {
|
if (formState === FormState.Failure) {
|
||||||
return <StakeFailure nodeName={nodeName} />;
|
return <StakeFailure nodeName={nodeName} />;
|
||||||
|
} else if (formState === FormState.Requested) {
|
||||||
|
return (
|
||||||
|
<Callout title="Confirm transaction in wallet" intent={Intent.Warning}>
|
||||||
|
<p>{t('stakingConfirm')}</p>
|
||||||
|
</Callout>
|
||||||
|
);
|
||||||
} else if (formState === FormState.Pending) {
|
} else if (formState === FormState.Pending) {
|
||||||
return <StakePending action={action} amount={amount} nodeName={nodeName} />;
|
return <StakePending action={action} amount={amount} nodeName={nodeName} />;
|
||||||
} else if (formState === FormState.Success) {
|
} else if (formState === FormState.Success) {
|
||||||
|
@ -88,7 +88,9 @@ export const StakingNode = ({ vegaKey, data }: StakingNodeProps) => {
|
|||||||
|
|
||||||
if (!nodeInfo) {
|
if (!nodeInfo) {
|
||||||
return (
|
return (
|
||||||
<span className={'text-red'}>{t('stakingNodeNotFound', { node })}</span>
|
<span className={'text-vega-red'}>
|
||||||
|
{t('stakingNodeNotFound', { node })}
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ export const TrancheProgress = ({
|
|||||||
<span className="tranches__progress-title">{t('Redeemed')}</span>
|
<span className="tranches__progress-title">{t('Redeemed')}</span>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
width={220}
|
width={220}
|
||||||
color={Colors.green.DEFAULT}
|
color={Colors.vega.green}
|
||||||
percentage={removedPercentage}
|
percentage={removedPercentage}
|
||||||
/>
|
/>
|
||||||
<span className="tranches__progress-numbers">
|
<span className="tranches__progress-numbers">
|
||||||
|
@ -36,7 +36,7 @@ export const VestingChart = () => {
|
|||||||
['pink', Colors.vega.pink],
|
['pink', Colors.vega.pink],
|
||||||
['green', Colors.vega.green],
|
['green', Colors.vega.green],
|
||||||
['orange', Colors.orange],
|
['orange', Colors.orange],
|
||||||
['yellow', Colors.yellow.DEFAULT],
|
['yellow', Colors.vega.yellow],
|
||||||
].map(([key, color]) => (
|
].map(([key, color]) => (
|
||||||
<linearGradient key={key} id={key} x1="0" y1="0" x2="0" y2="1">
|
<linearGradient key={key} id={key} x1="0" y1="0" x2="0" y2="1">
|
||||||
<stop offset="0%" stopColor={color} stopOpacity={0.85} />
|
<stop offset="0%" stopColor={color} stopOpacity={0.85} />
|
||||||
@ -119,7 +119,7 @@ export const VestingChart = () => {
|
|||||||
dot={false}
|
dot={false}
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="publicSale"
|
dataKey="publicSale"
|
||||||
stroke={Colors.yellow.DEFAULT}
|
stroke={Colors.vega.yellow}
|
||||||
fill="url(#yellow)"
|
fill="url(#yellow)"
|
||||||
yAxisId={0}
|
yAxisId={0}
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
|
@ -19,12 +19,14 @@ describe('orders', () => {
|
|||||||
const orderTimeInForce = 'timeInForce';
|
const orderTimeInForce = 'timeInForce';
|
||||||
const orderCreatedAt = 'createdAt';
|
const orderCreatedAt = 'createdAt';
|
||||||
|
|
||||||
it('renders orders', () => {
|
beforeEach(() => {
|
||||||
cy.getByTestId('Orders').click();
|
cy.getByTestId('Orders').click();
|
||||||
cy.getByTestId('tab-orders').contains('Please connect Vega wallet');
|
cy.getByTestId('tab-orders').contains('Please connect Vega wallet');
|
||||||
|
|
||||||
connectVegaWallet();
|
connectVegaWallet();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders orders', () => {
|
||||||
cy.getByTestId('tab-orders').should('be.visible');
|
cy.getByTestId('tab-orders').should('be.visible');
|
||||||
|
|
||||||
cy.getByTestId('tab-orders')
|
cy.getByTestId('tab-orders')
|
||||||
@ -68,4 +70,17 @@ describe('orders', () => {
|
|||||||
cy.wrap($dateTime).invoke('text').should('not.be.empty');
|
cy.wrap($dateTime).invoke('text').should('not.be.empty');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('orders are sorted by most recent order', () => {
|
||||||
|
const expectedOrderList = ['TSLA.QM21', 'BTCUSD.MF21', 'AAVEDAI.MF21'];
|
||||||
|
|
||||||
|
cy.getByTestId('tab-orders')
|
||||||
|
.get(`[col-id='${orderSymbol}']`)
|
||||||
|
.should('have.length.at.least', 3)
|
||||||
|
.each(($symbol, index) => {
|
||||||
|
if (index != 0) {
|
||||||
|
cy.wrap($symbol).should('have.text', expectedOrderList[index - 1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -15,50 +15,6 @@ export const generateDealTicketQuery = (
|
|||||||
positionDecimalPlaces: 0,
|
positionDecimalPlaces: 0,
|
||||||
state: MarketState.Active,
|
state: MarketState.Active,
|
||||||
tradingMode: MarketTradingMode.Continuous,
|
tradingMode: MarketTradingMode.Continuous,
|
||||||
fees: {
|
|
||||||
__typename: 'Fees',
|
|
||||||
factors: {
|
|
||||||
__typename: 'FeeFactors',
|
|
||||||
makerFee: '0.0002',
|
|
||||||
infrastructureFee: '0.0005',
|
|
||||||
liquidityFee: '0.01',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
priceMonitoringSettings: {
|
|
||||||
__typename: 'PriceMonitoringSettings',
|
|
||||||
parameters: {
|
|
||||||
__typename: 'PriceMonitoringParameters',
|
|
||||||
triggers: [
|
|
||||||
{
|
|
||||||
__typename: 'PriceMonitoringTrigger',
|
|
||||||
horizonSecs: 43200,
|
|
||||||
probability: 0.9999999,
|
|
||||||
auctionExtensionSecs: 600,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
updateFrequencySecs: 1,
|
|
||||||
},
|
|
||||||
riskFactors: {
|
|
||||||
__typename: 'RiskFactor',
|
|
||||||
market:
|
|
||||||
'54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
|
||||||
short: '0.008571790367285281',
|
|
||||||
long: '0.008508132993273576',
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
__typename: 'MarketData',
|
|
||||||
market: {
|
|
||||||
__typename: 'Market',
|
|
||||||
id: '54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
|
||||||
},
|
|
||||||
markPrice: '5749',
|
|
||||||
indicativeVolume: '0',
|
|
||||||
bestBidVolume: '5',
|
|
||||||
bestOfferVolume: '1',
|
|
||||||
bestStaticBidVolume: '5',
|
|
||||||
bestStaticOfferVolume: '1',
|
|
||||||
},
|
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
__typename: 'TradableInstrument',
|
__typename: 'TradableInstrument',
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -74,17 +30,6 @@ export const generateDealTicketQuery = (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
riskModel: {
|
|
||||||
__typename: 'LogNormalRiskModel',
|
|
||||||
tau: 0.0001140771161,
|
|
||||||
riskAversionParameter: 0.01,
|
|
||||||
params: {
|
|
||||||
__typename: 'LogNormalModelParams',
|
|
||||||
r: 0.016,
|
|
||||||
sigma: 0.3,
|
|
||||||
mu: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
depth: {
|
depth: {
|
||||||
__typename: 'MarketDepth',
|
__typename: 'MarketDepth',
|
||||||
|
100
apps/trading-e2e/src/support/mocks/generate-market-info-query.ts
Normal file
100
apps/trading-e2e/src/support/mocks/generate-market-info-query.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import type { MarketInfoQuery } from '@vegaprotocol/deal-ticket';
|
||||||
|
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||||
|
import merge from 'lodash/merge';
|
||||||
|
import type { PartialDeep } from 'type-fest';
|
||||||
|
|
||||||
|
export const generateMarketInfoQuery = (
|
||||||
|
override?: PartialDeep<MarketInfoQuery>
|
||||||
|
): MarketInfoQuery => {
|
||||||
|
const defaultResult: MarketInfoQuery = {
|
||||||
|
market: {
|
||||||
|
__typename: 'Market',
|
||||||
|
id: 'market-0',
|
||||||
|
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||||
|
decimalPlaces: 2,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
|
state: MarketState.Active,
|
||||||
|
tradingMode: MarketTradingMode.Continuous,
|
||||||
|
fees: {
|
||||||
|
__typename: 'Fees',
|
||||||
|
factors: {
|
||||||
|
__typename: 'FeeFactors',
|
||||||
|
makerFee: '0.0002',
|
||||||
|
infrastructureFee: '0.0005',
|
||||||
|
liquidityFee: '0.01',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
priceMonitoringSettings: {
|
||||||
|
__typename: 'PriceMonitoringSettings',
|
||||||
|
parameters: {
|
||||||
|
__typename: 'PriceMonitoringParameters',
|
||||||
|
triggers: [
|
||||||
|
{
|
||||||
|
__typename: 'PriceMonitoringTrigger',
|
||||||
|
horizonSecs: 43200,
|
||||||
|
probability: 0.9999999,
|
||||||
|
auctionExtensionSecs: 600,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
updateFrequencySecs: 1,
|
||||||
|
},
|
||||||
|
riskFactors: {
|
||||||
|
__typename: 'RiskFactor',
|
||||||
|
market:
|
||||||
|
'54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
||||||
|
short: '0.008571790367285281',
|
||||||
|
long: '0.008508132993273576',
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
__typename: 'MarketData',
|
||||||
|
market: {
|
||||||
|
__typename: 'Market',
|
||||||
|
id: '54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
||||||
|
},
|
||||||
|
markPrice: '5749',
|
||||||
|
indicativeVolume: '0',
|
||||||
|
bestBidVolume: '5',
|
||||||
|
bestOfferVolume: '1',
|
||||||
|
bestStaticBidVolume: '5',
|
||||||
|
bestStaticOfferVolume: '1',
|
||||||
|
},
|
||||||
|
tradableInstrument: {
|
||||||
|
__typename: 'TradableInstrument',
|
||||||
|
instrument: {
|
||||||
|
__typename: 'Instrument',
|
||||||
|
product: {
|
||||||
|
__typename: 'Future',
|
||||||
|
quoteName: 'BTC',
|
||||||
|
settlementAsset: {
|
||||||
|
__typename: 'Asset',
|
||||||
|
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||||
|
symbol: 'tBTC',
|
||||||
|
name: 'tBTC TEST',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
riskModel: {
|
||||||
|
__typename: 'LogNormalRiskModel',
|
||||||
|
tau: 0.0001140771161,
|
||||||
|
riskAversionParameter: 0.01,
|
||||||
|
params: {
|
||||||
|
__typename: 'LogNormalModelParams',
|
||||||
|
r: 0.016,
|
||||||
|
sigma: 0.3,
|
||||||
|
mu: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
depth: {
|
||||||
|
__typename: 'MarketDepth',
|
||||||
|
lastTrade: {
|
||||||
|
__typename: 'Trade',
|
||||||
|
price: '100',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return merge(defaultResult, override);
|
||||||
|
};
|
@ -12,6 +12,7 @@ export const generateOrderBook = (
|
|||||||
const marketDepth: MarketDepth_market = {
|
const marketDepth: MarketDepth_market = {
|
||||||
id: 'b2426f67b085ba8fb429f1b529d49372b2d096c6fb6f509f76c5863abb6d969e',
|
id: 'b2426f67b085ba8fb429f1b529d49372b2d096c6fb6f509f76c5863abb6d969e',
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
data: {
|
data: {
|
||||||
staticMidPrice: '826337',
|
staticMidPrice: '826337',
|
||||||
marketTradingMode: MarketTradingMode.Continuous,
|
marketTradingMode: MarketTradingMode.Continuous,
|
||||||
|
@ -18,6 +18,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
|||||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
__typename: 'TradableInstrument',
|
__typename: 'TradableInstrument',
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -33,7 +34,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
|||||||
remaining: '0',
|
remaining: '0',
|
||||||
price: '20000000',
|
price: '20000000',
|
||||||
timeInForce: OrderTimeInForce.GTC,
|
timeInForce: OrderTimeInForce.GTC,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date(2020, 1, 1).toISOString(),
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
expiresAt: null,
|
expiresAt: null,
|
||||||
rejectionReason: null,
|
rejectionReason: null,
|
||||||
@ -46,6 +47,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
|||||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
__typename: 'TradableInstrument',
|
__typename: 'TradableInstrument',
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -59,13 +61,42 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
|||||||
status: OrderStatus.Filled,
|
status: OrderStatus.Filled,
|
||||||
side: Side.Buy,
|
side: Side.Buy,
|
||||||
remaining: '0',
|
remaining: '0',
|
||||||
price: '0',
|
price: '100',
|
||||||
timeInForce: OrderTimeInForce.GTC,
|
timeInForce: OrderTimeInForce.GTC,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
expiresAt: null,
|
expiresAt: null,
|
||||||
rejectionReason: null,
|
rejectionReason: null,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
__typename: 'Order',
|
||||||
|
id: '4e93702990712c41f6995fcbbd94f60bb372ad12d64dfa7d96d205c49f790336',
|
||||||
|
market: {
|
||||||
|
__typename: 'Market',
|
||||||
|
id: 'c6f4337b31ed57a961969c3ba10297b369d01b9e75a4cbb96db4fc62886444e6',
|
||||||
|
name: 'BTCUSD Monthly (30 Jun 2022)',
|
||||||
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
|
tradableInstrument: {
|
||||||
|
__typename: 'TradableInstrument',
|
||||||
|
instrument: {
|
||||||
|
__typename: 'Instrument',
|
||||||
|
code: 'BTCUSD.MF21',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
size: '1',
|
||||||
|
type: OrderType.Limit,
|
||||||
|
status: OrderStatus.Filled,
|
||||||
|
side: Side.Buy,
|
||||||
|
remaining: '0',
|
||||||
|
price: '20000',
|
||||||
|
timeInForce: OrderTimeInForce.GTC,
|
||||||
|
createdAt: new Date(2022, 5, 10).toISOString(),
|
||||||
|
updatedAt: null,
|
||||||
|
expiresAt: null,
|
||||||
|
rejectionReason: null,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const defaultResult = {
|
const defaultResult = {
|
||||||
|
@ -25,6 +25,7 @@ export const generatePositions = (
|
|||||||
market: { __typename: 'Market', id: '123' },
|
market: { __typename: 'Market', id: '123' },
|
||||||
},
|
},
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
instrument: {
|
instrument: {
|
||||||
id: '',
|
id: '',
|
||||||
@ -78,6 +79,7 @@ export const generatePositions = (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
instrument: {
|
instrument: {
|
||||||
id: '',
|
id: '',
|
||||||
|
@ -12,6 +12,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
|||||||
market: {
|
market: {
|
||||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
__typename: 'Trade',
|
__typename: 'Trade',
|
||||||
@ -24,6 +25,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
|||||||
market: {
|
market: {
|
||||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
__typename: 'Trade',
|
__typename: 'Trade',
|
||||||
@ -36,6 +38,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
|||||||
market: {
|
market: {
|
||||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
__typename: 'Trade',
|
__typename: 'Trade',
|
||||||
|
@ -6,6 +6,7 @@ import { generateCandles } from './mocks/generate-candles';
|
|||||||
import { generateChart } from './mocks/generate-chart';
|
import { generateChart } from './mocks/generate-chart';
|
||||||
import { generateDealTicketQuery } from './mocks/generate-deal-ticket-query';
|
import { generateDealTicketQuery } from './mocks/generate-deal-ticket-query';
|
||||||
import { generateMarket } from './mocks/generate-market';
|
import { generateMarket } from './mocks/generate-market';
|
||||||
|
import { generateMarketInfoQuery } from './mocks/generate-market-info-query';
|
||||||
import { generateOrders } from './mocks/generate-orders';
|
import { generateOrders } from './mocks/generate-orders';
|
||||||
import { generatePositions } from './mocks/generate-positions';
|
import { generatePositions } from './mocks/generate-positions';
|
||||||
import { generateTrades } from './mocks/generate-trades';
|
import { generateTrades } from './mocks/generate-trades';
|
||||||
@ -31,6 +32,11 @@ export const mockTradingPage = (
|
|||||||
'DealTicketQuery',
|
'DealTicketQuery',
|
||||||
generateDealTicketQuery({ market: { state } })
|
generateDealTicketQuery({ market: { state } })
|
||||||
);
|
);
|
||||||
|
aliasQuery(
|
||||||
|
req,
|
||||||
|
'MarketInfoQuery',
|
||||||
|
generateMarketInfoQuery({ market: { state } })
|
||||||
|
);
|
||||||
aliasQuery(req, 'Trades', generateTrades());
|
aliasQuery(req, 'Trades', generateTrades());
|
||||||
aliasQuery(req, 'Chart', generateChart());
|
aliasQuery(req, 'Chart', generateChart());
|
||||||
aliasQuery(req, 'Candles', generateCandles());
|
aliasQuery(req, 'Candles', generateCandles());
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { Vega } from '../icons/vega';
|
import { Vega } from '../icons/vega';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { AnchorButton } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export const Navbar = () => {
|
export const Navbar = () => {
|
||||||
return (
|
return (
|
||||||
@ -33,14 +33,17 @@ const NavLink = ({ name, path, exact, testId = name }: NavLinkProps) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const isActive =
|
const isActive =
|
||||||
router.asPath === path || (!exact && router.asPath.startsWith(path));
|
router.asPath === path || (!exact && router.asPath.startsWith(path));
|
||||||
|
const linkClasses = classNames(
|
||||||
|
'px-16 py-6 border-0 self-end',
|
||||||
|
'uppercase xs:text-ui sm:text-body-large md:text-h5 lg:text-h4',
|
||||||
|
{
|
||||||
|
'bg-vega-pink dark:bg-vega-yellow text-white dark:text-black': isActive,
|
||||||
|
'text-black dark:text-white': !isActive,
|
||||||
|
}
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<AnchorButton
|
<Link data-testid={testId} href={path} passHref={true}>
|
||||||
variant={isActive ? 'accent' : 'inline'}
|
<a className={linkClasses}>{name}</a>
|
||||||
className="px-16 py-6 h-[38px] uppercase border-0 self-end xs:text-ui sm:text-body-large md:text-h5 lg:text-h4"
|
</Link>
|
||||||
data-testid={testId}
|
|
||||||
href={path}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</AnchorButton>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -24,84 +24,80 @@ function AppBody({ Component, pageProps }: AppProps) {
|
|||||||
const { push } = useRouter();
|
const { push } = useRouter();
|
||||||
const store = useGlobalStore();
|
const store = useGlobalStore();
|
||||||
const { VEGA_NETWORKS } = useEnvironment();
|
const { VEGA_NETWORKS } = useEnvironment();
|
||||||
const [, toggleTheme] = useThemeSwitcher();
|
const [theme, toggleTheme] = useThemeSwitcher();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full dark:bg-black dark:text-white-60 bg-white relative z-0 text-black-60 grid grid-rows-[min-content,1fr]">
|
<ThemeContext.Provider value={theme}>
|
||||||
<AppLoader>
|
<div className="h-full dark:bg-black dark:text-white-60 bg-white relative z-0 text-black-60 grid grid-rows-[min-content,1fr]">
|
||||||
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
|
<AppLoader>
|
||||||
<Navbar />
|
<div className="flex items-stretch border-b-[7px] border-vega-pink dark:border-vega-yellow">
|
||||||
<div className="flex items-center gap-4 ml-auto mr-8">
|
<Navbar />
|
||||||
<VegaWalletConnectButton
|
<div className="flex items-center gap-4 ml-auto mr-8">
|
||||||
setConnectDialog={(open) => {
|
<VegaWalletConnectButton
|
||||||
store.setVegaWalletConnectDialog(open);
|
setConnectDialog={(open) => {
|
||||||
}}
|
store.setVegaWalletConnectDialog(open);
|
||||||
setManageDialog={(open) => {
|
}}
|
||||||
store.setVegaWalletManageDialog(open);
|
setManageDialog={(open) => {
|
||||||
}}
|
store.setVegaWalletManageDialog(open);
|
||||||
/>
|
}}
|
||||||
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
/>
|
||||||
|
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<main data-testid={pageProps.page}>
|
||||||
<main data-testid={pageProps.page}>
|
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
|
||||||
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
|
<Component {...pageProps} />
|
||||||
<Component {...pageProps} />
|
</main>
|
||||||
</main>
|
<VegaConnectDialog
|
||||||
<VegaConnectDialog
|
connectors={Connectors}
|
||||||
connectors={Connectors}
|
dialogOpen={store.vegaWalletConnectDialog}
|
||||||
dialogOpen={store.vegaWalletConnectDialog}
|
setDialogOpen={(open) => store.setVegaWalletConnectDialog(open)}
|
||||||
setDialogOpen={(open) => store.setVegaWalletConnectDialog(open)}
|
/>
|
||||||
/>
|
<VegaManageDialog
|
||||||
<VegaManageDialog
|
dialogOpen={store.vegaWalletManageDialog}
|
||||||
dialogOpen={store.vegaWalletManageDialog}
|
setDialogOpen={(open) => store.setVegaWalletManageDialog(open)}
|
||||||
setDialogOpen={(open) => store.setVegaWalletManageDialog(open)}
|
/>
|
||||||
/>
|
<NetworkSwitcherDialog
|
||||||
<NetworkSwitcherDialog
|
dialogOpen={store.vegaNetworkSwitcherDialog}
|
||||||
dialogOpen={store.vegaNetworkSwitcherDialog}
|
setDialogOpen={(open) => store.setVegaNetworkSwitcherDialog(open)}
|
||||||
setDialogOpen={(open) => store.setVegaNetworkSwitcherDialog(open)}
|
onConnect={({ network }) => {
|
||||||
onConnect={({ network }) => {
|
if (VEGA_NETWORKS[network]) {
|
||||||
if (VEGA_NETWORKS[network]) {
|
push(VEGA_NETWORKS[network] ?? '');
|
||||||
push(VEGA_NETWORKS[network] ?? '');
|
}
|
||||||
}
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</AppLoader>
|
||||||
</AppLoader>
|
</div>
|
||||||
</div>
|
</ThemeContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function VegaTradingApp(props: AppProps) {
|
function VegaTradingApp(props: AppProps) {
|
||||||
const [theme] = useThemeSwitcher();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EnvironmentProvider>
|
<EnvironmentProvider>
|
||||||
<ThemeContext.Provider value={theme}>
|
<VegaWalletProvider>
|
||||||
<VegaWalletProvider>
|
<Head>
|
||||||
<Head>
|
<link
|
||||||
<link
|
rel="preload"
|
||||||
rel="preload"
|
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
as="font"
|
||||||
as="font"
|
type="font/woff2"
|
||||||
type="font/woff2"
|
crossOrigin="anonymous"
|
||||||
crossOrigin="anonymous"
|
/>
|
||||||
/>
|
<title>{t('Welcome to Vega trading!')}</title>
|
||||||
<title>{t('Welcome to Vega trading!')}</title>
|
<link
|
||||||
<link
|
rel="icon"
|
||||||
rel="icon"
|
type="image/x-icon"
|
||||||
type="image/x-icon"
|
href="https://static.vega.xyz/favicon.ico"
|
||||||
href="https://static.vega.xyz/favicon.ico"
|
/>
|
||||||
/>
|
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
||||||
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
{['1', 'true'].includes(process.env['NX_USE_ENV_OVERRIDES'] || '') ? (
|
||||||
{['1', 'true'].includes(
|
/* eslint-disable-next-line @next/next/no-sync-scripts */
|
||||||
process.env['NX_USE_ENV_OVERRIDES'] || ''
|
<script src="./env-config.js" type="text/javascript" />
|
||||||
) ? (
|
) : null}
|
||||||
/* eslint-disable-next-line @next/next/no-sync-scripts */
|
</Head>
|
||||||
<script src="./env-config.js" type="text/javascript" />
|
<AppBody {...props} />
|
||||||
) : null}
|
</VegaWalletProvider>
|
||||||
</Head>
|
|
||||||
<AppBody {...props} />
|
|
||||||
</VegaWalletProvider>
|
|
||||||
</ThemeContext.Provider>
|
|
||||||
</EnvironmentProvider>
|
</EnvironmentProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,10 @@ import classNames from 'classnames';
|
|||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { DealTicketContainer } from '@vegaprotocol/deal-ticket';
|
import {
|
||||||
|
DealTicketContainer,
|
||||||
|
MarketInfoContainer,
|
||||||
|
} from '@vegaprotocol/deal-ticket';
|
||||||
import { OrderListContainer } from '@vegaprotocol/order-list';
|
import { OrderListContainer } from '@vegaprotocol/order-list';
|
||||||
import { TradesContainer } from '@vegaprotocol/trades';
|
import { TradesContainer } from '@vegaprotocol/trades';
|
||||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||||
@ -15,8 +18,8 @@ import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
|
|||||||
import { SelectMarketDialog } from '@vegaprotocol/market-list';
|
import { SelectMarketDialog } from '@vegaprotocol/market-list';
|
||||||
import {
|
import {
|
||||||
ArrowDown,
|
ArrowDown,
|
||||||
GridTab,
|
Tab,
|
||||||
GridTabs,
|
Tabs,
|
||||||
PriceCellChange,
|
PriceCellChange,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import type { CandleClose } from '@vegaprotocol/types';
|
import type { CandleClose } from '@vegaprotocol/types';
|
||||||
@ -30,6 +33,7 @@ const TradingViews = {
|
|||||||
Positions: PositionsContainer,
|
Positions: PositionsContainer,
|
||||||
Accounts: AccountsContainer,
|
Accounts: AccountsContainer,
|
||||||
Trades: TradesContainer,
|
Trades: TradesContainer,
|
||||||
|
Info: MarketInfoContainer,
|
||||||
};
|
};
|
||||||
|
|
||||||
type TradingView = keyof typeof TradingViews;
|
type TradingView = keyof typeof TradingViews;
|
||||||
@ -52,17 +56,17 @@ export const TradeMarketHeader = ({
|
|||||||
'font-sans font-normal mb-0 text-dark/80 dark:text-white/80 text-ui-small';
|
'font-sans font-normal mb-0 text-dark/80 dark:text-white/80 text-ui-small';
|
||||||
const itemValueClassName =
|
const itemValueClassName =
|
||||||
'capitalize font-sans tracking-tighter text-black dark:text-white text-ui';
|
'capitalize font-sans tracking-tighter text-black dark:text-white text-ui';
|
||||||
const headerClassname = classNames(
|
const headerClassName = classNames(
|
||||||
'w-full p-8 bg-white dark:bg-black',
|
'w-full p-8 bg-white dark:bg-black',
|
||||||
className
|
className
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<header className={headerClassname}>
|
<header className={headerClassName}>
|
||||||
<SelectMarketDialog dialogOpen={open} setDialogOpen={setOpen} />
|
<SelectMarketDialog dialogOpen={open} setDialogOpen={setOpen} />
|
||||||
<div className="flex flex-col md:flex-row gap-20 md:gap-64 ml-auto mr-8">
|
<div className="flex flex-col md:flex-row gap-20 md:gap-64 ml-auto mr-8">
|
||||||
<button
|
<button
|
||||||
onClick={() => setOpen(!open)}
|
onClick={() => setOpen(!open)}
|
||||||
className="shrink-0 dark:text-vega-yellow text-black text-h5 flex items-center gap-8 px-4 py-0 h-37 hover:bg-vega-yellow dark:hover:bg-white/20"
|
className="shrink-0 dark:text-vega-yellow text-black text-h5 flex items-center gap-8 px-4 py-0 h-37 hover:bg-black/20 dark:hover:bg-white/20"
|
||||||
>
|
>
|
||||||
<span className="break-words text-left">{market.name}</span>
|
<span className="break-words text-left">{market.name}</span>
|
||||||
<ArrowDown color="yellow" borderX={8} borderTop={12} />
|
<ArrowDown color="yellow" borderX={8} borderTop={12} />
|
||||||
@ -105,7 +109,7 @@ interface TradeGridProps {
|
|||||||
export const TradeGrid = ({ market }: TradeGridProps) => {
|
export const TradeGrid = ({ market }: TradeGridProps) => {
|
||||||
const wrapperClasses = classNames(
|
const wrapperClasses = classNames(
|
||||||
'h-full max-h-full',
|
'h-full max-h-full',
|
||||||
'grid gap-4 grid-cols-[1fr_375px_460px] grid-rows-[min-content_1fr_200px]',
|
'grid gap-4 grid-cols-[1fr_375px_460px] grid-rows-[min-content_1fr_300px]',
|
||||||
'bg-black-10 dark:bg-white-10',
|
'bg-black-10 dark:bg-white-10',
|
||||||
'text-ui'
|
'text-ui'
|
||||||
);
|
);
|
||||||
@ -115,43 +119,50 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
|
|||||||
<div className={wrapperClasses}>
|
<div className={wrapperClasses}>
|
||||||
<TradeMarketHeader
|
<TradeMarketHeader
|
||||||
market={market}
|
market={market}
|
||||||
className="row-start-1 row-end-2 col-start-1 col-end-2"
|
className="row-start-1 row-end-2 col-start-1 col-end-4"
|
||||||
/>
|
/>
|
||||||
<TradeGridChild className="row-start-2 row-end-3 col-start-1 col-end-2">
|
<TradeGridChild className="row-start-2 row-end-3 col-start-1 col-end-2">
|
||||||
<GridTabs>
|
<Tabs>
|
||||||
<GridTab id="candles" name={t('Candles')}>
|
<Tab id="candles" name={t('Candles')}>
|
||||||
<TradingViews.Candles marketId={market.id} />
|
<TradingViews.Candles marketId={market.id} />
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="depth" name={t('Depth')}>
|
<Tab id="depth" name={t('Depth')}>
|
||||||
<TradingViews.Depth marketId={market.id} />
|
<TradingViews.Depth marketId={market.id} />
|
||||||
</GridTab>
|
</Tab>
|
||||||
</GridTabs>
|
</Tabs>
|
||||||
</TradeGridChild>
|
</TradeGridChild>
|
||||||
<TradeGridChild className="row-start-1 row-end-3">
|
<TradeGridChild className="row-start-2 row-end-3 col-start-2 col-end-3">
|
||||||
<TradingViews.Ticket marketId={market.id} />
|
<Tabs>
|
||||||
|
<Tab id="ticket" name={t('Ticket')}>
|
||||||
|
<TradingViews.Ticket marketId={market.id} />
|
||||||
|
</Tab>
|
||||||
|
<Tab id="info" name={t('Info')}>
|
||||||
|
<TradingViews.Info marketId={market.id} />
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
</TradeGridChild>
|
</TradeGridChild>
|
||||||
<TradeGridChild className="row-start-1 row-end-3">
|
<TradeGridChild className="row-start-2 row-end-3 col-start-3 col-end-4">
|
||||||
<GridTabs>
|
<Tabs>
|
||||||
<GridTab id="trades" name={t('Trades')}>
|
<Tab id="trades" name={t('Trades')}>
|
||||||
<TradingViews.Trades marketId={market.id} />
|
<TradingViews.Trades marketId={market.id} />
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="orderbook" name={t('Orderbook')}>
|
<Tab id="orderbook" name={t('Orderbook')}>
|
||||||
<TradingViews.Orderbook marketId={market.id} />
|
<TradingViews.Orderbook marketId={market.id} />
|
||||||
</GridTab>
|
</Tab>
|
||||||
</GridTabs>
|
</Tabs>
|
||||||
</TradeGridChild>
|
</TradeGridChild>
|
||||||
<TradeGridChild className="col-span-3">
|
<TradeGridChild className="col-span-3">
|
||||||
<GridTabs>
|
<Tabs>
|
||||||
<GridTab id="orders" name={t('Orders')}>
|
<Tab id="orders" name={t('Orders')}>
|
||||||
<TradingViews.Orders />
|
<TradingViews.Orders />
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="positions" name={t('Positions')}>
|
<Tab id="positions" name={t('Positions')}>
|
||||||
<TradingViews.Positions />
|
<TradingViews.Positions />
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="accounts" name={t('Accounts')}>
|
<Tab id="accounts" name={t('Accounts')}>
|
||||||
<TradingViews.Accounts />
|
<TradingViews.Accounts />
|
||||||
</GridTab>
|
</Tab>
|
||||||
</GridTabs>
|
</Tabs>
|
||||||
</TradeGridChild>
|
</TradeGridChild>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -3,8 +3,7 @@ import { t } from '@vegaprotocol/react-helpers';
|
|||||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||||
import { OrderListContainer } from '@vegaprotocol/order-list';
|
import { OrderListContainer } from '@vegaprotocol/order-list';
|
||||||
import { AccountsContainer } from '@vegaprotocol/accounts';
|
import { AccountsContainer } from '@vegaprotocol/accounts';
|
||||||
import { AnchorButton, GridTab, GridTabs } from '@vegaprotocol/ui-toolkit';
|
import { AnchorButton, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
import { WithdrawalsContainer } from './withdrawals/withdrawals-container';
|
import { WithdrawalsContainer } from './withdrawals/withdrawals-container';
|
||||||
|
|
||||||
const Portfolio = () => {
|
const Portfolio = () => {
|
||||||
@ -20,54 +19,54 @@ const Portfolio = () => {
|
|||||||
</h2>
|
</h2>
|
||||||
</aside>
|
</aside>
|
||||||
<section data-testid="portfolio-grid">
|
<section data-testid="portfolio-grid">
|
||||||
<GridTabs>
|
<Tabs>
|
||||||
<GridTab id="positions" name={t('Positions')}>
|
<Tab id="positions" name={t('Positions')}>
|
||||||
<div className={tabClassName}>
|
<div className={tabClassName}>
|
||||||
<h4 className="text-h4 text-black dark:text-white">
|
<h4 className="text-h4 text-black dark:text-white">
|
||||||
{t('Positions')}
|
{t('Positions')}
|
||||||
</h4>
|
</h4>
|
||||||
<PositionsContainer />
|
<PositionsContainer />
|
||||||
</div>
|
</div>
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="orders" name={t('Orders')}>
|
<Tab id="orders" name={t('Orders')}>
|
||||||
<div className={tabClassName}>
|
<div className={tabClassName}>
|
||||||
<h4 className="text-h4 text-black dark:text-white">
|
<h4 className="text-h4 text-black dark:text-white">
|
||||||
{t('Orders')}
|
{t('Orders')}
|
||||||
</h4>
|
</h4>
|
||||||
<OrderListContainer />
|
<OrderListContainer />
|
||||||
</div>
|
</div>
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="fills" name={t('Fills')}>
|
<Tab id="fills" name={t('Fills')}>
|
||||||
<div className={tabClassName}>
|
<div className={tabClassName}>
|
||||||
<h4 className="text-h4 text-black dark:text-white">
|
<h4 className="text-h4 text-black dark:text-white">
|
||||||
{t('Fills')}
|
{t('Fills')}
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="history" name={t('History')}>
|
<Tab id="history" name={t('History')}>
|
||||||
<div className={tabClassName}>
|
<div className={tabClassName}>
|
||||||
<h4 className="text-h4 text-black dark:text-white">
|
<h4 className="text-h4 text-black dark:text-white">
|
||||||
{t('History')}
|
{t('History')}
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
</GridTab>
|
</Tab>
|
||||||
</GridTabs>
|
</Tabs>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<section className="fixed bottom-0 left-0 w-full h-[200px]">
|
<section className="fixed bottom-0 left-0 w-full h-[200px]">
|
||||||
<GridTabs>
|
<Tabs>
|
||||||
<GridTab id="collateral" name={t('Collateral')}>
|
<Tab id="collateral" name={t('Collateral')}>
|
||||||
<AccountsContainer />
|
<AccountsContainer />
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="deposits" name={t('Deposits')}>
|
<Tab id="deposits" name={t('Deposits')}>
|
||||||
<AnchorButton data-testid="deposit" href="/portfolio/deposit">
|
<AnchorButton data-testid="deposit" href="/portfolio/deposit">
|
||||||
{t('Deposit')}
|
{t('Deposit')}
|
||||||
</AnchorButton>
|
</AnchorButton>
|
||||||
</GridTab>
|
</Tab>
|
||||||
<GridTab id="withdrawals" name={t('Withdrawals')}>
|
<Tab id="withdrawals" name={t('Withdrawals')}>
|
||||||
<WithdrawalsContainer />
|
<WithdrawalsContainer />
|
||||||
</GridTab>
|
</Tab>
|
||||||
</GridTabs>
|
</Tabs>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</Web3Container>
|
</Web3Container>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import produce from 'immer';
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import type {
|
import type {
|
||||||
Accounts,
|
Accounts,
|
||||||
@ -52,17 +53,18 @@ export const getId = (
|
|||||||
) => `${data.type}-${data.asset.symbol}-${data.market?.id ?? 'null'}`;
|
) => `${data.type}-${data.asset.symbol}-${data.market?.id ?? 'null'}`;
|
||||||
|
|
||||||
const update = (
|
const update = (
|
||||||
draft: Accounts_party_accounts[],
|
data: Accounts_party_accounts[],
|
||||||
delta: AccountSubscribe_accounts
|
delta: AccountSubscribe_accounts
|
||||||
) => {
|
) =>
|
||||||
const id = getId(delta);
|
produce(data, (draft) => {
|
||||||
const index = draft.findIndex((a) => getId(a) === id);
|
const id = getId(delta);
|
||||||
if (index !== -1) {
|
const index = draft.findIndex((a) => getId(a) === id);
|
||||||
draft[index] = delta;
|
if (index !== -1) {
|
||||||
} else {
|
draft[index] = delta;
|
||||||
draft.push(delta);
|
} else {
|
||||||
}
|
draft.push(delta);
|
||||||
};
|
}
|
||||||
|
});
|
||||||
const getData = (responseData: Accounts): Accounts_party_accounts[] | null =>
|
const getData = (responseData: Accounts): Accounts_party_accounts[] | null =>
|
||||||
responseData.party ? responseData.party.accounts : null;
|
responseData.party ? responseData.party.accounts : null;
|
||||||
const getDelta = (
|
const getDelta = (
|
||||||
|
@ -17,7 +17,6 @@ import { useContext, useMemo, useState } from 'react';
|
|||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuCheckboxItem,
|
DropdownMenuCheckboxItem,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@ -58,14 +57,14 @@ export const CandlesChartContainer = ({
|
|||||||
return new VegaDataSource(client, marketId, keypair?.pub);
|
return new VegaDataSource(client, marketId, keypair?.pub);
|
||||||
}, [client, marketId, keypair]);
|
}, [client, marketId, keypair]);
|
||||||
|
|
||||||
|
const dropdownTriggerStyles = 'border-black-60 dark:border-white-60 px-20';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex flex-col">
|
<div className="h-full flex flex-col">
|
||||||
<div className="p-8 flex flex-row flex-wrap gap-8">
|
<div className="p-8 flex flex-row flex-wrap gap-8">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild={true}>
|
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||||
<Button appendIconName="caret-down" variant="secondary">
|
{t('Interval')}
|
||||||
{t('Interval')}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
<DropdownMenuRadioGroup
|
<DropdownMenuRadioGroup
|
||||||
@ -90,10 +89,8 @@ export const CandlesChartContainer = ({
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild={true}>
|
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||||
<Button appendIconName="caret-down" variant="secondary">
|
<Icon name={chartTypeIcon.get(chartType) as IconName} />
|
||||||
<Icon name={chartTypeIcon.get(chartType) as IconName} />
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
<DropdownMenuRadioGroup
|
<DropdownMenuRadioGroup
|
||||||
@ -114,10 +111,8 @@ export const CandlesChartContainer = ({
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild={true}>
|
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||||
<Button appendIconName="caret-down" variant="secondary">
|
{t('Overlays')}
|
||||||
{t('Overlays')}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
{Object.values(Overlay).map((overlay) => (
|
{Object.values(Overlay).map((overlay) => (
|
||||||
@ -145,10 +140,8 @@ export const CandlesChartContainer = ({
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild={true}>
|
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||||
<Button appendIconName="caret-down" variant="secondary">
|
{t('Studies')}
|
||||||
{t('Studies')}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
{Object.values(Study).map((study) => (
|
{Object.values(Study).map((study) => (
|
||||||
|
@ -9,124 +9,6 @@ import { MarketState, MarketTradingMode } from "@vegaprotocol/types";
|
|||||||
// GraphQL query operation: DealTicketQuery
|
// GraphQL query operation: DealTicketQuery
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
|
||||||
export interface DealTicketQuery_market_fees_factors {
|
|
||||||
__typename: "FeeFactors";
|
|
||||||
/**
|
|
||||||
* The factor applied to calculate MakerFees, a non-negative float
|
|
||||||
*/
|
|
||||||
makerFee: string;
|
|
||||||
/**
|
|
||||||
* The factor applied to calculate InfrastructureFees, a non-negative float
|
|
||||||
*/
|
|
||||||
infrastructureFee: string;
|
|
||||||
/**
|
|
||||||
* The factor applied to calculate LiquidityFees, a non-negative float
|
|
||||||
*/
|
|
||||||
liquidityFee: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_fees {
|
|
||||||
__typename: "Fees";
|
|
||||||
/**
|
|
||||||
* The factors used to calculate the different fees
|
|
||||||
*/
|
|
||||||
factors: DealTicketQuery_market_fees_factors;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_priceMonitoringSettings_parameters_triggers {
|
|
||||||
__typename: "PriceMonitoringTrigger";
|
|
||||||
/**
|
|
||||||
* Price monitoring projection horizon τ in seconds (> 0).
|
|
||||||
*/
|
|
||||||
horizonSecs: number;
|
|
||||||
/**
|
|
||||||
* Price monitoring probability level p. (>0 and < 1)
|
|
||||||
*/
|
|
||||||
probability: number;
|
|
||||||
/**
|
|
||||||
* Price monitoring auction extension duration in seconds should the price
|
|
||||||
* breach it's theoretical level over the specified horizon at the specified
|
|
||||||
* probability level (> 0)
|
|
||||||
*/
|
|
||||||
auctionExtensionSecs: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_priceMonitoringSettings_parameters {
|
|
||||||
__typename: "PriceMonitoringParameters";
|
|
||||||
/**
|
|
||||||
* The list of triggers for this price monitoring
|
|
||||||
*/
|
|
||||||
triggers: DealTicketQuery_market_priceMonitoringSettings_parameters_triggers[] | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_priceMonitoringSettings {
|
|
||||||
__typename: "PriceMonitoringSettings";
|
|
||||||
/**
|
|
||||||
* Specified a set of PriceMonitoringParameters to be use for price monitoring purposes
|
|
||||||
*/
|
|
||||||
parameters: DealTicketQuery_market_priceMonitoringSettings_parameters | null;
|
|
||||||
/**
|
|
||||||
* How often (in seconds) the price monitoring bounds should be updated
|
|
||||||
*/
|
|
||||||
updateFrequencySecs: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_riskFactors {
|
|
||||||
__typename: "RiskFactor";
|
|
||||||
/**
|
|
||||||
* market the risk factor was emitted for
|
|
||||||
*/
|
|
||||||
market: string;
|
|
||||||
/**
|
|
||||||
* short factor
|
|
||||||
*/
|
|
||||||
short: string;
|
|
||||||
/**
|
|
||||||
* long factor
|
|
||||||
*/
|
|
||||||
long: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_data_market {
|
|
||||||
__typename: "Market";
|
|
||||||
/**
|
|
||||||
* Market ID
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_data {
|
|
||||||
__typename: "MarketData";
|
|
||||||
/**
|
|
||||||
* market id of the associated mark price
|
|
||||||
*/
|
|
||||||
market: DealTicketQuery_market_data_market;
|
|
||||||
/**
|
|
||||||
* the mark price (actually an unsigned int)
|
|
||||||
*/
|
|
||||||
markPrice: string;
|
|
||||||
/**
|
|
||||||
* indicative volume if the auction ended now, 0 if not in auction mode
|
|
||||||
*/
|
|
||||||
indicativeVolume: string;
|
|
||||||
/**
|
|
||||||
* the aggregated volume being bid at the best bid price.
|
|
||||||
*/
|
|
||||||
bestBidVolume: string;
|
|
||||||
/**
|
|
||||||
* the aggregated volume being offered at the best offer price.
|
|
||||||
*/
|
|
||||||
bestOfferVolume: string;
|
|
||||||
/**
|
|
||||||
* the aggregated volume being offered at the best static bid price, excluding pegged orders
|
|
||||||
*/
|
|
||||||
bestStaticBidVolume: string;
|
|
||||||
/**
|
|
||||||
* the aggregated volume being offered at the best static offer price, excluding pegged orders.
|
|
||||||
*/
|
|
||||||
bestStaticOfferVolume: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset {
|
export interface DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset {
|
||||||
__typename: "Asset";
|
__typename: "Asset";
|
||||||
/**
|
/**
|
||||||
@ -163,70 +45,12 @@ export interface DealTicketQuery_market_tradableInstrument_instrument {
|
|||||||
product: DealTicketQuery_market_tradableInstrument_instrument_product;
|
product: DealTicketQuery_market_tradableInstrument_instrument_product;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DealTicketQuery_market_tradableInstrument_riskModel_LogNormalRiskModel_params {
|
|
||||||
__typename: "LogNormalModelParams";
|
|
||||||
/**
|
|
||||||
* r parameter
|
|
||||||
*/
|
|
||||||
r: number;
|
|
||||||
/**
|
|
||||||
* sigma parameter
|
|
||||||
*/
|
|
||||||
sigma: number;
|
|
||||||
/**
|
|
||||||
* mu parameter
|
|
||||||
*/
|
|
||||||
mu: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_tradableInstrument_riskModel_LogNormalRiskModel {
|
|
||||||
__typename: "LogNormalRiskModel";
|
|
||||||
/**
|
|
||||||
* Tau parameter of the risk model
|
|
||||||
*/
|
|
||||||
tau: number;
|
|
||||||
/**
|
|
||||||
* Lambda parameter of the risk model
|
|
||||||
*/
|
|
||||||
riskAversionParameter: number;
|
|
||||||
/**
|
|
||||||
* Params for the log normal risk model
|
|
||||||
*/
|
|
||||||
params: DealTicketQuery_market_tradableInstrument_riskModel_LogNormalRiskModel_params;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_tradableInstrument_riskModel_SimpleRiskModel_params {
|
|
||||||
__typename: "SimpleRiskModelParams";
|
|
||||||
/**
|
|
||||||
* Risk factor for long
|
|
||||||
*/
|
|
||||||
factorLong: number;
|
|
||||||
/**
|
|
||||||
* Risk factor for short
|
|
||||||
*/
|
|
||||||
factorShort: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_tradableInstrument_riskModel_SimpleRiskModel {
|
|
||||||
__typename: "SimpleRiskModel";
|
|
||||||
/**
|
|
||||||
* Params for the simple risk model
|
|
||||||
*/
|
|
||||||
params: DealTicketQuery_market_tradableInstrument_riskModel_SimpleRiskModel_params;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DealTicketQuery_market_tradableInstrument_riskModel = DealTicketQuery_market_tradableInstrument_riskModel_LogNormalRiskModel | DealTicketQuery_market_tradableInstrument_riskModel_SimpleRiskModel;
|
|
||||||
|
|
||||||
export interface DealTicketQuery_market_tradableInstrument {
|
export interface DealTicketQuery_market_tradableInstrument {
|
||||||
__typename: "TradableInstrument";
|
__typename: "TradableInstrument";
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a fully specified instrument.
|
* An instance of or reference to a fully specified instrument.
|
||||||
*/
|
*/
|
||||||
instrument: DealTicketQuery_market_tradableInstrument_instrument;
|
instrument: DealTicketQuery_market_tradableInstrument_instrument;
|
||||||
/**
|
|
||||||
* A reference to a risk model that is valid for the instrument
|
|
||||||
*/
|
|
||||||
riskModel: DealTicketQuery_market_tradableInstrument_riskModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DealTicketQuery_market_depth_lastTrade {
|
export interface DealTicketQuery_market_depth_lastTrade {
|
||||||
@ -286,22 +110,6 @@ export interface DealTicketQuery_market {
|
|||||||
* Current mode of execution of the market
|
* Current mode of execution of the market
|
||||||
*/
|
*/
|
||||||
tradingMode: MarketTradingMode;
|
tradingMode: MarketTradingMode;
|
||||||
/**
|
|
||||||
* Fees related data
|
|
||||||
*/
|
|
||||||
fees: DealTicketQuery_market_fees;
|
|
||||||
/**
|
|
||||||
* Price monitoring settings for the market
|
|
||||||
*/
|
|
||||||
priceMonitoringSettings: DealTicketQuery_market_priceMonitoringSettings;
|
|
||||||
/**
|
|
||||||
* risk factors for the market
|
|
||||||
*/
|
|
||||||
riskFactors: DealTicketQuery_market_riskFactors | null;
|
|
||||||
/**
|
|
||||||
* marketData for the given market
|
|
||||||
*/
|
|
||||||
data: DealTicketQuery_market_data | null;
|
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a tradable instrument.
|
* An instance of or reference to a tradable instrument.
|
||||||
*/
|
*/
|
||||||
|
324
libs/deal-ticket/src/components/__generated__/MarketInfoQuery.ts
generated
Normal file
324
libs/deal-ticket/src/components/__generated__/MarketInfoQuery.ts
generated
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { MarketState, MarketTradingMode } from "@vegaprotocol/types";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL query operation: MarketInfoQuery
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_fees_factors {
|
||||||
|
__typename: "FeeFactors";
|
||||||
|
/**
|
||||||
|
* The factor applied to calculate MakerFees, a non-negative float
|
||||||
|
*/
|
||||||
|
makerFee: string;
|
||||||
|
/**
|
||||||
|
* The factor applied to calculate InfrastructureFees, a non-negative float
|
||||||
|
*/
|
||||||
|
infrastructureFee: string;
|
||||||
|
/**
|
||||||
|
* The factor applied to calculate LiquidityFees, a non-negative float
|
||||||
|
*/
|
||||||
|
liquidityFee: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_fees {
|
||||||
|
__typename: "Fees";
|
||||||
|
/**
|
||||||
|
* The factors used to calculate the different fees
|
||||||
|
*/
|
||||||
|
factors: MarketInfoQuery_market_fees_factors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_priceMonitoringSettings_parameters_triggers {
|
||||||
|
__typename: "PriceMonitoringTrigger";
|
||||||
|
/**
|
||||||
|
* Price monitoring projection horizon τ in seconds (> 0).
|
||||||
|
*/
|
||||||
|
horizonSecs: number;
|
||||||
|
/**
|
||||||
|
* Price monitoring probability level p. (>0 and < 1)
|
||||||
|
*/
|
||||||
|
probability: number;
|
||||||
|
/**
|
||||||
|
* Price monitoring auction extension duration in seconds should the price
|
||||||
|
* breach it's theoretical level over the specified horizon at the specified
|
||||||
|
* probability level (> 0)
|
||||||
|
*/
|
||||||
|
auctionExtensionSecs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_priceMonitoringSettings_parameters {
|
||||||
|
__typename: "PriceMonitoringParameters";
|
||||||
|
/**
|
||||||
|
* The list of triggers for this price monitoring
|
||||||
|
*/
|
||||||
|
triggers: MarketInfoQuery_market_priceMonitoringSettings_parameters_triggers[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_priceMonitoringSettings {
|
||||||
|
__typename: "PriceMonitoringSettings";
|
||||||
|
/**
|
||||||
|
* Specified a set of PriceMonitoringParameters to be use for price monitoring purposes
|
||||||
|
*/
|
||||||
|
parameters: MarketInfoQuery_market_priceMonitoringSettings_parameters | null;
|
||||||
|
/**
|
||||||
|
* How often (in seconds) the price monitoring bounds should be updated
|
||||||
|
*/
|
||||||
|
updateFrequencySecs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_riskFactors {
|
||||||
|
__typename: "RiskFactor";
|
||||||
|
/**
|
||||||
|
* market the risk factor was emitted for
|
||||||
|
*/
|
||||||
|
market: string;
|
||||||
|
/**
|
||||||
|
* short factor
|
||||||
|
*/
|
||||||
|
short: string;
|
||||||
|
/**
|
||||||
|
* long factor
|
||||||
|
*/
|
||||||
|
long: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_data_market {
|
||||||
|
__typename: "Market";
|
||||||
|
/**
|
||||||
|
* Market ID
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_data {
|
||||||
|
__typename: "MarketData";
|
||||||
|
/**
|
||||||
|
* market id of the associated mark price
|
||||||
|
*/
|
||||||
|
market: MarketInfoQuery_market_data_market;
|
||||||
|
/**
|
||||||
|
* the mark price (actually an unsigned int)
|
||||||
|
*/
|
||||||
|
markPrice: string;
|
||||||
|
/**
|
||||||
|
* indicative volume if the auction ended now, 0 if not in auction mode
|
||||||
|
*/
|
||||||
|
indicativeVolume: string;
|
||||||
|
/**
|
||||||
|
* the aggregated volume being bid at the best bid price.
|
||||||
|
*/
|
||||||
|
bestBidVolume: string;
|
||||||
|
/**
|
||||||
|
* the aggregated volume being offered at the best offer price.
|
||||||
|
*/
|
||||||
|
bestOfferVolume: string;
|
||||||
|
/**
|
||||||
|
* the aggregated volume being offered at the best static bid price, excluding pegged orders
|
||||||
|
*/
|
||||||
|
bestStaticBidVolume: string;
|
||||||
|
/**
|
||||||
|
* the aggregated volume being offered at the best static offer price, excluding pegged orders.
|
||||||
|
*/
|
||||||
|
bestStaticOfferVolume: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument_instrument_product_settlementAsset {
|
||||||
|
__typename: "Asset";
|
||||||
|
/**
|
||||||
|
* The id of the asset
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* The symbol of the asset (e.g: GBP)
|
||||||
|
*/
|
||||||
|
symbol: string;
|
||||||
|
/**
|
||||||
|
* The full name of the asset (e.g: Great British Pound)
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument_instrument_product {
|
||||||
|
__typename: "Future";
|
||||||
|
/**
|
||||||
|
* String representing the quote (e.g. BTCUSD -> USD is quote)
|
||||||
|
*/
|
||||||
|
quoteName: string;
|
||||||
|
/**
|
||||||
|
* The name of the asset (string)
|
||||||
|
*/
|
||||||
|
settlementAsset: MarketInfoQuery_market_tradableInstrument_instrument_product_settlementAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument_instrument {
|
||||||
|
__typename: "Instrument";
|
||||||
|
/**
|
||||||
|
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
|
||||||
|
*/
|
||||||
|
product: MarketInfoQuery_market_tradableInstrument_instrument_product;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument_riskModel_LogNormalRiskModel_params {
|
||||||
|
__typename: "LogNormalModelParams";
|
||||||
|
/**
|
||||||
|
* r parameter
|
||||||
|
*/
|
||||||
|
r: number;
|
||||||
|
/**
|
||||||
|
* sigma parameter
|
||||||
|
*/
|
||||||
|
sigma: number;
|
||||||
|
/**
|
||||||
|
* mu parameter
|
||||||
|
*/
|
||||||
|
mu: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument_riskModel_LogNormalRiskModel {
|
||||||
|
__typename: "LogNormalRiskModel";
|
||||||
|
/**
|
||||||
|
* Tau parameter of the risk model
|
||||||
|
*/
|
||||||
|
tau: number;
|
||||||
|
/**
|
||||||
|
* Lambda parameter of the risk model
|
||||||
|
*/
|
||||||
|
riskAversionParameter: number;
|
||||||
|
/**
|
||||||
|
* Params for the log normal risk model
|
||||||
|
*/
|
||||||
|
params: MarketInfoQuery_market_tradableInstrument_riskModel_LogNormalRiskModel_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument_riskModel_SimpleRiskModel_params {
|
||||||
|
__typename: "SimpleRiskModelParams";
|
||||||
|
/**
|
||||||
|
* Risk factor for long
|
||||||
|
*/
|
||||||
|
factorLong: number;
|
||||||
|
/**
|
||||||
|
* Risk factor for short
|
||||||
|
*/
|
||||||
|
factorShort: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument_riskModel_SimpleRiskModel {
|
||||||
|
__typename: "SimpleRiskModel";
|
||||||
|
/**
|
||||||
|
* Params for the simple risk model
|
||||||
|
*/
|
||||||
|
params: MarketInfoQuery_market_tradableInstrument_riskModel_SimpleRiskModel_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MarketInfoQuery_market_tradableInstrument_riskModel = MarketInfoQuery_market_tradableInstrument_riskModel_LogNormalRiskModel | MarketInfoQuery_market_tradableInstrument_riskModel_SimpleRiskModel;
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_tradableInstrument {
|
||||||
|
__typename: "TradableInstrument";
|
||||||
|
/**
|
||||||
|
* An instance of or reference to a fully specified instrument.
|
||||||
|
*/
|
||||||
|
instrument: MarketInfoQuery_market_tradableInstrument_instrument;
|
||||||
|
/**
|
||||||
|
* A reference to a risk model that is valid for the instrument
|
||||||
|
*/
|
||||||
|
riskModel: MarketInfoQuery_market_tradableInstrument_riskModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_depth_lastTrade {
|
||||||
|
__typename: "Trade";
|
||||||
|
/**
|
||||||
|
* The price of the trade (probably initially the passive order price, other determination algorithms are possible though) (uint64)
|
||||||
|
*/
|
||||||
|
price: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market_depth {
|
||||||
|
__typename: "MarketDepth";
|
||||||
|
/**
|
||||||
|
* Last trade for the given market (if available)
|
||||||
|
*/
|
||||||
|
lastTrade: MarketInfoQuery_market_depth_lastTrade | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery_market {
|
||||||
|
__typename: "Market";
|
||||||
|
/**
|
||||||
|
* Market ID
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* Market full name
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
||||||
|
* number denominated in the currency of the Market. (uint64)
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* Currency Balance decimalPlaces Real Balance
|
||||||
|
* GBP 100 0 GBP 100
|
||||||
|
* GBP 100 2 GBP 1.00
|
||||||
|
* GBP 100 4 GBP 0.01
|
||||||
|
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
||||||
|
*
|
||||||
|
* GBX (pence) 100 0 GBP 1.00 (100p )
|
||||||
|
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
||||||
|
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
||||||
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
|
*/
|
||||||
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* Current state of the market
|
||||||
|
*/
|
||||||
|
state: MarketState;
|
||||||
|
/**
|
||||||
|
* Current mode of execution of the market
|
||||||
|
*/
|
||||||
|
tradingMode: MarketTradingMode;
|
||||||
|
/**
|
||||||
|
* Fees related data
|
||||||
|
*/
|
||||||
|
fees: MarketInfoQuery_market_fees;
|
||||||
|
/**
|
||||||
|
* Price monitoring settings for the market
|
||||||
|
*/
|
||||||
|
priceMonitoringSettings: MarketInfoQuery_market_priceMonitoringSettings;
|
||||||
|
/**
|
||||||
|
* risk factors for the market
|
||||||
|
*/
|
||||||
|
riskFactors: MarketInfoQuery_market_riskFactors | null;
|
||||||
|
/**
|
||||||
|
* marketData for the given market
|
||||||
|
*/
|
||||||
|
data: MarketInfoQuery_market_data | null;
|
||||||
|
/**
|
||||||
|
* An instance of or reference to a tradable instrument.
|
||||||
|
*/
|
||||||
|
tradableInstrument: MarketInfoQuery_market_tradableInstrument;
|
||||||
|
/**
|
||||||
|
* Current depth on the order book for this market
|
||||||
|
*/
|
||||||
|
depth: MarketInfoQuery_market_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQuery {
|
||||||
|
/**
|
||||||
|
* An instrument that is trading on the VEGA network
|
||||||
|
*/
|
||||||
|
market: MarketInfoQuery_market | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoQueryVariables {
|
||||||
|
marketId: string;
|
||||||
|
}
|
@ -1,108 +0,0 @@
|
|||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
// @generated
|
|
||||||
// This file was automatically generated and should not be edited.
|
|
||||||
|
|
||||||
import { BusEventType, OrderType, OrderStatus, OrderRejectionReason } from "@vegaprotocol/types";
|
|
||||||
|
|
||||||
// ====================================================
|
|
||||||
// GraphQL subscription operation: OrderEvent
|
|
||||||
// ====================================================
|
|
||||||
|
|
||||||
export interface OrderEvent_busEvents_event_TimeUpdate {
|
|
||||||
__typename: "TimeUpdate" | "MarketEvent" | "TransferResponses" | "PositionResolution" | "Trade" | "Account" | "Party" | "MarginLevels" | "Proposal" | "Vote" | "MarketData" | "NodeSignature" | "LossSocialization" | "SettlePosition" | "Market" | "Asset" | "MarketTick" | "SettleDistressed" | "AuctionEvent" | "RiskFactor" | "Deposit" | "Withdrawal" | "OracleSpec" | "LiquidityProvision";
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OrderEvent_busEvents_event_Order_market {
|
|
||||||
__typename: "Market";
|
|
||||||
/**
|
|
||||||
* Market full name
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
/**
|
|
||||||
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
|
||||||
* number denominated in the currency of the Market. (uint64)
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
* Currency Balance decimalPlaces Real Balance
|
|
||||||
* GBP 100 0 GBP 100
|
|
||||||
* GBP 100 2 GBP 1.00
|
|
||||||
* GBP 100 4 GBP 0.01
|
|
||||||
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
|
||||||
*
|
|
||||||
* GBX (pence) 100 0 GBP 1.00 (100p )
|
|
||||||
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
|
||||||
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
|
||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
|
||||||
*/
|
|
||||||
decimalPlaces: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OrderEvent_busEvents_event_Order {
|
|
||||||
__typename: "Order";
|
|
||||||
/**
|
|
||||||
* Type the order type (defaults to PARTY)
|
|
||||||
*/
|
|
||||||
type: OrderType | null;
|
|
||||||
/**
|
|
||||||
* Hash of the order data
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
/**
|
|
||||||
* The status of an order, for example 'Active'
|
|
||||||
*/
|
|
||||||
status: OrderStatus;
|
|
||||||
/**
|
|
||||||
* Reason for the order to be rejected
|
|
||||||
*/
|
|
||||||
rejectionReason: OrderRejectionReason | null;
|
|
||||||
/**
|
|
||||||
* RFC3339Nano formatted date and time for when the order was created (timestamp)
|
|
||||||
*/
|
|
||||||
createdAt: string;
|
|
||||||
/**
|
|
||||||
* Total number of contracts that may be bought or sold (immutable) (uint64)
|
|
||||||
*/
|
|
||||||
size: string;
|
|
||||||
/**
|
|
||||||
* The worst price the order will trade at (e.g. buy for price or less, sell for price or more) (uint64)
|
|
||||||
*/
|
|
||||||
price: string;
|
|
||||||
/**
|
|
||||||
* The market the order is trading on (probably stored internally as a hash of the market details)
|
|
||||||
*/
|
|
||||||
market: OrderEvent_busEvents_event_Order_market | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OrderEvent_busEvents_event = OrderEvent_busEvents_event_TimeUpdate | OrderEvent_busEvents_event_Order;
|
|
||||||
|
|
||||||
export interface OrderEvent_busEvents {
|
|
||||||
__typename: "BusEvent";
|
|
||||||
/**
|
|
||||||
* the id for this event
|
|
||||||
*/
|
|
||||||
eventId: string;
|
|
||||||
/**
|
|
||||||
* the block hash
|
|
||||||
*/
|
|
||||||
block: string;
|
|
||||||
/**
|
|
||||||
* the type of event we're dealing with
|
|
||||||
*/
|
|
||||||
type: BusEventType;
|
|
||||||
/**
|
|
||||||
* the payload - the wrapped event
|
|
||||||
*/
|
|
||||||
event: OrderEvent_busEvents_event;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OrderEvent {
|
|
||||||
/**
|
|
||||||
* Subscribe to event data from the event bus
|
|
||||||
*/
|
|
||||||
busEvents: OrderEvent_busEvents[] | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OrderEventVariables {
|
|
||||||
partyId: string;
|
|
||||||
}
|
|
@ -1,2 +1,2 @@
|
|||||||
export * from './DealTicketQuery';
|
export * from './DealTicketQuery';
|
||||||
export * from './OrderEvent';
|
export * from './MarketInfoQuery';
|
||||||
|
@ -12,22 +12,17 @@ export interface DealTicketAmountProps {
|
|||||||
price?: string;
|
price?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAmountComponent = (type: OrderType) => {
|
export const DealTicketAmount = ({
|
||||||
switch (type) {
|
orderType,
|
||||||
|
...props
|
||||||
|
}: DealTicketAmountProps) => {
|
||||||
|
switch (orderType) {
|
||||||
case OrderType.Market:
|
case OrderType.Market:
|
||||||
return DealTicketMarketAmount;
|
return <DealTicketMarketAmount {...props} />;
|
||||||
case OrderType.Limit:
|
case OrderType.Limit:
|
||||||
return DealTicketLimitAmount;
|
return <DealTicketLimitAmount {...props} />;
|
||||||
default: {
|
default: {
|
||||||
throw new Error('Invalid ticket type');
|
throw new Error('Invalid ticket type');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DealTicketAmount = ({
|
|
||||||
orderType,
|
|
||||||
...props
|
|
||||||
}: DealTicketAmountProps) => {
|
|
||||||
const AmountComponent = getAmountComponent(orderType);
|
|
||||||
return <AmountComponent {...props} />;
|
|
||||||
};
|
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
import { gql, useQuery } from '@apollo/client';
|
import { gql, useQuery } from '@apollo/client';
|
||||||
import {
|
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
AsyncRenderer,
|
|
||||||
GridTab,
|
|
||||||
GridTabs,
|
|
||||||
Splash,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { DealTicketManager } from './deal-ticket-manager';
|
import { DealTicketManager } from './deal-ticket-manager';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
import { Info } from './info-market';
|
|
||||||
import type { DealTicketQuery_market, DealTicketQuery } from './__generated__';
|
import type { DealTicketQuery_market, DealTicketQuery } from './__generated__';
|
||||||
|
|
||||||
const DEAL_TICKET_QUERY = gql`
|
const DEAL_TICKET_QUERY = gql`
|
||||||
@ -19,40 +13,6 @@ const DEAL_TICKET_QUERY = gql`
|
|||||||
positionDecimalPlaces
|
positionDecimalPlaces
|
||||||
state
|
state
|
||||||
tradingMode
|
tradingMode
|
||||||
fees {
|
|
||||||
factors {
|
|
||||||
makerFee
|
|
||||||
infrastructureFee
|
|
||||||
liquidityFee
|
|
||||||
}
|
|
||||||
}
|
|
||||||
priceMonitoringSettings {
|
|
||||||
parameters {
|
|
||||||
triggers {
|
|
||||||
horizonSecs
|
|
||||||
probability
|
|
||||||
auctionExtensionSecs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateFrequencySecs
|
|
||||||
}
|
|
||||||
riskFactors {
|
|
||||||
market
|
|
||||||
short
|
|
||||||
long
|
|
||||||
}
|
|
||||||
data {
|
|
||||||
market {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
markPrice
|
|
||||||
indicativeVolume
|
|
||||||
bestBidVolume
|
|
||||||
bestOfferVolume
|
|
||||||
bestStaticBidVolume
|
|
||||||
bestStaticOfferVolume
|
|
||||||
indicativeVolume
|
|
||||||
}
|
|
||||||
tradableInstrument {
|
tradableInstrument {
|
||||||
instrument {
|
instrument {
|
||||||
product {
|
product {
|
||||||
@ -66,23 +26,6 @@ const DEAL_TICKET_QUERY = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
riskModel {
|
|
||||||
... on LogNormalRiskModel {
|
|
||||||
tau
|
|
||||||
riskAversionParameter
|
|
||||||
params {
|
|
||||||
r
|
|
||||||
sigma
|
|
||||||
mu
|
|
||||||
}
|
|
||||||
}
|
|
||||||
... on SimpleRiskModel {
|
|
||||||
params {
|
|
||||||
factorLong
|
|
||||||
factorShort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
depth {
|
depth {
|
||||||
lastTrade {
|
lastTrade {
|
||||||
@ -111,45 +54,18 @@ export const DealTicketContainer = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GridTabs>
|
<AsyncRenderer<DealTicketQuery> data={data} loading={loading} error={error}>
|
||||||
<GridTab id="ticket" name={t('Ticket')}>
|
{data && data.market ? (
|
||||||
<AsyncRenderer<DealTicketQuery>
|
children ? (
|
||||||
data={data}
|
children(data)
|
||||||
loading={loading}
|
) : (
|
||||||
error={error}
|
<DealTicketManager market={data.market} />
|
||||||
>
|
)
|
||||||
{data && data.market ? (
|
) : (
|
||||||
children ? (
|
<Splash>
|
||||||
children(data)
|
<p>{t('Could not load market')}</p>
|
||||||
) : (
|
</Splash>
|
||||||
<DealTicketManager market={data.market} />
|
)}
|
||||||
)
|
</AsyncRenderer>
|
||||||
) : (
|
|
||||||
<Splash>
|
|
||||||
<p>{t('Could not load market')}</p>
|
|
||||||
</Splash>
|
|
||||||
)}
|
|
||||||
</AsyncRenderer>
|
|
||||||
</GridTab>
|
|
||||||
<GridTab id="info" name={t('Info')}>
|
|
||||||
<AsyncRenderer<DealTicketQuery>
|
|
||||||
data={data}
|
|
||||||
loading={loading}
|
|
||||||
error={error}
|
|
||||||
>
|
|
||||||
{data && data.market ? (
|
|
||||||
children ? (
|
|
||||||
children(data)
|
|
||||||
) : (
|
|
||||||
<Info market={data.market} />
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<Splash>
|
|
||||||
<p>{t('Could not load market')}</p>
|
|
||||||
</Splash>
|
|
||||||
)}
|
|
||||||
</AsyncRenderer>
|
|
||||||
</GridTab>
|
|
||||||
</GridTabs>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -37,6 +37,10 @@ export const DealTicketManager = ({
|
|||||||
return Intent.Danger;
|
return Intent.Danger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status === VegaTxStatus.Requested) {
|
||||||
|
return Intent.Warning;
|
||||||
|
}
|
||||||
|
|
||||||
if (status === VegaTxStatus.Error) {
|
if (status === VegaTxStatus.Error) {
|
||||||
return Intent.Danger;
|
return Intent.Danger;
|
||||||
}
|
}
|
||||||
@ -47,6 +51,8 @@ export const DealTicketManager = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (transaction.status !== VegaTxStatus.Default) {
|
if (transaction.status !== VegaTxStatus.Default) {
|
||||||
setOrderDialogOpen(true);
|
setOrderDialogOpen(true);
|
||||||
|
} else {
|
||||||
|
setOrderDialogOpen(false);
|
||||||
}
|
}
|
||||||
}, [transaction.status]);
|
}, [transaction.status]);
|
||||||
|
|
||||||
|
@ -6,13 +6,14 @@ import {
|
|||||||
import { addDecimal } from '@vegaprotocol/react-helpers';
|
import { addDecimal } from '@vegaprotocol/react-helpers';
|
||||||
import { fireEvent, render, screen, act } from '@testing-library/react';
|
import { fireEvent, render, screen, act } from '@testing-library/react';
|
||||||
import { DealTicket } from './deal-ticket';
|
import { DealTicket } from './deal-ticket';
|
||||||
import type { DealTicketQuery_market } from '../__generated__/DealTicketQuery';
|
import type { DealTicketQuery_market } from './__generated__/DealTicketQuery';
|
||||||
import type { Order } from '../utils/get-default-order';
|
import type { Order } from '../utils/get-default-order';
|
||||||
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||||
|
|
||||||
const market: DealTicketQuery_market = {
|
const market: DealTicketQuery_market = {
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
id: 'market-id',
|
id: 'market-id',
|
||||||
|
name: 'market-name',
|
||||||
decimalPlaces: 2,
|
decimalPlaces: 2,
|
||||||
positionDecimalPlaces: 1,
|
positionDecimalPlaces: 1,
|
||||||
tradingMode: MarketTradingMode.Continuous,
|
tradingMode: MarketTradingMode.Continuous,
|
||||||
@ -24,6 +25,12 @@ const market: DealTicketQuery_market = {
|
|||||||
product: {
|
product: {
|
||||||
__typename: 'Future',
|
__typename: 'Future',
|
||||||
quoteName: 'quote-name',
|
quoteName: 'quote-name',
|
||||||
|
settlementAsset: {
|
||||||
|
__typename: 'Asset',
|
||||||
|
id: 'asset-id',
|
||||||
|
name: 'asset-name',
|
||||||
|
symbol: 'asset-symbol',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -77,7 +77,7 @@ export const DealTicket = ({
|
|||||||
/>
|
/>
|
||||||
<DealTicketAmount
|
<DealTicketAmount
|
||||||
orderType={orderType}
|
orderType={orderType}
|
||||||
step={0.02}
|
step={step}
|
||||||
register={register}
|
register={register}
|
||||||
price={
|
price={
|
||||||
market.depth.lastTrade
|
market.depth.lastTrade
|
||||||
@ -109,7 +109,7 @@ export const DealTicket = ({
|
|||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
className="w-full mb-8"
|
className="w-full mb-8"
|
||||||
variant="primary"
|
variant="trade"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
data-testid="place-order"
|
data-testid="place-order"
|
||||||
|
@ -8,18 +8,130 @@ import {
|
|||||||
import {
|
import {
|
||||||
KeyValueTable,
|
KeyValueTable,
|
||||||
KeyValueTableRow,
|
KeyValueTableRow,
|
||||||
|
AsyncRenderer,
|
||||||
|
Splash,
|
||||||
Accordion,
|
Accordion,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import startCase from 'lodash/startCase';
|
import startCase from 'lodash/startCase';
|
||||||
import pick from 'lodash/pick';
|
import pick from 'lodash/pick';
|
||||||
import omit from 'lodash/omit';
|
import omit from 'lodash/omit';
|
||||||
import type { DealTicketQuery_market } from './__generated__/DealTicketQuery';
|
import type {
|
||||||
|
MarketInfoQuery,
|
||||||
|
MarketInfoQuery_market,
|
||||||
|
} from './__generated__/MarketInfoQuery';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { gql, useQuery } from '@apollo/client';
|
||||||
|
|
||||||
|
const MARKET_INFO_QUERY = gql`
|
||||||
|
query MarketInfoQuery($marketId: ID!) {
|
||||||
|
market(id: $marketId) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
decimalPlaces
|
||||||
|
positionDecimalPlaces
|
||||||
|
state
|
||||||
|
tradingMode
|
||||||
|
fees {
|
||||||
|
factors {
|
||||||
|
makerFee
|
||||||
|
infrastructureFee
|
||||||
|
liquidityFee
|
||||||
|
}
|
||||||
|
}
|
||||||
|
priceMonitoringSettings {
|
||||||
|
parameters {
|
||||||
|
triggers {
|
||||||
|
horizonSecs
|
||||||
|
probability
|
||||||
|
auctionExtensionSecs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateFrequencySecs
|
||||||
|
}
|
||||||
|
riskFactors {
|
||||||
|
market
|
||||||
|
short
|
||||||
|
long
|
||||||
|
}
|
||||||
|
data {
|
||||||
|
market {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
markPrice
|
||||||
|
indicativeVolume
|
||||||
|
bestBidVolume
|
||||||
|
bestOfferVolume
|
||||||
|
bestStaticBidVolume
|
||||||
|
bestStaticOfferVolume
|
||||||
|
indicativeVolume
|
||||||
|
}
|
||||||
|
tradableInstrument {
|
||||||
|
instrument {
|
||||||
|
product {
|
||||||
|
... on Future {
|
||||||
|
quoteName
|
||||||
|
settlementAsset {
|
||||||
|
id
|
||||||
|
symbol
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
riskModel {
|
||||||
|
... on LogNormalRiskModel {
|
||||||
|
tau
|
||||||
|
riskAversionParameter
|
||||||
|
params {
|
||||||
|
r
|
||||||
|
sigma
|
||||||
|
mu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on SimpleRiskModel {
|
||||||
|
params {
|
||||||
|
factorLong
|
||||||
|
factorShort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
depth {
|
||||||
|
lastTrade {
|
||||||
|
price
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export interface InfoProps {
|
export interface InfoProps {
|
||||||
market: DealTicketQuery_market;
|
market: MarketInfoQuery_market;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MarketInfoContainerProps {
|
||||||
|
marketId: string;
|
||||||
|
}
|
||||||
|
export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
|
||||||
|
const { data, loading, error } = useQuery(MARKET_INFO_QUERY, {
|
||||||
|
variables: { marketId },
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AsyncRenderer<MarketInfoQuery> data={data} loading={loading} error={error}>
|
||||||
|
{data && data.market ? (
|
||||||
|
<div className={'overflow-auto h-full'}>
|
||||||
|
<Info market={data.market} />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Splash>
|
||||||
|
<p>{t('Could not load market')}</p>
|
||||||
|
</Splash>
|
||||||
|
)}
|
||||||
|
</AsyncRenderer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Info = ({ market }: InfoProps) => {
|
export const Info = ({ market }: InfoProps) => {
|
||||||
const headerClassName =
|
const headerClassName =
|
||||||
'text-h5 font-bold uppercase text-black dark:text-white';
|
'text-h5 font-bold uppercase text-black dark:text-white';
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
|
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import type { OrderEvent_busEvents_event_Order } from './__generated__/OrderEvent';
|
import {
|
||||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
addDecimal,
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
t,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||||
|
import type { OrderEvent_busEvents_event_Order } from '../hooks/__generated__/OrderEvent';
|
||||||
|
|
||||||
interface OrderDialogProps {
|
interface OrderDialogProps {
|
||||||
transaction: VegaTxState;
|
transaction: VegaTxState;
|
||||||
@ -14,9 +18,22 @@ export const OrderDialog = ({
|
|||||||
transaction,
|
transaction,
|
||||||
finalizedOrder,
|
finalizedOrder,
|
||||||
}: OrderDialogProps) => {
|
}: OrderDialogProps) => {
|
||||||
// TODO: When wallets support confirming transactions return UI for 'awaiting confirmation' step
|
|
||||||
|
|
||||||
// Rejected by wallet
|
// Rejected by wallet
|
||||||
|
if (transaction.status === VegaTxStatus.Requested) {
|
||||||
|
return (
|
||||||
|
<OrderDialogWrapper
|
||||||
|
title="Confirm transaction in wallet"
|
||||||
|
icon={<Icon name="hand-up" size={20} />}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Please open your wallet application and confirm or reject the
|
||||||
|
transaction
|
||||||
|
</p>
|
||||||
|
</OrderDialogWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transaction error
|
||||||
if (transaction.status === VegaTxStatus.Error) {
|
if (transaction.status === VegaTxStatus.Error) {
|
||||||
return (
|
return (
|
||||||
<OrderDialogWrapper
|
<OrderDialogWrapper
|
||||||
@ -72,7 +89,14 @@ export const OrderDialog = ({
|
|||||||
<p>{t(`Market: ${finalizedOrder.market.name}`)}</p>
|
<p>{t(`Market: ${finalizedOrder.market.name}`)}</p>
|
||||||
)}
|
)}
|
||||||
<p>{t(`Type: ${finalizedOrder.type}`)}</p>
|
<p>{t(`Type: ${finalizedOrder.type}`)}</p>
|
||||||
<p>{t(`Amount: ${finalizedOrder.size}`)}</p>
|
<p>
|
||||||
|
{t(
|
||||||
|
`Amount: ${addDecimal(
|
||||||
|
finalizedOrder.size,
|
||||||
|
finalizedOrder.market?.positionDecimalPlaces || 0
|
||||||
|
)}`
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
{finalizedOrder.type === 'Limit' && finalizedOrder.market && (
|
{finalizedOrder.type === 'Limit' && finalizedOrder.market && (
|
||||||
<p>
|
<p>
|
||||||
{t(
|
{t(
|
||||||
|
@ -36,6 +36,12 @@ export interface OrderEvent_busEvents_event_Order_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderEvent_busEvents_event_Order {
|
export interface OrderEvent_busEvents_event_Order {
|
||||||
|
@ -4,12 +4,12 @@ import type { Order } from '../utils/get-default-order';
|
|||||||
import { OrderType, useVegaWallet } from '@vegaprotocol/wallet';
|
import { OrderType, useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { determineId, removeDecimal } from '@vegaprotocol/react-helpers';
|
import { determineId, removeDecimal } from '@vegaprotocol/react-helpers';
|
||||||
import { useVegaTransaction } from '@vegaprotocol/wallet';
|
import { useVegaTransaction } from '@vegaprotocol/wallet';
|
||||||
|
import type { DealTicketQuery_market } from '../components/__generated__/DealTicketQuery';
|
||||||
import type {
|
import type {
|
||||||
OrderEvent,
|
OrderEvent,
|
||||||
OrderEventVariables,
|
OrderEventVariables,
|
||||||
OrderEvent_busEvents_event_Order,
|
OrderEvent_busEvents_event_Order,
|
||||||
} from '../components/__generated__/OrderEvent';
|
} from './__generated__/OrderEvent';
|
||||||
import type { DealTicketQuery_market } from '../components/__generated__/DealTicketQuery';
|
|
||||||
|
|
||||||
const ORDER_EVENT_SUB = gql`
|
const ORDER_EVENT_SUB = gql`
|
||||||
subscription OrderEvent($partyId: ID!) {
|
subscription OrderEvent($partyId: ID!) {
|
||||||
@ -29,6 +29,7 @@ const ORDER_EVENT_SUB = gql`
|
|||||||
market {
|
market {
|
||||||
name
|
name
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
|
positionDecimalPlaces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ beforeEach(() => {
|
|||||||
submitDeposit: jest.fn(),
|
submitDeposit: jest.fn(),
|
||||||
requestFaucet: jest.fn(),
|
requestFaucet: jest.fn(),
|
||||||
limits: {
|
limits: {
|
||||||
min: new BigNumber(0),
|
|
||||||
max: new BigNumber(20),
|
max: new BigNumber(20),
|
||||||
},
|
},
|
||||||
allowance: new BigNumber(30),
|
allowance: new BigNumber(30),
|
||||||
@ -199,6 +198,6 @@ it('Deposit', async () => {
|
|||||||
// @ts-ignore contract address definitely defined
|
// @ts-ignore contract address definitely defined
|
||||||
assetSource: asset.source.contractAddress,
|
assetSource: asset.source.contractAddress,
|
||||||
amount: '1500',
|
amount: '1500',
|
||||||
vegaPublicKey: `0x${vegaKey}`,
|
vegaPublicKey: vegaKey,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -89,7 +89,7 @@ export const DepositForm = ({
|
|||||||
submitDeposit({
|
submitDeposit({
|
||||||
assetSource: selectedAsset.source.contractAddress,
|
assetSource: selectedAsset.source.contractAddress,
|
||||||
amount: removeDecimal(fields.amount, selectedAsset.decimals),
|
amount: removeDecimal(fields.amount, selectedAsset.decimals),
|
||||||
vegaPublicKey: `0x${fields.to}`,
|
vegaPublicKey: fields.to,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,6 +132,12 @@ export interface MarketDepth_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* marketData for the given market
|
* marketData for the given market
|
||||||
*/
|
*/
|
||||||
|
@ -55,6 +55,12 @@ export interface MarketDepthSubscription_marketDepthUpdate_market {
|
|||||||
* Market ID
|
* Market ID
|
||||||
*/
|
*/
|
||||||
id: string;
|
id: string;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* marketData for the given market
|
* marketData for the given market
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { DepthChart } from 'pennant';
|
import { DepthChart } from 'pennant';
|
||||||
import { produce } from 'immer';
|
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import {
|
||||||
@ -92,28 +91,31 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
|||||||
if (!dataRef.current) {
|
if (!dataRef.current) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dataRef.current = produce(dataRef.current, (draft) => {
|
dataRef.current = {
|
||||||
if (delta.buy) {
|
...dataRef.current,
|
||||||
draft.data.buy = updateLevels(
|
midPrice: delta.market.data?.staticMidPrice
|
||||||
draft.data.buy,
|
|
||||||
delta.buy,
|
|
||||||
decimalPlacesRef.current
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (delta.sell) {
|
|
||||||
draft.data.sell = updateLevels(
|
|
||||||
draft.data.sell,
|
|
||||||
delta.sell,
|
|
||||||
decimalPlacesRef.current
|
|
||||||
);
|
|
||||||
}
|
|
||||||
draft.midPrice = delta.market.data?.staticMidPrice
|
|
||||||
? formatMidPrice(
|
? formatMidPrice(
|
||||||
delta.market.data?.staticMidPrice,
|
delta.market.data?.staticMidPrice,
|
||||||
decimalPlacesRef.current
|
decimalPlacesRef.current
|
||||||
)
|
)
|
||||||
: undefined;
|
: undefined,
|
||||||
});
|
data: {
|
||||||
|
buy: delta.buy
|
||||||
|
? updateLevels(
|
||||||
|
dataRef.current.data.buy,
|
||||||
|
delta.buy,
|
||||||
|
decimalPlacesRef.current
|
||||||
|
)
|
||||||
|
: dataRef.current.data.buy,
|
||||||
|
sell: delta.sell
|
||||||
|
? updateLevels(
|
||||||
|
dataRef.current.data.sell,
|
||||||
|
delta.sell,
|
||||||
|
decimalPlacesRef.current
|
||||||
|
)
|
||||||
|
: dataRef.current.data.sell,
|
||||||
|
},
|
||||||
|
};
|
||||||
setDepthDataThrottledRef.current(dataRef.current);
|
setDepthDataThrottledRef.current(dataRef.current);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
@ -16,6 +16,7 @@ const MARKET_DEPTH_QUERY = gql`
|
|||||||
market(id: $marketId) {
|
market(id: $marketId) {
|
||||||
id
|
id
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
|
positionDecimalPlaces
|
||||||
data {
|
data {
|
||||||
staticMidPrice
|
staticMidPrice
|
||||||
marketTradingMode
|
marketTradingMode
|
||||||
@ -52,6 +53,7 @@ export const MARKET_DEPTH_SUBSCRIPTION_QUERY = gql`
|
|||||||
marketDepthUpdate(marketId: $marketId) {
|
marketDepthUpdate(marketId: $marketId) {
|
||||||
market {
|
market {
|
||||||
id
|
id
|
||||||
|
positionDecimalPlaces
|
||||||
data {
|
data {
|
||||||
staticMidPrice
|
staticMidPrice
|
||||||
marketTradingMode
|
marketTradingMode
|
||||||
@ -84,27 +86,31 @@ const sequenceNumbers: Record<string, number> = {};
|
|||||||
const update: Update<
|
const update: Update<
|
||||||
MarketDepth_market,
|
MarketDepth_market,
|
||||||
MarketDepthSubscription_marketDepthUpdate
|
MarketDepthSubscription_marketDepthUpdate
|
||||||
> = (draft, delta, reload) => {
|
> = (data, delta, reload) => {
|
||||||
if (delta.market.id !== draft.id) {
|
if (delta.market.id !== data.id) {
|
||||||
return;
|
return data;
|
||||||
}
|
}
|
||||||
const sequenceNumber = Number(delta.sequenceNumber);
|
const sequenceNumber = Number(delta.sequenceNumber);
|
||||||
if (sequenceNumber <= sequenceNumbers[delta.market.id]) {
|
if (sequenceNumber <= sequenceNumbers[delta.market.id]) {
|
||||||
return;
|
return data;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (sequenceNumber - 1 !== sequenceNumbers[delta.market.id]) {
|
if (sequenceNumber - 1 !== sequenceNumbers[delta.market.id]) {
|
||||||
sequenceNumbers[delta.market.id] = 0;
|
sequenceNumbers[delta.market.id] = 0;
|
||||||
reload();
|
reload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
sequenceNumbers[delta.market.id] = sequenceNumber;
|
sequenceNumbers[delta.market.id] = sequenceNumber;
|
||||||
Object.assign(draft.data, delta.market.data);
|
const updatedData = { ...data };
|
||||||
|
data.data = delta.market.data;
|
||||||
if (delta.buy) {
|
if (delta.buy) {
|
||||||
draft.depth.buy = updateLevels(draft.depth.buy ?? [], delta.buy);
|
updatedData.depth.buy = updateLevels(data.depth.buy ?? [], delta.buy);
|
||||||
}
|
}
|
||||||
if (delta.sell) {
|
if (delta.sell) {
|
||||||
draft.depth.sell = updateLevels(draft.depth.sell ?? [], delta.sell);
|
updatedData.depth.sell = updateLevels(data.depth.sell ?? [], delta.sell);
|
||||||
}
|
}
|
||||||
|
return updatedData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getData = (responseData: MarketDepth) => {
|
const getData = (responseData: MarketDepth) => {
|
||||||
|
@ -55,10 +55,8 @@ describe('compactRows', () => {
|
|||||||
'1097': 3,
|
'1097': 3,
|
||||||
'1098': 2,
|
'1098': 2,
|
||||||
'1099': 1,
|
'1099': 1,
|
||||||
'1100': 0,
|
|
||||||
});
|
});
|
||||||
expect(orderbookRows[orderbookRows.length - 1].bidByLevel).toEqual({
|
expect(orderbookRows[orderbookRows.length - 1].bidByLevel).toEqual({
|
||||||
'901': 0,
|
|
||||||
'902': 1,
|
'902': 1,
|
||||||
'903': 2,
|
'903': 2,
|
||||||
'904': 3,
|
'904': 3,
|
||||||
@ -81,7 +79,7 @@ describe('compactRows', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('updateLevels', () => {
|
describe('updateLevels', () => {
|
||||||
const levels: MarketDepth_market_depth_sell[] = new Array(10)
|
let levels: MarketDepth_market_depth_sell[] = new Array(10)
|
||||||
.fill(null)
|
.fill(null)
|
||||||
.map((n, i) => ({
|
.map((n, i) => ({
|
||||||
__typename: 'PriceLevel',
|
__typename: 'PriceLevel',
|
||||||
@ -96,9 +94,9 @@ describe('updateLevels', () => {
|
|||||||
volume: '0',
|
volume: '0',
|
||||||
numberOfOrders: '0',
|
numberOfOrders: '0',
|
||||||
};
|
};
|
||||||
updateLevels(levels, [removeFirstRow]);
|
levels = updateLevels(levels, [removeFirstRow]);
|
||||||
expect(levels[0].price).toEqual('20');
|
expect(levels[0].price).toEqual('20');
|
||||||
updateLevels(levels, [removeFirstRow]);
|
levels = updateLevels(levels, [removeFirstRow]);
|
||||||
expect(levels[0].price).toEqual('20');
|
expect(levels[0].price).toEqual('20');
|
||||||
expect(updateLevels([], [removeFirstRow])).toEqual([]);
|
expect(updateLevels([], [removeFirstRow])).toEqual([]);
|
||||||
const addFirstRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
const addFirstRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||||
@ -107,7 +105,7 @@ describe('updateLevels', () => {
|
|||||||
volume: '10',
|
volume: '10',
|
||||||
numberOfOrders: '10',
|
numberOfOrders: '10',
|
||||||
};
|
};
|
||||||
updateLevels(levels, [addFirstRow]);
|
levels = updateLevels(levels, [addFirstRow]);
|
||||||
expect(levels[0].price).toEqual('10');
|
expect(levels[0].price).toEqual('10');
|
||||||
const addBeforeLastRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
const addBeforeLastRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||||
__typename: 'PriceLevel',
|
__typename: 'PriceLevel',
|
||||||
@ -115,7 +113,7 @@ describe('updateLevels', () => {
|
|||||||
volume: '95',
|
volume: '95',
|
||||||
numberOfOrders: '95',
|
numberOfOrders: '95',
|
||||||
};
|
};
|
||||||
updateLevels(levels, [addBeforeLastRow]);
|
levels = updateLevels(levels, [addBeforeLastRow]);
|
||||||
expect(levels[levels.length - 2].price).toEqual('95');
|
expect(levels[levels.length - 2].price).toEqual('95');
|
||||||
const addAtTheEnd: MarketDepthSubscription_marketDepthUpdate_sell = {
|
const addAtTheEnd: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||||
__typename: 'PriceLevel',
|
__typename: 'PriceLevel',
|
||||||
@ -123,7 +121,7 @@ describe('updateLevels', () => {
|
|||||||
volume: '115',
|
volume: '115',
|
||||||
numberOfOrders: '115',
|
numberOfOrders: '115',
|
||||||
};
|
};
|
||||||
updateLevels(levels, [addAtTheEnd]);
|
levels = updateLevels(levels, [addAtTheEnd]);
|
||||||
expect(levels[levels.length - 1].price).toEqual('115');
|
expect(levels[levels.length - 1].price).toEqual('115');
|
||||||
const updateLastRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
const updateLastRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||||
__typename: 'PriceLevel',
|
__typename: 'PriceLevel',
|
||||||
@ -131,7 +129,7 @@ describe('updateLevels', () => {
|
|||||||
volume: '116',
|
volume: '116',
|
||||||
numberOfOrders: '115',
|
numberOfOrders: '115',
|
||||||
};
|
};
|
||||||
updateLevels(levels, [updateLastRow]);
|
levels = updateLevels(levels, [updateLastRow]);
|
||||||
expect(levels[levels.length - 1]).toEqual(updateLastRow);
|
expect(levels[levels.length - 1]).toEqual(updateLastRow);
|
||||||
expect(updateLevels([], [updateLastRow])).toEqual([updateLastRow]);
|
expect(updateLevels([], [updateLastRow])).toEqual([updateLastRow]);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import produce from 'immer';
|
|
||||||
import groupBy from 'lodash/groupBy';
|
import groupBy from 'lodash/groupBy';
|
||||||
import { VolumeType } from '@vegaprotocol/react-helpers';
|
import { VolumeType } from '@vegaprotocol/react-helpers';
|
||||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||||
@ -31,6 +30,8 @@ export interface OrderbookRowData {
|
|||||||
cumulativeVol: CumulativeVol;
|
cumulativeVol: CumulativeVol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PartialOrderbookRowData = Pick<OrderbookRowData, 'price' | 'ask' | 'bid'>;
|
||||||
|
|
||||||
export type OrderbookData = Partial<
|
export type OrderbookData = Partial<
|
||||||
Omit<MarketDepth_market_data, '__typename' | 'market'>
|
Omit<MarketDepth_market_data, '__typename' | 'market'>
|
||||||
> & { rows: OrderbookRowData[] | null };
|
> & { rows: OrderbookRowData[] | null };
|
||||||
@ -75,21 +76,31 @@ const updateRelativeData = (data: OrderbookRowData[]) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createPartialRow = (
|
||||||
|
price: string,
|
||||||
|
volume = 0,
|
||||||
|
dataType?: VolumeType
|
||||||
|
): PartialOrderbookRowData => ({
|
||||||
|
price,
|
||||||
|
ask: dataType === VolumeType.ask ? volume : 0,
|
||||||
|
bid: dataType === VolumeType.bid ? volume : 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const extendRow = (row: PartialOrderbookRowData): OrderbookRowData =>
|
||||||
|
Object.assign(row, {
|
||||||
|
cumulativeVol: {
|
||||||
|
ask: 0,
|
||||||
|
bid: 0,
|
||||||
|
},
|
||||||
|
askByLevel: row.ask ? { [row.price]: row.ask } : {},
|
||||||
|
bidByLevel: row.bid ? { [row.price]: row.bid } : {},
|
||||||
|
});
|
||||||
|
|
||||||
export const createRow = (
|
export const createRow = (
|
||||||
price: string,
|
price: string,
|
||||||
volume = 0,
|
volume = 0,
|
||||||
dataType?: VolumeType
|
dataType?: VolumeType
|
||||||
): OrderbookRowData => ({
|
): OrderbookRowData => extendRow(createPartialRow(price, volume, dataType));
|
||||||
price,
|
|
||||||
ask: dataType === VolumeType.ask ? volume : 0,
|
|
||||||
bid: dataType === VolumeType.bid ? volume : 0,
|
|
||||||
cumulativeVol: {
|
|
||||||
ask: dataType === VolumeType.ask ? volume : 0,
|
|
||||||
bid: dataType === VolumeType.bid ? volume : 0,
|
|
||||||
},
|
|
||||||
askByLevel: dataType === VolumeType.ask ? { [price]: volume } : {},
|
|
||||||
bidByLevel: dataType === VolumeType.bid ? { [price]: volume } : {},
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapRawData =
|
const mapRawData =
|
||||||
(dataType: VolumeType.ask | VolumeType.bid) =>
|
(dataType: VolumeType.ask | VolumeType.bid) =>
|
||||||
@ -99,8 +110,8 @@ const mapRawData =
|
|||||||
| MarketDepthSubscription_marketDepthUpdate_sell
|
| MarketDepthSubscription_marketDepthUpdate_sell
|
||||||
| MarketDepth_market_depth_buy
|
| MarketDepth_market_depth_buy
|
||||||
| MarketDepthSubscription_marketDepthUpdate_buy
|
| MarketDepthSubscription_marketDepthUpdate_buy
|
||||||
): OrderbookRowData =>
|
): PartialOrderbookRowData =>
|
||||||
createRow(data.price, Number(data.volume), dataType);
|
createPartialRow(data.price, Number(data.volume), dataType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary merges sell amd buy data, orders by price desc, group by price level, counts cumulative and relative values
|
* @summary merges sell amd buy data, orders by price desc, group by price level, counts cumulative and relative values
|
||||||
@ -121,37 +132,38 @@ export const compactRows = (
|
|||||||
resolution: number
|
resolution: number
|
||||||
) => {
|
) => {
|
||||||
// map raw sell data to OrderbookData
|
// map raw sell data to OrderbookData
|
||||||
const askOrderbookData = [...(sell ?? [])].map<OrderbookRowData>(
|
const askOrderbookData = [...(sell ?? [])].map<PartialOrderbookRowData>(
|
||||||
mapRawData(VolumeType.ask)
|
mapRawData(VolumeType.ask)
|
||||||
);
|
);
|
||||||
// map raw buy data to OrderbookData
|
// map raw buy data to OrderbookData
|
||||||
const bidOrderbookData = [...(buy ?? [])].map<OrderbookRowData>(
|
const bidOrderbookData = [...(buy ?? [])].map<PartialOrderbookRowData>(
|
||||||
mapRawData(VolumeType.bid)
|
mapRawData(VolumeType.bid)
|
||||||
);
|
);
|
||||||
|
|
||||||
// group by price level
|
// group by price level
|
||||||
const groupedByLevel = groupBy<OrderbookRowData>(
|
const groupedByLevel = groupBy<PartialOrderbookRowData>(
|
||||||
[...askOrderbookData, ...bidOrderbookData],
|
[...askOrderbookData, ...bidOrderbookData],
|
||||||
(row) => getPriceLevel(row.price, resolution)
|
(row) => getPriceLevel(row.price, resolution)
|
||||||
);
|
);
|
||||||
|
const orderbookData: OrderbookRowData[] = [];
|
||||||
// create single OrderbookData from grouped OrderbookData[], sum volumes and atore volume by level
|
Object.keys(groupedByLevel).forEach((price) => {
|
||||||
const orderbookData = Object.keys(groupedByLevel).reduce<OrderbookRowData[]>(
|
const row = extendRow(
|
||||||
(rows, price) =>
|
groupedByLevel[price].pop() as PartialOrderbookRowData
|
||||||
rows.concat(
|
);
|
||||||
groupedByLevel[price].reduce<OrderbookRowData>(
|
row.price = price;
|
||||||
(a, c) => ({
|
let subRow: PartialOrderbookRowData | undefined;
|
||||||
...a,
|
// eslint-disable-next-line no-cond-assign
|
||||||
ask: a.ask + c.ask,
|
while ((subRow = groupedByLevel[price].pop())) {
|
||||||
askByLevel: Object.assign(a.askByLevel, c.askByLevel),
|
row.ask += subRow.ask;
|
||||||
bid: (a.bid ?? 0) + (c.bid ?? 0),
|
row.bid += subRow.bid;
|
||||||
bidByLevel: Object.assign(a.bidByLevel, c.bidByLevel),
|
if (subRow.ask) {
|
||||||
}),
|
row.askByLevel[subRow.price] = subRow.ask;
|
||||||
createRow(price)
|
}
|
||||||
)
|
if (subRow.bid) {
|
||||||
),
|
row.bidByLevel[subRow.price] = subRow.bid;
|
||||||
[]
|
}
|
||||||
);
|
}
|
||||||
|
orderbookData.push(row);
|
||||||
|
});
|
||||||
// order by price, it's safe to cast to number price diff should not exceed Number.MAX_SAFE_INTEGER
|
// order by price, it's safe to cast to number price diff should not exceed Number.MAX_SAFE_INTEGER
|
||||||
orderbookData.sort((a, b) => Number(BigInt(b.price) - BigInt(a.price)));
|
orderbookData.sort((a, b) => Number(BigInt(b.price) - BigInt(a.price)));
|
||||||
// count cumulative volumes
|
// count cumulative volumes
|
||||||
@ -163,11 +175,9 @@ export const compactRows = (
|
|||||||
(i !== 0 ? orderbookData[i - 1].cumulativeVol.bid : 0);
|
(i !== 0 ? orderbookData[i - 1].cumulativeVol.bid : 0);
|
||||||
}
|
}
|
||||||
for (let i = maxIndex; i >= 0; i--) {
|
for (let i = maxIndex; i >= 0; i--) {
|
||||||
if (!orderbookData[i].cumulativeVol.ask) {
|
orderbookData[i].cumulativeVol.ask =
|
||||||
orderbookData[i].cumulativeVol.ask =
|
orderbookData[i].ask +
|
||||||
orderbookData[i].ask +
|
(i !== maxIndex ? orderbookData[i + 1].cumulativeVol.ask : 0);
|
||||||
(i !== maxIndex ? orderbookData[i + 1].cumulativeVol.ask : 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// count relative volumes
|
// count relative volumes
|
||||||
@ -186,13 +196,13 @@ export const compactRows = (
|
|||||||
*/
|
*/
|
||||||
const partiallyUpdateCompactedRows = (
|
const partiallyUpdateCompactedRows = (
|
||||||
dataType: VolumeType,
|
dataType: VolumeType,
|
||||||
draft: OrderbookRowData[],
|
data: OrderbookRowData[],
|
||||||
delta:
|
delta:
|
||||||
| MarketDepthSubscription_marketDepthUpdate_sell
|
| MarketDepthSubscription_marketDepthUpdate_sell
|
||||||
| MarketDepthSubscription_marketDepthUpdate_buy,
|
| MarketDepthSubscription_marketDepthUpdate_buy,
|
||||||
resolution: number,
|
resolution: number,
|
||||||
modifiedIndex: number
|
modifiedIndex: number
|
||||||
) => {
|
): [number, OrderbookRowData[]] => {
|
||||||
const { price } = delta;
|
const { price } = delta;
|
||||||
const volume = Number(delta.volume);
|
const volume = Number(delta.volume);
|
||||||
const priceLevel = getPriceLevel(price, resolution);
|
const priceLevel = getPriceLevel(price, resolution);
|
||||||
@ -201,28 +211,36 @@ const partiallyUpdateCompactedRows = (
|
|||||||
const oppositeVolKey = isAskDataType ? 'bid' : 'ask';
|
const oppositeVolKey = isAskDataType ? 'bid' : 'ask';
|
||||||
const volByLevelKey = isAskDataType ? 'askByLevel' : 'bidByLevel';
|
const volByLevelKey = isAskDataType ? 'askByLevel' : 'bidByLevel';
|
||||||
const resolveModifiedIndex = isAskDataType ? Math.max : Math.min;
|
const resolveModifiedIndex = isAskDataType ? Math.max : Math.min;
|
||||||
let index = draft.findIndex((data) => data.price === priceLevel);
|
let index = data.findIndex((row) => row.price === priceLevel);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
modifiedIndex = resolveModifiedIndex(modifiedIndex, index);
|
modifiedIndex = resolveModifiedIndex(modifiedIndex, index);
|
||||||
draft[index][volKey] =
|
data[index] = {
|
||||||
draft[index][volKey] - (draft[index][volByLevelKey][price] || 0) + volume;
|
...data[index],
|
||||||
draft[index][volByLevelKey][price] = volume;
|
[volKey]:
|
||||||
|
data[index][volKey] - (data[index][volByLevelKey][price] || 0) + volume,
|
||||||
|
[volByLevelKey]: {
|
||||||
|
...data[index][volByLevelKey],
|
||||||
|
[price]: volume,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return [modifiedIndex, [...data]];
|
||||||
} else {
|
} else {
|
||||||
const newData: OrderbookRowData = createRow(priceLevel, volume, dataType);
|
const newData: OrderbookRowData = createRow(priceLevel, volume, dataType);
|
||||||
index = draft.findIndex((data) => BigInt(data.price) < BigInt(priceLevel));
|
index = data.findIndex((row) => BigInt(row.price) < BigInt(priceLevel));
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
draft.splice(index, 0, newData);
|
|
||||||
newData.cumulativeVol[oppositeVolKey] =
|
newData.cumulativeVol[oppositeVolKey] =
|
||||||
draft[index + (isAskDataType ? -1 : 1)]?.cumulativeVol[
|
data[index + (isAskDataType ? 0 : 1)]?.cumulativeVol[oppositeVolKey] ??
|
||||||
oppositeVolKey
|
0;
|
||||||
] ?? 0;
|
|
||||||
modifiedIndex = resolveModifiedIndex(modifiedIndex, index);
|
modifiedIndex = resolveModifiedIndex(modifiedIndex, index);
|
||||||
|
return [
|
||||||
|
modifiedIndex,
|
||||||
|
[...data.slice(0, index), newData, ...data.slice(index)],
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
draft.push(newData);
|
modifiedIndex = data.length - 1;
|
||||||
modifiedIndex = draft.length - 1;
|
return [modifiedIndex, [...data, newData]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return modifiedIndex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -239,59 +257,66 @@ export const updateCompactedRows = (
|
|||||||
sell: MarketDepthSubscription_marketDepthUpdate_sell[] | null,
|
sell: MarketDepthSubscription_marketDepthUpdate_sell[] | null,
|
||||||
buy: MarketDepthSubscription_marketDepthUpdate_buy[] | null,
|
buy: MarketDepthSubscription_marketDepthUpdate_buy[] | null,
|
||||||
resolution: number
|
resolution: number
|
||||||
) =>
|
) => {
|
||||||
produce(rows, (draft) => {
|
let sellModifiedIndex = -1;
|
||||||
let sellModifiedIndex = -1;
|
let data = [...rows];
|
||||||
sell?.forEach((delta) => {
|
sell?.forEach((delta) => {
|
||||||
sellModifiedIndex = partiallyUpdateCompactedRows(
|
[sellModifiedIndex, data] = partiallyUpdateCompactedRows(
|
||||||
VolumeType.ask,
|
VolumeType.ask,
|
||||||
draft,
|
data,
|
||||||
delta,
|
delta,
|
||||||
resolution,
|
resolution,
|
||||||
sellModifiedIndex
|
sellModifiedIndex
|
||||||
);
|
);
|
||||||
});
|
|
||||||
let buyModifiedIndex = draft.length;
|
|
||||||
buy?.forEach((delta) => {
|
|
||||||
buyModifiedIndex = partiallyUpdateCompactedRows(
|
|
||||||
VolumeType.bid,
|
|
||||||
draft,
|
|
||||||
delta,
|
|
||||||
resolution,
|
|
||||||
buyModifiedIndex
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// update cummulative ask only below hihgest modified price level
|
|
||||||
if (sellModifiedIndex !== -1) {
|
|
||||||
for (let i = Math.min(sellModifiedIndex, draft.length - 2); i >= 0; i--) {
|
|
||||||
draft[i].cumulativeVol.ask =
|
|
||||||
draft[i + 1].cumulativeVol.ask + draft[i].ask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// update cummulative bid only above lowest modified price level
|
|
||||||
if (buyModifiedIndex !== draft.length) {
|
|
||||||
for (
|
|
||||||
let i = Math.max(buyModifiedIndex, 1), l = draft.length;
|
|
||||||
i < l;
|
|
||||||
i++
|
|
||||||
) {
|
|
||||||
draft[i].cumulativeVol.bid =
|
|
||||||
draft[i - 1].cumulativeVol.bid + draft[i].bid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let index = 0;
|
|
||||||
// remove levels that do not have any volume
|
|
||||||
while (index < draft.length) {
|
|
||||||
if (!draft[index].ask && !draft[index].bid) {
|
|
||||||
draft.splice(index, 1);
|
|
||||||
} else {
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// count relative volumes
|
|
||||||
updateRelativeData(draft);
|
|
||||||
});
|
});
|
||||||
|
let buyModifiedIndex = data.length;
|
||||||
|
buy?.forEach((delta) => {
|
||||||
|
[buyModifiedIndex, data] = partiallyUpdateCompactedRows(
|
||||||
|
VolumeType.bid,
|
||||||
|
data,
|
||||||
|
delta,
|
||||||
|
resolution,
|
||||||
|
buyModifiedIndex
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// update cummulative ask only below hihgest modified price level
|
||||||
|
if (sellModifiedIndex !== -1) {
|
||||||
|
for (let i = Math.min(sellModifiedIndex, data.length - 2); i >= 0; i--) {
|
||||||
|
data[i] = {
|
||||||
|
...data[i],
|
||||||
|
cumulativeVol: {
|
||||||
|
...data[i].cumulativeVol,
|
||||||
|
ask: data[i + 1].cumulativeVol.ask + data[i].ask,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// update cummulative bid only above lowest modified price level
|
||||||
|
if (buyModifiedIndex !== data.length) {
|
||||||
|
for (let i = Math.max(buyModifiedIndex, 1), l = data.length; i < l; i++) {
|
||||||
|
data[i] = {
|
||||||
|
...data[i],
|
||||||
|
cumulativeVol: {
|
||||||
|
...data[i].cumulativeVol,
|
||||||
|
bid: data[i - 1].cumulativeVol.bid + data[i].bid,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let index = 0;
|
||||||
|
// remove levels that do not have any volume
|
||||||
|
while (index < data.length) {
|
||||||
|
if (!data[index].ask && !data[index].bid) {
|
||||||
|
data.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// count relative volumes
|
||||||
|
updateRelativeData(data);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
export const mapMarketData = (
|
export const mapMarketData = (
|
||||||
data:
|
data:
|
||||||
@ -319,23 +344,24 @@ export const mapMarketData = (
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const updateLevels = (
|
export const updateLevels = (
|
||||||
levels: (MarketDepth_market_depth_buy | MarketDepth_market_depth_sell)[],
|
draft: (MarketDepth_market_depth_buy | MarketDepth_market_depth_sell)[],
|
||||||
updates: (
|
updates: (
|
||||||
| MarketDepthSubscription_marketDepthUpdate_buy
|
| MarketDepthSubscription_marketDepthUpdate_buy
|
||||||
| MarketDepthSubscription_marketDepthUpdate_sell
|
| MarketDepthSubscription_marketDepthUpdate_sell
|
||||||
)[]
|
)[]
|
||||||
) => {
|
) => {
|
||||||
|
const levels = [...draft];
|
||||||
updates.forEach((update) => {
|
updates.forEach((update) => {
|
||||||
let index = levels.findIndex((level) => level.price === update.price);
|
let index = levels.findIndex((level) => level.price === update.price);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
if (update.volume === '0') {
|
if (update.volume === '0') {
|
||||||
levels.splice(index, 1);
|
levels.splice(index, 1);
|
||||||
} else {
|
} else {
|
||||||
Object.assign(levels[index], update);
|
levels[index] = update;
|
||||||
}
|
}
|
||||||
} else if (update.volume !== '0') {
|
} else if (update.volume !== '0') {
|
||||||
index = levels.findIndex(
|
index = levels.findIndex(
|
||||||
(level) => Number(level.price) > Number(update.price)
|
(level) => BigInt(level.price) > BigInt(update.price)
|
||||||
);
|
);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
levels.splice(index, 0, update);
|
levels.splice(index, 0, update);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
import produce from 'immer';
|
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Orderbook } from './orderbook';
|
import { Orderbook } from './orderbook';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
@ -25,27 +24,52 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
|||||||
rows: null,
|
rows: null,
|
||||||
});
|
});
|
||||||
const dataRef = useRef<OrderbookData>({ rows: null });
|
const dataRef = useRef<OrderbookData>({ rows: null });
|
||||||
const setOrderbookDataThrottled = useRef(throttle(setOrderbookData, 1000));
|
const deltaRef = useRef<MarketDepthSubscription_marketDepthUpdate>();
|
||||||
|
const updateOrderbookData = useRef(
|
||||||
|
throttle(() => {
|
||||||
|
if (!deltaRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dataRef.current = {
|
||||||
|
...deltaRef.current.market.data,
|
||||||
|
...mapMarketData(deltaRef.current.market.data, resolutionRef.current),
|
||||||
|
rows: updateCompactedRows(
|
||||||
|
dataRef.current.rows ?? [],
|
||||||
|
deltaRef.current.sell,
|
||||||
|
deltaRef.current.buy,
|
||||||
|
resolutionRef.current
|
||||||
|
),
|
||||||
|
};
|
||||||
|
deltaRef.current = undefined;
|
||||||
|
setOrderbookData(dataRef.current);
|
||||||
|
}, 1000)
|
||||||
|
);
|
||||||
|
|
||||||
const update = useCallback(
|
const update = useCallback(
|
||||||
(delta: MarketDepthSubscription_marketDepthUpdate) => {
|
(delta: MarketDepthSubscription_marketDepthUpdate) => {
|
||||||
if (!dataRef.current.rows) {
|
if (!dataRef.current.rows) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dataRef.current = produce(dataRef.current, (draft) => {
|
if (deltaRef.current) {
|
||||||
Object.assign(draft, delta.market.data);
|
deltaRef.current.market = delta.market;
|
||||||
draft.rows = updateCompactedRows(
|
if (delta.sell) {
|
||||||
draft.rows ?? [],
|
if (deltaRef.current.sell) {
|
||||||
delta.sell,
|
deltaRef.current.sell.push(...delta.sell);
|
||||||
delta.buy,
|
} else {
|
||||||
resolutionRef.current
|
deltaRef.current.sell = delta.sell;
|
||||||
);
|
}
|
||||||
Object.assign(
|
}
|
||||||
draft,
|
if (delta.buy) {
|
||||||
mapMarketData(delta.market.data, resolutionRef.current)
|
if (deltaRef.current.buy) {
|
||||||
);
|
deltaRef.current.buy.push(...delta.buy);
|
||||||
});
|
} else {
|
||||||
setOrderbookDataThrottled.current(dataRef.current);
|
deltaRef.current.buy = delta.buy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deltaRef.current = delta;
|
||||||
|
}
|
||||||
|
updateOrderbookData.current();
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
// using resolutionRef.current to avoid using resolution as a dependency - it will cause data provider restart on resolution change
|
// using resolutionRef.current to avoid using resolution as a dependency - it will cause data provider restart on resolution change
|
||||||
@ -82,6 +106,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
|||||||
<Orderbook
|
<Orderbook
|
||||||
{...orderbookData}
|
{...orderbookData}
|
||||||
decimalPlaces={data?.decimalPlaces ?? 0}
|
decimalPlaces={data?.decimalPlaces ?? 0}
|
||||||
|
positionDecimalPlaces={data?.positionDecimalPlaces ?? 0}
|
||||||
resolution={resolution}
|
resolution={resolution}
|
||||||
onResolutionChange={(resolution: number) => setResolution(resolution)}
|
onResolutionChange={(resolution: number) => setResolution(resolution)}
|
||||||
/>
|
/>
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
CumulativeVol,
|
CumulativeVol,
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
VolumeType,
|
VolumeType,
|
||||||
|
addDecimal,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
interface OrderbookRowProps {
|
interface OrderbookRowProps {
|
||||||
@ -15,6 +16,7 @@ interface OrderbookRowProps {
|
|||||||
cumulativeRelativeAsk?: number;
|
cumulativeRelativeAsk?: number;
|
||||||
cumulativeRelativeBid?: number;
|
cumulativeRelativeBid?: number;
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
positionDecimalPlaces: number;
|
||||||
indicativeVolume?: string;
|
indicativeVolume?: string;
|
||||||
price: string;
|
price: string;
|
||||||
relativeAsk?: number;
|
relativeAsk?: number;
|
||||||
@ -30,6 +32,7 @@ export const OrderbookRow = React.memo(
|
|||||||
cumulativeRelativeAsk,
|
cumulativeRelativeAsk,
|
||||||
cumulativeRelativeBid,
|
cumulativeRelativeBid,
|
||||||
decimalPlaces,
|
decimalPlaces,
|
||||||
|
positionDecimalPlaces,
|
||||||
indicativeVolume,
|
indicativeVolume,
|
||||||
price,
|
price,
|
||||||
relativeAsk,
|
relativeAsk,
|
||||||
@ -40,6 +43,7 @@ export const OrderbookRow = React.memo(
|
|||||||
<Vol
|
<Vol
|
||||||
testId={`bid-vol-${price}`}
|
testId={`bid-vol-${price}`}
|
||||||
value={bid}
|
value={bid}
|
||||||
|
valueFormatted={addDecimal(bid, positionDecimalPlaces)}
|
||||||
relativeValue={relativeBid}
|
relativeValue={relativeBid}
|
||||||
type={VolumeType.bid}
|
type={VolumeType.bid}
|
||||||
/>
|
/>
|
||||||
@ -51,6 +55,7 @@ export const OrderbookRow = React.memo(
|
|||||||
<Vol
|
<Vol
|
||||||
testId={`ask-vol-${price}`}
|
testId={`ask-vol-${price}`}
|
||||||
value={ask}
|
value={ask}
|
||||||
|
valueFormatted={addDecimal(ask, positionDecimalPlaces)}
|
||||||
relativeValue={relativeAsk}
|
relativeValue={relativeAsk}
|
||||||
type={VolumeType.ask}
|
type={VolumeType.ask}
|
||||||
/>
|
/>
|
||||||
|
@ -22,6 +22,7 @@ describe('Orderbook', () => {
|
|||||||
const result = render(
|
const result = render(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData(params)}
|
{...generateMockData(params)}
|
||||||
onResolutionChange={onResolutionChange}
|
onResolutionChange={onResolutionChange}
|
||||||
/>
|
/>
|
||||||
@ -35,6 +36,7 @@ describe('Orderbook', () => {
|
|||||||
const result = render(
|
const result = render(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData(params)}
|
{...generateMockData(params)}
|
||||||
onResolutionChange={onResolutionChange}
|
onResolutionChange={onResolutionChange}
|
||||||
/>
|
/>
|
||||||
@ -44,6 +46,7 @@ describe('Orderbook', () => {
|
|||||||
result.rerender(
|
result.rerender(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData({
|
{...generateMockData({
|
||||||
...params,
|
...params,
|
||||||
numberOfSellRows: params.numberOfSellRows - 1,
|
numberOfSellRows: params.numberOfSellRows - 1,
|
||||||
@ -60,6 +63,7 @@ describe('Orderbook', () => {
|
|||||||
const result = render(
|
const result = render(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData(params)}
|
{...generateMockData(params)}
|
||||||
onResolutionChange={onResolutionChange}
|
onResolutionChange={onResolutionChange}
|
||||||
/>
|
/>
|
||||||
@ -69,6 +73,7 @@ describe('Orderbook', () => {
|
|||||||
result.rerender(
|
result.rerender(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData({
|
{...generateMockData({
|
||||||
...params,
|
...params,
|
||||||
bestStaticBidPrice: params.bestStaticBidPrice + 1,
|
bestStaticBidPrice: params.bestStaticBidPrice + 1,
|
||||||
@ -86,6 +91,7 @@ describe('Orderbook', () => {
|
|||||||
const result = render(
|
const result = render(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData(params)}
|
{...generateMockData(params)}
|
||||||
onResolutionChange={onResolutionChange}
|
onResolutionChange={onResolutionChange}
|
||||||
/>
|
/>
|
||||||
@ -98,6 +104,7 @@ describe('Orderbook', () => {
|
|||||||
result.rerender(
|
result.rerender(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData({
|
{...generateMockData({
|
||||||
...params,
|
...params,
|
||||||
numberOfSellRows: params.numberOfSellRows - 1,
|
numberOfSellRows: params.numberOfSellRows - 1,
|
||||||
@ -114,6 +121,7 @@ describe('Orderbook', () => {
|
|||||||
const result = render(
|
const result = render(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData(params)}
|
{...generateMockData(params)}
|
||||||
onResolutionChange={onResolutionChange}
|
onResolutionChange={onResolutionChange}
|
||||||
/>
|
/>
|
||||||
@ -134,6 +142,7 @@ describe('Orderbook', () => {
|
|||||||
const result = render(
|
const result = render(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData(params)}
|
{...generateMockData(params)}
|
||||||
onResolutionChange={onResolutionChange}
|
onResolutionChange={onResolutionChange}
|
||||||
/>
|
/>
|
||||||
@ -153,6 +162,7 @@ describe('Orderbook', () => {
|
|||||||
result.rerender(
|
result.rerender(
|
||||||
<Orderbook
|
<Orderbook
|
||||||
decimalPlaces={decimalPlaces}
|
decimalPlaces={decimalPlaces}
|
||||||
|
positionDecimalPlaces={0}
|
||||||
{...generateMockData({
|
{...generateMockData({
|
||||||
...params,
|
...params,
|
||||||
resolution: 10,
|
resolution: 10,
|
||||||
|
@ -19,6 +19,7 @@ import { Icon, Splash } from '@vegaprotocol/ui-toolkit';
|
|||||||
import type { OrderbookData, OrderbookRowData } from './orderbook-data';
|
import type { OrderbookData, OrderbookRowData } from './orderbook-data';
|
||||||
interface OrderbookProps extends OrderbookData {
|
interface OrderbookProps extends OrderbookData {
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
positionDecimalPlaces: number;
|
||||||
resolution: number;
|
resolution: number;
|
||||||
onResolutionChange: (resolution: number) => void;
|
onResolutionChange: (resolution: number) => void;
|
||||||
}
|
}
|
||||||
@ -100,6 +101,7 @@ export const Orderbook = ({
|
|||||||
indicativeVolume,
|
indicativeVolume,
|
||||||
indicativePrice,
|
indicativePrice,
|
||||||
decimalPlaces,
|
decimalPlaces,
|
||||||
|
positionDecimalPlaces,
|
||||||
resolution,
|
resolution,
|
||||||
onResolutionChange,
|
onResolutionChange,
|
||||||
}: OrderbookProps) => {
|
}: OrderbookProps) => {
|
||||||
@ -174,7 +176,10 @@ export const Orderbook = ({
|
|||||||
// adjust to current rows position
|
// adjust to current rows position
|
||||||
scrollTop +=
|
scrollTop +=
|
||||||
(scrollTopRef.current % rowHeight) - (scrollTop % rowHeight);
|
(scrollTopRef.current % rowHeight) - (scrollTop % rowHeight);
|
||||||
const priceCenterScrollOffset = Math.max(0, Math.min(scrollTop));
|
const priceCenterScrollOffset = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(scrollTop, numberOfRows * rowHeight - viewportHeight)
|
||||||
|
);
|
||||||
if (scrollTopRef.current !== priceCenterScrollOffset) {
|
if (scrollTopRef.current !== priceCenterScrollOffset) {
|
||||||
updateScrollOffset(priceCenterScrollOffset);
|
updateScrollOffset(priceCenterScrollOffset);
|
||||||
scrollTopRef.current = priceCenterScrollOffset;
|
scrollTopRef.current = priceCenterScrollOffset;
|
||||||
@ -182,7 +187,13 @@ export const Orderbook = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[maxPriceLevel, resolution, viewportHeight, updateScrollOffset]
|
[
|
||||||
|
maxPriceLevel,
|
||||||
|
resolution,
|
||||||
|
viewportHeight,
|
||||||
|
numberOfRows,
|
||||||
|
updateScrollOffset,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -197,23 +208,36 @@ export const Orderbook = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
priceInCenter.current = undefined;
|
priceInCenter.current = undefined;
|
||||||
setLockOnMidPrice(true);
|
let midPrice = getPriceLevel(
|
||||||
scrollToPrice(
|
BigInt(bestStaticOfferPrice) +
|
||||||
getPriceLevel(
|
(BigInt(bestStaticBidPrice) - BigInt(bestStaticOfferPrice)) / BigInt(2),
|
||||||
BigInt(bestStaticOfferPrice) +
|
resolution
|
||||||
(BigInt(bestStaticBidPrice) - BigInt(bestStaticOfferPrice)) /
|
|
||||||
BigInt(2),
|
|
||||||
resolution
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}, [bestStaticOfferPrice, bestStaticBidPrice, scrollToPrice, resolution]);
|
if (BigInt(midPrice) > BigInt(maxPriceLevel)) {
|
||||||
|
midPrice = maxPriceLevel;
|
||||||
|
} else {
|
||||||
|
const minPriceLevel =
|
||||||
|
BigInt(maxPriceLevel) - BigInt(Math.floor(numberOfRows * resolution));
|
||||||
|
if (BigInt(midPrice) < minPriceLevel) {
|
||||||
|
midPrice = minPriceLevel.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scrollToPrice(midPrice);
|
||||||
|
setLockOnMidPrice(true);
|
||||||
|
}, [
|
||||||
|
bestStaticOfferPrice,
|
||||||
|
bestStaticBidPrice,
|
||||||
|
scrollToPrice,
|
||||||
|
resolution,
|
||||||
|
maxPriceLevel,
|
||||||
|
numberOfRows,
|
||||||
|
]);
|
||||||
|
|
||||||
// adjust scroll position to keep selected price in center
|
// adjust scroll position to keep selected price in center
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (resolutionRef.current !== resolution) {
|
if (resolutionRef.current !== resolution) {
|
||||||
priceInCenter.current = undefined;
|
priceInCenter.current = undefined;
|
||||||
resolutionRef.current = resolution;
|
resolutionRef.current = resolution;
|
||||||
setLockOnMidPrice(true);
|
|
||||||
}
|
}
|
||||||
if (priceInCenter.current) {
|
if (priceInCenter.current) {
|
||||||
scrollToPrice(priceInCenter.current);
|
scrollToPrice(priceInCenter.current);
|
||||||
@ -236,21 +260,19 @@ export const Orderbook = ({
|
|||||||
return () => window.removeEventListener('resize', handleResize);
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const renderedRows = useMemo(() => {
|
let offset = Math.max(0, Math.round(scrollOffset / rowHeight));
|
||||||
let offset = Math.max(0, Math.round(scrollOffset / rowHeight));
|
const prependingBufferSize = Math.min(bufferSize, offset);
|
||||||
const prependingBufferSize = Math.min(bufferSize, offset);
|
offset -= prependingBufferSize;
|
||||||
offset -= prependingBufferSize;
|
const viewportSize = Math.round(viewportHeight / rowHeight);
|
||||||
const viewportSize = Math.round(viewportHeight / rowHeight);
|
const limit = Math.min(
|
||||||
const limit = Math.min(
|
prependingBufferSize + viewportSize + bufferSize,
|
||||||
prependingBufferSize + viewportSize + bufferSize,
|
numberOfRows - offset
|
||||||
numberOfRows - offset
|
);
|
||||||
);
|
const renderedRows = {
|
||||||
return {
|
offset,
|
||||||
offset,
|
limit,
|
||||||
limit,
|
data: getRowsToRender(rows, resolution, offset, limit),
|
||||||
data: getRowsToRender(rows, resolution, offset, limit),
|
};
|
||||||
};
|
|
||||||
}, [rows, scrollOffset, resolution, viewportHeight, numberOfRows]);
|
|
||||||
|
|
||||||
const paddingTop = renderedRows.offset * rowHeight;
|
const paddingTop = renderedRows.offset * rowHeight;
|
||||||
const paddingBottom =
|
const paddingBottom =
|
||||||
@ -298,6 +320,7 @@ export const Orderbook = ({
|
|||||||
<OrderbookRow
|
<OrderbookRow
|
||||||
price={(BigInt(data.price) / BigInt(resolution)).toString()}
|
price={(BigInt(data.price) / BigInt(resolution)).toString()}
|
||||||
decimalPlaces={decimalPlaces - Math.log10(resolution)}
|
decimalPlaces={decimalPlaces - Math.log10(resolution)}
|
||||||
|
positionDecimalPlaces={positionDecimalPlaces}
|
||||||
bid={data.bid}
|
bid={data.bid}
|
||||||
relativeBid={data.relativeBid}
|
relativeBid={data.relativeBid}
|
||||||
cumulativeBid={data.cumulativeVol.bid}
|
cumulativeBid={data.cumulativeVol.bid}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import produce from 'immer';
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import type {
|
import type {
|
||||||
Markets,
|
Markets,
|
||||||
@ -90,13 +91,14 @@ const MARKET_DATA_SUB = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const update = (draft: Markets_markets[], delta: MarketDataSub_marketData) => {
|
const update = (data: Markets_markets[], delta: MarketDataSub_marketData) =>
|
||||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
produce(data, (draft) => {
|
||||||
if (index !== -1) {
|
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||||
draft[index].data = delta;
|
if (index !== -1) {
|
||||||
}
|
draft[index].data = delta;
|
||||||
// @TODO - else push new market to draft
|
}
|
||||||
};
|
// @TODO - else push new market to draft
|
||||||
|
});
|
||||||
const getData = (responseData: Markets): Markets_markets[] | null =>
|
const getData = (responseData: Markets): Markets_markets[] | null =>
|
||||||
responseData.markets;
|
responseData.markets;
|
||||||
const getDelta = (subscriptionData: MarketDataSub): MarketDataSub_marketData =>
|
const getDelta = (subscriptionData: MarketDataSub): MarketDataSub_marketData =>
|
||||||
|
@ -52,6 +52,12 @@ export interface OrderFields_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a tradable instrument.
|
* An instance of or reference to a tradable instrument.
|
||||||
*/
|
*/
|
||||||
|
@ -52,6 +52,12 @@ export interface OrderSub_orders_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a tradable instrument.
|
* An instance of or reference to a tradable instrument.
|
||||||
*/
|
*/
|
||||||
|
6
libs/order-list/src/lib/__generated__/Orders.ts
generated
6
libs/order-list/src/lib/__generated__/Orders.ts
generated
@ -52,6 +52,12 @@ export interface Orders_party_orders_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a tradable instrument.
|
* An instance of or reference to a tradable instrument.
|
||||||
*/
|
*/
|
||||||
|
@ -25,6 +25,7 @@ const marketOrder: Orders_party_orders = {
|
|||||||
id: 'market-id',
|
id: 'market-id',
|
||||||
name: 'market-name',
|
name: 'market-name',
|
||||||
decimalPlaces: 2,
|
decimalPlaces: 2,
|
||||||
|
positionDecimalPlaces: 0,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
__typename: 'TradableInstrument',
|
__typename: 'TradableInstrument',
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -54,6 +55,7 @@ const limitOrder: Orders_party_orders = {
|
|||||||
id: 'market-id',
|
id: 'market-id',
|
||||||
name: 'market-name',
|
name: 'market-name',
|
||||||
decimalPlaces: 2,
|
decimalPlaces: 2,
|
||||||
|
positionDecimalPlaces: 2,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
__typename: 'TradableInstrument',
|
__typename: 'TradableInstrument',
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -62,11 +64,11 @@ const limitOrder: Orders_party_orders = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
size: '10',
|
size: '1000',
|
||||||
type: OrderType.Limit,
|
type: OrderType.Limit,
|
||||||
status: OrderStatus.Active,
|
status: OrderStatus.Active,
|
||||||
side: Side.Sell,
|
side: Side.Sell,
|
||||||
remaining: '5',
|
remaining: '500',
|
||||||
price: '12345',
|
price: '12345',
|
||||||
timeInForce: OrderTimeInForce.GTT,
|
timeInForce: OrderTimeInForce.GTT,
|
||||||
createdAt: new Date('2022-3-3').toISOString(),
|
createdAt: new Date('2022-3-3').toISOString(),
|
||||||
@ -122,10 +124,10 @@ it('Correct formatting applied for GTT limit order', async () => {
|
|||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
const expectedValues = [
|
const expectedValues = [
|
||||||
limitOrder.market?.tradableInstrument.instrument.code,
|
limitOrder.market?.tradableInstrument.instrument.code,
|
||||||
'-10',
|
'-10.00',
|
||||||
limitOrder.type,
|
limitOrder.type,
|
||||||
limitOrder.status,
|
limitOrder.status,
|
||||||
'5',
|
'5.00',
|
||||||
formatNumber(limitOrder.price, limitOrder.market?.decimalPlaces ?? 0),
|
formatNumber(limitOrder.price, limitOrder.market?.decimalPlaces ?? 0),
|
||||||
`${limitOrder.timeInForce}: ${getDateTimeFormat().format(
|
`${limitOrder.timeInForce}: ${getDateTimeFormat().format(
|
||||||
new Date(limitOrder.expiresAt ?? '')
|
new Date(limitOrder.expiresAt ?? '')
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
import { OrderTimeInForce, OrderStatus, Side } from '@vegaprotocol/types';
|
import { OrderTimeInForce, OrderStatus, Side } from '@vegaprotocol/types';
|
||||||
import type { Orders_party_orders } from './__generated__/Orders';
|
import type { Orders_party_orders } from './__generated__/Orders';
|
||||||
import { formatNumber, getDateTimeFormat } from '@vegaprotocol/react-helpers';
|
import {
|
||||||
|
addDecimal,
|
||||||
|
formatNumber,
|
||||||
|
getDateTimeFormat,
|
||||||
|
t,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { ValueFormatterParams } from 'ag-grid-community';
|
import type { ValueFormatterParams } from 'ag-grid-community';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
import { forwardRef } from 'react';
|
import { forwardRef } from 'react';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
interface OrderListProps {
|
interface OrderListProps {
|
||||||
data: Orders_party_orders[] | null;
|
data: Orders_party_orders[] | null;
|
||||||
@ -23,16 +29,18 @@ export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
|||||||
getRowId={({ data }) => data.id}
|
getRowId={({ data }) => data.id}
|
||||||
>
|
>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName="Market"
|
headerName={t('Market')}
|
||||||
field="market.tradableInstrument.instrument.code"
|
field="market.tradableInstrument.instrument.code"
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName="Amount"
|
headerName={t('Amount')}
|
||||||
field="size"
|
field="size"
|
||||||
cellClass="font-mono"
|
cellClass="font-mono"
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) => {
|
valueFormatter={({ value, data }: ValueFormatterParams) => {
|
||||||
const prefix = data.side === Side.Buy ? '+' : '-';
|
const prefix = data.side === Side.Buy ? '+' : '-';
|
||||||
return prefix + value;
|
return (
|
||||||
|
prefix + addDecimal(value, data.market.positionDecimalPlaces)
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn field="type" />
|
<AgGridColumn field="type" />
|
||||||
@ -47,11 +55,18 @@ export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName="Filled"
|
headerName={t('Filled')}
|
||||||
field="remaining"
|
field="remaining"
|
||||||
cellClass="font-mono"
|
cellClass="font-mono"
|
||||||
valueFormatter={({ data }: ValueFormatterParams) => {
|
valueFormatter={({ data }: ValueFormatterParams) => {
|
||||||
return `${Number(data.size) - Number(data.remaining)}/${data.size}`;
|
const dps = data.market.positionDecimalPlaces;
|
||||||
|
const size = new BigNumber(data.size);
|
||||||
|
const remaining = new BigNumber(data.remaining);
|
||||||
|
const fills = size.minus(remaining);
|
||||||
|
return `${addDecimal(fills.toString(), dps)}/${addDecimal(
|
||||||
|
size.toString(),
|
||||||
|
dps
|
||||||
|
)}`;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import produce from 'immer';
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import type { OrderFields } from './__generated__/OrderFields';
|
import type { OrderFields } from './__generated__/OrderFields';
|
||||||
@ -13,6 +14,7 @@ const ORDER_FRAGMENT = gql`
|
|||||||
id
|
id
|
||||||
name
|
name
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
|
positionDecimalPlaces
|
||||||
tradableInstrument {
|
tradableInstrument {
|
||||||
instrument {
|
instrument {
|
||||||
code
|
code
|
||||||
@ -77,19 +79,20 @@ export const prepareIncomingOrders = (delta: OrderFields[]) => {
|
|||||||
return incoming;
|
return incoming;
|
||||||
};
|
};
|
||||||
|
|
||||||
const update = (draft: OrderFields[], delta: OrderFields[]) => {
|
const update = (data: OrderFields[], delta: OrderFields[]) =>
|
||||||
const incoming = prepareIncomingOrders(delta);
|
produce(data, (draft) => {
|
||||||
|
const incoming = prepareIncomingOrders(delta);
|
||||||
|
|
||||||
// Add or update incoming orders
|
// Add or update incoming orders
|
||||||
incoming.forEach((order) => {
|
incoming.forEach((order) => {
|
||||||
const index = draft.findIndex((o) => o.id === order.id);
|
const index = draft.findIndex((o) => o.id === order.id);
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
draft.unshift(order);
|
draft.unshift(order);
|
||||||
} else {
|
} else {
|
||||||
draft[index] = order;
|
draft[index] = order;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const getData = (responseData: Orders): Orders_party_orders[] | null =>
|
const getData = (responseData: Orders): Orders_party_orders[] | null =>
|
||||||
responseData?.party?.orders || null;
|
responseData?.party?.orders || null;
|
||||||
|
@ -136,6 +136,12 @@ export interface PositionDetails_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a tradable instrument.
|
* An instance of or reference to a tradable instrument.
|
||||||
*/
|
*/
|
||||||
|
@ -136,6 +136,12 @@ export interface PositionSubscribe_positions_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a tradable instrument.
|
* An instance of or reference to a tradable instrument.
|
||||||
*/
|
*/
|
||||||
|
@ -136,6 +136,12 @@ export interface Positions_party_positions_market {
|
|||||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
*/
|
*/
|
||||||
decimalPlaces: number;
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
/**
|
/**
|
||||||
* An instance of or reference to a tradable instrument.
|
* An instance of or reference to a tradable instrument.
|
||||||
*/
|
*/
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import produce from 'immer';
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import type {
|
import type {
|
||||||
Positions,
|
Positions,
|
||||||
@ -27,6 +28,7 @@ const POSITIONS_FRAGMENT = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
|
positionDecimalPlaces
|
||||||
tradableInstrument {
|
tradableInstrument {
|
||||||
instrument {
|
instrument {
|
||||||
id
|
id
|
||||||
@ -74,16 +76,17 @@ export const POSITIONS_SUB = gql`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const update = (
|
const update = (
|
||||||
draft: Positions_party_positions[],
|
data: Positions_party_positions[],
|
||||||
delta: PositionSubscribe_positions
|
delta: PositionSubscribe_positions
|
||||||
) => {
|
) =>
|
||||||
const index = draft.findIndex((m) => m.market.id === delta.market.id);
|
produce(data, (draft) => {
|
||||||
if (index !== -1) {
|
const index = draft.findIndex((m) => m.market.id === delta.market.id);
|
||||||
draft[index] = delta;
|
if (index !== -1) {
|
||||||
} else {
|
draft[index] = delta;
|
||||||
draft.push(delta);
|
} else {
|
||||||
}
|
draft.push(delta);
|
||||||
};
|
}
|
||||||
|
});
|
||||||
const getData = (responseData: Positions): Positions_party_positions[] | null =>
|
const getData = (responseData: Positions): Positions_party_positions[] | null =>
|
||||||
responseData.party ? responseData.party.positions : null;
|
responseData.party ? responseData.party.positions : null;
|
||||||
const getDelta = (
|
const getDelta = (
|
||||||
|
@ -5,7 +5,7 @@ import { MarketTradingMode } from '@vegaprotocol/types';
|
|||||||
|
|
||||||
const singleRow: Positions_party_positions = {
|
const singleRow: Positions_party_positions = {
|
||||||
realisedPNL: '520000000',
|
realisedPNL: '520000000',
|
||||||
openVolume: '100',
|
openVolume: '10000',
|
||||||
unrealisedPNL: '895000',
|
unrealisedPNL: '895000',
|
||||||
averageEntryPrice: '1129935',
|
averageEntryPrice: '1129935',
|
||||||
market: {
|
market: {
|
||||||
@ -17,6 +17,7 @@ const singleRow: Positions_party_positions = {
|
|||||||
__typename: 'MarketData',
|
__typename: 'MarketData',
|
||||||
market: { __typename: 'Market', id: '123' },
|
market: { __typename: 'Market', id: '123' },
|
||||||
},
|
},
|
||||||
|
positionDecimalPlaces: 2,
|
||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -90,7 +91,7 @@ it('Correct formatting applied', async () => {
|
|||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
const expectedValues = [
|
const expectedValues = [
|
||||||
singleRow.market.tradableInstrument.instrument.code,
|
singleRow.market.tradableInstrument.instrument.code,
|
||||||
'+100',
|
'+100.00',
|
||||||
'11.29935',
|
'11.29935',
|
||||||
'11.38885',
|
'11.38885',
|
||||||
'+5,200.000',
|
'+5,200.000',
|
||||||
|
@ -88,8 +88,11 @@ export const PositionsTable = forwardRef<AgGridReact, PositionsTableProps>(
|
|||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Amount')}
|
headerName={t('Amount')}
|
||||||
field="openVolume"
|
field="openVolume"
|
||||||
valueFormatter={({ value }: PositionsTableValueFormatterParams) =>
|
valueFormatter={({
|
||||||
volumePrefix(value)
|
value,
|
||||||
|
data,
|
||||||
|
}: PositionsTableValueFormatterParams) =>
|
||||||
|
volumePrefix(addDecimal(value, data.market.positionDecimalPlaces))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
|
@ -1,19 +1,6 @@
|
|||||||
import once from 'lodash/once';
|
import once from 'lodash/once';
|
||||||
import { getUserLocale } from './utils';
|
import { getUserLocale } from './utils';
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a number prefixed with either a '-' or a '+'. The open volume field
|
|
||||||
* already comes with a '-' if negative so we only need to actually prefix if
|
|
||||||
* its a positive value
|
|
||||||
*/
|
|
||||||
export function volumePrefix(value: string): string {
|
|
||||||
if (value === '0' || value.startsWith('-')) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return '+' + value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getTimeFormat = once(
|
export const getTimeFormat = once(
|
||||||
() =>
|
() =>
|
||||||
new Intl.DateTimeFormat(getUserLocale(), {
|
new Intl.DateTimeFormat(getUserLocale(), {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user