Skip to content

Commit

Permalink
Merge pull request #3 from joaobrunoah/customized-eth-components
Browse files Browse the repository at this point in the history
Customized eth components
  • Loading branch information
danielmkm committed Jun 1, 2023
2 parents c595de0 + d4b9c0e commit 88d37a7
Show file tree
Hide file tree
Showing 39 changed files with 942 additions and 39 deletions.
14 changes: 3 additions & 11 deletions packages/common/src/components/FaucetHintButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { IEthComponentsSettings } from 'eth-components/models';
import { useBalance } from 'eth-hooks';
import { useEthersAppContext } from 'eth-hooks/context';
import { IEthersContext } from 'eth-hooks/models';
import { utils } from 'ethers';
import React, { FC, useMemo, useState } from 'react';
import React, { FC, useMemo } from 'react';
import { useDebounce } from 'use-debounce';

import { useTxGasPrice } from '../../../nextjs-app-ts/src/modules/pool/hooks/useTxGasPrice';
Expand Down Expand Up @@ -58,14 +57,9 @@ export const FaucetHintButton: FC<IFaucetButton> = (props) => {
const [faucetAvailable] = useDebounce(isAvailable, 500, {
trailing: true,
});
const [faucetClicked, setFaucetClicked] = useState(false);

const faucetHint = useMemo(() => {
const min = parseFloat(utils.formatUnits(yourLocalBalance?.toBigInt() ?? 0, 'ether'));
const lowFunds = yourLocalBalance && min < 0.002;
const allowFaucet = faucetAvailable && !faucetClicked && lowFunds;

if (allowFaucet && ethersAppContext?.account != null) {
if (faucetAvailable && ethersAppContext?.account != null) {
return (
<div style={{ paddingTop: 10, paddingLeft: 10 }}>
<Button
Expand All @@ -75,9 +69,7 @@ export const FaucetHintButton: FC<IFaucetButton> = (props) => {
faucetTx({
to: ethersAppContext?.account,
value: parseEther('1').toHexString(),
})
.then(() => setFaucetClicked(true))
.catch(() => setFaucetClicked(false));
}).catch((e) => console.error(e));
}
}}>
💰 Grab funds from the faucet ⛽️
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as _ from 'lodash';
import { ChangeEvent, useContext, useMemo } from 'react';

import { IBalancerAddress } from '~~/components/balancer-eth-components/balancer-address/IBalancerAddress';
import { BalancerFunctionContext } from '~~/components/balancer-eth-components/balancer-function/BalancerFunction.context';

export const useBalancerAddress = ({ input, inputIndex }: IBalancerAddress) => {
const { inputValues, setInputValues } = useContext(BalancerFunctionContext);

const title = input.name ? `${input.name} (${input.type})` : input.type;
const currentValue = _.get(inputValues, inputIndex) as unknown as string;

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { value: inputValue } = e.target;

// Clear prefix, in case the value was pasted with it.
let fixedInputValue = inputValue;
if (inputValue.indexOf('0x') >= 0) {
fixedInputValue = inputValue.replace('0x', '');
}

// Only accept Hex
const reg = /^[0-9A-Fa-f]*$/;
if (reg.test(fixedInputValue) || fixedInputValue === '') {
setInputValues((oldInputValues) => {
const newInputValues = [...oldInputValues];
_.set(newInputValues, inputIndex, `0x${fixedInputValue}`);
return newInputValues;
});
}
};

// Show the value in the UI without 0x (it's already prefixed in the field)
const valueWithoutPrefix = useMemo(() => {
if (!currentValue) return;
return currentValue.replace('0x', '');
}, [currentValue]);

return {
handleChange,
title,
valueWithoutPrefix,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Input } from 'antd';
import { FC } from 'react';

import { useBalancerAddress } from './BalancerAddress.hook';
import { IBalancerAddress } from './IBalancerAddress';

export const BalancerAddress: FC<IBalancerAddress> = (props) => {
const { handleChange, title, valueWithoutPrefix } = useBalancerAddress(props);

return (
<div className={'balancer-input-container'}>
<div className={'balancer-input-title'}>{title}</div>
<div className={'balancer-input-element'}>
<Input
addonBefore={'0x'}
placeholder={title}
onChange={handleChange}
value={valueWithoutPrefix}
maxLength={42}
/>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ParamType } from '@ethersproject/abi';

export interface IBalancerAddress {
input: ParamType;
inputIndex: number[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as _ from 'lodash';
import { ChangeEvent, useContext, useEffect, useState } from 'react';

import { BalancerFunctionContext } from '../balancer-function/BalancerFunction.context';

import { IBalancerArray } from './IBalancerArray';

export const useBalancerArray = ({ input, inputIndex }: IBalancerArray) => {
const { inputValues, setInputValues } = useContext(BalancerFunctionContext);

const [isRaw, setIsRaw] = useState(false);
const [numberArrayElements, setNumberArrayElements] = useState(0);

const rawCurrentValue: any = _.get(inputValues, inputIndex);
let currentValue: string = rawCurrentValue as unknown as string;
if (!(typeof rawCurrentValue === 'string' || rawCurrentValue instanceof String)) {
currentValue = JSON.stringify(rawCurrentValue);
}
const elementsArray = Array.from(Array(numberArrayElements).keys());
const title = input.name ? `${input.name} (${input.type})` : input.type;

useEffect(() => {
if (rawCurrentValue && rawCurrentValue.length && numberArrayElements === 0) {
setNumberArrayElements(rawCurrentValue.length);
}
}, [rawCurrentValue, isRaw]);

const onAddClick = () => {
setNumberArrayElements((old) => old + 1);
};

const onInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
setInputValues((oldInputValues) => {
const newInputValues = [...oldInputValues];
try {
_.set(newInputValues, inputIndex, JSON.parse(value));
} catch (err) {
_.set(newInputValues, inputIndex, value);
}
return newInputValues;
});
};

const onRemoveClick = () => {
setInputValues((oldInputValues) => {
const newInputValues = [...oldInputValues];
const valuesArray = _.get(newInputValues, inputIndex) as unknown as any[];
if (valuesArray && valuesArray.length >= numberArrayElements) {
valuesArray.pop();
}
_.set(newInputValues, inputIndex, valuesArray);
return newInputValues;
});
setNumberArrayElements((old) => (old <= 0 ? 0 : old - 1));
};

const onSwitchChange = (isRaw: boolean) => {
setIsRaw(isRaw);
};

return { currentValue, elementsArray, isRaw, onAddClick, onInputChange, onRemoveClick, onSwitchChange, title };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { ParamType } from '@ethersproject/abi';
import { Button, Input, Switch } from 'antd';
import { FC } from 'react';

import { BalancerInput } from '../balancer-input/BalancerInput';

import { useBalancerArray } from './BalancerArray.hook';
import { IBalancerArray } from './IBalancerArray';

export const BalancerArray: FC<IBalancerArray> = (props) => {
const { input, inputIndex } = props;
const { currentValue, elementsArray, isRaw, onAddClick, onInputChange, onRemoveClick, onSwitchChange, title } =
useBalancerArray(props);

return (
<div className={'balancer-array-container'}>
<div className={'balancer-array-title'}>
{title}
<Switch checkedChildren={'raw'} unCheckedChildren={'full'} checked={isRaw} onChange={onSwitchChange} />
</div>
{!isRaw && (
<div className={'balancer-array-body'}>
{elementsArray.map((_, index) => {
const fieldTitle = `#${index}`;
const elementInput: ParamType = {
name: fieldTitle,
type: input.type.replace('[]', ''),
baseType: '',
indexed: false,
components: [],
arrayLength: 0,
arrayChildren: input.arrayChildren,
_isParamType: true,
format: input.format,
};

return (
<div className={'balancer-array-input'} key={fieldTitle}>
<BalancerInput input={elementInput} inputIndex={[...inputIndex, index]} />
</div>
);
})}
<Button type={'primary'} danger={true} onClick={onRemoveClick} className={'balancer-array-button'}>
-
</Button>
<Button type={'primary'} onClick={onAddClick} className={'balancer-array-button'}>
+
</Button>
</div>
)}
{isRaw && <Input placeholder={title} onChange={onInputChange} value={currentValue} />}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ParamType } from '@ethersproject/abi';

export interface IBalancerArray {
input: ParamType;
inputIndex: number[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FC } from 'react';

import { BalancerAddress } from '../balancer-address/BalancerAddress';
import { BalancerBoolean } from '../balancer-boolean/BalancerBoolean';
import { BalancerInteger } from '../balancer-integer/BalancerInteger';
import { BalancerText } from '../balancer-text/BalancerText';

import { IBalancerBaseInput } from './IBalancerBaseInput';

export const BalancerBaseInput: FC<IBalancerBaseInput> = ({ input, inputIndex }) => {
if (input.type === 'string') {
return <BalancerText input={input} inputIndex={inputIndex} />;
} else if (input.type === 'address') {
return <BalancerAddress input={input} inputIndex={inputIndex} />;
} else if (input.type === 'uint256') {
return <BalancerInteger input={input} inputIndex={inputIndex} />;
} else if (input.type === 'bool') {
return <BalancerBoolean input={input} inputIndex={inputIndex} />;
} else {
return <>INPUT {input.type} NOT IMPLEMENTED</>;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ParamType } from '@ethersproject/abi';

export interface IBalancerBaseInput {
input: ParamType;
inputIndex: number[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { CheckboxChangeEvent } from 'antd/es/checkbox';
import * as _ from 'lodash';
import { useContext } from 'react';

import { BalancerFunctionContext } from '../balancer-function/BalancerFunction.context';

import { IBalancerBoolean } from './IBalancerBoolean';

export const useBalancerBoolean = ({ input, inputIndex }: IBalancerBoolean) => {
const { inputValues, setInputValues } = useContext(BalancerFunctionContext);

const title = input.name ? `${input.name} (${input.type})` : input.type;
const currentValue = _.get(inputValues, inputIndex) as unknown as boolean;

const onInputChange = (event: CheckboxChangeEvent) => {
const value = event.target.checked;
setInputValues((oldInputValues) => {
const newInputValues = [...oldInputValues];
_.set(newInputValues, inputIndex, value);
return newInputValues;
});
};

return { currentValue, onInputChange, title };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Checkbox } from 'antd';
import { FC } from 'react';

import { useBalancerBoolean } from './BalancerBoolean.hook';
import { IBalancerBoolean } from './IBalancerBoolean';

export const BalancerBoolean: FC<IBalancerBoolean> = (props) => {
const { input } = props;
const { currentValue, onInputChange, title } = useBalancerBoolean(props);

return (
<div className={'balancer-input-container'}>
<div className={'balancer-input-title'}>{title}</div>
<div className={'balancer-input-element-boolean'}>
<Checkbox onChange={onInputChange} checked={currentValue}>
{input.name}
</Checkbox>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ParamType } from '@ethersproject/abi';

export interface IBalancerBoolean {
input: ParamType;
inputIndex: number[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState } from 'react';

import { IBalancerCopyIcon } from './IBalancerCopyIcon';

const COPY_TEXT = 'Click to copy';
const COPIED_TEXT = 'Copied!';

export const useBalancerCopyIcon = ({ textToCopy }: IBalancerCopyIcon) => {
const [tooltipText, setTooltipText] = useState(COPY_TEXT);

const copyToClipboard = async () => {
await navigator.clipboard.writeText(textToCopy || '');
setTooltipText(COPIED_TEXT);
};

const resetTooltip = () => {
setTimeout(() => {
setTooltipText(COPY_TEXT);
}, 500);
};

return {
copyToClipboard,
resetTooltip,
tooltipText,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CopyOutlined } from '@ant-design/icons';
import { Tooltip } from 'antd';
import { FC } from 'react';

import { IBalancerCopyIcon } from './IBalancerCopyIcon';

import { useBalancerCopyIcon } from '~~/components/balancer-eth-components/balancer-copy-icon/BalancerCopyIcon.hook';

export const BalancerCopyIcon: FC<IBalancerCopyIcon> = ({ textToCopy }) => {
const { copyToClipboard, resetTooltip, tooltipText } = useBalancerCopyIcon({ textToCopy });

return (
<Tooltip title={tooltipText} showArrow={false}>
<CopyOutlined className={'balancer-copy-icon'} onClick={copyToClipboard} onMouseLeave={resetTooltip} />
</Tooltip>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IBalancerCopyIcon {
textToCopy: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createContext, Dispatch, SetStateAction } from 'react';

export const BalancerFunctionContext = createContext<IBalancerFunctionContext>({
inputValues: [],
setInputValues: () => undefined,
});

interface IBalancerFunctionContext {
inputValues: any[];
setInputValues: Dispatch<SetStateAction<any[]>>;
}
Loading

0 comments on commit 88d37a7

Please sign in to comment.