diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index facd3bb8..cb6308ae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -101,15 +101,14 @@ jobs: - CIDv0: `${{ steps.upload.outputs.hash }}` - CIDv1: `${{ steps.convert_cidv0.outputs.cidv1 }}` - The latest release is always accessible via our alias to the Cloudflare IPFS gateway at [app.reflexer.finance](https://app.reflexer.finance). + The latest release is always accessible via our alias to the Cloudflare at [app.reflexer.finance](https://app.reflexer.finance). You can also access the Reflexer app directly from an IPFS gateway. **BEWARE**: The Reflexer app uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as transactions hashes. - **You should always use an IPFS gateway that enforces origin separation**, or our alias to the latest release at [ipfs.reflexer.finance](https://ipfs.reflexer.finance). + **You should always use an IPFS gateway that enforces origin separation**, or our alias to the latest release IPFS gateways: - https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.dweb.link/ - - https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.cf-ipfs.com/ - [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.upload.outputs.hash }}/) ${{ needs.bump_version.outputs.changelog }} diff --git a/README.md b/README.md index 1c1689e1..4b64f9c4 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Deposit your crypto assets, generate RAI and lever up your position. - Website: [reflexer.finance](https://reflexer.finance/) - App: [app.reflexer.finance](https://app.reflexer.finance) - Analytics: [stats.reflexer.finance](https://stats.reflexer.finance/) +- Tokenomics: [tokenomics.reflexer.finance](https://tokenomics.reflexer.finance/) - Docs: [docs.reflexer.finance](https://docs.reflexer.finance/) - Twitter: [@reflexerfinance](https://twitter.com/reflexerfinance) - Discord: [Reflexer](https://discord.com/invite/83t3xKT) @@ -20,7 +21,7 @@ Deposit your crypto assets, generate RAI and lever up your position. ## Accessing the Uniswap Interface -To access the Uniswap Interface, use an IPFS gateway link from the +To access the Reflexer Interface, use an IPFS gateway link from the [latest release](https://github.com/reflexer-labs/geb-app/releases/latest), or visit [https://app.reflexer.finance](https://app.reflexer.finance). @@ -47,6 +48,7 @@ To have the app default to a different network when a wallet is not connected: 2. Change `REACT_APP_NETWORK_ID` to `"42"` 3. Change `REACT_APP_NETWORK_URL` to e.g. `"https://kovan.infura.io/v3/{YOUR_INFURA_KEY}"` 4. Change `REACT_APP_COIN_TICKER_STAGING` to `"RAI"` +4. Change `REACT_APP_SHOW_AUCTIONS` to `"1"` ## Testing diff --git a/cypress/integration/landing-no-proxy.test.ts b/cypress/integration/landing-no-proxy.test.ts index fb0f0e88..c9b89d6c 100644 --- a/cypress/integration/landing-no-proxy.test.ts +++ b/cypress/integration/landing-no-proxy.test.ts @@ -12,7 +12,7 @@ describe('App Page - No Proxy', () => { cy.visit('/', { qs: { type: 'no_proxy' }, }) - cy.wait(2000) + cy.wait(5000) cy.get('body').then((body) => { if (body.find('[data-test-id="waiting-modal"]').length > 0) { cy.get('[data-test-id="waiting-modal"]').then((e) => { @@ -47,7 +47,7 @@ describe('App Page - No Proxy', () => { cy.get('#step1 > div').contains('Create Account') cy.contains('✓ Accept').click() cy.get('[data-test-id="steps-btn"]').contains('Create Account').click() - cy.wait(2000) + cy.wait(5000) cy.contains('Transaction Failed').should('be.visible') cy.contains('Dismiss').should('be.visible') }) diff --git a/cypress/integration/landing-no-safes.test.ts b/cypress/integration/landing-no-safes.test.ts index e62d4034..f7d2450f 100644 --- a/cypress/integration/landing-no-safes.test.ts +++ b/cypress/integration/landing-no-safes.test.ts @@ -11,7 +11,7 @@ describe('App Page - No Safes', () => { cy.visit('/', { qs: { type: 'no_safes' }, }) - cy.wait(2000) + cy.wait(5000) cy.get('body').then((body) => { if (body.find('[data-test-id="waiting-modal"]').length > 0) { cy.get('[data-test-id="waiting-modal"]').then((e) => { @@ -41,14 +41,14 @@ describe('App Page - No Safes', () => { cy.contains('✓ Accept').click() cy.get('#step2 > div').contains('Create a Safe') cy.get('[data-test-id="steps-btn"]').contains('Create a Safe').click() - cy.wait(2000) + cy.wait(5000) cy.url().should('include', 'create') }) it('creates a new safe', () => { cy.contains('✓ Accept').click() cy.get('[data-test-id="steps-btn"]').contains('Create a Safe').click() - cy.wait(2000) + cy.wait(5000) cy.url().should('include', 'create') cy.get('[data-test-id="deposit_borrow"]').type('4') cy.get('[data-test-id="repay_withdraw"]').type('1000') diff --git a/cypress/integration/landing-safes.test.ts b/cypress/integration/landing-safes.test.ts index 0bb72c10..a310332a 100644 --- a/cypress/integration/landing-safes.test.ts +++ b/cypress/integration/landing-safes.test.ts @@ -8,7 +8,7 @@ import { describe('App Page - Has Safes', () => { beforeEach(() => { cy.visit('/') - cy.wait(2000) + cy.wait(5000) cy.get('body').then((body) => { if (body.find('[data-test-id="waiting-modal"]').length > 0) { cy.get('[data-test-id="waiting-modal"]').then((e) => { diff --git a/cypress/integration/safe-details.test.ts b/cypress/integration/safe-details.test.ts index 3900f719..88897e2e 100644 --- a/cypress/integration/safe-details.test.ts +++ b/cypress/integration/safe-details.test.ts @@ -10,7 +10,7 @@ describe('App Page - Safe Details', () => { beforeEach(() => { cy.visit('/') - cy.wait(2000) + cy.wait(5000) cy.get('body').then((body) => { if (body.find('[data-test-id="waiting-modal"]').length > 0) { cy.get('[data-test-id="waiting-modal"]').then((e) => { @@ -24,7 +24,7 @@ describe('App Page - Safe Details', () => { }) cy.contains('✓ Accept').click() cy.get('.safeBlock').first().click() - cy.wait(2000) + cy.wait(5000) cy.get('body').then((body) => { if (body.find('[data-test-id="waiting-modal"]').length > 0) { cy.get('[data-test-id="waiting-modal"]').then((e) => { @@ -61,7 +61,7 @@ describe('App Page - Safe Details', () => { cy.get('[data-test-id="deposit_borrow_right"]').type( getValue(tx) ) - cy.wait(2000) + cy.wait(5000) cy.contains('140.00%') }) }) @@ -131,7 +131,7 @@ describe('App Page - Safe Details', () => { () => Cypress.$(e).text() === 'Transaction Submitted', { timeout: 100000, - interval: 2000, + interval: 5000, } ) ) @@ -154,7 +154,7 @@ describe('App Page - Safe Details', () => { () => Cypress.$(e).text() === 'Transaction Submitted', { timeout: 100000, - interval: 2000, + interval: 5000, } ) ) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index de99d804..7241518a 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -139,6 +139,12 @@ const returnWallet = (type: string) => { } } +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + return false +}) + Cypress.Commands.overwrite('visit', (original, url, options) => { const { privateKey, walletAddress, allowTx } = returnWallet( options && options.qs ? options.qs.type : '' diff --git a/package.json b/package.json index 5c754666..e360e3a4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "geb-app", "version": "0.1.0", - "homepage": "./", + "homepage": ".", "private": true, "dependencies": { "@ethersproject/address": "^5.0.10", @@ -54,14 +54,15 @@ "react-transition-group": "^4.4.1", "styled-components": "^5.2.0", "typescript": "3.8.3", - "walletlink": "^2.1.0" + "walletlink": "^2.1.0", + "web3-react-types": "npm:@web3-react/types@^6.0.7" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "prettier": "prettier --write \"{,**/*.{ts,tsx,json,js,md}}\"", "test": "react-scripts test", - "test:e2e": "start-server-and-test start http://localhost:3000 'cypress run'", + "test:e2e": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'", "eject": "react-scripts eject" }, "eslintConfig": { @@ -93,7 +94,7 @@ "@types/react-transition-group": "^4.4.0", "@types/styled-components": "^5.1.3", "crypto": "^1.0.1", - "cypress": "^6.4.0", + "cypress": "^7.7.0", "cypress-wait-until": "^1.7.1", "husky": "^5.0.9", "lint-staged": "^10.5.4", diff --git a/src/App.tsx b/src/App.tsx index ff4619ab..d43f772d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,29 +1,28 @@ import React, { Suspense, useEffect } from 'react' import i18next from 'i18next' -import { HashRouter as Router, Redirect, Route, Switch } from 'react-router-dom' +import { Redirect, Route, Switch } from 'react-router-dom' import { ThemeProvider } from 'styled-components' import { I18nextProvider } from 'react-i18next' import ErrorBoundary from './ErrorBoundary' import { useStoreState } from './store' import { darkTheme } from './utils/themes/dark' import { Theme } from './utils/interfaces' -import OnBoarding from './containers/OnBoarding' +import Safes from './containers/Safes' import { initI18n } from './utils/i18n' import GlobalStyle from './GlobalStyle' import Shared from './containers/Shared' import Web3ReactManager from './components/Web3ReactManager' -import SafeDetails from './containers/OnBoarding/SafeDetails' +import SafeDetails from './containers/Safes/SafeDetails' import Privacy from './containers/Privacy' import CustomToast from './components/CustomToast' import Auctions from './containers/Auctions' import GoogleTagManager from './components/Analytics/GoogleTagManager' import { SHOW_AUCTIONS } from './utils/constants' -import SafeSaviour from './containers/OnBoarding/Saviour/SafeSaviour' +import SafeSaviour from './containers/Safes/Saviour/SafeSaviour' import Staking from './containers/Earn/Staking' import Incentives from './containers/Earn/Incentives' -import CreateSafe from './containers/OnBoarding/CreateSafe' -// import MoneyGodLeague from './containers/Earn/MoneyGodLeague' +import CreateSafe from './containers/Safes/CreateSafe' // Toast css @@ -46,98 +45,90 @@ const App = () => { - - - - - - - {SHOW_AUCTIONS && - SHOW_AUCTIONS === '1' ? ( - - ) : null} + + + + + + {SHOW_AUCTIONS && SHOW_AUCTIONS === '1' ? ( - {/* */} - - - - - - - - - - - - - - - - + ) : null} + + + + + + + + + + + + + + + + + diff --git a/src/abis/Erc20.ts b/src/abis/Erc20.ts index 058fb6f3..9342fbae 100644 --- a/src/abis/Erc20.ts +++ b/src/abis/Erc20.ts @@ -16,7 +16,7 @@ import { } from 'ethers' import { FunctionFragment, Result, EventFragment } from '@ethersproject/abi' import { Listener, Provider } from '@ethersproject/providers' -import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from './common' +import { TypedEventFilter, TypedEvent, TypedListener } from './common' export interface Erc20Interface extends utils.Interface { functions: { @@ -81,45 +81,56 @@ export interface Erc20Interface extends utils.Interface { getEvent(nameOrSignatureOrTopic: 'Transfer'): EventFragment } -export type ApprovalEvent = TypedEvent< +export type ApprovalEventFilter = TypedEventFilter< [string, string, BigNumber], - { owner: string; spender: string; value: BigNumber } + { from: string; to: string; value: BigNumber } > -export type ApprovalEventFilter = TypedEventFilter - -export type TransferEvent = TypedEvent< +export type TransferEventFilter = TypedEventFilter< [string, string, BigNumber], { from: string; to: string; value: BigNumber } > -export type TransferEventFilter = TypedEventFilter - export interface Erc20 extends BaseContract { connect(signerOrProvider: Signer | Provider | string): this attach(addressOrName: string): this deployed(): Promise - interface: Erc20Interface - - queryFilter( - event: TypedEventFilter, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise> + listeners, EventArgsObject>( + eventFilter?: TypedEventFilter + ): Array> + off, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + on, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + once, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + removeListener, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + removeAllListeners, EventArgsObject>( + eventFilter: TypedEventFilter + ): this - listeners( - eventFilter?: TypedEventFilter - ): Array> listeners(eventName?: string): Array - removeAllListeners( - eventFilter: TypedEventFilter - ): this + off(eventName: string, listener: Listener): this + on(eventName: string, listener: Listener): this + once(eventName: string, listener: Listener): this + removeListener(eventName: string, listener: Listener): this removeAllListeners(eventName?: string): this - off: OnEvent - on: OnEvent - once: OnEvent - removeListener: OnEvent + + queryFilter, EventArgsObject>( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>> functions: { name(overrides?: CallOverrides): Promise<[string]> diff --git a/src/abis/Multicall.ts b/src/abis/Multicall.ts new file mode 100644 index 00000000..3a8e3a99 --- /dev/null +++ b/src/abis/Multicall.ts @@ -0,0 +1,171 @@ +import { MulticallRequest } from '@reflexer-finance/geb-contract-base' +import { Provider, Listener } from '@ethersproject/providers' +import { BytesLike } from '@ethersproject/bytes' +import { BigNumberish } from '@ethersproject/bignumber' +import { BigNumber } from '@ethersproject/bignumber' +import { FunctionFragment, Result } from 'ethers/lib/utils' +import { + BaseContract, + ethers, + Signer, + CallOverrides, + ContractTransaction, + Overrides, +} from 'ethers' +import { TypedEvent, TypedEventFilter, TypedListener } from './common' + +export type CallStruct = { target: string; callData: BytesLike } + +export type CallStructOutput = [string, string] & { + target: string + callData: string +} + +interface MulticallInterface extends ethers.utils.Interface { + functions: { + 'getCurrentBlockTimestamp()': FunctionFragment + 'getEthBalance(address)': FunctionFragment + 'multicall(tuple[])': FunctionFragment + } + + encodeFunctionData( + functionFragment: 'getCurrentBlockTimestamp', + values?: undefined + ): string + encodeFunctionData( + functionFragment: 'getEthBalance', + values: [string] + ): string + encodeFunctionData( + functionFragment: 'multicall', + values: [ + { target: string; gasLimit: BigNumberish; callData: BytesLike }[] + ] + ): string + + decodeFunctionResult( + functionFragment: 'getCurrentBlockTimestamp', + data: BytesLike + ): Result + decodeFunctionResult( + functionFragment: 'getEthBalance', + data: BytesLike + ): Result + decodeFunctionResult(functionFragment: 'multicall', data: BytesLike): Result + + events: {} +} + +export declare class Multicall extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this + attach(addressOrName: string): this + deployed(): Promise + + listeners, EventArgsObject>( + eventFilter?: TypedEventFilter + ): Array> + off, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + on, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + once, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + removeListener, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this + removeAllListeners, EventArgsObject>( + eventFilter: TypedEventFilter + ): this + + listeners(eventName?: string): Array + off(eventName: string, listener: Listener): this + on(eventName: string, listener: Listener): this + once(eventName: string, listener: Listener): this + removeListener(eventName: string, listener: Listener): this + removeAllListeners(eventName?: string): this + + queryFilter, EventArgsObject>( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>> + interface: MulticallInterface + aggregate( + calls: { + target: string + callData: BytesLike + }[] + ): Promise<{ + blockNumber: BigNumber + returnData: string[] + }> + aggregate_readOnly( + calls: { + target: string + callData: BytesLike + }[] + ): Promise<{ + blockNumber: BigNumber + returnData: string[] + }> + aggregate_readOnly( + calls: { + target: string + callData: BytesLike + }[], + multicall: true + ): MulticallRequest<{ + blockNumber: BigNumber + returnData: string[] + }> + getBlockHash(blockNumber: BigNumberish): Promise + getBlockHash( + blockNumber: BigNumberish, + multicall: true + ): MulticallRequest + getCurrentBlockCoinbase(): Promise + getCurrentBlockCoinbase(multicall: true): MulticallRequest + getCurrentBlockDifficulty(): Promise + getCurrentBlockDifficulty(multicall: true): MulticallRequest + getCurrentBlockGasLimit(): Promise + getCurrentBlockGasLimit(multicall: true): MulticallRequest + getCurrentBlockTimestamp(): Promise + getCurrentBlockTimestamp(multicall: true): MulticallRequest + getEthBalance(addr: string): Promise + getEthBalance(addr: string, multicall: true): MulticallRequest + getLastBlockHash(): Promise + getLastBlockHash(multicall: true): MulticallRequest + functions: { + aggregate( + calls: CallStruct[], + overrides?: Overrides & { from?: string | Promise } + ): Promise + getCurrentBlockTimestamp( + overrides?: CallOverrides + ): Promise<[BigNumber] & { timestamp: BigNumber }> + getEthBalance( + addr: string, + overrides?: CallOverrides + ): Promise<[BigNumber] & { balance: BigNumber }> + } + callStatic: { + aggregate( + calls: CallStruct[], + overrides?: CallOverrides + ): Promise< + [BigNumber, string[]] & { + blockNumber: BigNumber + returnData: string[] + } + > + getCurrentBlockTimestamp(overrides?: CallOverrides): Promise + getEthBalance(addr: string): Promise + } +} diff --git a/src/abis/Multicall2.ts b/src/abis/Multicall2.ts deleted file mode 100644 index 863111bf..00000000 --- a/src/abis/Multicall2.ts +++ /dev/null @@ -1,428 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import { - BaseContract, - BigNumber, - BigNumberish, - BytesLike, - CallOverrides, - ContractTransaction, - Overrides, - PopulatedTransaction, - Signer, - utils, -} from "ethers"; -import { FunctionFragment, Result } from "@ethersproject/abi"; -import { Listener, Provider } from "@ethersproject/providers"; -import { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from "./common"; - -export type CallStruct = { target: string; callData: BytesLike }; - -export type CallStructOutput = [string, string] & { - target: string; - callData: string; -}; - -export type ResultStruct = { success: boolean; returnData: BytesLike }; - -export type ResultStructOutput = [boolean, string] & { - success: boolean; - returnData: string; -}; - -export interface Multicall2Interface extends utils.Interface { - functions: { - "aggregate((address,bytes)[])": FunctionFragment; - "blockAndAggregate((address,bytes)[])": FunctionFragment; - "getBlockHash(uint256)": FunctionFragment; - "getBlockNumber()": FunctionFragment; - "getCurrentBlockCoinbase()": FunctionFragment; - "getCurrentBlockDifficulty()": FunctionFragment; - "getCurrentBlockGasLimit()": FunctionFragment; - "getCurrentBlockTimestamp()": FunctionFragment; - "getEthBalance(address)": FunctionFragment; - "getLastBlockHash()": FunctionFragment; - "tryAggregate(bool,(address,bytes)[])": FunctionFragment; - "tryBlockAndAggregate(bool,(address,bytes)[])": FunctionFragment; - }; - - encodeFunctionData( - functionFragment: "aggregate", - values: [CallStruct[]] - ): string; - encodeFunctionData( - functionFragment: "blockAndAggregate", - values: [CallStruct[]] - ): string; - encodeFunctionData( - functionFragment: "getBlockHash", - values: [BigNumberish] - ): string; - encodeFunctionData( - functionFragment: "getBlockNumber", - values?: undefined - ): string; - encodeFunctionData( - functionFragment: "getCurrentBlockCoinbase", - values?: undefined - ): string; - encodeFunctionData( - functionFragment: "getCurrentBlockDifficulty", - values?: undefined - ): string; - encodeFunctionData( - functionFragment: "getCurrentBlockGasLimit", - values?: undefined - ): string; - encodeFunctionData( - functionFragment: "getCurrentBlockTimestamp", - values?: undefined - ): string; - encodeFunctionData( - functionFragment: "getEthBalance", - values: [string] - ): string; - encodeFunctionData( - functionFragment: "getLastBlockHash", - values?: undefined - ): string; - encodeFunctionData( - functionFragment: "tryAggregate", - values: [boolean, CallStruct[]] - ): string; - encodeFunctionData( - functionFragment: "tryBlockAndAggregate", - values: [boolean, CallStruct[]] - ): string; - - decodeFunctionResult(functionFragment: "aggregate", data: BytesLike): Result; - decodeFunctionResult( - functionFragment: "blockAndAggregate", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getBlockHash", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getBlockNumber", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getCurrentBlockCoinbase", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getCurrentBlockDifficulty", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getCurrentBlockGasLimit", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getCurrentBlockTimestamp", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getEthBalance", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "getLastBlockHash", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "tryAggregate", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "tryBlockAndAggregate", - data: BytesLike - ): Result; - - events: {}; -} - -export interface Multicall2 extends BaseContract { - connect(signerOrProvider: Signer | Provider | string): this; - attach(addressOrName: string): this; - deployed(): Promise; - - interface: Multicall2Interface; - - queryFilter( - event: TypedEventFilter, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>; - - listeners( - eventFilter?: TypedEventFilter - ): Array>; - listeners(eventName?: string): Array; - removeAllListeners( - eventFilter: TypedEventFilter - ): this; - removeAllListeners(eventName?: string): this; - off: OnEvent; - on: OnEvent; - once: OnEvent; - removeListener: OnEvent; - - functions: { - aggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - blockAndAggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - getBlockHash( - blockNumber: BigNumberish, - overrides?: CallOverrides - ): Promise<[string] & { blockHash: string }>; - - getBlockNumber( - overrides?: CallOverrides - ): Promise<[BigNumber] & { blockNumber: BigNumber }>; - - getCurrentBlockCoinbase( - overrides?: CallOverrides - ): Promise<[string] & { coinbase: string }>; - - getCurrentBlockDifficulty( - overrides?: CallOverrides - ): Promise<[BigNumber] & { difficulty: BigNumber }>; - - getCurrentBlockGasLimit( - overrides?: CallOverrides - ): Promise<[BigNumber] & { gaslimit: BigNumber }>; - - getCurrentBlockTimestamp( - overrides?: CallOverrides - ): Promise<[BigNumber] & { timestamp: BigNumber }>; - - getEthBalance( - addr: string, - overrides?: CallOverrides - ): Promise<[BigNumber] & { balance: BigNumber }>; - - getLastBlockHash( - overrides?: CallOverrides - ): Promise<[string] & { blockHash: string }>; - - tryAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - tryBlockAndAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - }; - - aggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - blockAndAggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - getBlockHash( - blockNumber: BigNumberish, - overrides?: CallOverrides - ): Promise; - - getBlockNumber(overrides?: CallOverrides): Promise; - - getCurrentBlockCoinbase(overrides?: CallOverrides): Promise; - - getCurrentBlockDifficulty(overrides?: CallOverrides): Promise; - - getCurrentBlockGasLimit(overrides?: CallOverrides): Promise; - - getCurrentBlockTimestamp(overrides?: CallOverrides): Promise; - - getEthBalance(addr: string, overrides?: CallOverrides): Promise; - - getLastBlockHash(overrides?: CallOverrides): Promise; - - tryAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - tryBlockAndAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - callStatic: { - aggregate( - calls: CallStruct[], - overrides?: CallOverrides - ): Promise< - [BigNumber, string[]] & { blockNumber: BigNumber; returnData: string[] } - >; - - blockAndAggregate( - calls: CallStruct[], - overrides?: CallOverrides - ): Promise< - [BigNumber, string, ResultStructOutput[]] & { - blockNumber: BigNumber; - blockHash: string; - returnData: ResultStructOutput[]; - } - >; - - getBlockHash( - blockNumber: BigNumberish, - overrides?: CallOverrides - ): Promise; - - getBlockNumber(overrides?: CallOverrides): Promise; - - getCurrentBlockCoinbase(overrides?: CallOverrides): Promise; - - getCurrentBlockDifficulty(overrides?: CallOverrides): Promise; - - getCurrentBlockGasLimit(overrides?: CallOverrides): Promise; - - getCurrentBlockTimestamp(overrides?: CallOverrides): Promise; - - getEthBalance(addr: string, overrides?: CallOverrides): Promise; - - getLastBlockHash(overrides?: CallOverrides): Promise; - - tryAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: CallOverrides - ): Promise; - - tryBlockAndAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: CallOverrides - ): Promise< - [BigNumber, string, ResultStructOutput[]] & { - blockNumber: BigNumber; - blockHash: string; - returnData: ResultStructOutput[]; - } - >; - }; - - filters: {}; - - estimateGas: { - aggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - blockAndAggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - getBlockHash( - blockNumber: BigNumberish, - overrides?: CallOverrides - ): Promise; - - getBlockNumber(overrides?: CallOverrides): Promise; - - getCurrentBlockCoinbase(overrides?: CallOverrides): Promise; - - getCurrentBlockDifficulty(overrides?: CallOverrides): Promise; - - getCurrentBlockGasLimit(overrides?: CallOverrides): Promise; - - getCurrentBlockTimestamp(overrides?: CallOverrides): Promise; - - getEthBalance(addr: string, overrides?: CallOverrides): Promise; - - getLastBlockHash(overrides?: CallOverrides): Promise; - - tryAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - tryBlockAndAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - }; - - populateTransaction: { - aggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - blockAndAggregate( - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - getBlockHash( - blockNumber: BigNumberish, - overrides?: CallOverrides - ): Promise; - - getBlockNumber(overrides?: CallOverrides): Promise; - - getCurrentBlockCoinbase( - overrides?: CallOverrides - ): Promise; - - getCurrentBlockDifficulty( - overrides?: CallOverrides - ): Promise; - - getCurrentBlockGasLimit( - overrides?: CallOverrides - ): Promise; - - getCurrentBlockTimestamp( - overrides?: CallOverrides - ): Promise; - - getEthBalance( - addr: string, - overrides?: CallOverrides - ): Promise; - - getLastBlockHash(overrides?: CallOverrides): Promise; - - tryAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - - tryBlockAndAggregate( - requireSuccess: boolean, - calls: CallStruct[], - overrides?: Overrides & { from?: string | Promise } - ): Promise; - }; -} diff --git a/src/abis/common.ts b/src/abis/common.ts index d95ad5ca..903d55e2 100644 --- a/src/abis/common.ts +++ b/src/abis/common.ts @@ -1,45 +1,37 @@ /* Autogenerated file. Do not edit manually. */ /* tslint:disable */ /* eslint-disable */ -// @ts-nocheck -import type { Listener } from '@ethersproject/providers' -import type { Event, EventFilter } from 'ethers' -export interface TypedEvent< - TArgsArray extends Array = any, - TArgsObject = any -> extends Event { - args: TArgsArray & TArgsObject -} +import { EventFilter, Event } from 'ethers' +import { Result } from '@ethersproject/abi' -export interface TypedEventFilter<_TEvent extends TypedEvent> +export interface TypedEventFilter<_EventArgsArray, _EventArgsObject> extends EventFilter {} -export interface TypedListener { - (...listenerArg: [...__TypechainArgsArray, TEvent]): void +export interface TypedEvent extends Event { + args: EventArgs } -type __TypechainArgsArray = T extends TypedEvent ? U : never - -export interface OnEvent { - ( - eventFilter: TypedEventFilter, - listener: TypedListener - ): TRes - (eventName: string, listener: Listener): TRes -} +export type TypedListener< + EventArgsArray extends Array, + EventArgsObject +> = ( + ...listenerArg: [ + // @ts-ignore + ...EventArgsArray, + TypedEvent + ] +) => void export type MinEthersFactory = { deploy(...a: ARGS[]): Promise } - export type GetContractTypeFromFactory = F extends MinEthersFactory< infer C, any > ? C : never - export type GetARGsTypeFromFactory = F extends MinEthersFactory ? Parameters : never diff --git a/src/abis/multicall.json b/src/abis/multicall.json index 08a075de..44a55961 100644 --- a/src/abis/multicall.json +++ b/src/abis/multicall.json @@ -1,330 +1,330 @@ [ - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - } + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "aggregate", - "outputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "returnData", - "type": "bytes[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - } + "name": "aggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "returnData", + "type": "bytes[]" + } ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "blockAndAggregate", - "outputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "returnData", - "type": "bytes" - } + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } ], - "internalType": "struct Multicall2.Result[]", - "name": "returnData", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - } - ], - "name": "getBlockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "returnData", - "type": "bytes" - } + "name": "blockAndAggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } ], - "internalType": "struct Multicall2.Result[]", - "name": "returnData", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockCoinbase", - "outputs": [ - { - "internalType": "address", - "name": "coinbase", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockDifficulty", - "outputs": [ - { - "internalType": "uint256", - "name": "difficulty", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockGasLimit", - "outputs": [ - { - "internalType": "uint256", - "name": "gaslimit", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "getEthBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLastBlockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "requireSuccess", - "type": "bool" - }, - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - } + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "tryAggregate", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "returnData", - "type": "bytes" - } + "name": "getBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } ], - "internalType": "struct Multicall2.Result[]", - "name": "returnData", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "requireSuccess", - "type": "bool" - }, - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - } + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "tryBlockAndAggregate", - "outputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "returnData", - "type": "bytes" - } + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockCoinbase", + "outputs": [ + { + "internalType": "address", + "name": "coinbase", + "type": "address" + } ], - "internalType": "struct Multicall2.Result[]", - "name": "returnData", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockDifficulty", + "outputs": [ + { + "internalType": "uint256", + "name": "difficulty", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockGasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "gaslimit", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "getEthBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "requireSuccess", + "type": "bool" + }, + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryAggregate", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "requireSuccess", + "type": "bool" + }, + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryBlockAndAggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } ] diff --git a/src/abis/multicall2.json b/src/abis/multicall2.json deleted file mode 100644 index 76cadf4c..00000000 --- a/src/abis/multicall2.json +++ /dev/null @@ -1,165 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { "internalType": "address", "name": "target", "type": "address" }, - { "internalType": "bytes", "name": "callData", "type": "bytes" } - ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "aggregate", - "outputs": [ - { "internalType": "uint256", "name": "blockNumber", "type": "uint256" }, - { "internalType": "bytes[]", "name": "returnData", "type": "bytes[]" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { "internalType": "address", "name": "target", "type": "address" }, - { "internalType": "bytes", "name": "callData", "type": "bytes" } - ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "blockAndAggregate", - "outputs": [ - { "internalType": "uint256", "name": "blockNumber", "type": "uint256" }, - { "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }, - { - "components": [ - { "internalType": "bool", "name": "success", "type": "bool" }, - { "internalType": "bytes", "name": "returnData", "type": "bytes" } - ], - "internalType": "struct Multicall2.Result[]", - "name": "returnData", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [{ "internalType": "uint256", "name": "blockNumber", "type": "uint256" }], - "name": "getBlockHash", - "outputs": [{ "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBlockNumber", - "outputs": [{ "internalType": "uint256", "name": "blockNumber", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockCoinbase", - "outputs": [{ "internalType": "address", "name": "coinbase", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockDifficulty", - "outputs": [{ "internalType": "uint256", "name": "difficulty", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockGasLimit", - "outputs": [{ "internalType": "uint256", "name": "gaslimit", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentBlockTimestamp", - "outputs": [{ "internalType": "uint256", "name": "timestamp", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [{ "internalType": "address", "name": "addr", "type": "address" }], - "name": "getEthBalance", - "outputs": [{ "internalType": "uint256", "name": "balance", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLastBlockHash", - "outputs": [{ "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bool", "name": "requireSuccess", "type": "bool" }, - { - "components": [ - { "internalType": "address", "name": "target", "type": "address" }, - { "internalType": "bytes", "name": "callData", "type": "bytes" } - ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "tryAggregate", - "outputs": [ - { - "components": [ - { "internalType": "bool", "name": "success", "type": "bool" }, - { "internalType": "bytes", "name": "returnData", "type": "bytes" } - ], - "internalType": "struct Multicall2.Result[]", - "name": "returnData", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bool", "name": "requireSuccess", "type": "bool" }, - { - "components": [ - { "internalType": "address", "name": "target", "type": "address" }, - { "internalType": "bytes", "name": "callData", "type": "bytes" } - ], - "internalType": "struct Multicall2.Call[]", - "name": "calls", - "type": "tuple[]" - } - ], - "name": "tryBlockAndAggregate", - "outputs": [ - { "internalType": "uint256", "name": "blockNumber", "type": "uint256" }, - { "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }, - { - "components": [ - { "internalType": "bool", "name": "success", "type": "bool" }, - { "internalType": "bytes", "name": "returnData", "type": "bytes" } - ], - "internalType": "struct Multicall2.Result[]", - "name": "returnData", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/src/components/AuctionBlock.tsx b/src/components/AuctionBlock.tsx index b5317acf..389bbf77 100644 --- a/src/components/AuctionBlock.tsx +++ b/src/components/AuctionBlock.tsx @@ -74,7 +74,7 @@ const AuctionBlock = (auction: Props) => { const amountBN = BigNumber.from(amount) return formatNumber(parseWad(gebUtils.decimalShift(amountBN, -9)), 2) } - + // kickstart bid as in first bid when auction started const kickBidder = { bidder: _.get(auction, 'startedBy', ''), buyAmount: _.get(auction, 'buyInitialAmount', ''), diff --git a/src/connectors/NetworkConnector.ts b/src/connectors/NetworkConnector.ts index 1c87ff15..905fb37f 100644 --- a/src/connectors/NetworkConnector.ts +++ b/src/connectors/NetworkConnector.ts @@ -1,21 +1,6 @@ -// Copyright (C) 2020 Uniswap -// https://github.com/Uniswap/uniswap-interface - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -import { ConnectorUpdate } from '@web3-react/types' -import { AbstractConnector } from '@web3-react/abstract-connector' import invariant from 'tiny-invariant' +import { AbstractConnector } from '@web3-react/abstract-connector' +import { ConnectorUpdate } from 'web3-react-types' interface NetworkConnectorArguments { urls: { [chainId: number]: string } @@ -54,11 +39,19 @@ class MiniRpcProvider implements AsyncSendable { public readonly path: string public readonly batchWaitTimeMs: number + private readonly connector: NetworkConnector + private nextId = 1 private batchTimeoutId: ReturnType | null = null private batch: BatchItem[] = [] - constructor(chainId: number, url: string, batchWaitTimeMs?: number) { + constructor( + connector: NetworkConnector, + chainId: number, + url: string, + batchWaitTimeMs?: number + ) { + this.connector = connector this.chainId = chainId this.url = url const parsed = new URL(url) @@ -70,7 +63,26 @@ class MiniRpcProvider implements AsyncSendable { public readonly clearBatch = async () => { console.debug('Clearing batch', this.batch) - const batch = this.batch + let batch = this.batch + + batch = batch.filter((b) => { + if (b.request.method === 'wallet_switchEthereumChain') { + try { + this.connector.changeChainId( + parseInt( + (b.request.params as [{ chainId: string }])[0] + .chainId + ) + ) + b.resolve({ id: b.request.id }) + } catch (error) { + b.reject(error) + } + return false + } + return true + }) + this.batch = [] this.batchTimeoutId = null let response: Response @@ -124,26 +136,24 @@ class MiniRpcProvider implements AsyncSendable { reject, request: { method }, } = byKey[result.id] - if (resolve && reject) { - if ('error' in result) { - reject( - new RequestError( - result?.error?.message, - result?.error?.code, - result?.error?.data - ) + if ('error' in result) { + reject( + new RequestError( + result?.error?.message, + result?.error?.code, + result?.error?.data ) - } else if ('result' in result) { - resolve(result.result) - } else { - reject( - new RequestError( - `Received unexpected JSON-RPC response to ${method} request.`, - -32000, - result - ) + ) + } else if ('result' in result && resolve) { + resolve(result.result) + } else { + reject( + new RequestError( + `Received unexpected JSON-RPC response to ${method} request.`, + -32000, + result ) - } + ) } } } @@ -153,7 +163,7 @@ class MiniRpcProvider implements AsyncSendable { jsonrpc: '2.0' id: number | string | null method: string - params?: unknown[] | object + params?: unknown[] | Record }, callback: (error: any, response: any) => void ): void => { @@ -166,7 +176,7 @@ class MiniRpcProvider implements AsyncSendable { public readonly request = async ( method: string | { method: string; params: unknown[] }, - params?: unknown[] | object + params?: unknown[] | Record ): Promise => { if (typeof method !== 'string') { return this.request(method.method, method.params) @@ -206,11 +216,12 @@ export class NetworkConnector extends AbstractConnector { supportedChainIds: Object.keys(urls).map((k): number => Number(k)), }) - this.currentChainId = defaultChainId || Number(Object.keys(urls)[0]) + this.currentChainId = defaultChainId ?? Number(Object.keys(urls)[0]) this.providers = Object.keys(urls).reduce<{ [chainId: number]: MiniRpcProvider }>((accumulator, chainId) => { accumulator[Number(chainId)] = new MiniRpcProvider( + this, Number(chainId), urls[Number(chainId)] ) @@ -245,4 +256,21 @@ export class NetworkConnector extends AbstractConnector { public deactivate() { return } + + /** + * Meant to be called only by MiniRpcProvider + * @param chainId the new chain id + */ + public changeChainId(chainId: number) { + if (chainId in this.providers) { + this.currentChainId = chainId + this.emitUpdate({ + chainId, + account: null, + provider: this.providers[chainId], + }) + } else { + throw new Error(`Unsupported chain ID: ${chainId}`) + } + } } diff --git a/src/containers/Auctions/AuctionsList.tsx b/src/containers/Auctions/AuctionsList.tsx index 1e52fcd1..57119f42 100644 --- a/src/containers/Auctions/AuctionsList.tsx +++ b/src/containers/Auctions/AuctionsList.tsx @@ -21,10 +21,15 @@ const AuctionsList = ({ type }: Props) => { connectWalletModel: connectWalletState, } = useStoreState((state) => state) const { popupsModel: popupsActions } = useStoreActions((state) => state) + // internalbalance = user's RAI balance in the protocol + // protInternalBalance = user's FLX balance in the protocol const { internalBalance, protInternalBalance } = auctionsState const { proxyAddress } = connectWalletState + + // auctions list const auctions = useAuctions() + // handle clicking to claim const handleClick = (modalType: string) => { if (!account) { popupsActions.setIsConnectorsWalletOpen(true) diff --git a/src/containers/Earn/Incentives/index.tsx b/src/containers/Earn/Incentives/index.tsx index be18215e..8c2211a5 100644 --- a/src/containers/Earn/Incentives/index.tsx +++ b/src/containers/Earn/Incentives/index.tsx @@ -10,6 +10,7 @@ const Incentives = () => { const [isFetching, setIsFetching] = useState(true) const [error, setError] = useState('') + // fetching incentives rounds useEffect(() => { async function fetchIncentives() { try { diff --git a/src/containers/Earn/LiquidityPool/AddLiquidity.tsx b/src/containers/Earn/LiquidityPool/AddLiquidity.tsx deleted file mode 100644 index b4c12629..00000000 --- a/src/containers/Earn/LiquidityPool/AddLiquidity.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import React from 'react' -import { PlusCircle } from 'react-feather' -import styled from 'styled-components' -import Button from '../../../components/Button' -import DecimalInput from '../../../components/DecimalInput' -import useGeb from '../../../hooks/useGeb' -import { - useAddLiquidity, - useInputsHandlers, - useLiquidityInfo, -} from '../../../hooks/useLiquidityPool' -import { - ApprovalState, - useTokenApproval, -} from '../../../hooks/useTokenApproval' -import { formatNumber } from '../../../utils/helper' - -const AddLiquidity = () => { - const { - error, - balances: currencyBalances, - parsedAmounts, - } = useLiquidityInfo() - const geb = useGeb() - - const isValid = !error - - const { onEthInput, onRaiInput } = useInputsHandlers() - - const { addLiquidityCallback } = useAddLiquidity() - - const [depositApprovalState, approveDeposit] = useTokenApproval( - parsedAmounts.raiAmount, - 'coin', - geb?.contracts.uniswapV3TwoTrancheLiquidityManager.address - ) - - const ethValue = parsedAmounts.ethAmount - ? Number(parsedAmounts.ethAmount) > 0 - ? (formatNumber(parsedAmounts.ethAmount) as string) - : parsedAmounts.ethAmount - : '' - const raiValue = parsedAmounts.raiAmount - ? Number(parsedAmounts.raiAmount) > 0 - ? (formatNumber(parsedAmounts.raiAmount) as string) - : parsedAmounts.raiAmount - : '' - const liqBValue = - parsedAmounts && parsedAmounts.totalLiquidity - ? (formatNumber(parsedAmounts.totalLiquidity) as string) - : '0' - - const onEthMaxAmount = () => onEthInput(currencyBalances.eth.toString()) - const onRaiMaxAmount = () => onRaiInput(currencyBalances.rai.toString()) - - const handleAddLiquidity = async () => { - try { - await addLiquidityCallback() - onEthInput('') - onRaiInput('') - } catch (error) { - console.log(error) - } - } - - return ( - - - - - {`RAI (Available: ${formatNumber( - currencyBalances.rai.toString() - )})`} - - - - - - - - - - {`ETH (Available: ${formatNumber( - currencyBalances.eth.toString() - )})`} - - - - - - - {`Total Liquidity`} - {liqBValue} RAI/ETH - - - - - {isValid && - (depositApprovalState === ApprovalState.PENDING || - depositApprovalState === ApprovalState.NOT_APPROVED) ? ( - - ) : null} - - - - ) -} - -export default AddLiquidity - -const Container = styled.div`` -const InputLabel = styled.div` - line-height: 21px; - color: ${(props) => props.theme.colors.secondary}; - font-size: ${(props) => props.theme.font.small}; - letter-spacing: -0.09px; - margin-bottom: 8px; - text-transform: capitalize; - display: flex; - align-items: center; - img { - width: 23px; - margin-right: 5px; - } -` - -const InputContainer = styled.div`` - -const SeparatorIcon = styled.div` - display: flex; - justify-content: center; - margin: 20px 0; -` - -const Result = styled.div` - margin-top: 20px; - border-radius: ${(props) => props.theme.global.borderRadius}; - border: 1px solid ${(props) => props.theme.colors.border}; - background: ${(props) => props.theme.colors.foreground}; -` - -const Block = styled.div` - border-bottom: 1px solid; - padding: 16px 20px; - border-bottom: 1px solid ${(props) => props.theme.colors.border}; - &:last-child { - border-bottom: 0; - } -` - -const Item = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 8px; - &:last-child { - margin-bottom: 0; - } -` - -const Label = styled.div` - font-size: ${(props) => props.theme.font.small}; - color: ${(props) => props.theme.colors.secondary}; - letter-spacing: -0.09px; - line-height: 21px; -` - -const Value = styled.div` - font-size: ${(props) => props.theme.font.small}; - color: ${(props) => props.theme.colors.primary}; - letter-spacing: -0.09px; - line-height: 21px; - font-weight: 600; -` - -const BtnContainer = styled.div` - text-align: center; - margin-top: 20px; - display: flex; - align-items: center; - justify-content: space-between; -` diff --git a/src/containers/Earn/LiquidityPool/LiquidityManager.tsx b/src/containers/Earn/LiquidityPool/LiquidityManager.tsx deleted file mode 100644 index 8c1ac826..00000000 --- a/src/containers/Earn/LiquidityPool/LiquidityManager.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { useEffect, useState } from 'react' -import styled from 'styled-components' -import useGeb from '../../../hooks/useGeb' -import { useStoreActions } from '../../../store' -import AddLiquidity from './AddLiquidity' -import WithdrawLiquidity from './WithdrawLiquidity' - -const LiquidityManager = () => { - const [type, setType] = useState<'add' | 'withdraw'>('add') - const geb = useGeb() - const { earnModel: earnActions } = useStoreActions((state) => state) - - useEffect(() => { - if (!geb) return - earnActions.fetchPositionsAndThreshold(geb) - }, [earnActions, geb]) - return ( - - - setType('add')} - > - Add Liquidity - - setType('withdraw')} - > - Wihdraw - - - - {type === 'add' ? : } - - - ) -} - -export default LiquidityManager - -const Container = styled.div` - background: ${(props) => props.theme.colors.background}; - border-radius: ${(props) => props.theme.global.borderRadius}; - border: 1px solid ${(props) => props.theme.colors.border}; - width: 100%; - max-width: 430px; -` - -const Content = styled.div` - padding: 30px 25px; -` - -const Header = styled.div` - display: flex; - align-items: center; - border-bottom: 1px solid ${(props) => props.theme.colors.border}; - padding: 0px 20px 0; -` - -const Tab = styled.div` - color: ${(props) => props.theme.colors.secondary}; - position: relative; - padding: 20px 10px; - cursor: pointer; - &.active { - color: ${(props) => props.theme.colors.primary}; - :before { - content: ''; - height: 2px; - width: 100%; - bottom: 0; - left: 0; - position: absolute; - background: ${(props) => props.theme.colors.gradient}; - } - } -` diff --git a/src/containers/Earn/LiquidityPool/LiquidityStats.tsx b/src/containers/Earn/LiquidityPool/LiquidityStats.tsx deleted file mode 100644 index 33e52043..00000000 --- a/src/containers/Earn/LiquidityPool/LiquidityStats.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import { - useLiquidityInfo, - useTokensFromLiquidity, -} from '../../../hooks/useLiquidityPool' -import { formatNumber } from '../../../utils/helper' - -const LiquidityStats = () => { - const { balances: currencyBalances } = useLiquidityInfo() - - const myPosition = - currencyBalances && currencyBalances.totalLiquidity - ? formatNumber(currencyBalances.totalLiquidity) - : '0' - - const { eth: stakedETH, rai: stakedRAI } = useTokensFromLiquidity( - currencyBalances.totalLiquidity - ) - - return ( - - - - - - - - - - Flex Manager Shares - - - {`${myPosition} RAI/ETH`} - - - - - - {'My Stake'} - {`${ - stakedETH ? formatNumber(stakedETH) : '0' - } ETH + ${ - stakedRAI ? formatNumber(stakedRAI) : '0' - } RAI`} - - - - ) -} - -export default LiquidityStats - -const StatsGrid = styled.div` - margin-left: 30px; - max-width: 300px; - width: 100%; - ${({ theme }) => theme.mediaWidth.upToSmall` - margin-bottom:10px; - margin-left:0; - `} - ${({ theme }) => theme.mediaWidth.upToExtraSmall` - max-width: 100%; - `} -` - -const StatItem = styled.div` - :nth-child(2) { - margin: 40px 0; - ${({ theme }) => theme.mediaWidth.upToSmall` - margin: 5px 0; - `} - } -` -const StateInner = styled.div` - border-radius: ${(props) => props.theme.global.borderRadius}; - border: 1px solid ${(props) => props.theme.colors.border}; - background: ${(props) => props.theme.colors.background}; - text-align: center; - padding: 30px 20px; - text-align: left; - height: 100%; - position: relative; - ${({ theme }) => theme.mediaWidth.upToSmall` - padding: 20px; - `} -` -const Value = styled.div` - color: ${(props) => props.theme.colors.primary}; - font-size: ${(props) => props.theme.font.medium}; - line-height: 27px; - letter-spacing: -0.69px; - margin: 20px 0 0px; - display: flex; - align-items: center; - img { - width: 40px; - } - ${({ theme }) => theme.mediaWidth.upToSmall` - font-size: ${(props) => props.theme.font.default}; - margin-top:10px; - `} - >div { - button { - max-width: 200px; - padding: 15px 20px !important; - } - } - > div div { - font-size: ${(props) => props.theme.font.default}; - font-weight: normal; - } -` -const Label = styled.div` - font-size: ${(props) => props.theme.font.small}; - line-height: 21px; - letter-spacing: -0.09px; - - &.top { - display: flex; - justify-content: space-between; - align-items: center; - font-weight: bold; - color: ${(props) => props.theme.colors.secondary}; - } - &.small { - font-size: ${(props) => props.theme.font.extraSmall}; - color: ${(props) => props.theme.colors.secondary}; - margin-top: 10px; - b { - color: ${(props) => props.theme.colors.primary}; - } - a { - color: inherit; - filter: grayscale(100%); - - &:hover { - background: ${(props) => props.theme.colors.gradient}; - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - color: ${(props) => props.theme.colors.inputBorderColor}; - filter: grayscale(0%); - } - } - } - ${({ theme }) => theme.mediaWidth.upToSmall` - font-size: ${(props) => props.theme.font.extraSmall}; - `} -` - -const Position = styled.div` - display: flex; - align-items: center; -` - -const Images = styled.div` - display: flex; - align-items: center; - margin-right: 5px; - img { - width: 23px; - &:nth-child(2) { - margin-left: -10px; - } - } -` diff --git a/src/containers/Earn/LiquidityPool/WithdrawLiquidity.tsx b/src/containers/Earn/LiquidityPool/WithdrawLiquidity.tsx deleted file mode 100644 index ccf590f6..00000000 --- a/src/containers/Earn/LiquidityPool/WithdrawLiquidity.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import Button from '../../../components/Button' -import DecimalInput from '../../../components/DecimalInput' -import useGeb from '../../../hooks/useGeb' -import { - useInputsHandlers, - useLiquidityInfo, - useWithdrawLiquidity, -} from '../../../hooks/useLiquidityPool' -import { - ApprovalState, - useTokenApproval, -} from '../../../hooks/useTokenApproval' -import { formatNumber } from '../../../utils/helper' - -const WithdrawLiquidity = () => { - const { - balances: currencyBalances, - error, - parsedAmounts, - tokensStake, - } = useLiquidityInfo(false) - const geb = useGeb() - - const isValid = !error - - const { onLiquidityInput, onEthInput, onRaiInput } = useInputsHandlers() - - const { withdrawLiquidityCallback } = useWithdrawLiquidity() - - const [withdrawApprovalState, approve] = useTokenApproval( - parsedAmounts.totalLiquidity, - 'uniswapV3TwoTrancheLiquidityManager', - geb?.contracts.uniswapV3TwoTrancheLiquidityManager.address - ) - - const onLiquidityMaxInput = () => - onLiquidityInput(currencyBalances.totalLiquidity.toString()) - - const liqBValue = parsedAmounts.totalLiquidity - ? Number(parsedAmounts.totalLiquidity) > 0 && - parsedAmounts.totalLiquidity.length > 10 - ? (formatNumber(parsedAmounts.totalLiquidity) as string) - : parsedAmounts.totalLiquidity - : '' - - const handleWithdrawLiquidity = async () => { - try { - await withdrawLiquidityCallback() - onEthInput('') - onRaiInput('') - onLiquidityInput('') - } catch (error) { - console.log(error) - } - } - - return ( - - - - - - - - {`Flex Manager Shares (Available: ${formatNumber( - currencyBalances.totalLiquidity.toString() - )})`} - - - - - - - {`ETH to Receive`} - {`${ - tokensStake.eth - ? formatNumber(tokensStake.eth) - : '0' - } ETH`} - - - - {`RAI to Receive`} - {`${ - tokensStake.rai - ? formatNumber(tokensStake.rai) - : '0' - } RAI`} - - - - {`Total Liquidity`} - {liqBValue} RAI/ETH - - - - - - - {isValid && - (withdrawApprovalState === ApprovalState.PENDING || - withdrawApprovalState === ApprovalState.NOT_APPROVED) ? ( - - ) : null} - - - ) -} - -export default WithdrawLiquidity - -const Container = styled.div`` -const InputLabel = styled.div` - line-height: 21px; - color: ${(props) => props.theme.colors.secondary}; - font-size: ${(props) => props.theme.font.small}; - letter-spacing: -0.09px; - margin-bottom: 8px; - text-transform: capitalize; - display: flex; - align-items: center; - img { - width: 23px; - margin-right: 5px; - } -` - -const InputContainer = styled.div`` - -const Result = styled.div` - margin-top: 20px; - border-radius: ${(props) => props.theme.global.borderRadius}; - border: 1px solid ${(props) => props.theme.colors.border}; - background: ${(props) => props.theme.colors.foreground}; -` - -const Block = styled.div` - border-bottom: 1px solid; - padding: 16px 20px; - border-bottom: 1px solid ${(props) => props.theme.colors.border}; - &:last-child { - border-bottom: 0; - } -` - -const Item = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 8px; - &:last-child { - margin-bottom: 0; - } -` - -const Label = styled.div` - font-size: ${(props) => props.theme.font.small}; - color: ${(props) => props.theme.colors.secondary}; - letter-spacing: -0.09px; - line-height: 21px; -` - -const Value = styled.div` - font-size: ${(props) => props.theme.font.small}; - color: ${(props) => props.theme.colors.primary}; - letter-spacing: -0.09px; - line-height: 21px; - font-weight: 600; -` - -const BtnContainer = styled.div` - text-align: center; - margin-top: 20px; - display: flex; - align-items: center; - justify-content: space-between; -` - -const Images = styled.div` - display: flex; - align-items: center; - margin-right: 5px; - img { - width: 23px; - &:nth-child(2) { - margin-left: -10px; - } - } -` diff --git a/src/containers/Earn/LiquidityPool/index.tsx b/src/containers/Earn/LiquidityPool/index.tsx deleted file mode 100644 index d78ca1f5..00000000 --- a/src/containers/Earn/LiquidityPool/index.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React from 'react' -import { useTranslation } from 'react-i18next' -import styled from 'styled-components' -import GridContainer from '../../../components/GridContainer' -import PageHeader from '../../../components/PageHeader' -import LiquidityManager from './LiquidityManager' -import LiquidityStats from './LiquidityStats' - -const LiquidityPool = () => { - const { t } = useTranslation() - return ( - - - - - {t('lp_title')} - {t('lp_description')} - - - - - - - - - ) -} - -export default LiquidityPool - -const Container = styled.div`` -const Details = styled.div` - background: ${(props) => props.theme.colors.background}; - border: 1px solid ${(props) => props.theme.colors.border}; - border-radius: ${(props) => props.theme.global.borderRadius}; - padding: 30px; -` - -const Title = styled.div` - font-size: 18px; - line-height: 22px; - letter-spacing: -0.33px; - color: ${(props) => props.theme.colors.primary}; - font-weight: bold; -` -const Description = styled.div` - margin-top: 10px; - font-size: 14px; - color: ${(props) => props.theme.colors.secondary}; - line-height: 22px; -` - -const Content = styled.div` - display: flex; - align-items: center; - justify-content: center; - margin: 30px 0; - ${({ theme }) => theme.mediaWidth.upToSmall` - - flex-direction:column-reverse; - - `} -` diff --git a/src/containers/Earn/MoneyGodLeague/Stake.tsx b/src/containers/Earn/MoneyGodLeague/Stake.tsx deleted file mode 100644 index 6951499e..00000000 --- a/src/containers/Earn/MoneyGodLeague/Stake.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import Button from '../../../components/Button' -import TokenInput from '../../../components/TokenInput' -import { - useFarmingInfo, - useInputsHandlers, - useAddStaking, -} from '../../../hooks/useFarming' -import { - ApprovalState, - useTokenApproval, -} from '../../../hooks/useTokenApproval' -import { formatNumber } from '../../../utils/helper' - -const Stake = () => { - const { stakingToken, farmerData, parsedAmount, error } = useFarmingInfo() - const { onTypedValue } = useInputsHandlers() - const { addStakingCallback } = useAddStaking() - - const isValid = !error - - const [depositApprovalState, approveDeposit] = useTokenApproval( - parsedAmount, - stakingToken?.address ?? undefined, - farmerData.contractAddress ?? undefined - ) - - const stakingValue = parsedAmount - ? Number(parsedAmount) > 0 && - parsedAmount.includes('.') && - parsedAmount.split('.')[1].length > 5 - ? (formatNumber(parsedAmount) as string) - : parsedAmount - : '' - - const handleMaxInput = () => onTypedValue(stakingToken?.balance ?? '') - - const handleAddStaking = async () => { - try { - await addStakingCallback() - onTypedValue('') - } catch (error) { - console.log(error) - } - } - - return ( - <> - - Deposit {stakingToken?.name} - - - - - > - ) -} - -export default Stake - -const Body = styled.div` - padding: 30px 20px 20px; -` -const SideLabel = styled.div` - font-weight: 600; - font-size: ${(props) => props.theme.font.default}; - margin-bottom: 10px; -` - -const Footer = styled.div` - padding: 20px; -` - -const BtnContainer = styled.div` - text-align: center; - margin-top: 20px; - display: flex; - align-items: center; - justify-content: space-between; -` diff --git a/src/containers/Earn/MoneyGodLeague/StakingManager.tsx b/src/containers/Earn/MoneyGodLeague/StakingManager.tsx deleted file mode 100644 index f9639fa2..00000000 --- a/src/containers/Earn/MoneyGodLeague/StakingManager.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React, { useState } from 'react' -import styled from 'styled-components' -import Stake from './Stake' -import UnStake from './UnStake' - -const StakingManager = () => { - const [type, setType] = useState<'stake' | 'unstake'>('stake') - - return ( - - - setType('stake')} - > - Deposit - - setType('unstake')} - > - Withdraw - - - {type === 'unstake' ? : } - - ) -} - -export default StakingManager - -const StakingPayment = styled.div` - background: ${(props) => props.theme.colors.placeholder}; - border-radius: 15px; - flex: 1; - margin-right: 20px; - ${({ theme }) => theme.mediaWidth.upToSmall` - margin-right:0 - `} -` - -const Header = styled.div` - display: flex; - align-items: center; - border-bottom: 1px solid ${(props) => props.theme.colors.border}; - padding: 0px 20px 0; -` - -const Tab = styled.div` - color: ${(props) => props.theme.colors.secondary}; - position: relative; - padding: 20px 10px; - cursor: pointer; - &.active { - color: ${(props) => props.theme.colors.primary}; - :before { - content: ''; - height: 2px; - width: 100%; - bottom: 0; - left: 0; - position: absolute; - background: ${(props) => props.theme.colors.gradient}; - } - } -` diff --git a/src/containers/Earn/MoneyGodLeague/Statistics.tsx b/src/containers/Earn/MoneyGodLeague/Statistics.tsx deleted file mode 100644 index f7cc3168..00000000 --- a/src/containers/Earn/MoneyGodLeague/Statistics.tsx +++ /dev/null @@ -1,244 +0,0 @@ -import React, { useMemo } from 'react' -import styled from 'styled-components' -import numeral from 'numeral' -import Button from '../../../components/Button' -import { useActiveWeb3React } from '../../../hooks' -import { formatNumber } from '../../../utils/helper' -import { useFarmingInfo, useClaimReward } from '../../../hooks/useFarming' -import commaNumber from 'comma-number' - -const returnImg = (img: string, width = '20px', height = '20px') => { - return -} - -type StatsType = 'data' | 'info' -type Stats = { - [K in StatsType]: Array<{ - label: string - value: string | number - img?: string - }> -} -const Statistics = () => { - const { account } = useActiveWeb3React() - const { - poolData, - stakingToken, - farmerData: { rewardToken }, - } = useFarmingInfo() - const { claimRewardCallback } = useClaimReward() - const { poolBalance, stakedBalance, weeklyReward, apr, myCurrentReward } = - poolData - - const myWeeklyReward = useMemo(() => { - return (Number(stakedBalance) / Number(poolBalance)) * weeklyReward - }, [poolBalance, weeklyReward, stakedBalance]) - - const handleClaimReward = async () => { - try { - await claimRewardCallback() - } catch (error) { - console.log(error) - } - } - - const stats: Stats = { - data: [ - { - label: 'Total Pool Balance', - value: `${ - Number(poolBalance) > 0 - ? numeral(formatNumber(poolBalance)).format('0.0') - : '0' - } ${stakingToken.name}`, - }, - { - label: 'APR', - value: `${ - Number(apr) > 0 - ? commaNumber( - numeral(formatNumber(apr.toString(), 2)).format( - '0.0' - ) - ) - : '0' - }%`, - }, - { - label: 'Weekly Rewards', - value: formatNumber(weeklyReward.toString(), 2), - img: rewardToken.icon, - }, - ], - - info: [ - { - label: 'Deposited Balance', - value: stakedBalance, - img: stakingToken.icon, - }, - { - label: 'Accrued Rewards', - value: - Number(myCurrentReward) === 0 || !account - ? '0' - : Number(myWeeklyReward) > 0 - ? formatNumber(myWeeklyReward.toString()) - : '0', - img: rewardToken.icon, - }, - ], - } - - return ( - - - - {Object.keys(stats).map((key) => { - const isPrimary = key === 'data' - return ( - - {stats[key as StatsType].map((item) => { - return ( - - - {item.label} - - - {item.img - ? returnImg(item.img) - : null}{' '} - {item.value} - - - ) - })} - - ) - })} - - - - Claimable Rewards - - {Number(myCurrentReward) > 0 - ? Number(myCurrentReward) >= 0.0001 - ? formatNumber(myCurrentReward) - : '< 0.0001' - : '0'}{' '} - {returnImg(rewardToken.icon)} - - - - - - - - ) -} - -export default Statistics - -const Flex = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - margin: 13px 0; -` - -const Stats = styled.div` - padding: 20px; - border-radius: 10px; - background: ${(props) => props.theme.colors.placeholder}; - .blockie { - border-bottom: 1px solid ${(props) => props.theme.colors.border}; - &:last-child { - border: 0; - } - } - @media (max-width: 767px) { - margin-top: 20px; - } -` -const Container = styled.div` - flex: 1; - ${({ theme }) => theme.mediaWidth.upToSmall` - margin-bottom:20px; - `} -` - -const Content = styled.div` - display: flex; - flex-direction: column; - height: calc(100% - 61px); - justify-content: space-between; -` - -const StatsFooter = styled.div` - padding: 20px; - border-radius: 0 0 15px 15px; - background: ${(props) => props.theme.colors.background}; - button { - margin-top: 15px; - width: 100%; - } -` - -const RewardBox = styled.div` - display: flex; - align-items: center; - justify-content: space-between; -` - -const RewardValue = styled.div` - display: flex; - align-items: center; - font-size: 15px; - img { - margin-left: 5px; - } - span { - display: inline-block; - margin: 0 5px; - } -` -const RewardLabel = styled.div` - color: ${(props) => props.theme.colors.secondary}; - font-size: 14px; - ${({ theme }) => theme.mediaWidth.upToSmall` - font-size: 14px; - margin-top:0; - `} -` - -const Label = styled.div<{ color?: 'primary' | 'secondary' }>` - font-size: ${(props) => props.theme.font.small}; - color: ${({ theme, color }) => - color ? theme.colors[color] : theme.colors.primary}; - display: flex; - align-items: center; - svg { - margin-right: 5px; - } -` - -const Value = styled.div` - font-size: ${(props) => props.theme.font.small}; - color: ${(props) => props.theme.colors.primary}; - display: flex; - align-items: center; - img { - margin-right: 5px; - max-width: 20px; - } -` diff --git a/src/containers/Earn/MoneyGodLeague/UnStake.tsx b/src/containers/Earn/MoneyGodLeague/UnStake.tsx deleted file mode 100644 index 08742660..00000000 --- a/src/containers/Earn/MoneyGodLeague/UnStake.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react' -import styled from 'styled-components' -import Button from '../../../components/Button' -import TokenInput from '../../../components/TokenInput' -import { - useFarmingInfo, - useInputsHandlers, - useUnstake, -} from '../../../hooks/useFarming' -import { formatNumber } from '../../../utils/helper' - -const UnStake = () => { - const { stakingToken, poolData, parsedAmount, error } = - useFarmingInfo(false) - const { onTypedValue } = useInputsHandlers() - const { unStakeCallback } = useUnstake() - - const isValid = !error - - const value = parsedAmount - ? Number(parsedAmount) > 0 && - parsedAmount.includes('.') && - parsedAmount.split('.')[1].length > 5 - ? (formatNumber(parsedAmount) as string) - : parsedAmount - : '' - - const handleMaxInput = () => onTypedValue(poolData.stakedBalance) - - const handleUnstaking = async () => { - try { - await unStakeCallback() - onTypedValue('') - } catch (error) { - console.log(error) - } - } - - return ( - <> - - Withdraw {stakingToken?.name} - - - - - > - ) -} - -export default UnStake - -const Body = styled.div` - padding: 30px 20px 20px; -` -const SideLabel = styled.div` - font-weight: 600; - font-size: ${(props) => props.theme.font.default}; - margin-bottom: 10px; -` - -const Footer = styled.div` - padding: 20px; -` - -const BtnContainer = styled.div` - text-align: center; - margin-top: 20px; - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; -` diff --git a/src/containers/Earn/MoneyGodLeague/index.tsx b/src/containers/Earn/MoneyGodLeague/index.tsx deleted file mode 100644 index 230f0a2a..00000000 --- a/src/containers/Earn/MoneyGodLeague/index.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import React, { useMemo } from 'react' -import styled from 'styled-components' -import StakingManager from './StakingManager' -import Statistics from './Statistics' -import { BarChart2 } from 'react-feather' -import Dropdown from '../../../components/Dropdown' -import { useFarmingInfo } from '../../../hooks/useFarming' -import { - contractsArray, - CONTRACT_NAME, - farmersArray, - FARMER_NAME, -} from '../../../model/earnModel' -import { TokenName, TOKENS } from '../../../utils/tokens' -import { useStoreActions } from '../../../store' -import { useTranslation } from 'react-i18next' - -const projectImgs = { - volt: require('../../../assets/vcon.svg'), - h2o: require('../../../assets/aqua.svg'), -} - -const MoneyGodLeague = () => { - const { t } = useTranslation() - const { earnModel: earnActions } = useStoreActions((state) => state) - const { farmerName, contractName } = useFarmingInfo() - - const farmers = farmersArray.map((name) => ({ - item: name.toUpperCase(), - img: projectImgs[name], - })) - - const selectedFarmer = useMemo(() => { - return { - item: farmerName.toUpperCase(), - img: projectImgs[farmerName], - } - }, [farmerName]) - - const tokens = contractsArray.map((name) => ({ - item: TOKENS[name as TokenName].name, - img: TOKENS[name as TokenName].icon, - name, - })) - - const selectedToken = useMemo(() => { - return { - item: TOKENS[contractName as TokenName].name, - img: TOKENS[contractName as TokenName].icon, - name: contractName, - } - }, [contractName]) - - const handleSelectedProject = (selected: string) => { - earnActions.setFarmerName(selected.toLowerCase() as FARMER_NAME) - } - - const handleSelectedToken = (selected: string) => { - const key = Object.keys(TOKENS).find((key) => - TOKENS[key as TokenName].name === selected ? key : undefined - ) - earnActions.setContractName(key as CONTRACT_NAME) - } - - return ( - - - Money God League - - - - - - What is Money God League? - - {t('moneygod_desc')} - - - - - - - {`Select Project`} - - - - - {`Select Token`} - - - - - - - - - - - ) -} - -export default MoneyGodLeague - -const Container = styled.div` - max-width: 880px; - margin: 80px auto; - padding: 0 15px; - @media (max-width: 767px) { - margin: 50px auto; - } -` - -const Ops = styled.div` - display: flex; - align-items: stretch; - - ${({ theme }) => theme.mediaWidth.upToSmall` - flex-direction:column-reverse; - `} -` - -const Title = styled.div` - font-size: 18px; - line-height: 22px; - letter-spacing: -0.33px; - color: ${(props) => props.theme.colors.primary}; - font-weight: bold; -` - -const Content = styled.div` - padding: 20px; - border-radius: 15px; - background: ${(props) => props.theme.colors.colorSecondary}; -` - -const Header = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - img { - width: 40px; - margin-right: 5px; - } - font-weight: bold; - font-size: 18px; - margin-bottom: 20px; -` - -const InfoBox = styled.div` - display: flex; - justify-content: space-between; - margin-bottom: 20px; - margin-top: 20px; - @media (max-width: 767px) { - display: none; - } -` - -const LeftSide = styled.div` - flex: 0 0 100%; - background: url(${require('../../../assets/blueish-bg.png')}); - background-repeat: no-repeat; - background-size: cover; - padding: 20px; - border-radius: 15px; -` - -const InfoTitle = styled.div` - display: flex; - align-items: center; - font-size: ${(props) => props.theme.font.default}; - font-weight: 600; - svg { - margin-right: 5px; - } -` - -const InfoText = styled.div` - font-size: ${(props) => props.theme.font.small}; - margin-top: 10px; - a { - color: ${(props) => props.theme.colors.blueish}; - text-decoration: underline; - } - &.bigFont { - font-size: ${(props) => props.theme.font.default}; - } -` - -const SideLabel = styled.div` - font-weight: 600; - font-size: ${(props) => props.theme.font.default}; - margin-bottom: 10px; -` - -const StakingSelection = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - @media (max-width: 767px) { - flex-direction: column; - } -` - -const DropDownContainer = styled.div` - flex: 0 0 49%; - margin-bottom: 20px; -` diff --git a/src/containers/Earn/Staking/Stake.tsx b/src/containers/Earn/Staking/Stake.tsx index 74d6caf1..44490519 100644 --- a/src/containers/Earn/Staking/Stake.tsx +++ b/src/containers/Earn/Staking/Stake.tsx @@ -22,7 +22,7 @@ const Stake = () => { const { addStakingCallback } = useAddStaking() const isValid = !error - + // approving staking contract const [depositApprovalState, approveDeposit] = useTokenApproval( parsedAmounts.stakingAmount, geb?.contracts.stakingToken.address, diff --git a/src/containers/Earn/Staking/index.tsx b/src/containers/Earn/Staking/index.tsx index 691064c3..e8017299 100644 --- a/src/containers/Earn/Staking/index.tsx +++ b/src/containers/Earn/Staking/index.tsx @@ -15,6 +15,8 @@ dayjs.extend(relativeTime) const Staking = () => { const { t } = useTranslation() + + // how long before user can withdraw staking balance const { exitDelay } = useStakingInfo() return ( diff --git a/src/containers/Earn/index.tsx b/src/containers/Earn/index.tsx deleted file mode 100644 index a70d190f..00000000 --- a/src/containers/Earn/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const Earn = () => { - return Earn -} - -export default Earn diff --git a/src/containers/OnBoarding/Accounts.tsx b/src/containers/Safes/Accounts.tsx similarity index 100% rename from src/containers/OnBoarding/Accounts.tsx rename to src/containers/Safes/Accounts.tsx diff --git a/src/containers/OnBoarding/CreateSafe.tsx b/src/containers/Safes/CreateSafe.tsx similarity index 100% rename from src/containers/OnBoarding/CreateSafe.tsx rename to src/containers/Safes/CreateSafe.tsx diff --git a/src/containers/OnBoarding/ModifySafe.tsx b/src/containers/Safes/ModifySafe.tsx similarity index 100% rename from src/containers/OnBoarding/ModifySafe.tsx rename to src/containers/Safes/ModifySafe.tsx diff --git a/src/containers/OnBoarding/Review.tsx b/src/containers/Safes/Review.tsx similarity index 100% rename from src/containers/OnBoarding/Review.tsx rename to src/containers/Safes/Review.tsx diff --git a/src/containers/OnBoarding/SafeDetails.tsx b/src/containers/Safes/SafeDetails.tsx similarity index 100% rename from src/containers/OnBoarding/SafeDetails.tsx rename to src/containers/Safes/SafeDetails.tsx diff --git a/src/containers/OnBoarding/SafeHeader.tsx b/src/containers/Safes/SafeHeader.tsx similarity index 100% rename from src/containers/OnBoarding/SafeHeader.tsx rename to src/containers/Safes/SafeHeader.tsx diff --git a/src/containers/OnBoarding/SafeList.tsx b/src/containers/Safes/SafeList.tsx similarity index 100% rename from src/containers/OnBoarding/SafeList.tsx rename to src/containers/Safes/SafeList.tsx diff --git a/src/containers/OnBoarding/Saviour/Review.tsx b/src/containers/Safes/Saviour/Review.tsx similarity index 100% rename from src/containers/OnBoarding/Saviour/Review.tsx rename to src/containers/Safes/Saviour/Review.tsx diff --git a/src/containers/OnBoarding/Saviour/SafeSaviour.tsx b/src/containers/Safes/Saviour/SafeSaviour.tsx similarity index 100% rename from src/containers/OnBoarding/Saviour/SafeSaviour.tsx rename to src/containers/Safes/Saviour/SafeSaviour.tsx diff --git a/src/containers/OnBoarding/Saviour/SaviourHeader.tsx b/src/containers/Safes/Saviour/SaviourHeader.tsx similarity index 100% rename from src/containers/OnBoarding/Saviour/SaviourHeader.tsx rename to src/containers/Safes/Saviour/SaviourHeader.tsx diff --git a/src/containers/OnBoarding/Saviour/SaviourOps.tsx b/src/containers/Safes/Saviour/SaviourOps.tsx similarity index 100% rename from src/containers/OnBoarding/Saviour/SaviourOps.tsx rename to src/containers/Safes/Saviour/SaviourOps.tsx diff --git a/src/containers/OnBoarding/Saviour/SaviourStats.tsx b/src/containers/Safes/Saviour/SaviourStats.tsx similarity index 100% rename from src/containers/OnBoarding/Saviour/SaviourStats.tsx rename to src/containers/Safes/Saviour/SaviourStats.tsx diff --git a/src/containers/OnBoarding/index.tsx b/src/containers/Safes/index.tsx similarity index 100% rename from src/containers/OnBoarding/index.tsx rename to src/containers/Safes/index.tsx diff --git a/src/hooks/TransactionHooks.tsx b/src/hooks/TransactionHooks.tsx index 690d5b68..79a60446 100644 --- a/src/hooks/TransactionHooks.tsx +++ b/src/hooks/TransactionHooks.tsx @@ -11,6 +11,7 @@ import { ITransaction } from '../utils/interfaces' import { BigNumber } from 'ethers' import { newTransactionsFirst } from '../utils/helper' +// adding transaction to store export function useTransactionAdder(): ( response: TransactionResponse, summary?: string, @@ -64,6 +65,8 @@ export function useIsTransactionPending(transactionHash?: string): boolean { return !transactions[transactionHash].receipt } +// handking transactions gas limit as well as error messages + export async function handlePreTxGasEstimate( signer: JsonRpcSigner, tx: TransactionRequest, diff --git a/src/hooks/useAuctions.ts b/src/hooks/useAuctions.ts index f5859898..8c69c61d 100644 --- a/src/hooks/useAuctions.ts +++ b/src/hooks/useAuctions.ts @@ -3,6 +3,7 @@ import { useStoreState } from '../store' import { IAuction } from '../utils/interfaces' import _ from '../utils/lodash' +// list auctions data export default function useAuctions() { const [state, setState] = useState>() const { @@ -15,6 +16,7 @@ export default function useAuctions() { useEffect(() => { const oneMonthOld = new Date().setMonth(new Date().getMonth() - 1) + // show auctions less than one month old only const filteredAuctions = autctionsData .filter((auction: IAuction) => { return ( diff --git a/src/hooks/useBlocksConfirmations.tsx b/src/hooks/useBlocksConfirmations.tsx index 5257de45..0ed5e474 100644 --- a/src/hooks/useBlocksConfirmations.tsx +++ b/src/hooks/useBlocksConfirmations.tsx @@ -4,6 +4,7 @@ import { useStoreActions, useStoreState } from '../store' import { timeout } from '../utils/helper' import useGeb from './useGeb' +// handle await for 10 blocks confirmation before creating a reflexer account export function use10BlocksConfirmations() { const [blocksSinceCheck, setBlocksSinceCheck] = useState() const { account, chainId } = useActiveWeb3React() diff --git a/src/hooks/useContract.ts b/src/hooks/useContract.ts index cd5ca7e1..78e621fc 100644 --- a/src/hooks/useContract.ts +++ b/src/hooks/useContract.ts @@ -1,11 +1,11 @@ import { Contract } from '@ethersproject/contracts' import { useMemo } from 'react' import { useActiveWeb3React } from '.' -import { Multicall2 } from '../abis/Multicall2' +import { Multicall } from '../abis/Multicall' import { Erc20 } from '../abis/Erc20' import ERC20_ABI from '../abis/erc20.json' import ERC20_BYTES32_ABI from '../abis/erc20_bytes32.json' -import MULTICALL_ABI from '../abis/multicall2.json' +import MULTICALL_ABI from '../abis/multicall.json' import { EMPTY_ADDRESS, MULTICALL2_ADDRESSES } from '../utils/constants' import { isAddress } from '../utils/helper' import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers' @@ -95,9 +95,9 @@ export function useBytes32TokenContract( } export function useMulticall2Contract() { - return useContract( + return useContract( MULTICALL2_ADDRESSES, MULTICALL_ABI, false - ) as Multicall2 + ) as Multicall } diff --git a/src/hooks/useFarming.ts b/src/hooks/useFarming.ts deleted file mode 100644 index 06d390fe..00000000 --- a/src/hooks/useFarming.ts +++ /dev/null @@ -1,498 +0,0 @@ -import { BigNumber, ethers } from 'ethers' -import { getAddress } from '@ethersproject/address' -import SimpleStakingContract from '../abis/SimpleStakingContract.json' -import { useCallback, useEffect, useMemo, useState } from 'react' -import { useActiveWeb3React } from '.' -import store, { useStoreActions, useStoreState } from '../store' -import { - handlePreTxGasEstimate, - handleTransactionError, -} from './TransactionHooks' -import { useContract } from './useContract' -import useGeb, { useProxyAddress } from './useGeb' -import { useTokenBalances } from './Wallet' -import { useSingleCallResult } from './Multicall' -import { CONTRACT_NAME } from 'src/model/earnModel' -import { TokenName } from '../utils/tokens' -import { isAddress } from '../utils/helper' -import { contracts } from 'geb.js' -import { Interface } from 'ethers/lib/utils' -import ERC20ABI from '../abis/erc20.json' - -const REWARD_TOKEN_PRICE = 5 - -export const FARMERS = { - volt: { - stakingContracts: { - flx: '0xb93d828388e87Da9c39281D2C5f91DD499C8a43D', - flx_lp: '0x1CdF5A8093Cd177a8dF63C046e04bbe91791254c', - }, - farmerTokens: ['flx lp', 'flx'], - rewardToken: 'vcon', - }, - h2o: { - stakingContracts: { - flx: '0xD9bf979763075EBC65Bb88b69a851937e3d59B96', - flx_lp: '0x75f993e6297fb4ABd71beb5DB067248729B2d915', - }, - farmerTokens: ['flx lp', 'flx'], - rewardToken: 'aqua', - }, -} - -const DEFAULT_STATE = { - stFlxAmount: '', - stakingAmount: '', -} - -export const BLOCK_INTERVAL = 13 - -// helpers -export function useFarmingInfo(isDeposit = true) { - const { account } = useActiveWeb3React() - const proxyAddress = useProxyAddress() - - const { earnModel: earnState } = useStoreState((state) => state) - const { amount, contractName, farmerName } = earnState - const parsedAmount = useMemo(() => amount, [amount]) - - const farmerData = useFarmerData() - - const stakingToken = farmerData.tokens[contractName as TokenName] - - const poolData = usePoolData() - - let error: string | undefined - if (!account) { - error = 'Connect Wallet' - } - - if (!proxyAddress) { - error = error ?? 'Create a Reflexer Account to continue' - } - - if (!parsedAmount || Number(parsedAmount) <= 0) { - error = error ?? 'Enter an amount' - } - - if (isDeposit) { - if ( - stakingToken && - stakingToken.balance && - parsedAmount && - ethers.utils - .parseEther(stakingToken.balance.toString()) - .lt(ethers.utils.parseEther(parsedAmount.toString())) - ) { - error = error ?? `Insufficient ${stakingToken.name} balance` - } - } else { - if (!poolData.stakedBalance || Number(poolData.stakedBalance) <= 0) { - error = error ?? 'Enter an amount' - } - - if ( - parsedAmount && - Number(parsedAmount) >= 0 && - poolData.stakedBalance && - ethers.utils - .parseEther(poolData.stakedBalance) - .lt(ethers.utils.parseEther(parsedAmount.toString())) - ) { - error = error ?? `Insufficient st${stakingToken.name} balance` - } - } - - return { - farmerData, - parsedAmount, - contractName, - farmerName, - error, - stakingToken, - poolData, - } -} - -export function useFarmerData() { - const { account } = useActiveWeb3React() - const { earnModel: earnState, connectWalletModel: connectWalletState } = - useStoreState((state) => state) - const { farmerName, contractName } = earnState - const { flxPrice } = connectWalletState - const tokensList = useTokenBalances(account as string) - const tokens = useMemo(() => tokensList, [tokensList]) - const farmer = useMemo(() => FARMERS[farmerName], [farmerName]) - - return useMemo(() => { - return { - contractAddress: - farmer.stakingContracts[contractName as CONTRACT_NAME], - rewardToken: tokens[farmer.rewardToken as TokenName], - stakingToken: tokens[contractName as TokenName], - tokens, - contractName, - flxPrice, - } - }, [contractName, farmer, tokens, flxPrice]) -} - -export function useUniswapPairCoinEthPrice() { - const geb = useGeb() - const [state, setState] = useState(0) - - const resevesCallback = useCallback( - ([reserves]) => { - if (!reserves) return - let flxReserve - if ( - BigNumber.from(geb.contracts.protocolToken.address).gt( - BigNumber.from(geb.contracts.weth.address) - ) - ) { - // FLX is token 1 - flxReserve = ethers.utils.formatEther(reserves._reserve1) - } else { - // FLX is token 0 - flxReserve = ethers.utils.formatEther(reserves._reserve0) - } - setState(Number(flxReserve) * 2) - }, - [geb] - ) - - // attach/detach listeners - useEffect(() => { - if (!geb) return - const reservesCall = geb.contracts.uniswapPairCoinEth.getReserves(true) - reservesCall.to = geb.contracts.stakingToken.address - geb.multiCall([reservesCall]) - .then(resevesCallback) - .catch((e) => console.log(e)) - }, [geb, resevesCallback]) - - return useMemo(() => state, [state]) -} - -export function usePoolData() { - const { account } = useActiveWeb3React() - const farmerData = useFarmerData() - const StakingContractInterface = new Interface(SimpleStakingContract) - const ERC20Interface = new Interface(ERC20ABI) - const { contractAddress, tokens, contractName, flxPrice } = farmerData - const uniswapV2LpSharePrice = useUniswapPairCoinEthPrice() - const stakingToken = tokens[contractName as TokenName] - const stakingTokenAddress = isAddress(stakingToken?.address) - ? getAddress(stakingToken?.address) - : undefined - - //contracts - - const StakingContract = useContract( - contractAddress, - StakingContractInterface - ) - const StakingTokenContract = useContract( - stakingTokenAddress, - ERC20Interface - ) - - const poolBalanceRes = useSingleCallResult( - StakingTokenContract, - 'balanceOf', - [contractAddress] - ) - - const rewardRateResponse = useSingleCallResult( - StakingContract, - 'rewardRate' - ) - - const stakedBalanceResponse = useSingleCallResult( - StakingContract, - 'balanceOf', - [account as string] - ) - - const rewardsDurationResponse = useSingleCallResult( - StakingContract, - 'rewardsDuration' - ) - - const myRewardResponse = useSingleCallResult(StakingContract, 'earned', [ - account as string, - ]) - - const myCurrentReward = - myRewardResponse.result?.[0] > 0 - ? ethers.utils.formatEther(myRewardResponse?.result?.[0]) - : '0' - - const poolBalance = - poolBalanceRes.result?.[0] > 0 - ? ethers.utils.formatEther(poolBalanceRes?.result?.[0]) - : '0' - const rewardRate = - rewardRateResponse.result?.[0] > 0 - ? ethers.utils.formatEther(rewardRateResponse?.result?.[0]) - : '0' - const stakedBalance = - stakedBalanceResponse.result?.[0] > 0 - ? ethers.utils.formatEther(stakedBalanceResponse?.result?.[0]) - : '0' - - const rewardsDuration = - rewardsDurationResponse.result?.[0] > 0 - ? rewardsDurationResponse?.result?.[0].toString() - : '0' - - const weeklyReward = - (Number(rewardRate) * Number(poolBalance) * 7 * 3600 * 24) / - BLOCK_INTERVAL - - const stakedTokenPrice = - stakingToken?.name.toLowerCase() === 'flx' - ? flxPrice - : uniswapV2LpSharePrice - - // rewardRate * secondPerYear * reward token price - const numerator = - Number(rewardRate) * Number(rewardsDuration) * REWARD_TOKEN_PRICE - // stakedTokenPrice * stakedTokenAmt - const denominator = Number(poolBalance) * stakedTokenPrice - - const apr = (numerator / denominator) * 100 - - return useMemo(() => { - return { - poolBalance, - apr, - weeklyReward, - rewardRate, - stakedBalance, - myCurrentReward, - } - }, [ - apr, - myCurrentReward, - poolBalance, - rewardRate, - stakedBalance, - weeklyReward, - ]) -} - -export function useInputsHandlers(): { - onTypedValue: (typedValue: string) => void -} { - const { earnModel: earnActions } = useStoreActions((state) => state) - - const onTypedValue = useCallback( - (typedValue: string) => { - if (!typedValue || typedValue === '') { - earnActions.setAmount('') - return - } - earnActions.setAmount(typedValue) - }, - [earnActions] - ) - - return { - onTypedValue, - } -} - -// add staking function -export function useAddStaking(): { - addStakingCallback: () => Promise -} { - const geb = useGeb() - const { account, library } = useActiveWeb3React() - const { contractAddress } = useFarmerData() - const { earnModel: earnState } = useStoreState((state) => state) - const { amount, farmerName, contractName } = earnState - const addStakingCallback = useCallback(async () => { - if (!library || !amount || !account || !geb) { - return - } - try { - const stakingAmountBN = ethers.utils.parseEther(amount) - store.dispatch.popupsModel.setIsWaitingModalOpen(true) - store.dispatch.popupsModel.setBlockBackdrop(true) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Waiting for confirmation', - text: 'Confirm this transaction in your wallet', - status: 'loading', - }) - const contract = geb.getGebContract( - contracts.SimpleStakingRewards, - contractAddress - ) - - const signer = library.getSigner(account) - const txData = contract.stake(stakingAmountBN) - - if (!txData) throw new Error('No transaction request!') - const tx = await handlePreTxGasEstimate(signer, txData) - const txResponse = await signer.sendTransaction(tx) - store.dispatch.earnModel.setAmount('') - if (txResponse) { - const { hash, chainId } = txResponse - store.dispatch.transactionsModel.addTransaction({ - chainId, - hash, - from: txResponse.from, - summary: `Staking ${farmerName.toUpperCase()} ${contractName.toUpperCase()}`, - addedTime: new Date().getTime(), - originalTx: txResponse, - }) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Transaction Submitted', - hash: txResponse.hash, - status: 'success', - }) - await txResponse.wait() - } - } catch (e) { - handleTransactionError(e) - } - }, [ - library, - amount, - account, - geb, - contractAddress, - farmerName, - contractName, - ]) - - return { addStakingCallback } -} - -// unstaking function -export function useUnstake(): { - unStakeCallback: () => Promise -} { - const geb = useGeb() - const { account, library } = useActiveWeb3React() - const { contractAddress } = useFarmerData() - const { earnModel: earnState } = useStoreState((state) => state) - const { amount, farmerName, contractName } = earnState - const unStakeCallback = useCallback(async () => { - if (!library || !account || !geb || !contractAddress || !amount) { - return - } - try { - store.dispatch.popupsModel.setIsWaitingModalOpen(true) - store.dispatch.popupsModel.setBlockBackdrop(true) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Waiting for confirmation', - text: 'Confirm this transaction in your wallet', - status: 'loading', - }) - const amountBN = ethers.utils.parseEther(amount) - - const contract = geb.getGebContract( - contracts.SimpleStakingRewards, - contractAddress - ) - - const signer = library.getSigner(account) - const txData = contract.withdraw(amountBN) - - if (!txData) throw new Error('No transaction request!') - const tx = await handlePreTxGasEstimate(signer, txData) - const txResponse = await signer.sendTransaction(tx) - store.dispatch.earnModel.setAmount('') - if (txResponse) { - const { hash, chainId } = txResponse - store.dispatch.transactionsModel.addTransaction({ - chainId, - hash, - from: txResponse.from, - summary: `Unstake ${farmerName.toUpperCase()} st${contractName.toUpperCase()}`, - addedTime: new Date().getTime(), - originalTx: txResponse, - }) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Transaction Submitted', - hash: txResponse.hash, - status: 'success', - }) - await txResponse.wait() - } - } catch (e) { - handleTransactionError(e) - } - }, [ - account, - amount, - contractAddress, - contractName, - farmerName, - geb, - library, - ]) - - return { unStakeCallback } -} - -// claimReward function -export function useClaimReward(): { - claimRewardCallback: () => Promise -} { - const geb = useGeb() - const { account, library } = useActiveWeb3React() - const { contractAddress } = useFarmerData() - const { earnModel: earnState } = useStoreState((state) => state) - const { farmerName, contractName } = earnState - - const claimRewardCallback = useCallback(async () => { - if (!library || !account || !geb || !contractAddress) { - return - } - try { - store.dispatch.popupsModel.setIsWaitingModalOpen(true) - store.dispatch.popupsModel.setBlockBackdrop(true) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Waiting for confirmation', - text: 'Confirm this transaction in your wallet', - status: 'loading', - }) - const contract = geb.getGebContract( - contracts.SimpleStakingRewards, - contractAddress - ) - - const signer = library.getSigner(account) - const txData = contract.getReward() - - if (!txData) throw new Error('No transaction request!') - const tx = await handlePreTxGasEstimate(signer, txData) - const txResponse = await signer.sendTransaction(tx) - store.dispatch.earnModel.setStakingData(DEFAULT_STATE) - if (txResponse) { - const { hash, chainId } = txResponse - store.dispatch.transactionsModel.addTransaction({ - chainId, - hash, - from: txResponse.from, - summary: `Claiming ${farmerName.toUpperCase()} st${contractName.toUpperCase()} Reward`, - addedTime: new Date().getTime(), - originalTx: txResponse, - }) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Transaction Submitted', - hash: txResponse.hash, - status: 'success', - }) - await txResponse.wait() - } - } catch (e) { - handleTransactionError(e) - } - }, [account, contractAddress, contractName, farmerName, geb, library]) - - return { claimRewardCallback } -} diff --git a/src/hooks/useGeb.ts b/src/hooks/useGeb.ts index d3c8ac7a..9aea0850 100644 --- a/src/hooks/useGeb.ts +++ b/src/hooks/useGeb.ts @@ -8,6 +8,8 @@ import { formatNumber } from '../utils/helper' type TokenType = 'ETH' | 'RAI' +// connect to geb.js + export default function useGeb(): Geb { const { library } = useActiveWeb3React() const [state, setState] = useState() @@ -22,6 +24,7 @@ export default function useGeb(): Geb { return state as Geb } +// check if is owner of the safe export function useIsOwner(safeId: string): boolean { const [state, setState] = useState(true) const geb = useGeb() @@ -52,6 +55,7 @@ export function useIsOwner(safeId: string): boolean { return state } +// Returns proxy address from geb.js export function useProxyAddress() { const geb = useGeb() const { account } = useActiveWeb3React() @@ -86,10 +90,12 @@ export function useProxyAddress() { return useMemo(() => proxyAddress, [proxyAddress]) } +// fetches latest blocknumber from store export function useBlockNumber() { return store.getState().connectWalletModel.blockNumber[NETWORK_ID] } +// returns safe handler from geb.js export function useSafeHandler(safeId: string): string { const [state, setState] = useState('') const geb = useGeb() @@ -105,6 +111,7 @@ export function useSafeHandler(safeId: string): string { return state } +// returns amount of currency in USD export function useTokenBalanceInUSD(token: TokenType, balance: string) { const ethPrice = store.getState().connectWalletModel.fiatPrice const raiPrice = diff --git a/src/hooks/useLiquidityPool.ts b/src/hooks/useLiquidityPool.ts deleted file mode 100644 index 21ea9093..00000000 --- a/src/hooks/useLiquidityPool.ts +++ /dev/null @@ -1,476 +0,0 @@ -import { BigNumber, BigNumberish, ethers } from 'ethers' -import { Geb } from 'geb.js' -import { TwoTrancheUniV3ManagerMath } from '../services/UniswapLiquidityManager' -import { useActiveWeb3React } from '.' -import { Tranche } from '../utils/interfaces' -import store, { useStoreActions, useStoreState } from '../store' -import JSBI from 'jsbi' -import { useCallback, useEffect, useMemo, useState } from 'react' -import { NETWORK_ID } from '../connectors' -import useGeb, { useProxyAddress } from './useGeb' -import { - handlePreTxGasEstimate, - handleTransactionError, - useHasPendingTransactions, -} from './TransactionHooks' - -const DEFAULT_STATE = { - totalLiquidity: '', - ethAmount: '', - raiAmount: '', -} - -// liquidity helpers -export function useLiquidityInfo(isDeposit = true) { - const { account } = useActiveWeb3React() - const proxyAddress = useProxyAddress() - const { earnModel: earnState } = useStoreState((state) => state) - const { data } = earnState - const balances = useBalances() - - const parsedAmounts = useMemo(() => { - return data - }, [data]) - - const sharesToTokens = useTokensFromLiquidity(parsedAmounts.totalLiquidity) - - const tokensStake = useMemo(() => { - return sharesToTokens - }, [sharesToTokens]) - - let error: string | undefined - if (!account) { - error = 'Connect Wallet' - } - if (!proxyAddress) { - error = 'Create a Reflexer Account to continue' - } - if (isDeposit) { - if (!parsedAmounts.ethAmount || !parsedAmounts.raiAmount) { - error = error ?? 'Enter an amount' - } - - if ( - balances && - balances.eth && - parsedAmounts.ethAmount && - ethers.utils - .parseEther(balances.eth.toString()) - .lt(ethers.utils.parseEther(parsedAmounts.ethAmount.toString())) - ) { - error = 'Insufficient ETH balance' - } - - if ( - balances && - parsedAmounts.raiAmount && - balances.rai && - ethers.utils - .parseEther(balances.rai.toString()) - .lt(ethers.utils.parseEther(parsedAmounts.raiAmount.toString())) - ) { - error = 'Insufficient RAI balance' - } - } else { - if (!parsedAmounts.totalLiquidity) { - error = error ?? 'Enter an amount' - } - - if ( - balances && - balances.totalLiquidity && - parsedAmounts.totalLiquidity && - ethers.utils - .parseEther(balances.totalLiquidity.toString()) - .lt( - ethers.utils.parseEther( - parsedAmounts.totalLiquidity.toString() - ) - ) - ) { - error = 'Insufficient UNI V3 RAI/ETH balance' - } - } - - return { - error, - balances, - parsedAmounts, - tokensStake, - } -} - -// fetches balances for rai,eth and liquidity -export function useBalances() { - const geb = useGeb() - const { account } = useActiveWeb3React() - const { connectWalletModel: connectWalletState } = useStoreState( - (state) => state - ) - const { ethBalance } = connectWalletState - const hasPendingTx = useHasPendingTransactions() - const [state, setState] = useState({ - eth: '0', - rai: '0', - totalLiquidity: '', - }) - useEffect(() => { - let isCanceled = false - if (!geb || !account) return - async function getLiquidityBalance() { - if (!isCanceled) { - const [liquidityBalance, coinBalance] = await geb.multiCall([ - geb.contracts.uniswapV3TwoTrancheLiquidityManager.balanceOf( - account as string, - true - ), - geb.contracts.coin.balanceOf(account as string, true), - ]) - - setState({ - eth: ethBalance[NETWORK_ID].toString(), - rai: ethers.utils.formatEther(coinBalance), - totalLiquidity: ethers.utils.formatEther(liquidityBalance), - }) - } - } - getLiquidityBalance() - return () => { - isCanceled = true - } - }, [geb, account, hasPendingTx, ethBalance]) - - return useMemo(() => { - return state - }, [state]) -} - -export function useInputsHandlers(): { - onEthInput: (typedValue: string) => void - onRaiInput: (typedValue: string) => void - onLiquidityInput: (typedValue: string) => void -} { - const { earnModel: earnState } = useStoreState((state) => state) - const { earnModel: earnActions } = useStoreActions((state) => state) - const { positionAndThreshold } = earnState - - const onLiquidityInput = useCallback( - (typedValue: string) => { - if (!typedValue || typedValue === '' || !positionAndThreshold) { - earnActions.setData(DEFAULT_STATE) - return - } - earnActions.setData({ - totalLiquidity: typedValue, - raiAmount: '', - ethAmount: '', - }) - }, - [earnActions, positionAndThreshold] - ) - - const onRaiInput = useCallback( - (typedValue: string) => { - if (!typedValue || typedValue === '' || !positionAndThreshold) { - earnActions.setData(DEFAULT_STATE) - return - } - - const { slot0, t1, t2 } = positionAndThreshold - const [liqB, token1Amt] = - TwoTrancheUniV3ManagerMath.getLiquidityAndAmountFromToken0( - JSBI.BigInt(ethers.utils.parseEther(typedValue)), - JSBI.BigInt(slot0.sqrtPriceX96), - t1, - t2 - ) - earnActions.setData({ - totalLiquidity: - Number(typedValue) === 0 - ? '0' - : ethers.utils.formatEther(liqB.toString()), - raiAmount: typedValue, - ethAmount: - Number(typedValue) === 0 - ? '0' - : ethers.utils.formatEther(token1Amt.toString()), - }) - }, - [earnActions, positionAndThreshold] - ) - const onEthInput = useCallback( - (typedValue: string) => { - if (!typedValue || typedValue === '' || !positionAndThreshold) { - earnActions.setData(DEFAULT_STATE) - return - } - const { slot0, t1, t2 } = positionAndThreshold - const [liqB, token0Amt] = - TwoTrancheUniV3ManagerMath.getLiquidityAndAmountFromToken1( - JSBI.BigInt(ethers.utils.parseEther(typedValue)), - JSBI.BigInt(slot0.sqrtPriceX96), - t1, - t2 - ) - const totalLiquidityVal = ethers.utils.formatEther(liqB.toString()) - const raiAmountVal = ethers.utils.formatEther(token0Amt.toString()) - - earnActions.setData({ - totalLiquidity: - Number(totalLiquidityVal) < 0 ? '0' : totalLiquidityVal, - ethAmount: typedValue, - raiAmount: Number(raiAmountVal) < 0 ? '0' : totalLiquidityVal, - }) - }, - [earnActions, positionAndThreshold] - ) - - return { - onEthInput, - onRaiInput, - onLiquidityInput, - } -} - -export function useTokensFromLiquidity(liquidity: string) { - const geb = useGeb() - const [state, setState] = useState({ eth: '0', rai: '0' }) - - useEffect(() => { - let isCanceled = false - if (!geb || Number(liquidity) <= 0) { - setState({ eth: '0', rai: '0' }) - return - } - async function getSharesFromLiquidity() { - if (!isCanceled) { - const liquidityBN = ethers.utils.parseEther(liquidity) - const [sharesToT1, sharesToT2]: [BigNumber, BigNumber] = - await geb.multiCall([ - getTokenXFromLiquidity(geb, true, liquidityBN), - getTokenXFromLiquidity(geb, false, liquidityBN), - ]) - - setState({ - eth: ethers.utils.formatEther(sharesToT1), - rai: ethers.utils.formatEther(sharesToT2), - }) - } - } - getSharesFromLiquidity() - return () => { - isCanceled = true - } - }, [geb, liquidity]) - - return state -} - -// add liquidity function -export function useAddLiquidity(): { - addLiquidityCallback: () => Promise -} { - const geb = useGeb() - const { account, library } = useActiveWeb3React() - const { earnModel: earnState } = useStoreState((state) => state) - const { data } = earnState - const addLiquidityCallback = useCallback(async () => { - const { ethAmount, raiAmount, totalLiquidity } = data - if ( - !library || - !ethAmount || - !raiAmount || - !totalLiquidity || - !account || - !geb - ) { - return - } - try { - const ethAmountBN = ethers.utils.parseEther(ethAmount) - const raiAmountBN = ethers.utils.parseEther(raiAmount) - const totalLiquidityBN = ethers.utils.parseEther(totalLiquidity) - - store.dispatch.popupsModel.setIsWaitingModalOpen(true) - store.dispatch.popupsModel.setBlockBackdrop(true) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Waiting for confirmation', - text: 'Confirm this transaction in your wallet', - status: 'loading', - }) - const signer = library.getSigner(account) - - const txData = - geb.contracts.uniswapV3TwoTrancheLiquidityManager.deposit( - ethAmountBN, // First param is always ETH Amount - totalLiquidityBN, - account, - raiAmountBN.mul(9).div(10), // token0 Slippage safety at 90% - ethAmountBN.mul(9).div(10) // token1 Slippage safety at 90% - ) - - if (!txData) throw new Error('No transaction request!') - const tx = await handlePreTxGasEstimate(signer, txData) - const txResponse = await signer.sendTransaction(tx) - store.dispatch.earnModel.setData(DEFAULT_STATE) - if (txResponse) { - const { hash, chainId } = txResponse - store.dispatch.transactionsModel.addTransaction({ - chainId, - hash, - from: txResponse.from, - summary: 'Adding Uniswap V3 RAI/ETH liquidity', - addedTime: new Date().getTime(), - originalTx: txResponse, - }) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Transaction Submitted', - hash: txResponse.hash, - status: 'success', - }) - await txResponse.wait() - } - } catch (error) { - handleTransactionError(error) - } - }, [account, data, geb, library]) - - return { addLiquidityCallback } -} -//withdraw liquidity function -export function useWithdrawLiquidity(): { - withdrawLiquidityCallback: () => Promise -} { - const geb = useGeb() - const { account, library } = useActiveWeb3React() - const { earnModel: earnState } = useStoreState((state) => state) - const { data } = earnState - const withdrawLiquidityCallback = useCallback(async () => { - const { totalLiquidity } = data - if (!library || !totalLiquidity || !account || !geb) { - return - } - try { - const totalLiquidityBN = ethers.utils.parseEther(totalLiquidity) - - store.dispatch.popupsModel.setIsWaitingModalOpen(true) - store.dispatch.popupsModel.setBlockBackdrop(true) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Waiting for confirmation', - text: 'Confirm this transaction in your wallet', - status: 'loading', - }) - const signer = library.getSigner(account) - - const txData = - geb.contracts.uniswapV3TwoTrancheLiquidityManager.withdraw( - totalLiquidityBN, - account - ) - - if (!txData) throw new Error('No transaction request!') - const tx = await handlePreTxGasEstimate(signer, txData) - const txResponse = await signer.sendTransaction(tx) - store.dispatch.earnModel.setData(DEFAULT_STATE) - - if (txResponse) { - const { hash, chainId } = txResponse - store.dispatch.transactionsModel.addTransaction({ - chainId, - hash, - from: txResponse.from, - summary: 'Withdrawing Uniswap V3 RAI/ETH liquidity', - addedTime: new Date().getTime(), - originalTx: txResponse, - }) - store.dispatch.popupsModel.setWaitingPayload({ - title: 'Transaction Submitted', - hash: txResponse.hash, - status: 'success', - }) - await txResponse.wait() - } - } catch (error) { - handleTransactionError(error) - } - }, [account, data, geb, library]) - - return { withdrawLiquidityCallback } -} - -// helper function to fetch ticks -function getNextTicksMulticallRequest(geb: Geb, threshold: BigNumberish) { - const nextTickAbiFragment = { - inputs: [ - { - internalType: 'uint256', - name: '_threshold', - type: 'uint256', - }, - ], - name: 'getNextTicks', - outputs: [ - { internalType: 'int24', name: 'lowerTick', type: 'int24' }, - { internalType: 'int24', name: 'upperTick', type: 'int24' }, - { internalType: 'int24', name: 'targetTick', type: 'int24' }, - ], - stateMutability: 'nonpayable', - type: 'function', - } - - const tx = - geb.contracts.uniswapV3TwoTrancheLiquidityManager.getNextTicks( - threshold - ) - return { - data: tx.data as string, - to: tx.to as string, - abi: nextTickAbiFragment, - } -} -// helper function to fetch shareAmount of token0 and token1 -export function getTokenXFromLiquidity( - geb: Geb, - isToken1: boolean, - liquidity: BigNumberish -) { - const abiFragment = { - inputs: [ - { - internalType: 'uint128', - name: '_liquidity', - type: 'uint128', - }, - ], - name: isToken1 ? 'getToken1FromLiquidity' : 'getToken0FromLiquidity', - outputs: [ - { internalType: 'uint256', name: 'amount0', type: 'uint256' }, - ], - stateMutability: 'nonpayable', - type: 'function', - } - - const tx = isToken1 - ? geb.contracts.uniswapV3TwoTrancheLiquidityManager.getToken1FromLiquidity( - liquidity - ) - : geb.contracts.uniswapV3TwoTrancheLiquidityManager.getToken0FromLiquidity( - liquidity - ) - return { data: tx.data as string, to: tx.to as string, abi: abiFragment } -} - -// helper function fetches positions -export async function fetchPositions(geb: Geb) { - if (!geb) return - const [slot0, p1, p2] = await geb.multiCall([ - geb.contracts.uniswapV3PairCoinEth.slot0(true), - geb.contracts.uniswapV3TwoTrancheLiquidityManager.positions(0, true), - geb.contracts.uniswapV3TwoTrancheLiquidityManager.positions(1, true), - ]) - const [t1, t2]: [Tranche, Tranche] = await geb.multiCall([ - getNextTicksMulticallRequest(geb, p1.threshold), - getNextTicksMulticallRequest(geb, p2.threshold), - ]) - return { slot0, p1, p2, t1, t2 } -} diff --git a/src/hooks/useSafe.ts b/src/hooks/useSafe.ts index 8340c0e8..5ca702d7 100644 --- a/src/hooks/useSafe.ts +++ b/src/hooks/useSafe.ts @@ -33,11 +33,13 @@ export type Stats = { }> } +// returns safe model state from store export function useSafeState() { const { safeModel: safeState } = useStoreState((state) => state) return useMemo(() => safeState, [safeState]) } +// returns all safe info from amounts, debt, collateral and other helper attributes export function useSafeInfo(type: SafeTypes = 'create') { const { account } = useActiveWeb3React() const proxyAddress = useProxyAddress() @@ -46,12 +48,15 @@ export function useSafeInfo(type: SafeTypes = 'create') { safeModel: { safeData, singleSafe, liquidationData }, } = useStoreState((state) => state) + // parsed amounts of deposit/repay withdraw/borrow as in left input and right input, they get switched based on if its Deposit & Borrow or Repay & Withdraw const parsedAmounts = useMemo(() => { const { leftInput, rightInput } = safeData return { leftInput, rightInput } }, [safeData]) const { leftInput, rightInput } = parsedAmounts + + // get eth and rai balances const { eth, rai } = useTokenBalances(account as string) const balances = useMemo(() => { @@ -63,16 +68,23 @@ export function useSafeInfo(type: SafeTypes = 'create') { const { eth: ethBalance, rai: raiBalance } = balances + // returns collateral amount and takes into consideration if its a new safe or not const collateral = useTotalCollateral(leftInput, type) + // returns debt amount and takes into consideration if its a new safe or not const debt = useTotalDebt(rightInput, type) const totalCollateral = useMemo(() => collateral, [collateral]) const totalDebt = useMemo(() => debt, [debt]) + // Checks if for collateralRatio safety if its safe or not const isSafe = useSafeIsSafe(totalCollateral, totalDebt) + // returns collateral ratio const collateralRatio = useCollateralRatio(totalCollateral, totalDebt) + // returns liquidation price const liquidationPrice = useLiquidationPrice(totalCollateral, totalDebt) + // returns available ETH (collateral) + // singleSafe means already a deployed safe const availableEth = useMemo(() => { if (type === 'deposit_borrow') { return formatNumber(ethBalance) @@ -84,6 +96,8 @@ export function useSafeInfo(type: SafeTypes = 'create') { return '0.00' }, [ethBalance, singleSafe, type]) + // returns available RAI (debt) + // singleSafe means already a deployed safe const availableRai = useMemo(() => { if (type === 'create') { return returnAvaiableDebt( @@ -126,7 +140,7 @@ export function useSafeInfo(type: SafeTypes = 'create') { const availableRaiBN = BigNumber.from( toFixedString(availableRai.toString(), 'WAD') ) - + // account's RAI balance into BigNumber const raiBalanceBN = raiBalance ? BigNumber.from(toFixedString(raiBalance.toString(), 'WAD')) : BigNumber.from('0') @@ -138,12 +152,13 @@ export function useSafeInfo(type: SafeTypes = 'create') { const rightInputBN = rightInput ? BigNumber.from(toFixedString(rightInput, 'WAD')) : BigNumber.from('0') - + // returns debtFloor from liquidation data from store const debtFloorBN = BigNumber.from( toFixedString(liquidationData.debtFloor, 'WAD') ) const totalDebtBN = BigNumber.from(toFixedString(totalDebt, 'WAD')) + // returns stats data used into stats display of the safe const stats: Stats = useMemo(() => { return { data: [ @@ -347,7 +362,7 @@ export function useSafeInfo(type: SafeTypes = 'create') { balances, } } - +// returns totalCollateral export function useTotalCollateral(leftInput: string, type: SafeTypes) { const { singleSafe } = useSafeState() const totalCollateral = useMemo(() => { @@ -367,7 +382,7 @@ export function useTotalCollateral(leftInput: string, type: SafeTypes) { return totalCollateral || '0' } - +// returns total debt export function useTotalDebt(rightInput: string, type: SafeTypes) { const { singleSafe, @@ -393,7 +408,7 @@ export function useTotalDebt(rightInput: string, type: SafeTypes) { return totalDebt && Number(totalDebt) > 0.00001 ? totalDebt : '0' } - +// returns collateral Ratio export function useCollateralRatio(totalCollateral: string, totalDebt: string) { const { liquidationData: { currentPrice, liquidationCRatio }, @@ -413,7 +428,7 @@ export function useCollateralRatio(totalCollateral: string, totalDebt: string) { totalDebt, ]) } - +// returns liquidation price export function useLiquidationPrice( totalCollateral: string, totalDebt: string @@ -431,7 +446,7 @@ export function useLiquidationPrice( ) }, [currentRedemptionPrice, liquidationCRatio, totalCollateral, totalDebt]) } - +// checks for safe safety of collateral ratio export function useSafeIsSafe(totalCollateral: string, totalDebt: string) { const { liquidationData: { currentPrice }, @@ -441,7 +456,7 @@ export function useSafeIsSafe(totalCollateral: string, totalDebt: string) { return safeIsSafe(totalCollateral, totalDebt, currentPrice.safetyPrice) }, [currentPrice.safetyPrice, totalCollateral, totalDebt]) } - +// handles input data validation and storing them into store export function useInputsHandlers(): { onLeftInput: (typedValue: string) => void onRightInput: (typedValue: string) => void diff --git a/src/hooks/useSaviour.ts b/src/hooks/useSaviour.ts index 372a70fc..195bc457 100644 --- a/src/hooks/useSaviour.ts +++ b/src/hooks/useSaviour.ts @@ -66,15 +66,17 @@ export type Stats = { }> } +// returns saviour data export function useSaviourInfo() { const { t } = useTranslation() const { account } = useActiveWeb3React() - + // get account proxy address const proxyAddress = useProxyAddress() - + // get saviour data const saviourHook = useSaviourData() + // get min saviour balance const { getMinSaviourBalance } = useMinSaviourBalance() - + // safe data from store const { safeModel: safeState } = useStoreState((state) => state) const { isSaviourDeposit, @@ -88,13 +90,16 @@ export function useSaviourInfo() { return saviourHook }, [saviourHook]) + // checks if its curve saviour or Uniswap const isCurveSaviour = useMemo(() => saviourType === 'curve', [saviourType]) + // token label based on saviour type const tokenLabel = useMemo( () => (isCurveSaviour ? 'RAI3CRV' : 'UNI-V2'), [isCurveSaviour] ) + // saviour states const saviourState = useMemo(() => { return { isSaviourDeposit, @@ -105,8 +110,10 @@ export function useSaviourInfo() { } }, [isSaviourDeposit, amount, targetedCRatio, saviourType, isMaxWithdraw]) + // checks if safe has a saviour const hasSaviour = saviourData && saviourData.hasSaviour + // return saviour tokens const tokens = useMemo(() => { return saviourData ? { @@ -119,12 +126,15 @@ export function useSaviourInfo() { : TOKENS }, [saviourData]) + // return token balances const tokenBalances = useTokenBalances(account as string, tokens) + // returns safeId of the saviour data from store const safeId = useMemo(() => { return saviourData ? saviourData.safeId : '' }, [saviourData]) + // available balance to deposit const availableDepositBalance = useMemo(() => { return saviourData ? isCurveSaviour @@ -133,10 +143,12 @@ export function useSaviourInfo() { : '0' }, [isCurveSaviour, saviourData, tokenBalances]) + // available saviour balance to withdraw const availableWithdrawBalance = useMemo(() => { return saviourData ? saviourData.saviourBalance : '0' }, [saviourData]) + // account saviour balance const mySaviourBalance = useMemo(() => { if (!saviourData) return '0' const amountBN = amount @@ -151,11 +163,12 @@ export function useSaviourInfo() { return ethers.utils.formatEther(saviourBalanceBN.sub(amountBN)) }, [amount, isSaviourDeposit, saviourData]) + // min saviour balance to deposit or to save your safe const minSaviourBalance = getMinSaviourBalance({ type: saviourType, targetedCRatio, }) - + // saviour stats used to for display const stats: Stats = useMemo(() => { return { data: [ @@ -311,6 +324,7 @@ export function useSaviourInfo() { } } +// handles input handling input amount export function useInputHandler(): { onTypedInput: (typedValue: string) => void } { @@ -331,6 +345,7 @@ export function useInputHandler(): { } } +// returns saviour address if exists or 0X00000 address export function useSaviourAddress(safeHandler: string) { const [state, setState] = useState(EMPTY_ADDRESS) const geb = useGeb() @@ -355,6 +370,7 @@ export function useSaviourAddress(safeHandler: string) { return useMemo(() => state, [state]) } +// Checks if safe has a saviour export function useHasSaviour(safeHandler: string) { const saviourAddress = useSaviourAddress(safeHandler) return useMemo(() => { @@ -362,6 +378,7 @@ export function useHasSaviour(safeHandler: string) { }, [safeHandler, saviourAddress]) } +// Checks if safe has Left over after saving the safe has been successful export function useHasLeftOver(safeHandler: string) { const [state, setState] = useState(false) const geb = useGeb() @@ -434,7 +451,7 @@ export function useHasLeftOver(safeHandler: string) { [saviourAddress, state] ) } - +// Feching saviour data and saving it into store export async function fetchSaviourData({ account, safeId, diff --git a/src/hooks/useSwap.ts b/src/hooks/useSwap.ts index b4c7862d..ccd145ec 100644 --- a/src/hooks/useSwap.ts +++ b/src/hooks/useSwap.ts @@ -1,6 +1,7 @@ import { useCallback } from 'react' import { WYRE_WORKER } from '../utils/constants' +// geberates swap url for Wyre so it user can swap fiat to RAI export default function useSwap() { const generateSwap = useCallback(async () => { const res = await generateSwapUrl() diff --git a/src/hooks/useTokenApproval.tsx b/src/hooks/useTokenApproval.tsx index 36aae7e8..b6d48c49 100644 --- a/src/hooks/useTokenApproval.tsx +++ b/src/hooks/useTokenApproval.tsx @@ -19,7 +19,7 @@ export enum ApprovalState { PENDING, APPROVED, } - +// checks for token allowance export function useTokenAllowance( tokenAddress?: string, owner?: string, diff --git a/src/index.tsx b/src/index.tsx index e9d8e89b..66440016 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,7 @@ import React from 'react' import { createWeb3ReactRoot, Web3ReactProvider } from '@web3-react/core' import ReactDOM from 'react-dom' +import { HashRouter } from 'react-router-dom' import { StoreProvider } from 'easy-peasy' import './index.css' import App from './App' @@ -18,13 +19,15 @@ if ('ethereum' in window) { ReactDOM.render( - - - - - - - + + + + + + + + + , document.getElementById('root') diff --git a/src/model/connectWalletModel.ts b/src/model/connectWalletModel.ts index 8fa120d6..bc07b661 100644 --- a/src/model/connectWalletModel.ts +++ b/src/model/connectWalletModel.ts @@ -84,9 +84,16 @@ const connectWalletModel: ConnectWalletModel = { fetchFiatPrice: thunk(async (actions, payload) => { const res = await api.fetchFiatPrice() const flxRes = await api.fetchFiatPrice('reflexer-ungovernance-token') - actions.setFiatPrice(res.usd) - actions.setFlxPrice(flxRes.usd) - actions.setEthPriceChange(res.usd_24h_change) + if (res && res.used) { + actions.setFiatPrice(res.usd) + } + if (flxRes && flxRes.usd) { + actions.setFlxPrice(flxRes.usd) + } + + if (res && res.usd_24h_change) { + actions.setEthPriceChange(res.usd_24h_change) + } }), fetchUser: thunk(async (actions, payload) => { diff --git a/src/model/earnModel.ts b/src/model/earnModel.ts index bb6f18f7..9e1abb4d 100644 --- a/src/model/earnModel.ts +++ b/src/model/earnModel.ts @@ -1,12 +1,5 @@ -import { action, Action, thunk, Thunk } from 'easy-peasy' -import { Geb } from 'geb.js' -import { fetchPositions } from '../hooks/useLiquidityPool' -import { - ILiquidityData, - IStakedLP, - PositionsAndThreshold, - IStakingData, -} from '../utils/interfaces' +import { action, Action } from 'easy-peasy' +import { ILiquidityData, IStakedLP, IStakingData } from '../utils/interfaces' export const farmersArray = ['volt', 'h2o'] as const export const contractsArray = ['flx', 'flx_lp'] as const @@ -20,9 +13,6 @@ export interface EarnModel { amount: string farmerName: FARMER_NAME contractName: CONTRACT_NAME - positionAndThreshold: PositionsAndThreshold | null - fetchPositionsAndThreshold: Thunk - setPositionAndThreshold: Action setData: Action setStakedLP: Action setStakingData: Action @@ -32,7 +22,6 @@ export interface EarnModel { } const earnModel: EarnModel = { - positionAndThreshold: null, amount: '', farmerName: 'volt', contractName: 'flx', @@ -49,15 +38,6 @@ const earnModel: EarnModel = { eth: '', rai: '', }, - fetchPositionsAndThreshold: thunk(async (actions, payload) => { - const res = await fetchPositions(payload) - if (res) { - actions.setPositionAndThreshold(res) - } - }), - setPositionAndThreshold: action((state, payload) => { - state.positionAndThreshold = payload - }), setData: action((state, payload) => { state.data = payload }), diff --git a/src/services/BalanceUpdater.ts b/src/services/BalanceUpdater.ts index 33b25ff2..ef1d433c 100644 --- a/src/services/BalanceUpdater.ts +++ b/src/services/BalanceUpdater.ts @@ -23,6 +23,7 @@ export default function ApplicationUpdater(): null { (result: any) => { setState((state) => { if (chainId === state.chainId) { + store.dispatch.connectWalletModel.fetchFiatPrice() return { chainId, balance: Number(ethers.utils.formatEther(result)), @@ -57,8 +58,6 @@ export default function ApplicationUpdater(): null { chainId: debouncedState.chainId, balance: debouncedState.balance, }) - - store.dispatch.connectWalletModel.fetchFiatPrice() }, [debouncedState.balance, debouncedState.chainId]) return null diff --git a/src/services/MulticallUpdater.tsx b/src/services/MulticallUpdater.tsx index c41e4539..b4efd095 100644 --- a/src/services/MulticallUpdater.tsx +++ b/src/services/MulticallUpdater.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useRef } from 'react' import { Call, CallListeners, CallResults } from '../utils/interfaces' -import { Multicall2 } from '../abis/Multicall2' +import { Multicall } from '../abis/Multicall' import { retry, RetryableError } from '../utils/retry' import store from '../store' import useDebounce from '../hooks/useDebounce' @@ -17,7 +17,7 @@ import chunkArray from '../utils/chunkArray' * @param minBlockNumber minimum block number of the result set */ async function fetchChunk( - multicall2Contract: Multicall2, + multicall2Contract: Multicall, chunk: Call[], minBlockNumber: number ): Promise<{ @@ -29,15 +29,14 @@ async function fetchChunk( let results: { success: boolean; returnData: string }[] try { const { blockNumber, returnData } = - await multicall2Contract.callStatic.tryBlockAndAggregate( - false, + await multicall2Contract.callStatic.aggregate( chunk.map((obj) => ({ target: obj.address, callData: obj.callData, })) ) resultsBlockNumber = blockNumber.toNumber() - results = returnData + results = returnData.map((x) => ({ success: true, returnData: x })) } catch (error) { console.debug('Failed to fetch chunk', error) throw error @@ -235,7 +234,7 @@ export default function Updater(): null { ) // dispatch any new results - if (Object.keys(results).length > 0) + if (results && Object.keys(results).length > 0) { store.dispatch.multicallModel.updateMulticallResults( { chainId, @@ -243,7 +242,7 @@ export default function Updater(): null { blockNumber: fetchBlockNumber, } ) - + } // dispatch any errored calls if (erroredCalls.length > 0) { console.debug( diff --git a/src/services/UniswapLiquidityManager.ts b/src/services/UniswapLiquidityManager.ts deleted file mode 100644 index 126bf9ef..00000000 --- a/src/services/UniswapLiquidityManager.ts +++ /dev/null @@ -1,326 +0,0 @@ -/* eslint-disable eqeqeq */ -import JSBI from 'jsbi' -import { Tranche } from '../utils/interfaces' - -// From @JG with fixes from @Guillaume -class TwoTrancheUniV3ManagerMath { - private static Q96 = JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(96)) - - public static getLiquidityAndAmountFromToken0( - token0Amount: JSBI, - currentPrice: JSBI, - tranche1: Tranche, - tranche2: Tranche - ) { - let liq = this.getLiquidityFromAmount0( - token0Amount, - currentPrice, - TickMath.getSqrtRatioAtTick(tranche1.upperTick), - TickMath.getSqrtRatioAtTick(tranche2.upperTick) - ) - let tknAm1 = this.getAmount1ForLiquidity( - liq, - TickMath.getSqrtRatioAtTick(tranche1.lowerTick), - currentPrice - ) - let tknAm2 = this.getAmount1ForLiquidity( - liq, - TickMath.getSqrtRatioAtTick(tranche2.lowerTick), - currentPrice - ) - - let finalLiquidity = JSBI.multiply(liq, JSBI.BigInt(2)) - let finalAmount = JSBI.add(tknAm1, tknAm2) - - // Rounding error that would make the transfer fail - // Fix added by @Guillaume - finalAmount = JSBI.add(finalAmount, JSBI.BigInt('10000')) - - return [finalLiquidity, finalAmount] - } - - public static getLiquidityAndAmountFromToken1( - token1Amount: JSBI, - currentPrice: JSBI, - tranche1: Tranche, - tranche2: Tranche - ) { - // Rounding error that would make the transfer fail - // Fix added by @Guillaume - token1Amount = JSBI.subtract(token1Amount, JSBI.BigInt('10000')) - - let liq = this.getLiquidityFromAmount1( - token1Amount, - currentPrice, - TickMath.getSqrtRatioAtTick(tranche1.lowerTick), - TickMath.getSqrtRatioAtTick(tranche2.lowerTick) - ) - let tknAm1 = this.getAmount0ForLiquidity( - liq, - currentPrice, - TickMath.getSqrtRatioAtTick(tranche1.upperTick) - ) - let tknAm2 = this.getAmount0ForLiquidity( - liq, - currentPrice, - TickMath.getSqrtRatioAtTick(tranche2.upperTick) - ) - - let finalLiquidity = JSBI.multiply(liq, JSBI.BigInt(2)) - let finalAmount = JSBI.add(tknAm1, tknAm2) - - return [finalLiquidity, finalAmount] - } - - public static getLiquidityFromAmount0( - token0Amount: JSBI, - currentPrice: JSBI, - boundary1: JSBI, - boundary2: JSBI - ): JSBI { - let delta1 = JSBI.greaterThan(currentPrice, boundary1) - ? JSBI.subtract(currentPrice, boundary1) - : JSBI.subtract(boundary1, currentPrice) - let delta2 = JSBI.greaterThan(currentPrice, boundary2) - ? JSBI.subtract(currentPrice, boundary2) - : JSBI.subtract(boundary2, currentPrice) - - let num1 = JSBI.multiply(currentPrice, boundary1) - let num2 = JSBI.multiply(currentPrice, boundary2) - let num = JSBI.multiply(token0Amount, JSBI.multiply(num1, num2)) - - let den1 = JSBI.multiply(delta2, JSBI.multiply(currentPrice, boundary1)) - let den2 = JSBI.multiply(delta1, JSBI.multiply(currentPrice, boundary2)) - let den = JSBI.multiply(JSBI.add(den1, den2), this.Q96) - - return JSBI.divide(num, den) - } - - public static getLiquidityFromAmount1( - token1Amount: JSBI, - currentPrice: JSBI, - boundary1: JSBI, - boundary2: JSBI - ): JSBI { - let delta1 = JSBI.greaterThan(currentPrice, boundary1) - ? JSBI.subtract(currentPrice, boundary1) - : JSBI.subtract(boundary1, currentPrice) - let delta2 = JSBI.greaterThan(currentPrice, boundary2) - ? JSBI.subtract(currentPrice, boundary2) - : JSBI.subtract(boundary2, currentPrice) - - let num = JSBI.multiply(token1Amount, this.Q96) - let den = JSBI.add(delta1, delta2) - return JSBI.divide(num, den) - } - - public static getAmount1ForLiquidity( - liquidity: JSBI, - lowerPrice: JSBI, - upperPrice: JSBI - ): JSBI { - let delta = JSBI.subtract(upperPrice, lowerPrice) - return JSBI.divide(JSBI.multiply(liquidity, delta), this.Q96) - } - - public static getAmount0ForLiquidity( - liquidity: JSBI, - lowerPrice: JSBI, - upperPrice: JSBI - ): JSBI { - let delta = JSBI.subtract(upperPrice, lowerPrice) - let num = JSBI.multiply( - JSBI.leftShift(liquidity, JSBI.BigInt(96)), - delta - ) - return JSBI.divide(JSBI.divide(num, upperPrice), lowerPrice) - } -} - -// From Uniswap SDK -// https://github.com/Uniswap/uniswap-v3-sdk/blob/main/src/utils/tickMath.ts -class TickMath { - /** - * Cannot be constructed. - */ - private constructor() {} - - /** - * The minimum tick that can be used on any pool. - */ - public static MIN_TICK: number = -887272 - /** - * The maximum tick that can be used on any pool. - */ - public static MAX_TICK: number = -TickMath.MIN_TICK - - /** - * The sqrt ratio corresponding to the minimum tick that could be used on any pool. - */ - public static MIN_SQRT_RATIO: JSBI = JSBI.BigInt('4295128739') - /** - * The sqrt ratio corresponding to the maximum tick that could be used on any pool. - */ - public static MAX_SQRT_RATIO: JSBI = JSBI.BigInt( - '1461446703485210103287273052203988822378723970342' - ) - - /** - * Returns the sqrt ratio as a Q64.96 for the given tick. The sqrt ratio is computed as sqrt(1.0001)^tick - * @param tick the tick for which to compute the sqrt ratio - */ - - private static ZERO = JSBI.BigInt(0) - private static ONE = JSBI.BigInt(1) - private static Q32 = JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(32)) - private static MaxUint256 = JSBI.BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' - ) - - public static getSqrtRatioAtTick(tick: number): JSBI { - // invariant(tick >= TickMath.MIN_TICK && tick <= TickMath.MAX_TICK && Number.isInteger(tick), 'TICK') - const absTick: number = tick < 0 ? tick * -1 : tick - - let ratio: JSBI = - (absTick & 0x1) != 0 - ? JSBI.BigInt('0xfffcb933bd6fad37aa2d162d1a594001') - : JSBI.BigInt('0x100000000000000000000000000000000') - if ((absTick & 0x2) != 0) - ratio = this.mulShift(ratio, '0xfff97272373d413259a46990580e213a') - if ((absTick & 0x4) != 0) - ratio = this.mulShift(ratio, '0xfff2e50f5f656932ef12357cf3c7fdcc') - if ((absTick & 0x8) != 0) - ratio = this.mulShift(ratio, '0xffe5caca7e10e4e61c3624eaa0941cd0') - if ((absTick & 0x10) != 0) - ratio = this.mulShift(ratio, '0xffcb9843d60f6159c9db58835c926644') - if ((absTick & 0x20) != 0) - ratio = this.mulShift(ratio, '0xff973b41fa98c081472e6896dfb254c0') - if ((absTick & 0x40) != 0) - ratio = this.mulShift(ratio, '0xff2ea16466c96a3843ec78b326b52861') - if ((absTick & 0x80) != 0) - ratio = this.mulShift(ratio, '0xfe5dee046a99a2a811c461f1969c3053') - if ((absTick & 0x100) != 0) - ratio = this.mulShift(ratio, '0xfcbe86c7900a88aedcffc83b479aa3a4') - if ((absTick & 0x200) != 0) - ratio = this.mulShift(ratio, '0xf987a7253ac413176f2b074cf7815e54') - if ((absTick & 0x400) != 0) - ratio = this.mulShift(ratio, '0xf3392b0822b70005940c7a398e4b70f3') - if ((absTick & 0x800) != 0) - ratio = this.mulShift(ratio, '0xe7159475a2c29b7443b29c7fa6e889d9') - if ((absTick & 0x1000) != 0) - ratio = this.mulShift(ratio, '0xd097f3bdfd2022b8845ad8f792aa5825') - if ((absTick & 0x2000) != 0) - ratio = this.mulShift(ratio, '0xa9f746462d870fdf8a65dc1f90e061e5') - if ((absTick & 0x4000) != 0) - ratio = this.mulShift(ratio, '0x70d869a156d2a1b890bb3df62baf32f7') - if ((absTick & 0x8000) != 0) - ratio = this.mulShift(ratio, '0x31be135f97d08fd981231505542fcfa6') - if ((absTick & 0x10000) != 0) - ratio = this.mulShift(ratio, '0x9aa508b5b7a84e1c677de54f3e99bc9') - if ((absTick & 0x20000) != 0) - ratio = this.mulShift(ratio, '0x5d6af8dedb81196699c329225ee604') - if ((absTick & 0x40000) != 0) - ratio = this.mulShift(ratio, '0x2216e584f5fa1ea926041bedfe98') - if ((absTick & 0x80000) != 0) - ratio = this.mulShift(ratio, '0x48a170391f7dc42444e8fa2') - - if (tick > 0) ratio = JSBI.divide(this.MaxUint256, ratio) - - // back to Q96 - return JSBI.greaterThan(JSBI.remainder(ratio, this.Q32), this.ZERO) - ? JSBI.add(JSBI.divide(ratio, this.Q32), this.ONE) - : JSBI.divide(ratio, this.Q32) - } - - /** - * Returns the tick corresponding to a given sqrt ratio, s.t. #getSqrtRatioAtTick(tick) <= sqrtRatioX96 - * and #getSqrtRatioAtTick(tick + 1) > sqrtRatioX96 - * @param sqrtRatioX96 the sqrt ratio as a Q64.96 for which to compute the tick - */ - public static getTickAtSqrtRatio(sqrtRatioX96: JSBI): number { - const sqrtRatioX128 = JSBI.leftShift(sqrtRatioX96, JSBI.BigInt(32)) - - const msb = this.mostSignificantBit(sqrtRatioX128) - - let r: JSBI - if (JSBI.greaterThanOrEqual(JSBI.BigInt(msb), JSBI.BigInt(128))) { - r = JSBI.signedRightShift(sqrtRatioX128, JSBI.BigInt(msb - 127)) - } else { - r = JSBI.leftShift(sqrtRatioX128, JSBI.BigInt(127 - msb)) - } - - let log_2: JSBI = JSBI.leftShift( - JSBI.subtract(JSBI.BigInt(msb), JSBI.BigInt(128)), - JSBI.BigInt(64) - ) - - for (let i = 0; i < 14; i++) { - r = JSBI.signedRightShift(JSBI.multiply(r, r), JSBI.BigInt(127)) - const f = JSBI.signedRightShift(r, JSBI.BigInt(128)) - log_2 = JSBI.bitwiseOr( - log_2, - JSBI.leftShift(f, JSBI.BigInt(63 - i)) - ) - r = JSBI.signedRightShift(r, f) - } - - const log_sqrt10001 = JSBI.multiply( - log_2, - JSBI.BigInt('255738958999603826347141') - ) - - const tickLow = JSBI.toNumber( - JSBI.signedRightShift( - JSBI.subtract( - log_sqrt10001, - JSBI.BigInt('3402992956809132418596140100660247210') - ), - JSBI.BigInt(128) - ) - ) - const tickHigh = JSBI.toNumber( - JSBI.signedRightShift( - JSBI.add( - log_sqrt10001, - JSBI.BigInt('291339464771989622907027621153398088495') - ), - JSBI.BigInt(128) - ) - ) - - return tickLow === tickHigh - ? tickLow - : JSBI.lessThanOrEqual( - TickMath.getSqrtRatioAtTick(tickHigh), - sqrtRatioX96 - ) - ? tickHigh - : tickLow - } - - private static mulShift(val: JSBI, mulBy: string): JSBI { - return JSBI.signedRightShift( - JSBI.multiply(val, JSBI.BigInt(mulBy)), - JSBI.BigInt(128) - ) - } - - private static mostSignificantBit(x: JSBI): number { - const TWO = JSBI.BigInt(2) - const POWERS_OF_2 = [128, 64, 32, 16, 8, 4, 2, 1].map((pow: number): [ - number, - JSBI - ] => [pow, JSBI.exponentiate(TWO, JSBI.BigInt(pow))]) - - let msb: number = 0 - for (const [power, min] of POWERS_OF_2) { - if (JSBI.greaterThanOrEqual(x, min)) { - x = JSBI.signedRightShift(x, JSBI.BigInt(power)) - msb += power - } - } - return msb - } -} - -export { TwoTrancheUniV3ManagerMath, TickMath } diff --git a/src/services/api.ts b/src/services/api.ts index c392f6ec..c2db5982 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -1,10 +1,14 @@ import axios from 'axios' const fetchFiatPrice = async (token: string = 'ethereum') => { - const res = await axios.get( - `https://api.coingecko.com/api/v3/simple/price?ids=${token}&vs_currencies=usd&include_24hr_change=true` - ) - return res.data[token] + try { + const res = await axios.get( + `https://api.coingecko.com/api/v3/simple/price?ids=${token}&vs_currencies=usd&include_24hr_change=true` + ) + return res.data[token] + } catch (error) { + console.log(error) + } } const api = { diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 77c57af0..9bdbc874 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers' import { Geb } from 'geb.js' import { css } from 'styled-components' import { injected, walletconnect, walletlink } from '../connectors' -import { constructSameAddressMap } from './constructSameAddressMap' +import { SupportedChainId } from './chains' import { ChainId, WalletInfo } from './interfaces' type AddressMap = { [chainId: number]: string } @@ -18,10 +18,8 @@ const { } = process.env export const MULTICALL2_ADDRESSES: AddressMap = { - ...constructSameAddressMap( - '0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696', - false - ), + [SupportedChainId.MAINNET]: '0x51812e07497586ce025D798Bb44b6d11bBEe3a01', + [SupportedChainId.KOVAN]: '0x551283ecB1257B5aE0A4b2DFe42e06E5F29b8068', } export enum Network { diff --git a/src/utils/constructSameAddressMap.ts b/src/utils/constructSameAddressMap.ts deleted file mode 100644 index ffa6e917..00000000 --- a/src/utils/constructSameAddressMap.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SupportedChainId } from './chains' - -export function constructSameAddressMap( - address: T, - includeArbitrum: boolean -): { [chainId: number]: T } { - if (includeArbitrum) - return { - [SupportedChainId.MAINNET]: address, - [SupportedChainId.ROPSTEN]: address, - [SupportedChainId.RINKEBY]: address, - [SupportedChainId.GOERLI]: address, - [SupportedChainId.KOVAN]: address, - [SupportedChainId.ARBITRUM_ONE]: address, - } - return { - [SupportedChainId.MAINNET]: address, - [SupportedChainId.ROPSTEN]: address, - [SupportedChainId.RINKEBY]: address, - [SupportedChainId.GOERLI]: address, - [SupportedChainId.KOVAN]: address, - } -}