Skip to content
This repository has been archived by the owner on May 31, 2023. It is now read-only.

Commit

Permalink
added max button (#153)
Browse files Browse the repository at this point in the history
* #41 | refactoring

* #41 | Install polkadot extension CTA

* #41 | Reload page link

* #41 | simplified the install extension scenario

* Revert "#41 | simplified the install extension scenario"

This reverts commit 3144db9.

* feat: #54 update balances resolver

* feat: #54 update imports

* test: #54 add test for getBalancesByAddress

* refactor: #54 constants

* feat: #54 add implement. for getBalancesByAddress resolver

* docs: format comments

* feat: add assetIds type

* refactor: #54 getBalancesByAddress

* feat: #54 update implementation getBalancesByAddress

* #41 | introduce patch for CRAP issue

facebook/create-react-app#11797

REMINDER:
check for pull request #11797 release to remove the patch. Removing the patch is pretty straightforward. Remove patch-package postinstall-postinstall, remove the package.json script & delete the /patch dir (if you don't use patch-package for anything else).

* #41 | fix postinstall script

* Update yarn.lock

* #41 | WIP resolver tests

* feat: add wait-for-expect testing library

* feat: remove unnecessary propertiy in gql schema

* feat: add mocked polkadotJsContext for testing purposes

* feat: update getBalancesByAddress implementation

* feat: update gql schema

* #41 | move render function to fix ESlint validation

* refactor: mockApiPromise and mockUsePolkadotJsContext

* test: add fail cases

* feat: upgrade type def for polkadot/api v7

* #41 accounts resolver mock

* #41 | clear VestingSchedule from account schema

* #41 | selectedAccount => activeAccount

* #41 | remove duplicated line

* #41 | PR comment fixes

* #41 | PR comment fixes

* #41 | addressing PR review - refactored onAccountSelected handling

* #41 | PR issue fix - use classNames FTW

* #41 | PR comment fix - account is always populated

* #41 | TODO comment

* #41 | basic react-intl setup

* #41 | Formatted messages for links

* #41 | handle and propagate getAllAccounts loading state

* #41 | moving files along to match desired dir structures

* #41 | moving files along to match desired dir structures

* #41 | further dir structure shaking and cleanup

* #41 | accounts dir structure refactoring finished

* #41 | Todo

* #41 | add source field to Account GQL type

* #41 | test update

* #41 | add transformIgnorePatterns for polkadot to jest.config.js file

* #41 | getAccounts lib function and tests

* #41 | cleanup

* #41 | cleanup

* #41 | getAccounts refactoring

* #41 | getAccounts tests finished

* #41 | use waitForExpect

* #41 | accounts resolver tests

* #41 | pass ss58Format as an option to avoid manual address encoding

* #41 | tests structured formatting

* #41 | fix test description

* #41 | shared withTypename helper

* #41 | propper return type

* #41 | extract callback to separate function

* test: refactor getAccounts

* #41 | basilisk ui app provider name  moved to constants

* #41 | update mocked web3Enable response format

* #41 | update padding to result in whole px value

* #41 | use skip instead of lazy query to avoid manual effects

* #41 | post merge fixes

* Create .nvmrc

* #41 | post install yarn.lock update

* #41 | fix storybook test snapshots

* #41 | remove tests for deprecated component

* #41 | Icon component refactoring

* #41 | translations

* Really remove husky:

* account-selector redesign

* Updates to tradeform

* fixes to AssetBalanceInput + stories

* Added default asset out bsx

* remove trade chart

* cleanup trade form

* working towards trade info

* reverse spot price

* spot price display

* submit trade

* complete wallet

* fix wallet

* start balance input

* fix balance fetching for accounts

* Added last block fetching and trade info

* added spot price display to trade form

* mumbo jumbo with spot price

* debugging last block

* update polkadot dependencies, fix trade limit calc

* change event listener for trade type changing

* feat: subscription for last block

* added historical dataset with latest data composition, added asset switcher

* fix asset balance input + metric unit selector

* page layout

* fix ci?

* Update styles

* some chart fixes

* small story fix

* remove an unwanted dot

* chart-style

* correct loading statuses for accounts & pool by ids

* Revive trade chart

* reset dataset on asset id change

* fix loading status for wallet & trade form

* responsive something

* better flex

* polish

* more swag

* fix overlay

* hide trade form settings instead of comment out

* added pool asset list

* disable lbp pool fetching

* fix styles

* add placeholder

* xyk trade status handling

* extract trade settings as portal

* add updating of query params

* fix trade settings form submit

* settings

* button n info

* limit graph bounds

* icons~WIP

* icons something

* asset styling + longname

* swag, actually fix chart jail and rendering, disable tooltip logs

* style fixes

* trade balances before/after/%

* fix unique assets for asset selector

* no default values for calculated amount counterparts

* graph fix

* linechart x axis scale

* Trade info style

* moar space

* asset selector

* fix decimal input in BalanceInput

* USDC metadata

* use formattedbalance in chart & form

* fix straight graph

* fix clickable area for unit selector

* trade chart precision fix

* switchfix

* header fix

* trade form tweaks

* jumpy

* footer liveliness and spot price in graph fix

* colors for footer

* bring back notifs

* notifs v1

* spinner

* settings

* trade info errors

* swag

* Uupdate E2E testing workflow

* Update polkadot-dapp

* Unlock e2e tests

* warning styling

* more swag for trade info

* trade paddings

* new test for trade page

* clean console logs and remove graceful error handler from xyk.sell

* center modal close button

* add sha version to footer

* remove unit if value is 0

* switch to short sha version

* fix footer sha display

* short git hash version

* minor fixes

* spicy validations

* add small fix for calculated amounts

* Error styling

* trade balance fixes

* loading status fixes

* eerrrrs

* added faucete mutation + fixed % trade balance change

* add faucetg

* remove loader from faucet

* fix error timing

* fix alignment in tradeinfo

* fix % trade balances

* units and balance input remove trailing zeroes

* Adjust unit balance recalculation in inputs

* timeout hack for tradeinfo errors

* switch you get / pay with

* fix switching of in/out in form

* add help

* Fix graph loading status

* Fix chart loading text, fix block num loading status

* fix asset ordering

* Simplify wallet button logic (show connect account)

* Added debug box"

* fix debug box false

* debug stuff

* Moveup active account validation, move debugbox closer to root

* add pretty json view to debug box

* debug box details for trade form

* fix rerender of debug box

* debug box features

* Fix trade balances loading state

* Tweak trade balances display for none/some account connected + none/some amount input value

* Add extension availability pseudo-polling

* remove secondary account item address

* unify account address triming between mini wallet and account list item

* tweaks to account list / item

* Add horizontal bar when no asset is selected for unit selector

* Filter of trade form assets

* Added payment info estimation for xyk sell

* add multiple empty states with horizontal bar

* Added tooltip to formatted balance

* show spotprice in the tradeform as formattede balance

* update URLs for new testnet

* tokens

* styling error fix + hide faucet

* wallet genesis hash handling

* fix unnecessary display of trade balance change

* Align wallet correctly

* shorter tooltip delay

* adjust extension detection timeout

* revalidate when allowed slippage changes

* Add calculating of usable balance for the native asset + sufficient fee balance validation (#141)

* Add calculating of usable balance for the native asset

* Added fee balance validation to trade form

* added max button

* use payment info when calculating trade balances

Co-authored-by: Václav Slavík <[email protected]>
Co-authored-by: dexterslabor <[email protected]>
Co-authored-by: Istvan <[email protected]>
Co-authored-by: Jakub Panik <[email protected]>
Co-authored-by: Jakub Panik <[email protected]>
Co-authored-by: Jakub Panik <[email protected]>
Co-authored-by: mckrava <[email protected]>
Co-authored-by: Jakub Vitek <[email protected]>
Co-authored-by: Ayoub Fakir <[email protected]>
  • Loading branch information
10 people authored Apr 26, 2022
1 parent 5aa8f03 commit adff415
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 73 deletions.
40 changes: 31 additions & 9 deletions src/components/Balance/AssetBalanceInput/AssetBalanceInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,42 @@
&__input-wrapper {
flex-grow: 1;
padding: 16px 12px;
display: flex;
flex-direction: column;

&__unit-selector {
&__controls {
display: flex;
justify-content: end;

&__asset-name {
font-size: 10px;
font-weight: 600;
letter-spacing: 0.5px;
}
.horizontal-bar {
position: relative;
top: -1px;
&__unit-selector {
display: flex;
justify-content: end;

&__asset-name {
font-size: 10px;
font-weight: 600;
letter-spacing: 0.5px;
}
.horizontal-bar {
position: relative;
top: -1px;
}
}
}
}

&.disabled {
&::after {
content: '';
width: 100%;
height: 100%;
background-color: rgba($d-gray2, 0.4);
position: absolute;
top: 0;
left: 0;
border-radius: $border-radius;
transition: all ease-in-out 500ms;
cursor: progress;
}
}
}
38 changes: 26 additions & 12 deletions src/components/Balance/AssetBalanceInput/AssetBalanceInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import classNames from 'classnames';
import { MutableRefObject, useCallback } from 'react';
import { Asset } from '../../../generated/graphql';
import { MutableRefObject, useCallback, useEffect } from 'react';
import { Asset, Maybe } from '../../../generated/graphql';
import { BalanceInput, BalanceInputProps } from '../BalanceInput/BalanceInput';
import { useModalPortal } from './hooks/useModalPortal';
import { useModalPortalElement } from './hooks/useModalPortalElement';
Expand All @@ -24,7 +24,8 @@ export interface AssetBalanceInputProps {
isAssetSelectable?: boolean;
// onAssetSelected: (asset: Asset) => void,
balanceInputRef?: MutableRefObject<HTMLInputElement | null>;
required?: boolean
required?: boolean;
maxBalanceLoading?: boolean,
}

export const AssetBalanceInput = ({
Expand All @@ -38,6 +39,7 @@ export const AssetBalanceInput = ({
// onAssetSelected,
balanceInputRef,
required,
maxBalanceLoading,
}: AssetBalanceInputProps) => {
const modalPortalElement = useModalPortalElement({
assets,
Expand All @@ -58,7 +60,9 @@ export const AssetBalanceInput = ({
const methods = useFormContext();

return (
<div className="asset-balance-input">
<div className={classNames('asset-balance-input', {
disabled: maxBalanceLoading
})}>
{/* This portal will be rendered at it's container ref as defined above */}
{modalPortal}
<div
Expand Down Expand Up @@ -88,14 +92,24 @@ export const AssetBalanceInput = ({
</div>
</div>
<div className="asset-balance-input__input-wrapper">
<div className="asset-balance-input__input-wrapper__unit-selector">
<MetricUnitSelector unit={unit} onUnitSelected={setUnit}>
<div className={classNames("asset-balance-input__input-wrapper__unit-selector__asset-name", {
'horizontal-bar': !idToAsset(methods.getValues(assetInputName))?.symbol
})}>
{idToAsset(methods.getValues(assetInputName))?.symbol || `${horizontalBar}`}
</div>
</MetricUnitSelector>
<div className='asset-balance-input__input-wrapper__controls'>
<div className="asset-balance-input__input-wrapper__controls__unit-selector">
<MetricUnitSelector unit={unit} onUnitSelected={setUnit}>
<div
className={classNames(
'asset-balance-input__input-wrapper__controls__unit-selector__asset-name',
{
'horizontal-bar': !idToAsset(
methods.getValues(assetInputName)
)?.symbol,
}
)}
>
{idToAsset(methods.getValues(assetInputName))?.symbol ||
`${horizontalBar}`}
</div>
</MetricUnitSelector>
</div>
</div>

<BalanceInput
Expand Down
16 changes: 16 additions & 0 deletions src/components/Trade/TradeForm/TradeForm.scss
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,19 @@

background-color: rgba(0, 0, 0, 0.8);
}


.max-button {
font-size: 8px;
font-weight: 400;
color: $white1;
border: 1px solid $white1;
padding: 1px 4px;
border-radius: 3px;
cursor: pointer;

&.disabled {
cursor: not-allowed;
opacity: 0.5;
}
}
160 changes: 118 additions & 42 deletions src/components/Trade/TradeForm/TradeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { usePolkadotJsContext } from '../../../hooks/polkadotJs/usePolkadotJs';
import { useApolloClient } from '@apollo/client';
import { estimateBuy } from '../../../hooks/pools/xyk/buy';
import { estimateSell } from '../../../hooks/pools/xyk/sell';
import { payment } from '@polkadot/types/interfaces/definitions';

export interface TradeFormSettingsProps {
allowedSlippage: string | null;
Expand Down Expand Up @@ -238,6 +239,20 @@ export const TradeForm = ({
trigger('submit');
}, []);

useEffect(() => {
// must provide input name otherwise it does not validate appropriately
trigger('submit');
}, [
isActiveAccountConnected,
pool,
isPoolLoading,
activeAccountTradeBalances,
assetInLiquidity,
assetOutLiquidity,
allowedSlippage,
...watch(['assetInAmount', 'assetOutAmount']),
]);

// when the assetIds change, propagate the change to the parent
useEffect(() => {
const { assetIn, assetOut } = getValues();
Expand Down Expand Up @@ -443,29 +458,34 @@ export const TradeForm = ({
const { apiInstance } = usePolkadotJsContext()
const { cache } = useApolloClient();
const [paymentInfo, setPaymentInfo] = useState<string>();
useEffect(() => {
const calculatePaymentInfo = useCallback(async () => {
if (!apiInstance) return;
const [ assetIn, assetOut, assetInAmount, assetOutAmount ] = getValues(['assetIn', 'assetOut', 'assetInAmount', 'assetOutAmount']);
let [ assetIn, assetOut, assetInAmount, assetOutAmount ] = getValues(['assetIn', 'assetOut', 'assetInAmount', 'assetOutAmount']);

if (!assetIn || !assetOut || !assetInAmount || !assetOutAmount || !tradeLimit) return;

(async () => {
switch (tradeType) {
case TradeType.Buy: {
const estimate = (await estimateBuy(cache, apiInstance, assetOut, assetIn, assetOutAmount, tradeLimit.balance))
const partialFee = estimate?.partialFee.toString();
return setPaymentInfo(partialFee);
}
case TradeType.Sell: {
const estimate = (await estimateSell(cache, apiInstance, assetIn, assetOut, assetInAmount, tradeLimit.balance))
const partialFee = estimate?.partialFee.toString();
return setPaymentInfo(partialFee);
}
default:
return;
switch (tradeType) {
case TradeType.Buy: {
const estimate = (await estimateBuy(cache, apiInstance, assetOut, assetIn, assetOutAmount, tradeLimit.balance))
const partialFee = estimate?.partialFee.toString();
return partialFee
}
})();

case TradeType.Sell: {
const estimate = (await estimateSell(cache, apiInstance, assetIn, assetOut, assetInAmount, tradeLimit.balance))
const partialFee = estimate?.partialFee.toString();
return partialFee
}
default:
return;
}
}, [apiInstance, cache, ...watch(['assetInAmount', 'assetOutAmount']), tradeLimit, tradeType]);

useEffect(() => {
(async () => {
const paymentInfo = await calculatePaymentInfo();
if (!paymentInfo) return;
setPaymentInfo(paymentInfo)
})()
}, [apiInstance, cache, ...watch(['assetInAmount', 'assetOutAmount']), tradeLimit, tradeType]);

useEffect(() => {
Expand All @@ -490,10 +510,17 @@ export const TradeForm = ({

const assetInAmount = getValues('assetInAmount');
const inBeforeTrade = activeAccountTradeBalances?.inBalance?.balance;
const inAfterTrade =
let inAfterTrade =
inBeforeTrade &&
assetInAmount &&
new BigNumber(inBeforeTrade).minus(assetInAmount).toFixed(0) || undefined

inAfterTrade = getValues('assetIn') !== '0'
? inAfterTrade
: paymentInfo && inAfterTrade && new BigNumber(inAfterTrade)
.minus(paymentInfo)
.toFixed(0);

const inTradeChange =
inBeforeTrade !== '0'
? percentageChange(
Expand All @@ -513,13 +540,13 @@ export const TradeForm = ({
};
}, [
activeAccountTradeBalances,
...watch(['assetOutAmount', 'assetInAmount']),
...watch(['assetOutAmount', 'assetInAmount', 'assetIn']),
paymentInfo
]);

const { debugComponent } = useDebugBoxContext();

useEffect(() => {
console.log('all values', getValues());
debugComponent('TradeForm', {
...getValues(),
spotPrice,
Expand Down Expand Up @@ -549,24 +576,67 @@ export const TradeForm = ({
errors,
assetInLiquidity,
assetOutLiquidity,
slippage
slippage,
formState.isDirty
]);

useEffect(() => {
// must provide input name otherwise it does not validate appropriately
trigger('submit');
}, [
isActiveAccountConnected,
pool,
isPoolLoading,
activeAccountTradeBalances,
assetInLiquidity,
assetOutLiquidity,
allowedSlippage,
paymentInfo,
tradeBalances,
...watch(['assetInAmount', 'assetOutAmount']),
]);
const minTradeLimitIn = useCallback((assetInAmount?: Maybe<string>) => {
if (!assetInAmount || assetInAmount === '0') return false;
return new BigNumber(assetInLiquidity || '0')
.dividedBy(3)
.gte(assetInAmount);
}, [assetInLiquidity]);

const [maxAmountInLoading, setMaxAmountInLoading] = useState(false);

const calculateMaxAmountIn = useCallback(async () => {
const [assetIn, assetOut] = getValues(['assetIn', 'assetOut']);
console.log('calculateMaxAmountIn1',
tradeBalances.inBeforeTrade,
cache,
apiInstance,
assetIn,
assetOut,
)
if (!tradeBalances.inBeforeTrade || !cache || !apiInstance || !assetIn || !assetOut) return;
console.log('calculateMaxAmountIn11')
const maxAmount = tradeBalances.inBeforeTrade;
const estimate = (await estimateSell(cache, apiInstance, assetIn, assetOut, maxAmount, '0'))
console.log('calculateMaxAmountIn11 estimate done', estimate)
const paymentInfo = estimate?.partialFee.toString()
const maxAmountWithoutFee = new BigNumber(maxAmount).minus(paymentInfo || '0');
console.log('calculateMaxAmountIn12', {
inBeforeTrade: tradeBalances.inBeforeTrade,
estimate,
paymentInfo,
maxAmount,
maxAmountWithoutFee: maxAmountWithoutFee.toFixed(10)
});

return (
getValues('assetIn') === '0'
// max amount changed when all fields are filled out since that allows
// us to calculate paymentInfo
? maxAmountWithoutFee.gt('0')
? maxAmountWithoutFee.toFixed(10) : undefined
: maxAmount
);
}, [tradeBalances.inBeforeTrade, paymentInfo, cache, apiInstance, ...watch(['assetIn'])])

const maxButtonDisabled = useMemo(() => {
return maxAmountInLoading || activeAccountTradeBalancesLoading || isPoolLoading
}, [maxAmountInLoading, activeAccountTradeBalancesLoading, isPoolLoading])

const handleMaxButtonOnClick = useCallback(async () => {
setMaxAmountInLoading(true);
const maxAmountIn = await calculateMaxAmountIn();
console.log('setting max amount in', maxAmountIn);
if (maxAmountIn) setValue('assetInAmount', maxAmountIn, {
shouldDirty: true,
shouldValidate: true
})
setMaxAmountInLoading(false);
}, [calculateMaxAmountIn]);

return (
<div className="trade-form-wrapper">
Expand All @@ -593,8 +663,17 @@ export const TradeForm = ({
modalContainerRef={modalContainerRef}
balanceInputRef={assetInAmountInputRef}
assets={assets?.filter(asset => !Object.values(assetIds).includes(asset.id))}
maxBalanceLoading={maxAmountInLoading}
/>
<div className="balance-info balance-out-info">
<div
className={classNames('max-button', {
disabled: maxButtonDisabled
})}
onClick={() => handleMaxButtonOnClick()}
>
MAX
</div>
{activeAccountTradeBalancesLoading ||
isPoolLoading
? (
Expand Down Expand Up @@ -826,10 +905,7 @@ export const TradeForm = ({
},
maxTradeLimitIn: () => {
const assetInAmount = getValues('assetInAmount');
if (!assetInAmount || assetInAmount === '0') return false;
return new BigNumber(assetInLiquidity || '0')
.dividedBy(3)
.gte(assetInAmount);
return minTradeLimitIn(assetInAmount);
},
slippageHigherThanTolerance: () => {
if (!allowedSlippage) return false;
Expand Down
5 changes: 2 additions & 3 deletions src/hooks/accounts/graphql/Accounts.graphql
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#import "./../../balances/graphql/Balance.graphql"
#import './../../vesting/graphql/VestingSchedule.graphql'

type Account implements Balances {
type Account {
id: String!
name: String
source: String
genesisHash: String
# TODO: Can the balances query definition be re-used here?
balances(assetIds: [String]): [Balance!]!
balances: [Balance!]!
}

extend type Query {
Expand Down
Loading

0 comments on commit adff415

Please sign in to comment.