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
|
||||
Then transactions page is correctly displayed
|
||||
|
||||
@ignore
|
||||
Scenario: Navigate to transaction details page
|
||||
Given I am on the homepage
|
||||
When I navigate to the transactions page
|
||||
And I click on the top transaction
|
||||
Then transaction details are displayed
|
||||
|
||||
@ignore
|
||||
Scenario: Navigate to transactions page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to the transactions page
|
||||
|
@ -36,7 +36,12 @@ export const JumpTo = ({
|
||||
placeholder={placeholder}
|
||||
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')}
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -75,7 +75,12 @@ export const Search = () => {
|
||||
</InputError>
|
||||
)}
|
||||
</FormGroup>
|
||||
<Button type="submit" variant="secondary" data-testid="search-button">
|
||||
<Button
|
||||
type="submit"
|
||||
boxShadow={false}
|
||||
variant="secondary"
|
||||
data-testid="search-button"
|
||||
>
|
||||
{t('Search')}
|
||||
</Button>
|
||||
</form>
|
||||
|
@ -7,7 +7,6 @@ import { DealTicketSteps } from './deal-ticket-steps';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { DealTicketBalance } from './deal-ticket-balance';
|
||||
import * as React from 'react';
|
||||
import type { PartyBalanceQuery } from './__generated__/PartyBalanceQuery';
|
||||
|
||||
const tempEmptyText = <p>Please select a market from the markets page</p>;
|
||||
|
@ -35,7 +35,7 @@ export const DrawerToggle = ({
|
||||
}, [variant]);
|
||||
|
||||
return (
|
||||
<Button variant="inline" className={classes} onClick={onToggle}>
|
||||
<Button variant="inline-link" className={classes} onClick={onToggle}>
|
||||
<Icon name={iconName as IconName} />
|
||||
</Button>
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import produce from 'immer';
|
||||
import { gql } from '@apollo/client';
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
@ -87,15 +88,16 @@ export const FILTERS_QUERY = gql`
|
||||
`;
|
||||
|
||||
const update = (
|
||||
draft: SimpleMarkets_markets[],
|
||||
data: SimpleMarkets_markets[],
|
||||
delta: SimpleMarketDataSub_marketData
|
||||
) => {
|
||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index].data = delta;
|
||||
}
|
||||
// @TODO - else push new market to draft
|
||||
};
|
||||
) =>
|
||||
produce(data, (draft) => {
|
||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index].data = delta;
|
||||
}
|
||||
// @TODO - else push new market to draft
|
||||
});
|
||||
|
||||
const getData = (responseData: SimpleMarkets) => responseData.markets;
|
||||
const getDelta = (
|
||||
|
@ -101,7 +101,7 @@ const SimpleMarketList = () => {
|
||||
<div className="absolute right-16 top-1/2 -translate-y-1/2">
|
||||
<Button
|
||||
onClick={() => onClick(market.id)}
|
||||
variant="inline"
|
||||
variant="inline-link"
|
||||
prependIconName="chevron-right"
|
||||
/>
|
||||
</div>
|
||||
|
@ -70,7 +70,7 @@ export default ({ steps }: StepperProps) => {
|
||||
{index === steps.length - 1 ? 'Finish' : 'Continue'}
|
||||
</Button>
|
||||
<Button
|
||||
variant="inline"
|
||||
variant="inline-link"
|
||||
disabled={index === 0}
|
||||
onClick={handleBack}
|
||||
>
|
||||
|
@ -38,7 +38,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "125847.249906896297139465",
|
||||
"locked_amount": "124661.013711767544930765",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@ -488,7 +488,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "97499.58",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "66666.63057997215661197",
|
||||
"locked_amount": "65503.04337545080622283",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "97499.58",
|
||||
@ -521,7 +521,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "135173.4239508",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "91121.77448920241599915064844",
|
||||
"locked_amount": "89531.35166557213976323285608",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "135173.4239508",
|
||||
@ -554,7 +554,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "32499.86",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "28045.500213863789588014",
|
||||
"locked_amount": "27555.99917099787937361",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "32499.86",
|
||||
@ -587,7 +587,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "10833.29",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "9128.538172520424723312",
|
||||
"locked_amount": "8969.210333073256934278",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@ -675,7 +675,7 @@
|
||||
"tranche_end": "2022-11-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "16079.77241847825975",
|
||||
"locked_amount": "15468.3027626811615",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "15000",
|
||||
@ -761,7 +761,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1830956.520319353226245706",
|
||||
"locked_amount": "1804379.69836047439128314",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@ -1776,8 +1776,8 @@
|
||||
"tranche_start": "2021-09-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-30T00:00:00.000Z",
|
||||
"total_added": "60916.66666633337",
|
||||
"total_removed": "18323.723696937179372649",
|
||||
"locked_amount": "15541.060867673757124652184217191",
|
||||
"total_removed": "18705.279504739679372649",
|
||||
"locked_amount": "14760.0056484630890178248654459722",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2833.333333",
|
||||
@ -1876,6 +1876,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "381.5558078025",
|
||||
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||
"tx": "0xdf5387ab07596bf2a4a608ea38d3f98f8020941f4fa7ad88f1ccd223669ac2c7"
|
||||
},
|
||||
{
|
||||
"amount": "327.532400005",
|
||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||
@ -2591,6 +2596,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "381.5558078025",
|
||||
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||
"tranche_id": 13,
|
||||
"tx": "0xdf5387ab07596bf2a4a608ea38d3f98f8020941f4fa7ad88f1ccd223669ac2c7"
|
||||
},
|
||||
{
|
||||
"amount": "490.9767850775",
|
||||
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||
@ -2635,8 +2646,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "4250",
|
||||
"withdrawn_tokens": "2838.102475055",
|
||||
"remaining_tokens": "1411.897524945"
|
||||
"withdrawn_tokens": "3219.6582828575",
|
||||
"remaining_tokens": "1030.3417171425"
|
||||
},
|
||||
{
|
||||
"address": "0xDFaF6D0a0102ea5e4688F95Eb22Dc353751a7563",
|
||||
@ -3228,8 +3239,8 @@
|
||||
"tranche_id": 10,
|
||||
"tranche_start": "2021-07-15T23:37:11.000Z",
|
||||
"tranche_end": "2021-07-15T23:37:11.000Z",
|
||||
"total_added": "3653968.150000000000000001",
|
||||
"total_removed": "3645778.640000000000000001",
|
||||
"total_added": "3710968.150000000000000001",
|
||||
"total_removed": "3702778.640000000000000001",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@ -3242,6 +3253,11 @@
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tx": "0x7b0e95e1914579c79eff111dd0df59e767321858e552cbd2a65e5f0ea8c60868"
|
||||
},
|
||||
{
|
||||
"amount": "57000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tx": "0x66d007fc762ef9b7d2c0b57434295d06dfbafb9aeb5884cedc650f5f0c98d68f"
|
||||
},
|
||||
{
|
||||
"amount": "40000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@ -3669,6 +3685,11 @@
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tx": "0xc5ad7140387b5c2eeeae5c158d97a8df0d4c0bbae4a61b3c03c784f11272c89a"
|
||||
},
|
||||
{
|
||||
"amount": "57000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tx": "0x25c796bbfae4d91dca908b1ea7c50f6ea26b38d5350862b154a7963802bc3497"
|
||||
},
|
||||
{
|
||||
"amount": "40000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@ -4041,6 +4062,12 @@
|
||||
"tranche_id": 10,
|
||||
"tx": "0x7b0e95e1914579c79eff111dd0df59e767321858e552cbd2a65e5f0ea8c60868"
|
||||
},
|
||||
{
|
||||
"amount": "57000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tranche_id": 10,
|
||||
"tx": "0x66d007fc762ef9b7d2c0b57434295d06dfbafb9aeb5884cedc650f5f0c98d68f"
|
||||
},
|
||||
{
|
||||
"amount": "40000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@ -4127,6 +4154,12 @@
|
||||
"tranche_id": 10,
|
||||
"tx": "0xc5ad7140387b5c2eeeae5c158d97a8df0d4c0bbae4a61b3c03c784f11272c89a"
|
||||
},
|
||||
{
|
||||
"amount": "57000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tranche_id": 10,
|
||||
"tx": "0x25c796bbfae4d91dca908b1ea7c50f6ea26b38d5350862b154a7963802bc3497"
|
||||
},
|
||||
{
|
||||
"amount": "40000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@ -4194,8 +4227,8 @@
|
||||
"tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc"
|
||||
}
|
||||
],
|
||||
"total_tokens": "507651",
|
||||
"withdrawn_tokens": "507651",
|
||||
"total_tokens": "564651",
|
||||
"withdrawn_tokens": "564651",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
@ -5194,8 +5227,8 @@
|
||||
"tranche_start": "2021-09-03T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-03T00:00:00.000Z",
|
||||
"total_added": "19455.000000000000000003",
|
||||
"total_removed": "5052.45813105178",
|
||||
"locked_amount": "3864.17904680365295175059586415525114155",
|
||||
"total_removed": "5056.88782409978",
|
||||
"locked_amount": "3597.64752092846370375055476445966514475",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "75",
|
||||
@ -8249,6 +8282,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "4.429693048",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
"tx": "0xfbca378f6263977884e6eebc653c8d68f39b6c8eb6ce2f6668767ed63bfcc55b"
|
||||
},
|
||||
{
|
||||
"amount": "8.25227042",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
@ -13997,6 +14035,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "4.429693048",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xfbca378f6263977884e6eebc653c8d68f39b6c8eb6ce2f6668767ed63bfcc55b"
|
||||
},
|
||||
{
|
||||
"amount": "8.25227042",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
@ -14053,8 +14097,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200",
|
||||
"withdrawn_tokens": "157.871905124",
|
||||
"remaining_tokens": "42.128094876"
|
||||
"withdrawn_tokens": "162.301598172",
|
||||
"remaining_tokens": "37.698401828"
|
||||
},
|
||||
{
|
||||
"address": "0x1775cc97E5c05Fde8b571ef75CA52d0A9ff19025",
|
||||
@ -14079,7 +14123,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "74162.9780761646031",
|
||||
"locked_amount": "2838044.0251062046717742172",
|
||||
"locked_amount": "2797204.7028220379638062054",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@ -14791,8 +14835,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15788853.065470999700000001",
|
||||
"total_removed": "5923.782558947259825",
|
||||
"locked_amount": "15284554.9536832239111747473350177541524737",
|
||||
"total_removed": "7926.7627792759659",
|
||||
"locked_amount": "15140482.7365636033722263648641426217383077",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@ -15291,6 +15335,31 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"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",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@ -15383,6 +15452,36 @@
|
||||
"tranche_id": 2,
|
||||
"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",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@ -15427,8 +15526,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "194999.1675",
|
||||
"withdrawn_tokens": "5923.782558947259825",
|
||||
"remaining_tokens": "189075.384941052740175"
|
||||
"withdrawn_tokens": "7926.7627792759659",
|
||||
"remaining_tokens": "187072.4047207240341"
|
||||
},
|
||||
{
|
||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||
@ -16832,8 +16931,8 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "2068423.077146290360122272",
|
||||
"locked_amount": "8461771.6695419306722268828527521",
|
||||
"total_removed": "2113641.840890679071831632",
|
||||
"locked_amount": "8328080.66510881884167481291924447",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@ -17047,6 +17146,41 @@
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"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",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@ -18629,6 +18763,42 @@
|
||||
"tranche_id": 3,
|
||||
"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",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@ -19867,8 +20037,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "359123.469575",
|
||||
"withdrawn_tokens": "150390.162087073825163",
|
||||
"remaining_tokens": "208733.307487926174837"
|
||||
"withdrawn_tokens": "154092.9757912160630365",
|
||||
"remaining_tokens": "205030.4937837839369635"
|
||||
},
|
||||
{
|
||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||
@ -20055,6 +20225,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "41515.95004024647383586",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xd950c34bf5f503998bddc8f9fdeb7cdc4ae1e76c5e9b1564795c306c2e8cad63"
|
||||
},
|
||||
{
|
||||
"amount": "17786.1881146007542887",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
@ -20261,8 +20437,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "1266324.603486",
|
||||
"withdrawn_tokens": "497356.38070819243695426",
|
||||
"remaining_tokens": "768968.22277780756304574"
|
||||
"withdrawn_tokens": "538872.33074843891079012",
|
||||
"remaining_tokens": "727452.27273756108920988"
|
||||
},
|
||||
{
|
||||
"address": "0xC5d9221EB9c28A69859264c0A2Fe0d3272228296",
|
||||
@ -20859,7 +21035,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "1390546.591547348229906227",
|
||||
"locked_amount": "3026393.75946481397995019109643517",
|
||||
"locked_amount": "2973571.63505682836710488797665665",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@ -21981,8 +22157,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "449704.29872935272705903095281584",
|
||||
"total_removed": "34.173053016",
|
||||
"locked_amount": "443233.07466590775804275636428212",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@ -28600,7 +28776,18 @@
|
||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "11.163032724",
|
||||
"user": "0xF5037DDA4A660d67560200f45380FF8364e35540",
|
||||
"tx": "0x0db96c68606a35c59786e3b1ff4f8e939a56af133709dd154718eb03138fe227"
|
||||
},
|
||||
{
|
||||
"amount": "23.010020292",
|
||||
"user": "0xD27929d68ac0E5fd5C919A5eb5968C1D06D3Fb83",
|
||||
"tx": "0x8daf320262d0384cf5f9c290cc33721587beabd5e93026b3e9b76dc3fcd6659c"
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"address": "0xD18ffAa4a1d16f9eD9d3BE4078738Eeda3f160FD",
|
||||
@ -47113,10 +47300,17 @@
|
||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "23.010020292",
|
||||
"user": "0xD27929d68ac0E5fd5C919A5eb5968C1D06D3Fb83",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x8daf320262d0384cf5f9c290cc33721587beabd5e93026b3e9b76dc3fcd6659c"
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "400"
|
||||
"withdrawn_tokens": "23.010020292",
|
||||
"remaining_tokens": "376.989979708"
|
||||
},
|
||||
{
|
||||
"address": "0xF5037DDA4A660d67560200f45380FF8364e35540",
|
||||
@ -47128,10 +47322,17 @@
|
||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "11.163032724",
|
||||
"user": "0xF5037DDA4A660d67560200f45380FF8364e35540",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x0db96c68606a35c59786e3b1ff4f8e939a56af133709dd154718eb03138fe227"
|
||||
}
|
||||
],
|
||||
"total_tokens": "200",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "200"
|
||||
"withdrawn_tokens": "11.163032724",
|
||||
"remaining_tokens": "188.836967276"
|
||||
},
|
||||
{
|
||||
"address": "0x2843a3A61C7a129e432455c02101Cec3fA428E60",
|
||||
@ -47635,7 +47836,7 @@
|
||||
"tranche_start": "2021-12-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-06-05T00:00:00.000Z",
|
||||
"total_added": "171288.42",
|
||||
"total_removed": "29185.5825162206377",
|
||||
"total_removed": "32094.1716569431377",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@ -51870,6 +52071,71 @@
|
||||
"user": "0x7fAA8d1Cb6Ab8A9fC039b66fe844575557389CD4",
|
||||
"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",
|
||||
"user": "0x690Fc36d52eD3f198F0eBDea1557333a1766f786",
|
||||
@ -57843,10 +58109,17 @@
|
||||
"tx": "0x75de6ca47e0da361181d14aceb5d08e572754861465caa67a12b528886d55307"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "249.9",
|
||||
"user": "0xcad0D46627628A8bAF524BF202669e8B9f04250f",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xa403d8af5a940c4abd4aadcc579e279218ae73b9c7fc3d7e4216d6aab5ba70eb"
|
||||
}
|
||||
],
|
||||
"total_tokens": "249.9",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "249.9"
|
||||
"withdrawn_tokens": "249.9",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x783C204FfCC479cec7807C37480A4D4C77FB1F22",
|
||||
@ -58384,6 +58657,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "58.6891407225",
|
||||
"user": "0xDD5730a33719083470e641cF0e4154Dd04D5738d",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x49bd6332008e65069aad8012f76f15f3dae19f664237b02f9152946297db812d"
|
||||
},
|
||||
{
|
||||
"amount": "65.928596865",
|
||||
"user": "0xDD5730a33719083470e641cF0e4154Dd04D5738d",
|
||||
@ -58398,8 +58677,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "191.3108592775",
|
||||
"remaining_tokens": "58.6891407225"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x243e23c83135cA0fed2F9f5dF9068dE644929433",
|
||||
@ -59330,10 +59609,17 @@
|
||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xEc925Fd72B46E2101D20686800343220c12Dedde",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xeaf8173b80d3ea3eb5c440a6edcc4fbf6d8624fa437203b66f6acb72d7462b5e"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x08e9b80fCa090CB3E50d77964dc8777cD828253D",
|
||||
@ -59570,10 +59856,17 @@
|
||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x2b28Fd98804e19cFe8d46f2d729C2A5195339fA4",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xd8c87e89222f0fea8933a403cd39756c6721d1e3d86a0bb7747b428f50c7f790"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x61f908D9ee13a68983e5FECc8D9467232F5E9cB4",
|
||||
@ -59630,10 +59923,17 @@
|
||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xDA83Ff6862ed0579248CEd14422C8B782732233b",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x7eb0ec3a5e3d8792b341881083f9046d550fdf0e92429b53bbdddfe439e83983"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xbC10086CB362caE3071f2e09DF2aEE5265FdA238",
|
||||
@ -59645,10 +59945,17 @@
|
||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xbC10086CB362caE3071f2e09DF2aEE5265FdA238",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x1ea368a1c1f000d36d93627ccda127da12e4beade77d869aab7cadb7edfa354f"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xEe3183EcE9ee7d73Fb7bA7F4eB262A2dE68C42B0",
|
||||
@ -61749,10 +62056,17 @@
|
||||
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x9f6b5A46593b991dC78a0e1907a07517A1F80CC2",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x55b21517cf5fd148e596d9e4b63964ab1df82534fd76b6d9dc9d7cfd00971da0"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x758E9AA35F2feA08aEc1613A0F0d9Ebe4d374152",
|
||||
@ -61804,10 +62118,17 @@
|
||||
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x8FC36B7695965Bc39BCB8a3679529f1825e472aE",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x7072667bf81811acda07177c1ace2edcfe19ce68711fa349ad94c1f8aa3d0b25"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x8186CDe8f7A2f95b50f847e2a3301c28bB61Fa8A",
|
||||
@ -62231,10 +62552,17 @@
|
||||
"tx": "0x9f916cf09e8a3c4ade0ffce5190db464d0a2b1dadba78e1ee7ba5d6e751d6148"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x0941FC05E3DA8d9dD29bCBB15F9FF3A16F342612",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xb3cffc52e62679835e65be5472f80bcfa949f7eb0c4c9948efc3271cca02fdae"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x0a5688ed5b0b804db2ee18767476bb60598EC398",
|
||||
@ -63811,10 +64139,17 @@
|
||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x696971413b8Ae5342277AfeC16591271648B4FfF",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xa55b22bf465927c195b424ad7ea893c1c497da34290d5261be205c760fc11cf5"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xcbEca0abcc675A0F977c4Eb9a45bB4153C0246C3",
|
||||
@ -63848,10 +64183,17 @@
|
||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xC26B3b40DC383d97B69Eedcd4E78a9e4eEb73499",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x2c9f57d5e697c29b67034cea8738939ec13b20b5a7d7fcb995fe83f16b4abf75"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xd866082E19c9E36bcA4fA649d530166303B656f2",
|
||||
@ -64126,10 +64468,17 @@
|
||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xEF5D4Be15019F9b972E54b6B904076617aDAfb1C",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x44d207a93bdb1ef457d5a31207d3ccbda3e9fce6528f3a6c0d04f9153e064a2a"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x660Bc2766867E1E19252ad30A413fe20d08A85c4",
|
||||
@ -64156,10 +64505,17 @@
|
||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "100",
|
||||
"user": "0x4796314cC5bDa80Ee2E8b119004b1fc72Cfb1783",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xbfdbd5e3712968f2726e8dba1f226944cfa637f8738f25c3a5b12a1c6a8e7197"
|
||||
}
|
||||
],
|
||||
"total_tokens": "100",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "100"
|
||||
"withdrawn_tokens": "100",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x351cc2560C870f01B099B106Be22C0073Fce10B2",
|
||||
|
@ -38,7 +38,7 @@
|
||||
"tranche_end": "2022-11-26T13:48:10.000Z",
|
||||
"total_added": "100",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "43.033418949771685",
|
||||
"locked_amount": "41.663429096905125",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "100",
|
||||
@ -242,7 +242,7 @@
|
||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||
"total_added": "1100",
|
||||
"total_removed": "673.04388635",
|
||||
"locked_amount": "336.1295630390665",
|
||||
"locked_amount": "321.05967465753423",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1000",
|
||||
|
@ -69,7 +69,7 @@
|
||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||
"total_added": "1010.000000000000000001",
|
||||
"total_removed": "668.4622323651",
|
||||
"locked_amount": "308.628053335870150000305572330035515",
|
||||
"locked_amount": "294.7911558219177930002918724315068493",
|
||||
"deposits": [
|
||||
{
|
||||
"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
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
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
|
||||
|
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
|
||||
NX_VEGA_ENV=TESTNET
|
||||
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:
|
||||
|
||||
| **Flag** | **Purpose** |
|
||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------- |
|
||||
| `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_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_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_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_CUSTOM_URLS` | When NX_APP_ENV=CUSTOM use these Data Node REST URLs, optional if CUSTOM_URLS_WITH_GRAPHQL is used. |
|
||||
| `NX_CUSTOM_URLS_WITH_GRAPHQL` | When NX_APP_ENV=CUSTOM use these Data Node GraphQL URLs, optional if CUSTOM_URLS is used. |
|
||||
| `NX_CUSTOM_TOKEN_ADDRESS` | When NX_APP_ENV=CUSTOM specify Vega token address. |
|
||||
| `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. |
|
||||
| **Flag** | **Purpose** |
|
||||
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `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_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_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_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_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_ETH_WALLET_MNEMONIC` (optional) | The mnemonic to be used to sign transactions with in browser |
|
||||
| `NX_LOCAL_PROVIDER_URL` (optional) | The local node to use to send transaction to when signing in browser |
|
||||
|
||||
## Example configs:
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { useWeb3React } from '@web3-react/core';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getButtonClasses, Button } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import {
|
||||
AppStateActionType,
|
||||
@ -70,7 +71,7 @@ const AssociatedAmounts = ({
|
||||
rightLabel={t('notAssociated')}
|
||||
leftColor={Colors.white.DEFAULT}
|
||||
rightColor={Colors.black.DEFAULT}
|
||||
light={true}
|
||||
light={false}
|
||||
/>
|
||||
{vestingAssociationByVegaKey.length ? (
|
||||
<>
|
||||
@ -129,6 +130,7 @@ const ConnectedKey = () => {
|
||||
name="VEGA"
|
||||
symbol="In vesting contract"
|
||||
balance={totalInVestingContract}
|
||||
dark={true}
|
||||
/>
|
||||
<LockedProgress
|
||||
locked={totalLockedBalance}
|
||||
@ -136,7 +138,7 @@ const ConnectedKey = () => {
|
||||
total={totalVestedBalance.plus(totalLockedBalance)}
|
||||
leftLabel={t('Locked')}
|
||||
rightLabel={t('Unlocked')}
|
||||
light={true}
|
||||
light={false}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -153,6 +155,7 @@ const ConnectedKey = () => {
|
||||
name="VEGA"
|
||||
symbol="In Wallet"
|
||||
balance={walletWithAssociations}
|
||||
dark={true}
|
||||
/>
|
||||
{!Object.keys(
|
||||
appState.associationBreakdown.stakingAssociations
|
||||
@ -163,15 +166,17 @@ const ConnectedKey = () => {
|
||||
/>
|
||||
)}
|
||||
<WalletCardActions>
|
||||
<Link className="flex-1" to={`${Routes.STAKING}/associate`}>
|
||||
<span className="flex items-center justify-center w-full text-center px-28 border h-28">
|
||||
{t('associate')}
|
||||
</span>
|
||||
<Link
|
||||
className={getButtonClasses('flex-1 mr-4', 'secondary')}
|
||||
to={`${Routes.STAKING}/associate`}
|
||||
>
|
||||
{t('associate')}
|
||||
</Link>
|
||||
<Link className="flex-1" to={`${Routes.STAKING}/disassociate`}>
|
||||
<span className="flex items-center justify-center w-full px-28 border h-28">
|
||||
{t('disassociate')}
|
||||
</span>
|
||||
<Link
|
||||
className={getButtonClasses('flex-1 ml-4', 'secondary')}
|
||||
to={`${Routes.STAKING}/disassociate`}
|
||||
>
|
||||
{t('disassociate')}
|
||||
</Link>
|
||||
</WalletCardActions>
|
||||
</>
|
||||
@ -185,7 +190,7 @@ export const EthWallet = () => {
|
||||
const pendingTxs = usePendingTransactions();
|
||||
|
||||
return (
|
||||
<WalletCard>
|
||||
<WalletCard dark={true}>
|
||||
<WalletCardHeader>
|
||||
<h1 className="text-h3 uppercase">{t('ethereumKey')}</h1>
|
||||
{account && (
|
||||
@ -203,7 +208,7 @@ export const EthWallet = () => {
|
||||
})
|
||||
}
|
||||
>
|
||||
<Loader size="small" forceTheme="light" />
|
||||
<Loader size="small" forceTheme="dark" />
|
||||
{t('pendingTransactions')}
|
||||
</button>
|
||||
</div>
|
||||
@ -215,7 +220,8 @@ export const EthWallet = () => {
|
||||
{account ? (
|
||||
<ConnectedKey />
|
||||
) : (
|
||||
<button
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
className="w-full px-28 border h-28"
|
||||
onClick={() =>
|
||||
appDispatch({
|
||||
@ -226,7 +232,7 @@ export const EthWallet = () => {
|
||||
data-test-id="connect-to-eth-wallet-button"
|
||||
>
|
||||
{t('connectEthWalletToAssociate')}
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
{account && (
|
||||
<WalletCardActions>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
|
||||
import { formatNumber } from '../../lib/format-number';
|
||||
import type { BigNumber } from '../../lib/bignumber';
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const Colors = theme.colors;
|
||||
|
||||
@ -14,9 +14,10 @@ const ProgressContents = ({
|
||||
children: React.ReactNode;
|
||||
}) => (
|
||||
<div
|
||||
className={`flex justify-between py-2 font-mono ${
|
||||
light ? 'gap-0 px-0 text-black' : 'gap-y-0 gap-x-4 px-4'
|
||||
}`}
|
||||
className={classnames('flex justify-between py-2 font-mono', {
|
||||
'gap-0 px-0 text-black': light,
|
||||
'gap-y-0 gap-x-4': !light,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
@ -25,17 +26,22 @@ const ProgressContents = ({
|
||||
const ProgressIndicator = ({
|
||||
bgColor,
|
||||
side,
|
||||
light,
|
||||
}: {
|
||||
bgColor: string;
|
||||
side: 'left' | 'right';
|
||||
light: boolean;
|
||||
}) => (
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: bgColor,
|
||||
}}
|
||||
className={`inline-block w-12 h-12 border border-black ${
|
||||
side === 'left' ? 'mr-8' : 'ml-8'
|
||||
}`}
|
||||
className={classnames('inline-block w-12 h-12 border', {
|
||||
'mr-8': side === 'left',
|
||||
'ml-8': side === 'right',
|
||||
'border-black': light,
|
||||
'border-white': !light,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -64,6 +70,7 @@ export interface LockedProgressProps {
|
||||
leftColor?: string;
|
||||
rightColor?: string;
|
||||
light?: boolean;
|
||||
decimals?: number;
|
||||
}
|
||||
|
||||
export const LockedProgress = ({
|
||||
@ -73,8 +80,9 @@ export const LockedProgress = ({
|
||||
leftLabel,
|
||||
rightLabel,
|
||||
leftColor = Colors.vega.pink,
|
||||
rightColor = Colors.green.DEFAULT,
|
||||
rightColor = Colors.vega.green,
|
||||
light = false,
|
||||
decimals = 2,
|
||||
}: LockedProgressProps) => {
|
||||
const lockedPercentage = React.useMemo(() => {
|
||||
return locked.div(total).times(100);
|
||||
@ -85,26 +93,35 @@ export const LockedProgress = ({
|
||||
}, [total, unlocked]);
|
||||
|
||||
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={unlockedPercentage} bgColor={rightColor} />
|
||||
</div>
|
||||
<ProgressContents light={light}>
|
||||
<span>
|
||||
<ProgressIndicator bgColor={leftColor} side={'left'} />
|
||||
<ProgressIndicator bgColor={leftColor} side={'left'} light={false} />
|
||||
{leftLabel}
|
||||
</span>
|
||||
<span>
|
||||
{rightLabel}
|
||||
<ProgressIndicator bgColor={rightColor} side={'right'} />
|
||||
<ProgressIndicator
|
||||
bgColor={rightColor}
|
||||
side={'right'}
|
||||
light={false}
|
||||
/>
|
||||
</span>
|
||||
</ProgressContents>
|
||||
|
||||
<ProgressContents light={light}>
|
||||
<span>{formatNumber(locked, 2)}</span>
|
||||
<span>{formatNumber(unlocked, 2)}</span>
|
||||
<span>{formatNumber(locked, decimals)}</span>
|
||||
<span>{formatNumber(unlocked, decimals)}</span>
|
||||
</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]">
|
||||
<Nav />
|
||||
<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) => (
|
||||
<section className="mb-20 last:mb-0" key={i}>
|
||||
{Component}
|
||||
|
@ -180,15 +180,15 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
||||
</div>
|
||||
))}
|
||||
<WalletCardActions>
|
||||
<Link style={{ flex: 1 }} to={Routes.GOVERNANCE}>
|
||||
<span className="flex items-center justify-center w-full px-28 border h-28 bg-white text-black">
|
||||
<Link className="flex-1 pr-8" to={Routes.GOVERNANCE}>
|
||||
<Button variant={'secondary'} className="w-full">
|
||||
{t('governance')}
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
<Link style={{ flex: 1 }} to={Routes.STAKING}>
|
||||
<span className="flex items-center justify-center w-full px-28 border h-28 bg-white text-black">
|
||||
<Link className="flex-1 pl-8" to={Routes.STAKING}>
|
||||
<Button variant={'secondary'} className="w-full">
|
||||
{t('staking')}
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
</WalletCardActions>
|
||||
<VegaWalletAssetList accounts={accounts} />
|
||||
|
@ -55,6 +55,9 @@ export const ENV = {
|
||||
commit: windowOrDefault('NX_COMMIT_REF'),
|
||||
branch: windowOrDefault('NX_BRANCH'),
|
||||
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: {
|
||||
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
|
||||
HOSTED_WALLET_ENABLED: TRUTHY.includes(
|
||||
|
@ -1,10 +1,8 @@
|
||||
import React from 'react';
|
||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||
import mock from './tranches-mock';
|
||||
import type { Tranche } from '@vegaprotocol/smart-contracts';
|
||||
|
||||
export function useTranches() {
|
||||
const { vesting } = useContracts();
|
||||
const [tranches, setTranches] = React.useState<Tranche[] | null>(null);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
|
||||
@ -17,7 +15,7 @@ export function useTranches() {
|
||||
}
|
||||
};
|
||||
run();
|
||||
}, [vesting]);
|
||||
}, []);
|
||||
|
||||
return { tranches, error };
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
@ -7,23 +8,26 @@ import {
|
||||
import { useContracts } from '../contexts/contracts/contracts-context';
|
||||
|
||||
export function useRefreshAssociatedBalances() {
|
||||
const { appDispatch } = useAppState();
|
||||
const {
|
||||
appDispatch,
|
||||
appState: { decimals },
|
||||
} = useAppState();
|
||||
const { staking, vesting } = useContracts();
|
||||
|
||||
return React.useCallback(
|
||||
async (ethAddress: string, vegaKey: string) => {
|
||||
const [walletAssociatedBalance, vestingAssociatedBalance] =
|
||||
await Promise.all([
|
||||
staking.stakeBalance(ethAddress, `0x${vegaKey}`),
|
||||
vesting.stakeBalance(ethAddress, `0x${vegaKey}`),
|
||||
staking.stakeBalance(ethAddress, vegaKey),
|
||||
vesting.stakeBalance(ethAddress, vegaKey),
|
||||
]);
|
||||
|
||||
appDispatch({
|
||||
type: AppStateActionType.REFRESH_ASSOCIATED_BALANCES,
|
||||
walletAssociatedBalance,
|
||||
vestingAssociatedBalance,
|
||||
walletAssociatedBalance: toBigNum(walletAssociatedBalance, decimals),
|
||||
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",
|
||||
"youVoted": "You voted",
|
||||
"changeVote": "Change vote",
|
||||
"voteRequested": "Please confirm transaction in wallet",
|
||||
"votePending": "Casting vote",
|
||||
"voteError": "Something went wrong, and your vote was not seen by the network",
|
||||
"back": "back",
|
||||
@ -280,6 +281,7 @@
|
||||
"stakingHasAssociated": "You have {{tokens}} $VEGA tokens associated.",
|
||||
"stakingAssociateMoreButton": "Associate more $VEGA tokens with wallet",
|
||||
"stakingDisassociateButton": "Disassociate $VEGA tokens from wallet",
|
||||
"stakingConfirm": "Open you wallet app to confirm",
|
||||
"associateButton": "Associate $VEGA tokens with wallet",
|
||||
"nodeQueryFailed": "Could not get data for validator {{node}}",
|
||||
"stakeAddPendingTitle": "Adding {{amount}} $VEGA to validator {{node}}",
|
||||
@ -540,5 +542,8 @@
|
||||
"numberOfAgainstVotes": "Number of votes against",
|
||||
"yesPercentage": "Yes percentage",
|
||||
"noPercentage": "No percentage",
|
||||
"proposalTerms": "Proposal terms"
|
||||
"proposalTerms": "Proposal terms",
|
||||
"currentlySetTo": "Currently set to ",
|
||||
"pass": "Pass",
|
||||
"fail": "Fail"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="bg-black w-full h-full">
|
||||
<html lang="en" class="dark bg-black w-full h-full">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<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 { MetaMask } from '@web3-react/metamask';
|
||||
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>(
|
||||
(actions) => new MetaMask(actions)
|
||||
);
|
||||
|
||||
const [urlConnector, urlHooks] = initializeConnector<Url>(
|
||||
(actions) => new Url(actions, ENV.localProviderUrl)
|
||||
);
|
||||
|
||||
export const createDefaultProvider = (providerUrl: string, chainId: number) => {
|
||||
return new ethers.providers.JsonRpcProvider(providerUrl, chainId);
|
||||
};
|
||||
@ -27,7 +34,8 @@ export const createConnectors = (providerUrl: string, chainId: number) => {
|
||||
[chainId]
|
||||
);
|
||||
return [
|
||||
ENV.urlConnect ? [urlConnector, urlHooks] : null,
|
||||
[metamask, metamaskHooks],
|
||||
[walletconnect, walletconnectHooks],
|
||||
] as [MetaMask | WalletConnect, Web3ReactHooks][];
|
||||
].filter(Boolean) as [Connector, Web3ReactHooks][];
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ export const TargetAddressMismatch = ({
|
||||
}}
|
||||
components={{
|
||||
bold: <strong />,
|
||||
red: <span className={'text-red'} />,
|
||||
red: <span className={'text-vega-red'} />,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
|
@ -43,7 +43,7 @@ const Contracts = () => {
|
||||
title={t('View address on Etherscan')}
|
||||
href={`${ETHERSCAN_URL}/address/${contract.address}`}
|
||||
>
|
||||
{config.collateral_bridge_contract.address}
|
||||
{contract.address}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
@ -58,7 +58,6 @@ const Contracts = () => {
|
||||
title={t('View address on Etherscan')}
|
||||
href={`${ETHERSCAN_URL}/address/${value}`}
|
||||
>
|
||||
asdfasd
|
||||
{value}
|
||||
</Link>
|
||||
</div>
|
||||
|
@ -34,30 +34,22 @@ export const CurrentProposalStatus = ({
|
||||
{ addSuffix: true }
|
||||
);
|
||||
|
||||
if (proposal.state === ProposalState.Open && willPass) {
|
||||
return <StatusPass>{t('shouldPass')}</StatusPass>;
|
||||
}
|
||||
|
||||
if (!participationMet) {
|
||||
return (
|
||||
<>
|
||||
<span>{t('voteFailedReason')}</span>
|
||||
<span className="current-proposal-status__fail">
|
||||
{t('participationNotMet')}
|
||||
</span>
|
||||
<span> {daysClosedAgo}.</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (!majorityMet) {
|
||||
return (
|
||||
<>
|
||||
<span>{t('voteFailedReason')}</span>
|
||||
<StatusFail>{t('majorityNotMet')}</StatusFail>
|
||||
<span> {daysClosedAgo}.</span>
|
||||
</>
|
||||
);
|
||||
if (proposal.state === ProposalState.Open) {
|
||||
if (willPass) {
|
||||
return (
|
||||
<>
|
||||
{t('currentlySetTo')}
|
||||
<StatusPass>{t('pass')}</StatusPass>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
{t('currentlySetTo')}
|
||||
<StatusFail>{t('fail')}</StatusFail>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
@ -65,6 +57,26 @@ export const CurrentProposalStatus = ({
|
||||
proposal.state === ProposalState.Declined ||
|
||||
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 (
|
||||
<>
|
||||
<span>{t('voteFailedReason')}</span>
|
||||
|
@ -17,6 +17,7 @@ export enum VoteState {
|
||||
NotCast = 'NotCast',
|
||||
Yes = 'Yes',
|
||||
No = 'No',
|
||||
Requested = 'Requested',
|
||||
Pending = 'Pending',
|
||||
Failed = 'Failed',
|
||||
}
|
||||
@ -69,7 +70,7 @@ export function useUserVote(
|
||||
}
|
||||
}, [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
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line
|
||||
@ -93,7 +94,7 @@ export function useUserVote(
|
||||
async function castVote(value: VoteValue) {
|
||||
if (!proposalId || !keypair) return;
|
||||
|
||||
setVoteState(VoteState.Pending);
|
||||
setVoteState(VoteState.Requested);
|
||||
|
||||
try {
|
||||
const variables = {
|
||||
@ -105,6 +106,7 @@ export function useUserVote(
|
||||
},
|
||||
};
|
||||
await sendTx(variables);
|
||||
setVoteState(VoteState.Pending);
|
||||
|
||||
// Now await vote via poll in parent component
|
||||
} catch (err) {
|
||||
|
@ -124,6 +124,10 @@ export const VoteButtons = ({
|
||||
return <p>{cantVoteUI}</p>;
|
||||
}
|
||||
|
||||
if (voteState === VoteState.Requested) {
|
||||
return <p>{t('voteRequested')}...</p>;
|
||||
}
|
||||
|
||||
if (voteState === VoteState.Pending) {
|
||||
return <p>{t('votePending')}...</p>;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ export const VoteDetails = ({ proposal }: VoteDetailsProps) => {
|
||||
<span>
|
||||
<CurrentProposalStatus proposal={proposal} />
|
||||
</span>
|
||||
.
|
||||
{'. '}
|
||||
{proposal.state === ProposalState.Open ? daysLeft : null}
|
||||
</p>
|
||||
<table className="w-full font-normal mb-12">
|
||||
|
@ -24,6 +24,7 @@ export const ProposalsContainer = () => {
|
||||
const { t } = useTranslation();
|
||||
const { data, loading, error } = useQuery<Proposals, never>(PROPOSALS_QUERY, {
|
||||
pollInterval: 5000,
|
||||
errorPolicy: 'ignore', // this is to get around some backend issues and should be removed in future
|
||||
});
|
||||
|
||||
const proposals = React.useMemo(() => {
|
||||
|
@ -52,7 +52,13 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
<Trans
|
||||
i18nKey="Tokens are held in different <trancheLink>Tranches</trancheLink>. Each tranche has its own schedule for how the tokens are unlocked."
|
||||
components={{
|
||||
trancheLink: <Link to={Routes.TRANCHES} />,
|
||||
trancheLink: (
|
||||
<Link
|
||||
data-testid="tranches-link"
|
||||
to={Routes.TRANCHES}
|
||||
className="underline text-white"
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
@ -62,7 +68,7 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
)}
|
||||
</p>
|
||||
<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')}
|
||||
</Button>
|
||||
</Link>
|
||||
@ -81,7 +87,7 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
data-test-id="get-vega-wallet-link"
|
||||
data-testid="get-vega-wallet-link"
|
||||
href={Links.WALLET_GUIDE}
|
||||
className="underline text-white"
|
||||
target="_blank"
|
||||
@ -90,8 +96,9 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
{t('Get a Vega wallet')}
|
||||
</a>
|
||||
</p>
|
||||
<p data-test-id="associate-vega-tokens-link-on-homepage">
|
||||
<p>
|
||||
<Link
|
||||
data-testid="associate-vega-tokens-link-on-homepage"
|
||||
to={`${Routes.STAKING}/associate`}
|
||||
className="underline text-white"
|
||||
>
|
||||
@ -110,7 +117,12 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
</p>
|
||||
<p>
|
||||
<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>
|
||||
</p>
|
||||
</HomeSection>
|
||||
@ -125,7 +137,10 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
</p>
|
||||
<p>
|
||||
<Link to={Routes.GOVERNANCE}>
|
||||
<Button variant="secondary">
|
||||
<Button
|
||||
variant="secondary"
|
||||
data-testid="governance-button-on-homepage"
|
||||
>
|
||||
{t('View Governance proposals')}
|
||||
</Button>
|
||||
</Link>
|
||||
|
@ -8,7 +8,6 @@ import { Link } from 'react-router-dom';
|
||||
import { EthConnectPrompt } from '../../components/eth-connect-prompt';
|
||||
import { SplashLoader } from '../../components/splash-loader';
|
||||
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||
import { useTranches } from '../../hooks/use-tranches';
|
||||
import { Routes as RoutesConfig } from '../router-config';
|
||||
import {
|
||||
@ -19,7 +18,6 @@ import {
|
||||
|
||||
const RedemptionRouter = () => {
|
||||
const { t } = useTranslation();
|
||||
const { vesting } = useContracts();
|
||||
const [state, dispatch] = React.useReducer(
|
||||
redemptionReducer,
|
||||
initialRedemptionState
|
||||
@ -49,7 +47,7 @@ const RedemptionRouter = () => {
|
||||
if (account) {
|
||||
run(account);
|
||||
}
|
||||
}, [account, tranches, vesting]);
|
||||
}, [account, tranches]);
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
|
@ -76,6 +76,7 @@ export const TrancheItem = ({
|
||||
total={total}
|
||||
leftLabel={t('Locked')}
|
||||
rightLabel={t('Unlocked')}
|
||||
decimals={18}
|
||||
/>
|
||||
|
||||
<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 { AssociateInfo } from './associate-info';
|
||||
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';
|
||||
|
||||
export const WalletAssociate = ({
|
||||
@ -35,19 +35,18 @@ export const WalletAssociate = ({
|
||||
appDispatch,
|
||||
appState: { walletBalance, allowance, walletAssociatedBalance, decimals },
|
||||
} = useAppState();
|
||||
|
||||
const { token } = useContracts();
|
||||
|
||||
const {
|
||||
state: approveState,
|
||||
perform: approve,
|
||||
dispatch: approveDispatch,
|
||||
} = useTransaction(() =>
|
||||
token.approve(
|
||||
} = useTransaction(() => {
|
||||
return token.approve(
|
||||
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
|
||||
React.useEffect(() => {
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
} from '../../../components/staking-method-radio';
|
||||
import { TxState } from '../../../hooks/transaction-reducer';
|
||||
import { useSearchParams } from '../../../hooks/use-search-params';
|
||||
import { useRefreshAssociatedBalances } from '../../../hooks/use-refresh-associated-balances';
|
||||
import { ContractDisassociate } from './contract-disassociate';
|
||||
import { DisassociateTransaction } from './disassociate-transaction';
|
||||
import { useRemoveStake } from './hooks';
|
||||
@ -26,6 +27,7 @@ export const DisassociatePage = ({
|
||||
const [amount, setAmount] = React.useState<string>('');
|
||||
const [selectedStakingMethod, setSelectedStakingMethod] =
|
||||
React.useState<StakingMethod | null>(params.method || null);
|
||||
const refreshBalances = useRefreshAssociatedBalances();
|
||||
|
||||
// Clear the amount when the staking method changes
|
||||
React.useEffect(() => {
|
||||
@ -38,6 +40,12 @@ export const DisassociatePage = ({
|
||||
perform: txPerform,
|
||||
} = 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) {
|
||||
return (
|
||||
<DisassociateTransaction
|
||||
|
@ -18,7 +18,14 @@ import type {
|
||||
import { StakeFailure } from './stake-failure';
|
||||
import { StakePending } from './stake-pending';
|
||||
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 type {
|
||||
DelegateSubmissionBody,
|
||||
@ -46,6 +53,7 @@ export const PARTY_DELEGATIONS_QUERY = gql`
|
||||
|
||||
enum FormState {
|
||||
Default,
|
||||
Requested,
|
||||
Pending,
|
||||
Success,
|
||||
Failure,
|
||||
@ -115,7 +123,7 @@ export const StakingForm = ({
|
||||
}, [action, availableStakeToAdd, availableStakeToRemove]);
|
||||
|
||||
async function onSubmit() {
|
||||
setFormState(FormState.Pending);
|
||||
setFormState(FormState.Requested);
|
||||
const delegateInput: DelegateSubmissionBody = {
|
||||
pubKey: pubkey,
|
||||
propagate: true,
|
||||
@ -139,6 +147,7 @@ export const StakingForm = ({
|
||||
try {
|
||||
const command = action === Actions.Add ? delegateInput : undelegateInput;
|
||||
await sendTx(command);
|
||||
setFormState(FormState.Pending);
|
||||
|
||||
// await success via poll
|
||||
} catch (err) {
|
||||
@ -184,6 +193,12 @@ export const StakingForm = ({
|
||||
|
||||
if (formState === FormState.Failure) {
|
||||
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) {
|
||||
return <StakePending action={action} amount={amount} nodeName={nodeName} />;
|
||||
} else if (formState === FormState.Success) {
|
||||
|
@ -88,7 +88,9 @@ export const StakingNode = ({ vegaKey, data }: StakingNodeProps) => {
|
||||
|
||||
if (!nodeInfo) {
|
||||
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>
|
||||
<ProgressBar
|
||||
width={220}
|
||||
color={Colors.green.DEFAULT}
|
||||
color={Colors.vega.green}
|
||||
percentage={removedPercentage}
|
||||
/>
|
||||
<span className="tranches__progress-numbers">
|
||||
|
@ -36,7 +36,7 @@ export const VestingChart = () => {
|
||||
['pink', Colors.vega.pink],
|
||||
['green', Colors.vega.green],
|
||||
['orange', Colors.orange],
|
||||
['yellow', Colors.yellow.DEFAULT],
|
||||
['yellow', Colors.vega.yellow],
|
||||
].map(([key, color]) => (
|
||||
<linearGradient key={key} id={key} x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stopColor={color} stopOpacity={0.85} />
|
||||
@ -119,7 +119,7 @@ export const VestingChart = () => {
|
||||
dot={false}
|
||||
type="monotone"
|
||||
dataKey="publicSale"
|
||||
stroke={Colors.yellow.DEFAULT}
|
||||
stroke={Colors.vega.yellow}
|
||||
fill="url(#yellow)"
|
||||
yAxisId={0}
|
||||
strokeWidth={2}
|
||||
|
@ -19,12 +19,14 @@ describe('orders', () => {
|
||||
const orderTimeInForce = 'timeInForce';
|
||||
const orderCreatedAt = 'createdAt';
|
||||
|
||||
it('renders orders', () => {
|
||||
beforeEach(() => {
|
||||
cy.getByTestId('Orders').click();
|
||||
cy.getByTestId('tab-orders').contains('Please connect Vega wallet');
|
||||
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
it('renders orders', () => {
|
||||
cy.getByTestId('tab-orders').should('be.visible');
|
||||
|
||||
cy.getByTestId('tab-orders')
|
||||
@ -68,4 +70,17 @@ describe('orders', () => {
|
||||
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,
|
||||
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: {
|
||||
@ -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: {
|
||||
__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 = {
|
||||
id: 'b2426f67b085ba8fb429f1b529d49372b2d096c6fb6f509f76c5863abb6d969e',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
data: {
|
||||
staticMidPrice: '826337',
|
||||
marketTradingMode: MarketTradingMode.Continuous,
|
||||
|
@ -18,6 +18,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
@ -33,7 +34,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
remaining: '0',
|
||||
price: '20000000',
|
||||
timeInForce: OrderTimeInForce.GTC,
|
||||
createdAt: new Date().toISOString(),
|
||||
createdAt: new Date(2020, 1, 1).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
@ -46,6 +47,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
@ -59,13 +61,42 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
status: OrderStatus.Filled,
|
||||
side: Side.Buy,
|
||||
remaining: '0',
|
||||
price: '0',
|
||||
price: '100',
|
||||
timeInForce: OrderTimeInForce.GTC,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: 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 = {
|
||||
|
@ -25,6 +25,7 @@ export const generatePositions = (
|
||||
market: { __typename: 'Market', id: '123' },
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: '',
|
||||
@ -78,6 +79,7 @@ export const generatePositions = (
|
||||
},
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: '',
|
||||
|
@ -12,6 +12,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
@ -24,6 +25,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
@ -36,6 +38,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
|
@ -6,6 +6,7 @@ import { generateCandles } from './mocks/generate-candles';
|
||||
import { generateChart } from './mocks/generate-chart';
|
||||
import { generateDealTicketQuery } from './mocks/generate-deal-ticket-query';
|
||||
import { generateMarket } from './mocks/generate-market';
|
||||
import { generateMarketInfoQuery } from './mocks/generate-market-info-query';
|
||||
import { generateOrders } from './mocks/generate-orders';
|
||||
import { generatePositions } from './mocks/generate-positions';
|
||||
import { generateTrades } from './mocks/generate-trades';
|
||||
@ -31,6 +32,11 @@ export const mockTradingPage = (
|
||||
'DealTicketQuery',
|
||||
generateDealTicketQuery({ market: { state } })
|
||||
);
|
||||
aliasQuery(
|
||||
req,
|
||||
'MarketInfoQuery',
|
||||
generateMarketInfoQuery({ market: { state } })
|
||||
);
|
||||
aliasQuery(req, 'Trades', generateTrades());
|
||||
aliasQuery(req, 'Chart', generateChart());
|
||||
aliasQuery(req, 'Candles', generateCandles());
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { useRouter } from 'next/router';
|
||||
import { Vega } from '../icons/vega';
|
||||
import Link from 'next/link';
|
||||
import { AnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export const Navbar = () => {
|
||||
return (
|
||||
@ -33,14 +33,17 @@ const NavLink = ({ name, path, exact, testId = name }: NavLinkProps) => {
|
||||
const router = useRouter();
|
||||
const isActive =
|
||||
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 (
|
||||
<AnchorButton
|
||||
variant={isActive ? 'accent' : 'inline'}
|
||||
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"
|
||||
data-testid={testId}
|
||||
href={path}
|
||||
>
|
||||
{name}
|
||||
</AnchorButton>
|
||||
<Link data-testid={testId} href={path} passHref={true}>
|
||||
<a className={linkClasses}>{name}</a>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
@ -24,84 +24,80 @@ function AppBody({ Component, pageProps }: AppProps) {
|
||||
const { push } = useRouter();
|
||||
const store = useGlobalStore();
|
||||
const { VEGA_NETWORKS } = useEnvironment();
|
||||
const [, toggleTheme] = useThemeSwitcher();
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
|
||||
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]">
|
||||
<AppLoader>
|
||||
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
|
||||
<Navbar />
|
||||
<div className="flex items-center gap-4 ml-auto mr-8">
|
||||
<VegaWalletConnectButton
|
||||
setConnectDialog={(open) => {
|
||||
store.setVegaWalletConnectDialog(open);
|
||||
}}
|
||||
setManageDialog={(open) => {
|
||||
store.setVegaWalletManageDialog(open);
|
||||
}}
|
||||
/>
|
||||
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<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]">
|
||||
<AppLoader>
|
||||
<div className="flex items-stretch border-b-[7px] border-vega-pink dark:border-vega-yellow">
|
||||
<Navbar />
|
||||
<div className="flex items-center gap-4 ml-auto mr-8">
|
||||
<VegaWalletConnectButton
|
||||
setConnectDialog={(open) => {
|
||||
store.setVegaWalletConnectDialog(open);
|
||||
}}
|
||||
setManageDialog={(open) => {
|
||||
store.setVegaWalletManageDialog(open);
|
||||
}}
|
||||
/>
|
||||
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<main data-testid={pageProps.page}>
|
||||
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
|
||||
<Component {...pageProps} />
|
||||
</main>
|
||||
<VegaConnectDialog
|
||||
connectors={Connectors}
|
||||
dialogOpen={store.vegaWalletConnectDialog}
|
||||
setDialogOpen={(open) => store.setVegaWalletConnectDialog(open)}
|
||||
/>
|
||||
<VegaManageDialog
|
||||
dialogOpen={store.vegaWalletManageDialog}
|
||||
setDialogOpen={(open) => store.setVegaWalletManageDialog(open)}
|
||||
/>
|
||||
<NetworkSwitcherDialog
|
||||
dialogOpen={store.vegaNetworkSwitcherDialog}
|
||||
setDialogOpen={(open) => store.setVegaNetworkSwitcherDialog(open)}
|
||||
onConnect={({ network }) => {
|
||||
if (VEGA_NETWORKS[network]) {
|
||||
push(VEGA_NETWORKS[network] ?? '');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</AppLoader>
|
||||
</div>
|
||||
<main data-testid={pageProps.page}>
|
||||
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
|
||||
<Component {...pageProps} />
|
||||
</main>
|
||||
<VegaConnectDialog
|
||||
connectors={Connectors}
|
||||
dialogOpen={store.vegaWalletConnectDialog}
|
||||
setDialogOpen={(open) => store.setVegaWalletConnectDialog(open)}
|
||||
/>
|
||||
<VegaManageDialog
|
||||
dialogOpen={store.vegaWalletManageDialog}
|
||||
setDialogOpen={(open) => store.setVegaWalletManageDialog(open)}
|
||||
/>
|
||||
<NetworkSwitcherDialog
|
||||
dialogOpen={store.vegaNetworkSwitcherDialog}
|
||||
setDialogOpen={(open) => store.setVegaNetworkSwitcherDialog(open)}
|
||||
onConnect={({ network }) => {
|
||||
if (VEGA_NETWORKS[network]) {
|
||||
push(VEGA_NETWORKS[network] ?? '');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</AppLoader>
|
||||
</div>
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function VegaTradingApp(props: AppProps) {
|
||||
const [theme] = useThemeSwitcher();
|
||||
|
||||
return (
|
||||
<EnvironmentProvider>
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<VegaWalletProvider>
|
||||
<Head>
|
||||
<link
|
||||
rel="preload"
|
||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<title>{t('Welcome to Vega trading!')}</title>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/x-icon"
|
||||
href="https://static.vega.xyz/favicon.ico"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
||||
{['1', 'true'].includes(
|
||||
process.env['NX_USE_ENV_OVERRIDES'] || ''
|
||||
) ? (
|
||||
/* eslint-disable-next-line @next/next/no-sync-scripts */
|
||||
<script src="./env-config.js" type="text/javascript" />
|
||||
) : null}
|
||||
</Head>
|
||||
<AppBody {...props} />
|
||||
</VegaWalletProvider>
|
||||
</ThemeContext.Provider>
|
||||
<VegaWalletProvider>
|
||||
<Head>
|
||||
<link
|
||||
rel="preload"
|
||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<title>{t('Welcome to Vega trading!')}</title>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/x-icon"
|
||||
href="https://static.vega.xyz/favicon.ico"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
||||
{['1', 'true'].includes(process.env['NX_USE_ENV_OVERRIDES'] || '') ? (
|
||||
/* eslint-disable-next-line @next/next/no-sync-scripts */
|
||||
<script src="./env-config.js" type="text/javascript" />
|
||||
) : null}
|
||||
</Head>
|
||||
<AppBody {...props} />
|
||||
</VegaWalletProvider>
|
||||
</EnvironmentProvider>
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,10 @@ import classNames from 'classnames';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import type { ReactNode } 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 { TradesContainer } from '@vegaprotocol/trades';
|
||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||
@ -15,8 +18,8 @@ import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
|
||||
import { SelectMarketDialog } from '@vegaprotocol/market-list';
|
||||
import {
|
||||
ArrowDown,
|
||||
GridTab,
|
||||
GridTabs,
|
||||
Tab,
|
||||
Tabs,
|
||||
PriceCellChange,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import type { CandleClose } from '@vegaprotocol/types';
|
||||
@ -30,6 +33,7 @@ const TradingViews = {
|
||||
Positions: PositionsContainer,
|
||||
Accounts: AccountsContainer,
|
||||
Trades: TradesContainer,
|
||||
Info: MarketInfoContainer,
|
||||
};
|
||||
|
||||
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';
|
||||
const itemValueClassName =
|
||||
'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',
|
||||
className
|
||||
);
|
||||
return (
|
||||
<header className={headerClassname}>
|
||||
<header className={headerClassName}>
|
||||
<SelectMarketDialog dialogOpen={open} setDialogOpen={setOpen} />
|
||||
<div className="flex flex-col md:flex-row gap-20 md:gap-64 ml-auto mr-8">
|
||||
<button
|
||||
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>
|
||||
<ArrowDown color="yellow" borderX={8} borderTop={12} />
|
||||
@ -105,7 +109,7 @@ interface TradeGridProps {
|
||||
export const TradeGrid = ({ market }: TradeGridProps) => {
|
||||
const wrapperClasses = classNames(
|
||||
'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',
|
||||
'text-ui'
|
||||
);
|
||||
@ -115,43 +119,50 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
|
||||
<div className={wrapperClasses}>
|
||||
<TradeMarketHeader
|
||||
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">
|
||||
<GridTabs>
|
||||
<GridTab id="candles" name={t('Candles')}>
|
||||
<Tabs>
|
||||
<Tab id="candles" name={t('Candles')}>
|
||||
<TradingViews.Candles marketId={market.id} />
|
||||
</GridTab>
|
||||
<GridTab id="depth" name={t('Depth')}>
|
||||
</Tab>
|
||||
<Tab id="depth" name={t('Depth')}>
|
||||
<TradingViews.Depth marketId={market.id} />
|
||||
</GridTab>
|
||||
</GridTabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
<TradeGridChild className="row-start-1 row-end-3">
|
||||
<TradingViews.Ticket marketId={market.id} />
|
||||
<TradeGridChild className="row-start-2 row-end-3 col-start-2 col-end-3">
|
||||
<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 className="row-start-1 row-end-3">
|
||||
<GridTabs>
|
||||
<GridTab id="trades" name={t('Trades')}>
|
||||
<TradeGridChild className="row-start-2 row-end-3 col-start-3 col-end-4">
|
||||
<Tabs>
|
||||
<Tab id="trades" name={t('Trades')}>
|
||||
<TradingViews.Trades marketId={market.id} />
|
||||
</GridTab>
|
||||
<GridTab id="orderbook" name={t('Orderbook')}>
|
||||
</Tab>
|
||||
<Tab id="orderbook" name={t('Orderbook')}>
|
||||
<TradingViews.Orderbook marketId={market.id} />
|
||||
</GridTab>
|
||||
</GridTabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
<TradeGridChild className="col-span-3">
|
||||
<GridTabs>
|
||||
<GridTab id="orders" name={t('Orders')}>
|
||||
<Tabs>
|
||||
<Tab id="orders" name={t('Orders')}>
|
||||
<TradingViews.Orders />
|
||||
</GridTab>
|
||||
<GridTab id="positions" name={t('Positions')}>
|
||||
</Tab>
|
||||
<Tab id="positions" name={t('Positions')}>
|
||||
<TradingViews.Positions />
|
||||
</GridTab>
|
||||
<GridTab id="accounts" name={t('Accounts')}>
|
||||
</Tab>
|
||||
<Tab id="accounts" name={t('Accounts')}>
|
||||
<TradingViews.Accounts />
|
||||
</GridTab>
|
||||
</GridTabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</div>
|
||||
</>
|
||||
|
@ -3,8 +3,7 @@ import { t } from '@vegaprotocol/react-helpers';
|
||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||
import { OrderListContainer } from '@vegaprotocol/order-list';
|
||||
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';
|
||||
|
||||
const Portfolio = () => {
|
||||
@ -20,54 +19,54 @@ const Portfolio = () => {
|
||||
</h2>
|
||||
</aside>
|
||||
<section data-testid="portfolio-grid">
|
||||
<GridTabs>
|
||||
<GridTab id="positions" name={t('Positions')}>
|
||||
<Tabs>
|
||||
<Tab id="positions" name={t('Positions')}>
|
||||
<div className={tabClassName}>
|
||||
<h4 className="text-h4 text-black dark:text-white">
|
||||
{t('Positions')}
|
||||
</h4>
|
||||
<PositionsContainer />
|
||||
</div>
|
||||
</GridTab>
|
||||
<GridTab id="orders" name={t('Orders')}>
|
||||
</Tab>
|
||||
<Tab id="orders" name={t('Orders')}>
|
||||
<div className={tabClassName}>
|
||||
<h4 className="text-h4 text-black dark:text-white">
|
||||
{t('Orders')}
|
||||
</h4>
|
||||
<OrderListContainer />
|
||||
</div>
|
||||
</GridTab>
|
||||
<GridTab id="fills" name={t('Fills')}>
|
||||
</Tab>
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
<div className={tabClassName}>
|
||||
<h4 className="text-h4 text-black dark:text-white">
|
||||
{t('Fills')}
|
||||
</h4>
|
||||
</div>
|
||||
</GridTab>
|
||||
<GridTab id="history" name={t('History')}>
|
||||
</Tab>
|
||||
<Tab id="history" name={t('History')}>
|
||||
<div className={tabClassName}>
|
||||
<h4 className="text-h4 text-black dark:text-white">
|
||||
{t('History')}
|
||||
</h4>
|
||||
</div>
|
||||
</GridTab>
|
||||
</GridTabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</section>
|
||||
</main>
|
||||
<section className="fixed bottom-0 left-0 w-full h-[200px]">
|
||||
<GridTabs>
|
||||
<GridTab id="collateral" name={t('Collateral')}>
|
||||
<Tabs>
|
||||
<Tab id="collateral" name={t('Collateral')}>
|
||||
<AccountsContainer />
|
||||
</GridTab>
|
||||
<GridTab id="deposits" name={t('Deposits')}>
|
||||
</Tab>
|
||||
<Tab id="deposits" name={t('Deposits')}>
|
||||
<AnchorButton data-testid="deposit" href="/portfolio/deposit">
|
||||
{t('Deposit')}
|
||||
</AnchorButton>
|
||||
</GridTab>
|
||||
<GridTab id="withdrawals" name={t('Withdrawals')}>
|
||||
</Tab>
|
||||
<Tab id="withdrawals" name={t('Withdrawals')}>
|
||||
<WithdrawalsContainer />
|
||||
</GridTab>
|
||||
</GridTabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</section>
|
||||
</div>
|
||||
</Web3Container>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import produce from 'immer';
|
||||
import { gql } from '@apollo/client';
|
||||
import type {
|
||||
Accounts,
|
||||
@ -52,17 +53,18 @@ export const getId = (
|
||||
) => `${data.type}-${data.asset.symbol}-${data.market?.id ?? 'null'}`;
|
||||
|
||||
const update = (
|
||||
draft: Accounts_party_accounts[],
|
||||
data: Accounts_party_accounts[],
|
||||
delta: AccountSubscribe_accounts
|
||||
) => {
|
||||
const id = getId(delta);
|
||||
const index = draft.findIndex((a) => getId(a) === id);
|
||||
if (index !== -1) {
|
||||
draft[index] = delta;
|
||||
} else {
|
||||
draft.push(delta);
|
||||
}
|
||||
};
|
||||
) =>
|
||||
produce(data, (draft) => {
|
||||
const id = getId(delta);
|
||||
const index = draft.findIndex((a) => getId(a) === id);
|
||||
if (index !== -1) {
|
||||
draft[index] = delta;
|
||||
} else {
|
||||
draft.push(delta);
|
||||
}
|
||||
});
|
||||
const getData = (responseData: Accounts): Accounts_party_accounts[] | null =>
|
||||
responseData.party ? responseData.party.accounts : null;
|
||||
const getDelta = (
|
||||
|
@ -17,7 +17,6 @@ import { useContext, useMemo, useState } from 'react';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
Button,
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
@ -58,14 +57,14 @@ export const CandlesChartContainer = ({
|
||||
return new VegaDataSource(client, marketId, keypair?.pub);
|
||||
}, [client, marketId, keypair]);
|
||||
|
||||
const dropdownTriggerStyles = 'border-black-60 dark:border-white-60 px-20';
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="p-8 flex flex-row flex-wrap gap-8">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild={true}>
|
||||
<Button appendIconName="caret-down" variant="secondary">
|
||||
{t('Interval')}
|
||||
</Button>
|
||||
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||
{t('Interval')}
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuRadioGroup
|
||||
@ -90,10 +89,8 @@ export const CandlesChartContainer = ({
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild={true}>
|
||||
<Button appendIconName="caret-down" variant="secondary">
|
||||
<Icon name={chartTypeIcon.get(chartType) as IconName} />
|
||||
</Button>
|
||||
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||
<Icon name={chartTypeIcon.get(chartType) as IconName} />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuRadioGroup
|
||||
@ -114,10 +111,8 @@ export const CandlesChartContainer = ({
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild={true}>
|
||||
<Button appendIconName="caret-down" variant="secondary">
|
||||
{t('Overlays')}
|
||||
</Button>
|
||||
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||
{t('Overlays')}
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
{Object.values(Overlay).map((overlay) => (
|
||||
@ -145,10 +140,8 @@ export const CandlesChartContainer = ({
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild={true}>
|
||||
<Button appendIconName="caret-down" variant="secondary">
|
||||
{t('Studies')}
|
||||
</Button>
|
||||
<DropdownMenuTrigger className={dropdownTriggerStyles}>
|
||||
{t('Studies')}
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
{Object.values(Study).map((study) => (
|
||||
|
@ -9,124 +9,6 @@ import { MarketState, MarketTradingMode } from "@vegaprotocol/types";
|
||||
// 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 {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
@ -163,70 +45,12 @@ export interface DealTicketQuery_market_tradableInstrument_instrument {
|
||||
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 {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of or reference to a fully specified 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 {
|
||||
@ -286,22 +110,6 @@ export interface DealTicketQuery_market {
|
||||
* Current mode of execution of the market
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
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 './OrderEvent';
|
||||
export * from './MarketInfoQuery';
|
||||
|
@ -12,22 +12,17 @@ export interface DealTicketAmountProps {
|
||||
price?: string;
|
||||
}
|
||||
|
||||
const getAmountComponent = (type: OrderType) => {
|
||||
switch (type) {
|
||||
export const DealTicketAmount = ({
|
||||
orderType,
|
||||
...props
|
||||
}: DealTicketAmountProps) => {
|
||||
switch (orderType) {
|
||||
case OrderType.Market:
|
||||
return DealTicketMarketAmount;
|
||||
return <DealTicketMarketAmount {...props} />;
|
||||
case OrderType.Limit:
|
||||
return DealTicketLimitAmount;
|
||||
return <DealTicketLimitAmount {...props} />;
|
||||
default: {
|
||||
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 {
|
||||
AsyncRenderer,
|
||||
GridTab,
|
||||
GridTabs,
|
||||
Splash,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { DealTicketManager } from './deal-ticket-manager';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Info } from './info-market';
|
||||
import type { DealTicketQuery_market, DealTicketQuery } from './__generated__';
|
||||
|
||||
const DEAL_TICKET_QUERY = gql`
|
||||
@ -19,40 +13,6 @@ const DEAL_TICKET_QUERY = gql`
|
||||
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 {
|
||||
@ -66,23 +26,6 @@ const DEAL_TICKET_QUERY = gql`
|
||||
}
|
||||
}
|
||||
}
|
||||
riskModel {
|
||||
... on LogNormalRiskModel {
|
||||
tau
|
||||
riskAversionParameter
|
||||
params {
|
||||
r
|
||||
sigma
|
||||
mu
|
||||
}
|
||||
}
|
||||
... on SimpleRiskModel {
|
||||
params {
|
||||
factorLong
|
||||
factorShort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
depth {
|
||||
lastTrade {
|
||||
@ -111,45 +54,18 @@ export const DealTicketContainer = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<GridTabs>
|
||||
<GridTab id="ticket" name={t('Ticket')}>
|
||||
<AsyncRenderer<DealTicketQuery>
|
||||
data={data}
|
||||
loading={loading}
|
||||
error={error}
|
||||
>
|
||||
{data && data.market ? (
|
||||
children ? (
|
||||
children(data)
|
||||
) : (
|
||||
<DealTicketManager market={data.market} />
|
||||
)
|
||||
) : (
|
||||
<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>
|
||||
<AsyncRenderer<DealTicketQuery> data={data} loading={loading} error={error}>
|
||||
{data && data.market ? (
|
||||
children ? (
|
||||
children(data)
|
||||
) : (
|
||||
<DealTicketManager market={data.market} />
|
||||
)
|
||||
) : (
|
||||
<Splash>
|
||||
<p>{t('Could not load market')}</p>
|
||||
</Splash>
|
||||
)}
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
||||
|
@ -37,6 +37,10 @@ export const DealTicketManager = ({
|
||||
return Intent.Danger;
|
||||
}
|
||||
|
||||
if (status === VegaTxStatus.Requested) {
|
||||
return Intent.Warning;
|
||||
}
|
||||
|
||||
if (status === VegaTxStatus.Error) {
|
||||
return Intent.Danger;
|
||||
}
|
||||
@ -47,6 +51,8 @@ export const DealTicketManager = ({
|
||||
useEffect(() => {
|
||||
if (transaction.status !== VegaTxStatus.Default) {
|
||||
setOrderDialogOpen(true);
|
||||
} else {
|
||||
setOrderDialogOpen(false);
|
||||
}
|
||||
}, [transaction.status]);
|
||||
|
||||
|
@ -6,13 +6,14 @@ import {
|
||||
import { addDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { fireEvent, render, screen, act } from '@testing-library/react';
|
||||
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 { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
const market: DealTicketQuery_market = {
|
||||
__typename: 'Market',
|
||||
id: 'market-id',
|
||||
name: 'market-name',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 1,
|
||||
tradingMode: MarketTradingMode.Continuous,
|
||||
@ -24,6 +25,12 @@ const market: DealTicketQuery_market = {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'quote-name',
|
||||
settlementAsset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
name: 'asset-name',
|
||||
symbol: 'asset-symbol',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -77,7 +77,7 @@ export const DealTicket = ({
|
||||
/>
|
||||
<DealTicketAmount
|
||||
orderType={orderType}
|
||||
step={0.02}
|
||||
step={step}
|
||||
register={register}
|
||||
price={
|
||||
market.depth.lastTrade
|
||||
@ -109,7 +109,7 @@ export const DealTicket = ({
|
||||
)}
|
||||
<Button
|
||||
className="w-full mb-8"
|
||||
variant="primary"
|
||||
variant="trade"
|
||||
type="submit"
|
||||
disabled={isDisabled}
|
||||
data-testid="place-order"
|
||||
|
@ -8,18 +8,130 @@ import {
|
||||
import {
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
AsyncRenderer,
|
||||
Splash,
|
||||
Accordion,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import startCase from 'lodash/startCase';
|
||||
import pick from 'lodash/pick';
|
||||
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 { 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 {
|
||||
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) => {
|
||||
const headerClassName =
|
||||
'text-h5 font-bold uppercase text-black dark:text-white';
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { OrderEvent_busEvents_event_Order } from './__generated__/OrderEvent';
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
addDecimal,
|
||||
addDecimalsFormatNumber,
|
||||
t,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import type { OrderEvent_busEvents_event_Order } from '../hooks/__generated__/OrderEvent';
|
||||
|
||||
interface OrderDialogProps {
|
||||
transaction: VegaTxState;
|
||||
@ -14,9 +18,22 @@ export const OrderDialog = ({
|
||||
transaction,
|
||||
finalizedOrder,
|
||||
}: OrderDialogProps) => {
|
||||
// TODO: When wallets support confirming transactions return UI for 'awaiting confirmation' step
|
||||
|
||||
// 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) {
|
||||
return (
|
||||
<OrderDialogWrapper
|
||||
@ -72,7 +89,14 @@ export const OrderDialog = ({
|
||||
<p>{t(`Market: ${finalizedOrder.market.name}`)}</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 && (
|
||||
<p>
|
||||
{t(
|
||||
|
@ -36,6 +36,12 @@ export interface OrderEvent_busEvents_event_Order_market {
|
||||
* 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;
|
||||
}
|
||||
|
||||
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 { determineId, removeDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaTransaction } from '@vegaprotocol/wallet';
|
||||
import type { DealTicketQuery_market } from '../components/__generated__/DealTicketQuery';
|
||||
import type {
|
||||
OrderEvent,
|
||||
OrderEventVariables,
|
||||
OrderEvent_busEvents_event_Order,
|
||||
} from '../components/__generated__/OrderEvent';
|
||||
import type { DealTicketQuery_market } from '../components/__generated__/DealTicketQuery';
|
||||
} from './__generated__/OrderEvent';
|
||||
|
||||
const ORDER_EVENT_SUB = gql`
|
||||
subscription OrderEvent($partyId: ID!) {
|
||||
@ -29,6 +29,7 @@ const ORDER_EVENT_SUB = gql`
|
||||
market {
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ beforeEach(() => {
|
||||
submitDeposit: jest.fn(),
|
||||
requestFaucet: jest.fn(),
|
||||
limits: {
|
||||
min: new BigNumber(0),
|
||||
max: new BigNumber(20),
|
||||
},
|
||||
allowance: new BigNumber(30),
|
||||
@ -199,6 +198,6 @@ it('Deposit', async () => {
|
||||
// @ts-ignore contract address definitely defined
|
||||
assetSource: asset.source.contractAddress,
|
||||
amount: '1500',
|
||||
vegaPublicKey: `0x${vegaKey}`,
|
||||
vegaPublicKey: vegaKey,
|
||||
});
|
||||
});
|
||||
|
@ -89,7 +89,7 @@ export const DepositForm = ({
|
||||
submitDeposit({
|
||||
assetSource: selectedAsset.source.contractAddress,
|
||||
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)
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -55,6 +55,12 @@ export interface MarketDepthSubscription_marketDepthUpdate_market {
|
||||
* Market ID
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { DepthChart } from 'pennant';
|
||||
import { produce } from 'immer';
|
||||
import throttle from 'lodash/throttle';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
@ -92,28 +91,31 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
||||
if (!dataRef.current) {
|
||||
return false;
|
||||
}
|
||||
dataRef.current = produce(dataRef.current, (draft) => {
|
||||
if (delta.buy) {
|
||||
draft.data.buy = updateLevels(
|
||||
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
|
||||
dataRef.current = {
|
||||
...dataRef.current,
|
||||
midPrice: delta.market.data?.staticMidPrice
|
||||
? formatMidPrice(
|
||||
delta.market.data?.staticMidPrice,
|
||||
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);
|
||||
return true;
|
||||
},
|
||||
|
@ -16,6 +16,7 @@ const MARKET_DEPTH_QUERY = gql`
|
||||
market(id: $marketId) {
|
||||
id
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
data {
|
||||
staticMidPrice
|
||||
marketTradingMode
|
||||
@ -52,6 +53,7 @@ export const MARKET_DEPTH_SUBSCRIPTION_QUERY = gql`
|
||||
marketDepthUpdate(marketId: $marketId) {
|
||||
market {
|
||||
id
|
||||
positionDecimalPlaces
|
||||
data {
|
||||
staticMidPrice
|
||||
marketTradingMode
|
||||
@ -84,27 +86,31 @@ const sequenceNumbers: Record<string, number> = {};
|
||||
const update: Update<
|
||||
MarketDepth_market,
|
||||
MarketDepthSubscription_marketDepthUpdate
|
||||
> = (draft, delta, reload) => {
|
||||
if (delta.market.id !== draft.id) {
|
||||
return;
|
||||
> = (data, delta, reload) => {
|
||||
if (delta.market.id !== data.id) {
|
||||
return data;
|
||||
}
|
||||
const sequenceNumber = Number(delta.sequenceNumber);
|
||||
if (sequenceNumber <= sequenceNumbers[delta.market.id]) {
|
||||
return;
|
||||
return data;
|
||||
}
|
||||
/*
|
||||
if (sequenceNumber - 1 !== sequenceNumbers[delta.market.id]) {
|
||||
sequenceNumbers[delta.market.id] = 0;
|
||||
reload();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
sequenceNumbers[delta.market.id] = sequenceNumber;
|
||||
Object.assign(draft.data, delta.market.data);
|
||||
const updatedData = { ...data };
|
||||
data.data = delta.market.data;
|
||||
if (delta.buy) {
|
||||
draft.depth.buy = updateLevels(draft.depth.buy ?? [], delta.buy);
|
||||
updatedData.depth.buy = updateLevels(data.depth.buy ?? [], delta.buy);
|
||||
}
|
||||
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) => {
|
||||
|
@ -55,10 +55,8 @@ describe('compactRows', () => {
|
||||
'1097': 3,
|
||||
'1098': 2,
|
||||
'1099': 1,
|
||||
'1100': 0,
|
||||
});
|
||||
expect(orderbookRows[orderbookRows.length - 1].bidByLevel).toEqual({
|
||||
'901': 0,
|
||||
'902': 1,
|
||||
'903': 2,
|
||||
'904': 3,
|
||||
@ -81,7 +79,7 @@ describe('compactRows', () => {
|
||||
});
|
||||
|
||||
describe('updateLevels', () => {
|
||||
const levels: MarketDepth_market_depth_sell[] = new Array(10)
|
||||
let levels: MarketDepth_market_depth_sell[] = new Array(10)
|
||||
.fill(null)
|
||||
.map((n, i) => ({
|
||||
__typename: 'PriceLevel',
|
||||
@ -96,9 +94,9 @@ describe('updateLevels', () => {
|
||||
volume: '0',
|
||||
numberOfOrders: '0',
|
||||
};
|
||||
updateLevels(levels, [removeFirstRow]);
|
||||
levels = updateLevels(levels, [removeFirstRow]);
|
||||
expect(levels[0].price).toEqual('20');
|
||||
updateLevels(levels, [removeFirstRow]);
|
||||
levels = updateLevels(levels, [removeFirstRow]);
|
||||
expect(levels[0].price).toEqual('20');
|
||||
expect(updateLevels([], [removeFirstRow])).toEqual([]);
|
||||
const addFirstRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||
@ -107,7 +105,7 @@ describe('updateLevels', () => {
|
||||
volume: '10',
|
||||
numberOfOrders: '10',
|
||||
};
|
||||
updateLevels(levels, [addFirstRow]);
|
||||
levels = updateLevels(levels, [addFirstRow]);
|
||||
expect(levels[0].price).toEqual('10');
|
||||
const addBeforeLastRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||
__typename: 'PriceLevel',
|
||||
@ -115,7 +113,7 @@ describe('updateLevels', () => {
|
||||
volume: '95',
|
||||
numberOfOrders: '95',
|
||||
};
|
||||
updateLevels(levels, [addBeforeLastRow]);
|
||||
levels = updateLevels(levels, [addBeforeLastRow]);
|
||||
expect(levels[levels.length - 2].price).toEqual('95');
|
||||
const addAtTheEnd: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||
__typename: 'PriceLevel',
|
||||
@ -123,7 +121,7 @@ describe('updateLevels', () => {
|
||||
volume: '115',
|
||||
numberOfOrders: '115',
|
||||
};
|
||||
updateLevels(levels, [addAtTheEnd]);
|
||||
levels = updateLevels(levels, [addAtTheEnd]);
|
||||
expect(levels[levels.length - 1].price).toEqual('115');
|
||||
const updateLastRow: MarketDepthSubscription_marketDepthUpdate_sell = {
|
||||
__typename: 'PriceLevel',
|
||||
@ -131,7 +129,7 @@ describe('updateLevels', () => {
|
||||
volume: '116',
|
||||
numberOfOrders: '115',
|
||||
};
|
||||
updateLevels(levels, [updateLastRow]);
|
||||
levels = updateLevels(levels, [updateLastRow]);
|
||||
expect(levels[levels.length - 1]).toEqual(updateLastRow);
|
||||
expect(updateLevels([], [updateLastRow])).toEqual([updateLastRow]);
|
||||
});
|
||||
|
@ -1,4 +1,3 @@
|
||||
import produce from 'immer';
|
||||
import groupBy from 'lodash/groupBy';
|
||||
import { VolumeType } from '@vegaprotocol/react-helpers';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
@ -31,6 +30,8 @@ export interface OrderbookRowData {
|
||||
cumulativeVol: CumulativeVol;
|
||||
}
|
||||
|
||||
type PartialOrderbookRowData = Pick<OrderbookRowData, 'price' | 'ask' | 'bid'>;
|
||||
|
||||
export type OrderbookData = Partial<
|
||||
Omit<MarketDepth_market_data, '__typename' | 'market'>
|
||||
> & { 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 = (
|
||||
price: string,
|
||||
volume = 0,
|
||||
dataType?: VolumeType
|
||||
): OrderbookRowData => ({
|
||||
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 } : {},
|
||||
});
|
||||
): OrderbookRowData => extendRow(createPartialRow(price, volume, dataType));
|
||||
|
||||
const mapRawData =
|
||||
(dataType: VolumeType.ask | VolumeType.bid) =>
|
||||
@ -99,8 +110,8 @@ const mapRawData =
|
||||
| MarketDepthSubscription_marketDepthUpdate_sell
|
||||
| MarketDepth_market_depth_buy
|
||||
| MarketDepthSubscription_marketDepthUpdate_buy
|
||||
): OrderbookRowData =>
|
||||
createRow(data.price, Number(data.volume), dataType);
|
||||
): PartialOrderbookRowData =>
|
||||
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
|
||||
@ -121,37 +132,38 @@ export const compactRows = (
|
||||
resolution: number
|
||||
) => {
|
||||
// map raw sell data to OrderbookData
|
||||
const askOrderbookData = [...(sell ?? [])].map<OrderbookRowData>(
|
||||
const askOrderbookData = [...(sell ?? [])].map<PartialOrderbookRowData>(
|
||||
mapRawData(VolumeType.ask)
|
||||
);
|
||||
// map raw buy data to OrderbookData
|
||||
const bidOrderbookData = [...(buy ?? [])].map<OrderbookRowData>(
|
||||
const bidOrderbookData = [...(buy ?? [])].map<PartialOrderbookRowData>(
|
||||
mapRawData(VolumeType.bid)
|
||||
);
|
||||
|
||||
// group by price level
|
||||
const groupedByLevel = groupBy<OrderbookRowData>(
|
||||
const groupedByLevel = groupBy<PartialOrderbookRowData>(
|
||||
[...askOrderbookData, ...bidOrderbookData],
|
||||
(row) => getPriceLevel(row.price, resolution)
|
||||
);
|
||||
|
||||
// create single OrderbookData from grouped OrderbookData[], sum volumes and atore volume by level
|
||||
const orderbookData = Object.keys(groupedByLevel).reduce<OrderbookRowData[]>(
|
||||
(rows, price) =>
|
||||
rows.concat(
|
||||
groupedByLevel[price].reduce<OrderbookRowData>(
|
||||
(a, c) => ({
|
||||
...a,
|
||||
ask: a.ask + c.ask,
|
||||
askByLevel: Object.assign(a.askByLevel, c.askByLevel),
|
||||
bid: (a.bid ?? 0) + (c.bid ?? 0),
|
||||
bidByLevel: Object.assign(a.bidByLevel, c.bidByLevel),
|
||||
}),
|
||||
createRow(price)
|
||||
)
|
||||
),
|
||||
[]
|
||||
);
|
||||
const orderbookData: OrderbookRowData[] = [];
|
||||
Object.keys(groupedByLevel).forEach((price) => {
|
||||
const row = extendRow(
|
||||
groupedByLevel[price].pop() as PartialOrderbookRowData
|
||||
);
|
||||
row.price = price;
|
||||
let subRow: PartialOrderbookRowData | undefined;
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((subRow = groupedByLevel[price].pop())) {
|
||||
row.ask += subRow.ask;
|
||||
row.bid += subRow.bid;
|
||||
if (subRow.ask) {
|
||||
row.askByLevel[subRow.price] = subRow.ask;
|
||||
}
|
||||
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
|
||||
orderbookData.sort((a, b) => Number(BigInt(b.price) - BigInt(a.price)));
|
||||
// count cumulative volumes
|
||||
@ -163,11 +175,9 @@ export const compactRows = (
|
||||
(i !== 0 ? orderbookData[i - 1].cumulativeVol.bid : 0);
|
||||
}
|
||||
for (let i = maxIndex; i >= 0; i--) {
|
||||
if (!orderbookData[i].cumulativeVol.ask) {
|
||||
orderbookData[i].cumulativeVol.ask =
|
||||
orderbookData[i].ask +
|
||||
(i !== maxIndex ? orderbookData[i + 1].cumulativeVol.ask : 0);
|
||||
}
|
||||
orderbookData[i].cumulativeVol.ask =
|
||||
orderbookData[i].ask +
|
||||
(i !== maxIndex ? orderbookData[i + 1].cumulativeVol.ask : 0);
|
||||
}
|
||||
}
|
||||
// count relative volumes
|
||||
@ -186,13 +196,13 @@ export const compactRows = (
|
||||
*/
|
||||
const partiallyUpdateCompactedRows = (
|
||||
dataType: VolumeType,
|
||||
draft: OrderbookRowData[],
|
||||
data: OrderbookRowData[],
|
||||
delta:
|
||||
| MarketDepthSubscription_marketDepthUpdate_sell
|
||||
| MarketDepthSubscription_marketDepthUpdate_buy,
|
||||
resolution: number,
|
||||
modifiedIndex: number
|
||||
) => {
|
||||
): [number, OrderbookRowData[]] => {
|
||||
const { price } = delta;
|
||||
const volume = Number(delta.volume);
|
||||
const priceLevel = getPriceLevel(price, resolution);
|
||||
@ -201,28 +211,36 @@ const partiallyUpdateCompactedRows = (
|
||||
const oppositeVolKey = isAskDataType ? 'bid' : 'ask';
|
||||
const volByLevelKey = isAskDataType ? 'askByLevel' : 'bidByLevel';
|
||||
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) {
|
||||
modifiedIndex = resolveModifiedIndex(modifiedIndex, index);
|
||||
draft[index][volKey] =
|
||||
draft[index][volKey] - (draft[index][volByLevelKey][price] || 0) + volume;
|
||||
draft[index][volByLevelKey][price] = volume;
|
||||
data[index] = {
|
||||
...data[index],
|
||||
[volKey]:
|
||||
data[index][volKey] - (data[index][volByLevelKey][price] || 0) + volume,
|
||||
[volByLevelKey]: {
|
||||
...data[index][volByLevelKey],
|
||||
[price]: volume,
|
||||
},
|
||||
};
|
||||
return [modifiedIndex, [...data]];
|
||||
} else {
|
||||
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) {
|
||||
draft.splice(index, 0, newData);
|
||||
newData.cumulativeVol[oppositeVolKey] =
|
||||
draft[index + (isAskDataType ? -1 : 1)]?.cumulativeVol[
|
||||
oppositeVolKey
|
||||
] ?? 0;
|
||||
data[index + (isAskDataType ? 0 : 1)]?.cumulativeVol[oppositeVolKey] ??
|
||||
0;
|
||||
modifiedIndex = resolveModifiedIndex(modifiedIndex, index);
|
||||
return [
|
||||
modifiedIndex,
|
||||
[...data.slice(0, index), newData, ...data.slice(index)],
|
||||
];
|
||||
} else {
|
||||
draft.push(newData);
|
||||
modifiedIndex = draft.length - 1;
|
||||
modifiedIndex = data.length - 1;
|
||||
return [modifiedIndex, [...data, newData]];
|
||||
}
|
||||
}
|
||||
return modifiedIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -239,59 +257,66 @@ export const updateCompactedRows = (
|
||||
sell: MarketDepthSubscription_marketDepthUpdate_sell[] | null,
|
||||
buy: MarketDepthSubscription_marketDepthUpdate_buy[] | null,
|
||||
resolution: number
|
||||
) =>
|
||||
produce(rows, (draft) => {
|
||||
let sellModifiedIndex = -1;
|
||||
sell?.forEach((delta) => {
|
||||
sellModifiedIndex = partiallyUpdateCompactedRows(
|
||||
VolumeType.ask,
|
||||
draft,
|
||||
delta,
|
||||
resolution,
|
||||
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 sellModifiedIndex = -1;
|
||||
let data = [...rows];
|
||||
sell?.forEach((delta) => {
|
||||
[sellModifiedIndex, data] = partiallyUpdateCompactedRows(
|
||||
VolumeType.ask,
|
||||
data,
|
||||
delta,
|
||||
resolution,
|
||||
sellModifiedIndex
|
||||
);
|
||||
});
|
||||
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 = (
|
||||
data:
|
||||
@ -319,23 +344,24 @@ export const mapMarketData = (
|
||||
* @returns
|
||||
*/
|
||||
export const updateLevels = (
|
||||
levels: (MarketDepth_market_depth_buy | MarketDepth_market_depth_sell)[],
|
||||
draft: (MarketDepth_market_depth_buy | MarketDepth_market_depth_sell)[],
|
||||
updates: (
|
||||
| MarketDepthSubscription_marketDepthUpdate_buy
|
||||
| MarketDepthSubscription_marketDepthUpdate_sell
|
||||
)[]
|
||||
) => {
|
||||
const levels = [...draft];
|
||||
updates.forEach((update) => {
|
||||
let index = levels.findIndex((level) => level.price === update.price);
|
||||
if (index !== -1) {
|
||||
if (update.volume === '0') {
|
||||
levels.splice(index, 1);
|
||||
} else {
|
||||
Object.assign(levels[index], update);
|
||||
levels[index] = update;
|
||||
}
|
||||
} else if (update.volume !== '0') {
|
||||
index = levels.findIndex(
|
||||
(level) => Number(level.price) > Number(update.price)
|
||||
(level) => BigInt(level.price) > BigInt(update.price)
|
||||
);
|
||||
if (index !== -1) {
|
||||
levels.splice(index, 0, update);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import throttle from 'lodash/throttle';
|
||||
import produce from 'immer';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { Orderbook } from './orderbook';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
@ -25,27 +24,52 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
||||
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(
|
||||
(delta: MarketDepthSubscription_marketDepthUpdate) => {
|
||||
if (!dataRef.current.rows) {
|
||||
return false;
|
||||
}
|
||||
dataRef.current = produce(dataRef.current, (draft) => {
|
||||
Object.assign(draft, delta.market.data);
|
||||
draft.rows = updateCompactedRows(
|
||||
draft.rows ?? [],
|
||||
delta.sell,
|
||||
delta.buy,
|
||||
resolutionRef.current
|
||||
);
|
||||
Object.assign(
|
||||
draft,
|
||||
mapMarketData(delta.market.data, resolutionRef.current)
|
||||
);
|
||||
});
|
||||
setOrderbookDataThrottled.current(dataRef.current);
|
||||
if (deltaRef.current) {
|
||||
deltaRef.current.market = delta.market;
|
||||
if (delta.sell) {
|
||||
if (deltaRef.current.sell) {
|
||||
deltaRef.current.sell.push(...delta.sell);
|
||||
} else {
|
||||
deltaRef.current.sell = delta.sell;
|
||||
}
|
||||
}
|
||||
if (delta.buy) {
|
||||
if (deltaRef.current.buy) {
|
||||
deltaRef.current.buy.push(...delta.buy);
|
||||
} else {
|
||||
deltaRef.current.buy = delta.buy;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deltaRef.current = delta;
|
||||
}
|
||||
updateOrderbookData.current();
|
||||
return true;
|
||||
},
|
||||
// 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
|
||||
{...orderbookData}
|
||||
decimalPlaces={data?.decimalPlaces ?? 0}
|
||||
positionDecimalPlaces={data?.positionDecimalPlaces ?? 0}
|
||||
resolution={resolution}
|
||||
onResolutionChange={(resolution: number) => setResolution(resolution)}
|
||||
/>
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
CumulativeVol,
|
||||
addDecimalsFormatNumber,
|
||||
VolumeType,
|
||||
addDecimal,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
|
||||
interface OrderbookRowProps {
|
||||
@ -15,6 +16,7 @@ interface OrderbookRowProps {
|
||||
cumulativeRelativeAsk?: number;
|
||||
cumulativeRelativeBid?: number;
|
||||
decimalPlaces: number;
|
||||
positionDecimalPlaces: number;
|
||||
indicativeVolume?: string;
|
||||
price: string;
|
||||
relativeAsk?: number;
|
||||
@ -30,6 +32,7 @@ export const OrderbookRow = React.memo(
|
||||
cumulativeRelativeAsk,
|
||||
cumulativeRelativeBid,
|
||||
decimalPlaces,
|
||||
positionDecimalPlaces,
|
||||
indicativeVolume,
|
||||
price,
|
||||
relativeAsk,
|
||||
@ -40,6 +43,7 @@ export const OrderbookRow = React.memo(
|
||||
<Vol
|
||||
testId={`bid-vol-${price}`}
|
||||
value={bid}
|
||||
valueFormatted={addDecimal(bid, positionDecimalPlaces)}
|
||||
relativeValue={relativeBid}
|
||||
type={VolumeType.bid}
|
||||
/>
|
||||
@ -51,6 +55,7 @@ export const OrderbookRow = React.memo(
|
||||
<Vol
|
||||
testId={`ask-vol-${price}`}
|
||||
value={ask}
|
||||
valueFormatted={addDecimal(ask, positionDecimalPlaces)}
|
||||
relativeValue={relativeAsk}
|
||||
type={VolumeType.ask}
|
||||
/>
|
||||
|
@ -22,6 +22,7 @@ describe('Orderbook', () => {
|
||||
const result = render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData(params)}
|
||||
onResolutionChange={onResolutionChange}
|
||||
/>
|
||||
@ -35,6 +36,7 @@ describe('Orderbook', () => {
|
||||
const result = render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData(params)}
|
||||
onResolutionChange={onResolutionChange}
|
||||
/>
|
||||
@ -44,6 +46,7 @@ describe('Orderbook', () => {
|
||||
result.rerender(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData({
|
||||
...params,
|
||||
numberOfSellRows: params.numberOfSellRows - 1,
|
||||
@ -60,6 +63,7 @@ describe('Orderbook', () => {
|
||||
const result = render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData(params)}
|
||||
onResolutionChange={onResolutionChange}
|
||||
/>
|
||||
@ -69,6 +73,7 @@ describe('Orderbook', () => {
|
||||
result.rerender(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData({
|
||||
...params,
|
||||
bestStaticBidPrice: params.bestStaticBidPrice + 1,
|
||||
@ -86,6 +91,7 @@ describe('Orderbook', () => {
|
||||
const result = render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData(params)}
|
||||
onResolutionChange={onResolutionChange}
|
||||
/>
|
||||
@ -98,6 +104,7 @@ describe('Orderbook', () => {
|
||||
result.rerender(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData({
|
||||
...params,
|
||||
numberOfSellRows: params.numberOfSellRows - 1,
|
||||
@ -114,6 +121,7 @@ describe('Orderbook', () => {
|
||||
const result = render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData(params)}
|
||||
onResolutionChange={onResolutionChange}
|
||||
/>
|
||||
@ -134,6 +142,7 @@ describe('Orderbook', () => {
|
||||
const result = render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData(params)}
|
||||
onResolutionChange={onResolutionChange}
|
||||
/>
|
||||
@ -153,6 +162,7 @@ describe('Orderbook', () => {
|
||||
result.rerender(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
{...generateMockData({
|
||||
...params,
|
||||
resolution: 10,
|
||||
|
@ -19,6 +19,7 @@ import { Icon, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import type { OrderbookData, OrderbookRowData } from './orderbook-data';
|
||||
interface OrderbookProps extends OrderbookData {
|
||||
decimalPlaces: number;
|
||||
positionDecimalPlaces: number;
|
||||
resolution: number;
|
||||
onResolutionChange: (resolution: number) => void;
|
||||
}
|
||||
@ -100,6 +101,7 @@ export const Orderbook = ({
|
||||
indicativeVolume,
|
||||
indicativePrice,
|
||||
decimalPlaces,
|
||||
positionDecimalPlaces,
|
||||
resolution,
|
||||
onResolutionChange,
|
||||
}: OrderbookProps) => {
|
||||
@ -174,7 +176,10 @@ export const Orderbook = ({
|
||||
// adjust to current rows position
|
||||
scrollTop +=
|
||||
(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) {
|
||||
updateScrollOffset(priceCenterScrollOffset);
|
||||
scrollTopRef.current = priceCenterScrollOffset;
|
||||
@ -182,7 +187,13 @@ export const Orderbook = ({
|
||||
}
|
||||
}
|
||||
},
|
||||
[maxPriceLevel, resolution, viewportHeight, updateScrollOffset]
|
||||
[
|
||||
maxPriceLevel,
|
||||
resolution,
|
||||
viewportHeight,
|
||||
numberOfRows,
|
||||
updateScrollOffset,
|
||||
]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@ -197,23 +208,36 @@ export const Orderbook = ({
|
||||
return;
|
||||
}
|
||||
priceInCenter.current = undefined;
|
||||
setLockOnMidPrice(true);
|
||||
scrollToPrice(
|
||||
getPriceLevel(
|
||||
BigInt(bestStaticOfferPrice) +
|
||||
(BigInt(bestStaticBidPrice) - BigInt(bestStaticOfferPrice)) /
|
||||
BigInt(2),
|
||||
resolution
|
||||
)
|
||||
let midPrice = getPriceLevel(
|
||||
BigInt(bestStaticOfferPrice) +
|
||||
(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
|
||||
useLayoutEffect(() => {
|
||||
if (resolutionRef.current !== resolution) {
|
||||
priceInCenter.current = undefined;
|
||||
resolutionRef.current = resolution;
|
||||
setLockOnMidPrice(true);
|
||||
}
|
||||
if (priceInCenter.current) {
|
||||
scrollToPrice(priceInCenter.current);
|
||||
@ -236,21 +260,19 @@ export const Orderbook = ({
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
const renderedRows = useMemo(() => {
|
||||
let offset = Math.max(0, Math.round(scrollOffset / rowHeight));
|
||||
const prependingBufferSize = Math.min(bufferSize, offset);
|
||||
offset -= prependingBufferSize;
|
||||
const viewportSize = Math.round(viewportHeight / rowHeight);
|
||||
const limit = Math.min(
|
||||
prependingBufferSize + viewportSize + bufferSize,
|
||||
numberOfRows - offset
|
||||
);
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
data: getRowsToRender(rows, resolution, offset, limit),
|
||||
};
|
||||
}, [rows, scrollOffset, resolution, viewportHeight, numberOfRows]);
|
||||
let offset = Math.max(0, Math.round(scrollOffset / rowHeight));
|
||||
const prependingBufferSize = Math.min(bufferSize, offset);
|
||||
offset -= prependingBufferSize;
|
||||
const viewportSize = Math.round(viewportHeight / rowHeight);
|
||||
const limit = Math.min(
|
||||
prependingBufferSize + viewportSize + bufferSize,
|
||||
numberOfRows - offset
|
||||
);
|
||||
const renderedRows = {
|
||||
offset,
|
||||
limit,
|
||||
data: getRowsToRender(rows, resolution, offset, limit),
|
||||
};
|
||||
|
||||
const paddingTop = renderedRows.offset * rowHeight;
|
||||
const paddingBottom =
|
||||
@ -298,6 +320,7 @@ export const Orderbook = ({
|
||||
<OrderbookRow
|
||||
price={(BigInt(data.price) / BigInt(resolution)).toString()}
|
||||
decimalPlaces={decimalPlaces - Math.log10(resolution)}
|
||||
positionDecimalPlaces={positionDecimalPlaces}
|
||||
bid={data.bid}
|
||||
relativeBid={data.relativeBid}
|
||||
cumulativeBid={data.cumulativeVol.bid}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import produce from 'immer';
|
||||
import { gql } from '@apollo/client';
|
||||
import type {
|
||||
Markets,
|
||||
@ -90,13 +91,14 @@ const MARKET_DATA_SUB = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
const update = (draft: Markets_markets[], delta: MarketDataSub_marketData) => {
|
||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index].data = delta;
|
||||
}
|
||||
// @TODO - else push new market to draft
|
||||
};
|
||||
const update = (data: Markets_markets[], delta: MarketDataSub_marketData) =>
|
||||
produce(data, (draft) => {
|
||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index].data = delta;
|
||||
}
|
||||
// @TODO - else push new market to draft
|
||||
});
|
||||
const getData = (responseData: Markets): Markets_markets[] | null =>
|
||||
responseData.markets;
|
||||
const getDelta = (subscriptionData: MarketDataSub): MarketDataSub_marketData =>
|
||||
|
@ -52,6 +52,12 @@ export interface OrderFields_market {
|
||||
* 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;
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
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)
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -25,6 +25,7 @@ const marketOrder: Orders_party_orders = {
|
||||
id: 'market-id',
|
||||
name: 'market-name',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
@ -54,6 +55,7 @@ const limitOrder: Orders_party_orders = {
|
||||
id: 'market-id',
|
||||
name: 'market-name',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 2,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
@ -62,11 +64,11 @@ const limitOrder: Orders_party_orders = {
|
||||
},
|
||||
},
|
||||
},
|
||||
size: '10',
|
||||
size: '1000',
|
||||
type: OrderType.Limit,
|
||||
status: OrderStatus.Active,
|
||||
side: Side.Sell,
|
||||
remaining: '5',
|
||||
remaining: '500',
|
||||
price: '12345',
|
||||
timeInForce: OrderTimeInForce.GTT,
|
||||
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 expectedValues = [
|
||||
limitOrder.market?.tradableInstrument.instrument.code,
|
||||
'-10',
|
||||
'-10.00',
|
||||
limitOrder.type,
|
||||
limitOrder.status,
|
||||
'5',
|
||||
'5.00',
|
||||
formatNumber(limitOrder.price, limitOrder.market?.decimalPlaces ?? 0),
|
||||
`${limitOrder.timeInForce}: ${getDateTimeFormat().format(
|
||||
new Date(limitOrder.expiresAt ?? '')
|
||||
|
@ -1,11 +1,17 @@
|
||||
import { OrderTimeInForce, OrderStatus, Side } from '@vegaprotocol/types';
|
||||
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 type { ValueFormatterParams } from 'ag-grid-community';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridColumn } from 'ag-grid-react';
|
||||
import { forwardRef } from 'react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
interface OrderListProps {
|
||||
data: Orders_party_orders[] | null;
|
||||
@ -23,16 +29,18 @@ export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
||||
getRowId={({ data }) => data.id}
|
||||
>
|
||||
<AgGridColumn
|
||||
headerName="Market"
|
||||
headerName={t('Market')}
|
||||
field="market.tradableInstrument.instrument.code"
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName="Amount"
|
||||
headerName={t('Amount')}
|
||||
field="size"
|
||||
cellClass="font-mono"
|
||||
valueFormatter={({ value, data }: ValueFormatterParams) => {
|
||||
const prefix = data.side === Side.Buy ? '+' : '-';
|
||||
return prefix + value;
|
||||
return (
|
||||
prefix + addDecimal(value, data.market.positionDecimalPlaces)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn field="type" />
|
||||
@ -47,11 +55,18 @@ export const OrderList = forwardRef<AgGridReact, OrderListProps>(
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName="Filled"
|
||||
headerName={t('Filled')}
|
||||
field="remaining"
|
||||
cellClass="font-mono"
|
||||
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
|
||||
|
@ -1,3 +1,4 @@
|
||||
import produce from 'immer';
|
||||
import { gql } from '@apollo/client';
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type { OrderFields } from './__generated__/OrderFields';
|
||||
@ -13,6 +14,7 @@ const ORDER_FRAGMENT = gql`
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
code
|
||||
@ -77,19 +79,20 @@ export const prepareIncomingOrders = (delta: OrderFields[]) => {
|
||||
return incoming;
|
||||
};
|
||||
|
||||
const update = (draft: OrderFields[], delta: OrderFields[]) => {
|
||||
const incoming = prepareIncomingOrders(delta);
|
||||
const update = (data: OrderFields[], delta: OrderFields[]) =>
|
||||
produce(data, (draft) => {
|
||||
const incoming = prepareIncomingOrders(delta);
|
||||
|
||||
// Add or update incoming orders
|
||||
incoming.forEach((order) => {
|
||||
const index = draft.findIndex((o) => o.id === order.id);
|
||||
if (index === -1) {
|
||||
draft.unshift(order);
|
||||
} else {
|
||||
draft[index] = order;
|
||||
}
|
||||
// Add or update incoming orders
|
||||
incoming.forEach((order) => {
|
||||
const index = draft.findIndex((o) => o.id === order.id);
|
||||
if (index === -1) {
|
||||
draft.unshift(order);
|
||||
} else {
|
||||
draft[index] = order;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getData = (responseData: Orders): Orders_party_orders[] | null =>
|
||||
responseData?.party?.orders || null;
|
||||
|
@ -136,6 +136,12 @@ export interface PositionDetails_market {
|
||||
* 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;
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -136,6 +136,12 @@ export interface Positions_party_positions_market {
|
||||
* 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;
|
||||
/**
|
||||
* An instance of or reference to a tradable instrument.
|
||||
*/
|
||||
|
@ -1,3 +1,4 @@
|
||||
import produce from 'immer';
|
||||
import { gql } from '@apollo/client';
|
||||
import type {
|
||||
Positions,
|
||||
@ -27,6 +28,7 @@ const POSITIONS_FRAGMENT = gql`
|
||||
}
|
||||
}
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
id
|
||||
@ -74,16 +76,17 @@ export const POSITIONS_SUB = gql`
|
||||
`;
|
||||
|
||||
const update = (
|
||||
draft: Positions_party_positions[],
|
||||
data: Positions_party_positions[],
|
||||
delta: PositionSubscribe_positions
|
||||
) => {
|
||||
const index = draft.findIndex((m) => m.market.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index] = delta;
|
||||
} else {
|
||||
draft.push(delta);
|
||||
}
|
||||
};
|
||||
) =>
|
||||
produce(data, (draft) => {
|
||||
const index = draft.findIndex((m) => m.market.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index] = delta;
|
||||
} else {
|
||||
draft.push(delta);
|
||||
}
|
||||
});
|
||||
const getData = (responseData: Positions): Positions_party_positions[] | null =>
|
||||
responseData.party ? responseData.party.positions : null;
|
||||
const getDelta = (
|
||||
|
@ -5,7 +5,7 @@ import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
const singleRow: Positions_party_positions = {
|
||||
realisedPNL: '520000000',
|
||||
openVolume: '100',
|
||||
openVolume: '10000',
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '1129935',
|
||||
market: {
|
||||
@ -17,6 +17,7 @@ const singleRow: Positions_party_positions = {
|
||||
__typename: 'MarketData',
|
||||
market: { __typename: 'Market', id: '123' },
|
||||
},
|
||||
positionDecimalPlaces: 2,
|
||||
decimalPlaces: 5,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
@ -90,7 +91,7 @@ it('Correct formatting applied', async () => {
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
singleRow.market.tradableInstrument.instrument.code,
|
||||
'+100',
|
||||
'+100.00',
|
||||
'11.29935',
|
||||
'11.38885',
|
||||
'+5,200.000',
|
||||
|
@ -88,8 +88,11 @@ export const PositionsTable = forwardRef<AgGridReact, PositionsTableProps>(
|
||||
<AgGridColumn
|
||||
headerName={t('Amount')}
|
||||
field="openVolume"
|
||||
valueFormatter={({ value }: PositionsTableValueFormatterParams) =>
|
||||
volumePrefix(value)
|
||||
valueFormatter={({
|
||||
value,
|
||||
data,
|
||||
}: PositionsTableValueFormatterParams) =>
|
||||
volumePrefix(addDecimal(value, data.market.positionDecimalPlaces))
|
||||
}
|
||||
/>
|
||||
<AgGridColumn
|
||||
|
@ -1,19 +1,6 @@
|
||||
import once from 'lodash/once';
|
||||
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(
|
||||
() =>
|
||||
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