Compare commits

..
Author SHA1 Message Date
Dariusz Majcherczyk 08f21eeee4 test: fixed capsule tests 2023-03-27 12:21:41 +02:00
dexturr a6964bc3cf chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-27 06:06:57 +00:00
dexturr 48a9998441 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-27 00:16:27 +00:00
dexturr bd1bd94ee7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-26 18:07:12 +00:00
dexturr 2fdebbd694 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-26 12:10:22 +00:00
dexturr 96af8035d0 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-26 06:07:03 +00:00
dexturr 051e3da366 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-26 00:17:44 +00:00
dexturr af5e666d5e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-25 18:09:35 +00:00
dexturr 333a7d6206 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-25 12:10:21 +00:00
dexturr cb6b988466 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-25 06:09:33 +00:00
dexturr 806ea74f7e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-25 00:14:18 +00:00
Matthew Russell 8693f3bfd8 chore(trading): dont show faucet button until connected (#3251) 2023-03-24 17:06:22 -07:00
Bartłomiej Głownia 58c6652e29 feat(trading): use mini scroll in deal ticket, market info for and landing dialog (#3269) 2023-03-24 17:01:12 -07:00
Bartłomiej Głownia e8adff25c4 fix(trading): handle lack of approval in trading deposit flow (#3278) 2023-03-24 16:57:00 -07:00
Penny Andrews 3e594a783a chore(ci): add release issue template (#3272) 2023-03-24 16:55:22 -07:00
dexturr 1f7117075b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-24 18:09:07 +00:00
Bartłomiej Głownia 4c850ecead fix(trading): change etherscan link label on toast (#3262) 2023-03-24 17:57:59 +01:00
Mikołaj Młodzikowski 19f8fa909e feat(explorer,trading,governance): use nx to know which apps needs building (#3267) 2023-03-24 16:42:33 +01:00
Sam Keen 8214858685 feat(governance): lp vote now reflected on proposal cards (#3256) 2023-03-24 14:56:56 +00:00
dexturr 868f8e21dc chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-24 12:08:16 +00:00
dexturr 6ead84b57c chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-24 06:09:30 +00:00
dexturr 3975477985 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-24 00:14:29 +00:00
26 changed files with 876 additions and 380 deletions
+4
View File
@@ -3,3 +3,7 @@ apps/**/node_modules/*
tmp/*
.dockerignore
dockerfiles
node_modules
.git
.github
.vscode
+2
View File
@@ -1,3 +1,4 @@
name: Cypress Run
on:
workflow_call:
inputs:
@@ -17,6 +18,7 @@ jobs:
fail-fast: false
matrix:
project: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.project }}
runs-on: self-hosted-runner
timeout-minutes: 30
steps:
@@ -1,4 +1,4 @@
name: Cypress tests - PR
name: PR Validations
on:
push:
@@ -20,14 +20,16 @@ jobs:
with:
fetch-depth: 0
- name: Check node version
id: node-version
run: |
npmVersion=$(cat .nvmrc | head -n 1)
echo ::set-output name=npmVersion::${npmVersion}
- name: Setup node
uses: actions/setup-node@v3
- name: Remove package.json & yarn.lock to avoid installing everything
run: rm package.json yarn.lock
- name: Install nx
run: yarn add nx
with:
node-version: ${{ steps.node-version.outputs.npmVersion }}
# Check SHAs
- name: Derive appropriate SHAs for base and head for `nx affected` commands
@@ -39,38 +41,51 @@ jobs:
# See affected apps
- name: See affected apps
run: |
nx_version=$(cat package.json | grep '"nx"' | cut -d ':' -f 2 | tr -d '",[:space:]')
rm package.json yarn.lock
yarn add nx@$nx_version
affected=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)
echo -n "Affected projects: $affected"
projects=""
if [[ $affected == *"governance"* ]]; then projects+='"governance-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects+='"explorer-e2e" '; fi
if [[ -z "$projects" ]]; then projects+='"governance-e2e" "trading-e2e" "explorer-e2e" '; fi
projects=${projects%?}
projects=[${projects// /,}]
echo PROJECTS=$projects >> $GITHUB_ENV
projects_e2e=""
if [[ $affected == *"governance"* ]]; then projects_e2e+='"governance-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects_e2e+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects_e2e+='"explorer-e2e" '; fi
if [[ -z "$projects_e2e" ]]; then projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '; fi
projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}]
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
outputs:
projects: ${{ env.PROJECTS }}
projects-e2e: ${{ env.PROJECTS_E2E }}
run:
run-cypress:
needs: pr
if: ${{ needs.pr.outputs.projects != '[]' }}
uses: ./.github/workflows/cypress-run.yml
secrets: inherit
with:
projects: ${{ needs.pr.outputs.projects }}
projects: ${{ needs.pr.outputs.projects-e2e }}
tags: '@smoke @regression'
run-docker-build:
needs: pr
if: ${{ needs.pr.outputs.projects != '[]' }}
uses: ./.github/workflows/publish-docker-containers.yml
secrets: inherit
with:
projects: ${{ needs.pr.outputs.projects }}
# Report single result at the end, to avoid mess with required checks in PR
result:
if: ${{ always() }}
needs: run
needs: run-cypress
runs-on: ubuntu-latest
name: Cypress result
steps:
- run: |
result="${{ needs.run.result }}"
result="${{ needs.run-cypress.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
+17 -12
View File
@@ -1,16 +1,19 @@
name: Publish docker containers
name: Docker build
'on':
pull_request:
on:
workflow_call:
inputs:
projects:
required: true
type: string
jobs:
master:
strategy:
fail-fast: false
# to be replaced by nix: https://github.com/vegaprotocol/frontend-monorepo/blob/develop/tools/ipfs-deploy.js#L106-L108
matrix:
app: ${{ fromJson('["explorer"]') }}
name: Build the ${{ matrix.app }} image
app: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.app }}
runs-on: ubuntu-latest
steps:
- name: Check out code
@@ -45,13 +48,10 @@ jobs:
- name: Build and export to local Docker
uses: docker/build-push-action@v3
with:
context: .
push: false
file: dockerfiles/Dockerfile
load: true
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
load: true
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
@@ -75,9 +75,7 @@ jobs:
id: docker_build
uses: docker/build-push-action@v3
with:
context: .
push: true
file: dockerfiles/Dockerfile
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
@@ -85,5 +83,12 @@ jobs:
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:latest
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ steps.tags.outputs.version }}
- name: Add preview label
uses: actions-ecosystem/action-add-labels@v1
if: ${{ github.event_name == 'pull_request' }}
with:
labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
+8 -6
View File
@@ -4,13 +4,15 @@ FROM --platform=amd64 node:${NODE_VERSION}-alpine3.16 as build
WORKDIR /app
# Argument to allow building of different apps
ARG APP
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY yarn.lock ./
RUN apk add --update --no-cache \
python3 \
make \
gcc \
g++
COPY . ./
RUN apk add python3 make gcc g++
RUN yarn --network-timeout 100000 --pure-lockfile
RUN yarn nx build ${APP} --network-timeout 100000 --pure-lockfile
# work around for different build process in trading
RUN sh ./docker-build.sh
# Server environment
# if this fails you need to docker pull nginx:1.23-alpine and pin new SHA
@@ -25,7 +27,7 @@ CMD ["/entrypoint.sh"]
# Copy dist
WORKDIR /usr/share/nginx/html
COPY --from=build /app/dist/apps/${APP} /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist/apps/${APP} /usr/share/nginx/html
COPY ./apps/${APP}/.env .env
RUN ipfs init && echo "$(ipfs add -rQ .)" > ipfs-hash
@@ -341,7 +341,7 @@ context(
'Currently expected to pass'
);
getProposalInformationFromTable('Expected to pass')
.contains('👍 by Token vote')
.contains('👍 by token vote')
.should('be.visible');
});
@@ -221,8 +221,9 @@
"votePending": "Casting vote",
"voteError": "Something went wrong, and your vote was not seen by the network",
"back": "back",
"byTokenVote": "by Token vote",
"byLiquidityVote": "by Liquidity vote",
"byTokenVote": "by token vote",
"byLiquidityVote": "by liquidity vote",
"byLPVote": "by LP vote",
"youDidNotVote": "Voting has ended. You did not vote",
"voteState_Yes": "For",
"voteState_No": "Against",
@@ -86,7 +86,7 @@ describe('Proposal Votes Table', () => {
it('displays if an update market proposal will pass by token vote', () => {
renderComponent(updateMarketProposal, updateMarketProposalType);
expect(screen.getByText('👍 by Token vote')).toBeInTheDocument();
expect(screen.getByText('👍 by token vote')).toBeInTheDocument();
});
it('displays if an update market proposal will pass by LP vote', () => {
@@ -110,6 +110,6 @@ describe('Proposal Votes Table', () => {
}),
updateMarketProposalType
);
expect(screen.getByText('👍 by Liquidity vote')).toBeInTheDocument();
expect(screen.getByText('👍 by liquidity vote')).toBeInTheDocument();
});
});
@@ -136,6 +136,82 @@ describe('Proposals list item details', () => {
);
});
it('Renders proposal state: Update market proposal - set to pass by LP vote', () => {
renderComponent(
generateProposal({
state: ProposalState.STATE_OPEN,
terms: {
change: {
__typename: 'UpdateMarket',
},
},
votes: {
yes: {
...generateYesVotes(0),
totalEquityLikeShareWeight: '1000',
},
no: {
...generateNoVotes(0),
totalEquityLikeShareWeight: '0',
},
},
})
);
expect(screen.getByTestId('vote-status')).toHaveTextContent(
'Set to pass by LP vote'
);
});
it('Renders proposal state: Update market proposal - set to pass by token vote', () => {
renderComponent(
generateProposal({
state: ProposalState.STATE_OPEN,
terms: {
change: {
__typename: 'UpdateMarket',
},
},
votes: {
yes: {
...generateYesVotes(1000, 1000),
totalEquityLikeShareWeight: '0',
},
no: {
...generateNoVotes(0),
totalEquityLikeShareWeight: '0',
},
},
})
);
expect(screen.getByTestId('vote-status')).toHaveTextContent(
'Set to pass by token vote'
);
});
it('Renders proposal state: Update market proposal - set to fail', () => {
renderComponent(
generateProposal({
state: ProposalState.STATE_OPEN,
terms: {
change: {
__typename: 'UpdateMarket',
},
},
votes: {
yes: {
...generateYesVotes(0),
totalEquityLikeShareWeight: '0',
},
no: {
...generateNoVotes(0),
totalEquityLikeShareWeight: '0',
},
},
})
);
expect(screen.getByTestId('vote-status')).toHaveTextContent('Set to fail');
});
it('Renders proposal state: Open - 5 minutes left to vote', () => {
renderComponent(
generateProposal({
@@ -41,12 +41,22 @@ export const ProposalsListItemDetails = ({
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
}) => {
const state = proposal?.state;
const { willPassByTokenVote, majorityMet, participationMet } =
useVoteInformation({
proposal,
});
const {
willPassByTokenVote,
willPassByLPVote,
majorityMet,
participationMet,
} = useVoteInformation({
proposal,
});
const { t } = useTranslation();
const { voteState } = useUserVote(proposal?.id);
const isUpdateMarket = proposal?.terms.change.__typename === 'UpdateMarket';
const updateMarketWillPass = willPassByTokenVote || willPassByLPVote;
const updateMarketVotePassMethod = willPassByTokenVote
? t('byTokenVote')
: t('byLPVote');
let proposalStatus: ReactNode;
let voteDetails: ReactNode;
let voteStatus: ReactNode;
@@ -128,6 +138,19 @@ export const ProposalsListItemDetails = ({
</>
);
voteStatus =
(isUpdateMarket &&
(updateMarketWillPass ? (
<>
{t('Set to')}{' '}
<StatusPass>
{t('pass')} {updateMarketVotePassMethod}
</StatusPass>
</>
) : (
<>
{t('Set to')} <StatusFail>{t('fail')}</StatusFail>
</>
))) ||
(!participationMet && <ParticipationNotReached />) ||
(!majorityMet && <MajorityNotReached />) ||
(willPassByTokenVote ? (
@@ -32,6 +32,7 @@ export const VoteDetails = ({
totalTokensPercentage,
participationMet,
totalTokensVoted,
totalLPTokensPercentage,
noPercentage,
noLPPercentage,
yesPercentage,
@@ -41,6 +42,8 @@ export const VoteDetails = ({
requiredMajorityPercentage,
requiredMajorityLPPercentage,
requiredParticipation,
requiredParticipationLP,
participationLPMet,
} = useVoteInformation({ proposal });
const { t } = useTranslation();
@@ -101,6 +104,25 @@ export const VoteDetails = ({
</tr>
</tbody>
</table>
<p className="mb-6">
{t('participation')}
{': '}
{participationLPMet ? (
<span className="text-vega-green mx-4">{t('met')}</span>
) : (
<span className="text-danger mx-4">{t('notMet')}</span>
)}{' '}
{formatNumber(totalLPTokensPercentage, defaultDecimals)}%
<span className="ml-4">
{requiredParticipationLP && (
<>
({formatNumber(requiredParticipationLP, defaultDecimals)}%{' '}
{t('governanceRequired')})
</>
)}
</span>
</p>
</section>
)}
<section data-testid="votes-table">
File diff suppressed because it is too large Load Diff
+13 -7
View File
@@ -135,7 +135,7 @@ describe('capsule - without MultiSign', { tags: '@slow' }, () => {
cy.getByTestId(transferForm).find(submitTransferBtn).click();
cy.getByTestId(toastContent).should(
'contain.text',
'Transfer completeYour transaction has been confirmed TransferTo 7f9cf0…c255351.00 tBTC'
'Transfer completeYour transaction has been confirmed View in block explorerTransferTo 7f9cf0…c255351.00 tBTC'
);
cy.getByTestId(toastCloseBtn).click();
});
@@ -283,7 +283,7 @@ describe('capsule', { tags: '@slow' }, () => {
});
});
// comment because of bug #2695
it.skip('can edit order', function () {
it('can edit order', function () {
cy.getByTestId(ordersTab).click();
cy.getByTestId('edit').first().should('be.visible').click();
cy.getByTestId('dialog-title').should('contain.text', 'Edit order');
@@ -422,7 +422,11 @@ describe('capsule', { tags: '@slow' }, () => {
cy.getByTestId(depositSubmit).click();
cy.getByTestId('input-error-text').should(
'contain.text',
'Amount is above approved amount.Update approve amount'
'Amount is above approved amount'
);
cy.getByTestId('reapprove-default').should(
'contain.text',
'Approve again to deposit more than'
);
});
@@ -437,9 +441,11 @@ describe('capsule', { tags: '@slow' }, () => {
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(vegaName, { force: true });
cy.getByTestId('deposit-submit').click();
cy.getByTestId('dialog-title').should('contain.text', 'Approve complete');
cy.get('[data-testid="Return to deposit"]').click();
cy.getByTestId('approve-submit').click();
cy.getByTestId('approve-confirmed').should(
'contain.text',
'You can now make deposits in VEGA, up to a maximum of'
);
cy.get(amountField).clear().type('10000');
cy.getByTestId('deposit-submit').click();
cy.getByTestId(toastContent, txTimeout).should(
@@ -447,7 +453,7 @@ describe('capsule', { tags: '@slow' }, () => {
`Your transaction has been confirmed.`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId(toastCloseBtn).click({ multiple: true });
cy.getByTestId('Collateral').click();
cy.highlight('deposit verification');
@@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
import { useMarketList } from '@vegaprotocol/market-list';
import { t } from '@vegaprotocol/i18n';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { Link as UILink } from '@vegaprotocol/ui-toolkit';
import { Link as UILink, TinyScroll } from '@vegaprotocol/ui-toolkit';
import type { OnCellClickHandler } from '../select-market';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
import {
@@ -55,8 +55,8 @@ export const SelectMarketLandingTable = ({
const showProposed = (markets?.length || 0) <= 5;
return (
<>
<div
className="max-h-[60vh] overflow-x-auto"
<TinyScroll
className="max-h-[60vh] overflow-x-auto -mr-4 pr-4"
data-testid="select-market-list"
>
<p className="text-neutral-500 dark:text-neutral-400 mb-4">
@@ -78,7 +78,7 @@ export const SelectMarketLandingTable = ({
))}
</tbody>
</table>
</div>
</TinyScroll>
<div className="mt-4 text-md">
<Link
to={Links[Routes.MARKETS]()}
@@ -103,7 +103,9 @@ const EthTxPendingToastContent = ({ tx }: EthTxToastContentProps) => {
<>
<ToastHeading>{t('Awaiting confirmation')}</ToastHeading>
<p>{t('Please wait for your transaction to be confirmed.')}</p>
{tx.txHash && <EtherscanLink tx={tx.txHash} />}
{tx.txHash && (
<EtherscanLink tx={tx.txHash}>{t('View on Etherscan')}</EtherscanLink>
)}
<EthTransactionDetails tx={tx} />
</>
);
@@ -131,7 +133,9 @@ const EthTxConfirmedToastContent = ({ tx }: EthTxToastContentProps) => {
<>
<ToastHeading>{t('Transaction confirmed')}</ToastHeading>
<p>{t('Your transaction has been confirmed.')}</p>
{tx.txHash && <EtherscanLink tx={tx.txHash} />}
{tx.txHash && (
<EtherscanLink tx={tx.txHash}>{t('View on Etherscan')}</EtherscanLink>
)}
<EthTransactionDetails tx={tx} />
</>
);
@@ -148,7 +152,9 @@ const EthTxCompletedToastContent = ({ tx }: EthTxToastContentProps) => {
{t('Your transaction has been completed.')}{' '}
{isDeposit && t('Waiting for deposit confirmation.')}
</p>
{tx.txHash && <EtherscanLink tx={tx.txHash} />}
{tx.txHash && (
<EtherscanLink tx={tx.txHash}>{t('View on Etherscan')}</EtherscanLink>
)}
<EthTransactionDetails tx={tx} />
</>
);
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh -eux
export PATH="/app/node_modules/.bin:$PATH"
if [ "${APP}" = "trading" ]; then
yarn nx export ${APP} --network-timeout 100000 --pure-lockfile
mv /app/dist/apps/trading/exported/ /app/tmp
rm -rf /app/dist/apps/trading
mv /app/tmp /app/dist/apps/trading
else
yarn nx build ${APP} --network-timeout 100000 --pure-lockfile
fi
+5 -1
View File
@@ -7,6 +7,10 @@ mkdir -p $(dirname $env_file)
rm -rf $env_file || echo "no file to delete"
touch $env_file
env_vars_file=/usr/share/nginx/html/.env
sed -i '/^#/d' $env_vars_file # remove comment lines
sed -i '/^$/d' $env_vars_file # remove empty lines
# Add assignment
echo "window._env_ = {" >> $env_file
@@ -29,7 +33,7 @@ do
if [ ! -z "$varname" ]; then
echo " $varname: \"$value\"," >> $env_file
fi
done < /usr/share/nginx/html/.env
done < $env_vars_file
echo "}" >> $env_file
@@ -20,6 +20,7 @@ import {
InputError,
Intent,
Notification,
TinyScroll,
} from '@vegaprotocol/ui-toolkit';
import {
@@ -160,136 +161,140 @@ export const DealTicket = ({
if (!order || !normalizedOrder) return null;
return (
<form
onSubmit={isReadOnly ? undefined : handleSubmit(onSubmit)}
className="p-4"
noValidate
>
<Controller
name="type"
control={control}
rules={{
validate: validateType(
marketData.marketTradingMode,
marketData.trigger
),
}}
render={() => (
<TypeSelector
value={order.type}
onSelect={(type) => {
if (type === OrderType.TYPE_NETWORK) return;
update({
type,
// when changing type also update the tif to what was last used of new type
timeInForce: lastTIF[type] || order.timeInForce,
expiresAt: undefined,
});
clearErrors('expiresAt');
}}
market={market}
marketData={marketData}
errorMessage={errors.type?.message}
/>
)}
/>
<Controller
name="side"
control={control}
render={() => (
<SideSelector
value={order.side}
onSelect={(side) => {
update({ side });
}}
/>
)}
/>
<DealTicketAmount
control={control}
orderType={order.type}
market={market}
marketData={marketData}
sizeError={errors.size?.message}
priceError={errors.price?.message}
update={update}
size={order.size}
price={order.price}
/>
<Controller
name="timeInForce"
control={control}
rules={{
validate: validateTimeInForce(
marketData.marketTradingMode,
marketData.trigger
),
}}
render={() => (
<TimeInForceSelector
value={order.timeInForce}
orderType={order.type}
onSelect={(timeInForce) => {
update({ timeInForce });
// Set tif value for the given order type, so that when switching
// types we know the last used TIF for the given order type
setLastTIF((curr) => ({
...curr,
[order.type]: timeInForce,
expiresAt: undefined,
}));
clearErrors('expiresAt');
}}
market={market}
marketData={marketData}
errorMessage={errors.timeInForce?.message}
/>
)}
/>
{order.type === Schema.OrderType.TYPE_LIMIT &&
order.timeInForce === Schema.OrderTimeInForce.TIME_IN_FORCE_GTT && (
<Controller
name="expiresAt"
control={control}
rules={{
validate: validateExpiration,
}}
render={() => (
<ExpirySelector
value={order.expiresAt}
onSelect={(expiresAt) =>
update({
expiresAt: expiresAt || undefined,
})
}
errorMessage={errors.expiresAt?.message}
/>
)}
/>
)}
<SummaryMessage
errorMessage={errors.summary?.message}
asset={asset}
marketTradingMode={marketData.marketTradingMode}
balance={balance}
margin={totalMargin}
isReadOnly={isReadOnly}
pubKey={pubKey}
onClickCollateral={onClickCollateral}
/>
<DealTicketButton
disabled={Object.keys(errors).length >= 1 || isReadOnly}
variant={order.side === Schema.Side.SIDE_BUY ? 'ternary' : 'secondary'}
/>
<DealTicketFeeDetails
order={normalizedOrder}
market={market}
marketData={marketData}
margin={margin}
totalMargin={totalMargin}
balance={marginAccountBalance}
/>
</form>
<TinyScroll className="h-full overflow-auto">
<form
onSubmit={isReadOnly ? undefined : handleSubmit(onSubmit)}
className="p-4"
noValidate
>
<Controller
name="type"
control={control}
rules={{
validate: validateType(
marketData.marketTradingMode,
marketData.trigger
),
}}
render={() => (
<TypeSelector
value={order.type}
onSelect={(type) => {
if (type === OrderType.TYPE_NETWORK) return;
update({
type,
// when changing type also update the tif to what was last used of new type
timeInForce: lastTIF[type] || order.timeInForce,
expiresAt: undefined,
});
clearErrors('expiresAt');
}}
market={market}
marketData={marketData}
errorMessage={errors.type?.message}
/>
)}
/>
<Controller
name="side"
control={control}
render={() => (
<SideSelector
value={order.side}
onSelect={(side) => {
update({ side });
}}
/>
)}
/>
<DealTicketAmount
control={control}
orderType={order.type}
market={market}
marketData={marketData}
sizeError={errors.size?.message}
priceError={errors.price?.message}
update={update}
size={order.size}
price={order.price}
/>
<Controller
name="timeInForce"
control={control}
rules={{
validate: validateTimeInForce(
marketData.marketTradingMode,
marketData.trigger
),
}}
render={() => (
<TimeInForceSelector
value={order.timeInForce}
orderType={order.type}
onSelect={(timeInForce) => {
update({ timeInForce });
// Set tif value for the given order type, so that when switching
// types we know the last used TIF for the given order type
setLastTIF((curr) => ({
...curr,
[order.type]: timeInForce,
expiresAt: undefined,
}));
clearErrors('expiresAt');
}}
market={market}
marketData={marketData}
errorMessage={errors.timeInForce?.message}
/>
)}
/>
{order.type === Schema.OrderType.TYPE_LIMIT &&
order.timeInForce === Schema.OrderTimeInForce.TIME_IN_FORCE_GTT && (
<Controller
name="expiresAt"
control={control}
rules={{
validate: validateExpiration,
}}
render={() => (
<ExpirySelector
value={order.expiresAt}
onSelect={(expiresAt) =>
update({
expiresAt: expiresAt || undefined,
})
}
errorMessage={errors.expiresAt?.message}
/>
)}
/>
)}
<SummaryMessage
errorMessage={errors.summary?.message}
asset={asset}
marketTradingMode={marketData.marketTradingMode}
balance={balance}
margin={totalMargin}
isReadOnly={isReadOnly}
pubKey={pubKey}
onClickCollateral={onClickCollateral}
/>
<DealTicketButton
disabled={Object.keys(errors).length >= 1 || isReadOnly}
variant={
order.side === Schema.Side.SIDE_BUY ? 'ternary' : 'secondary'
}
/>
<DealTicketFeeDetails
order={normalizedOrder}
market={market}
marketData={marketData}
margin={margin}
totalMargin={totalMargin}
balance={marginAccountBalance}
/>
</form>
</TinyScroll>
);
};
@@ -16,6 +16,7 @@ interface ApproveNotificationProps {
balances: DepositBalances | null;
amount: string;
approveTxId: number | null;
intent?: Intent;
}
export const ApproveNotification = ({
@@ -26,6 +27,7 @@ export const ApproveNotification = ({
balances,
approved,
approveTxId,
intent = Intent.Warning,
}: ApproveNotificationProps) => {
const tx = useEthTransactionStore((state) => {
return state.transactions.find((t) => t?.id === approveTxId);
@@ -46,7 +48,7 @@ export const ApproveNotification = ({
const approvePrompt = (
<div className="mb-4">
<Notification
intent={Intent.Warning}
intent={intent}
testId="approve-default"
message={t(
`Before you can make a deposit of your chosen asset, ${selectedAsset?.symbol}, you need to approve its use in your Ethereum wallet`
@@ -63,7 +65,7 @@ export const ApproveNotification = ({
const reApprovePrompt = (
<div className="mb-4">
<Notification
intent={Intent.Warning}
intent={intent}
testId="reapprove-default"
message={t(
`Approve again to deposit more than ${formatNumber(
+12 -4
View File
@@ -83,6 +83,8 @@ export const DepositForm = ({
const openDialog = useWeb3ConnectStore((store) => store.open);
const { isActive, account } = useWeb3React();
const { pubKey, pubKeys: _pubKeys } = useVegaWallet();
const [approveNotificationIntent, setApproveNotificationIntent] =
useState<Intent>(Intent.Warning);
const {
register,
handleSubmit,
@@ -103,8 +105,10 @@ export const DepositForm = ({
if (!selectedAsset || selectedAsset.source.__typename !== 'ERC20') {
throw new Error('Invalid asset');
}
if (!approved) throw new Error('Deposits not approved');
if (!approved) {
setApproveNotificationIntent(Intent.Danger);
return;
}
submitDeposit({
assetSource: selectedAsset.source.contractAddress,
amount: fields.amount,
@@ -219,7 +223,7 @@ export const DepositForm = ({
{errors.asset.message}
</InputError>
)}
{isFaucetable && selectedAsset && (
{isActive && isFaucetable && selectedAsset && (
<UseButton onClick={submitFaucet}>
{t(`Get ${selectedAsset.symbol}`)}
</UseButton>
@@ -355,9 +359,13 @@ export const DepositForm = ({
isActive={isActive}
approveTxId={approveTxId}
selectedAsset={selectedAsset}
onApprove={submitApprove}
onApprove={() => {
submitApprove();
setApproveNotificationIntent(Intent.Warning);
}}
balances={balances}
approved={approved}
intent={approveNotificationIntent}
amount={amount}
/>
<FormButton approved={approved} selectedAsset={selectedAsset} />
+4 -5
View File
@@ -1,4 +1,3 @@
import styles from './orderbook.module.scss';
import colors from 'tailwindcss/colors';
import { useEffect, useRef, useState, useCallback, Fragment } from 'react';
import classNames from 'classnames';
@@ -14,7 +13,7 @@ import {
import * as Schema from '@vegaprotocol/types';
import { OrderbookRow } from './orderbook-row';
import { createRow } from './orderbook-data';
import { Checkbox, Icon, Splash } from '@vegaprotocol/ui-toolkit';
import { Checkbox, Icon, Splash, TinyScroll } from '@vegaprotocol/ui-toolkit';
import type { OrderbookData, OrderbookRowData } from './orderbook-data';
interface OrderbookProps extends OrderbookData {
@@ -547,8 +546,8 @@ export const Orderbook = ({
{t('Cumulative vol')}
</div>
</div>
<div
className={`h-full overflow-auto relative ${styles['scroll']}`}
<TinyScroll
className="h-full overflow-auto relative"
onScroll={onScroll}
ref={scrollElement}
data-testid="scroll"
@@ -580,7 +579,7 @@ export const Orderbook = ({
testId={'best-static-offer-price'}
/>
)}
</div>
</TinyScroll>
<div
className="absolute bottom-0 grid grid-cols-4 gap-2 border-t border-default mt-2 z-10 bg-white dark:bg-black w-full"
ref={footerElement}
@@ -9,6 +9,7 @@ import {
ExternalLink,
Link as UILink,
Splash,
TinyScroll,
} from '@vegaprotocol/ui-toolkit';
import { useMemo } from 'react';
import { generatePath, Link } from 'react-router-dom';
@@ -71,7 +72,9 @@ export const MarketInfoContainer = ({
return (
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
{data ? (
<Info market={data} onSelect={(id) => onSelect?.(id)} />
<TinyScroll className="h-full overflow-auto">
<Info market={data} onSelect={(id) => onSelect?.(id)} />
</TinyScroll>
) : (
<Splash>
<p>{t('Could not load market')}</p>
+1
View File
@@ -40,6 +40,7 @@ export * from './tabs';
export * from './text-area';
export * from './theme-switcher';
export * from './thumbs';
export * from './tiny-scroll';
export * from './toast';
export * from './toggle';
export * from './tooltip';
@@ -0,0 +1 @@
export * from './tiny-scroll';
@@ -0,0 +1,20 @@
import styles from './tiny-scroll.module.scss';
import { forwardRef } from 'react';
import classNames from 'classnames';
import type { HTMLAttributes, ReactNode } from 'react';
export interface Props extends HTMLAttributes<HTMLDivElement> {
children: ReactNode;
}
export const TinyScroll = forwardRef<HTMLDivElement, Props>(
({ children, className, ...props }, ref) => (
<div
ref={ref}
className={classNames(className, styles['scroll'])}
{...props}
>
{children}
</div>
)
);