Skip to content

Commit

Permalink
added key based assets transfer, version bump
Browse files Browse the repository at this point in the history
  • Loading branch information
poocart committed Aug 30, 2022
1 parent 6509274 commit 7ea34c9
Show file tree
Hide file tree
Showing 20 changed files with 183 additions and 126 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@etherspot/react-transaction-buidler",
"version": "0.5.10",
"version": "0.5.11",
"description": "Etherspot React component.",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down
8 changes: 5 additions & 3 deletions src/components/SelectInput/SelectInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ interface SelectInputProps {
options: SelectOption[];
selectedOption?: SelectOption | null;
onOptionSelect?: (option: SelectOption) => void;
disabled?: boolean;
}

const SelectInput = ({
Expand All @@ -83,21 +84,22 @@ const SelectInput = ({
options,
selectedOption,
onOptionSelect,
disabled = false,
}: SelectInputProps) => {
const [inputId] = useState(uniqueId('etherspot-select-input-'));

const { showSelectModal, hideSelectModal } = useTransactionBuilderModal();

const onSelectClick = useCallback(() => {
if (isLoading) return;
if (isLoading || disabled) return;

if (!onOptionSelect) {
showSelectModal(options, () => hideSelectModal());
return;
}

showSelectModal(options, onOptionSelect)
}, [isLoading, options]);
}, [isLoading, options, disabled]);

const selectedOptionTitle = useMemo(() => {
if (isLoading && !selectedOption?.title) return 'Loading options...';
Expand All @@ -114,7 +116,7 @@ const SelectInput = ({
{!!label && <Label htmlFor={inputId}>{label}</Label>}
<InputWrapper onClick={onSelectClick}>
{selectedOptionTitle}
<SelectWrapper disabled={!!isLoading}>
<SelectWrapper disabled={!!isLoading || disabled}>
{!isLoading && <SelectButton size={15} />}
{isLoading && <BeatLoader size={6} />}
</SelectWrapper>
Expand Down
13 changes: 10 additions & 3 deletions src/components/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const Input = styled.input<TextInputProps>`
&:focus {
outline: none;
}
${({ disabled }) => disabled && `
opacity: 0.6;
`}
`;

const SelectedOption = styled.span<{ placeholderText?: boolean }>`
Expand Down Expand Up @@ -88,6 +92,7 @@ interface TextInputProps {
selectedOptionDisplayValue?: string;
onOptionSelect?: (option: SelectOption) => void;
onValueChange?: (value: string) => void;
disabled?: boolean;
}

const TextInput = ({
Expand All @@ -100,6 +105,7 @@ const TextInput = ({
onOptionSelect,
onValueChange,
isLoading = false,
disabled = false,
}: TextInputProps) => {
const [inputId] = useState(uniqueId('etherspot-text-input-'));

Expand All @@ -108,15 +114,15 @@ const TextInput = ({
const { showSelectModal, hideSelectModal } = useTransactionBuilderModal();

const onSelectClick = useCallback(() => {
if (isLoading || !hasSelect) return;
if (isLoading || !hasSelect || disabled) return;

if (!onOptionSelect) {
showSelectModal(selectOptions, () => hideSelectModal());
return;
}

showSelectModal(selectOptions, onOptionSelect)
}, [isLoading, selectOptions]);
}, [isLoading, selectOptions, disabled]);


const selectedOptionTitle = useMemo(() => {
Expand All @@ -137,10 +143,11 @@ const TextInput = ({
<Input
id={inputId}
value={value ?? ''}
disabled={disabled}
onChange={(event) => onValueChange && onValueChange(event?.target?.value ?? '')}
/>
{hasSelect && (
<SelectWrapper onClick={onSelectClick} disabled={isLoading || !selectOptions?.length}>
<SelectWrapper onClick={onSelectClick} disabled={isLoading || !selectOptions?.length || disabled}>
{!isLoading && !!selectedOptionTitle && <SelectedOption>{selectedOptionTitle}</SelectedOption>}
{!isLoading && !selectedOptionTitle && <SelectedOption placeholderText>SELECT</SelectedOption>}
{isLoading && <BeatLoader size={6} />}
Expand Down
78 changes: 61 additions & 17 deletions src/components/TransactionBlock/SendAssetTransactionBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ import {
ErrorMessages,
} from '../../utils/validation';
import { supportedChains } from '../../utils/chain';
import Checkbox from '../Checkbox';

export interface SendAssetTransactionBlockValues {
fromAddress?: string;
receiverAddress?: string;
chainId?: number;
assetAddress?: string;
assetDecimals?: number;
assetSymbol?: string;
amount?: string;
isFromEtherspotWallet?: boolean;
}

const Title = styled.h3`
Expand Down Expand Up @@ -61,10 +64,18 @@ const SendAssetTransactionBlock = ({
const [availableAssets, setAvailableAssets] = useState<TokenListToken[] | null>(null);
const [availableAssetsBalances, setAvailableAssetsBalances] = useState<AccountBalance[] | null>(null);
const [isLoadingAvailableAssets, setIsLoadingAvailableAssets] = useState<boolean>(false);
const [isFromEtherspotWallet, setIsFromEtherspotWallet] = useState<boolean>(true);

const { setTransactionBlockValues, resetTransactionBlockFieldValidationError } = useTransactionBuilder();

const { sdk, getSupportedAssetsForChainId, getAssetsBalancesForChainId } = useEtherspot();
const {
sdk,
getSupportedAssetsForChainId,
getAssetsBalancesForChainId,
providerAddress,
accountAddress,
chainId,
} = useEtherspot();

useEffect(() => {
setSelectedAsset(null);
Expand All @@ -76,12 +87,21 @@ const SendAssetTransactionBlock = ({
}, [selectedNetwork]);

const updateAvailableAssets = useCallback(async () => {
if (!sdk || !selectedNetwork) return;
if (!sdk) return;
if ((isFromEtherspotWallet && !selectedNetwork) || !providerAddress) return;
setIsLoadingAvailableAssets(true);

const chainIdToLoad = isFromEtherspotWallet
? +selectedNetwork?.value
: chainId;

const addressToCheck = isFromEtherspotWallet
? accountAddress
: providerAddress;

try {
const assets = await getSupportedAssetsForChainId(+selectedNetwork.value);
const assetsBalances = await getAssetsBalancesForChainId(assets, +selectedNetwork.value);
const assets = await getSupportedAssetsForChainId(chainIdToLoad);
const assetsBalances = await getAssetsBalancesForChainId(assets, chainIdToLoad, addressToCheck);

const assetsWithPositiveBalances = assets.filter((asset) => assetsBalances.some((assetBalance) => {
if (addressesEqual(asset.address, ethers.constants.AddressZero) && assetBalance.token === null) return true;
Expand All @@ -94,7 +114,7 @@ const SendAssetTransactionBlock = ({
//
}
setIsLoadingAvailableAssets(false);
}, [sdk, selectedNetwork]);
}, [sdk, selectedNetwork, isFromEtherspotWallet, providerAddress, accountAddress, chainId]);

useEffect(() => { updateAvailableAssets(); }, [updateAvailableAssets]);

Expand Down Expand Up @@ -131,12 +151,14 @@ const SendAssetTransactionBlock = ({
if (setTransactionBlockValues) {
const asset = availableAssets?.find((availableAsset) => availableAsset.address === selectedAsset?.value);
setTransactionBlockValues(transactionBlockId, {
chainId: selectedNetwork?.value,
chainId: isFromEtherspotWallet ? selectedNetwork?.value : chainId,
assetAddress: asset?.address,
assetSymbol: asset?.symbol,
assetDecimals: asset?.decimals,
amount,
receiverAddress,
isFromEtherspotWallet,
fromAddress: (isFromEtherspotWallet ? accountAddress : providerAddress) as string,
});
}
}, [
Expand All @@ -146,6 +168,9 @@ const SendAssetTransactionBlock = ({
selectedAsset,
receiverAddress,
amount,
isFromEtherspotWallet,
accountAddress,
providerAddress,
]);

const selectedAssetDisplayValue = useMemo(
Expand All @@ -156,19 +181,38 @@ const SendAssetTransactionBlock = ({
return (
<>
<Title>Send asset</Title>
<SelectInput
label="Network"
options={supportedChains.map(mapSupportedChainToSelectOption)}
selectedOption={selectedNetwork}
onOptionSelect={(option) => {
resetTransactionBlockFieldValidationError(transactionBlockId, 'chainId');
setSelectedNetwork(option);
<Checkbox
label={`Send from Etherspot account`}
isChecked={isFromEtherspotWallet}
onChange={(isChecked) => {
setIsFromEtherspotWallet(isChecked);
resetTransactionBlockFieldValidationError(transactionBlockId, 'fromAddress');
}}
errorMessage={errorMessages?.chainId}
errorMessage={errorMessages?.fromAddress}
/>
{!!selectedNetwork && (
{isFromEtherspotWallet && (
<SelectInput
label="Network"
options={supportedChains.map(mapSupportedChainToSelectOption)}
selectedOption={selectedNetwork}
onOptionSelect={(option) => {
resetTransactionBlockFieldValidationError(transactionBlockId, 'chainId');
setSelectedNetwork(option);
}}
errorMessage={errorMessages?.chainId}
/>
)}
{!isFromEtherspotWallet && (
<TextInput
label="Network"
disabled
value={supportedChains.find((chain) => +chainId === +chain.chainId)?.title}
errorMessage={errorMessages?.chainId}
/>
)}
{(!!selectedNetwork || !isFromEtherspotWallet) && (
<TextInput
label={`Asset on ${selectedNetwork.title}`}
label={`Asset`}
isLoading={isLoadingAvailableAssets}
selectOptions={availableAssetsOptions ?? []}
selectedOption={selectedAsset}
Expand All @@ -189,7 +233,7 @@ const SendAssetTransactionBlock = ({
}
/>
)}
{!!selectedNetwork && (
{!!selectedNetwork || !isFromEtherspotWallet && (
<TextInput
label={`Receiver address`}
value={receiverAddress}
Expand Down
3 changes: 0 additions & 3 deletions src/components/TransactionBlock/TransactionBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ const TransactionBlock = (props: {
type: string;
}) => {
if (props.type === TRANSACTION_BLOCK_TYPE.SEND_ASSET) return <SendAssetTransactionBlock {...props} />;

if (props.type === TRANSACTION_BLOCK_TYPE.ASSET_BRIDGE) return <AssetBridgeTransactionBlock {...props} />;

if (props.type === TRANSACTION_BLOCK_TYPE.ASSET_SWAP) return <AssetSwapTransactionBlock {...props} />;

return null;
};

Expand Down
6 changes: 5 additions & 1 deletion src/components/TransactionPreview/ActionPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const ActionPreview = ({
if (type === TRANSACTION_BLOCK_TYPE.SEND_ASSET) {
// @ts-ignore
// TODO: fix type
const { asset, chainId, receiverAddress } = data;
const { asset, chainId, receiverAddress, fromAddress } = data;

const chainTitle = CHAIN_ID_TO_NETWORK_NAME[chainId].toUpperCase();

Expand All @@ -102,6 +102,10 @@ const ActionPreview = ({
&nbsp;<strong>{amount} ${asset.symbol}</strong>
&nbsp;on <strong>{chainTitle}</strong>
</TransactionAction>
<TransactionAction>
From address:
&nbsp;<strong>{humanizeHexString(fromAddress)}<CopyButton valueToCopy={fromAddress} left={5} top={1} /></strong>
</TransactionAction>
<TransactionAction>
Receiver address:
&nbsp;<strong>{humanizeHexString(receiverAddress)}<CopyButton valueToCopy={receiverAddress} left={5} top={1} /></strong>
Expand Down
26 changes: 8 additions & 18 deletions src/contexts/EtherspotContext.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { createContext } from 'react';
import { Sdk as EtherspotSdk } from 'etherspot/dist/sdk/sdk';
import { TokenListToken } from 'etherspot/dist/sdk/assets/classes/token-list-token';
import { AccountBalance } from 'etherspot';
import {
AccountBalance,
WalletProviderLike,
Web3WalletProvider,
} from 'etherspot';

export interface EtherspotContextData {
initialized: boolean;
data: {
accountAddress: string | null;
providerAddress: string | null;
Expand All @@ -15,24 +18,11 @@ export interface EtherspotContextData {
isConnecting: boolean;
sdk: EtherspotSdk | null;
getSupportedAssetsForChainId: (chainId: number) => Promise<TokenListToken[]>;
getAssetsBalancesForChainId: (assets: TokenListToken[], chainId: number) => Promise<AccountBalance[]>;
getAssetsBalancesForChainId: (assets: TokenListToken[], chainId: number, address?: string | null) => Promise<AccountBalance[]>;
web3Provider: WalletProviderLike | Web3WalletProvider | null;
}
}

const EtherspotContext = createContext<EtherspotContextData>({
initialized: false,
data: {
accountAddress: null,
providerAddress: null,
connect: () => new Promise(() => undefined),
chainId: 0,
setChainId: () => null,
getSdkForChainId: () => null,
isConnecting: false,
sdk: null,
getSupportedAssetsForChainId: () => new Promise(() => []),
getAssetsBalancesForChainId: () => new Promise(() => []),
}
});
const EtherspotContext = createContext<EtherspotContextData | null>(null);

export default EtherspotContext;
10 changes: 1 addition & 9 deletions src/contexts/TransactionBuilderContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,13 @@ import React, { createContext } from 'react';
import { TransactionBlockValues } from '../providers/TransactionBuilderContextProvider';

export interface TransactionBuilderContextData {
initialized: boolean;
data: {
setTransactionBlockValues: (id: string, values: TransactionBlockValues) => void;
resetTransactionBlockFieldValidationError: (id: string, field: string) => void;
resetAllTransactionBlockFieldValidationError: (id: string) => void;
}
}

const TransactionBuilderContext = createContext<TransactionBuilderContextData>({
initialized: false,
data: {
setTransactionBlockValues: () => {},
resetTransactionBlockFieldValidationError: () => {},
resetAllTransactionBlockFieldValidationError: () => {},
}
});
const TransactionBuilderContext = createContext<TransactionBuilderContextData | null>(null);

export default TransactionBuilderContext;
13 changes: 1 addition & 12 deletions src/contexts/TransactionBuilderModalContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import React, {
import { SelectOption } from '../components/SelectInput/SelectInput';

export interface TransactionBuilderModalContextData {
initialized: boolean;
data: {
showSelectModal: (options: SelectOption[], callback: (option: SelectOption) => void) => void;
hideSelectModal: () => void;
Expand All @@ -17,16 +16,6 @@ export interface TransactionBuilderModalContextData {
}
}

const TransactionBuilderModalContext = createContext<TransactionBuilderModalContextData>({
initialized: false,
data: {
showSelectModal: () => {},
hideSelectModal: () => {},
hideConfirmModal: () => {},
showConfirmModal: () => {},
hideAlertModal: () => {},
showAlertModal: () => {},
}
});
const TransactionBuilderModalContext = createContext<TransactionBuilderModalContextData | null>(null);

export default TransactionBuilderModalContext;
Loading

0 comments on commit 7ea34c9

Please sign in to comment.