Merge branch 'master' of github.com:vegaprotocol/frontend-monorepo
This commit is contained in:
commit
d6f5ece80f
@ -1,4 +1,7 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { defaultFallbackInView } from 'react-intersection-observer';
|
||||
|
||||
defaultFallbackInView(true);
|
||||
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
writable: true,
|
||||
|
@ -43,7 +43,7 @@ function App() {
|
||||
<ApolloProvider client={client}>
|
||||
<VegaWalletProvider>
|
||||
<AppLoader>
|
||||
<div className="h-full dark:bg-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]">
|
||||
<div className="max-h-full min-h-full dark:bg-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]">
|
||||
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
|
||||
<DrawerToggle
|
||||
onToggle={onToggle}
|
||||
|
@ -1,12 +1,15 @@
|
||||
import type { DealTicketContainerProps } from '@vegaprotocol/deal-ticket';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import {
|
||||
DealTicketManager,
|
||||
DealTicketContainer as Container,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import { DealTicketSteps } from './deal-ticket-steps';
|
||||
|
||||
export const DealTicketContainer = ({ marketId }: DealTicketContainerProps) => {
|
||||
return (
|
||||
const tempEmptyText = <p>Please select a market from the markets page</p>;
|
||||
|
||||
export const DealTicketContainer = () => {
|
||||
const { marketId } = useParams<{ marketId: string }>();
|
||||
return marketId ? (
|
||||
<Container marketId={marketId}>
|
||||
{(data) => (
|
||||
<DealTicketManager market={data.market}>
|
||||
@ -14,5 +17,7 @@ export const DealTicketContainer = ({ marketId }: DealTicketContainerProps) => {
|
||||
</DealTicketManager>
|
||||
)}
|
||||
</Container>
|
||||
) : (
|
||||
tempEmptyText
|
||||
);
|
||||
};
|
||||
|
@ -70,7 +70,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
{
|
||||
label: 'Select Asset',
|
||||
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
|
||||
component: <div />,
|
||||
component: <h1 className="font-bold mb-16">{market.name}</h1>,
|
||||
},
|
||||
{
|
||||
label: 'Select Order Type',
|
||||
|
@ -10,5 +10,5 @@ export const DrawerContainer = ({ children }: Props) => (
|
||||
);
|
||||
|
||||
export const DrawerWrapper = ({ children }: Props) => (
|
||||
<div className="flex">{children}</div>
|
||||
<div className="flex dark:bg-black">{children}</div>
|
||||
);
|
||||
|
27
apps/simple-trading-app/src/app/components/simple-market-list/__generated__/CandleLive.ts
generated
Normal file
27
apps/simple-trading-app/src/app/components/simple-market-list/__generated__/CandleLive.ts
generated
Normal file
@ -0,0 +1,27 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL subscription operation: CandleLive
|
||||
// ====================================================
|
||||
|
||||
export interface CandleLive_candles {
|
||||
__typename: "Candle";
|
||||
/**
|
||||
* Close price (uint64)
|
||||
*/
|
||||
close: string;
|
||||
}
|
||||
|
||||
export interface CandleLive {
|
||||
/**
|
||||
* Subscribe to the candles updates
|
||||
*/
|
||||
candles: CandleLive_candles;
|
||||
}
|
||||
|
||||
export interface CandleLiveVariables {
|
||||
marketId: string;
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { Interval, MarketState } from "@vegaprotocol/types";
|
||||
import { MarketState } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: SimpleMarkets
|
||||
@ -117,6 +117,5 @@ export interface SimpleMarkets {
|
||||
}
|
||||
|
||||
export interface SimpleMarketsVariables {
|
||||
CandleInterval: Interval;
|
||||
CandleSince: string;
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ const MARKET_DATA_FRAGMENT = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
const MARKETS_QUERY = gql`
|
||||
export const MARKETS_QUERY = gql`
|
||||
${MARKET_DATA_FRAGMENT}
|
||||
query SimpleMarkets($CandleInterval: Interval!, $CandleSince: String!) {
|
||||
query SimpleMarkets($CandleSince: String!) {
|
||||
markets {
|
||||
id
|
||||
name
|
||||
@ -41,7 +41,7 @@ const MARKETS_QUERY = gql`
|
||||
}
|
||||
}
|
||||
}
|
||||
candles(interval: $CandleInterval, since: $CandleSince) {
|
||||
candles(interval: I1H, since: $CandleSince) {
|
||||
open
|
||||
close
|
||||
}
|
||||
@ -58,6 +58,14 @@ const MARKET_DATA_SUB = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const CANDLE_SUB = gql`
|
||||
subscription CandleLive($marketId: ID!) {
|
||||
candles(marketId: $marketId, interval: I1H) {
|
||||
close
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const update = (
|
||||
draft: SimpleMarkets_markets[],
|
||||
delta: SimpleMarketDataSub_marketData
|
||||
|
@ -1,15 +1,22 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import SimpleMarketList from './simple-market-list';
|
||||
import { MARKETS_QUERY } from './data-provider';
|
||||
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
||||
import type { SimpleMarkets } from './__generated__/SimpleMarkets';
|
||||
|
||||
jest.mock('./data-provider', () => jest.fn());
|
||||
const mockedNavigate = jest.fn();
|
||||
|
||||
jest.mock('@vegaprotocol/react-helpers', () => ({
|
||||
useDataProvider: jest.fn(),
|
||||
t: (txt: string) => txt,
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useNavigate: () => mockedNavigate,
|
||||
}));
|
||||
|
||||
jest.mock('date-fns', () => ({
|
||||
subDays: () => new Date('2022-06-02T11:11:21.721Z'),
|
||||
}));
|
||||
|
||||
describe('SimpleMarketList', () => {
|
||||
@ -17,16 +24,31 @@ describe('SimpleMarketList', () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should be properly renderer as empty', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(useDataProvider as unknown as jest.SpyInstance<any>).mockImplementation(
|
||||
() => ({ data: [], error: false, loading: false })
|
||||
it('should be properly renderer as empty', async () => {
|
||||
const mocks: MockedResponse<SimpleMarkets> = {
|
||||
request: {
|
||||
query: MARKETS_QUERY,
|
||||
variables: {
|
||||
CandleSince: '2022-06-02T11:11:21.721Z',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: { markets: [] },
|
||||
},
|
||||
};
|
||||
|
||||
render(
|
||||
<MockedProvider mocks={[mocks]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>
|
||||
);
|
||||
render(<SimpleMarketList />);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
expect(screen.getByText('No data to display')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should be properly rendered with some data', () => {
|
||||
it('should be properly rendered with some data', async () => {
|
||||
const data = [
|
||||
{
|
||||
id: '1',
|
||||
@ -69,11 +91,26 @@ describe('SimpleMarketList', () => {
|
||||
},
|
||||
},
|
||||
] as unknown as SimpleMarkets_markets[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(useDataProvider as unknown as jest.SpyInstance<any>).mockImplementation(
|
||||
() => ({ data, error: false, loading: false })
|
||||
|
||||
const mocks: MockedResponse<SimpleMarkets> = {
|
||||
request: {
|
||||
query: MARKETS_QUERY,
|
||||
variables: {
|
||||
CandleSince: '2022-06-02T11:11:21.721Z',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: { markets: data },
|
||||
},
|
||||
};
|
||||
render(
|
||||
<MockedProvider mocks={[mocks]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>
|
||||
);
|
||||
render(<SimpleMarketList />);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
expect(screen.getByRole('list')).toBeInTheDocument();
|
||||
expect(screen.getAllByRole('listitem')).toHaveLength(2);
|
||||
});
|
||||
|
@ -1,30 +1,55 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { subDays } from 'date-fns';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer, Lozenge, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import type { MarketState } from '@vegaprotocol/types';
|
||||
import SimpleMarketPercentChange from './simple-market-percent-change';
|
||||
import SimpleMarketExpires from './simple-market-expires';
|
||||
import DataProvider from './data-provider';
|
||||
import { MARKET_STATUS } from './constants';
|
||||
|
||||
const SimpleMarketList = () => {
|
||||
const navigate = useNavigate();
|
||||
const statusesRef = useRef<Record<string, MarketState | ''>>({});
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
CandleInterval: 'I1H',
|
||||
CandleSince: new Date(Date.now() - 24 * 60 * 60 * 1000).toJSON(),
|
||||
CandleSince: subDays(Date.now(), 1).toJSON(),
|
||||
}),
|
||||
[]
|
||||
);
|
||||
const update = useCallback(
|
||||
(delta) => {
|
||||
if (statusesRef.current[delta.market.id] !== delta.market.state) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[statusesRef]
|
||||
);
|
||||
|
||||
const { data, error, loading } = useDataProvider(
|
||||
DataProvider,
|
||||
undefined, // @TODO - if we need a live update in the future
|
||||
update,
|
||||
variables
|
||||
);
|
||||
const onClick = useCallback((marketId) => {
|
||||
// @TODO - let's try to have navigation first
|
||||
console.log('trigger market', marketId);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const statuses: Record<string, MarketState | ''> = {};
|
||||
data?.forEach((market) => {
|
||||
statuses[market.id] = market.data?.market.state || '';
|
||||
});
|
||||
statusesRef.current = statuses;
|
||||
}, [data]);
|
||||
|
||||
const onClick = useCallback(
|
||||
(marketId) => {
|
||||
navigate(`/trading/${marketId}`);
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
{data && data.length > 0 ? (
|
||||
@ -47,7 +72,10 @@ const SimpleMarketList = () => {
|
||||
</div>
|
||||
<div className="w-full grid sm:grid-rows-2">
|
||||
<div>
|
||||
<SimpleMarketPercentChange candles={market.candles} />
|
||||
<SimpleMarketPercentChange
|
||||
candles={market.candles}
|
||||
marketId={market.id}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Lozenge
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import SimpleMarketPercentChange from './simple-market-percent-change';
|
||||
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
|
||||
|
||||
@ -8,12 +9,20 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
let candles: (SimpleMarkets_markets_candles | null)[] | null;
|
||||
it('empty array', () => {
|
||||
candles = [];
|
||||
render(<SimpleMarketPercentChange candles={candles} />);
|
||||
render(
|
||||
<MockedProvider>
|
||||
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByText('-')).toBeInTheDocument();
|
||||
});
|
||||
it('null', () => {
|
||||
candles = null;
|
||||
render(<SimpleMarketPercentChange candles={candles} />);
|
||||
render(
|
||||
<MockedProvider>
|
||||
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByText('-')).toBeInTheDocument();
|
||||
});
|
||||
it('an appreciated one', () => {
|
||||
@ -22,7 +31,11 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
{ close: '100' } as SimpleMarkets_markets_candles,
|
||||
null,
|
||||
];
|
||||
render(<SimpleMarketPercentChange candles={candles} />);
|
||||
render(
|
||||
<MockedProvider>
|
||||
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByText('100.000%')).toBeInTheDocument();
|
||||
expect(screen.getByText('100.000%')).toHaveStyle(
|
||||
`color: ${theme.colors.vega.green}`
|
||||
@ -34,7 +47,11 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
{ close: '50' } as SimpleMarkets_markets_candles,
|
||||
null,
|
||||
];
|
||||
render(<SimpleMarketPercentChange candles={candles} />);
|
||||
render(
|
||||
<MockedProvider>
|
||||
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByText('-50.000%')).toBeInTheDocument();
|
||||
expect(screen.getByText('-50.000%')).toHaveStyle(
|
||||
`color: ${theme.colors.vega.pink}`
|
||||
|
@ -1,22 +1,34 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import { useSubscription } from '@apollo/client';
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
|
||||
import type {
|
||||
CandleLive,
|
||||
CandleLiveVariables,
|
||||
} from './__generated__/CandleLive';
|
||||
import { CANDLE_SUB } from './data-provider';
|
||||
|
||||
interface Props {
|
||||
candles: (SimpleMarkets_markets_candles | null)[] | null;
|
||||
marketId: string;
|
||||
}
|
||||
|
||||
const getChange = (
|
||||
candles: (SimpleMarkets_markets_candles | null)[] | null
|
||||
candles: (SimpleMarkets_markets_candles | null)[] | null,
|
||||
lastClose?: string
|
||||
) => {
|
||||
if (candles) {
|
||||
const first = parseInt(candles.find((item) => item?.open)?.open || '-1');
|
||||
const last = candles.reduceRight((aggr, item) => {
|
||||
const last =
|
||||
typeof lastClose === 'undefined'
|
||||
? candles.reduceRight((aggr, item) => {
|
||||
if (aggr === -1 && item?.close) {
|
||||
aggr = parseInt(item.close);
|
||||
}
|
||||
return aggr;
|
||||
}, -1);
|
||||
}, -1)
|
||||
: parseInt(lastClose);
|
||||
if (first !== -1 && last !== -1) {
|
||||
return Number(((last - first) / first) * 100).toFixed(3) + '%';
|
||||
}
|
||||
@ -34,10 +46,25 @@ const getColor = (change: number | string) => {
|
||||
return theme.colors.intent.highlight;
|
||||
};
|
||||
|
||||
const SimpleMarketPercentChange = ({ candles }: Props) => {
|
||||
const change = getChange(candles);
|
||||
const SimpleMarketPercentChangeWrapper = (props: Props) => {
|
||||
const [inView, setInView] = useState(false);
|
||||
|
||||
return (
|
||||
// @ts-ignore falsy wrong type?
|
||||
<InView onChange={setInView}>
|
||||
{inView && <SimpleMarketPercentChange {...props} />}
|
||||
</InView>
|
||||
);
|
||||
};
|
||||
|
||||
const SimpleMarketPercentChange = ({ candles, marketId }: Props) => {
|
||||
const { data: { candles: { close = undefined } = {} } = {} } =
|
||||
useSubscription<CandleLive, CandleLiveVariables>(CANDLE_SUB, {
|
||||
variables: { marketId },
|
||||
});
|
||||
const change = getChange(candles, close);
|
||||
const color = getColor(change);
|
||||
return <p style={{ color }}>{change}</p>;
|
||||
};
|
||||
|
||||
export default SimpleMarketPercentChange;
|
||||
export default SimpleMarketPercentChangeWrapper;
|
||||
|
@ -1,6 +1,15 @@
|
||||
import { ApolloClient, from, HttpLink, InMemoryCache } from '@apollo/client';
|
||||
import {
|
||||
ApolloClient,
|
||||
from,
|
||||
HttpLink,
|
||||
InMemoryCache,
|
||||
split,
|
||||
} from '@apollo/client';
|
||||
import { onError } from '@apollo/client/link/error';
|
||||
import { RetryLink } from '@apollo/client/link/retry';
|
||||
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
|
||||
import { createClient as createWSClient } from 'graphql-ws';
|
||||
import { getMainDefinition } from '@apollo/client/utilities';
|
||||
|
||||
export function createClient(base?: string) {
|
||||
if (!base) {
|
||||
@ -40,6 +49,24 @@ export function createClient(base?: string) {
|
||||
credentials: 'same-origin',
|
||||
});
|
||||
|
||||
const wsLink = new GraphQLWsLink(
|
||||
createWSClient({
|
||||
url: urlWS.href,
|
||||
})
|
||||
);
|
||||
|
||||
const splitLink = split(
|
||||
({ query }) => {
|
||||
const definition = getMainDefinition(query);
|
||||
return (
|
||||
definition.kind === 'OperationDefinition' &&
|
||||
definition.operation === 'subscription'
|
||||
);
|
||||
},
|
||||
wsLink,
|
||||
httpLink
|
||||
);
|
||||
|
||||
const errorLink = onError(({ graphQLErrors, networkError }) => {
|
||||
console.log(graphQLErrors);
|
||||
console.log(networkError);
|
||||
@ -47,7 +74,7 @@ export function createClient(base?: string) {
|
||||
|
||||
return new ApolloClient({
|
||||
connectToDevTools: process.env['NODE_ENV'] === 'development',
|
||||
link: from([errorLink, retryLink, httpLink]),
|
||||
link: from([errorLink, retryLink, splitLink]),
|
||||
cache,
|
||||
});
|
||||
}
|
||||
|
@ -28,13 +28,13 @@ export const routerConfig = [
|
||||
path: ROUTES.TRADING,
|
||||
name: 'Trading',
|
||||
text: t('Trading'),
|
||||
element: (
|
||||
<DealTicketContainer
|
||||
marketId={
|
||||
'41013c28d53a72225c07cf2660cdd415d9dd0e9317ec4574e77592332db35596'
|
||||
}
|
||||
/>
|
||||
),
|
||||
element: <DealTicketContainer />,
|
||||
children: [
|
||||
{
|
||||
path: ':marketId',
|
||||
element: <DealTicketContainer />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: ROUTES.LIQUIDITY,
|
||||
|
@ -38,7 +38,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "129999.45",
|
||||
"locked_amount": "129682.36162978697785023",
|
||||
"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": "71359.360754532949904994",
|
||||
"locked_amount": "70428.517923311130372024",
|
||||
"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": "97535.92647176062142134244004",
|
||||
"locked_amount": "96263.62502479102429967123688",
|
||||
"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": "30019.65075918605161088",
|
||||
"locked_amount": "29628.061254886910252894",
|
||||
"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": "9771.105018319376583514",
|
||||
"locked_amount": "9643.646434564611031407",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@ -675,7 +675,7 @@
|
||||
"tranche_end": "2022-11-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "18545.82059556159525",
|
||||
"locked_amount": "18056.6590240036215",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "15000",
|
||||
@ -761,7 +761,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1938140.454506446441067284",
|
||||
"locked_amount": "1916879.612086597542469696",
|
||||
"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": "17568.575895506846757997",
|
||||
"locked_amount": "18691.0451412597139137896684208311",
|
||||
"total_removed": "17896.108295511846757997",
|
||||
"locked_amount": "18066.219044199191697914984957962",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2833.333333",
|
||||
@ -1876,6 +1876,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "327.532400005",
|
||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||
"tx": "0x6002d50af16df494528c32126c3cb569f105ee8118a3f48a34e8883037132198"
|
||||
},
|
||||
{
|
||||
"amount": "490.9767850775",
|
||||
"user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||
@ -2493,6 +2498,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "327.532400005",
|
||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||
"tranche_id": 13,
|
||||
"tx": "0x6002d50af16df494528c32126c3cb569f105ee8118a3f48a34e8883037132198"
|
||||
},
|
||||
{
|
||||
"amount": "327.7316817825",
|
||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||
@ -2555,8 +2566,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "4250",
|
||||
"withdrawn_tokens": "2653.6331018125",
|
||||
"remaining_tokens": "1596.3668981875"
|
||||
"withdrawn_tokens": "2981.1655018175",
|
||||
"remaining_tokens": "1268.8344981825"
|
||||
},
|
||||
{
|
||||
"address": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||
@ -5040,8 +5051,8 @@
|
||||
"tranche_start": "2021-09-03T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-03T00:00:00.000Z",
|
||||
"total_added": "15073.000000000000000003",
|
||||
"total_removed": "2897.73152892253",
|
||||
"locked_amount": "3826.6258515664639083007616186263318113",
|
||||
"total_removed": "2905.98379934253",
|
||||
"locked_amount": "3661.43177476534672755072873982115677305",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10",
|
||||
@ -7685,6 +7696,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "8.25227042",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
"tx": "0xce562db43fe92ccd76b20c462f4f680336542c064020dfb646512994c4f229d9"
|
||||
},
|
||||
{
|
||||
"amount": "7.42538686",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
@ -12837,6 +12853,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "8.25227042",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xce562db43fe92ccd76b20c462f4f680336542c064020dfb646512994c4f229d9"
|
||||
},
|
||||
{
|
||||
"amount": "7.42538686",
|
||||
"user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
|
||||
@ -12881,8 +12903,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200",
|
||||
"withdrawn_tokens": "142.68559107",
|
||||
"remaining_tokens": "57.31440893"
|
||||
"withdrawn_tokens": "150.93786149",
|
||||
"remaining_tokens": "49.06213851"
|
||||
},
|
||||
{
|
||||
"address": "0x1775cc97E5c05Fde8b571ef75CA52d0A9ff19025",
|
||||
@ -12907,7 +12929,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "74162.9780761646031",
|
||||
"locked_amount": "3002748.41446940756547250008",
|
||||
"locked_amount": "2970077.9019092314063579103",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@ -13620,7 +13642,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15788853.065470999700000001",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "15788853.065470999700000001",
|
||||
"locked_amount": "15750341.6587991785653755639256064283711814",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@ -15571,8 +15593,8 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "1563001.535509480008878233",
|
||||
"locked_amount": "9000945.53475187470322777308704175",
|
||||
"total_removed": "2039274.435730582717034572",
|
||||
"locked_amount": "8893995.82561804098467636432418579",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@ -15781,6 +15803,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "652.48254356494551875",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x4a972ce40877c56aaa0fb53f479666723bf6a89ea9df5a18ffeffb2580d416d4"
|
||||
},
|
||||
{
|
||||
"amount": "1384.357697656285885",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@ -15916,6 +15943,26 @@
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x3f1666dc9c401996a37b4543b7945d14f6d66561cd1d0a84caa30b92fc55408e"
|
||||
},
|
||||
{
|
||||
"amount": "755.451613460173812",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x41ce3e549c72e49df5ebe782512c14113e7df9258c9d4c8bccd2dcb654fbb898"
|
||||
},
|
||||
{
|
||||
"amount": "31474.290919355234375",
|
||||
"user": "0xDdc5F6484349B242A9B23382Aa21f49B5Dc9a089",
|
||||
"tx": "0x34be40dc6242c39c9fefcebcdf7f09167297c0a3e099e9b76428758a9953fd48"
|
||||
},
|
||||
{
|
||||
"amount": "442758.921918885747690339",
|
||||
"user": "0xa8679b60612Fb2e19d68964326CA02dCe6a08D08",
|
||||
"tx": "0x232e5795842832a7105c1e8cff4125da02020c1b348758998f06d71fbd674a9d"
|
||||
},
|
||||
{
|
||||
"amount": "631.75322583660676025",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x9d31de2586ae4a6ce3525a15347349febfd085aa6e202b9641621e12e58909e2"
|
||||
},
|
||||
{
|
||||
"amount": "58127.81687116447134108",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
@ -17237,6 +17284,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "652.48254356494551875",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x4a972ce40877c56aaa0fb53f479666723bf6a89ea9df5a18ffeffb2580d416d4"
|
||||
},
|
||||
{
|
||||
"amount": "1384.357697656285885",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@ -17327,6 +17380,18 @@
|
||||
"tranche_id": 3,
|
||||
"tx": "0x3f1666dc9c401996a37b4543b7945d14f6d66561cd1d0a84caa30b92fc55408e"
|
||||
},
|
||||
{
|
||||
"amount": "755.451613460173812",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x41ce3e549c72e49df5ebe782512c14113e7df9258c9d4c8bccd2dcb654fbb898"
|
||||
},
|
||||
{
|
||||
"amount": "631.75322583660676025",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x9d31de2586ae4a6ce3525a15347349febfd085aa6e202b9641621e12e58909e2"
|
||||
},
|
||||
{
|
||||
"amount": "673.86655774325828525",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@ -18349,8 +18414,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "359123.469575",
|
||||
"withdrawn_tokens": "136988.021403105210273",
|
||||
"remaining_tokens": "222135.448171894789727"
|
||||
"withdrawn_tokens": "139027.708785966936364",
|
||||
"remaining_tokens": "220095.760789033063636"
|
||||
},
|
||||
{
|
||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||
@ -18795,6 +18860,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "31474.290919355234375",
|
||||
"user": "0xDdc5F6484349B242A9B23382Aa21f49B5Dc9a089",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x34be40dc6242c39c9fefcebcdf7f09167297c0a3e099e9b76428758a9953fd48"
|
||||
},
|
||||
{
|
||||
"amount": "250551.564697895841552119",
|
||||
"user": "0xDdc5F6484349B242A9B23382Aa21f49B5Dc9a089",
|
||||
@ -18809,8 +18880,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "805741.847535494",
|
||||
"withdrawn_tokens": "278425.719380526241012802",
|
||||
"remaining_tokens": "527316.128154967758987198"
|
||||
"withdrawn_tokens": "309900.010299881475387802",
|
||||
"remaining_tokens": "495841.837235612524612198"
|
||||
},
|
||||
{
|
||||
"address": "0x47FbE34Fd93416c63d35544dEE6c6f442Db8513d",
|
||||
@ -19068,10 +19139,17 @@
|
||||
"tx": "0xff922daf92e19ea138491989d06d76cc4e92011c1cbf2b83e3caebe7179594fb"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "442758.921918885747690339",
|
||||
"user": "0xa8679b60612Fb2e19d68964326CA02dCe6a08D08",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x232e5795842832a7105c1e8cff4125da02020c1b348758998f06d71fbd674a9d"
|
||||
}
|
||||
],
|
||||
"total_tokens": "1151073.5946347",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "1151073.5946347"
|
||||
"withdrawn_tokens": "442758.921918885747690339",
|
||||
"remaining_tokens": "708314.672715814252309661"
|
||||
},
|
||||
{
|
||||
"address": "0x97E5985117F47c8d110Be1c422DdCB9bE9b46e62",
|
||||
@ -19321,8 +19399,8 @@
|
||||
"tranche_start": "2021-10-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "1292362.811321297942666742",
|
||||
"locked_amount": "3239424.61450565009103150955191263",
|
||||
"total_removed": "1341050.833974497576969742",
|
||||
"locked_amount": "3197168.13760041683379941673182373",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@ -19486,6 +19564,11 @@
|
||||
"user": "0xdbC5d439F373EB646345e1c67D1d46231ACE7dD3",
|
||||
"tx": "0x8e9f65bfea45a61e4f20108bc0ad1ce2bdeba8e355c7b1d4e024a3ffd73065a4"
|
||||
},
|
||||
{
|
||||
"amount": "48688.022653199634303",
|
||||
"user": "0xa8679b60612Fb2e19d68964326CA02dCe6a08D08",
|
||||
"tx": "0xd6949910fc00a00de948bf09b7d8d294d0bda6f50c960432679cfd18bd15cd18"
|
||||
},
|
||||
{
|
||||
"amount": "7013.412182841867109",
|
||||
"user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
|
||||
@ -19753,10 +19836,17 @@
|
||||
"tx": "0x9d3432b818054796489848c415af5c523acb16c1540e5865010baf71964c03a7"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "48688.022653199634303",
|
||||
"user": "0xa8679b60612Fb2e19d68964326CA02dCe6a08D08",
|
||||
"tranche_id": 4,
|
||||
"tx": "0xd6949910fc00a00de948bf09b7d8d294d0bda6f50c960432679cfd18bd15cd18"
|
||||
}
|
||||
],
|
||||
"total_tokens": "110499.5291",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "110499.5291"
|
||||
"withdrawn_tokens": "48688.022653199634303",
|
||||
"remaining_tokens": "61811.506446800365697"
|
||||
},
|
||||
{
|
||||
"address": "0x8767d65677CabaD2050b764AEf40610f2f9796F5",
|
||||
@ -20366,7 +20456,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "472355.6199999996",
|
||||
"locked_amount": "470625.82124660851890028549873164",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@ -46019,8 +46109,8 @@
|
||||
"tranche_start": "2021-12-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-06-05T00:00:00.000Z",
|
||||
"total_added": "171288.42",
|
||||
"total_removed": "17067.9263679026803",
|
||||
"locked_amount": "2506.83382533958609789446",
|
||||
"total_removed": "20783.0438075488377",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "250",
|
||||
@ -50244,6 +50334,116 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "183.6335597275",
|
||||
"user": "0x690Fc36d52eD3f198F0eBDea1557333a1766f786",
|
||||
"tx": "0xba954a4d4b886c981f4965fe7da9c29120a6f1b44c4ce73a94bd7f2eff690434"
|
||||
},
|
||||
{
|
||||
"amount": "183.6407458275",
|
||||
"user": "0xb7f112a2Ff7984Ef494E87b2539059d77d500f37",
|
||||
"tx": "0x66ecf2cabcc78741ac276ace894a5d203475284a7dbaa3df624dd9765b5e34f8"
|
||||
},
|
||||
{
|
||||
"amount": "183.6396170375",
|
||||
"user": "0x391484aff3906c940325C63Cf69dC5509710eA6a",
|
||||
"tx": "0x70e570adefd4935fcf33ef02e007a3f584a55def453b8d3cddba657e21858af5"
|
||||
},
|
||||
{
|
||||
"amount": "249.9983783575",
|
||||
"user": "0xf0352681BcDBA8296b716d4EE085C27433Fff690",
|
||||
"tx": "0x65af2b3830875fac6eddb4ccdbaa62a6a43c9be071af5c4a201742704141e388"
|
||||
},
|
||||
{
|
||||
"amount": "34.2757777525",
|
||||
"user": "0x967C162B564c83A30509CB77e572A98e1150a9D3",
|
||||
"tx": "0x41d9be48e1130b253b786db21c3d6f8ab169114251b3a3866ce6e2d4ef1870e0"
|
||||
},
|
||||
{
|
||||
"amount": "23.0332214085",
|
||||
"user": "0x8433BF349d4f71FB37c8CacF5D6D4863D43EaE23",
|
||||
"tx": "0xf55524a47a3b15876ef7965636d7caff9a0bb11566f359998bf4c79afad22673"
|
||||
},
|
||||
{
|
||||
"amount": "46.069991352",
|
||||
"user": "0x2814A08930732406a99139B6856001023239F9Dd",
|
||||
"tx": "0xa047a1c664e5c65286e3e4470d85497376315623a6be3c7f9289d1484d2209dc"
|
||||
},
|
||||
{
|
||||
"amount": "120",
|
||||
"user": "0xA301F00b655a45D454747B4b8fb3dcEFD8C4D66f",
|
||||
"tx": "0x7f3a81b45debc735d8c383ed438f92627b2f2a3021b92ffc3db4c6d8261f28f2"
|
||||
},
|
||||
{
|
||||
"amount": "25.40420228",
|
||||
"user": "0xfeF4b56A370135A17Eef5ba8f5c308451a64Cf86",
|
||||
"tx": "0x6ecd654e1aeecdcc7073e1ec881b5b0fe4e24df9e9e226470aa35671e5c0be29"
|
||||
},
|
||||
{
|
||||
"amount": "157.270935085",
|
||||
"user": "0x2740029049CF5d991202DeEd75965C6F34Aa36B9",
|
||||
"tx": "0xe613bfdfe6d2dbbff73e7089139458b2d905150649739392e067a652d3226557"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x7b82f39c7AC83442EE6b025D5B69b4A49E6FD168",
|
||||
"tx": "0xffcba1d72b13cb6fe9c5cf269b956cf55d54367d1dbb2d48ba6c03a2b94e9434"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x02B5Fd5A74367D192b807Da32EaF1adF5E683573",
|
||||
"tx": "0xc833bf14e1891f661410ddafd4f97f009f63d4ac2ca906d19c74cf2223ff430a"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xBD352479242D160FaEeFB21422786C5B201A1cEc",
|
||||
"tx": "0x90a9ff32dac087d7f7a7050ee67a9fdf3fe2cc2dacf5f1e900dac53b9741fd68"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x9b427a2EA3536FbFcD37E48c9EC798ea11E2Ec87",
|
||||
"tx": "0xe5355d8976bf4d26018fea411fb0f01cbc1c43ebda8ad48970df81ae1ef7e8d6"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xe87aE24a4bE0158f25DFC6733c48177C86998B6F",
|
||||
"tx": "0x98625ddb4f277e915fd5478dc6f97b22ec9793a668bba209c9c82805da44f403"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x5417806fA87Be7F9bA7aEf4FFB9277E8922Fd9BE",
|
||||
"tx": "0x1c8ed1ce8127a594747ae20827659e12715af4dae9f855a8b641c1b35412b8a3"
|
||||
},
|
||||
{
|
||||
"amount": "0.0016216425",
|
||||
"user": "0xf0352681BcDBA8296b716d4EE085C27433Fff690",
|
||||
"tx": "0xbe02347c087aaed316855eca5a01116fc178087524e3e1885d20c0b119a2af2a"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xD1C87a90455f2765bE275c506738C026B011a6C8",
|
||||
"tx": "0xf19508bf8446e4c1bf9cf879df87087a3c0ee57a175ecae7a75e4a6442c08270"
|
||||
},
|
||||
{
|
||||
"amount": "150",
|
||||
"user": "0x92f15CBCE433FDcA0a87FD778e5BBbD0B3d7eE0f",
|
||||
"tx": "0x2638a870214b1d904c8e8e80cf35d4bc1b382801b9c16239af41ca2cf06a1654"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xc8aC50a6BA786450676f278Aa716Eb2bA7249B22",
|
||||
"tx": "0x91d6f0ea8c0c19d00a1c08a53fdf7e839a35fce2c3a80ce993f058c0b4ae9cac"
|
||||
},
|
||||
{
|
||||
"amount": "29.9837040875",
|
||||
"user": "0xF047Ee0434548d5E2cA1F080ba6208A22C97d290",
|
||||
"tx": "0xe2885fb42ec26c0d8964c772f19eff356947add7b0b44f1cb7a3d49c0fdc830b"
|
||||
},
|
||||
{
|
||||
"amount": "64.1735506975",
|
||||
"user": "0xe8F33102aDD808E841268E4161326C76A3D31d24",
|
||||
"tx": "0xaf108d45b68929af7d63e571bf6f4d9d2415437c95470d70d70786398aa192ab"
|
||||
},
|
||||
{
|
||||
"amount": "65.56208982",
|
||||
"user": "0x36d345DCEB35816AD557355fA51E7C99FEE7d18E",
|
||||
@ -50339,6 +50539,16 @@
|
||||
"user": "0x27049a430Df8b89Ae4f899b0383B0C876F9cAcEb",
|
||||
"tx": "0x2dadd46cff92cdcb974ba556776f69b136a526e05391e07618503526ef3667e0"
|
||||
},
|
||||
{
|
||||
"amount": "17.2834799106574",
|
||||
"user": "0x34D4Da6a0829607fFAb8C0aFfDf6aBe059d89b86",
|
||||
"tx": "0x9d5a7c722b96c3a94457ca95d2152c3decdaf3ae89634a7503b0ff1e131d2960"
|
||||
},
|
||||
{
|
||||
"amount": "246.70865448",
|
||||
"user": "0x00Ddf1483dEc8E5A38D0fFE78b6C14D0954D255e",
|
||||
"tx": "0xd1c9e882269eee55b067744c783ed78b875c7f3602bac5e8ed0e7c0b1fe623e6"
|
||||
},
|
||||
{
|
||||
"amount": "252.08931115",
|
||||
"user": "0xE245503f8a33eBDDD718915132869C9Ba9df37A8",
|
||||
@ -51691,10 +51901,17 @@
|
||||
"tx": "0xee02e72ef8e0755982704385da512cc12c8ff0ea7b58056fa3d5a5932394e9ca"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xD1C87a90455f2765bE275c506738C026B011a6C8",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xf19508bf8446e4c1bf9cf879df87087a3c0ee57a175ecae7a75e4a6442c08270"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x3A7983a6e8AaC25E5DeB6Bf1D0F21c8b8a17D1a6",
|
||||
@ -54263,6 +54480,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "183.6335597275",
|
||||
"user": "0x690Fc36d52eD3f198F0eBDea1557333a1766f786",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xba954a4d4b886c981f4965fe7da9c29120a6f1b44c4ce73a94bd7f2eff690434"
|
||||
},
|
||||
{
|
||||
"amount": "66.325088395",
|
||||
"user": "0x690Fc36d52eD3f198F0eBDea1557333a1766f786",
|
||||
@ -54271,8 +54494,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "66.325088395",
|
||||
"remaining_tokens": "183.674911605"
|
||||
"withdrawn_tokens": "249.9586481225",
|
||||
"remaining_tokens": "0.0413518775"
|
||||
},
|
||||
{
|
||||
"address": "0x391484aff3906c940325C63Cf69dC5509710eA6a",
|
||||
@ -54285,6 +54508,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "183.6396170375",
|
||||
"user": "0x391484aff3906c940325C63Cf69dC5509710eA6a",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x70e570adefd4935fcf33ef02e007a3f584a55def453b8d3cddba657e21858af5"
|
||||
},
|
||||
{
|
||||
"amount": "66.3216225325",
|
||||
"user": "0x391484aff3906c940325C63Cf69dC5509710eA6a",
|
||||
@ -54293,8 +54522,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "66.3216225325",
|
||||
"remaining_tokens": "183.6783774675"
|
||||
"withdrawn_tokens": "249.96123957",
|
||||
"remaining_tokens": "0.03876043"
|
||||
},
|
||||
{
|
||||
"address": "0xb7f112a2Ff7984Ef494E87b2539059d77d500f37",
|
||||
@ -54307,6 +54536,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "183.6407458275",
|
||||
"user": "0xb7f112a2Ff7984Ef494E87b2539059d77d500f37",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x66ecf2cabcc78741ac276ace894a5d203475284a7dbaa3df624dd9765b5e34f8"
|
||||
},
|
||||
{
|
||||
"amount": "66.3197624125",
|
||||
"user": "0xb7f112a2Ff7984Ef494E87b2539059d77d500f37",
|
||||
@ -54315,8 +54550,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "66.3197624125",
|
||||
"remaining_tokens": "183.6802375875"
|
||||
"withdrawn_tokens": "249.96050824",
|
||||
"remaining_tokens": "0.03949176"
|
||||
},
|
||||
{
|
||||
"address": "0x967C162B564c83A30509CB77e572A98e1150a9D3",
|
||||
@ -54329,6 +54564,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "34.2757777525",
|
||||
"user": "0x967C162B564c83A30509CB77e572A98e1150a9D3",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x41d9be48e1130b253b786db21c3d6f8ab169114251b3a3866ce6e2d4ef1870e0"
|
||||
},
|
||||
{
|
||||
"amount": "53.1604376525",
|
||||
"user": "0x967C162B564c83A30509CB77e572A98e1150a9D3",
|
||||
@ -54367,8 +54608,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "215.7242222475",
|
||||
"remaining_tokens": "34.2757777525"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xC9ce3264ac5d3Ff850744043c8F3f87899c1a1D2",
|
||||
@ -54598,6 +54839,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "157.270935085",
|
||||
"user": "0x2740029049CF5d991202DeEd75965C6F34Aa36B9",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xe613bfdfe6d2dbbff73e7089139458b2d905150649739392e067a652d3226557"
|
||||
},
|
||||
{
|
||||
"amount": "92.729064915",
|
||||
"user": "0x2740029049CF5d991202DeEd75965C6F34Aa36B9",
|
||||
@ -54606,8 +54853,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "92.729064915",
|
||||
"remaining_tokens": "157.270935085"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x573bd9385a35708C24478A385B2Cac38F2a247D3",
|
||||
@ -55369,6 +55616,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "25.40420228",
|
||||
"user": "0xfeF4b56A370135A17Eef5ba8f5c308451a64Cf86",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x6ecd654e1aeecdcc7073e1ec881b5b0fe4e24df9e9e226470aa35671e5c0be29"
|
||||
},
|
||||
{
|
||||
"amount": "41.18821861",
|
||||
"user": "0xfeF4b56A370135A17Eef5ba8f5c308451a64Cf86",
|
||||
@ -55395,8 +55648,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "224.59579772",
|
||||
"remaining_tokens": "25.40420228"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xA8D108c6e91f16CEecDAC9d0230946D02D98d931",
|
||||
@ -56906,10 +57159,17 @@
|
||||
"tx": "0x057f65938b1360b6d2c4ebf5e789c67897cf60cb6a13f947004def03891afbd8"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xe87aE24a4bE0158f25DFC6733c48177C86998B6F",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x98625ddb4f277e915fd5478dc6f97b22ec9793a668bba209c9c82805da44f403"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x2735b9c217291c3FAa42FDF4bb130b504AAf4f9D",
|
||||
@ -57768,6 +58028,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "17.2834799106574",
|
||||
"user": "0x34D4Da6a0829607fFAb8C0aFfDf6aBe059d89b86",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x9d5a7c722b96c3a94457ca95d2152c3decdaf3ae89634a7503b0ff1e131d2960"
|
||||
},
|
||||
{
|
||||
"amount": "21.9796154290108",
|
||||
"user": "0x34D4Da6a0829607fFAb8C0aFfDf6aBe059d89b86",
|
||||
@ -57776,8 +58042,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "39.82",
|
||||
"withdrawn_tokens": "21.9796154290108",
|
||||
"remaining_tokens": "17.8403845709892"
|
||||
"withdrawn_tokens": "39.2630953396682",
|
||||
"remaining_tokens": "0.5569046603318"
|
||||
},
|
||||
{
|
||||
"address": "0xd2FeED64D23115162723F1BBd97770190a1f4ffB",
|
||||
@ -59852,10 +60118,17 @@
|
||||
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x7b82f39c7AC83442EE6b025D5B69b4A49E6FD168",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xffcba1d72b13cb6fe9c5cf269b956cf55d54367d1dbb2d48ba6c03a2b94e9434"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x645c8D7Bc67b6c1E17d1dCA6621972ce50F3b373",
|
||||
@ -60167,10 +60440,17 @@
|
||||
"tx": "0x9f916cf09e8a3c4ade0ffce5190db464d0a2b1dadba78e1ee7ba5d6e751d6148"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xc8aC50a6BA786450676f278Aa716Eb2bA7249B22",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x91d6f0ea8c0c19d00a1c08a53fdf7e839a35fce2c3a80ce993f058c0b4ae9cac"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x92f15CBCE433FDcA0a87FD778e5BBbD0B3d7eE0f",
|
||||
@ -60182,10 +60462,17 @@
|
||||
"tx": "0x9f916cf09e8a3c4ade0ffce5190db464d0a2b1dadba78e1ee7ba5d6e751d6148"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "150",
|
||||
"user": "0x92f15CBCE433FDcA0a87FD778e5BBbD0B3d7eE0f",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x2638a870214b1d904c8e8e80cf35d4bc1b382801b9c16239af41ca2cf06a1654"
|
||||
}
|
||||
],
|
||||
"total_tokens": "150",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "150"
|
||||
"withdrawn_tokens": "150",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x0e80E23fa0ae15A06Ad986792F02625f80955E6E",
|
||||
@ -60309,6 +60596,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "46.069991352",
|
||||
"user": "0x2814A08930732406a99139B6856001023239F9Dd",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xa047a1c664e5c65286e3e4470d85497376315623a6be3c7f9289d1484d2209dc"
|
||||
},
|
||||
{
|
||||
"amount": "18.472387566",
|
||||
"user": "0x2814A08930732406a99139B6856001023239F9Dd",
|
||||
@ -60323,8 +60616,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "100",
|
||||
"withdrawn_tokens": "53.930008648",
|
||||
"remaining_tokens": "46.069991352"
|
||||
"withdrawn_tokens": "100",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xdE6b94C3a927FF6c5b4E4C53556b155C6A7b1d94",
|
||||
@ -60367,6 +60660,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "23.0332214085",
|
||||
"user": "0x8433BF349d4f71FB37c8CacF5D6D4863D43EaE23",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xf55524a47a3b15876ef7965636d7caff9a0bb11566f359998bf4c79afad22673"
|
||||
},
|
||||
{
|
||||
"amount": "26.9667785915",
|
||||
"user": "0x8433BF349d4f71FB37c8CacF5D6D4863D43EaE23",
|
||||
@ -60375,8 +60674,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "50",
|
||||
"withdrawn_tokens": "26.9667785915",
|
||||
"remaining_tokens": "23.0332214085"
|
||||
"withdrawn_tokens": "50",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xaD8a77d52Dd1E2dDD364AfE960DF49CAe1124C6D",
|
||||
@ -61809,10 +62108,23 @@
|
||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "249.9983783575",
|
||||
"user": "0xf0352681BcDBA8296b716d4EE085C27433Fff690",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x65af2b3830875fac6eddb4ccdbaa62a6a43c9be071af5c4a201742704141e388"
|
||||
},
|
||||
{
|
||||
"amount": "0.0016216425",
|
||||
"user": "0xf0352681BcDBA8296b716d4EE085C27433Fff690",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xbe02347c087aaed316855eca5a01116fc178087524e3e1885d20c0b119a2af2a"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x7D3e0aC6aB823fC1757B2B0F929c06BE155339Ae",
|
||||
@ -62086,10 +62398,17 @@
|
||||
"tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "246.70865448",
|
||||
"user": "0x00Ddf1483dEc8E5A38D0fFE78b6C14D0954D255e",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xd1c9e882269eee55b067744c783ed78b875c7f3602bac5e8ed0e7c0b1fe623e6"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "246.70865448",
|
||||
"remaining_tokens": "3.29134552"
|
||||
},
|
||||
{
|
||||
"address": "0xe2A2F60ed248CDE54Fc2e3f5d4c00fDf3138CbBB",
|
||||
@ -62676,6 +62995,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "29.9837040875",
|
||||
"user": "0xF047Ee0434548d5E2cA1F080ba6208A22C97d290",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xe2885fb42ec26c0d8964c772f19eff356947add7b0b44f1cb7a3d49c0fdc830b"
|
||||
},
|
||||
{
|
||||
"amount": "220.0162959125",
|
||||
"user": "0xF047Ee0434548d5E2cA1F080ba6208A22C97d290",
|
||||
@ -62684,8 +63009,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "220.0162959125",
|
||||
"remaining_tokens": "29.9837040875"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xd7DDc95Ac6FEe7069e913218545b7D6Fdfea0E05",
|
||||
@ -62896,10 +63221,17 @@
|
||||
"tx": "0xc8541da6a57f410b6faba47a5e5184bae700193b7bd042914fffc562114d92f5"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x5417806fA87Be7F9bA7aEf4FFB9277E8922Fd9BE",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x1c8ed1ce8127a594747ae20827659e12715af4dae9f855a8b641c1b35412b8a3"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x9b427a2EA3536FbFcD37E48c9EC798ea11E2Ec87",
|
||||
@ -62911,10 +63243,17 @@
|
||||
"tx": "0xc8541da6a57f410b6faba47a5e5184bae700193b7bd042914fffc562114d92f5"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x9b427a2EA3536FbFcD37E48c9EC798ea11E2Ec87",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xe5355d8976bf4d26018fea411fb0f01cbc1c43ebda8ad48970df81ae1ef7e8d6"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xBD352479242D160FaEeFB21422786C5B201A1cEc",
|
||||
@ -62926,10 +63265,17 @@
|
||||
"tx": "0xc8541da6a57f410b6faba47a5e5184bae700193b7bd042914fffc562114d92f5"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0xBD352479242D160FaEeFB21422786C5B201A1cEc",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x90a9ff32dac087d7f7a7050ee67a9fdf3fe2cc2dacf5f1e900dac53b9741fd68"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x1D92cb812FdeDF1a5aFE3c5080B2D3Ec102694c6",
|
||||
@ -62956,10 +63302,17 @@
|
||||
"tx": "0xc8541da6a57f410b6faba47a5e5184bae700193b7bd042914fffc562114d92f5"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x02B5Fd5A74367D192b807Da32EaF1adF5E683573",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xc833bf14e1891f661410ddafd4f97f009f63d4ac2ca906d19c74cf2223ff430a"
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "250"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xc008A0b1DF32d27A7283c199a7F2a92266029079",
|
||||
@ -63655,6 +64008,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "64.1735506975",
|
||||
"user": "0xe8F33102aDD808E841268E4161326C76A3D31d24",
|
||||
"tranche_id": 6,
|
||||
"tx": "0xaf108d45b68929af7d63e571bf6f4d9d2415437c95470d70d70786398aa192ab"
|
||||
},
|
||||
{
|
||||
"amount": "25.4253631225",
|
||||
"user": "0xe8F33102aDD808E841268E4161326C76A3D31d24",
|
||||
@ -63681,8 +64040,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "185.8264493025",
|
||||
"remaining_tokens": "64.1735506975"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x57E427ad38383A4A97D0CC4c3Cc4bb9187ec3A00",
|
||||
@ -63857,10 +64216,17 @@
|
||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "120",
|
||||
"user": "0xA301F00b655a45D454747B4b8fb3dcEFD8C4D66f",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x7f3a81b45debc735d8c383ed438f92627b2f2a3021b92ffc3db4c6d8261f28f2"
|
||||
}
|
||||
],
|
||||
"total_tokens": "120",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "120"
|
||||
"withdrawn_tokens": "120",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x075A6AF774C9Ef7315879231730916ceD13e84f8",
|
||||
|
@ -38,7 +38,7 @@
|
||||
"tranche_end": "2022-11-26T13:48:10.000Z",
|
||||
"total_added": "100",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "48.558558472856417",
|
||||
"locked_amount": "47.46261732623034",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "100",
|
||||
@ -242,7 +242,7 @@
|
||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||
"total_added": "100",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "36.08237252663623",
|
||||
"locked_amount": "34.98643138001015",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "100",
|
||||
|
@ -78,18 +78,51 @@
|
||||
"tranche_id": 3,
|
||||
"tranche_start": "2021-05-15T09:09:30.000Z",
|
||||
"tranche_end": "2022-05-15T09:09:30.000Z",
|
||||
"total_added": "10000",
|
||||
"total_removed": "0",
|
||||
"total_added": "10000.0000000000000005",
|
||||
"total_removed": "5e-16",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5e-16",
|
||||
"user": "0x72c22822A19D20DE7e426fB84aa047399Ddd8853",
|
||||
"tx": "0xe8f875e4c7e291676d4de38b40ac75cdb7ae23c3cbfc389152a67d25e557a632"
|
||||
},
|
||||
{
|
||||
"amount": "10000",
|
||||
"user": "0x1FF32F8A5895DAcdcC0Fe8bC6dDAa7D2c7717f3e",
|
||||
"tx": "0x085994c06447bb8ed4b305a5fa5485e38e34b0347a40ee4a66233c8151fac0be"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "5e-16",
|
||||
"user": "0x72c22822A19D20DE7e426fB84aa047399Ddd8853",
|
||||
"tx": "0x454b4116649ee74c7fb6223ffe0d475128fdd8a5b9dca14a9ad3def605abd38c"
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"address": "0x72c22822A19D20DE7e426fB84aa047399Ddd8853",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5e-16",
|
||||
"user": "0x72c22822A19D20DE7e426fB84aa047399Ddd8853",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xe8f875e4c7e291676d4de38b40ac75cdb7ae23c3cbfc389152a67d25e557a632"
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "5e-16",
|
||||
"user": "0x72c22822A19D20DE7e426fB84aa047399Ddd8853",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x454b4116649ee74c7fb6223ffe0d475128fdd8a5b9dca14a9ad3def605abd38c"
|
||||
}
|
||||
],
|
||||
"total_tokens": "5e-16",
|
||||
"withdrawn_tokens": "5e-16",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x1FF32F8A5895DAcdcC0Fe8bC6dDAa7D2c7717f3e",
|
||||
"deposits": [
|
||||
|
@ -1,7 +1,7 @@
|
||||
export const Links = {
|
||||
WALLET_RELEASES:
|
||||
'https://github.com/vegaprotocol/vegawallet-desktop/releases',
|
||||
WALLET_GUIDE: 'https://docs.vega.xyz/docs/mainnet/tools/vega-wallet',
|
||||
WALLET_GUIDE: 'https://vega.xyz/wallet',
|
||||
SUSHI_PAIRS: 'https://analytics.sushi.com/pairs/',
|
||||
SUSHI_ONSEN_MENU: 'https://app.sushi.com/farm',
|
||||
SUSHI_ONSEN_WHAT_IS:
|
||||
|
@ -9,6 +9,7 @@ export const generateDealTicketQuery = (
|
||||
const defaultResult: DealTicketQuery = {
|
||||
market: {
|
||||
id: 'market-id',
|
||||
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 1,
|
||||
state: MarketState.Active,
|
||||
|
@ -1,6 +1,6 @@
|
||||
export default class BasePage {
|
||||
closeDialogBtn = 'dialog-close';
|
||||
porfolioUrl = '/portfolio';
|
||||
portfolioUrl = '/portfolio';
|
||||
marketsUrl = '/markets';
|
||||
assetSelectField = 'select[name="asset"]';
|
||||
toAddressField = 'input[name="to"]';
|
||||
@ -10,21 +10,22 @@ export default class BasePage {
|
||||
dialogText = 'dialog-text';
|
||||
|
||||
closeDialog() {
|
||||
cy.getByTestId(this.closeDialogBtn, { timeout: 8000 }).click({
|
||||
cy.getByTestId(this.closeDialogBtn, { timeout: 8000 })?.click({
|
||||
force: true,
|
||||
});
|
||||
}
|
||||
|
||||
navigateToPortfolio() {
|
||||
cy.get(`a[href='${this.porfolioUrl}']`).should('be.visible').click();
|
||||
cy.get(`a[href='${this.portfolioUrl}']`)
|
||||
.should('be.visible')
|
||||
.click({ force: true });
|
||||
cy.url().should('include', '/portfolio');
|
||||
cy.getByTestId('portfolio');
|
||||
}
|
||||
|
||||
navigateToMarkets() {
|
||||
cy.get(`a[href='${this.marketsUrl}']`).should('be.visible').click();
|
||||
cy.getByTestId('markets-link').should('be.visible').click({ force: true });
|
||||
cy.url().should('include', '/markets');
|
||||
cy.getByTestId('markets');
|
||||
}
|
||||
|
||||
verifyFormErrorDisplayed(expectedError: string, expectedNumErrors: number) {
|
||||
@ -35,7 +36,7 @@ export default class BasePage {
|
||||
);
|
||||
}
|
||||
|
||||
updateTransactionform(args?: {
|
||||
updateTransactionForm(args?: {
|
||||
asset?: string;
|
||||
to?: string;
|
||||
amount?: string;
|
||||
|
@ -1,13 +1,14 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class MarketPage extends BasePage {
|
||||
marketRowHeaderClassname = '.ag-header-cell-text';
|
||||
marketRowHeaderClassname = 'div > span.ag-header-cell-text';
|
||||
marketRowNameColumn = 'tradableInstrument.instrument.code';
|
||||
marketRowSymbolColumn =
|
||||
'tradableInstrument.instrument.product.settlementAsset.symbol';
|
||||
marketRowPrices = 'flash-cell';
|
||||
marketRowDescription = 'name';
|
||||
marketStateColId = 'data';
|
||||
openMarketMenu = 'arrow-down';
|
||||
|
||||
validateMarketsAreDisplayed() {
|
||||
// We need this to ensure that ag-grid is fully rendered before asserting
|
||||
@ -27,16 +28,12 @@ export default class MarketPage extends BasePage {
|
||||
'Description',
|
||||
];
|
||||
|
||||
cy.get(this.marketRowHeaderClassname)
|
||||
.each(($marketHeader, index) => {
|
||||
cy.wrap($marketHeader).should(
|
||||
'have.text',
|
||||
for (let index = 0; index < expectedMarketHeaders.length; index++) {
|
||||
cy.get(this.marketRowHeaderClassname).should(
|
||||
'contain.text',
|
||||
expectedMarketHeaders[index]
|
||||
);
|
||||
})
|
||||
.then(($list) => {
|
||||
cy.wrap($list).should('have.length', expectedMarketHeaders.length);
|
||||
});
|
||||
}
|
||||
|
||||
cy.get(`[col-id='${this.marketRowNameColumn}']`).each(($marketName) => {
|
||||
cy.wrap($marketName).should('not.be.empty');
|
||||
@ -65,4 +62,8 @@ export default class MarketPage extends BasePage {
|
||||
'portfolio=orders&trade=orderbook'
|
||||
);
|
||||
}
|
||||
|
||||
clickOpenMarketMenu() {
|
||||
cy.getByTestId(this.openMarketMenu).click();
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ import { Given } from 'cypress-cucumber-preprocessor/steps';
|
||||
import { hasOperationName } from '..';
|
||||
import { generateMarketList } from '../mocks/generate-market-list';
|
||||
import BasePage from '../pages/base-page';
|
||||
import MarketPage from '../pages/markets-page';
|
||||
|
||||
const basePage = new BasePage();
|
||||
const marketPage = new MarketPage();
|
||||
|
||||
Given('I am on the homepage', () => {
|
||||
cy.mockGQL('MarketsList', (req) => {
|
||||
@ -15,4 +17,5 @@ Given('I am on the homepage', () => {
|
||||
});
|
||||
cy.visit('/');
|
||||
basePage.closeDialog();
|
||||
marketPage.validateMarketsAreDisplayed();
|
||||
});
|
||||
|
@ -30,7 +30,7 @@ Then('I can see the deposit form', () => {
|
||||
});
|
||||
|
||||
When('I submit a deposit with empty fields', () => {
|
||||
depositsPage.updateTransactionform();
|
||||
depositsPage.updateTransactionForm();
|
||||
depositsPage.submitForm();
|
||||
});
|
||||
|
||||
@ -39,7 +39,7 @@ Then('I can see empty form validation errors present', () => {
|
||||
});
|
||||
|
||||
Then('I enter the following deposit details in deposit form', (table) => {
|
||||
depositsPage.updateTransactionform({
|
||||
depositsPage.updateTransactionForm({
|
||||
asset: table.rowsHash().asset,
|
||||
to: Cypress.env(table.rowsHash().to),
|
||||
amount: table.rowsHash().amount,
|
||||
@ -59,7 +59,7 @@ Then('Amount too small message shown', () => {
|
||||
});
|
||||
|
||||
And('I enter a valid amount', () => {
|
||||
depositsPage.updateTransactionform({ amount: '1' });
|
||||
depositsPage.updateTransactionForm({ amount: '1' });
|
||||
});
|
||||
|
||||
Then('Not approved message shown', () => {
|
||||
|
@ -19,6 +19,7 @@ const mockMarkets = () => {
|
||||
Then('I navigate to markets page', () => {
|
||||
mockMarkets();
|
||||
marketsPage.navigateToMarkets();
|
||||
marketsPage.clickOpenMarketMenu();
|
||||
cy.wait('@Markets');
|
||||
});
|
||||
|
||||
|
@ -88,7 +88,7 @@ Given('I am on the trading page for an active market', () => {
|
||||
|
||||
cy.visit('/markets/market-id');
|
||||
cy.wait('@Market');
|
||||
cy.contains('Market: ACTIVE MARKET');
|
||||
cy.contains('ACTIVE MARKET');
|
||||
});
|
||||
|
||||
Given('I am on the trading page for a suspended market', () => {
|
||||
@ -96,7 +96,7 @@ Given('I am on the trading page for a suspended market', () => {
|
||||
|
||||
cy.visit('/markets/market-id');
|
||||
cy.wait('@Market');
|
||||
cy.contains('Market: SUSPENDED MARKET');
|
||||
cy.contains('SUSPENDED MARKET');
|
||||
});
|
||||
|
||||
When('I click on {string} mocked market', (marketType) => {
|
||||
@ -115,11 +115,11 @@ Then('trading page for {string} market is displayed', (marketType) => {
|
||||
switch (marketType) {
|
||||
case 'active':
|
||||
cy.wait('@Market');
|
||||
cy.contains('Market: ACTIVE MARKET');
|
||||
cy.contains('ACTIVE MARKET');
|
||||
break;
|
||||
case 'suspended':
|
||||
cy.wait('@Market');
|
||||
cy.contains('Market: SUSPENDED MARKET');
|
||||
cy.contains('SUSPENDED MARKET');
|
||||
break;
|
||||
}
|
||||
tradingPage.clickOnTradesTab();
|
||||
|
@ -27,6 +27,7 @@ When('I connect to Vega Wallet', () => {
|
||||
Cypress.env('TRADING_TEST_VEGA_WALLET_PASSPHRASE')
|
||||
);
|
||||
vegaWallet.clickConnectVegaWallet();
|
||||
vegaWallet.validateWalletConnected();
|
||||
});
|
||||
|
||||
When('I open wallet dialog', () => {
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';
|
||||
import MarketPage from '../pages/markets-page';
|
||||
import PortfolioPage from '../pages/portfolio-page';
|
||||
import WithdrawalsPage from '../pages/withdrawals-page';
|
||||
|
||||
const marketPage = new MarketPage();
|
||||
const portfolioPage = new PortfolioPage();
|
||||
const withdrawalsPage = new WithdrawalsPage();
|
||||
|
||||
Given('I navigate to withdrawal page', () => {
|
||||
cy.visit('/');
|
||||
portfolioPage.closeDialog();
|
||||
marketPage.validateMarketsAreDisplayed();
|
||||
portfolioPage.navigateToPortfolio();
|
||||
portfolioPage.navigateToWithdraw();
|
||||
});
|
||||
@ -26,14 +29,14 @@ When('click submit', () => {
|
||||
});
|
||||
|
||||
When('I enter an invalid ethereum address', () => {
|
||||
withdrawalsPage.updateTransactionform({
|
||||
withdrawalsPage.updateTransactionForm({
|
||||
to: '0x0dAAACaa868f87BB4666F918742141cAEAe893Fa',
|
||||
});
|
||||
withdrawalsPage.clickSubmit();
|
||||
});
|
||||
|
||||
When('I select {string}', (selectedAsset) => {
|
||||
withdrawalsPage.updateTransactionform({
|
||||
withdrawalsPage.updateTransactionForm({
|
||||
asset: selectedAsset,
|
||||
});
|
||||
});
|
||||
@ -47,7 +50,7 @@ When('I click Use maximum', () => {
|
||||
});
|
||||
|
||||
When('I enter the following details in withdrawal form', (table) => {
|
||||
withdrawalsPage.updateTransactionform({
|
||||
withdrawalsPage.updateTransactionForm({
|
||||
asset: table.rowsHash().asset,
|
||||
to: table.rowsHash().to,
|
||||
amount: table.rowsHash().amount,
|
||||
@ -56,7 +59,7 @@ When('I enter the following details in withdrawal form', (table) => {
|
||||
});
|
||||
|
||||
When('I succesfully fill in and submit withdrawal form', () => {
|
||||
withdrawalsPage.updateTransactionform({
|
||||
withdrawalsPage.updateTransactionForm({
|
||||
asset: Cypress.env('WITHDRAWAL_ASSET_ID'),
|
||||
amount: '0.1',
|
||||
});
|
||||
|
@ -20,11 +20,11 @@ export default class DealTicket {
|
||||
);
|
||||
|
||||
if (isBuy == false) {
|
||||
cy.getByTestId(this.sellOrder).click();
|
||||
cy.getByTestId(this.sellOrder)?.click();
|
||||
}
|
||||
|
||||
cy.getByTestId(this.orderSizeField).clear().type(orderSize);
|
||||
cy.getByTestId(this.orderTypeDropDown).select(orderType);
|
||||
cy.getByTestId(this.orderSizeField)?.clear().type(orderSize);
|
||||
cy.getByTestId(this.orderTypeDropDown)?.select(orderType);
|
||||
}
|
||||
|
||||
placeLimitOrder(
|
||||
@ -33,10 +33,10 @@ export default class DealTicket {
|
||||
orderPrice: string,
|
||||
orderType: string
|
||||
) {
|
||||
cy.getByTestId(this.limitOrderType).click();
|
||||
cy.getByTestId(this.limitOrderType)?.click();
|
||||
|
||||
if (isBuy == false) {
|
||||
cy.getByTestId(this.sellOrder).click();
|
||||
cy.getByTestId(this.sellOrder)?.click();
|
||||
}
|
||||
|
||||
cy.getByTestId(this.orderSizeField).clear().type(orderSize);
|
||||
|
@ -50,6 +50,10 @@ export default class VegaWallet {
|
||||
);
|
||||
}
|
||||
|
||||
validateWalletConnected() {
|
||||
cy.getByTestId(this.connectVegaBtn).should('contain.text', '…');
|
||||
}
|
||||
|
||||
selectPublicKey() {
|
||||
cy.getByTestId(this.selectPublicKeyBtn).click();
|
||||
}
|
||||
|
@ -2,9 +2,38 @@ 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 { LocalStorage, t } from '@vegaprotocol/react-helpers';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const Navbar = () => {
|
||||
const initNavItemsState = [
|
||||
{
|
||||
name: t('Portfolio'),
|
||||
path: '/portfolio',
|
||||
testId: 'portfolio-link',
|
||||
slug: '',
|
||||
},
|
||||
];
|
||||
const [navItems, setNavItems] = useState(initNavItemsState);
|
||||
const marketId = LocalStorage.getItem('marketId') ?? '';
|
||||
|
||||
useEffect(() => {
|
||||
setNavItems([
|
||||
{
|
||||
name: t('Trading'),
|
||||
path: '/markets',
|
||||
testId: 'markets-link',
|
||||
slug: marketId,
|
||||
},
|
||||
{
|
||||
name: t('Portfolio'),
|
||||
path: '/portfolio',
|
||||
testId: 'portfolio-link',
|
||||
slug: '',
|
||||
},
|
||||
]);
|
||||
}, [marketId]);
|
||||
|
||||
return (
|
||||
<nav className="flex items-center">
|
||||
<Link href="/" passHref={true}>
|
||||
@ -12,10 +41,7 @@ export const Navbar = () => {
|
||||
<Vega className="fill-black dark:fill-white" />
|
||||
</a>
|
||||
</Link>
|
||||
{[
|
||||
{ name: t('Trading'), path: '/markets' },
|
||||
{ name: t('Portfolio'), path: '/portfolio' },
|
||||
].map((route) => (
|
||||
{navItems.map((route) => (
|
||||
<NavLink key={route.path} {...route} />
|
||||
))}
|
||||
</nav>
|
||||
@ -26,20 +52,30 @@ interface NavLinkProps {
|
||||
name: string;
|
||||
path: string;
|
||||
exact?: boolean;
|
||||
testId?: string;
|
||||
slug?: string;
|
||||
}
|
||||
|
||||
const NavLink = ({ name, path, exact }: NavLinkProps) => {
|
||||
const NavLink = ({
|
||||
name,
|
||||
path,
|
||||
exact,
|
||||
testId = name,
|
||||
slug = '',
|
||||
}: NavLinkProps) => {
|
||||
const router = useRouter();
|
||||
const isActive =
|
||||
router.asPath === path || (!exact && router.asPath.startsWith(path));
|
||||
const href = slug !== '' ? `${path}/${slug}` : path;
|
||||
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"
|
||||
href={path}
|
||||
data-testid={testId}
|
||||
href={href}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
router.push(path);
|
||||
router.push(href);
|
||||
}}
|
||||
>
|
||||
{name}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { LocalStorage } from '@vegaprotocol/react-helpers';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
@ -35,10 +36,13 @@ export function Index() {
|
||||
// should be the oldest market that is currently trading in continuous mode(i.e. not in auction).
|
||||
const { data, error, loading } = useQuery<MarketsLanding>(MARKETS_QUERY);
|
||||
const setLandingDialog = useGlobalStore((state) => state.setLandingDialog);
|
||||
const lastSelectedMarketId = LocalStorage.getItem('marketId');
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
const marketId = marketList(data)[0]?.id;
|
||||
const marketId = lastSelectedMarketId
|
||||
? lastSelectedMarketId
|
||||
: marketList(data)[0]?.id;
|
||||
|
||||
// If a default market is found, go to it with the landing dialog open
|
||||
if (marketId) {
|
||||
@ -50,7 +54,7 @@ export function Index() {
|
||||
replace('/markets');
|
||||
}
|
||||
}
|
||||
}, [data, replace, setLandingDialog]);
|
||||
}, [data, lastSelectedMarketId, replace, setLandingDialog]);
|
||||
|
||||
return (
|
||||
<AsyncRenderer data={data} loading={loading} error={error}>
|
||||
|
@ -1,21 +1,55 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import type { Market, MarketVariables } from './__generated__/Market';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { PageQueryContainer } from '../../components/page-query-container';
|
||||
import { TradeGrid, TradePanels } from './trade-grid';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { LocalStorage, t } from '@vegaprotocol/react-helpers';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
import { LandingDialog } from '@vegaprotocol/market-list';
|
||||
import type { Market, MarketVariables } from './__generated__/Market';
|
||||
import { Interval } from '@vegaprotocol/types';
|
||||
|
||||
// Top level page query
|
||||
const MARKET_QUERY = gql`
|
||||
query Market($marketId: ID!) {
|
||||
query Market($marketId: ID!, $interval: Interval!, $since: String!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
name
|
||||
tradingMode
|
||||
state
|
||||
decimalPlaces
|
||||
data {
|
||||
market {
|
||||
id
|
||||
}
|
||||
markPrice
|
||||
indicativeVolume
|
||||
bestBidVolume
|
||||
bestOfferVolume
|
||||
bestStaticBidVolume
|
||||
bestStaticOfferVolume
|
||||
indicativeVolume
|
||||
}
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
code
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
marketTimestamps {
|
||||
open
|
||||
close
|
||||
}
|
||||
candles(interval: $interval, since: $since) {
|
||||
open
|
||||
close
|
||||
volume
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -29,6 +63,9 @@ const MarketPage = ({ id }: { id?: string }) => {
|
||||
const marketId =
|
||||
id || (Array.isArray(query.marketId) ? query.marketId[0] : query.marketId);
|
||||
|
||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||
const yTimestamp = new Date(yesterday * 1000).toISOString();
|
||||
|
||||
if (!marketId) {
|
||||
return (
|
||||
<Splash>
|
||||
@ -37,12 +74,15 @@ const MarketPage = ({ id }: { id?: string }) => {
|
||||
);
|
||||
}
|
||||
|
||||
LocalStorage.setItem('marketId', marketId);
|
||||
return (
|
||||
<PageQueryContainer<Market, MarketVariables>
|
||||
query={MARKET_QUERY}
|
||||
options={{
|
||||
variables: {
|
||||
marketId,
|
||||
interval: Interval.I1H,
|
||||
since: yTimestamp,
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
}}
|
||||
|
145
apps/trading/pages/markets/__generated__/Market.ts
generated
145
apps/trading/pages/markets/__generated__/Market.ts
generated
@ -3,10 +3,112 @@
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { Interval, MarketTradingMode, MarketState } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: Market
|
||||
// ====================================================
|
||||
|
||||
export interface Market_market_data_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface Market_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* market id of the associated mark price
|
||||
*/
|
||||
market: Market_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 Market_market_tradableInstrument_instrument_metadata {
|
||||
__typename: "InstrumentMetadata";
|
||||
/**
|
||||
* An arbitrary list of tags to associated to associate to the Instrument (string list)
|
||||
*/
|
||||
tags: string[] | null;
|
||||
}
|
||||
|
||||
export interface Market_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||
*/
|
||||
code: string;
|
||||
/**
|
||||
* Metadata for this instrument
|
||||
*/
|
||||
metadata: Market_market_tradableInstrument_instrument_metadata;
|
||||
}
|
||||
|
||||
export interface Market_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of or reference to a fully specified instrument.
|
||||
*/
|
||||
instrument: Market_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface Market_market_marketTimestamps {
|
||||
__typename: "MarketTimestamps";
|
||||
/**
|
||||
* Time when the market is open and ready to accept trades
|
||||
*/
|
||||
open: string | null;
|
||||
/**
|
||||
* Time when the market is closed
|
||||
*/
|
||||
close: string | null;
|
||||
}
|
||||
|
||||
export interface Market_market_candles {
|
||||
__typename: "Candle";
|
||||
/**
|
||||
* Open price (uint64)
|
||||
*/
|
||||
open: string;
|
||||
/**
|
||||
* Close price (uint64)
|
||||
*/
|
||||
close: string;
|
||||
/**
|
||||
* Volume price (uint64)
|
||||
*/
|
||||
volume: string;
|
||||
}
|
||||
|
||||
export interface Market_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
@ -17,6 +119,47 @@ export interface Market_market {
|
||||
* Market full name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Current mode of execution of the market
|
||||
*/
|
||||
tradingMode: MarketTradingMode;
|
||||
/**
|
||||
* Current state of the market
|
||||
*/
|
||||
state: MarketState;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: Market_market_data | null;
|
||||
/**
|
||||
* An instance of or reference to a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: Market_market_tradableInstrument;
|
||||
/**
|
||||
* timestamps for state changes in the market
|
||||
*/
|
||||
marketTimestamps: Market_market_marketTimestamps;
|
||||
/**
|
||||
* Candles on a market, for the 'last' n candles, at 'interval' seconds as specified by params
|
||||
*/
|
||||
candles: (Market_market_candles | null)[] | null;
|
||||
}
|
||||
|
||||
export interface Market {
|
||||
@ -28,4 +171,6 @@ export interface Market {
|
||||
|
||||
export interface MarketVariables {
|
||||
marketId: string;
|
||||
interval: Interval;
|
||||
since: string;
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { MarketsContainer } from '@vegaprotocol/market-list';
|
||||
|
||||
const Markets = () => {
|
||||
return <MarketsContainer />;
|
||||
};
|
||||
const Markets = () => <MarketsContainer />;
|
||||
|
||||
Markets.getInitialProps = () => ({
|
||||
page: 'markets',
|
||||
|
@ -13,6 +13,9 @@ import { t } from '@vegaprotocol/react-helpers';
|
||||
import { AccountsContainer } from '@vegaprotocol/accounts';
|
||||
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
||||
import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
|
||||
import { SelectMarketDialog } from '@vegaprotocol/market-list';
|
||||
import { ArrowDown, PriceCellChange } from '@vegaprotocol/ui-toolkit';
|
||||
import type { CandleClose } from '@vegaprotocol/types';
|
||||
|
||||
const TradingViews = {
|
||||
Candles: CandlesChartContainer,
|
||||
@ -31,6 +34,58 @@ interface TradeGridProps {
|
||||
market: Market_market;
|
||||
}
|
||||
|
||||
export const TradeMarketHeader = ({ market }: TradeGridProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const candlesClose: string[] = (market?.candles || [])
|
||||
.map((candle) => candle?.close)
|
||||
.filter((c): c is CandleClose => c !== null);
|
||||
const headerItemClassName = 'whitespace-nowrap flex flex-col';
|
||||
const itemClassName =
|
||||
'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';
|
||||
return (
|
||||
<header className="w-full p-8">
|
||||
<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"
|
||||
>
|
||||
<span className="break-words text-left">{market.name}</span>
|
||||
<ArrowDown color="yellow" borderX={8} borderTop={12} />
|
||||
</button>
|
||||
|
||||
<div className="flex flex-auto items-start gap-64 overflow-x-scroll whitespace-nowrap w-[400px]">
|
||||
<div className={headerItemClassName}>
|
||||
<span className={itemClassName}>Change (24h)</span>
|
||||
<PriceCellChange
|
||||
candles={candlesClose}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
/>
|
||||
</div>
|
||||
<div className={headerItemClassName}>
|
||||
<span className={itemClassName}>Volume</span>
|
||||
<span className={itemValueClassName}>
|
||||
{market.data && market.data.indicativeVolume !== '0'
|
||||
? market.data.indicativeVolume
|
||||
: '-'}
|
||||
</span>
|
||||
</div>
|
||||
<div className={headerItemClassName}>
|
||||
<span className={itemClassName}>Trading mode</span>
|
||||
<span className={itemValueClassName}>{market.tradingMode}</span>
|
||||
</div>
|
||||
<div className={headerItemClassName}>
|
||||
<span className={itemClassName}>State</span>
|
||||
<span className={itemValueClassName}>{market.state}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export const TradeGrid = ({ market }: TradeGridProps) => {
|
||||
const wrapperClasses = classNames(
|
||||
'h-full max-h-full',
|
||||
@ -38,14 +93,12 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
|
||||
'bg-black-10 dark:bg-white-10',
|
||||
'text-ui'
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<TradeMarketHeader market={market} />
|
||||
<div className={wrapperClasses}>
|
||||
<header className="col-start-1 col-end-2 row-start-1 row-end-1 p-8">
|
||||
<h1>
|
||||
{t('Market')}: {market.name}
|
||||
</h1>
|
||||
</header>
|
||||
<TradeGridChild className="col-start-1 col-end-2">
|
||||
<TradeGridChild className="row-start-1 row-end-3">
|
||||
<GridTabs group="chart">
|
||||
<GridTab id="candles" name={t('Candles')}>
|
||||
<TradingViews.Candles marketId={market.id} />
|
||||
@ -82,6 +135,7 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
|
||||
</GridTabs>
|
||||
</TradeGridChild>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -124,11 +178,7 @@ export const TradePanels = ({ market }: TradePanelsProps) => {
|
||||
|
||||
return (
|
||||
<div className="h-full grid grid-rows-[min-content_1fr_min-content]">
|
||||
<header className="p-8">
|
||||
<h1>
|
||||
{t('Market')}: {market.name}
|
||||
</h1>
|
||||
</header>
|
||||
<TradeMarketHeader market={market} />
|
||||
<div className="h-full">
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
|
@ -55,6 +55,10 @@ export interface DealTicketQuery_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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { DealTicketManager } from './deal-ticket-manager';
|
||||
import type {
|
||||
DealTicketQuery,
|
||||
@ -11,6 +11,7 @@ const DEAL_TICKET_QUERY = gql`
|
||||
query DealTicketQuery($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
|
@ -1,2 +1,3 @@
|
||||
export * from './landing-dialog';
|
||||
export * from './select-market-dialog';
|
||||
export * from './select-market-list';
|
||||
|
@ -0,0 +1,33 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { SelectMarketDialog } from './select-market-dialog';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
|
||||
jest.mock(
|
||||
'next/link',
|
||||
() =>
|
||||
({ children }: { children: ReactNode }) =>
|
||||
children
|
||||
);
|
||||
|
||||
jest.mock('next/router', () => ({
|
||||
useRouter() {
|
||||
return {
|
||||
route: '/',
|
||||
pathname: '',
|
||||
query: '',
|
||||
asPath: '',
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
describe('SelectMarketDialog', () => {
|
||||
it('should render select a market dialog', () => {
|
||||
render(
|
||||
<MockedProvider>
|
||||
<SelectMarketDialog dialogOpen={true} setDialogOpen={() => jest.fn()} />
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByText('Select a market')).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,28 @@
|
||||
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { MarketsContainer } from '../markets-container';
|
||||
|
||||
export interface SelectMarketListProps {
|
||||
dialogOpen: boolean;
|
||||
setDialogOpen: (open: boolean) => void;
|
||||
}
|
||||
|
||||
export const SelectMarketDialog = ({
|
||||
dialogOpen,
|
||||
setDialogOpen,
|
||||
}: SelectMarketListProps) => {
|
||||
return (
|
||||
<Dialog
|
||||
title={t('Select a market')}
|
||||
intent={Intent.Prompt}
|
||||
open={dialogOpen}
|
||||
onChange={() => setDialogOpen(false)}
|
||||
titleClassNames="font-bold font-sans text-3xl tracking-tight mb-0 pl-8"
|
||||
contentClassNames="w-full md:w-[1120px]"
|
||||
>
|
||||
<div className="h-[200px] w-full">
|
||||
<MarketsContainer />
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
@ -3,19 +3,21 @@ import {
|
||||
PriceCell,
|
||||
t,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type { CandleClose } from '@vegaprotocol/types';
|
||||
import { PriceCellChange, Sparkline } from '@vegaprotocol/ui-toolkit';
|
||||
import Link from 'next/link';
|
||||
import { mapDataToMarketList } from '../../utils';
|
||||
import type { MarketList } from '../markets-container/__generated__/MarketList';
|
||||
|
||||
export interface SelectMarketListProps {
|
||||
export interface SelectMarketListDataProps {
|
||||
data: MarketList | undefined;
|
||||
onSelect: (id: string) => void;
|
||||
}
|
||||
|
||||
type CandleClose = Required<string>;
|
||||
|
||||
export const SelectMarketList = ({ data, onSelect }: SelectMarketListProps) => {
|
||||
export const SelectMarketList = ({
|
||||
data,
|
||||
onSelect,
|
||||
}: SelectMarketListDataProps) => {
|
||||
const thClassNames = (direction: 'left' | 'right') =>
|
||||
`px-8 text-${direction} font-sans font-normal text-ui-small leading-9 mb-0 text-dark/80 dark:text-white/80`;
|
||||
const tdClassNames =
|
||||
|
@ -13,7 +13,7 @@ import type {
|
||||
import { marketsDataProvider } from './markets-data-provider';
|
||||
|
||||
export const MarketsContainer = () => {
|
||||
const { pathname, push } = useRouter();
|
||||
const { push } = useRouter();
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const update = useCallback(
|
||||
(delta: Markets_markets_data) => {
|
||||
@ -57,7 +57,7 @@ export const MarketsContainer = () => {
|
||||
ref={gridRef}
|
||||
data={data}
|
||||
onRowClicked={(id) =>
|
||||
push(`${pathname}/${id}?portfolio=orders&trade=orderbook`)
|
||||
push(`/markets/${id}?portfolio=orders&trade=orderbook`)
|
||||
}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
|
@ -4,7 +4,7 @@ import type { Positions_party_positions } from './__generated__/Positions';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
const singleRow: Positions_party_positions = {
|
||||
realisedPNL: '5',
|
||||
realisedPNL: '520000000',
|
||||
openVolume: '100',
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '1129935',
|
||||
@ -93,7 +93,7 @@ it('Correct formatting applied', async () => {
|
||||
'+100',
|
||||
'11.29935',
|
||||
'11.38885',
|
||||
'+5',
|
||||
'+5,200.000',
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
|
@ -131,8 +131,10 @@ export const PositionsTable = forwardRef<AgGridReact, PositionsTableProps>(
|
||||
'color-vega-red': ({ value }: { value: string }) =>
|
||||
Number(value) < 0,
|
||||
}}
|
||||
valueFormatter={({ value }: ValueFormatterParams) =>
|
||||
volumePrefix(value)
|
||||
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
||||
volumePrefix(
|
||||
addDecimalsFormatNumber(value, data.market.decimalPlaces, 3)
|
||||
)
|
||||
}
|
||||
cellRenderer="PriceFlashCell"
|
||||
/>
|
||||
|
@ -46,8 +46,8 @@ interface GetDelta<SubscriptionData, Delta> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subscriptionQuery query that will beused for subscription
|
||||
* @param update function that will be execued on each onNext, it should update data base on delta, it can restart data provider
|
||||
* @param subscriptionQuery query that will be used for subscription
|
||||
* @param update function that will be executed on each onNext, it should update data base on delta, it can restart data provider
|
||||
* @param getData transforms received query data to format that will be stored in data provider
|
||||
* @param getDelta transforms delta data to format that will be stored in data provider
|
||||
* @param fetchPolicy
|
||||
@ -63,7 +63,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
): Subscribe<Data, Delta> {
|
||||
// list of callbacks passed through subscribe call
|
||||
const callbacks: UpdateCallback<Data, Delta>[] = [];
|
||||
// subscription is started before inital query, all deltas that will arrive before inital query response are put on queue
|
||||
// subscription is started before initial query, all deltas that will arrive before initial query response are put on queue
|
||||
const updateQueue: Delta[] = [];
|
||||
|
||||
let variables: OperationVariables | undefined = undefined;
|
||||
@ -88,7 +88,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
callbacks.forEach((callback) => notify(callback, delta));
|
||||
};
|
||||
|
||||
const initalFetch = async () => {
|
||||
const initialFetch = async () => {
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
@ -99,7 +99,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
fetchPolicy,
|
||||
});
|
||||
data = getData(res.data);
|
||||
// if there was some updates received from subscription during initial query loading apply them on just reveived data
|
||||
// if there was some updates received from subscription during initial query loading apply them on just received data
|
||||
if (data && updateQueue && updateQueue.length > 0) {
|
||||
data = produce(data, (draft) => {
|
||||
while (updateQueue.length) {
|
||||
@ -135,7 +135,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
} else {
|
||||
loading = true;
|
||||
error = undefined;
|
||||
initalFetch();
|
||||
initialFetch();
|
||||
}
|
||||
};
|
||||
|
||||
@ -176,7 +176,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
},
|
||||
() => restart()
|
||||
);
|
||||
await initalFetch();
|
||||
await initialFetch();
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
@ -242,8 +242,8 @@ const memoize = <Data, Delta>(
|
||||
|
||||
/**
|
||||
* @param query Query<QueryData>
|
||||
* @param subscriptionQuery Query<SubscriptionData> query that will beused for subscription
|
||||
* @param update Update<Data, Delta> function that will be execued on each onNext, it should update data base on delta, it can restart data provider
|
||||
* @param subscriptionQuery Query<SubscriptionData> query that will be used for subscription
|
||||
* @param update Update<Data, Delta> function that will be executed on each onNext, it should update data base on delta, it can restart data provider
|
||||
* @param getData transforms received query data to format that will be stored in data provider
|
||||
* @param getDelta transforms delta data to format that will be stored in data provider
|
||||
* @param fetchPolicy
|
||||
|
@ -13,7 +13,7 @@ export const PriceCell = React.memo(
|
||||
return <span data-testid="price">-</span>;
|
||||
}
|
||||
return (
|
||||
<span className="font-mono relative" data-testid="price">
|
||||
<span className="font-mono relative text-ui-small" data-testid="price">
|
||||
{valueFormatted}
|
||||
</span>
|
||||
);
|
||||
|
1
libs/types/src/candle.ts
Normal file
1
libs/types/src/candle.ts
Normal file
@ -0,0 +1 @@
|
||||
export type CandleClose = Required<string>;
|
@ -1 +1,2 @@
|
||||
export * from './__generated__/globalTypes';
|
||||
export * from './candle';
|
||||
|
@ -1,13 +1,38 @@
|
||||
export const ArrowUp = () => (
|
||||
export interface ArrowStyleProps {
|
||||
color?: string;
|
||||
borderX?: number;
|
||||
borderTop?: number;
|
||||
borderBottom?: number;
|
||||
}
|
||||
|
||||
export const ArrowUp = ({
|
||||
color = 'green',
|
||||
borderX = 4,
|
||||
borderBottom = 4,
|
||||
}: ArrowStyleProps) => (
|
||||
<span
|
||||
data-testid="arrow-up"
|
||||
className="w-0 h-0 border-x border-x-[4px] border-solid border-x-transparent border-b-[4px] border-b-green-dark dark:border-b-green"
|
||||
style={{
|
||||
borderLeft: `${borderX}px solid transparent`,
|
||||
borderRight: `${borderX}px solid transparent`,
|
||||
borderBottom: `${borderBottom}px solid`,
|
||||
}}
|
||||
className={`w-0 h-0 border-b-${color}-dark dark:border-b-${color}`}
|
||||
></span>
|
||||
);
|
||||
export const ArrowDown = () => (
|
||||
export const ArrowDown = ({
|
||||
color = 'red',
|
||||
borderX = 4,
|
||||
borderTop = 4,
|
||||
}: ArrowStyleProps) => (
|
||||
<span
|
||||
data-testid="arrow-down"
|
||||
className="w-0 h-0 border-x border-x-[4px] border-solid border-x-transparent border-t-[4px] border-t-red-dark dark:border-t-red"
|
||||
style={{
|
||||
borderLeft: `${borderX}px solid transparent`,
|
||||
borderRight: `${borderX}px solid transparent`,
|
||||
borderTop: `${borderTop}px solid`,
|
||||
}}
|
||||
className={`w-0 h-0 border-t-${color}-dark dark:border-t-${color}`}
|
||||
></span>
|
||||
);
|
||||
|
||||
|
@ -215,12 +215,12 @@ export const AnchorButton = forwardRef<HTMLAnchorElement, AnchorButtonProps>(
|
||||
className,
|
||||
prependIconName,
|
||||
appendIconName,
|
||||
...prosp
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<a ref={ref} className={classes(className, variant)} {...prosp}>
|
||||
<a ref={ref} className={classes(className, variant)} {...props}>
|
||||
{getContent(children, prependIconName, appendIconName)}
|
||||
</a>
|
||||
);
|
||||
|
@ -12,6 +12,7 @@ interface DialogProps {
|
||||
title?: string;
|
||||
intent?: Intent;
|
||||
titleClassNames?: string;
|
||||
contentClassNames?: string;
|
||||
}
|
||||
|
||||
export function Dialog({
|
||||
@ -21,13 +22,15 @@ export function Dialog({
|
||||
title,
|
||||
intent,
|
||||
titleClassNames,
|
||||
contentClassNames,
|
||||
}: DialogProps) {
|
||||
const contentClasses = classNames(
|
||||
// Positions the modal in the center of screen
|
||||
'z-20 fixed w-full md:w-[520px] px-28 py-24 top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]',
|
||||
// Need to apply background and text colors again as content is rendered in a portal
|
||||
'dark:bg-black dark:text-white-95 bg-white text-black-95',
|
||||
getIntentShadow(intent)
|
||||
getIntentShadow(intent),
|
||||
contentClassNames
|
||||
);
|
||||
return (
|
||||
<DialogPrimitives.Root open={open} onOpenChange={(x) => onChange(x)}>
|
||||
|
@ -60,6 +60,7 @@
|
||||
"react-dom": "17.0.2",
|
||||
"react-hook-form": "^7.27.0",
|
||||
"react-i18next": "^11.11.4",
|
||||
"react-intersection-observer": "^9.2.2",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-syntax-highlighter": "^15.4.5",
|
||||
"react-use-websocket": "^3.0.0",
|
||||
|
@ -18049,6 +18049,11 @@ react-inspector@^5.1.0:
|
||||
is-dom "^1.0.0"
|
||||
prop-types "^15.0.0"
|
||||
|
||||
react-intersection-observer@^9.2.2:
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.2.2.tgz#4f72487e2e9c62b6a6f55f38c5b0b6b7dc6c196d"
|
||||
integrity sha512-xrFOWo5DbDzayAuDn6WpLrXfw73mvfx4WjuAjjy7dY7jWeTTle5+18nGtvMlR7q0npJanmmh6/CaSaSg4JxTJQ==
|
||||
|
||||
react-is@17.0.2, react-is@^17.0.1, react-is@^17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||
|
Loading…
Reference in New Issue
Block a user