chore: handle not found errors as correct response (#2759)
This commit is contained in:
parent
05559f3ea0
commit
00e319b3c6
@ -5,10 +5,12 @@ import { Heading } from '../../components/heading';
|
||||
import { SplashLoader } from '../../components/splash-loader';
|
||||
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||
import {
|
||||
useWithdrawals,
|
||||
withdrawalProvider,
|
||||
useWithdrawalDialog,
|
||||
WithdrawalsTable,
|
||||
} from '@vegaprotocol/withdraws';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
import type { RouteChildProps } from '../index';
|
||||
|
||||
@ -29,7 +31,12 @@ const Withdrawals = ({ name }: RouteChildProps) => {
|
||||
const WithdrawPendingContainer = () => {
|
||||
const openWithdrawalDialog = useWithdrawalDialog((state) => state.open);
|
||||
const { t } = useTranslation();
|
||||
const { data, loading, error } = useWithdrawals();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: withdrawalProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
|
@ -1,22 +1,28 @@
|
||||
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { useDepositDialog, DepositsTable } from '@vegaprotocol/deposits';
|
||||
import { useDeposits } from '@vegaprotocol/deposits';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { depositsProvider } from '@vegaprotocol/deposits';
|
||||
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
|
||||
export const DepositsContainer = () => {
|
||||
const { deposits, loading, error } = useDeposits();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: depositsProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
const openDepositDialog = useDepositDialog((state) => state.open);
|
||||
|
||||
return (
|
||||
<div className="h-full grid grid-rows-[1fr,min-content]">
|
||||
<div className="h-full relative">
|
||||
<DepositsTable
|
||||
rowData={deposits || []}
|
||||
rowData={data || []}
|
||||
noRowsOverlayComponent={() => null}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
data={deposits}
|
||||
data={data}
|
||||
loading={loading}
|
||||
error={error}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
|
@ -1,14 +1,20 @@
|
||||
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
useWithdrawals,
|
||||
withdrawalProvider,
|
||||
useWithdrawalDialog,
|
||||
WithdrawalsTable,
|
||||
} from '@vegaprotocol/withdraws';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||
|
||||
export const WithdrawalsContainer = () => {
|
||||
const { data, loading, error } = useWithdrawals();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: withdrawalProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
const openWithdrawDialog = useWithdrawalDialog((state) => state.open);
|
||||
|
||||
return (
|
||||
|
@ -50,10 +50,10 @@ export type Account = Omit<AccountFieldsFragment, 'market' | 'asset'> & {
|
||||
};
|
||||
|
||||
const update = (
|
||||
data: AccountFieldsFragment[],
|
||||
data: AccountFieldsFragment[] | null,
|
||||
deltas: AccountEventsSubscription['accounts']
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
return produce(data || [], (draft) => {
|
||||
deltas.forEach((delta) => {
|
||||
const id = getId(delta);
|
||||
const index = draft.findIndex((a) => getId(a) === id);
|
||||
@ -73,15 +73,8 @@ const update = (
|
||||
});
|
||||
};
|
||||
|
||||
const getData = (
|
||||
responseData: AccountsQuery
|
||||
): AccountFieldsFragment[] | null => {
|
||||
return (
|
||||
removePaginationWrapper(responseData.party?.accountsConnection?.edges) ??
|
||||
null
|
||||
);
|
||||
};
|
||||
|
||||
const getData = (responseData: AccountsQuery | null): AccountFieldsFragment[] =>
|
||||
removePaginationWrapper(responseData?.party?.accountsConnection?.edges) || [];
|
||||
const getDelta = (
|
||||
subscriptionData: AccountEventsSubscription
|
||||
): AccountEventsSubscription['accounts'] => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { ApolloError, InMemoryCacheConfig } from '@apollo/client';
|
||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||
import {
|
||||
ApolloClient,
|
||||
from,
|
||||
@ -13,7 +13,6 @@ import { createClient as createWSClient } from 'graphql-ws';
|
||||
import { onError } from '@apollo/client/link/error';
|
||||
import { RetryLink } from '@apollo/client/link/retry';
|
||||
import ApolloLinkTimeout from 'apollo-link-timeout';
|
||||
import type { GraphQLErrors } from '@apollo/client/errors';
|
||||
import { localLoggerFactory } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const isBrowser = typeof window !== 'undefined';
|
||||
@ -110,21 +109,3 @@ export function createClient({
|
||||
connectToDevTools,
|
||||
});
|
||||
}
|
||||
|
||||
const isApolloGraphQLError = (
|
||||
error: ApolloError | Error | undefined
|
||||
): error is ApolloError => {
|
||||
return !!error && !!(error as ApolloError).graphQLErrors;
|
||||
};
|
||||
|
||||
const hasNotFoundGraphQLErrors = (errors: GraphQLErrors) => {
|
||||
return errors.some((e) => e.extensions && e.extensions['type'] === NOT_FOUND);
|
||||
};
|
||||
|
||||
export const isNotFoundGraphQLError = (
|
||||
error: Error | ApolloError | undefined
|
||||
) => {
|
||||
return (
|
||||
isApolloGraphQLError(error) && hasNotFoundGraphQLErrors(error.graphQLErrors)
|
||||
);
|
||||
};
|
||||
|
@ -6,20 +6,15 @@ import { AssetDocument } from './__generated__/Asset';
|
||||
|
||||
export type Asset = AssetFieldsFragment;
|
||||
|
||||
const getData = (responseData: AssetQuery) => {
|
||||
const foundAssets = responseData.assetsConnection?.edges
|
||||
const getData = (responseData: AssetQuery | null) => {
|
||||
const foundAssets = responseData?.assetsConnection?.edges
|
||||
?.filter((e) => Boolean(e?.node))
|
||||
.map((e) => e?.node as Asset);
|
||||
if (foundAssets && foundAssets?.length > 0) return foundAssets[0];
|
||||
return null;
|
||||
};
|
||||
|
||||
export const assetProvider = makeDataProvider<
|
||||
AssetQuery,
|
||||
Asset | null,
|
||||
never,
|
||||
never
|
||||
>({
|
||||
export const assetProvider = makeDataProvider<AssetQuery, Asset, never, never>({
|
||||
query: AssetDocument,
|
||||
getData,
|
||||
});
|
||||
|
@ -16,14 +16,14 @@ export type BuiltinAsset = Omit<Asset, 'source'> & {
|
||||
source: BuiltinAssetSource;
|
||||
};
|
||||
|
||||
const getData = (responseData: AssetsQuery) =>
|
||||
responseData.assetsConnection?.edges
|
||||
const getData = (responseData: AssetsQuery | null) =>
|
||||
responseData?.assetsConnection?.edges
|
||||
?.filter((e) => Boolean(e?.node))
|
||||
.map((e) => e?.node as Asset) ?? [];
|
||||
|
||||
export const assetsProvider = makeDataProvider<
|
||||
AssetsQuery,
|
||||
Asset[] | null,
|
||||
Asset[],
|
||||
never,
|
||||
never
|
||||
>({
|
||||
|
49
libs/deposits/src/lib/deposits-provider.ts
Normal file
49
libs/deposits/src/lib/deposits-provider.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import {
|
||||
getEvents,
|
||||
makeDataProvider,
|
||||
removePaginationWrapper,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
DepositsDocument,
|
||||
DepositEventDocument,
|
||||
} from './__generated__/Deposit';
|
||||
import type {
|
||||
DepositFieldsFragment,
|
||||
DepositsQuery,
|
||||
DepositEventSubscription,
|
||||
DepositEventSubscriptionVariables,
|
||||
} from './__generated__/Deposit';
|
||||
|
||||
export const depositsProvider = makeDataProvider<
|
||||
DepositsQuery,
|
||||
DepositFieldsFragment[],
|
||||
DepositEventSubscription,
|
||||
DepositEventSubscription,
|
||||
DepositEventSubscriptionVariables
|
||||
>({
|
||||
query: DepositsDocument,
|
||||
subscriptionQuery: DepositEventDocument,
|
||||
getData: (data: DepositsQuery | null) =>
|
||||
orderBy(
|
||||
removePaginationWrapper(data?.party?.depositsConnection?.edges || []),
|
||||
['createdTimestamp'],
|
||||
['desc']
|
||||
),
|
||||
getDelta: (data: DepositEventSubscription) => data,
|
||||
update: (
|
||||
data: DepositFieldsFragment[] | null,
|
||||
delta: DepositEventSubscription
|
||||
) => {
|
||||
if (!delta.busEvents?.length) {
|
||||
return data;
|
||||
}
|
||||
const incoming = getEvents<DepositFieldsFragment>(
|
||||
Schema.BusEventType.Deposit,
|
||||
delta.busEvents
|
||||
);
|
||||
return uniqBy([...incoming, ...(data || [])], 'id');
|
||||
},
|
||||
});
|
@ -5,7 +5,7 @@ export * from './deposit-limits';
|
||||
export * from './deposit-manager';
|
||||
export * from './deposits-table';
|
||||
export * from './use-deposit-balances';
|
||||
export * from './use-deposits';
|
||||
export * from './deposits-provider';
|
||||
export * from './use-get-allowance';
|
||||
export * from './use-get-balance-of-erc20-token';
|
||||
export * from './use-get-deposit-maximum';
|
||||
|
@ -1,100 +0,0 @@
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import { getNodes, getEvents } from '@vegaprotocol/react-helpers';
|
||||
import type { UpdateQueryFn } from '@apollo/client/core/watchQueryOptions';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
useDepositsQuery,
|
||||
DepositEventDocument,
|
||||
} from './__generated__/Deposit';
|
||||
import type {
|
||||
DepositFieldsFragment,
|
||||
DepositsQuery,
|
||||
DepositEventSubscription,
|
||||
DepositEventSubscriptionVariables,
|
||||
} from './__generated__/Deposit';
|
||||
|
||||
export const useDeposits = () => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data, loading, error, subscribeToMore } = useDepositsQuery({
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
const deposits = useMemo(() => {
|
||||
if (!data?.party?.depositsConnection?.edges?.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return orderBy(
|
||||
getNodes<DepositFieldsFragment>(data.party?.depositsConnection),
|
||||
['createdTimestamp'],
|
||||
['desc']
|
||||
);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!pubKey) return;
|
||||
|
||||
const unsub = subscribeToMore<
|
||||
DepositEventSubscription,
|
||||
DepositEventSubscriptionVariables
|
||||
>({
|
||||
document: DepositEventDocument,
|
||||
variables: { partyId: pubKey },
|
||||
updateQuery,
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsub();
|
||||
};
|
||||
}, [pubKey, subscribeToMore]);
|
||||
|
||||
return { data, loading, error, deposits };
|
||||
};
|
||||
|
||||
const updateQuery: UpdateQueryFn<
|
||||
DepositsQuery,
|
||||
DepositEventSubscriptionVariables,
|
||||
DepositEventSubscription
|
||||
> = (prev, { subscriptionData, variables }) => {
|
||||
if (!subscriptionData.data.busEvents?.length || !variables?.partyId) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
const curr = getNodes<DepositFieldsFragment>(prev.party?.depositsConnection);
|
||||
const incoming = getEvents<DepositFieldsFragment>(
|
||||
Schema.BusEventType.Deposit,
|
||||
subscriptionData.data.busEvents
|
||||
);
|
||||
|
||||
const deposits = uniqBy([...incoming, ...curr], 'id');
|
||||
|
||||
if (!prev.party) {
|
||||
return {
|
||||
...prev,
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: variables?.partyId,
|
||||
depositsConnection: {
|
||||
__typename: 'DepositsConnection',
|
||||
edges: deposits.map((d) => ({ __typename: 'DepositEdge', node: d })),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
party: {
|
||||
...prev.party,
|
||||
id: variables?.partyId,
|
||||
depositsConnection: {
|
||||
__typename: 'DepositsConnection',
|
||||
edges: deposits.map((d) => ({ __typename: 'DepositEdge', node: d })),
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
@ -59,8 +59,8 @@ const update = (
|
||||
export type Trade = Omit<FillFieldsFragment, 'market'> & { market?: Market };
|
||||
export type TradeEdge = Edge<Trade>;
|
||||
|
||||
const getData = (responseData: FillsQuery): FillEdgeFragment[] =>
|
||||
responseData.party?.tradesConnection?.edges || [];
|
||||
const getData = (responseData: FillsQuery | null): FillEdgeFragment[] =>
|
||||
responseData?.party?.tradesConnection?.edges || [];
|
||||
|
||||
const getPageInfo = (responseData: FillsQuery): PageInfo | null =>
|
||||
responseData.party?.tradesConnection?.pageInfo || null;
|
||||
|
@ -5,8 +5,8 @@ import type {
|
||||
} from './__generated__/Proposals';
|
||||
import { ProposalsListDocument } from './__generated__/Proposals';
|
||||
|
||||
const getData = (responseData: ProposalsListQuery) =>
|
||||
responseData.proposalsConnection?.edges
|
||||
const getData = (responseData: ProposalsListQuery | null) =>
|
||||
responseData?.proposalsConnection?.edges
|
||||
?.filter((edge) => Boolean(edge?.node))
|
||||
.map((edge) => edge?.node as ProposalListFieldsFragment) || null;
|
||||
|
||||
|
@ -35,12 +35,12 @@ export type LedgerEntry = LedgerEntryFragment & {
|
||||
|
||||
export type AggregatedLedgerEntriesEdge = Schema.AggregatedLedgerEntriesEdge;
|
||||
|
||||
const getData = (responseData: LedgerEntriesQuery) => {
|
||||
return responseData.ledgerEntries?.edges || [];
|
||||
const getData = (responseData: LedgerEntriesQuery | null) => {
|
||||
return responseData?.ledgerEntries?.edges || [];
|
||||
};
|
||||
|
||||
export const update = (
|
||||
data: ReturnType<typeof getData>,
|
||||
data: ReturnType<typeof getData> | null,
|
||||
delta: ReturnType<typeof getData>,
|
||||
reload: () => void,
|
||||
variables?: LedgerEntriesQueryVariables
|
||||
|
@ -35,10 +35,10 @@ export const liquidityProvisionsDataProvider = makeDataProvider<
|
||||
query: LiquidityProvisionsDocument,
|
||||
subscriptionQuery: LiquidityProvisionsUpdateDocument,
|
||||
update: (
|
||||
data: LiquidityProvisionFieldsFragment[],
|
||||
data: LiquidityProvisionFieldsFragment[] | null,
|
||||
deltas: LiquidityProvisionsUpdateSubscription['liquidityProvisions']
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
return produce(data || [], (draft) => {
|
||||
deltas?.forEach((delta) => {
|
||||
const id = getId(delta);
|
||||
const index = draft.findIndex((a) => getId(a) === id);
|
||||
@ -63,9 +63,9 @@ export const liquidityProvisionsDataProvider = makeDataProvider<
|
||||
});
|
||||
});
|
||||
},
|
||||
getData: (responseData: LiquidityProvisionsQuery) => {
|
||||
getData: (responseData: LiquidityProvisionsQuery | null) => {
|
||||
return (
|
||||
responseData.market?.liquidityProvisionsConnection?.edges?.map(
|
||||
responseData?.market?.liquidityProvisionsConnection?.edges?.map(
|
||||
(e) => e?.node
|
||||
) ?? []
|
||||
).filter((e) => !!e) as LiquidityProvisionFieldsFragment[];
|
||||
@ -105,7 +105,7 @@ export const marketLiquidityDataProvider = makeDataProvider<
|
||||
never
|
||||
>({
|
||||
query: MarketLpDocument,
|
||||
getData: (responseData: MarketLpQuery) => {
|
||||
getData: (responseData: MarketLpQuery | null) => {
|
||||
return responseData;
|
||||
},
|
||||
});
|
||||
@ -119,10 +119,10 @@ export const liquidityFeeShareDataProvider = makeDataProvider<
|
||||
query: LiquidityProviderFeeShareDocument,
|
||||
subscriptionQuery: LiquidityProviderFeeShareUpdateDocument,
|
||||
update: (
|
||||
data: LiquidityProviderFeeShareFieldsFragment[],
|
||||
data: LiquidityProviderFeeShareFieldsFragment[] | null,
|
||||
deltas: LiquidityProviderFeeShareUpdateSubscription['marketsData'][0]['liquidityProviderFeeShare']
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
return produce(data || [], (draft) => {
|
||||
deltas?.forEach((delta) => {
|
||||
const id = delta.partyId;
|
||||
const index = draft.findIndex((a) => a.party.id === id);
|
||||
@ -143,7 +143,7 @@ export const liquidityFeeShareDataProvider = makeDataProvider<
|
||||
});
|
||||
},
|
||||
getData: (data) => {
|
||||
return data.market?.data?.liquidityProviderFeeShare || [];
|
||||
return data?.market?.data?.liquidityProviderFeeShare || [];
|
||||
},
|
||||
getDelta: (subscriptionData: LiquidityProviderFeeShareUpdateSubscription) => {
|
||||
return subscriptionData.marketsData[0].liquidityProviderFeeShare;
|
||||
|
@ -58,7 +58,7 @@ export interface Markets {
|
||||
}
|
||||
|
||||
const getData = (
|
||||
responseData: LiquidityProvisionMarketsQuery
|
||||
responseData: LiquidityProvisionMarketsQuery | null
|
||||
): LiquidityProvisionMarket[] | null => {
|
||||
return (
|
||||
responseData?.marketsConnection?.edges.map((edge) => {
|
||||
|
@ -53,7 +53,7 @@ export const update: Update<
|
||||
return data;
|
||||
};
|
||||
|
||||
const getData = (responseData: MarketDepthQuery) => responseData.market;
|
||||
const getData = (responseData: MarketDepthQuery | null) => responseData?.market;
|
||||
|
||||
const getDelta = (subscriptionData: MarketDepthUpdateSubscription) =>
|
||||
subscriptionData.marketsDepthUpdate;
|
||||
|
@ -9,5 +9,5 @@ export const marketInfoDataProvider = makeDataProvider<
|
||||
never
|
||||
>({
|
||||
query: MarketInfoDocument,
|
||||
getData: (responseData: MarketInfoQuery) => responseData,
|
||||
getData: (responseData: MarketInfoQuery | null) => responseData,
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ export const update = (data: Candle[] | null, delta: Candle) => {
|
||||
return [delta];
|
||||
};
|
||||
|
||||
const getData = (responseData: MarketCandlesQuery): Candle[] | null =>
|
||||
const getData = (responseData: MarketCandlesQuery | null): Candle[] | null =>
|
||||
responseData?.marketsConnection?.edges[0]?.node.candlesConnection?.edges
|
||||
?.filter((edge) => edge?.node)
|
||||
.map((edge) => edge?.node as Candle) || null;
|
||||
|
@ -18,14 +18,20 @@ import type {
|
||||
|
||||
export type MarketData = MarketDataFieldsFragment;
|
||||
|
||||
const update = (data: MarketData, delta: MarketDataUpdateFieldsFragment) => {
|
||||
return produce(data, (draft) => {
|
||||
const { marketId, __typename, ...marketData } = delta;
|
||||
Object.assign(draft, marketData);
|
||||
});
|
||||
const update = (
|
||||
data: MarketData | null,
|
||||
delta: MarketDataUpdateFieldsFragment
|
||||
) => {
|
||||
return (
|
||||
data &&
|
||||
produce(data, (draft) => {
|
||||
const { marketId, __typename, ...marketData } = delta;
|
||||
Object.assign(draft, marketData);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const getData = (responseData: MarketDataQuery): MarketData | null =>
|
||||
const getData = (responseData: MarketDataQuery | null): MarketData | null =>
|
||||
responseData?.marketsConnection?.edges[0].node.data || null;
|
||||
|
||||
const getDelta = (
|
||||
|
@ -11,7 +11,7 @@ import type { MarketData } from './market-data-provider';
|
||||
import { marketDataProvider } from './market-data-provider';
|
||||
|
||||
const getData = (
|
||||
responseData: MarketQuery
|
||||
responseData: MarketQuery | null
|
||||
): SingleMarketFieldsFragment | null => responseData?.market || null;
|
||||
|
||||
export const marketProvider = makeDataProvider<
|
||||
|
@ -8,7 +8,9 @@ export interface MarketCandles {
|
||||
candles: Candle[] | undefined;
|
||||
}
|
||||
|
||||
const getData = (responseData: MarketsCandlesQuery): MarketCandles[] | null =>
|
||||
const getData = (
|
||||
responseData: MarketsCandlesQuery | null
|
||||
): MarketCandles[] | null =>
|
||||
responseData?.marketsConnection?.edges.map((edge) => ({
|
||||
marketId: edge.node.id,
|
||||
candles: edge.node.candlesConnection?.edges
|
||||
|
@ -3,8 +3,8 @@ import type { MarketsDataQuery } from './__generated__/markets-data';
|
||||
import { MarketsDataDocument } from './__generated__/markets-data';
|
||||
import type { MarketData } from './market-data-provider';
|
||||
|
||||
const getData = (responseData: MarketsDataQuery): MarketData[] | null =>
|
||||
responseData.marketsConnection?.edges
|
||||
const getData = (responseData: MarketsDataQuery | null): MarketData[] | null =>
|
||||
responseData?.marketsConnection?.edges
|
||||
.filter((edge) => edge.node.data)
|
||||
.map((edge) => edge.node.data as MarketData) || null;
|
||||
|
||||
|
@ -21,7 +21,7 @@ import type { Candle } from './market-candles-provider';
|
||||
|
||||
export type Market = MarketFieldsFragment;
|
||||
|
||||
const getData = (responseData: MarketsQuery): Market[] | null =>
|
||||
const getData = (responseData: MarketsQuery | null): Market[] | null =>
|
||||
responseData?.marketsConnection?.edges.map((edge) => edge.node) || null;
|
||||
|
||||
export const marketsProvider = makeDataProvider<
|
||||
|
@ -62,7 +62,7 @@ describe('order data provider', () => {
|
||||
expect(updatedData && updatedData[1].node.updatedAt).toEqual(
|
||||
delta[4].updatedAt
|
||||
);
|
||||
expect(update([], delta, () => null, { partyId: '0x123' }).length).toEqual(
|
||||
expect(update([], delta, () => null, { partyId: '0x123' })?.length).toEqual(
|
||||
4
|
||||
);
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ const orderMatchFilters = (
|
||||
return true;
|
||||
};
|
||||
|
||||
const getData = (responseData: OrdersQuery) =>
|
||||
const getData = (responseData: OrdersQuery | null) =>
|
||||
responseData?.party?.ordersConnection?.edges || [];
|
||||
|
||||
const getDelta = (subscriptionData: OrdersUpdateSubscription) =>
|
||||
@ -81,7 +81,7 @@ const getPageInfo = (responseData: OrdersQuery): PageInfo | null =>
|
||||
responseData.party?.ordersConnection?.pageInfo || null;
|
||||
|
||||
export const update = (
|
||||
data: ReturnType<typeof getData>,
|
||||
data: ReturnType<typeof getData> | null,
|
||||
delta: ReturnType<typeof getDelta>,
|
||||
reload: () => void,
|
||||
variables?: OrdersQueryVariables
|
||||
|
@ -14,10 +14,10 @@ import type {
|
||||
} from './__generated__/Positions';
|
||||
|
||||
const update = (
|
||||
data: MarginFieldsFragment[],
|
||||
data: MarginFieldsFragment[] | null,
|
||||
delta: MarginsSubscriptionSubscription['margins']
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
return produce(data || [], (draft) => {
|
||||
const { marketId } = delta;
|
||||
const index = draft.findIndex((node) => node.market.id === marketId);
|
||||
if (index !== -1) {
|
||||
@ -49,8 +49,9 @@ const update = (
|
||||
});
|
||||
};
|
||||
|
||||
const getData = (responseData: MarginsQuery) =>
|
||||
removePaginationWrapper(responseData.party?.marginsConnection?.edges) || [];
|
||||
const getData = (responseData: MarginsQuery | null) =>
|
||||
removePaginationWrapper(responseData?.party?.marginsConnection?.edges) || [];
|
||||
|
||||
const getDelta = (subscriptionData: MarginsSubscriptionSubscription) =>
|
||||
subscriptionData.margins;
|
||||
|
||||
|
@ -4,8 +4,8 @@ import BigNumber from 'bignumber.js';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import type { Account } from '@vegaprotocol/accounts';
|
||||
import { accountsDataProvider } from '@vegaprotocol/accounts';
|
||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
toBigNum,
|
||||
makeDataProvider,
|
||||
makeDerivedDataProvider,
|
||||
removePaginationWrapper,
|
||||
@ -171,10 +171,10 @@ export const getMetrics = (
|
||||
};
|
||||
|
||||
export const update = (
|
||||
data: PositionFieldsFragment[],
|
||||
data: PositionFieldsFragment[] | null,
|
||||
deltas: PositionsSubscriptionSubscription['positions']
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
return produce(data || [], (draft) => {
|
||||
deltas.forEach((delta) => {
|
||||
const index = draft.findIndex(
|
||||
(node) => node.market.id === delta.marketId
|
||||
@ -212,8 +212,8 @@ export const positionsDataProvider = makeDataProvider<
|
||||
query: PositionsDocument,
|
||||
subscriptionQuery: PositionsSubscriptionDocument,
|
||||
update,
|
||||
getData: (responseData: PositionsQuery) =>
|
||||
removePaginationWrapper(responseData.party?.positionsConnection?.edges) ||
|
||||
getData: (responseData: PositionsQuery | null) =>
|
||||
removePaginationWrapper(responseData?.party?.positionsConnection?.edges) ||
|
||||
[],
|
||||
getDelta: (subscriptionData: PositionsSubscriptionSubscription) =>
|
||||
subscriptionData.positions,
|
||||
|
@ -2,10 +2,7 @@ import { useCallback, useState } from 'react';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { positionsDataProvider } from './positions-data-providers';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
PositionFieldsFragment,
|
||||
PositionsSubscriptionSubscription,
|
||||
} from './__generated__/Positions';
|
||||
import type { PositionFieldsFragment } from './__generated__/Positions';
|
||||
|
||||
export const useMarketPositionOpenVolume = (marketId: string) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
@ -21,10 +18,7 @@ export const useMarketPositionOpenVolume = (marketId: string) => {
|
||||
[setOpenVolume, marketId]
|
||||
);
|
||||
|
||||
useDataProvider<
|
||||
PositionFieldsFragment[],
|
||||
PositionsSubscriptionSubscription['positions']
|
||||
>({
|
||||
useDataProvider({
|
||||
dataProvider: positionsDataProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey || !marketId,
|
||||
|
@ -1,20 +1,2 @@
|
||||
export * from './hooks';
|
||||
export * from './lib/format';
|
||||
export * from './lib/generic-data-provider';
|
||||
export * from './lib/get-nodes';
|
||||
export * from './lib/get-events';
|
||||
export * from './lib/grid';
|
||||
export * from './lib/i18n';
|
||||
export * from './lib/pagination';
|
||||
export * from './lib/ag-grid-update';
|
||||
export * from './lib/remove-0x';
|
||||
export * from './lib/storage';
|
||||
export * from './lib/time';
|
||||
export * from './lib/validate';
|
||||
export * from './lib/links';
|
||||
export * from './lib/is-asset-erc20';
|
||||
export * from './lib/remove-pagination-wrapper';
|
||||
export * from './lib/__generated__/ChainId';
|
||||
export * from './lib/data-grid';
|
||||
export * from './lib/local-logger';
|
||||
export * from './lib/market-expires';
|
||||
export * from './lib';
|
||||
|
29
libs/react-helpers/src/lib/apollo-client.ts
Normal file
29
libs/react-helpers/src/lib/apollo-client.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import type { ApolloError } from '@apollo/client';
|
||||
import type { GraphQLErrors } from '@apollo/client/errors';
|
||||
|
||||
const NOT_FOUND = 'NotFound';
|
||||
|
||||
const isApolloGraphQLError = (
|
||||
error: ApolloError | Error | undefined
|
||||
): error is ApolloError => {
|
||||
return !!error && !!(error as ApolloError).graphQLErrors;
|
||||
};
|
||||
|
||||
const hasNotFoundGraphQLErrors = (errors: GraphQLErrors, path?: string) => {
|
||||
return errors.some(
|
||||
(e) =>
|
||||
e.extensions &&
|
||||
e.extensions['type'] === NOT_FOUND &&
|
||||
(!path || e.path?.[0] === path)
|
||||
);
|
||||
};
|
||||
|
||||
export const isNotFoundGraphQLError = (
|
||||
error: Error | ApolloError | undefined,
|
||||
path?: string
|
||||
) => {
|
||||
return (
|
||||
isApolloGraphQLError(error) &&
|
||||
hasNotFoundGraphQLErrors(error.graphQLErrors, path)
|
||||
);
|
||||
};
|
@ -62,7 +62,7 @@ const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
||||
query,
|
||||
subscriptionQuery,
|
||||
update,
|
||||
getData: (r) => r.data,
|
||||
getData: (r) => r?.data || null,
|
||||
getDelta: (r) => r.data,
|
||||
});
|
||||
|
||||
@ -91,7 +91,7 @@ const paginatedSubscribe = makeDataProvider<
|
||||
query,
|
||||
subscriptionQuery,
|
||||
update,
|
||||
getData: (r) => r.data,
|
||||
getData: (r) => r?.data || null,
|
||||
getDelta: (r) => r.data,
|
||||
pagination: {
|
||||
first,
|
||||
@ -215,7 +215,7 @@ describe('data provider', () => {
|
||||
const subscription = subscribe(callback, client);
|
||||
await resolveQuery({ data });
|
||||
const delta: Item[] = [];
|
||||
update.mockImplementationOnce((data, delta) => [...data, ...delta]);
|
||||
update.mockImplementationOnce((data, delta) => [...(data || []), ...delta]);
|
||||
// calling onNext from client.subscribe({ query }).subscribe(onNext)
|
||||
await clientSubscribeSubscribe.mock.calls[
|
||||
clientSubscribeSubscribe.mock.calls.length - 1
|
||||
@ -234,7 +234,7 @@ describe('data provider', () => {
|
||||
const subscription = subscribe(callback, client);
|
||||
await resolveQuery({ data });
|
||||
const delta: Item[] = [];
|
||||
update.mockImplementationOnce((data, delta) => data);
|
||||
update.mockImplementationOnce((data, delta) => data || []);
|
||||
const callbackCallsLength = callback.mock.calls.length;
|
||||
// calling onNext from client.subscribe({ query }).subscribe(onNext)
|
||||
await clientSubscribeSubscribe.mock.calls[
|
||||
@ -591,7 +591,7 @@ describe('derived data provider', () => {
|
||||
await resolveQuery({ data: part2 });
|
||||
expect(combineData).toBeCalledTimes(1);
|
||||
expect(callback).toBeCalledTimes(1);
|
||||
update.mockImplementation((data, delta) => [...data, ...delta]);
|
||||
update.mockImplementation((data, delta) => [...(data || []), ...delta]);
|
||||
combineData.mockReturnValueOnce({ ...data });
|
||||
const combinedDelta = {};
|
||||
combineDelta.mockReturnValueOnce(combinedDelta);
|
||||
@ -629,7 +629,7 @@ describe('derived data provider', () => {
|
||||
await resolveQuery({ data: [] });
|
||||
expect(combineData).toBeCalledTimes(1);
|
||||
expect(callback).toBeCalledTimes(1);
|
||||
update.mockImplementation((data, delta) => [...data, ...delta]);
|
||||
update.mockImplementation((data, delta) => [...(data || []), ...delta]);
|
||||
combineData.mockReturnValueOnce({ ...data });
|
||||
const combinedInsertionData = {};
|
||||
combineInsertionData.mockReturnValueOnce(combinedInsertionData);
|
||||
|
@ -8,6 +8,7 @@ import type {
|
||||
} from '@apollo/client';
|
||||
import type { Subscription } from 'zen-observable-ts';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { isNotFoundGraphQLError } from './apollo-client';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
interface UpdateData<Data, Delta> {
|
||||
delta?: Delta;
|
||||
@ -71,7 +72,12 @@ export interface Update<
|
||||
Delta,
|
||||
Variables extends OperationVariables = OperationVariables
|
||||
> {
|
||||
(data: Data, delta: Delta, reload: Reload, variables?: Variables): Data;
|
||||
(
|
||||
data: Data | null,
|
||||
delta: Delta,
|
||||
reload: Reload,
|
||||
variables?: Variables
|
||||
): Data;
|
||||
}
|
||||
|
||||
export interface Append<Data> {
|
||||
@ -88,7 +94,7 @@ export interface Append<Data> {
|
||||
}
|
||||
|
||||
interface GetData<QueryData, Data, Variables> {
|
||||
(queryData: QueryData, variables?: Variables): Data | null;
|
||||
(queryData: QueryData | null, variables?: Variables): Data | null;
|
||||
}
|
||||
|
||||
interface GetPageInfo<QueryData> {
|
||||
@ -160,7 +166,7 @@ interface DataProviderParams<
|
||||
> {
|
||||
query: Query<QueryData>;
|
||||
subscriptionQuery?: Query<SubscriptionData>;
|
||||
update?: Update<Data, Delta, Variables>;
|
||||
update?: Update<Data | null, Delta, Variables>;
|
||||
getData: GetData<QueryData, Data, Variables>;
|
||||
getDelta?: GetDelta<SubscriptionData, Delta, Variables>;
|
||||
pagination?: {
|
||||
@ -349,6 +355,11 @@ function makeDataProviderInternal<
|
||||
}
|
||||
loaded = true;
|
||||
} catch (e) {
|
||||
if (isNotFoundGraphQLError(e as Error, 'party')) {
|
||||
data = getData(null, variables);
|
||||
loaded = true;
|
||||
return;
|
||||
}
|
||||
// if error will occur data provider stops subscription
|
||||
error = e as Error;
|
||||
if (subscription) {
|
||||
@ -384,7 +395,7 @@ function makeDataProviderInternal<
|
||||
return;
|
||||
}
|
||||
const delta = getDelta(subscriptionData, variables);
|
||||
if (loading || !data) {
|
||||
if (loading) {
|
||||
updateQueue.push(delta);
|
||||
} else {
|
||||
const updatedData = update(data, delta, reload, variables);
|
||||
@ -409,7 +420,6 @@ function makeDataProviderInternal<
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (subscriptionQuery && getDelta && update) {
|
||||
subscription = client
|
||||
.subscribe<SubscriptionData>({
|
||||
|
@ -1,16 +1,20 @@
|
||||
export * from './format';
|
||||
export * from './grid';
|
||||
export * from './storage';
|
||||
export * from './validate';
|
||||
export * from './generic-data-provider';
|
||||
export * from './get-nodes';
|
||||
export * from './get-events';
|
||||
export * from './i18n';
|
||||
export * from './pagination';
|
||||
export * from './remove-0x';
|
||||
export * from './time';
|
||||
export * from './links';
|
||||
export * from './remove-pagination-wrapper';
|
||||
export * from './__generated__/ChainId';
|
||||
export * from './ag-grid-update';
|
||||
export * from './apollo-client';
|
||||
export * from './data-grid';
|
||||
export * from './format';
|
||||
export * from './generic-data-provider';
|
||||
export * from './get-events';
|
||||
export * from './get-nodes';
|
||||
export * from './grid';
|
||||
export * from './i18n';
|
||||
export * from './is-asset-erc20';
|
||||
export * from './links';
|
||||
export * from './local-logger';
|
||||
export * from './market-expires';
|
||||
export * from './pagination';
|
||||
export * from './remove-0x';
|
||||
export * from './remove-pagination-wrapper';
|
||||
export * from './storage';
|
||||
export * from './time';
|
||||
export * from './validate';
|
||||
|
@ -20,7 +20,7 @@ import produce from 'immer';
|
||||
export const MAX_TRADES = 50;
|
||||
|
||||
const getData = (
|
||||
responseData: TradesQuery
|
||||
responseData: TradesQuery | null
|
||||
): ({
|
||||
cursor: string;
|
||||
node: TradeFieldsFragment;
|
||||
@ -30,7 +30,7 @@ const getDelta = (subscriptionData: TradesUpdateSubscription) =>
|
||||
subscriptionData?.trades || [];
|
||||
|
||||
const update = (
|
||||
data: ReturnType<typeof getData>,
|
||||
data: ReturnType<typeof getData> | null,
|
||||
delta: ReturnType<typeof getDelta>
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Splash } from '../splash';
|
||||
import type { ReactNode } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { isNotFoundGraphQLError } from '@vegaprotocol/apollo-client';
|
||||
|
||||
interface AsyncRendererProps<T> {
|
||||
loading: boolean;
|
||||
@ -26,7 +25,7 @@ export function AsyncRenderer<T = object>({
|
||||
children,
|
||||
render,
|
||||
}: AsyncRendererProps<T>) {
|
||||
if (error && !isNotFoundGraphQLError(error)) {
|
||||
if (error) {
|
||||
return (
|
||||
<Splash>
|
||||
{errorMessage
|
||||
|
@ -8,6 +8,6 @@ export * from './lib/withdrawal-feedback';
|
||||
export * from './lib/use-complete-withdraw';
|
||||
export * from './lib/use-create-withdraw';
|
||||
export * from './lib/use-verify-withdrawal';
|
||||
export * from './lib/use-withdrawals';
|
||||
export * from './lib/withdrawals-provider';
|
||||
export * from './lib/__generated__/Withdrawal';
|
||||
export * from './lib/__generated__/Erc20Approval';
|
||||
|
@ -1,170 +0,0 @@
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { generateWithdrawal } from './test-helpers';
|
||||
import { updateQuery } from './use-withdrawals';
|
||||
import type {
|
||||
WithdrawalsQuery,
|
||||
WithdrawalEventSubscription,
|
||||
WithdrawalFieldsFragment,
|
||||
} from './__generated__/Withdrawal';
|
||||
|
||||
describe('updateQuery', () => {
|
||||
it('updates existing withdrawals', () => {
|
||||
const withdrawal = generateWithdrawal({
|
||||
id: '1',
|
||||
status: Schema.WithdrawalStatus.STATUS_OPEN,
|
||||
});
|
||||
const withdrawalUpdate = generateWithdrawal({
|
||||
id: '1',
|
||||
status: Schema.WithdrawalStatus.STATUS_FINALIZED,
|
||||
});
|
||||
const prev = mockQuery([withdrawal]);
|
||||
const incoming = mockSub([withdrawalUpdate]);
|
||||
|
||||
expect(updateQuery(prev, incoming)).toEqual({
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: 'party-id',
|
||||
withdrawalsConnection: {
|
||||
__typename: 'WithdrawalsConnection',
|
||||
edges: [
|
||||
{
|
||||
node: withdrawalUpdate,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Adds new withdrawals', () => {
|
||||
const withdrawal = generateWithdrawal({
|
||||
id: '1',
|
||||
amount: '100',
|
||||
});
|
||||
const withdrawalUpdate = generateWithdrawal({
|
||||
id: '2',
|
||||
amount: '200',
|
||||
});
|
||||
const prev = mockQuery([withdrawal]);
|
||||
const incoming = mockSub([withdrawalUpdate]);
|
||||
|
||||
expect(updateQuery(prev, incoming)).toEqual({
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: 'party-id',
|
||||
withdrawalsConnection: {
|
||||
__typename: 'WithdrawalsConnection',
|
||||
edges: [
|
||||
{
|
||||
node: withdrawalUpdate,
|
||||
},
|
||||
{
|
||||
node: withdrawal,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('creates new party if not present', () => {
|
||||
const partyId = 'party-id';
|
||||
const withdrawalUpdate = generateWithdrawal({
|
||||
id: '2',
|
||||
});
|
||||
const incoming = mockSub([withdrawalUpdate]);
|
||||
|
||||
expect(
|
||||
updateQuery({ party: null }, { ...incoming, variables: { partyId } })
|
||||
).toEqual({
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: partyId,
|
||||
withdrawalsConnection: {
|
||||
__typename: 'WithdrawalsConnection',
|
||||
edges: [
|
||||
{
|
||||
node: withdrawalUpdate,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Handles updates and inserts simultaneously', () => {
|
||||
const withdrawal1 = generateWithdrawal({
|
||||
id: '1',
|
||||
status: Schema.WithdrawalStatus.STATUS_OPEN,
|
||||
});
|
||||
const withdrawal2 = generateWithdrawal({
|
||||
id: '2',
|
||||
});
|
||||
const withdrawalUpdate = generateWithdrawal({
|
||||
id: '1',
|
||||
status: Schema.WithdrawalStatus.STATUS_FINALIZED,
|
||||
});
|
||||
const withdrawalNew = generateWithdrawal({
|
||||
id: '3',
|
||||
});
|
||||
|
||||
const prev = mockQuery([withdrawal1, withdrawal2]);
|
||||
const incoming = mockSub([withdrawalUpdate, withdrawalNew]);
|
||||
expect(updateQuery(prev, incoming)).toEqual({
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: 'party-id',
|
||||
withdrawalsConnection: {
|
||||
__typename: 'WithdrawalsConnection',
|
||||
edges: [
|
||||
{
|
||||
node: withdrawalUpdate,
|
||||
},
|
||||
{
|
||||
node: withdrawalNew,
|
||||
},
|
||||
{
|
||||
node: withdrawal2,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const mockQuery = (
|
||||
withdrawals: WithdrawalFieldsFragment[]
|
||||
): WithdrawalsQuery => {
|
||||
return {
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: 'party-id',
|
||||
withdrawalsConnection: {
|
||||
__typename: 'WithdrawalsConnection',
|
||||
edges: withdrawals.map((w) => ({
|
||||
node: w,
|
||||
})),
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const mockSub = (
|
||||
withdrawals: WithdrawalFieldsFragment[]
|
||||
): {
|
||||
subscriptionData: {
|
||||
data: WithdrawalEventSubscription;
|
||||
};
|
||||
} => {
|
||||
return {
|
||||
subscriptionData: {
|
||||
data: {
|
||||
busEvents: withdrawals.map((w) => ({
|
||||
__typename: 'BusEvent',
|
||||
event: w,
|
||||
})),
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
@ -1,111 +0,0 @@
|
||||
import type { UpdateQueryFn } from '@apollo/client/core/watchQueryOptions';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import { useEffect } from 'react';
|
||||
import {
|
||||
useWithdrawalsQuery,
|
||||
WithdrawalEventDocument,
|
||||
} from './__generated__/Withdrawal';
|
||||
import type {
|
||||
WithdrawalsQuery,
|
||||
WithdrawalFieldsFragment,
|
||||
WithdrawalEventSubscription,
|
||||
WithdrawalEventSubscriptionVariables,
|
||||
} from './__generated__/Withdrawal';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/react-helpers';
|
||||
|
||||
type WithdrawalEdges = { node: WithdrawalFieldsFragment }[];
|
||||
|
||||
export const useWithdrawals = () => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data, loading, error, subscribeToMore } = useWithdrawalsQuery({
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!pubKey) return;
|
||||
|
||||
const unsubscribe = subscribeToMore<
|
||||
WithdrawalEventSubscription,
|
||||
WithdrawalEventSubscriptionVariables
|
||||
>({
|
||||
document: WithdrawalEventDocument,
|
||||
variables: { partyId: pubKey },
|
||||
updateQuery,
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [pubKey, subscribeToMore]);
|
||||
|
||||
return {
|
||||
data: removePaginationWrapper(
|
||||
data?.party?.withdrawalsConnection?.edges ?? []
|
||||
).sort((a, b) => {
|
||||
if (!b.txHash !== !a.txHash) {
|
||||
return b.txHash ? -1 : 1;
|
||||
}
|
||||
return (
|
||||
b.txHash ? b.withdrawnTimestamp : b.createdTimestamp
|
||||
).localeCompare(a.txHash ? a.withdrawnTimestamp : a.createdTimestamp);
|
||||
}),
|
||||
loading,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export const updateQuery: UpdateQueryFn<
|
||||
WithdrawalsQuery,
|
||||
WithdrawalEventSubscriptionVariables,
|
||||
WithdrawalEventSubscription
|
||||
> = (prev, { subscriptionData, variables }) => {
|
||||
if (!subscriptionData.data.busEvents?.length) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
const curr = prev.party?.withdrawalsConnection?.edges || [];
|
||||
const incoming = subscriptionData.data.busEvents.reduce<WithdrawalEdges>(
|
||||
(acc, event) => {
|
||||
if (event.event.__typename === 'Withdrawal') {
|
||||
acc.push({
|
||||
node: {
|
||||
...event.event,
|
||||
pendingOnForeignChain: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const edges = uniqBy([...incoming, ...curr], 'node.id');
|
||||
|
||||
// Write new party to cache if not present
|
||||
if (!prev.party) {
|
||||
return {
|
||||
...prev,
|
||||
party: {
|
||||
id: variables?.partyId,
|
||||
__typename: 'Party',
|
||||
withdrawalsConnection: {
|
||||
__typename: 'WithdrawalsConnection',
|
||||
edges,
|
||||
},
|
||||
},
|
||||
} as WithdrawalsQuery;
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
party: {
|
||||
...prev.party,
|
||||
withdrawalsConnection: {
|
||||
__typename: 'WithdrawalsConnection',
|
||||
edges,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
56
libs/withdraws/src/lib/withdrawals-provider.ts
Normal file
56
libs/withdraws/src/lib/withdrawals-provider.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
WithdrawalsDocument,
|
||||
WithdrawalEventDocument,
|
||||
} from './__generated__/Withdrawal';
|
||||
import type {
|
||||
WithdrawalsQuery,
|
||||
WithdrawalFieldsFragment,
|
||||
WithdrawalEventSubscription,
|
||||
WithdrawalEventSubscriptionVariables,
|
||||
} from './__generated__/Withdrawal';
|
||||
import {
|
||||
removePaginationWrapper,
|
||||
getEvents,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
|
||||
const sortWithdrawals = (data: WithdrawalFieldsFragment[]) =>
|
||||
data.sort((a, b) => {
|
||||
if (!b.txHash !== !a.txHash) {
|
||||
return b.txHash ? -1 : 1;
|
||||
}
|
||||
return (b.txHash ? b.withdrawnTimestamp : b.createdTimestamp).localeCompare(
|
||||
a.txHash ? a.withdrawnTimestamp : a.createdTimestamp
|
||||
);
|
||||
});
|
||||
|
||||
export const withdrawalProvider = makeDataProvider<
|
||||
WithdrawalsQuery,
|
||||
WithdrawalFieldsFragment[],
|
||||
WithdrawalEventSubscription,
|
||||
WithdrawalEventSubscription,
|
||||
WithdrawalEventSubscriptionVariables
|
||||
>({
|
||||
query: WithdrawalsDocument,
|
||||
subscriptionQuery: WithdrawalEventDocument,
|
||||
getData: (data: WithdrawalsQuery | null) =>
|
||||
sortWithdrawals(
|
||||
removePaginationWrapper(data?.party?.withdrawalsConnection?.edges || [])
|
||||
),
|
||||
getDelta: (data: WithdrawalEventSubscription) => data,
|
||||
update: (
|
||||
data: WithdrawalFieldsFragment[] | null,
|
||||
delta: WithdrawalEventSubscription
|
||||
) => {
|
||||
if (!delta.busEvents?.length) {
|
||||
return data;
|
||||
}
|
||||
const incoming = getEvents<WithdrawalFieldsFragment>(
|
||||
Schema.BusEventType.Withdrawal,
|
||||
delta.busEvents
|
||||
);
|
||||
return uniqBy([...incoming, ...(data || [])], 'id');
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue
Block a user