Compare commits

..
Author SHA1 Message Date
asiaznik ba38c48755 fix(trading): asset balance being rendered when disconnected from eth wallet 2023-05-05 09:26:30 +02:00
dexturr 023a83e0f7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-05 06:08:12 +00:00
dexturr 4f6ed1eadf chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-05 00:14:53 +00:00
m.ray 85e293f3ec fix(liquidity): use LP order ID as ag-grid row ID (#3615) 2023-05-04 16:23:33 -07:00
dexturr 7b15d2db10 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-04 18:07:23 +00:00
m.ray b1b9695998 fix(liquidity): rows duplicated wrong ag-grid row ID (#3614) 2023-05-04 17:23:52 +00:00
Edd 6b8b33a78b chore(explorer,trading,governance): remove stagnet3 (#3608) 2023-05-04 16:50:39 +00:00
Mikołaj Młodzikowski 4fd0f6819a feat(ci): deploy develop to stagnet1 (#3609) 2023-05-04 14:29:31 +00:00
Mikołaj Młodzikowski 5032d87f98 feat(ci): define max lenght of a branch (#3607) 2023-05-04 16:06:46 +02:00
Matthew Russell b15d9cb7dc fix(governance,trading): validator testnet link for governance app (#3599) 2023-05-04 15:21:24 +02:00
dexturr 6aa7cc5bab chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-04 12:09:32 +00:00
Bartłomiej Głownia c37f9ebe66 feat(trading): divide order tab into open, closed, rejected and all (#3541) 2023-05-04 12:09:55 +02:00
Art 768b3b29f0 feat(trading): protocol upgrade notification (#3517) 2023-05-04 09:51:24 +02:00
dexturr 378946f22b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-04 06:07:49 +00:00
dexturr 523598645a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-04 00:13:39 +00:00
98 changed files with 1250 additions and 988 deletions
+16
View File
@@ -0,0 +1,16 @@
name: 'Check if branch is shorter than 52 chars'
on: pull_request
jobs:
branch-naming-rules:
runs-on: ubuntu-latest
steps:
# echo "branches that are longer than 51 chars can't be parsed by kubernetes to create previews. Each app has prefix of it's name like: 'governance-' (12 chars), what leaves 51 max branch length"
# current parsable length: $( git rev-parse --abbrev-ref HEAD | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | wc -c)
- uses: deepakputhraya/action-branch-name@master
with:
# regex: '([a-z])+\/([a-z])+' # Regex the branch should match. This example enforces grouping
# allowed_prefixes: 'feature,stable,fix' # All branches should start with the given prefix
# ignore: master,develop # Ignore exactly matching branch names from convention
min_length: 1 # Min length of the branch name
max_length: 51 # Max length of the branch name
+1 -1
View File
@@ -105,7 +105,7 @@ jobs:
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
echo -n "Affected projects: $affected"
branch_slug="$(echo ${{ github.head_ref || github.ref_name }} | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g )"
branch_slug="$(echo ${{ github.head_ref || github.ref_name }} | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | cut -c 1-50 )"
projects_e2e=""
preview_governance="not deployed"
preview_trading="not deployed"
+1 -1
View File
@@ -66,7 +66,7 @@ jobs:
fi
fi
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
envName="stagnet3"
envName="stagnet1"
fi
bucketName="${{ matrix.app }}.${envName}.${domain}"
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
-1
View File
@@ -7,5 +7,4 @@ __generated___
apps/static/src/assets/devnet-tranches.json
apps/static/src/assets/mainnet-tranches.json
apps/static/src/assets/stagnet3-tranches.json
apps/static/src/assets/testnet-tranches.json
-18
View File
@@ -1,18 +0,0 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
# App flags
NX_EXPLORER_ASSETS=1
NX_EXPLORER_GENESIS=1
NX_EXPLORER_GOVERNANCE=1
NX_EXPLORER_MARKETS=1
NX_EXPLORER_ORACLES=1
NX_EXPLORER_TXS_LIST=0
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
+12 -8
View File
@@ -1,13 +1,17 @@
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_NETWORKS='{"STAGNET1":"https://stagnet1.token.vega.xyz", "STAGNET3":"https://stagnet3.explorer.vega.xyz","VALIDATOR_TESTNET":"https://validator-testnet.fairground.wtf","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://stagnet1.token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo
# App flags
NX_EXPLORER_ASSETS=1
-8
View File
@@ -6,12 +6,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
# App flags
NX_EXPLORER_ASSETS=1
NX_EXPLORER_GENESIS=1
NX_EXPLORER_GOVERNANCE=1
NX_EXPLORER_MARKETS=1
NX_EXPLORER_ORACLES=1
NX_EXPLORER_TXS_LIST=0
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
+1 -14
View File
@@ -1,14 +1 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://stagnet1.token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
# .env is stagnet1, so there are no overrides required
-8
View File
@@ -1,8 +0,0 @@
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_ENV=STAGNET3
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases/
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1 -2
View File
@@ -35,12 +35,11 @@ Example configurations are provided here:
- [Devnet](./.env.devnet)
- [Capsule](./.env.capsule)
- [Testnet](./.env.testnet)
- [Stagnet3](./.env.stagnet3)
For convenience, you can boot the app injecting one of the configurations above by running:
```bash
yarn nx run explorer:serve --env={env} # e.g. stagnet3
yarn nx run explorer:serve --env={env} # e.g. stagnet1
```
There are a few different configuration options offered for this app:
+1 -1
View File
@@ -13,7 +13,7 @@ NX_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
-5
View File
@@ -1,5 +0,0 @@
# App configuration variables
NX_VEGA_ENV=STAGNET3
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -89,6 +89,6 @@ export function mockNetworkUpgradeProposal() {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Nodes', nodeData);
aliasGQLQuery(req, 'Proposals', proposalsData);
aliasGQLQuery(req, 'ProtocolUpgrades', upgradeProposalsData);
aliasGQLQuery(req, 'ProtocolUpgradeProposals', upgradeProposalsData);
});
}
+6 -6
View File
@@ -1,18 +1,18 @@
# App configuration variables
NX_VEGA_ENV=STAGNET3
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET1
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
+2 -2
View File
@@ -3,7 +3,7 @@ NX_VEGA_ENV=CUSTOM
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_CONFIG_URL=''
@@ -16,7 +16,7 @@ NX_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
#Test configuration variables
CYPRESS_FAIRGROUND=false
+1 -1
View File
@@ -2,7 +2,7 @@
NX_VEGA_ENV=DEVNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_URL=https://api.n00.devnet1.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
+1 -1
View File
@@ -2,7 +2,7 @@
NX_VEGA_ENV=MAINNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.xyz/query
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
+1 -1
View File
@@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_VEGA_ENV=STAGNET1
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
-11
View File
@@ -1,11 +0,0 @@
# App configuration variables
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1 -1
View File
@@ -2,7 +2,7 @@
NX_VEGA_ENV=TESTNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
+1 -1
View File
@@ -3,7 +3,7 @@ NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
+1 -2
View File
@@ -27,12 +27,11 @@ Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Devnet](./.env.devnet)
- [Testnet](./.env.testnet)
- [Stagnet3](./.env.stagnet3)
For convenience, you can boot the app injecting one of the configurations above by running:
```bash
yarn nx run governance:serve --env={env} # e.g. stagnet3
yarn nx run governance:serve --env={env} # e.g. stagnet1
```
There are a few different configuration options offered for this app:
-4
View File
@@ -33,10 +33,6 @@ export const ContractAddresses: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
STAGNET3: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
TESTNET: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
+3 -3
View File
@@ -15,7 +15,6 @@ import Routes from '../routes';
import { ExternalLinks, removePaginationWrapper } from '@vegaprotocol/utils';
import { useNodesQuery } from '../staking/home/__generated__/Nodes';
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
import { useProtocolUpgradesQuery } from '../proposals/protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import {
getNotRejectedProposals,
getNotRejectedProtocolUpgradeProposals,
@@ -25,7 +24,8 @@ import * as Schema from '@vegaprotocol/types';
import type { RouteChildProps } from '..';
import type { ProposalFieldsFragment } from '../proposals/proposals/__generated__/Proposals';
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
import type { ProtocolUpgradeProposalFieldsFragment } from '../proposals/protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
const nodesToShow = 6;
@@ -181,7 +181,7 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
data: protocolUpgradesData,
loading: protocolUpgradesLoading,
error: protocolUpgradesError,
} = useProtocolUpgradesQuery({
} = useProtocolUpgradeProposalsQuery({
pollInterval: 5000,
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
@@ -12,7 +12,7 @@ import { ExternalLinks } from '@vegaprotocol/utils';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '../../protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
interface ProposalsListProps {
proposals: Array<ProposalFieldsFragment | ProposalQuery['proposal']>;
@@ -5,7 +5,7 @@ import {
RoundedWrapper,
} from '@vegaprotocol/ui-toolkit';
import { SubHeading } from '../../../../components/heading';
import type { ProtocolUpgradeProposalFieldsFragment } from '../../protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
export interface ProtocolUpgradeProposalDetailInfoProps {
proposal: ProtocolUpgradeProposalFieldsFragment;
@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { ProtocolUpgradeProposalsListItem } from './protocol-upgrade-proposals-list-item';
import { ProtocolUpgradeProposalStatus } from '@vegaprotocol/types';
import type { ProtocolUpgradeProposalFieldsFragment } from '../../protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
const proposal = {
status:
@@ -11,8 +11,8 @@ import { stripFullStops } from '@vegaprotocol/utils';
import { ProtocolUpgradeProposalStatus } from '@vegaprotocol/types';
import { SubHeading } from '../../../../components/heading';
import type { ReactNode } from 'react';
import type { ProtocolUpgradeProposalFieldsFragment } from '../../protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import Routes from '../../../routes';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
interface ProtocolProposalsListItemProps {
proposal: ProtocolUpgradeProposalFieldsFragment;
@@ -13,10 +13,9 @@ import {
} from '@vegaprotocol/types';
import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils';
import type { ProposalFieldsFragment } from './__generated__/Proposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '../protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import orderBy from 'lodash/orderBy';
import { useProtocolUpgradesQuery } from '../protocol-upgrade/__generated__/ProtocolUpgradeProposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
const orderByDate = (arr: ProposalFieldsFragment[]) =>
orderBy(
@@ -73,7 +72,7 @@ export const ProposalsContainer = () => {
data: protocolUpgradesData,
loading: protocolUpgradesLoading,
error: protocolUpgradesError,
} = useProtocolUpgradesQuery({
} = useProtocolUpgradeProposalsQuery({
pollInterval: 5000,
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
@@ -1,59 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProtocolUpgradeProposalFieldsFragment = { __typename?: 'ProtocolUpgradeProposal', upgradeBlockHeight: string, vegaReleaseTag: string, approvers: Array<string>, status: Types.ProtocolUpgradeProposalStatus };
export type ProtocolUpgradesQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ProtocolUpgradesQuery = { __typename?: 'Query', lastBlockHeight: string, protocolUpgradeProposals?: { __typename?: 'ProtocolUpgradeProposalConnection', edges?: Array<{ __typename?: 'ProtocolUpgradeProposalEdge', node: { __typename?: 'ProtocolUpgradeProposal', upgradeBlockHeight: string, vegaReleaseTag: string, approvers: Array<string>, status: Types.ProtocolUpgradeProposalStatus } }> | null } | null };
export const ProtocolUpgradeProposalFieldsFragmentDoc = gql`
fragment ProtocolUpgradeProposalFields on ProtocolUpgradeProposal {
upgradeBlockHeight
vegaReleaseTag
approvers
status
}
`;
export const ProtocolUpgradesDocument = gql`
query ProtocolUpgrades {
lastBlockHeight
protocolUpgradeProposals {
edges {
node {
...ProtocolUpgradeProposalFields
}
}
}
}
${ProtocolUpgradeProposalFieldsFragmentDoc}`;
/**
* __useProtocolUpgradesQuery__
*
* To run a query within a React component, call `useProtocolUpgradesQuery` and pass it any options that fit your needs.
* When your component renders, `useProtocolUpgradesQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useProtocolUpgradesQuery({
* variables: {
* },
* });
*/
export function useProtocolUpgradesQuery(baseOptions?: Apollo.QueryHookOptions<ProtocolUpgradesQuery, ProtocolUpgradesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ProtocolUpgradesQuery, ProtocolUpgradesQueryVariables>(ProtocolUpgradesDocument, options);
}
export function useProtocolUpgradesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProtocolUpgradesQuery, ProtocolUpgradesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ProtocolUpgradesQuery, ProtocolUpgradesQueryVariables>(ProtocolUpgradesDocument, options);
}
export type ProtocolUpgradesQueryHookResult = ReturnType<typeof useProtocolUpgradesQuery>;
export type ProtocolUpgradesLazyQueryHookResult = ReturnType<typeof useProtocolUpgradesLazyQuery>;
export type ProtocolUpgradesQueryResult = Apollo.QueryResult<ProtocolUpgradesQuery, ProtocolUpgradesQueryVariables>;
@@ -6,14 +6,14 @@ import * as Schema from '@vegaprotocol/types';
import { ProtocolUpgradeProposal } from './protocol-upgrade-proposal';
import { ProposalNotFound } from '../components/proposal-not-found';
import { useProtocolUpgradesQuery } from './__generated__/ProtocolUpgradeProposals';
import { useNodesQuery } from '../../staking/home/__generated__/Nodes';
import { useRefreshAfterEpoch } from '../../../hooks/use-refresh-after-epoch';
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
export const ProtocolUpgradeProposalContainer = () => {
const params = useParams<{ proposalReleaseTag: string }>();
const { data, loading, error, refetch } = useProtocolUpgradesQuery({
const { data, loading, error, refetch } = useProtocolUpgradeProposalsQuery({
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
skip: !params.proposalReleaseTag,
@@ -9,7 +9,7 @@ import {
import { ProtocolUpgradeProposalStatus } from '@vegaprotocol/types';
import { getNormalisedVotingPower } from '../../staking/shared';
import type { NodesFragmentFragment } from '../../staking/home/__generated__/Nodes';
import type { ProtocolUpgradeProposalFieldsFragment } from './__generated__/ProtocolUpgradeProposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
const mockProposal: ProtocolUpgradeProposalFieldsFragment = {
vegaReleaseTag: 'v0.1.234',
@@ -3,8 +3,8 @@ import { ProtocolUpgradeProposalDetailHeader } from '../components/protocol-upgr
import { ProtocolUpdateProposalDetailApprovals } from '../components/protocol-upgrade-proposal-detail-approvals';
import { ProtocolUpgradeProposalDetailInfo } from '../components/protocol-upgrade-proposal-detail-info';
import { getNormalisedVotingPower } from '../../staking/shared';
import type { ProtocolUpgradeProposalFieldsFragment } from './__generated__/ProtocolUpgradeProposals';
import type { NodesFragmentFragment } from '../../staking/home/__generated__/Nodes';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
export interface ProtocolUpgradeProposalProps {
proposal: ProtocolUpgradeProposalFieldsFragment;
+1 -1
View File
@@ -23,5 +23,5 @@ NX_VEGA_URL="https://api.n07.testnet.vega.xyz/graphql"
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
@@ -2,7 +2,7 @@
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
NX_VEGA_ENV=DEVNET
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
@@ -5,4 +5,4 @@ NX_VEGA_ENV=STAGNET1
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
@@ -1,8 +0,0 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_EXPLORER_URL=https://staging2.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
+3 -3
View File
@@ -1,5 +1,5 @@
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_URL=https://api.stagnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
NX_VEGA_ENV=STAGNET1
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
-5
View File
@@ -1,5 +0,0 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
+1 -2
View File
@@ -22,12 +22,11 @@ Example configurations are provided here:
- [Devnet](./.env.devnet)
- [Capsule](./.env.capsule)
- [Testnet](./.env.testnet)
- [Stagnet3](./.env.stagnet3)
For convenience, you can boot the app injecting one of the configurations above by running:
```bash
yarn nx run multisig-signer:serve --env={env} # e.g. stagnet3
yarn nx run multisig-signer:serve --env={env} # e.g. stagnet1
```
There are a few different configuration options offered for this app:
+94 -28
View File
@@ -1,4 +1,15 @@
[
{
"tranche_id": 58,
"tranche_start": "2023-05-11T00:00:00.000Z",
"tranche_end": "2023-06-11T00:00:00.000Z",
"total_added": "0",
"total_removed": "0",
"locked_amount": "0",
"deposits": [],
"withdrawals": [],
"users": []
},
{
"tranche_id": 57,
"tranche_start": "2024-04-01T00:00:00.000Z",
@@ -37,8 +48,8 @@
"tranche_start": "2023-04-20T00:00:00.000Z",
"tranche_end": "2023-05-20T00:00:00.000Z",
"total_added": "19242.125",
"total_removed": "959.3245960538025",
"locked_amount": "10418.7792376543211777",
"total_removed": "1214.9959502191275",
"locked_amount": "9457.0664415991503175975",
"deposits": [
{
"amount": "188",
@@ -236,6 +247,11 @@
"amount": "422.1034736680125",
"user": "0xf915Da10e5136352Ba049acB0545Deb119054256",
"tx": "0x5932f574afe019060f5812fc89c7298ab9f768cddebe0a803c27e9914b45dc3d"
},
{
"amount": "255.671354165325",
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tx": "0x92cd553dcee22eb58abadc7aab2dc8d4d9b2285943b41aacea8ed09eff5a0914"
}
],
"users": [
@@ -297,11 +313,17 @@
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tranche_id": 56,
"tx": "0x5f544a659ae728cc7b1a29dcda14740425cadf1f47aa74bae92bf2ade3c8093d"
},
{
"amount": "255.671354165325",
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tranche_id": 56,
"tx": "0x92cd553dcee22eb58abadc7aab2dc8d4d9b2285943b41aacea8ed09eff5a0914"
}
],
"total_tokens": "1207.5",
"withdrawn_tokens": "341.3307146949",
"remaining_tokens": "866.1692853051"
"withdrawn_tokens": "597.002068860225",
"remaining_tokens": "610.497931139775"
},
{
"address": "0x33Ce1D9E53AFb7367E34749517C086405a651a95",
@@ -845,7 +867,7 @@
"tranche_end": "2023-05-06T00:00:00.000Z",
"total_added": "14520",
"total_removed": "5079.76864115505",
"locked_amount": "1085.952592592592978",
"locked_amount": "360.24949074073997136",
"deposits": [
{
"amount": "111",
@@ -4715,7 +4737,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297",
"total_removed": "0",
"locked_amount": "51107.876034425155701037",
"locked_amount": "50751.8588230648417449891",
"deposits": [
{
"amount": "86666.297",
@@ -4781,7 +4803,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500",
"total_removed": "0",
"locked_amount": "387.962962962963",
"locked_amount": "367.3669935388685",
"deposits": [
{
"amount": "2500",
@@ -4814,7 +4836,7 @@
"tranche_end": "2023-11-01T00:00:00.000Z",
"total_added": "15000.000000000000015",
"total_removed": "0",
"locked_amount": "14775.301932367149014775301932367149",
"locked_amount": "14653.0693312198065146530693312198065",
"deposits": [
{
"amount": "1.5e-14",
@@ -4902,7 +4924,7 @@
"tranche_end": "2023-09-01T00:00:00.000Z",
"total_added": "17500",
"total_removed": "0",
"locked_amount": "11436.2218196457315",
"locked_amount": "11293.61711830716525",
"deposits": [
{
"amount": "12500",
@@ -5169,7 +5191,7 @@
"tranche_end": "2023-08-01T00:00:00.000Z",
"total_added": "37500",
"total_removed": "17836.1796921",
"locked_amount": "18489.717618170655",
"locked_amount": "18179.07122851442625",
"deposits": [
{
"amount": "7500",
@@ -5577,7 +5599,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "51061.24652818329987399",
"locked_amount": "50705.5541377325336221035",
"deposits": [
{
"amount": "129999.45",
@@ -5610,7 +5632,7 @@
"tranche_end": "2024-04-01T00:00:00.000Z",
"total_added": "54144.7663",
"total_removed": "0",
"locked_amount": "49298.9138196269965560045",
"locked_amount": "49077.09978780568889746099",
"deposits": [
{
"amount": "54144.7663",
@@ -5643,7 +5665,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600",
"total_removed": "0",
"locked_amount": "20965.63247082699134",
"locked_amount": "20708.477403602233016",
"deposits": [
{
"amount": "10000",
@@ -5836,7 +5858,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "1866.352105530188",
"locked_amount": "1845.81256341958375",
"deposits": [
{
"amount": "5000",
@@ -6894,7 +6916,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "1709370.7872515768348",
"locked_amount": "155426.5500030847769098336",
"locked_amount": "147457.5018725717723958",
"deposits": [
{
"amount": "1852091.69",
@@ -40766,7 +40788,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "715655.108029600523393",
"locked_amount": "263337.818306825404305623187",
"locked_amount": "251092.165858100635559352498",
"deposits": [
{
"amount": "1998.95815",
@@ -42158,8 +42180,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "867610.78878511272497352",
"locked_amount": "6233466.5814528903248765151216390212111382",
"total_removed": "869802.17678213314859352",
"locked_amount": "6190044.28411574715560088425053188532414163",
"deposits": [
{
"amount": "16249.93",
@@ -42713,6 +42735,11 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xc5cea08b124cdf6264d5b0c7494d63d9de264b429822d9a4e4cfadc43e611a1b"
},
{
"amount": "2191.38799702042362",
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
"tx": "0xa809dbfa0c31522127924306a6117331a578dfc402cf5fa464832baec46e4ac2"
},
{
"amount": "981.387731774910625",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -46611,6 +46638,12 @@
"tranche_id": 2,
"tx": "0x9d12dadb940c59a796a405a4971e73f24d7ad284528ec7ce676ae361a4ac1f51"
},
{
"amount": "2191.38799702042362",
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
"tranche_id": 2,
"tx": "0xa809dbfa0c31522127924306a6117331a578dfc402cf5fa464832baec46e4ac2"
},
{
"amount": "2873.74755113623213",
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
@@ -46883,8 +46916,8 @@
}
],
"total_tokens": "150551.801",
"withdrawn_tokens": "89385.81693579122338",
"remaining_tokens": "61165.98406420877662"
"withdrawn_tokens": "91577.204932811647",
"remaining_tokens": "58974.596067188353"
},
{
"address": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148",
@@ -48747,8 +48780,8 @@
"tranche_start": "2021-11-05T00:00:00.000Z",
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "6168897.174282186485373182",
"locked_amount": "33251.32064708015607663338925032586",
"total_removed": "6169862.126766503085603932",
"locked_amount": "0",
"deposits": [
{
"amount": "129284.449",
@@ -49007,6 +49040,11 @@
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x53d67a8df4d069f956ae1eb76d5e099642dcc8d7e40fa9357be0b8ae879b90c4"
},
{
"amount": "964.95248431660023075",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x35f722557b9bc3a2dc314f9fac173013697c484059bd8d5c65497f8df72b9097"
},
{
"amount": "1360.32447632896938825",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -52349,6 +52387,12 @@
"tranche_id": 3,
"tx": "0x53d67a8df4d069f956ae1eb76d5e099642dcc8d7e40fa9357be0b8ae879b90c4"
},
{
"amount": "964.95248431660023075",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x35f722557b9bc3a2dc314f9fac173013697c484059bd8d5c65497f8df72b9097"
},
{
"amount": "1360.32447632896938825",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -55171,8 +55215,8 @@
}
],
"total_tokens": "359123.469575",
"withdrawn_tokens": "357792.4615146437139805",
"remaining_tokens": "1331.0080603562860195"
"withdrawn_tokens": "358757.41399896031421125",
"remaining_tokens": "366.05557603968578875"
},
{
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
@@ -58846,8 +58890,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "44078.8527972103416",
"locked_amount": "41727.382613860946149215697311012",
"total_removed": "44110.3307271943416",
"locked_amount": "39786.9889842268933819326661593",
"deposits": [
{
"amount": "3000",
@@ -65501,6 +65545,11 @@
"user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53",
"tx": "0x1e4902d0a3cb7b4f2ba7119dfcaa681a784e1d724c984961767e9feaa078fe54"
},
{
"amount": "31.477929984",
"user": "0xcB555C5602cC0b2434A27d277e14Cb5C7bF4Ead1",
"tx": "0x1b9ddd24634b4c6eab202f0a65dc0d3119fbc5502cbac5086352eab14ebd7b02"
},
{
"amount": "168.502276762",
"user": "0x38A292CB98Dc602ECAFF94E8E5fADD9800e4bA13",
@@ -84326,6 +84375,12 @@
}
],
"withdrawals": [
{
"amount": "31.477929984",
"user": "0xcB555C5602cC0b2434A27d277e14Cb5C7bF4Ead1",
"tranche_id": 5,
"tx": "0x1b9ddd24634b4c6eab202f0a65dc0d3119fbc5502cbac5086352eab14ebd7b02"
},
{
"amount": "19.918569252",
"user": "0xcB555C5602cC0b2434A27d277e14Cb5C7bF4Ead1",
@@ -84370,8 +84425,8 @@
}
],
"total_tokens": "400",
"withdrawn_tokens": "334.458891424",
"remaining_tokens": "65.541108576"
"withdrawn_tokens": "365.936821408",
"remaining_tokens": "34.063178592"
},
{
"address": "0x3738bec36216eA2F11B954891C65AAd1Bc852156",
@@ -144155,6 +144210,11 @@
}
],
"withdrawals": [
{
"amount": "0",
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
"tx": "0xbc31dbb6851f0e1a856afaedfe96fba29ed357ba1da151eb27c495aa49ab1f39"
},
{
"amount": "0",
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
@@ -144445,6 +144505,12 @@
}
],
"withdrawals": [
{
"amount": "0",
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
"tranche_id": 9,
"tx": "0xbc31dbb6851f0e1a856afaedfe96fba29ed357ba1da151eb27c495aa49ab1f39"
},
{
"amount": "0",
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
@@ -1,3 +0,0 @@
{
"hosts": ["https://api-stagnet3.vega.rocks/graphql"]
}
+1 -1
View File
@@ -6,7 +6,7 @@ NX_VEGA_CONFIG_URL=''
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
+1 -1
View File
@@ -5,7 +5,7 @@ NX_VEGA_CONFIG_URL=''
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
-24
View File
@@ -1,24 +0,0 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://stagnet3.token.vega.xyz
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_ETH_WALLET_MNEMONIC=
CYPRESS_ETHEREUM_WALLET_ADDRESS=0xEe7D375bcB50C26d52E1A4a472D8822A2A22d94F
CYPRESS_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
CYPRESS_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=1a18cd…0cf2e4
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=47836c…c7d278
CYPRESS_VEGA_ENV=STAGNET3
CYPRESS_VEGA_PUBLIC_KEY=1a18cdcaaa4f44a57b35a4e9b77e0701c17a476f2b407620f8c17371740cf2e4
CYPRESS_VEGA_PUBLIC_KEY2=47836c253520d2661bf5bed6339c0de08fd02cf5d4db0efee3b4373f20c7d278
CYPRESS_VEGA_TOKEN_URL=https://stagnet3.token.vega.xyz
CYPRESS_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
CYPRESS_VEGA_WALLET_API_TOKEN=
@@ -9,6 +9,21 @@ describe('market bottom panel', { tags: '@smoke' }, () => {
it('on xxl screen should be splitted out into two tables', () => {
cy.getByTestId('tab-positions').should('have.attr', 'data-state', 'active');
cy.getByTestId('tab-open-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-closed-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-rejected-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-orders').should('have.attr', 'data-state', 'inactive');
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'inactive');
cy.getByTestId('tab-accounts').should(
@@ -19,7 +34,22 @@ describe('market bottom panel', { tags: '@smoke' }, () => {
cy.viewport(1801, 1000);
cy.getByTestId('tab-positions').should('have.attr', 'data-state', 'active');
cy.getByTestId('tab-orders').should('have.attr', 'data-state', 'active');
cy.getByTestId('tab-open-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-closed-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-rejected-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-orders').should('have.attr', 'data-state', 'inactive');
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'inactive');
cy.getByTestId('tab-accounts').should(
'have.attr',
@@ -29,7 +29,7 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.mockSubscription(subscriptionMocks);
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.getByTestId('All').click();
cy.wait('@Markets');
});
@@ -87,7 +87,7 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.get('[col-id="status"] .ag-icon-menu').click();
});
cy.contains('Partially Filled').click();
cy.getByTestId('Orders').click();
cy.getByTestId('All').click();
cy.get(`[row-id="${partiallyFilledId}"]`)
.eq(1)
@@ -116,7 +116,7 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.get('[col-id="status"] .ag-icon-menu').click();
});
cy.contains('Reset').click();
cy.getByTestId('Orders').click();
cy.getByTestId('All').click();
cy.getByTestId('tab-orders')
.get(`.ag-center-cols-container [col-id='${orderSymbol}']`)
@@ -139,14 +139,15 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
});
describe('subscribe orders', { tags: '@smoke' }, () => {
before(() => {
let orderId = '0';
beforeEach(() => {
const subscriptionMocks = getSubscriptionMocks();
cy.spy(subscriptionMocks, 'OrdersUpdate');
cy.mockTradingPage();
cy.mockSubscription(subscriptionMocks);
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.getByTestId('All').click();
cy.getByTestId('tab-orders').within(() => {
cy.get('[col-id="status"][role="columnheader"]')
.focus()
@@ -154,8 +155,8 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
.click();
cy.get('.ag-filter-apply-panel-button').click();
});
orderId = (parseInt(orderId, 10) + 1).toString();
});
const orderId = '1234567890';
// 7002-SORD-053
// 7002-SORD-040
// 7003-MORD-001
@@ -299,7 +300,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
});
cy.get(`[row-id=${orderId}]`)
.find('[col-id="price"]')
.should('have.text', '200.00');
.should('have.text', '-');
});
it('must see the time in force applied to the order', () => {
@@ -370,7 +371,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
cy.mockSubscription(subscriptionMocks);
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.getByTestId('All').click();
cy.getByTestId('tab-orders').within(() => {
cy.get('[col-id="status"][role="columnheader"]')
.focus()
+4 -4
View File
@@ -3,10 +3,10 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
+2 -2
View File
@@ -4,8 +4,8 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=''
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
+1 -1
View File
@@ -5,7 +5,7 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_ENV=DEVNET
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
+1 -1
View File
@@ -4,7 +4,7 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_ENV=MAINNET
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
+1 -1
View File
@@ -5,7 +5,7 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
-14
View File
@@ -1,14 +0,0 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
+1 -1
View File
@@ -5,7 +5,7 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_ENV=TESTNET
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
+1 -1
View File
@@ -5,7 +5,7 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_EXPLORER_URL=https://validator-testnet.explorer.vega.xyz
NX_VEGA_NETWORKS={\"STAGNET3\":\"https://stagnet3.console.vega.xyz\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
NX_VEGA_NETWORKS={\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
NX_VEGA_TOKEN_URL=https://validator-testnet.governance.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
+1 -2
View File
@@ -21,12 +21,11 @@ Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Devnet](./.env.devnet)
- [Testnet](./.env.testnet)
- [Stagnet3](./.env.stagnet3)
For convenience, you can boot the app injecting one of the configurations above by running:
```bash
yarn nx run token:serve --env={env} # e.g. stagnet3
yarn nx run token:serve --env={env} # e.g. stagnet1
```
There are a few different configuration options offered for this app:
+144 -32
View File
@@ -1,7 +1,8 @@
import { DealTicketContainer } from '@vegaprotocol/deal-ticket';
import { MarketInfoAccordionContainer } from '@vegaprotocol/market-info';
import { OrderbookContainer } from '@vegaprotocol/market-depth';
import { OrderListContainer } from '@vegaprotocol/orders';
import { OrderListContainer, Filter } from '@vegaprotocol/orders';
import type { OrderListContainerProps } from '@vegaprotocol/orders';
import { FillsContainer } from '@vegaprotocol/fills';
import { PositionsContainer } from '@vegaprotocol/positions';
import { TradesContainer } from '@vegaprotocol/trades';
@@ -58,17 +59,59 @@ const requiresMarket = (View: MarketDependantView) => {
};
const TradingViews = {
Candles: requiresMarket(CandlesChartContainer),
Depth: requiresMarket(DepthChartContainer),
Liquidity: requiresMarket(LiquidityContainer),
Ticket: requiresMarket(DealTicketContainer),
Info: requiresMarket(MarketInfoAccordionContainer),
Orderbook: requiresMarket(OrderbookContainer),
Trades: requiresMarket(TradesContainer),
Positions: PositionsContainer,
Orders: OrderListContainer,
Collateral: AccountsContainer,
Fills: FillsContainer,
candles: {
label: 'Candles',
component: requiresMarket(CandlesChartContainer),
},
depth: {
label: 'Depth',
component: requiresMarket(DepthChartContainer),
},
liquidity: {
label: 'Liquidity',
component: requiresMarket(LiquidityContainer),
},
ticket: {
label: 'Ticket',
component: requiresMarket(DealTicketContainer),
},
info: {
label: 'Info',
component: requiresMarket(MarketInfoAccordionContainer),
},
orderbook: {
label: 'Orderbook',
component: requiresMarket(OrderbookContainer),
},
trades: {
label: 'Trades',
component: requiresMarket(TradesContainer),
},
positions: { label: 'Positions', component: PositionsContainer },
activeOrders: {
label: 'Active',
component: (props: OrderListContainerProps) => (
<OrderListContainer {...props} filter={Filter.Open} />
),
},
closedOrders: {
label: 'Closed',
component: (props: OrderListContainerProps) => (
<OrderListContainer {...props} filter={Filter.Closed} />
),
},
rejectedOrders: {
label: 'Rejected',
component: (props: OrderListContainerProps) => (
<OrderListContainer {...props} filter={Filter.Rejected} />
),
},
orders: {
label: 'All',
component: OrderListContainer,
},
collateral: { label: 'Collateral', component: AccountsContainer },
fills: { label: 'Fills', component: FillsContainer },
};
type TradingView = keyof typeof TradingViews;
@@ -104,9 +147,42 @@ const MarketBottomPanel = memo(
>
<TradeGridChild>
<Tabs storageKey="console-trade-grid-bottom-left">
<Tab id="orders" name={t('Orders')}>
<Tab id="open-orders" name={t('Open')}>
<VegaWalletContainer>
<TradingViews.Orders
<TradingViews.orders.component
marketId={marketId}
filter={Filter.Open}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
</Tab>
<Tab id="closed-orders" name={t('Closed')}>
<VegaWalletContainer>
<TradingViews.orders.component
marketId={marketId}
filter={Filter.Closed}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
</Tab>
<Tab id="rejected-orders" name={t('Rejected')}>
<VegaWalletContainer>
<TradingViews.orders.component
marketId={marketId}
filter={Filter.Rejected}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
</Tab>
<Tab id="orders" name={t('All')}>
<VegaWalletContainer>
<TradingViews.orders.component
marketId={marketId}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
@@ -116,7 +192,7 @@ const MarketBottomPanel = memo(
</Tab>
<Tab id="fills" name={t('Fills')}>
<VegaWalletContainer>
<TradingViews.Fills
<TradingViews.fills.component
marketId={marketId}
onMarketClick={onMarketClick}
/>
@@ -134,7 +210,7 @@ const MarketBottomPanel = memo(
<Tabs storageKey="console-trade-grid-bottom-right">
<Tab id="positions" name={t('Positions')}>
<VegaWalletContainer>
<TradingViews.Positions
<TradingViews.positions.component
onMarketClick={onMarketClick}
noBottomPlaceholder
/>
@@ -142,7 +218,7 @@ const MarketBottomPanel = memo(
</Tab>
<Tab id="accounts" name={t('Collateral')}>
<VegaWalletContainer>
<TradingViews.Collateral
<TradingViews.collateral.component
pinnedAsset={pinnedAsset}
noBottomPlaceholder
hideButtons
@@ -158,12 +234,45 @@ const MarketBottomPanel = memo(
<Tabs storageKey="console-trade-grid-bottom">
<Tab id="positions" name={t('Positions')}>
<VegaWalletContainer>
<TradingViews.Positions onMarketClick={onMarketClick} />
<TradingViews.positions.component onMarketClick={onMarketClick} />
</VegaWalletContainer>
</Tab>
<Tab id="orders" name={t('Orders')}>
<Tab id="open-orders" name={t('Open')}>
<VegaWalletContainer>
<TradingViews.Orders
<TradingViews.orders.component
marketId={marketId}
filter={Filter.Open}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
</Tab>
<Tab id="closed-orders" name={t('Closed')}>
<VegaWalletContainer>
<TradingViews.orders.component
marketId={marketId}
filter={Filter.Closed}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
</Tab>
<Tab id="rejected-orders" name={t('Rejected')}>
<VegaWalletContainer>
<TradingViews.orders.component
marketId={marketId}
filter={Filter.Rejected}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
</Tab>
<Tab id="orders" name={t('All')}>
<VegaWalletContainer>
<TradingViews.orders.component
marketId={marketId}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
@@ -173,7 +282,7 @@ const MarketBottomPanel = memo(
</Tab>
<Tab id="fills" name={t('Fills')}>
<VegaWalletContainer>
<TradingViews.Fills
<TradingViews.fills.component
marketId={marketId}
onMarketClick={onMarketClick}
/>
@@ -181,7 +290,10 @@ const MarketBottomPanel = memo(
</Tab>
<Tab id="accounts" name={t('Collateral')}>
<VegaWalletContainer>
<TradingViews.Collateral pinnedAsset={pinnedAsset} hideButtons />
<TradingViews.collateral.component
pinnedAsset={pinnedAsset}
hideButtons
/>
</VegaWalletContainer>
</Tab>
</Tabs>
@@ -221,13 +333,13 @@ const MainGrid = memo(
<TradeGridChild>
<Tabs storageKey="console-trade-grid-main-left">
<Tab id="chart" name={t('Chart')}>
<TradingViews.Candles marketId={marketId} />
<TradingViews.candles.component marketId={marketId} />
</Tab>
<Tab id="depth" name={t('Depth')}>
<TradingViews.Depth marketId={marketId} />
<TradingViews.depth.component marketId={marketId} />
</Tab>
<Tab id="liquidity" name={t('Liquidity')}>
<TradingViews.Liquidity marketId={marketId} />
<TradingViews.liquidity.component marketId={marketId} />
</Tab>
</Tabs>
</TradeGridChild>
@@ -240,13 +352,13 @@ const MainGrid = memo(
<TradeGridChild>
<Tabs storageKey="console-trade-grid-main-center">
<Tab id="ticket" name={t('Ticket')}>
<TradingViews.Ticket
<TradingViews.ticket.component
marketId={marketId}
onClickCollateral={() => navigate('/portfolio')}
/>
</Tab>
<Tab id="info" name={t('Info')}>
<TradingViews.Info marketId={marketId} />
<TradingViews.info.component marketId={marketId} />
</Tab>
</Tabs>
</TradeGridChild>
@@ -259,10 +371,10 @@ const MainGrid = memo(
<TradeGridChild>
<Tabs storageKey="console-trade-grid-main-right">
<Tab id="orderbook" name={t('Orderbook')}>
<TradingViews.Orderbook marketId={marketId} />
<TradingViews.orderbook.component marketId={marketId} />
</Tab>
<Tab id="trades" name={t('Trades')}>
<TradingViews.Trades marketId={marketId} />
<TradingViews.trades.component marketId={marketId} />
</Tab>
</Tabs>
</TradeGridChild>
@@ -330,7 +442,7 @@ export const TradePanels = ({
const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler(true);
const [view, setView] = useState<TradingView>('Candles');
const [view, setView] = useState<TradingView>('candles');
const renderView = () => {
const Component = memo<{
marketId: string;
@@ -339,7 +451,7 @@ export const TradePanels = ({
onOrderTypeClick?: (marketId: string) => void;
onClickCollateral: () => void;
pinnedAsset?: PinnedAsset;
}>(TradingViews[view]);
}>(TradingViews[view].component);
if (!Component) {
throw new Error(`No component for view: ${view}`);
@@ -388,7 +500,7 @@ export const TradePanels = ({
className={className}
key={key}
>
{key}
{TradingViews[key as keyof typeof TradingViews].label}
</button>
);
})}
+8 -1
View File
@@ -24,6 +24,10 @@ import {
import { Links, Routes } from '../../pages/client-router';
import { createDocsLinks } from '@vegaprotocol/utils';
import { SettingsButton } from '../../client-pages/settings';
import {
ProtocolUpgradeCountdown,
ProtocolUpgradeCountdownMode,
} from '@vegaprotocol/proposals';
export const Navbar = ({
theme = 'system',
@@ -45,11 +49,14 @@ export const Navbar = ({
theme={theme}
actions={
<>
<ProtocolUpgradeCountdown
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
/>
<SettingsButton />
<VegaWalletConnectButton />
</>
}
breakpoints={[521, 1067]}
breakpoints={[521, 1122]}
>
<NavigationList
className="[.drawer-content_&]:border-b [.drawer-content_&]:border-b-vega-light-200 dark:[.drawer-content_&]:border-b-vega-dark-200 [.drawer-content_&]:pb-8 [.drawer-content_&]:mb-2"
@@ -5,7 +5,5 @@ export const ViewingBanner = () => {
const { isReadOnly, pubKey, disconnect } = useVegaWallet();
return isReadOnly ? (
<ViewingAsBanner pubKey={pubKey} disconnect={disconnect} />
) : (
<div />
);
) : null;
};
@@ -20,7 +20,6 @@ describe('Risk notice dialog', () => {
assertion | network
${'displays'} | ${Networks.CUSTOM}
${'displays'} | ${Networks.DEVNET}
${'displays'} | ${Networks.STAGNET3}
${'displays'} | ${Networks.TESTNET}
`(
'$assertion a generic message on $network',
+16 -2
View File
@@ -35,8 +35,12 @@ import { AppLoader, DynamicLoader } from '../components/app-loader';
import { Navbar } from '../components/navbar';
import { ENV } from '../lib/config';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { activeOrdersProvider } from '@vegaprotocol/orders';
import { activeOrdersProvider, allOrdersProvider } from '@vegaprotocol/orders';
import { useTelemetryApproval } from '../lib/hooks/use-telemetry-approval';
import {
ProtocolUpgradeCountdownMode,
ProtocolUpgradeProposalNotification,
} from '@vegaprotocol/proposals';
const DEFAULT_TITLE = t('Welcome to Vega trading!');
@@ -89,7 +93,12 @@ function AppBody({ Component }: AppProps) {
<div className={gridClasses}>
<AnnouncementBanner />
<Navbar theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'system'} />
<ViewingBanner />
<div data-testid="banners">
<ProtocolUpgradeProposalNotification
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
/>
<ViewingBanner />
</div>
<main data-testid={location.pathname}>
<Component />
</main>
@@ -141,6 +150,11 @@ const PartyData = () => {
variables,
skip,
});
useDataProvider({
dataProvider: allOrdersProvider,
variables,
skip,
});
return null;
};
+2 -2
View File
@@ -37,9 +37,9 @@ export const AccountManager = ({
variables,
});
const setId = useCallback(
(data: AccountFields) => ({
(data: AccountFields, id: string) => ({
...data,
asset: { ...data.asset, id: `${data.asset.id}-1` },
asset: { ...data.asset, id },
}),
[]
);
+15 -9
View File
@@ -126,14 +126,20 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
return currentPinnedAssetRow;
}, [pinnedAssetId, props.pinnedAsset, props.rowData]);
const getRowHeight = useCallback(
(params: RowHeightParams) =>
params.node.rowPinned &&
params.data.asset.id === pinnedAssetId &&
new BigNumber(params.data.total).isLessThanOrEqualTo(0)
? 32
: 24,
[pinnedAssetId]
const { getRowHeight } = props;
const getPinnedAssetRowHeight = useCallback(
(params: RowHeightParams) => {
if (
params.node.rowPinned &&
params.data.asset.id === pinnedAssetId &&
new BigNumber(params.data.total).isLessThanOrEqualTo(0)
) {
return 32;
}
return getRowHeight ? getRowHeight(params) : undefined;
},
[pinnedAssetId, getRowHeight]
);
return (
@@ -155,7 +161,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
sortable: true,
comparator: accountValuesComparator,
}}
getRowHeight={getRowHeight}
getRowHeight={getPinnedAssetRowHeight}
pinnedTopRowData={pinnedAssetRow ? [pinnedAssetRow] : undefined}
>
<AgGridColumn
+80 -75
View File
@@ -9,85 +9,90 @@ import {
import type { IDoesFilterPassParams, IFilterParams } from 'ag-grid-community';
import { t } from '@vegaprotocol/i18n';
export const SetFilter = forwardRef((props: IFilterParams, ref) => {
const [value, setValue] = useState<string[]>([]);
const valueRef = useRef(value);
export const SetFilter = forwardRef(
(props: IFilterParams & { readonly?: boolean }, ref) => {
const [value, setValue] = useState<string[]>([]);
const valueRef = useRef(value);
const { readonly } = props;
// expose AG Grid Filter Lifecycle callbacks
useImperativeHandle(ref, () => {
return {
doesFilterPass(params: IDoesFilterPassParams) {
const { api, colDef, column, columnApi, context } = props;
const { node } = params;
const getValue = props.valueGetter({
api,
colDef,
column,
columnApi,
context,
data: node.data,
getValue: (field) => node.data[field],
node,
});
return Array.isArray(value)
? value.includes(getValue)
: getValue === value;
},
// expose AG Grid Filter Lifecycle callbacks
useImperativeHandle(ref, () => {
return {
doesFilterPass(params: IDoesFilterPassParams) {
const { api, colDef, column, columnApi, context } = props;
const { node } = params;
const getValue = props.valueGetter({
api,
colDef,
column,
columnApi,
context,
data: node.data,
getValue: (field) => node.data[field],
node,
});
return Array.isArray(value)
? value.includes(getValue)
: getValue === value;
},
isFilterActive() {
return valueRef.current.length !== 0;
},
isFilterActive() {
return valueRef.current.length !== 0;
},
getModel() {
if (!this.isFilterActive()) {
return null;
}
return { value: valueRef.current };
},
getModel() {
if (!this.isFilterActive()) {
return null;
}
return { value: valueRef.current };
},
setModel(model?: { value: string[] } | null) {
valueRef.current = !model ? [] : model.value;
setValue(valueRef.current);
},
};
});
setModel(model?: { value: string[] } | null) {
valueRef.current = !model ? [] : model.value;
setValue(valueRef.current);
},
const onChange = (event: ChangeEvent<HTMLInputElement>) => {
valueRef.current = event.target.checked
? [...value, event.target.value]
: value.filter((v) => v !== event.target.value);
setValue(valueRef.current);
};
});
const onChange = (event: ChangeEvent<HTMLInputElement>) => {
valueRef.current = event.target.checked
? [...value, event.target.value]
: value.filter((v) => v !== event.target.value);
setValue(valueRef.current);
};
useEffect(() => {
props.filterChangedCallback();
}, [value]); //eslint-disable-line react-hooks/exhaustive-deps
return (
<div className="ag-filter-body-wrapper">
<fieldset className="ag-simple-filter-body-wrapper">
{Object.keys(props.colDef.filterParams.set).map((key) => (
<label className="flex" key={key}>
<input
type="checkbox"
value={key}
className="mr-1"
checked={value.includes(key)}
onChange={onChange}
/>
<span>{props.colDef.filterParams.set[key]}</span>
</label>
))}
</fieldset>
<div className="ag-filter-apply-panel">
<button
type="button"
className="ag-standard-button ag-filter-apply-panel-button"
onClick={() => setValue((valueRef.current = []))}
>
{t('Reset')}
</button>
useEffect(() => {
props.filterChangedCallback();
}, [value]); //eslint-disable-line react-hooks/exhaustive-deps
return (
<div className="ag-filter-body-wrapper">
<fieldset className="ag-simple-filter-body-wrapper">
{Object.keys(props.colDef.filterParams.set).map((key) => (
<label className="flex" key={key}>
<input
type="checkbox"
value={key}
disabled={readonly}
className="mr-1"
checked={value.includes(key)}
onChange={onChange}
/>
<span>{props.colDef.filterParams.set[key]}</span>
</label>
))}
</fieldset>
{!readonly && (
<div className="ag-filter-apply-panel">
<button
type="button"
disabled={readonly}
className="ag-standard-button ag-filter-apply-panel-button"
onClick={() => setValue((valueRef.current = []))}
>
{t('Reset')}
</button>
</div>
)}
</div>
</div>
);
});
);
}
);
+3 -1
View File
@@ -260,7 +260,9 @@ export const DepositForm = ({
<AssetOption
asset={asset}
key={asset.id}
balance={<AssetBalance asset={asset} />}
balance={
isActive && account && <AssetBalance asset={asset} />
}
/>
))}
</RichSelect>
@@ -14,12 +14,11 @@ jest.mock('../../hooks/use-environment');
describe('Network switcher', () => {
it.each`
network | label
${Networks.CUSTOM} | ${envTriggerMapping[Networks.CUSTOM]}
${Networks.DEVNET} | ${envTriggerMapping[Networks.DEVNET]}
${Networks.STAGNET3} | ${envTriggerMapping[Networks.STAGNET3]}
${Networks.TESTNET} | ${envTriggerMapping[Networks.TESTNET]}
${Networks.MAINNET} | ${envTriggerMapping[Networks.MAINNET]}
network | label
${Networks.CUSTOM} | ${envTriggerMapping[Networks.CUSTOM]}
${Networks.DEVNET} | ${envTriggerMapping[Networks.DEVNET]}
${Networks.TESTNET} | ${envTriggerMapping[Networks.TESTNET]}
${Networks.MAINNET} | ${envTriggerMapping[Networks.MAINNET]}
`(
'displays the correct selection label for $network',
({ network, label }) => {
@@ -137,7 +136,6 @@ describe('Network switcher', () => {
[Networks.MAINNET]: 'https://main.net',
[Networks.TESTNET]: 'https://test.net',
[Networks.VALIDATOR_TESTNET]: 'https://validator-test.net',
[Networks.STAGNET3]: 'https://stag3.net',
[Networks.DEVNET]: 'https://dev.net',
[Networks.STAGNET1]: 'https://stag1.net',
};
@@ -154,12 +152,7 @@ describe('Network switcher', () => {
screen.getByRole('menuitem', { name: t('Advanced') })
);
[
Networks.MAINNET,
Networks.TESTNET,
Networks.STAGNET3,
Networks.DEVNET,
].forEach((network) => {
[Networks.MAINNET, Networks.TESTNET, Networks.DEVNET].forEach((network) => {
expect(
screen.getByRole('link', { name: envNameMapping[network] })
).toHaveAttribute('href', VEGA_NETWORKS[network]);
@@ -176,7 +169,6 @@ describe('Network switcher', () => {
[Networks.MAINNET]: 'https://main.net',
[Networks.VALIDATOR_TESTNET]: 'https://validator-test.net',
[Networks.TESTNET]: 'https://test.net',
[Networks.STAGNET3]: 'https://stag3.net',
[Networks.DEVNET]: 'https://dev.net',
[Networks.STAGNET1]: 'https://stag1.net',
};
@@ -208,7 +200,6 @@ describe('Network switcher', () => {
[Networks.MAINNET]: undefined,
[Networks.VALIDATOR_TESTNET]: 'https://validator-test.net',
[Networks.TESTNET]: 'https://test.net',
[Networks.STAGNET3]: 'https://stag3.net',
[Networks.DEVNET]: 'https://dev.net',
[Networks.STAGNET1]: 'https://stag1.net',
};
@@ -18,7 +18,6 @@ export const envNameMapping: Record<Networks, string> = {
[Networks.CUSTOM]: t('Custom'),
[Networks.DEVNET]: t('Devnet'),
[Networks.STAGNET1]: t('Stagnet'),
[Networks.STAGNET3]: t('Stagnet3'),
[Networks.TESTNET]: t('Fairground testnet'),
[Networks.MAINNET]: t('Mainnet'),
};
@@ -33,7 +32,6 @@ export const envDescriptionMapping: Record<Networks, string> = {
[Networks.VALIDATOR_TESTNET]: t('The validator deployed testnet'),
[Networks.DEVNET]: t('The latest Vega code auto-deployed'),
[Networks.STAGNET1]: t('A release candidate for the staging environment'),
[Networks.STAGNET3]: t('A staging environment with trading'),
[Networks.TESTNET]: t(
'Public testnet run by the Vega team, often used for incentives'
),
@@ -44,7 +42,6 @@ const standardNetworkKeys = [Networks.MAINNET, Networks.TESTNET];
const advancedNetworkKeys = [
Networks.MAINNET,
Networks.TESTNET,
Networks.STAGNET3,
Networks.DEVNET,
];
@@ -55,7 +55,6 @@ const mockEnvVars = {
VEGA_NETWORKS: {
DEVNET: 'https://devnet.url',
TESTNET: 'https://testnet.url',
STAGNET3: 'https://stagnet3.url',
MAINNET: 'https://mainnet.url',
},
VEGA_WALLET_URL: 'https://localhost:1234',
+18 -4
View File
@@ -2,6 +2,7 @@ import trim from 'lodash/trim';
import { useCallback } from 'react';
import { Networks } from '../types';
import { useEnvironment } from './use-environment';
import { stripFullStops } from '@vegaprotocol/utils';
type Net = Exclude<Networks, 'CUSTOM'>;
export enum DApp {
@@ -18,7 +19,6 @@ const EmptyLinks: DAppLinks = {
[Networks.VALIDATOR_TESTNET]: '',
[Networks.DEVNET]: '',
[Networks.STAGNET1]: '',
[Networks.STAGNET3]: '',
[Networks.TESTNET]: '',
[Networks.MAINNET]: '',
};
@@ -33,14 +33,12 @@ const ExplorerLinks = {
const ConsoleLinks = {
...EmptyLinks,
[Networks.STAGNET1]: 'https://stagnet1.console.vega.xyz',
[Networks.STAGNET3]: 'https://stagnet3.console.vega.xyz',
[Networks.TESTNET]: 'https://console.fairground.wtf',
};
const TokenLinks = {
...EmptyLinks,
[Networks.DEVNET]: 'https://dev.token.vega.xyz',
[Networks.STAGNET3]: 'https://stagnet3.token.vega.xyz',
[Networks.TESTNET]: 'https://token.fairground.wtf',
[Networks.VALIDATOR_TESTNET]: 'https://validator-testnet.governance.vega.xyz',
[Networks.MAINNET]: 'https://token.vega.xyz',
@@ -89,15 +87,31 @@ export const useEtherscanLink = () => {
// Vega blog
export const BLOG = 'https://blog.vega.xyz/';
// Token pages
// Governance pages
export const TOKEN_NEW_MARKET_PROPOSAL = '/proposals/propose/new-market';
export const TOKEN_NEW_NETWORK_PARAM_PROPOSAL =
'/proposals/propose/network-parameter';
export const TOKEN_GOVERNANCE = '/proposals';
export const TOKEN_PROPOSALS = '/proposals';
export const TOKEN_PROPOSAL = '/proposals/:id';
export const TOKEN_PROTOCOL_UPGRADE_PROPOSAL =
'/proposals/protocol-upgrade/:tag';
export const TOKEN_VALIDATOR = '/validators/:id';
/**
* Generates link to the protocol upgrade proposal details on Governance
*/
export const useProtocolUpgradeProposalLink = () => {
const governance = useLinks(DApp.Token);
return (releaseTag: string) =>
governance(
TOKEN_PROTOCOL_UPGRADE_PROPOSAL.replace(
':tag',
stripFullStops(releaseTag)
)
);
};
// Explorer pages
export const EXPLORER_TX = '/txs/:hash';
export const EXPLORER_ORACLE = '/oracles/:id';
-1
View File
@@ -7,7 +7,6 @@ export enum Networks {
CUSTOM = 'CUSTOM',
TESTNET = 'TESTNET',
STAGNET1 = 'STAGNET1',
STAGNET3 = 'STAGNET3',
DEVNET = 'DEVNET',
MAINNET = 'MAINNET',
}
@@ -5,7 +5,6 @@ export enum Networks {
CUSTOM = 'CUSTOM',
TESTNET = 'TESTNET',
STAGNET1 = 'STAGNET1',
STAGNET3 = 'STAGNET3',
DEVNET = 'DEVNET',
MAINNET = 'MAINNET',
}
+2 -1
View File
@@ -62,7 +62,7 @@ export const FillsManager = ({
scrolledToTop.current = event.top <= 0;
}, []);
const { isFullWidthRow, fullWidthCellRenderer, rowClassRules } =
const { isFullWidthRow, fullWidthCellRenderer, rowClassRules, getRowHeight } =
useBottomPlaceholder<Trade>({
gridRef,
});
@@ -82,6 +82,7 @@ export const FillsManager = ({
isFullWidthRow={isFullWidthRow}
fullWidthCellRenderer={fullWidthCellRenderer}
rowClassRules={rowClassRules}
getRowHeight={getRowHeight}
/>
<div className="pointer-events-none absolute inset-0">
<AsyncRenderer
@@ -22,7 +22,6 @@ import type {
LiquidityProvisionsQueryVariables,
LiquidityProvisionsUpdateSubscription,
} from './__generated__/MarketLiquidity';
import type { IterableElement } from 'type-fest';
export const liquidityProvisionsDataProvider = makeDataProvider<
LiquidityProvisionsQuery,
@@ -39,8 +38,8 @@ export const liquidityProvisionsDataProvider = makeDataProvider<
) => {
return produce(data || [], (draft) => {
deltas?.forEach((delta) => {
const id = getId(delta);
const index = draft.findIndex((a) => getId(a) === id);
const id = delta.id;
const index = draft.findIndex((a) => delta.id === id);
if (index !== -1) {
draft[index].commitmentAmount = delta.commitmentAmount;
draft[index].fee = delta.fee;
@@ -76,27 +75,6 @@ export const liquidityProvisionsDataProvider = makeDataProvider<
},
});
function isLpFragment(
entry:
| LiquidityProvisionFieldsFragment
| IterableElement<
LiquidityProvisionsUpdateSubscription['liquidityProvisions']
>
): entry is LiquidityProvisionFieldsFragment {
return entry.__typename === 'LiquidityProvision';
}
export const getId = (
entry:
| LiquidityProvisionFieldsFragment
| IterableElement<
LiquidityProvisionsUpdateSubscription['liquidityProvisions']
>
) =>
isLpFragment(entry)
? `${entry.party.id}${entry.status}${entry.createdAt}${entry.updatedAt}`
: `${entry.partyID}${entry.status}${entry.createdAt}${entry.updatedAt}`;
export const marketLiquidityDataProvider = makeDataProvider<
MarketLpQuery,
MarketLpQuery,
+1 -2
View File
@@ -17,7 +17,6 @@ import type { ValueFormatterParams } from 'ag-grid-community';
import BigNumber from 'bignumber.js';
import { LiquidityProvisionStatusMapping } from '@vegaprotocol/types';
import type { LiquidityProvisionData } from './liquidity-data-provider';
import { getId } from './liquidity-data-provider';
const percentageFormatter = ({ value }: ValueFormatterParams) => {
if (!value) return '-';
@@ -56,7 +55,7 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
<AgGrid
style={{ width: '100%', height: '100%' }}
overlayNoRowsTemplate={t('No liquidity provisions')}
getRowId={({ data }) => getId(data)}
getRowId={({ data }) => data.id}
ref={ref}
tooltipShowDelay={500}
defaultColDef={{
@@ -7,15 +7,14 @@ describe('order data provider', () => {
const data = [
{
node: {
id: '1',
updatedAt: new Date('2022-01-31').toISOString(),
id: '2',
createdAt: new Date('2022-01-29').toISOString(),
},
},
{
node: {
id: '2',
createdAt: new Date('2022-01-30').toISOString(),
id: '1',
createdAt: new Date('2022-01-28').toISOString(),
},
},
] as Edge<OrderFieldsFragment>[];
@@ -24,47 +23,51 @@ describe('order data provider', () => {
// this one should be dropped because id don't exits and it's older than newest
{
id: '0',
createdAt: new Date('2022-01-30').toISOString(),
createdAt: new Date('2022-01-27').toISOString(),
},
// this one should be dropped because newer below
{
id: '1',
updatedAt: new Date('2022-02-01').toISOString(),
createdAt: new Date('2022-01-29').toISOString(),
createdAt: new Date('2022-01-28').toISOString(),
},
{
id: '1',
updatedAt: new Date('2022-02-02').toISOString(),
createdAt: new Date('2022-01-29').toISOString(),
updatedAt: new Date('2022-02-04').toISOString(),
createdAt: new Date('2022-01-28').toISOString(),
},
// this should be added
{
id: '4',
createdAt: new Date('2022-02-04').toISOString(),
},
// this should be move to top
{
id: '2',
updatedAt: new Date('2022-02-03').toISOString(),
createdAt: new Date('2022-01-29').toISOString(),
updatedAt: new Date('2022-02-04').toISOString(),
createdAt: new Date('2022-01-30').toISOString(),
},
// this should be added
{
id: '5',
createdAt: new Date('2022-02-05').toISOString(),
},
] as OrderUpdateFieldsFragment[];
const updatedData = update(data, delta, () => null, { partyId: '0x123' });
expect(
updatedData?.findIndex((edge) => edge.node.id === delta[0].id)
).toEqual(-1);
expect(updatedData && updatedData[2].node.id).toEqual(delta[2].id);
expect(updatedData && updatedData[2].node.updatedAt).toEqual(
expect(updatedData && updatedData[3].node.id).toEqual(delta[2].id);
expect(updatedData && updatedData[3].node.updatedAt).toEqual(
delta[2].updatedAt
);
expect(updatedData && updatedData[0].node.id).toEqual(delta[3].id);
expect(updatedData && updatedData[1].node.id).toEqual(delta[4].id);
expect(updatedData && updatedData[1].node.updatedAt).toEqual(
expect(updatedData && updatedData[0].node.id).toEqual(delta[5].id);
expect(updatedData && updatedData[1].node.id).toEqual(delta[3].id);
expect(updatedData && updatedData[2].node.id).toEqual(delta[4].id);
expect(updatedData && updatedData[2].node.updatedAt).toEqual(
delta[4].updatedAt
);
expect(update([], delta, () => null, { partyId: '0x123' })?.length).toEqual(
4
5
);
});
it('add only data matching date range filter', () => {
@@ -72,7 +75,6 @@ describe('order data provider', () => {
{
node: {
id: '1',
updatedAt: new Date('2022-01-31').toISOString(),
createdAt: new Date('2022-01-29').toISOString(),
},
},
@@ -90,12 +92,6 @@ describe('order data provider', () => {
id: '0',
createdAt: new Date('2022-02-02').toISOString(),
},
// this one should be removed because it does not match date range
{
id: '1',
updatedAt: new Date('2022-02-02').toISOString(),
createdAt: new Date('2022-01-29').toISOString(),
},
// this one should be updated
{
id: '2',
@@ -118,16 +114,13 @@ describe('order data provider', () => {
expect(
updatedData?.findIndex((edge) => edge.node.id === delta[0].id)
).toEqual(-1);
expect(
updatedData?.findIndex((edge) => edge.node.id === delta[1].id)
).toEqual(-1);
expect(updatedData && updatedData[0].node.id).toEqual(delta[2].id);
expect(updatedData && updatedData[0].node.updatedAt).toEqual(
delta[2].updatedAt
);
expect(updatedData && updatedData[1].node.id).toEqual(delta[3].id);
expect(updatedData && updatedData[1].node.updatedAt).toEqual(
delta[3].updatedAt
expect(updatedData && updatedData[2].node.id).toEqual(delta[1].id);
expect(updatedData && updatedData[2].node.updatedAt).toEqual(
delta[1].updatedAt
);
});
});
@@ -5,8 +5,6 @@ import {
makeDataProvider,
makeDerivedDataProvider,
defaultAppend as append,
paginatedCombineDelta as combineDelta,
paginatedCombineInsertionData as combineInsertionData,
} from '@vegaprotocol/utils';
import type { Market } from '@vegaprotocol/market-list';
import { marketsProvider } from '@vegaprotocol/market-list';
@@ -28,6 +26,11 @@ export type Order = Omit<OrderFieldsFragment, 'market'> & {
};
export type OrderEdge = Edge<Order>;
const liveOnlyOrderStatuses = [
OrderStatus.STATUS_ACTIVE,
OrderStatus.STATUS_PARKED,
];
const orderMatchFilters = (
order: OrderUpdateFieldsFragment,
variables: OrdersQueryVariables
@@ -41,6 +44,12 @@ const orderMatchFilters = (
) {
return false;
}
if (
variables?.filter?.liveOnly &&
!(order.status && liveOnlyOrderStatuses.includes(order.status))
) {
return false;
}
if (
variables?.filter?.types &&
!(order.type && variables.filter.types.includes(order.type))
@@ -58,19 +67,13 @@ const orderMatchFilters = (
}
if (
variables?.filter?.dateRange?.start &&
!(
(order.updatedAt || order.createdAt) &&
variables.filter.dateRange.start < (order.updatedAt || order.createdAt)
)
!(order.createdAt && variables.filter.dateRange.start < order.createdAt)
) {
return false;
}
if (
variables?.filter?.dateRange?.end &&
!(
(order.updatedAt || order.createdAt) &&
variables.filter.dateRange.end > (order.updatedAt || order.createdAt)
)
!(order.createdAt && variables.filter.dateRange.end > order.createdAt)
) {
return false;
}
@@ -120,28 +123,25 @@ export const update = (
if (!data) {
return data;
}
return produce(data, (draft) => {
// A single update can contain the same order with multiple updates, so we need to find
// the latest version of the order and only update using that
const incoming = uniqBy(
// A single update can contain the same order with multiple updates, so we need to find
// the latest version of the order and only update using that
const incoming = orderBy(
uniqBy(
orderBy(delta, (order) => order.updatedAt || order.createdAt, 'desc'),
'id'
);
),
'createdAt'
);
return produce(data, (draft) => {
// Add or update incoming orders
incoming.reverse().forEach((node) => {
incoming.forEach((node) => {
const index = draft.findIndex((edge) => edge.node.id === node.id);
const newer =
draft.length === 0 ||
(node.updatedAt || node.createdAt) >=
(draft[0].node.updatedAt || draft[0].node.createdAt);
draft.length === 0 || node.createdAt >= draft[0].node.createdAt;
const doesFilterPass = !variables || orderMatchFilters(node, variables);
if (index !== -1) {
if (doesFilterPass) {
Object.assign(draft[index].node, node);
if (newer) {
draft.unshift(...draft.splice(index, 1));
}
} else {
draft.splice(index, 1);
}
@@ -194,6 +194,34 @@ const ordersProvider = makeDataProvider<
additionalContext: { isEnlargedTimeout: true },
});
const allOrderMaxCount = 50000;
export const allOrdersProvider = makeDerivedDataProvider<
ReturnType<typeof getData>,
never,
{ partyId: string; marketId?: string }
>(
[
(callback, client, variables) =>
ordersProvider(callback, client, { partyId: variables.partyId }),
],
(partsData, variables, prevData, parts, subscriptions) => {
const orders = partsData[0] as ReturnType<typeof getData>;
// load next pages until allOrderMaxCount reached
if (
!parts[0].isUpdate &&
subscriptions &&
subscriptions[0].load &&
orders?.length < allOrderMaxCount
) {
subscriptions[0].load();
}
return variables.marketId
? orders.filter((edge) => variables.marketId === edge.node.market.id)
: orders;
}
);
export const activeOrdersProvider = makeDerivedDataProvider<
ReturnType<typeof getData>,
never,
@@ -204,11 +232,12 @@ export const activeOrdersProvider = makeDerivedDataProvider<
ordersProvider(callback, client, {
partyId: variables.partyId,
filter: {
status: [OrderStatus.STATUS_ACTIVE, OrderStatus.STATUS_PARKED],
liveOnly: true,
},
}),
],
(partsData, variables, prevData, parts, subscriptions) => {
// load all pages
if (!parts[0].isUpdate && subscriptions && subscriptions[0].load) {
subscriptions[0].load();
}
@@ -220,7 +249,7 @@ export const activeOrdersProvider = makeDerivedDataProvider<
);
export const ordersWithMarketProvider = makeDerivedDataProvider<
(OrderEdge | null)[],
(Order | null)[],
Order[],
OrdersQueryVariables
>(
@@ -228,18 +257,13 @@ export const ordersWithMarketProvider = makeDerivedDataProvider<
ordersProvider,
(callback, client) => marketsProvider(callback, client, undefined),
],
(partsData): OrderEdge[] =>
(partsData): Order[] =>
((partsData[0] as ReturnType<typeof getData>) || []).map((edge) => ({
cursor: edge.cursor,
node: {
...edge.node,
market: (partsData[1] as Market[]).find(
(market) => market.id === edge.node.market.id
),
},
})),
combineDelta<Order, ReturnType<typeof getDelta>['0']>,
combineInsertionData<Order>
...edge.node,
market: (partsData[1] as Market[]).find(
(market) => market.id === edge.node.market.id
),
}))
);
export const hasActiveOrderProvider = makeDerivedDataProvider<
@@ -2,18 +2,23 @@ import { t } from '@vegaprotocol/i18n';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { OrderListManager } from './order-list-manager';
import type { Filter } from './order-list-manager';
export interface OrderListContainerProps {
marketId?: string;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void;
enforceBottomPlaceholder?: boolean;
filter?: Filter;
}
export const OrderListContainer = ({
marketId,
onMarketClick,
onOrderTypeClick,
enforceBottomPlaceholder,
}: {
marketId?: string;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void;
enforceBottomPlaceholder?: boolean;
}) => {
filter,
}: OrderListContainerProps) => {
const { pubKey, isReadOnly } = useVegaWallet();
if (!pubKey) {
@@ -24,6 +29,7 @@ export const OrderListContainer = ({
<OrderListManager
partyId={pubKey}
marketId={marketId}
filter={filter}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
isReadOnly={isReadOnly}
@@ -1,2 +1 @@
export * from './order-list-manager';
export * from './use-order-list-data';
@@ -1,25 +1,41 @@
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { useCallback, useEffect, useRef, useState } from 'react';
import type { FilterChangedEvent, SortChangedEvent } from 'ag-grid-community';
import { Button } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import type { GridReadyEvent } from 'ag-grid-community';
import type { GridReadyEvent, FilterChangedEvent } from 'ag-grid-community';
import { OrderListTable } from '../order-list/order-list';
import { useOrderListData } from './use-order-list-data';
import { useHasAmendableOrder } from '../../order-hooks/use-has-amendable-order';
import type { Filter, Sort } from './use-order-list-data';
import { useBottomPlaceholder } from '@vegaprotocol/react-helpers';
import { OrderStatus } from '@vegaprotocol/types';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { ordersWithMarketProvider } from '../order-data-provider/order-data-provider';
import {
normalizeOrderAmendment,
useVegaTransactionStore,
} from '@vegaprotocol/wallet';
import isEqual from 'lodash/isEqual';
import type { OrderTxUpdateFieldsFragment } from '@vegaprotocol/wallet';
import { OrderEditDialog } from '../order-list/order-edit-dialog';
import type { Order, OrderEdge } from '../order-data-provider';
import type { Order } from '../order-data-provider';
import { OrderStatus } from '@vegaprotocol/types';
export enum Filter {
'Open',
'Closed',
'Rejected',
}
const FilterStatusValue = {
[Filter.Open]: [OrderStatus.STATUS_ACTIVE, OrderStatus.STATUS_PARKED],
[Filter.Closed]: [
OrderStatus.STATUS_CANCELLED,
OrderStatus.STATUS_EXPIRED,
OrderStatus.STATUS_FILLED,
OrderStatus.STATUS_PARTIALLY_FILLED,
OrderStatus.STATUS_STOPPED,
],
[Filter.Rejected]: [OrderStatus.STATUS_REJECTED],
};
export interface OrderListManagerProps {
partyId: string;
@@ -28,6 +44,7 @@ export interface OrderListManagerProps {
onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void;
isReadOnly: boolean;
enforceBottomPlaceholder?: boolean;
filter?: Filter;
}
const CancelAllOrdersButton = ({ onClick }: { onClick: () => void }) => (
@@ -43,12 +60,6 @@ const CancelAllOrdersButton = ({ onClick }: { onClick: () => void }) => (
</div>
);
const initialFilter: Filter = {
status: {
value: [OrderStatus.STATUS_ACTIVE, OrderStatus.STATUS_PARKED],
},
};
export const OrderListManager = ({
partyId,
marketId,
@@ -56,27 +67,22 @@ export const OrderListManager = ({
onOrderTypeClick,
isReadOnly,
enforceBottomPlaceholder,
filter,
}: OrderListManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const [dataCount, setDataCount] = useState(0);
const scrolledToTop = useRef(false);
const [sort, setSort] = useState<Sort[] | undefined>();
const [filter, setFilter] = useState<Filter | undefined>(initialFilter);
const filterRef = useRef(initialFilter);
const [hasData, setHasData] = useState(false);
const [editOrder, setEditOrder] = useState<Order | null>(null);
const create = useVegaTransactionStore((state) => state.create);
const hasAmendableOrder = useHasAmendableOrder(marketId);
const { data, error, loading, reload } = useOrderListData({
partyId,
sort,
filter,
gridRef,
scrolledToTop,
const { data, error, loading, reload } = useDataProvider({
dataProvider: ordersWithMarketProvider,
variables:
filter === Filter.Open
? { partyId, filter: { liveOnly: true } }
: { partyId },
});
const {
onSortChanged: bottomPlaceholderOnSortChanged,
onFilterChanged: bottomPlaceholderOnFilterChanged,
...bottomPlaceholderProps
} = useBottomPlaceholder<Order>({
@@ -84,42 +90,6 @@ export const OrderListManager = ({
disabled: !enforceBottomPlaceholder && !isReadOnly && !hasAmendableOrder,
});
const onFilterChanged = useCallback(
(event: FilterChangedEvent) => {
const updatedFilter = event.api.getFilterModel();
if (isEqual(updatedFilter, filterRef.current)) {
return;
}
filterRef.current = updatedFilter;
if (Object.keys(updatedFilter).length) {
setFilter(updatedFilter);
} else {
setFilter(undefined);
}
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
bottomPlaceholderOnFilterChanged?.();
},
[setFilter, bottomPlaceholderOnFilterChanged]
);
const onSortChange = useCallback(
(event: SortChangedEvent) => {
const sort = event.columnApi
.getColumnState()
.sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0))
.reduce((acc, col) => {
if (col.sort) {
const { colId, sort } = col;
acc.push({ colId, sort });
}
return acc;
}, [] as { colId: string; sort: string }[]);
setSort(sort.length > 0 ? sort : undefined);
bottomPlaceholderOnSortChanged?.();
},
[setSort, bottomPlaceholderOnSortChanged]
);
const cancel = useCallback(
(order: Order) => {
if (!order.market) return;
@@ -133,12 +103,30 @@ export const OrderListManager = ({
[create]
);
const onGridReady = useCallback(({ api }: GridReadyEvent) => {
api.setFilterModel(initialFilter);
}, []);
const onGridReady = useCallback(
({ api }: GridReadyEvent) => {
if (filter !== undefined) {
api.setFilterModel({
status: {
value: FilterStatusValue[filter],
},
});
}
},
[filter]
);
const onFilterChanged = useCallback(
(event: FilterChangedEvent) => {
const rowCount = gridRef.current?.api?.getModel().getRowCount();
setHasData((rowCount ?? 0) > 0);
bottomPlaceholderOnFilterChanged?.();
},
[bottomPlaceholderOnFilterChanged]
);
useEffect(() => {
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
setHasData((gridRef.current?.api?.getModel().getRowCount() ?? 0) > 0);
}, [data]);
const cancelAll = useCallback(() => {
@@ -148,26 +136,20 @@ export const OrderListManager = ({
},
});
}, [create, marketId]);
const extractedData =
data && !loading
? data
.filter((item) => item !== null)
.map((item) => (item as OrderEdge).node)
: null;
return (
<>
<div className="h-full relative">
<OrderListTable
rowData={extractedData}
rowData={data as Order[]}
ref={gridRef}
readonlyStatusFilter={filter !== undefined}
onGridReady={onGridReady}
onFilterChanged={onFilterChanged}
onSortChanged={onSortChange}
cancel={cancel}
setEditOrder={setEditOrder}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
onFilterChanged={onFilterChanged}
isReadOnly={isReadOnly}
blockLoadDebounceMillis={100}
suppressLoadingOverlay
@@ -180,7 +162,7 @@ export const OrderListManager = ({
error={error}
data={data}
noDataMessage={t('No orders')}
noDataCondition={(data) => !dataCount}
noDataCondition={(data) => !hasData}
reload={reload}
/>
</div>
@@ -1,166 +0,0 @@
import type { AgGridReact } from 'ag-grid-react';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook, waitFor } from '@testing-library/react';
import { useOrderListData } from './use-order-list-data';
import type { Edge } from '@vegaprotocol/utils';
import type { OrderFieldsFragment } from '../order-data-provider/__generated__/Orders';
import type { IGetRowsParams } from 'ag-grid-community';
const loadMock = jest.fn();
let mockData: Edge<OrderFieldsFragment>[] | null = null;
let mockDataProviderData = {
data: mockData as (Edge<OrderFieldsFragment> | null)[] | null,
error: undefined,
loading: true,
load: loadMock,
totalCount: undefined,
};
let updateMock: jest.Mock;
const mockDataProvider = jest.fn((args) => {
updateMock = args.update;
return mockDataProviderData;
});
jest.mock('@vegaprotocol/react-helpers', () => ({
...jest.requireActual('@vegaprotocol/react-helpers'),
useDataProvider: jest.fn((args) => mockDataProvider(args)),
}));
describe('useOrderListData Hook', () => {
const mockRefreshAgGridApi = jest.fn();
const partyId = 'partyId';
const gridRef = {
current: {
api: {
refreshInfiniteCache: mockRefreshAgGridApi,
getModel: () => ({ getType: () => 'infinite' }),
},
} as unknown as AgGridReact,
};
const scrolledToTop = {
current: false,
};
afterEach(() => {
jest.clearAllMocks();
});
it('should return proper dataProvider results', () => {
const { result } = renderHook(
() => useOrderListData({ partyId, gridRef, scrolledToTop }),
{
wrapper: MockedProvider,
}
);
expect(result.current).toMatchObject({
data: null,
error: undefined,
loading: true,
addNewRows: expect.any(Function),
getRows: expect.any(Function),
});
});
it('return proper mocked results', () => {
mockData = [
{
node: {
id: 'data_id_1',
createdAt: 1,
},
} as unknown as Edge<OrderFieldsFragment>,
{
node: {
id: 'data_id_2',
createdAt: 2,
},
} as unknown as Edge<OrderFieldsFragment>,
];
mockDataProviderData = {
...mockDataProviderData,
data: mockData,
loading: false,
};
const { result } = renderHook(
() => useOrderListData({ partyId, gridRef, scrolledToTop }),
{
wrapper: MockedProvider,
}
);
expect(result.current).toMatchObject({
data: mockData,
error: undefined,
loading: false,
addNewRows: expect.any(Function),
getRows: expect.any(Function),
});
updateMock({ data: mockData, delta: [] });
expect(mockRefreshAgGridApi).toHaveBeenCalled();
});
it('methods for pagination should work', async () => {
const successCallback = jest.fn();
mockData = [
{
node: {
id: 'data_id_1',
createdAt: 1,
},
} as unknown as Edge<OrderFieldsFragment>,
{
node: {
id: 'data_id_2',
createdAt: 2,
},
} as unknown as Edge<OrderFieldsFragment>,
];
Object.assign(mockDataProviderData, {
data: mockData,
loading: false,
});
const mockDelta = [
{
node: {
id: 'data_id_3',
createdAt: 3,
},
} as unknown as Edge<OrderFieldsFragment>,
{
node: {
id: 'data_id_4',
createdAt: 4,
},
} as unknown as Edge<OrderFieldsFragment>,
];
const mockNextData = [...mockData, ...mockDelta];
const { result } = renderHook(
() => useOrderListData({ partyId, gridRef, scrolledToTop }),
{
wrapper: MockedProvider,
}
);
const getRowsParams = {
successCallback,
failCallback: jest.fn(),
startRow: 2,
endRow: 4,
} as unknown as IGetRowsParams;
await waitFor(async () => {
updateMock({ data: mockData });
});
await waitFor(async () => {
const promise = result.current.getRows(getRowsParams);
updateMock({ data: mockNextData, delta: mockDelta });
await promise;
});
expect(loadMock).toHaveBeenCalled();
expect(successCallback).toHaveBeenLastCalledWith(
mockDelta.map((item) => item.node),
undefined
);
});
});
@@ -1,171 +0,0 @@
import { useCallback, useMemo, useRef } from 'react';
import type { RefObject } from 'react';
import type { AgGridReact } from 'ag-grid-react';
import { makeInfiniteScrollGetRows } from '@vegaprotocol/utils';
import { useDataProvider, updateGridData } from '@vegaprotocol/react-helpers';
import { ordersWithMarketProvider } from '../order-data-provider/order-data-provider';
import type {
OrderEdge,
Order,
} from '../order-data-provider/order-data-provider';
import type {
OrdersQueryVariables,
OrdersUpdateSubscriptionVariables,
} from '../order-data-provider/__generated__/Orders';
import type * as Types from '@vegaprotocol/types';
export interface Sort {
colId: string;
sort: string;
}
export interface Filter {
updatedAt?: {
value: Types.DateRange;
};
type?: {
value: Types.OrderType[];
};
status?: {
value: Types.OrderStatus[];
};
timeInForce?: {
value: Types.OrderTimeInForce[];
};
}
interface Props {
partyId: string;
marketId?: string;
filter?: Filter;
sort?: Sort[];
gridRef: RefObject<AgGridReact>;
scrolledToTop: RefObject<boolean>;
}
export const useOrderListData = ({
partyId,
marketId,
sort,
filter,
gridRef,
scrolledToTop,
}: Props) => {
const dataRef = useRef<(OrderEdge | null)[] | null>(null);
const totalCountRef = useRef<number | undefined>(undefined);
const newRows = useRef(0);
const placeholderAdded = useRef(-1);
const makeBottomPlaceholders = useCallback((order?: Order) => {
if (!order) {
if (placeholderAdded.current >= 0) {
dataRef.current?.splice(placeholderAdded.current, 1);
}
placeholderAdded.current = -1;
} else if (placeholderAdded.current === -1) {
dataRef.current?.push({
node: { ...order, id: `${order?.id}-1`, isLastPlaceholder: true },
});
placeholderAdded.current = (dataRef.current?.length || 0) - 1;
}
}, []);
const variables = useMemo(() => {
// define variable as const to get type safety, using generic with useMemo resulted in lost type safety
const allVars: OrdersQueryVariables & OrdersUpdateSubscriptionVariables = {
partyId,
};
if (
filter?.updatedAt?.value ||
filter?.status?.value.length ||
filter?.timeInForce?.value.length ||
filter?.type?.value.length
) {
allVars.filter = {};
if (filter?.updatedAt?.value) {
allVars.filter.dateRange = filter?.updatedAt?.value;
}
if (filter?.status?.value.length) {
allVars.filter.status = filter?.status?.value;
}
if (filter?.timeInForce?.value.length) {
allVars.filter.timeInForce = filter?.timeInForce?.value;
}
if (filter?.type?.value.length) {
allVars.filter.types = filter?.type?.value;
}
}
return allVars;
}, [partyId, filter]);
const addNewRows = useCallback(() => {
if (newRows.current === 0) {
return;
}
if (totalCountRef.current !== undefined) {
totalCountRef.current += newRows.current;
}
newRows.current = 0;
gridRef.current?.api?.refreshInfiniteCache();
}, [gridRef]);
const update = useCallback(
({
data,
delta,
}: {
data: (OrderEdge | null)[] | null;
delta?: Order[];
totalCount?: number;
}) => {
if (dataRef.current?.length && delta?.length && !scrolledToTop.current) {
const createdAt = dataRef.current?.[0]?.node.createdAt;
if (createdAt) {
newRows.current += (delta || []).filter(
(trade) => trade.createdAt > createdAt
).length;
}
}
if (gridRef.current?.api?.getModel().getType() === 'infinite') {
return updateGridData(dataRef, data, gridRef);
}
return false;
},
[gridRef, scrolledToTop]
);
const insert = useCallback(
({
data,
totalCount,
}: {
data: (OrderEdge | null)[] | null;
totalCount?: number;
}) => {
totalCountRef.current = totalCount;
if (gridRef.current?.api?.getModel().getType() === 'infinite') {
return updateGridData(dataRef, data, gridRef);
}
return false;
},
[gridRef]
);
const { data, error, loading, load, totalCount, reload } = useDataProvider({
dataProvider: ordersWithMarketProvider,
update,
insert,
variables,
});
totalCountRef.current = totalCount;
const getRows = useRef(
makeInfiniteScrollGetRows<OrderEdge>(dataRef, totalCountRef, load, newRows)
);
return {
loading,
error,
data,
addNewRows,
getRows: getRows.current,
reload,
makeBottomPlaceholders,
};
};
@@ -33,13 +33,21 @@ export type OrderListTableProps = OrderListProps & {
setEditOrder: (order: Order) => void;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void;
readonlyStatusFilter?: boolean;
isReadOnly: boolean;
};
export const OrderListTable = memo(
forwardRef<AgGridReact, OrderListTableProps>(
(
{ cancel, setEditOrder, onMarketClick, onOrderTypeClick, ...props },
{
cancel,
setEditOrder,
onMarketClick,
onOrderTypeClick,
readonlyStatusFilter,
...props
},
ref
) => {
return (
@@ -119,6 +127,7 @@ export const OrderListTable = memo(
filter={SetFilter}
filterParams={{
set: Schema.OrderStatusMapping,
readonly: readonlyStatusFilter,
}}
valueFormatter={({
value,
@@ -229,6 +238,7 @@ export const OrderListTable = memo(
/>
<AgGridColumn
field="createdAt"
filter={DateRangeFilter}
cellRenderer={({
data,
value,
@@ -243,7 +253,6 @@ export const OrderListTable = memo(
/>
<AgGridColumn
field="updatedAt"
filter={DateRangeFilter}
cellRenderer={({
data,
value,
+2 -2
View File
@@ -55,10 +55,10 @@ export const PositionsManager = ({
},
});
const setId = useCallback((data: Position) => {
const setId = useCallback((data: Position, id: string) => {
return {
...data,
marketId: `${data.marketId}-1`,
marketId: id,
};
}, []);
const bottomPlaceholderProps = useBottomPlaceholder<Position>({
+2
View File
@@ -1,2 +1,4 @@
export * from './asset-proposal-notification';
export * from './market-proposal-notification';
export * from './protocol-upgrade-countdown';
export * from './protocol-upgrade-proposal-notification';
@@ -0,0 +1,99 @@
import { t } from '@vegaprotocol/i18n';
import { useNextProtocolUpgradeProposal, useTimeToUpgrade } from '../lib';
import { convertToCountdownString } from '@vegaprotocol/utils';
import { IconNames } from '@blueprintjs/icons';
import classNames from 'classnames';
import { Icon, NavigationContext } from '@vegaprotocol/ui-toolkit';
import { useProtocolUpgradeProposalLink } from '@vegaprotocol/environment';
import { useContext } from 'react';
export enum ProtocolUpgradeCountdownMode {
IN_BLOCKS,
IN_ESTIMATED_TIME_REMAINING,
}
type ProtocolUpgradeCountdownProps = {
mode?: ProtocolUpgradeCountdownMode;
};
export const ProtocolUpgradeCountdown = ({
mode = ProtocolUpgradeCountdownMode.IN_BLOCKS,
}: ProtocolUpgradeCountdownProps) => {
const { theme } = useContext(NavigationContext);
const { data, lastBlockHeight } = useNextProtocolUpgradeProposal();
const time = useTimeToUpgrade(
data && data.upgradeBlockHeight
? Number(data.upgradeBlockHeight)
: undefined
);
const detailsLink = useProtocolUpgradeProposalLink();
if (!data) return null;
const emphasis = classNames(
'text-vega-orange-500 dark:text-vega-orange-500',
{
'!text-black': theme === 'yellow',
}
);
let countdown;
switch (mode) {
case ProtocolUpgradeCountdownMode.IN_BLOCKS:
countdown = (
<>
<span className={emphasis}>
{Number(data.upgradeBlockHeight) - Number(lastBlockHeight)}
</span>{' '}
{t('blocks')}
</>
);
break;
case ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING:
countdown =
time !== undefined ? (
<span className={emphasis}>
{convertToCountdownString(time, '0:00:00:00')}
</span>
) : (
<span
className={classNames('italic lowercase text-vega-orange-600', {
'!text-black': theme === 'yellow',
})}
>
{t('estimating...')}
</span>
);
break;
}
return (
<a
href={detailsLink(data.vegaReleaseTag)}
target="_blank"
rel="noreferrer nofollow noopener"
>
<div
data-testid="protocol-upgrade-counter"
className={classNames(
'flex flex-nowrap items-center text-xs py-2 px-4',
'border rounded',
'border-vega-orange-500 dark:border-vega-orange-500',
'bg-vega-orange-300 dark:bg-vega-orange-700',
{
'!bg-transparent !border-black': theme === 'yellow',
}
)}
>
<Icon
name={IconNames.WARNING_SIGN}
size={3}
className={classNames('mr-2', emphasis)}
/>{' '}
<span className="flex gap-1 flex-nowrap whitespace-nowrap">
<span>{t('Network upgrade in')} </span>
{countdown}
</span>
</div>
</a>
);
};
@@ -0,0 +1,79 @@
import {
ExternalLink,
Intent,
NotificationBanner,
} from '@vegaprotocol/ui-toolkit';
import { useNextProtocolUpgradeProposal, useTimeToUpgrade } from '../lib';
import { t } from '@vegaprotocol/i18n';
import { useProtocolUpgradeProposalLink } from '@vegaprotocol/environment';
import { ProtocolUpgradeCountdownMode } from './protocol-upgrade-countdown';
import { convertToCountdownString } from '@vegaprotocol/utils';
import { useState } from 'react';
type ProtocolUpgradeProposalNotificationProps = {
mode?: ProtocolUpgradeCountdownMode;
};
export const ProtocolUpgradeProposalNotification = ({
mode = ProtocolUpgradeCountdownMode.IN_BLOCKS,
}: ProtocolUpgradeProposalNotificationProps) => {
const [visible, setVisible] = useState(true);
const { data, lastBlockHeight } = useNextProtocolUpgradeProposal();
const detailsLink = useProtocolUpgradeProposalLink();
const time = useTimeToUpgrade(
data && data.upgradeBlockHeight
? Number(data.upgradeBlockHeight)
: undefined
);
if (!data || !lastBlockHeight || !visible) return null;
const { vegaReleaseTag, upgradeBlockHeight } = data;
let countdown;
switch (mode) {
case ProtocolUpgradeCountdownMode.IN_BLOCKS:
countdown = (
<>
<span className="text-vega-orange-500">
{Number(upgradeBlockHeight) - Number(lastBlockHeight)}
</span>{' '}
{t('blocks')}
</>
);
break;
case ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING:
countdown =
time !== undefined ? (
<span className="text-vega-orange-500">
{convertToCountdownString(time, '0:00:00:00')}
</span>
) : (
<span className="text-vega-orange-600 lowercase italic">
{t('estimating...')}
</span>
);
break;
}
return (
<NotificationBanner
intent={Intent.Warning}
onClose={() => {
setVisible(false);
}}
>
<div className="uppercase ">
{t('The network will upgrade to %s in ', [data.vegaReleaseTag])}
{countdown}
</div>
<div>
{t(
'Trading activity will be interrupted, manage your risk appropriately.'
)}{' '}
<ExternalLink href={detailsLink(vegaReleaseTag)}>
{t('View details')}
</ExternalLink>
</div>
</NotificationBanner>
);
};
+1
View File
@@ -3,3 +3,4 @@ export * from './voting-hooks';
export * from './proposals-data-provider';
export * from './proposals-list';
export * from './voting-progress';
export * from './protocol-upgrade-proposals';
@@ -0,0 +1,6 @@
query BlockStatistics {
statistics {
blockHeight
blockDuration
}
}
@@ -5,9 +5,9 @@ fragment ProtocolUpgradeProposalFields on ProtocolUpgradeProposal {
status
}
query ProtocolUpgrades {
query ProtocolUpgradeProposals($inState: ProtocolUpgradeProposalStatus) {
lastBlockHeight
protocolUpgradeProposals {
protocolUpgradeProposals(inState: $inState) {
edges {
node {
...ProtocolUpgradeProposalFields
@@ -0,0 +1,46 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type BlockStatisticsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type BlockStatisticsQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', blockHeight: string, blockDuration: string } };
export const BlockStatisticsDocument = gql`
query BlockStatistics {
statistics {
blockHeight
blockDuration
}
}
`;
/**
* __useBlockStatisticsQuery__
*
* To run a query within a React component, call `useBlockStatisticsQuery` and pass it any options that fit your needs.
* When your component renders, `useBlockStatisticsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useBlockStatisticsQuery({
* variables: {
* },
* });
*/
export function useBlockStatisticsQuery(baseOptions?: Apollo.QueryHookOptions<BlockStatisticsQuery, BlockStatisticsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<BlockStatisticsQuery, BlockStatisticsQueryVariables>(BlockStatisticsDocument, options);
}
export function useBlockStatisticsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<BlockStatisticsQuery, BlockStatisticsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<BlockStatisticsQuery, BlockStatisticsQueryVariables>(BlockStatisticsDocument, options);
}
export type BlockStatisticsQueryHookResult = ReturnType<typeof useBlockStatisticsQuery>;
export type BlockStatisticsLazyQueryHookResult = ReturnType<typeof useBlockStatisticsLazyQuery>;
export type BlockStatisticsQueryResult = Apollo.QueryResult<BlockStatisticsQuery, BlockStatisticsQueryVariables>;
@@ -0,0 +1,62 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProtocolUpgradeProposalFieldsFragment = { __typename?: 'ProtocolUpgradeProposal', upgradeBlockHeight: string, vegaReleaseTag: string, approvers: Array<string>, status: Types.ProtocolUpgradeProposalStatus };
export type ProtocolUpgradeProposalsQueryVariables = Types.Exact<{
inState?: Types.InputMaybe<Types.ProtocolUpgradeProposalStatus>;
}>;
export type ProtocolUpgradeProposalsQuery = { __typename?: 'Query', lastBlockHeight: string, protocolUpgradeProposals?: { __typename?: 'ProtocolUpgradeProposalConnection', edges?: Array<{ __typename?: 'ProtocolUpgradeProposalEdge', node: { __typename?: 'ProtocolUpgradeProposal', upgradeBlockHeight: string, vegaReleaseTag: string, approvers: Array<string>, status: Types.ProtocolUpgradeProposalStatus } }> | null } | null };
export const ProtocolUpgradeProposalFieldsFragmentDoc = gql`
fragment ProtocolUpgradeProposalFields on ProtocolUpgradeProposal {
upgradeBlockHeight
vegaReleaseTag
approvers
status
}
`;
export const ProtocolUpgradeProposalsDocument = gql`
query ProtocolUpgradeProposals($inState: ProtocolUpgradeProposalStatus) {
lastBlockHeight
protocolUpgradeProposals(inState: $inState) {
edges {
node {
...ProtocolUpgradeProposalFields
}
}
}
}
${ProtocolUpgradeProposalFieldsFragmentDoc}`;
/**
* __useProtocolUpgradeProposalsQuery__
*
* To run a query within a React component, call `useProtocolUpgradeProposalsQuery` and pass it any options that fit your needs.
* When your component renders, `useProtocolUpgradeProposalsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useProtocolUpgradeProposalsQuery({
* variables: {
* inState: // value for 'inState'
* },
* });
*/
export function useProtocolUpgradeProposalsQuery(baseOptions?: Apollo.QueryHookOptions<ProtocolUpgradeProposalsQuery, ProtocolUpgradeProposalsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ProtocolUpgradeProposalsQuery, ProtocolUpgradeProposalsQueryVariables>(ProtocolUpgradeProposalsDocument, options);
}
export function useProtocolUpgradeProposalsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProtocolUpgradeProposalsQuery, ProtocolUpgradeProposalsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ProtocolUpgradeProposalsQuery, ProtocolUpgradeProposalsQueryVariables>(ProtocolUpgradeProposalsDocument, options);
}
export type ProtocolUpgradeProposalsQueryHookResult = ReturnType<typeof useProtocolUpgradeProposalsQuery>;
export type ProtocolUpgradeProposalsLazyQueryHookResult = ReturnType<typeof useProtocolUpgradeProposalsLazyQuery>;
export type ProtocolUpgradeProposalsQueryResult = Apollo.QueryResult<ProtocolUpgradeProposalsQuery, ProtocolUpgradeProposalsQueryVariables>;
@@ -0,0 +1,3 @@
export * from './__generated__/ProtocolUpgradeProposals';
export * from './use-next-protocol-upgrade-proposals';
export * from './use-time-to-upgrade';
@@ -0,0 +1,53 @@
import { useMemo } from 'react';
import * as Schema from '@vegaprotocol/types';
import { removePaginationWrapper } from '@vegaprotocol/utils';
import { useProtocolUpgradeProposalsQuery } from './__generated__/ProtocolUpgradeProposals';
export const useNextProtocolUpgradeProposals = (since?: number) => {
const { data, loading, error } = useProtocolUpgradeProposalsQuery({
pollInterval: 5000,
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
variables: {
inState:
Schema.ProtocolUpgradeProposalStatus
.PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED,
},
});
const nextUpgrades = useMemo(() => {
if (!data) return [];
const proposals = removePaginationWrapper(
data?.protocolUpgradeProposals?.edges
);
return proposals
.filter(
(p) =>
Number(p.upgradeBlockHeight) > (since || Number(data.lastBlockHeight))
)
.sort(
(a, b) => Number(a.upgradeBlockHeight) - Number(b.upgradeBlockHeight)
);
}, [data, since]);
return {
data: nextUpgrades,
lastBlockHeight: data?.lastBlockHeight,
loading,
error,
};
};
export const useNextProtocolUpgradeProposal = (since?: number) => {
const { data, lastBlockHeight, loading, error } =
useNextProtocolUpgradeProposals(since);
return {
data: !data ? undefined : data[0],
lastBlockHeight,
loading,
error,
};
};
@@ -0,0 +1,32 @@
import { renderHook, waitFor } from '@testing-library/react';
import { useTimeToUpgrade } from './use-time-to-upgrade';
jest.mock('./__generated__/BlockStatistics', () => ({
...jest.requireActual('./__generated__/BlockStatistics'),
useBlockStatisticsQuery: jest.fn(() => {
return {
data: {
statistics: {
blockHeight: 1,
blockDuration: 500,
},
},
};
}),
}));
describe('useTimeToUpgrade', () => {
it.each([
[-1, -1000],
[0, -500],
[1, 0],
[2, 500],
[3, 1000],
[10, 4500],
])('time in %d block(s) should be %d ms', async (block, avg) => {
const { result } = renderHook(() => useTimeToUpgrade(block, 1));
await waitFor(() => {
expect(result.current).toEqual(avg);
});
});
});
@@ -0,0 +1,64 @@
import { useEffect, useState } from 'react';
import { useBlockStatisticsQuery } from './__generated__/BlockStatistics';
import sum from 'lodash/sum';
const DEFAULT_POLLS = 10;
const INTERVAL = 1000;
const durations = [] as number[];
const useAverageBlockDuration = (polls = DEFAULT_POLLS) => {
const [avg, setAvg] = useState<number | undefined>(undefined);
const { data } = useBlockStatisticsQuery({
pollInterval: INTERVAL,
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
skip: durations.length === polls,
});
useEffect(() => {
if (durations.length < polls && data) {
durations.push(parseFloat(data.statistics.blockDuration));
}
if (durations.length === polls) {
const averageBlockDuration = sum(durations) / durations.length; // ms
console.log('setting avg', averageBlockDuration);
setAvg(averageBlockDuration);
}
}, [data, polls]);
return avg;
};
export const useTimeToUpgrade = (
upgradeBlockHeight?: number,
polls = DEFAULT_POLLS
) => {
const [time, setTime] = useState<number | undefined>(undefined);
const avg = useAverageBlockDuration(polls);
const { data } = useBlockStatisticsQuery({
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
});
useEffect(() => {
const t =
(Number(upgradeBlockHeight) - Number(data?.statistics.blockHeight)) *
Number(avg);
if (!isNaN(t)) {
setTime(t);
}
}, [avg, data?.statistics.blockHeight, upgradeBlockHeight]);
useEffect(() => {
const i = setInterval(() => {
if (time !== undefined) {
setTime(time - 1000);
}
}, 1000);
return () => {
clearInterval(i);
};
}, [time]);
return time;
};
@@ -1,16 +1,17 @@
import type { RefObject } from 'react';
import { useCallback, useMemo } from 'react';
import type { AgGridReact } from 'ag-grid-react';
import type { IsFullWidthRowParams } from 'ag-grid-community';
import type { IsFullWidthRowParams, RowHeightParams } from 'ag-grid-community';
const NO_HOVER_CSS_RULE = { 'no-hover': 'data?.isLastPlaceholder' };
const ROW_ID = 'bottomPlaceholder';
const fullWidthCellRenderer = () => null;
const isFullWidthRow = (params: IsFullWidthRowParams) =>
params.rowNode.data?.isLastPlaceholder;
interface Props<T> {
gridRef: RefObject<AgGridReact>;
setId?: (data: T) => T;
setId?: (data: T, id: string) => T;
disabled?: boolean;
}
// eslint-disable-next-line @typescript-eslint/ban-types
@@ -20,45 +21,42 @@ export const useBottomPlaceholder = <T extends {}>({
disabled,
}: Props<T>) => {
const onBodyScrollEnd = useCallback(() => {
const rowCont = gridRef.current?.api.getModel().getRowCount() ?? 0;
const lastRowIndex = gridRef.current?.api.getLastDisplayedRow() ?? 0;
if (lastRowIndex && rowCont - 1 === lastRowIndex) {
const lastRow = gridRef.current?.api.getDisplayedRowAtIndex(lastRowIndex);
if (lastRow?.data && !lastRow?.data.isLastPlaceholder) {
const newData = setId
? setId({ ...lastRow.data, isLastPlaceholder: true })
const rowCont = gridRef.current?.api.getDisplayedRowCount() ?? 0;
if (rowCont) {
const lastRow = gridRef.current?.api.getDisplayedRowAtIndex(rowCont - 1);
if (lastRow && lastRow.data) {
const placeholderRow = setId
? setId({ ...lastRow.data, isLastPlaceholder: true }, ROW_ID)
: {
...lastRow.data,
isLastPlaceholder: true,
id: `${lastRow.data?.id || '-'}-1`,
id: ROW_ID,
};
const add = [newData];
const newIndex = lastRowIndex + 1;
gridRef.current?.api.applyTransaction({
add,
addIndex: newIndex,
});
const newLastRow =
gridRef.current?.api.getDisplayedRowAtIndex(newIndex);
newLastRow?.setRowHeight(50);
gridRef.current?.api.onRowHeightChanged();
const transaction = gridRef.current?.api.getRowNode(ROW_ID)
? { update: [placeholderRow] }
: { add: [placeholderRow] };
gridRef.current?.api.applyTransaction(transaction);
}
}
}, [gridRef, setId]);
const onRowsChanged = useCallback(() => {
const remove: T[] = [];
gridRef.current?.api.forEachNodeAfterFilterAndSort((rowNode) => {
if (rowNode.data.isLastPlaceholder) {
remove.push(rowNode.data);
}
});
gridRef.current?.api.applyTransaction({
remove,
});
const placeholderNode = gridRef.current?.api.getRowNode(ROW_ID);
if (placeholderNode) {
const transaction = {
remove: [placeholderNode.data],
};
gridRef.current?.api.applyTransaction(transaction);
}
onBodyScrollEnd();
}, [gridRef, onBodyScrollEnd]);
const getRowHeight = useCallback(
(params: RowHeightParams) =>
params.data?.isLastPlaceholder ? 50 : undefined,
[]
);
return useMemo(
() =>
!disabled
@@ -69,8 +67,9 @@ export const useBottomPlaceholder = <T extends {}>({
fullWidthCellRenderer,
onSortChanged: onRowsChanged,
onFilterChanged: onRowsChanged,
getRowHeight,
}
: {},
[onBodyScrollEnd, onRowsChanged, disabled]
[onBodyScrollEnd, onRowsChanged, disabled, getRowHeight]
);
};
+46 -1
View File
@@ -1,4 +1,8 @@
import { getSecondsFromInterval } from './time';
import {
convertToCountdown,
convertToCountdownString,
getSecondsFromInterval,
} from './time';
describe('getSecondsFromInterval', () => {
it('returns 0 for bad data', () => {
@@ -34,3 +38,44 @@ describe('getSecondsFromInterval', () => {
expect(getSecondsFromInterval('1D1h30m1s')).toEqual(91801);
});
});
describe('convertToCountdown', () => {
it.each([
[1 * 1000, [0, 0, 0, 1]],
[2 * 1000, [0, 0, 0, 2]],
[3999, [0, 0, 0, 3]],
[1 * 60 * 1000 + 3 * 1000, [0, 0, 1, 3]],
[12 * 60 * 1000 + 3 * 1000, [0, 0, 12, 3]],
[3 * 60 * 60 * 1000 + 12 * 60 * 1000 + 3 * 1000, [0, 3, 12, 3]],
[
30 * 24 * 60 * 60 * 1000 + 3 * 60 * 60 * 1000 + 12 * 60 * 1000 + 3 * 1000,
[30, 3, 12, 3],
],
[
-1 *
(30 * 24 * 60 * 60 * 1000 +
3 * 60 * 60 * 1000 +
12 * 60 * 1000 +
3 * 1000),
[30, 3, 12, 3],
],
])('converts %d ms to %s', (time, countdown) => {
expect(convertToCountdown(time)).toEqual(countdown);
});
});
describe('convertToCountdownString', () => {
it.each([
[1 * 1000, '00m01s'],
[2 * 1000, '00m02s'],
[1 * 60 * 1000 + 3 * 1000, '01m03s'],
[12 * 60 * 1000 + 3 * 1000, '12m03s'],
[3 * 60 * 60 * 1000 + 12 * 60 * 1000 + 3 * 1000, '03h12m03s'],
[
30 * 24 * 60 * 60 * 1000 + 3 * 60 * 60 * 1000 + 12 * 60 * 1000 + 3 * 1000,
'30d03h12m03s',
],
])('converts %d ms to %s', (time, countdown) => {
expect(convertToCountdownString(time)).toEqual(countdown);
});
});
+44
View File
@@ -46,3 +46,47 @@ export function getSecondsFromInterval(str: string) {
}
return seconds;
}
export const convertToCountdown = (time: number) => {
const s = 1000;
const m = 1000 * 60;
const h = 1000 * 60 * 60;
const d = 1000 * 60 * 60 * 24;
const t = Math.abs(time);
const days = Math.floor(t / d);
const hours = Math.floor((t - days * d) / h);
const minutes = Math.floor((t - days * d - hours * h) / m);
const seconds = Math.floor((t - days * d - hours * h - minutes * m) / s);
return [days, hours, minutes, seconds];
};
/**
* Converts given time in ms to countdown string, e.g. 1d20h34m10s
*/
export const convertToCountdownString = (
time: number,
pattern = '0d00h00m00s'
) => {
const values = convertToCountdown(time);
let i = 0;
const countdown = pattern
.replace(/00*/g, (match) => {
const value = String(values[i++]);
if (value.length < match.length) {
const filler = Array(match.length - value.length)
.fill('0')
.join('');
return `${filler}${value}`;
}
return value;
})
.replace(/^00*[^\d]*/g, '') // replace leading 00, e.g. 00d01h23m45s -> 01h23m45s
.replace(/^00[^\d]*/g, ''); // replace leading 00, e.g. 00d00h23m45s -> 23m45s
return countdown;
};