Skip to content

Commit

Permalink
feat(transfer to L2): max amount (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-ziv authored Jan 18, 2022
1 parent dd99a80 commit aeefa55
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 11 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"react-redux": "^7.2.6",
"react-scripts": "4.0.3",
"starknet": "^2.5.0",
"use-async-memo": "^1.2.3",
"use-deep-compare-effect": "^1.8.1",
"use-wallet": "^0.13.4",
"uuid": "^8.3.2",
Expand Down
13 changes: 11 additions & 2 deletions src/api/bridge.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {parseToDecimals, parseToFelt, parseToUint256} from '../utils';
import {l1_sendTransaction, l2_sendTransaction} from '../utils/contract';
import {parseFromDecimals, parseToDecimals, parseToFelt, parseToUint256} from '../utils';
import {l1_callContract, l1_sendTransaction, l2_sendTransaction} from '../utils/contract';

export const deposit = async ({recipient, amount, decimals, contract, options, emitter}) => {
try {
Expand Down Expand Up @@ -48,6 +48,15 @@ export const withdraw = async ({recipient, amount, decimals, contract, emitter})
}
};

export const maxDeposit = async ({decimals, contract}) => {
try {
const maxDeposit = await l1_callContract(contract, 'maxDeposit');
return parseFromDecimals(maxDeposit, decimals);
} catch (ex) {
return Promise.reject(ex);
}
};

export const initiateWithdraw = async ({recipient, amount, decimals, contract}) => {
try {
return l2_sendTransaction(contract, 'initiate_withdraw', {
Expand Down
1 change: 1 addition & 0 deletions src/components/Features/Transfer/Transfer.hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const useTransferData = () => {
return {
...useSelector(selectTransfer),
selectedToken: useSelectedToken(),
symbol: useSelector(selectSymbol),
isL1: useSelector(toL2Selector),
isL2: useSelector(toL1Selector),
fromNetwork: useSelector(fromNetworkSelector),
Expand Down
27 changes: 19 additions & 8 deletions src/components/Features/Transfer/Transfer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {useEffect, useState} from 'react';

import {ActionType, NetworkType} from '../../../enums';
import {useTransferToL1, useTransferToL2} from '../../../hooks';
import {useMaxAmount, useTransferToL1, useTransferToL2} from '../../../hooks';
import {useL1Token, useL2Token, useTokens} from '../../../providers/TokensProvider';
import {
Loading,
Expand All @@ -16,22 +16,24 @@ import {LoadingSize} from '../../UI/Loading/Loading.enums';
import {useBridgeActions} from '../Bridge/Bridge.hooks';
import {useAmount, useIsL1, useIsL2, useTransferActions, useTransferData} from './Transfer.hooks';
import styles from './Transfer.module.scss';
import {INSUFFICIENT_BALANCE_ERROR_MSG} from './Transfer.strings';
import {INSUFFICIENT_BALANCE_ERROR_MSG, MAX_AMOUNT_ERROR_MSG} from './Transfer.strings';

export const Transfer = () => {
const [isL1, swapToL1] = useIsL1();
const [isL2, swapToL2] = useIsL2();
const [amount, setAmount] = useAmount();
const [hasInputError, setHasInputError] = useState(false);
const [errorMsg, setErrorMsg] = useState('');
const [isButtonDisabled, setIsButtonDisabled] = useState(true);
const {showSelectTokenMenu} = useBridgeActions();
const {selectedToken, action} = useTransferData();
const {selectedToken, action, symbol} = useTransferData();
const {selectToken} = useTransferActions();
const {tokens} = useTokens();
const transferToL2 = useTransferToL2();
const transferToL1 = useTransferToL1();
const {tokens} = useTokens();
const getL1Token = useL1Token();
const getL2Token = useL2Token();
const maxAmount = useMaxAmount();

useEffect(() => {
if (!selectedToken) {
Expand All @@ -42,21 +44,30 @@ export const Transfer = () => {
useEffect(() => {
if (selectedToken) {
setHasInputError(false);
if (selectedToken.isLoading || Math.ceil(amount) === 0) {
if (selectedToken.isLoading || Math.ceil(amount) === 0 || (isL1 && !maxAmount)) {
setIsButtonDisabled(true);
} else {
if (amount > selectedToken.balance) {
setHasInputError(true);
setErrorMsg(INSUFFICIENT_BALANCE_ERROR_MSG);
setIsButtonDisabled(true);
} else if (isL1 && amount > maxAmount) {
setHasInputError(true);
setErrorMsg(MAX_AMOUNT_ERROR_MSG(maxAmount, symbol));
setIsButtonDisabled(true);
} else {
setIsButtonDisabled(false);
}
}
}
}, [amount, selectedToken]);
}, [amount, selectedToken, maxAmount, isL1]);

const onMaxClick = () => {
setAmount(selectedToken.balance.toString());
try {
setAmount(Math.min(selectedToken.balance, Number(maxAmount)));
} catch (ex) {
setAmount(selectedToken.balance);
}
};

const onInputChange = event => {
Expand Down Expand Up @@ -111,7 +122,7 @@ export const Transfer = () => {
onMaxClick={onMaxClick}
onTokenSelect={showSelectTokenMenu}
/>
{hasInputError && <div className={styles.errorMsg}>{INSUFFICIENT_BALANCE_ERROR_MSG}</div>}
{hasInputError && <div className={styles.errorMsg}>{errorMsg}</div>}
<TransferButton isDisabled={isButtonDisabled} onClick={onTransferClick} />
</>
);
Expand Down
5 changes: 4 additions & 1 deletion src/components/Features/Transfer/Transfer.strings.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import {getString} from '../../../utils';
import {evaluate, getString} from '../../../utils';

export const INSUFFICIENT_BALANCE_ERROR_MSG = getString(
'menus.transfer.insufficient_balance_error_msg'
);

export const MAX_AMOUNT_ERROR_MSG = (maxAmount, symbol) =>
evaluate(getString('menus.transfer.max_amount_error_msg'), {maxAmount, symbol});
1 change: 1 addition & 0 deletions src/config/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"to_txt": "to",
"from_txt": "from",
"insufficient_balance_error_msg": "Insufficient balance",
"max_amount_error_msg": "StarkNet Alpha Limitation: transfer to StarkNet limited to {{maxAmount}} {{symbol}}.",
"max_btn_txt": "Max",
"balance_title_txt": "Available balance",
"input_placeholder_txt": "0.00",
Expand Down
1 change: 1 addition & 0 deletions src/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export * from './useTransfer';
export * from './useConfig';
export * from './useEventListener';
export * from './useTransferProgress';
export * from './useMaxAmount';
30 changes: 30 additions & 0 deletions src/hooks/useMaxAmount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {useAsyncMemo} from 'use-async-memo';

import {maxDeposit} from '../api/bridge';
import {useTransferData} from '../components/Features/Transfer/Transfer.hooks';
import {useTokenBridgeContract} from './useContract';

const cache = {};

export const useMaxAmount = () => {
const {symbol, isL1, selectedToken} = useTransferData();
const getTokenBridgeContract = useTokenBridgeContract();

const fetchMaxAmount = async () => {
const {decimals, bridgeAddress} = selectedToken;
const contract = getTokenBridgeContract(bridgeAddress);
return await maxDeposit({decimals, contract});
};

return useAsyncMemo(async () => {
if (symbol && isL1) {
if (!cache[symbol]) {
const value = await fetchMaxAmount();
cache[symbol] = value;
return value;
}
return cache[symbol];
}
return null;
}, [symbol, isL1]);
};
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16374,6 +16374,11 @@ usb@^1.6.0:
node-addon-api "^4.2.0"
node-gyp-build "^4.3.0"

use-async-memo@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/use-async-memo/-/use-async-memo-1.2.3.tgz#fe49d7ae1cd850199cf9e4a8ee483e31ed85659f"
integrity sha512-AjZ1Wy1vfOSlaxohqoLIpauV+jwph/p0N72PBzxeEcjrZ4Mf/4o1Vav4bLaAPYuHLJZo+4M/4TIcAk7XC6H98g==

use-deep-compare-effect@^1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/use-deep-compare-effect/-/use-deep-compare-effect-1.8.1.tgz#ef0ce3b3271edb801da1ec23bf0754ef4189d0c6"
Expand Down

0 comments on commit aeefa55

Please sign in to comment.