@foreverrbum/ethsign
Version:
This package will allow you to electronically sign documents within your application
215 lines (201 loc) • 9.87 kB
JavaScript
import React, {useState, useEffect} from 'react';
import PhonebookIcon from '../../assets/phonebook.svg';
import XIcon from '../../assets/x.svg';
import EditIcon from '../../assets/edit.svg';
import {storeNotif} from '../../helpers/dashboard';
import Identicon from 'react-identicons';
import { ethers } from 'ethers';
import { useIntl, FormattedMessage } from 'react-intl';
import { getAlias } from '../../helpers/signer';
import { format } from 'highcharts';
const SignerForm = (props) => {
const {ensEnabled, signers, provider, handleSigners, id, initialValue, ethAccount, added, inReview, updateStoredData} = props;
const [currentSigner, handleCurrentSigner] = useState(initialValue);
const [loading, handleLoading] = useState(false)
const [final, handleFinal] = useState(initialValue? true:false);
const [error, handleError] = useState(false);
const [remove, handleRemove] = useState(false);
const [entered, handleEntered] = useState(0); // 0 = address, 1 = ens alias
const { formatMessage } = useIntl();
const addSigner = async () => {
handleLoading(true);
let curSigner = document.getElementById('signer-'+id).value?.toLowerCase();
if(!curSigner || curSigner.length === 0) {
handleLoading(false);
return;
}
curSigner = curSigner.trim();
let temp = signers;
const index = _.findIndex(temp, function(o) { return (o.address == curSigner || o.alias == curSigner); });
if (index>-1){ // if address has already been added to signers
storeNotif(formatMessage({id: 'ERROR'}), formatMessage({id: 'THE_SIGNER_HAS_ALREADY_BEEN_ADDED'}), "danger")
handleLoading(false)
return;
} else if(ensEnabled) {
provider.resolveName(curSigner).then(async (address) => {
// resolve is the address if curSigner is an address/alias
if(!address) { // user entered an invalid alias/address
if(curSigner.startsWith("0x") ) {
storeNotif(formatMessage({id: 'ERROR'}), formatMessage({id: 'THE_ADDRESS_YOU_ENTER_IS_INVALID'}),"danger")
} else {
storeNotif(formatMessage({id: 'ERROR'}), formatMessage({id: 'THE_SIGNER_NAME_COULD_NOT_BE_FOUND'}),"danger")
}
handleError(true)
handleLoading(false)
return;
}else{ // user entered a valid alias or an address
address = address.toLowerCase();
let alias, avatar = null;
if(ethers.utils.isAddress(address)) { // address is valid
if(!curSigner.startsWith('0x')) {
alias = curSigner;
handleEntered(1); // user entered an address
} else {
alias = await provider.lookupAddress(address)
handleEntered(0); // user entered an alias
}
if (alias){
const resolver = await provider.getResolver(alias);
avatar = await resolver.getText("avatar");
}
const temp_signer = {
address: address,
alias: alias,
avatar: avatar
}
temp.push(temp_signer);
handleSigners(temp);
updateStoredData(temp)
handleCurrentSigner(temp_signer)
handleFinal(true);
handleLoading(false)
} else {
storeNotif(formatMessage({id: 'ERROR'}), formatMessage({id: 'THE_ADDRESS_YOU_ENTER_IS_INVALID'}),"danger");
handleError(true);
handleLoading(false)
return;
}
}
}).catch((err)=> {
console.log(err)
storeNotif(formatMessage({id: 'ERROR'}), formatMessage({id: 'THE_ADDRESS_YOU_ENTER_IS_INVALID'}),"danger");
handleError(true);
handleLoading(false)
return;
})
} else {
if(curSigner.startsWith("0x")){
if(ethers.utils.isAddress(curSigner)) {
const temp_signer = {
address: curSigner,
alias: null,
avatar: null
}
temp.push(temp_signer);
handleCurrentSigner(temp_signer);
handleSigners(temp);
updateStoredData(temp)
handleFinal(true);
} else {
storeNotif(formatMessage({id: 'ERROR'}), formatMessage({id: 'THE_ADDRESS_YOU_ENTER_IS_INVALID'}),"danger");
handleLoading(false)
handleError(true);
return;
}
}else{
storeNotif(formatMessage({id: 'ERROR'}), formatMessage({id: 'THE_SIGNER_ADDRESS_SHOULD_START_WITH_0X'}),"danger")
handleLoading(false)
handleError(true)
return;
}
handleLoading(false)
}
}
const removeSigner = () => {
if(currentSigner != null){
let temp = signers;
temp = _.pull(temp, currentSigner);
handleSigners(temp)
updateStoredData(temp)
}
handleRemove(true);
}
useEffect (()=>{
// if editing
if(final == false && currentSigner != null){
document.getElementById('signer-'+id).value = entered == 0 ? currentSigner.address : currentSigner.alias;
// remove currentSigner from the signers
let temp = signers;
temp = _.pull(temp, currentSigner);
}
handleError(false)
},[final]);
return (
<>
{ !remove &&
<div className="min-h-20 shadow-md px-5 my-4 py-4 flex w-45p relative flex-wrap xs:flex-nowrap md:flex-wrap lg:flex-nowrap">
{!added && !inReview &&
<img src={XIcon} className="absolute -top-2 -right-2 z-20 cursor-pointer" onClick={()=>{removeSigner()}}/>
}
<div className="flex flex-grow">
<div className={`flex flex-col mr-3 ${!final && 'self-end'}`}>
{final?
<>
<div className={`identicon flex flex-col justify-center my-auto w-11 h-11 border border-orange-500 rounded-full`}>
{ensEnabled && currentSigner?.avatar != null?
<img className="w-11 h-11 rounded-full object-cover" src={currentSigner.avatar} />
:
<div className="p-2">
<Identicon string={currentSigner?.address?.toLowerCase()} size="25" palette={['#D7EEFF', '#eef2ff', '#991A1A', '#FFDECC', '#E98234', '#D98234','#EE9F63', '#464648']} />
</div>
}
</div>
{!added && <img src={EditIcon} onClick={()=>{handleFinal(false);}} className="xs:hidden mx-auto my-auto mt-2 cursor-pointer"/>}
</>
:
<img src={PhonebookIcon} className='mb-1'></img>
}
</div>
<div className="flex-grow mr-3 xl:mr-8 my-auto">
<div className="font-medium pb-1">
{final ?
<>
{getAlias(ethAccount, currentSigner, ensEnabled, formatMessage)}
</>
: <FormattedMessage id="ENS_ALIAS_OR_ADDRESS" />
}
</div>
{final?
<div className="text-gray-200 font-medium select-all">
{currentSigner?.address?.toLowerCase()}
</div>
:
<input
className={`focus:outline-none focus:ring focus:border-blue-300 w-full rounded-sm border-b mr-0 border-gray-200 ${error && 'ring border-b border-blue-300'}`}
type="text"
name="signer"
id={`signer-${id}`}
placeholder={formatMessage({id: 'ENS_ALIAS_OR_ADDRESS'})}
autoComplete="new-password"
/>
}
</div>
{!added && final && !inReview && <img src={EditIcon} onClick={()=>{handleFinal(false)}} className="hidden xs:block my-auto px-5 cursor-pointer"/>}
</div>
{!final &&
<div className="mt-2 lg:mt-0 w-full xs:w-auto md:w-full lg:w-auto self-end">
<div className="text-center cursor-pointer h-auto rounded-md px-5 py-2 bg-orange-500 hover:bg-orange-600 text-white" onClick={()=>{addSigner()}}>
{loading == true?
<FormattedMessage id='ADDING' />
:
<FormattedMessage id='ADD' />
}
</div>
</div>
}
</div>
}
</>
);
}
export default SignerForm;