Skip to content

Commit

Permalink
Linting
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasdenH committed Apr 26, 2022
1 parent 8326bc5 commit 3f9c1dd
Show file tree
Hide file tree
Showing 9 changed files with 638 additions and 133 deletions.
2 changes: 2 additions & 0 deletions frontend/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
src/abi
src/generated
16 changes: 16 additions & 0 deletions frontend/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking'
],
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
};
578 changes: 524 additions & 54 deletions frontend/package-lock.json

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"react-scripts": "5.0.0",
"sass": "^1.49.10",
"tslint": "^6.1.3",
"typescript": "^4.6.2",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down Expand Up @@ -45,8 +44,12 @@
]
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"eslint": "^8.14.0",
"ethereum-abi-types-generator": "^1.3.2",
"ethers": "^5.6.2",
"prettier": "2.6.1"
"prettier": "2.6.1",
"typescript": "^4.6.3"
}
}
104 changes: 55 additions & 49 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Invest from "./components/Invest";
import poolAbi from "./abi/Pool.json";
import cauldronAbi from "./abi/Cauldron.json";
import ladleAbi from "./abi/Ladle.json";
import { emptyVaults, Vaults } from "./objects/Vault";
import { Balances, emptyVaults, Vaults, VaultsAndBalances } from "./objects/Vault";
import VaultComponent from "./components/Vault";
import { Tabs } from "./components/Tabs";
import { ContractContext as ERC20 } from "./abi/ERC20";
Expand All @@ -17,23 +17,26 @@ import { ContractContext as Cauldron } from "./abi/Cauldron";
import { ContractContext as Ladle } from "./abi/Ladle";
import yieldLeverAbi from "./generated/abi/YieldLever.json";
import yieldLeverDeployed from "./generated/deployment.json";
import { ExternalProvider } from "@ethersproject/providers";

const YIELD_LEVER_CONTRACT_ADDRESS: string = yieldLeverDeployed.deployedTo;
const USDC_ADDRESS: string = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const POOL_CONTRACT: string = "0xEf82611C6120185D3BF6e020D1993B49471E7da0";
const CAULDRON_CONTRACT: string = "0xc88191F8cb8e6D4a668B047c1C8503432c3Ca867";
const LADLE_CONTRACT: string = "0x6cB18fF2A33e981D1e38A663Ca056c0a5265066A";
const USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const POOL_CONTRACT = "0xEf82611C6120185D3BF6e020D1993B49471E7da0";
const CAULDRON_CONTRACT = "0xc88191F8cb8e6D4a668B047c1C8503432c3Ca867";
const LADLE_CONTRACT = "0x6cB18fF2A33e981D1e38A663Ca056c0a5265066A";

const YEARN_STRATEGY: string = '0xa354F35829Ae975e850e23e9615b11Da1B3dC4DE';
const YEARN_STRATEGY = '0xa354F35829Ae975e850e23e9615b11Da1B3dC4DE';

export const SERIES_ID: string = "0x303230360000";
export const ILK_ID: string = "0x303900000000";
export const SERIES_ID = "0x303230360000";
export const ILK_ID = "0x303900000000";

type YearnApiJson = { address: string, apy: { net_apy: number } }[];

interface State {
selectedAddress?: string;
networkError?: string;
usdcBalance?: BigNumber;
vaults: Vaults;
vaults: VaultsAndBalances;
yearn_apy?: number;
}

Expand All @@ -45,7 +48,7 @@ export interface Contracts {
ladleContract: Ladle;
}

