Skip to content

Commit

Permalink
feat: permissioned faucets (#1359)
Browse files Browse the repository at this point in the history
* feat: captcha faucet

* fix: env example

* feat: new market, send up faucet address to api

* feat: configure new markets

* feat: send up token symbol

* feat: new ui for captcha faucet

* chore: new markets

* feat: captcha faucet modal

* fix: goerli facuet config

* fix: error handling

* fix: auto refresh token

* fix: updated env types

* ci: add turnstile key

* fix: cleanup reused code

* fix: updated wording in success modal

* chore: i18n

* refactor: tx success view

* fix: remove txHash prop

* feat: added v3.0.1 market, use new flag to determine which faucet to use

* feat: handle all types of faucets

* fix: don't use modal wrapper for permissioned faucets

* fix: use latest temp build of utils, fixed race condtion with multiple calls in flight

* feat: udated UiPoolDataProvider contracts

* fix: v2 market config

* fix: updated ui pool data provider for goerli v3

* fix: updated v2 goerli, removed console log

* fix: update prod markets with new data provider contracts

* fix: better error handling

* fix: updated v3 markets

* fix: op v3 testnet

* feat: goerli market config

* fix: add site key to env

* fix: updated config for prod v2 markets

* fix: market config

* chore: use latest utils packages

* Fix tests

* fix: temporaily disalbe pokt rpcs for testing

* fix: attribute name

* fix: test e-mode

* fix: add back in pokt rpcs

* fix: remove dependency

Co-authored-by: Vladimir Yumatov <vladimir@aave.com>
Co-authored-by: Mark Hinschberger <foodaka@users.noreply.github.com>
Co-authored-by: bojank93 <bojan@aave.com>
Co-authored-by: NikitaY <right2maresko@gmail.com>
  • Loading branch information
5 people authored Jan 18, 2023
1 parent a8b6dee commit 74bd1ac
Show file tree
Hide file tree
Showing 25 changed files with 505 additions and 113 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ NEXT_PUBLIC_API_BASEURL=https://aave-api-v2.aave.com
NEXT_PUBLIC_TRANSAK_APP_URL=https://global.transak.com
NEXT_PUBLIC_TRANSAK_API_URL=https://api.transak.com
NEXT_PUBLIC_TRANSAK_API_KEY=799087ea-c2be-44b8-a0fe-56d96b37ee3c
NEXT_PUBLIC_TURNSTILE_SITE_KEY=0x4AAAAAAABe-kMUW_1JUfT7
NEXT_PUBLIC_FORK_BASE_CHAIN_ID=1
NEXT_PUBLIC_FORK_CHAIN_ID=1
NEXT_PUBLIC_FORK_URL_RPC=https://rpc.tenderly.co/fork/1234567
1 change: 1 addition & 0 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ runs:
NEXT_PUBLIC_TRANSAK_APP_URL: 'https://global.transak.com'
NEXT_PUBLIC_TRANSAK_API_URL: 'https://api.transak.com'
NEXT_PUBLIC_TRANSAK_API_KEY: '799087ea-c2be-44b8-a0fe-56d96b37ee3c'
NEXT_PUBLIC_TURNSTILE_SITE_KEY: 0x4AAAAAAABe-kMUW_1JUfT7
NEXT_PUBLIC_FORK_BASE_CHAIN_ID: '${{ inputs.NEXT_PUBLIC_FORK_BASE_CHAIN_ID }}'
NEXT_PUBLIC_FORK_CHAIN_ID: '${{ inputs.NEXT_PUBLIC_FORK_CHAIN_ID }}'
NEXT_PUBLIC_FORK_URL_RPC: '${{ inputs.NEXT_PUBLIC_FORK_URL_RPC }}'
1 change: 1 addition & 0 deletions custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace NodeJS {
NEXT_PUBLIC_ENABLE_STAKING: string;
NEXT_PUBLIC_ENV: string;
NEXT_PUBLIC_API_BASEURL: string;
NEXT_PUBLIC_TURNSTILE_SITE_KEY: string;
NEXT_PUBLIC_FORK_BASE_CHAIN_ID?: string;
NEXT_PUBLIC_FORK_CHAIN_ID?: string;
NEXT_PUBLIC_FORK_URL_RPC?: string;
Expand Down
4 changes: 0 additions & 4 deletions cypress/support/steps/verification.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,5 @@ export const verifyCountOfBorrowAssets = (
);
});
});
it('Verifying length', () => {
cy.doSwitchToDashboardBorrowView();
cy.get('[data-cy*=dashboardBorrowListItem_]').should('have.length', assets.length);
});
});
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
"test:ci": "jest --ci"
},
"dependencies": {
"@aave/contract-helpers": "1.11.2",
"@aave/math-utils": "1.11.2",
"@aave/contract-helpers": "^1.12.2",
"@aave/math-utils": "^1.12.2",
"@emotion/cache": "11.10.3",
"@emotion/react": "11.10.4",
"@emotion/server": "latest",
Expand Down
2 changes: 2 additions & 0 deletions pages/faucet.page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Script from 'next/script';
import * as React from 'react';
import { FaucetModal } from 'src/components/transactions/Faucet/FaucetModal';
import { MainLayout } from 'src/layouts/MainLayout';
Expand All @@ -9,6 +10,7 @@ import { ContentContainer } from '../src/components/ContentContainer';
export default function Faucet() {
return (
<>
<Script src="https://challenges.cloudflare.com/turnstile/v0/api.js" strategy="lazyOnload" />
<FaucetTopPanel />
<ContentContainer>
<FaucetAssetsList />
Expand Down
4 changes: 2 additions & 2 deletions src/components/icons/WalletIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export const WalletIcon = ({ sx, ...rest }: SvgIconProps) => {
<path d="M17.3203 17.398H3.32031C2.78988 17.398 2.28117 17.1872 1.9061 16.8122C1.53103 16.4371 1.32031 15.9284 1.32031 15.3979V6.39795C1.32031 5.86752 1.53103 5.35881 1.9061 4.98374C2.28117 4.60866 2.78988 4.39795 3.32031 4.39795H17.3203C17.8507 4.39795 18.3595 4.60866 18.7345 4.98374C19.1096 5.35881 19.3203 5.86752 19.3203 6.39795V15.3979C19.3203 15.9284 19.1096 16.4371 18.7345 16.8122C18.3595 17.1872 17.8507 17.398 17.3203 17.398Z" />
<path
d="M14.8203 11.3979C14.6877 11.3979 14.5605 11.3453 14.4668 11.2515C14.373 11.1577 14.3203 11.0306 14.3203 10.8979C14.3203 10.7653 14.373 10.6382 14.4668 10.5444C14.5605 10.4506 14.6877 10.3979 14.8203 10.3979C14.9529 10.3979 15.0801 10.4506 15.1739 10.5444C15.2676 10.6382 15.3203 10.7653 15.3203 10.8979C15.3203 11.0306 15.2676 11.1577 15.1739 11.2515C15.0801 11.3453 14.9529 11.3979 14.8203 11.3979Z"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="M16.3203 4.39793V2.99993C16.3202 2.69343 16.2497 2.39106 16.1142 2.11615C15.9787 1.84124 15.7818 1.60116 15.5387 1.41444C15.2956 1.22773 15.0129 1.09937 14.7124 1.03929C14.4118 0.979209 14.1015 0.989009 13.8053 1.06793L2.80531 4.00093C2.37937 4.11444 2.00285 4.36549 1.7343 4.71506C1.46575 5.06462 1.32021 5.49312 1.32031 5.93393V6.39793" />
</g>
Expand Down
128 changes: 128 additions & 0 deletions src/components/transactions/Faucet/CaptchaFaucetModalContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { Trans } from '@lingui/macro';
import { Box, Button, CircularProgress, Typography } from '@mui/material';
import { useState } from 'react';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
import { selectCurrentReserves } from 'src/store/poolSelectors';
import { useRootStore } from 'src/store/root';

import { TxSuccessView } from '../FlowCommons/Success';
import { DetailsNumberLine } from '../FlowCommons/TxModalDetails';
import Turnstile from './Turnstile';
import { getNormalizedMintAmount } from './utils';

export const CaptchaFaucetModalContent = ({ underlyingAsset }: { underlyingAsset: string }) => {
const { readOnlyModeAddress } = useWeb3Context();
const { account, currentMarket, currentMarketData } = useRootStore();
const reserves = useRootStore((state) => selectCurrentReserves(state));

const [captchaToken, setCaptchaToken] = useState<string>('');
const [loading, setLoading] = useState<boolean>(false);
const [captchaLoading, setCaptchaLoading] = useState<boolean>(true);
const [txHash, setTxHash] = useState<string>('');
const [error, setError] = useState<string>('');

const faucetUrl = `${process.env.NEXT_PUBLIC_API_BASEURL}/faucet`;
const siteKey = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY as string;

const poolReserve = reserves.find(
(reserve) => reserve.underlyingAsset === underlyingAsset
) as ComputedReserveData;

const normalizedAmount = getNormalizedMintAmount(poolReserve.symbol, poolReserve.decimals);

const captchaVerify = (token: string) => {
setCaptchaToken(token);
setCaptchaLoading(false);
};

const faucet = async () => {
try {
setTxHash('');
setLoading(true);
setError('');
const response = await fetch(faucetUrl, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
address: account,
captchaToken,
market: currentMarket,
tokenAddress: poolReserve.underlyingAsset,
tokenSymbol: poolReserve.symbol,
faucetAddress: currentMarketData.addresses.FAUCET,
}),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.msg);
}
setTxHash(data.msg);
} catch (e: unknown) {
if (e instanceof Error && e.message) {
setError(e.message);
} else {
setError('An error occurred trying to send the transaction');
}
} finally {
setLoading(false);
}
};

if (txHash) {
return (
<TxSuccessView
txHash={txHash}
action={<Trans>will receive</Trans>}
symbol={poolReserve.symbol}
amount={normalizedAmount}
/>
);
}

return (
<>
<Turnstile sitekey={siteKey} onVerify={captchaVerify} autoResetOnExpire />
<Typography variant="h2" sx={{ mb: 6 }}>
<Trans>Faucet</Trans> {poolReserve.symbol}
</Typography>
<Box
sx={(theme) => ({
p: 3,
border: `1px solid ${theme.palette.divider}`,
borderRadius: '4px',
'.MuiBox-root:last-of-type': {
mb: 0,
},
})}
>
<DetailsNumberLine
description={<Trans>Amount</Trans>}
iconSymbol={poolReserve.symbol}
symbol={poolReserve.symbol}
value={normalizedAmount}
/>
</Box>
<Typography variant="helperText" color="error.main">
{error}
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', mt: 12 }}>
<Button
variant="contained"
disabled={loading || !captchaToken || readOnlyModeAddress !== undefined}
onClick={faucet}
size="large"
sx={{ minHeight: '44px' }}
>
{(loading || captchaLoading) && (
<CircularProgress color="inherit" size="16px" sx={{ mr: 2 }} />
)}
{<Trans>Faucet {poolReserve.symbol}</Trans>}
</Button>
</Box>
</>
);
};
14 changes: 11 additions & 3 deletions src/components/transactions/Faucet/FaucetModal.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { Trans } from '@lingui/macro';
import React from 'react';
import { ModalContextType, ModalType, useModalContext } from 'src/hooks/useModal';
import { useRootStore } from 'src/store/root';

import { BasicModal } from '../../primitives/BasicModal';
import { ModalWrapper } from '../FlowCommons/ModalWrapper';
import { CaptchaFaucetModalContent } from './CaptchaFaucetModalContent';
import { FaucetModalContent } from './FaucetModalContent';

export const FaucetModal = () => {
const { type, close, args } = useModalContext() as ModalContextType<{
underlyingAsset: string;
}>;

const { isFaucetPermissioned } = useRootStore();

return (
<BasicModal open={type === ModalType.Faucet} setOpen={close}>
<ModalWrapper title={<Trans>Faucet</Trans>} underlyingAsset={args.underlyingAsset}>
{(params) => <FaucetModalContent {...params} />}
</ModalWrapper>
{isFaucetPermissioned ? (
<CaptchaFaucetModalContent underlyingAsset={args.underlyingAsset} />
) : (
<ModalWrapper title={<Trans>Faucet</Trans>} underlyingAsset={args.underlyingAsset}>
{(params) => <FaucetModalContent {...params} />}
</ModalWrapper>
)}
</BasicModal>
);
};
10 changes: 3 additions & 7 deletions src/components/transactions/Faucet/FaucetModalContent.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { mintAmountsPerToken, valueToWei } from '@aave/contract-helpers';
import { normalize } from '@aave/math-utils';
import { Trans } from '@lingui/macro';
import { useModalContext } from 'src/hooks/useModal';

Expand All @@ -8,6 +6,7 @@ import { ModalWrapperProps } from '../FlowCommons/ModalWrapper';
import { TxSuccessView } from '../FlowCommons/Success';
import { DetailsNumberLine, TxModalDetails } from '../FlowCommons/TxModalDetails';
import { FaucetActions } from './FaucetActions';
import { getNormalizedMintAmount } from './utils';

export type FaucetModalContentProps = {
underlyingAsset: string;
Expand All @@ -17,11 +16,8 @@ export enum ErrorType {}

export const FaucetModalContent = ({ poolReserve, isWrongNetwork }: ModalWrapperProps) => {
const { gasLimit, mainTxState: faucetTxState, txError } = useModalContext();
const defaultValue = valueToWei('1000', 18);
const mintAmount = mintAmountsPerToken[poolReserve.symbol.toUpperCase()]
? mintAmountsPerToken[poolReserve.symbol.toUpperCase()]
: defaultValue;
const normalizedAmount = normalize(mintAmount, poolReserve.decimals);

const normalizedAmount = getNormalizedMintAmount(poolReserve.symbol, poolReserve.decimals);

if (faucetTxState.success)
return (
Expand Down
Loading

4 comments on commit 74bd1ac

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

Please sign in to comment.