Skip to content

Commit

Permalink
Merge pull request #70 from rsksmart/feat/validateRNSEnv
Browse files Browse the repository at this point in the history
Feat/validate rns env
  • Loading branch information
ivegabr authored Jan 22, 2025
2 parents e85e3f9 + b1f18b0 commit 42090aa
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 12 deletions.
13 changes: 8 additions & 5 deletions src/app/lib/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface IData {
address: string
captcha: CaptchaSolutionRequest,
promoCode: string | undefined
isMainnetRns: boolean
}

//Job
Expand Down Expand Up @@ -50,15 +51,15 @@ const TESTNET_CHAIN_ID = 31;

export async function dispense(data: IData) {
const faucetHistory: FaucetHistory = loadFaucetHistory();
const { address, captcha, promoCode } = data;
const { address, captcha, promoCode, isMainnetRns } = data;

const headersList = await headers();
const ip: string = headersList.get('x-forwarded-for') || headersList.get('x-user-ip') as string;
logger.event('IP ' + ip);
const faucetBalance: number = Number(await web3.eth.getBalance(faucetAddress()));
try {

const dispenseAddress: string = await addressUtil.retriveAddressFromFrontend(address);
const dispenseAddress: string = await addressUtil.retriveAddressFromFrontend(address, isMainnetRns);
const captchaSolutionRequest: CaptchaSolutionRequest = captcha;

logger.event('dispensing to ' + dispenseAddress);
Expand All @@ -74,7 +75,8 @@ export async function dispense(data: IData) {
faucetBalance,
ip!,
promoCode,
faucetHistory
faucetHistory,
isMainnetRns
);

if (!validationStatus.valid()) {
Expand Down Expand Up @@ -183,12 +185,13 @@ const runValidations = (
faucetBalance: number,
ip: string,
promoCode: string | undefined,
faucetHistory: FaucetHistory
faucetHistory: FaucetHistory,
isMainnetRns: boolean
): ValidationStatus => {
const validations: (() => string)[] = [
() => captchaRejected(captchaSolutionResponse),
() => alreadyDispensed(dispenseAddress, ip, faucetHistory, promoCode),
() => invalidAddress(dispenseAddress),
() => invalidAddress(dispenseAddress, isMainnetRns),
() => insuficientFunds(faucetBalance)
];
const errorMessages: string[] = validations.map(validate => validate()).filter(e => e != '' && e != '-');
Expand Down
6 changes: 5 additions & 1 deletion src/components/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function Container() {
const captchaValue = useRef<ReCAPTCHA>(null);
const [dispenseAddress, setDispenseAddress] = useState<string>('');
const [siteKeyCaptcha, setSiteKeyCaptcha] = useState('');
const [isMainnetRns, setIsMainnetRns] = useState<boolean>(true);

useEffect(() => {
setSiteKeyCaptcha(siteKey());
Expand Down Expand Up @@ -56,7 +57,8 @@ function Container() {
promoCode: code,
captcha: {
token: captchaValue.current!.getValue()!
}
},
isMainnetRns: isMainnetRns
})
.then((res: DispenseResponse | undefined) => {
const data: DispenseResponse = res!;
Expand Down Expand Up @@ -88,6 +90,8 @@ function Container() {
onAddressChange: handleDispenseAddressChange,
onDispenseClick: handleFaucetButtonClick,
siteKeyCaptcha,
isMainnetRns: isMainnetRns,
setIsMainnetRns: setIsMainnetRns
};
return (
<>
Expand Down
34 changes: 32 additions & 2 deletions src/components/faucet.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ChangeEvent, RefObject, useCallback, useState } from 'react';
import React, { ChangeEvent, RefObject, useCallback, useEffect, useState } from 'react';
import ReCAPTCHA from "react-google-recaptcha";
import { debounce } from '../utils/debounce';
import Spinner from './control/Spinner';
Expand All @@ -12,6 +12,8 @@ export interface FaucetProps {
captchaValue: RefObject<ReCAPTCHA | null>;
onAddressChange: (event: ChangeEvent<HTMLInputElement>) => void;
onDispenseClick: (code: string | undefined) => void;
isMainnetRns: boolean;
setIsMainnetRns: (state: boolean) => void;
}

const Faucet = (props: FaucetProps) => {
Expand All @@ -23,7 +25,7 @@ const Faucet = (props: FaucetProps) => {
const [inputCode, setInputCode] = useState<string>('');
const [validCode, setValidCode] = useState<boolean>();
const [msgError, setMsgError] = useState<string>();

const [isRNS, setIsRNS] = useState<boolean>(false);
const handleForm = () => {
// validate form
setError({ address: false, captchaValue: false });
Expand Down Expand Up @@ -57,6 +59,14 @@ const Faucet = (props: FaucetProps) => {
debouncedGetCode(code);
}

useEffect(() => {
if(props.dispenseAddress.includes('.rsk')) {
setIsRNS(true);
} else {
setIsRNS(false);
}
}, [props.dispenseAddress]);

return (
<div className='content-form'>
<div className='faucet-form'>
Expand Down Expand Up @@ -104,6 +114,26 @@ const Faucet = (props: FaucetProps) => {
}
</div>
</div>
{isRNS &&
<div
className="toggle-container mt-4 flex items-center justify-between p-2 bg-gray-800 rounded-lg"
onClick={() => props.setIsMainnetRns(!props.isMainnetRns)}
>
<label htmlFor="toggle-feature" className="text-sm font-medium text-white">
{'RNS From Mainnet'}
</label>
<div className="relative">
<input
id="toggle-feature"
type="checkbox"
checked={props.isMainnetRns}
className="sr-only peer"
onChange={() => props.setIsMainnetRns(!props.isMainnetRns)}
/>
<div className="w-11 h-6 bg-gray-400 rounded-full peer-checked:bg-blue-600 peer-focus:ring-2 peer-focus:ring-blue-500 dark:peer-focus:ring-blue-800 transition duration-300"></div>
<div className="peer-checked:translate-x-5 absolute top-[2px] left-[2px] w-5 h-5 bg-white rounded-full transition-transform duration-300"></div>
</div>
</div>}
<div className='captcha-content'>
{ props.siteKeyCaptcha ?
<ReCAPTCHA
Expand Down
67 changes: 67 additions & 0 deletions src/styles/_content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,70 @@ footer {
}
}
}

.toggle-container {
display: flex;
align-items: center;
justify-content: space-between;
background-color: $bg2-color;
border: 1px solid $bg1-color;
border-radius: 8px;
padding: 8px 12px;
margin-top: 10px;
margin-bottom: 25px;
transition: background-color 0.3s ease;

&:hover {
background-color: darken($bg2-color, 5%);
}

label {
color: $white1;
font-size: 14px;
font-weight: 500;
}

input {
&.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}

+ div {
width: 44px;
height: 22px;
background-color: lighten($bg1-color, 5%);
border-radius: 11px;
position: relative;
cursor: pointer;
transition: background-color 0.3s ease;

&:after {
content: '';
position: absolute;
top: 1px;
left: 1px;
width: 20px;
height: 20px;
background: $white1;
border-radius: 50%;
transition: transform 0.3s ease;
}
}

&:checked + div {
background-color: green;

&:after {
transform: translateX(22px);
}
}
}
}
10 changes: 7 additions & 3 deletions src/utils/address-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ import Resolver from '@rsksmart/rns-resolver.js'

class AddressUtil {
constructor() {}
async retriveAddressFromFrontend(frontendAddress: string = 'Undefined address'): Promise<string> {
async retriveAddressFromFrontend(frontendAddress: string = 'Undefined address', mainnet: boolean): Promise<string> {
const posibleRnsAlias = frontendAddress.includes('.rsk');

if(posibleRnsAlias) {
try {
const resolver = Resolver.forRskMainnet({})
let resolver;
if(mainnet) {
resolver = Resolver.forRskMainnet({})
} else {
resolver = Resolver.forRskTestnet({})
}
const address = await resolver.addr(frontendAddress);
return address
} catch(e) {
logger.error(`Couldn't resolve address for this rnsAlias: ${frontendAddress}`);
logger.error(e);

return 'INVALID RNS';
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ export const alreadyDispensed = (address: string, ip:string, faucetHistory: Fauc
saveFaucetHistory(faucetHistory)
return ''
}
export const invalidAddress = (dispenseAddress: string): string => !isValidAddress(dispenseAddress, CHAIN_ID) ? 'Invalid address, provide a valid one.' : '';
export const invalidAddress = (dispenseAddress: string, isMainnetRns: boolean): string => !isValidAddress(dispenseAddress, isMainnetRns ? 30 : 31) ? 'Invalid address, provide a valid one.' : '';

0 comments on commit 42090aa

Please sign in to comment.