export class App extends React.Component<{}, State> {
export class App extends React.Component<Record<string, never>, State> {
private readonly initialState: State;

private _provider?: ethers.providers.Web3Provider;
Expand All @@ -56,7 +59,7 @@ export class App extends React.Component<{}, State> {

private vaultsToMonitor: string[] = [];

constructor(properties: {}) {
constructor(properties: Record<string, never>) {
super(properties);
this.initialState = {
selectedAddress: undefined,
Expand All @@ -83,9 +86,9 @@ export class App extends React.Component<{}, State> {
if (!this.state.selectedAddress) {
return (
<ConnectWallet
connectWallet={() => this._connectWallet()}
connectWallet={() => void this.connectWallet()}
networkError={this.state.networkError}
dismiss={() => this._dismissNetworkError()}
dismiss={() => this.dismissNetworkError()}
/>
);
}
Expand Down Expand Up @@ -122,48 +125,53 @@ export class App extends React.Component<{}, State> {

return <Tabs>{elements}</Tabs>;
}
dismissNetworkError(): void {
throw new Error("Method not implemented.");
}

async _connectWallet() {
private async connectWallet() {
// This method is run when the user clicks the Connect. It connects the
// dapp to the user's wallet, and initializes it.

// To connect to the user's wallet, we have to run this method.
// It returns a promise that will resolve to the user's address.
const [selectedAddress] = await window.ethereum.request({
const [selectedAddress] = await (window.ethereum as { request(arg: {method: string}): Promise<[string]>}).request({
method: "eth_requestAccounts",
});

// Once we have the address, we can initialize the application.

// First we check the network
if (!this._checkNetwork()) {
if (!this.checkNetwork()) {
return;
}

this._initialize(selectedAddress);
this.initialize(selectedAddress);

// We reinitialize it whenever the user changes their account.
window.ethereum.on("accountsChanged", ([newAddress]: [string]) => {
this._stopPollingData();
(window.ethereum as { on(method: string, callback: (a: any) => void): void }
).on("accountsChanged", ([newAddress]: [string]) => {
this.stopPollingData();
// `accountsChanged` event can be triggered with an undefined newAddress.
// This happens when the user removes the Dapp from the "Connected
// list of sites allowed access to your addresses" (Metamask > Settings > Connections)
// To avoid errors, we reset the dapp state
if (newAddress === undefined) {
return this._resetState();
return this.resetState();
}

this._initialize(newAddress);
this.initialize(newAddress);
});

// We reset the dapp state if the network is changed
window.ethereum.on("chainChanged", ([networkId]: [string]) => {
this._stopPollingData();
this._resetState();
(window.ethereum as { on(method: string, callback: (a: any) => void): void }
).on("chainChanged", ([_networkId]: [string]) => {
this.stopPollingData();
this.resetState();
});
}

_initialize(userAddress: string) {
private initialize(userAddress: string) {
// This method initializes the dapp

// We first store the user's address in the component's state
Expand All @@ -176,39 +184,39 @@ export class App extends React.Component<{}, State> {

// Fetching the token data and the user's balance are specific to this
// sample project, but you can reuse the same initialization pattern.
this._initializeEthers();
this._startPollingData();
void this.initializeEthers();
void this.startPollingData();
}

async _initializeEthers() {
private initializeEthers() {
// We first initialize ethers by creating a provider using window.ethereum
this._provider = new ethers.providers.Web3Provider(window.ethereum);
this._provider = new ethers.providers.Web3Provider(window.ethereum as any as ExternalProvider, "any");
this.contracts = {
usdcContract: new ethers.Contract(
USDC_ADDRESS,
erc20Abi,
this._provider.getSigner(0)
) as any,
) as any as ERC20,
yieldLeverContract: new ethers.Contract(
YIELD_LEVER_CONTRACT_ADDRESS,
yieldLeverAbi.abi,
this._provider.getSigner(0)
) as any,
) as any as YieldLever,
poolContract: new ethers.Contract(
POOL_CONTRACT,
poolAbi,
this._provider.getSigner(0)
) as any,
) as any as Pool,
cauldronContract: new ethers.Contract(
CAULDRON_CONTRACT,
cauldronAbi,
this._provider
) as any,
) as any as Cauldron,
ladleContract: new ethers.Contract(
LADLE_CONTRACT,
ladleAbi,
this._provider
) as any,
) as any as Ladle,
};

// if (this.state.selectedAddress !== undefined)
Expand All @@ -226,19 +234,19 @@ export class App extends React.Component<{}, State> {
this.state.selectedAddress
);
this.contracts.cauldronContract.on(vaultsBuiltFilter, (vaultId: string) =>
this.addVault(vaultId)
void this.addVault(vaultId)
);
this.contracts.cauldronContract.on(
vaultsReceivedFilter,
(vaultId: string) => this.addVault(vaultId)
(vaultId: string) => void this.addVault(vaultId)
);

await this._startPollingData();
this.startPollingData();
}

// This is an utility method that turns an RPC error into a human readable
// message.
_getRpcErrorMessage(error: { data?: { message: string }; message: string }) {
getRpcErrorMessage(error: { data?: { message: string }; message: string }) {
if (error.data) {
return error.data.message;
}
Expand All @@ -247,19 +255,17 @@ export class App extends React.Component<{}, State> {
}

// This method resets the state
_resetState() {
resetState() {
this.setState(this.initialState);
}

_checkNetwork() {
checkNetwork() {
// TODO: Really check network
return true;
}

_dismissNetworkError() {}

private async _startPollingData() {
this.pollId = setInterval(() => this.pollData(), 1000) as any;
private startPollingData() {
this.pollId = setInterval(() => void this.pollData(), 1000) as any as number;
}

private async pollData() {
Expand All @@ -278,8 +284,8 @@ export class App extends React.Component<{}, State> {
])
),
]);
const vaults = Object.create(null);
const balances = Object.create(null);
const vaults = Object.create(null) as Vaults;
const balances = Object.create(null) as Balances;
this.vaultsToMonitor.forEach((vaultId, i) => {
if (vaultAndBalances[i] !== undefined) {
vaults[vaultId] = vaultAndBalances[i][0];
Expand All @@ -288,9 +294,9 @@ export class App extends React.Component<{}, State> {
});

const yearnResponse = await fetch('https://api.yearn.finance/v1/chains/1/vaults/all');
const yearnStrategies: any[] = await yearnResponse.json();
const yearnStrategies = await yearnResponse.json() as YearnApiJson;
const strategy = yearnStrategies.find((strat) => strat.address === YEARN_STRATEGY);
const yearn_apy = strategy.apy.net_apy as number;
const yearn_apy = strategy?.apy.net_apy;

this.setState({
usdcBalance,
Expand All @@ -303,7 +309,7 @@ export class App extends React.Component<{}, State> {
}
}

private _stopPollingData() {
private stopPollingData() {
clearInterval(this.pollId);
}

Expand Down
28 changes: 14 additions & 14 deletions frontend/src/components/Invest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
ContractContext as Cauldron,
} from "../abi/Cauldron";

const UNITS_USDC: number = 6;
const UNITS_LEVERAGE: number = 2;
const UNITS_USDC = 6;
const UNITS_LEVERAGE = 2;

interface Properties {
usdcBalance: BigNumber;
Expand Down Expand Up @@ -79,7 +79,7 @@ export default class Invest extends React.Component<Properties, State> {
className="button"
type="button"
value="Approve"
onClick={() => this.approve()}
onClick={() => void this.approve()}
/>
);
break;
Expand All @@ -90,7 +90,7 @@ export default class Invest extends React.Component<Properties, State> {
className="button"
type="button"
value="Transact!"
onClick={() => this.transact()}
onClick={() => void this.transact()}
/>
);
break;
Expand Down Expand Up @@ -174,14 +174,14 @@ export default class Invest extends React.Component<Properties, State> {
{this.state.interest !== undefined ? (
<ValueDisplay
label="Yield interest:"
value={this.state.interest + "% APY"}
value={`${this.state.interest} % APY`}
valueType={ValueType.Literal}
/>
) : null}
{this.props.yearnApi !== undefined ? (
<ValueDisplay
label="Yearn interest (after fees):"
value={Math.round(this.props.yearnApi * 1000) / 10 + "% APY"}
value={`${Math.round(this.props.yearnApi * 1000) / 10} % APY`}
valueType={ValueType.Literal}
/>
) : null}
Expand All @@ -190,23 +190,23 @@ export default class Invest extends React.Component<Properties, State> {
);
}

private async onSlippageChange(slippage: number) {
private onSlippageChange(slippage: number) {
this.setState({ slippage });
await this.checkApprovalState();
void this.checkApprovalState();
}

private onUsdcInputChange(usdcToInvest: BigNumber) {
this.setState({ usdcToInvest, approvalState: ApprovalState.Loading });
this.checkApprovalState();
void this.checkApprovalState();
}

private async onLeverageChange(leverage: string) {
this.setState({ leverage: utils.parseUnits(leverage, UNITS_LEVERAGE) });
await this.checkApprovalState();
private onLeverageChange(leverage: string) {
this.setState({ leverage: utils.parseUnits(leverage, UNITS_LEVERAGE), approvalState: ApprovalState.Loading });
void this.checkApprovalState();
}

public componentDidMount() {
this.checkApprovalState();
void this.checkApprovalState();
}

private totalToInvest(): BigNumber {
Expand Down Expand Up @@ -337,7 +337,7 @@ export default class Invest extends React.Component<Properties, State> {
if (this.series === undefined)
this.series = this.contracts.cauldronContract.series(
SERIES_ID
) as Promise<Series>;
) ;
return this.series;
}

Expand Down
Loading

0 comments on commit 3f9c1dd

Please sign in to comment.