Skip to content
This repository has been archived by the owner on Jun 24, 2022. It is now read-only.

Commit

Permalink
Merge branch 'develop' into claim
Browse files Browse the repository at this point in the history
  • Loading branch information
anxolin committed Jan 12, 2022
2 parents be65cac + 4b174aa commit 5d7aa61
Show file tree
Hide file tree
Showing 474 changed files with 31,055 additions and 12,105 deletions.
16 changes: 8 additions & 8 deletions .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,18 @@ REACT_APP_PATH_REGEX_ENS="/ipfs"
#REACT_APP_SENTRY_AUTH_TOKEN='<sentry_auth_token>'

# API
#REACT_APP_API_URL_PROD_MAINNET=https://protocol-mainnet.gnosis.io/api
#REACT_APP_API_URL_PROD_RINKEBY=https://protocol-rinkeby.gnosis.io/api
#REACT_APP_API_URL_PROD_XDAI=https://protocol-xdai.gnosis.io/api
#REACT_APP_API_URL_STAGING_MAINNET=https://protocol-mainnet.dev.gnosisdev.com/api
#REACT_APP_API_URL_STAGING_RINKEBY=https://protocol-rinkeby.dev.gnosisdev.com/api
#REACT_APP_API_URL_STAGING_XDAI=https://protocol-xdai.dev.gnosisdev.com/api
#REACT_APP_API_URL_PROD_MAINNET=https://api.cow.fi/mainnet/api
#REACT_APP_API_URL_PROD_RINKEBY=https://api.cow.fi/rinkeby/api
#REACT_APP_API_URL_PROD_XDAI=https://api.cow.fi/xdai/api
#REACT_APP_API_URL_STAGING_MAINNET=https://barn.api.cow.fi/mainnet/api
#REACT_APP_API_URL_STAGING_RINKEBY=https://barn.api.cow.fi/rinkeby/api
#REACT_APP_API_URL_STAGING_XDAI=https://barn.api.cow.fi/xdai/api

# EXPLORER
#REACT_APP_EXPLORER_URL_DEV=https://protocol-explorer.dev.gnosisdev.com
#REACT_APP_EXPLORER_URL_STAGING=https://protocol-explorer.staging.gnosisdev.com
#REACT_APP_EXPLORER_URL_PROD=https://gnosis-protocol.io
#REACT_APP_EXPLORER_URL_BARN=https://barn.gnosis-protocol.io
#REACT_APP_EXPLORER_URL_PROD=https://explorer.cow.fi
#REACT_APP_EXPLORER_URL_BARN=https://barn.explorer.cow.fi

# Enables mock mode (default = false)
REACT_APP_MOCK=false
23 changes: 22 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,33 @@
"error",
{
"paths": [
{
"name": "lodash",
"message": "Please import from 'lodash/module' directly to support tree-shaking."
},
{
"name": "ethers",
"message": "Please import from '@ethersproject/module' directly to support tree-shaking."
},
{
"name": "styled-components",
"message": "Please import from styled-components/macro."
},
{
"name": "@lingui/macro",
"importNames": ["t"],
"message": "Please use <Trans> instead of t."
}
],
"patterns": ["!styled-components/macro"]
"patterns": [
{
"group": ["**/dist"],
"message": "Do not import from dist/ - this is an implementation detail, and breaks tree-shaking."
},
{
"group": ["!styled-components/macro"]
}
]
}
]
}
Expand Down
1 change: 1 addition & 0 deletions .github/uniswap-original/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
jobs:
run-linters:
name: Run linters
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.repository_owner }}
runs-on: ubuntu-latest

steps:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
# production
/build

# bundle
/dist

# misc
.DS_Store
.env.local
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ It allows you to buy and sell tokens using gas-less orders that are settled peer
- ENS Website (alternative): <https://cowswap.eth.link>, or <https://cowswap.eth/> if you have MetaMask or an ENS compatible browser.
- The website can also be run locally, or from IPFS. Every release will have an IPFS hash associated, available in the [Releases](https://github.com/gnosis/gp-swap-ui/releases) section.

- Docs: <https://docs.cowswap.exchange>
- Docs: <https://docs.cow.fi>
- Stats: <https://dune.xyz/gnosis.protocol/Gnosis-Protocol-V2>
- Twitter: [@gnosisPM](https://twitter.com/gnosisPM)
- Reddit: [/r/gnosisPM](https://www.reddit.com/r/gnosisPM)
Expand Down Expand Up @@ -72,6 +72,14 @@ yarn start:default
yarn cypress
```

### Run cosmos

This will start a server on the `http://localhost:5000/`

```bash
yarn run cosmos
```

## Configuring the environment (optional)

The app has some default configuration, but it's highly encouraged to define your own.
Expand Down
7 changes: 7 additions & 0 deletions cosmos.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"staticPath": "public",
"watchDirs": ["src"],
"webpack": {
"configPath": "./cosmos.webpack.config"
}
}
6 changes: 6 additions & 0 deletions cosmos.webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { createWebpackDevConfig } = require('@craco/craco')
const cracoConfig = require('./craco.config.js')
const webpackConfig = createWebpackDevConfig(cracoConfig)

module.exports = webpackConfig
48 changes: 23 additions & 25 deletions craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,30 @@ if (SENTRY_AUTH_TOKEN) {
)
}

module.exports = function () {
return {
babel: {
plugins: [
'@babel/plugin-proposal-nullish-coalescing-operator',
[
'@simbathesailor/babel-plugin-use-what-changed',
{
active: process.env.NODE_ENV === 'development', // boolean
},
],
module.exports = {
babel: {
plugins: [
'@babel/plugin-proposal-nullish-coalescing-operator',
[
'@simbathesailor/babel-plugin-use-what-changed',
{
active: process.env.NODE_ENV === 'development', // boolean
},
],
],
},
webpack: {
plugins,
alias: {
'@src': path.resolve(__dirname, 'src'),
},
webpack: {
plugins,
alias: {
'@src': path.resolve(__dirname, 'src'),
// https://webpack.js.org/configuration
configure: (webpackConfig) => ({
...webpackConfig,
resolve: {
...webpackConfig.resolve,
modules: [path.resolve(__dirname, 'src/custom'), ...webpackConfig.resolve.modules],
},
// https://webpack.js.org/configuration
configure: (webpackConfig) => ({
...webpackConfig,
resolve: {
...webpackConfig.resolve,
modules: [path.resolve(__dirname, 'src/custom'), ...webpackConfig.resolve.modules],
},
}),
},
}
}),
},
}
96 changes: 59 additions & 37 deletions cypress-custom/integration/fee.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
import { WETH9 as WETH } from '@uniswap/sdk-core'
import { OrderKind } from '@gnosis.pm/gp-v2-contracts'
import { FeeQuoteParams, FeeInformation } from '../../src/custom/utils/price'
import { GetQuoteResponse } from '@gnosis.pm/gp-v2-contracts'
import { parseUnits } from 'ethers/lib/utils'

const DAI = '0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735'
const FOUR_HOURS = 3600 * 4 * 1000
const DEFAULT_SELL_TOKEN = WETH[4]
const DEFAULT_APP_DATA = '0x0000000000000000000000000000000000000000000000000000000000000000'
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'

const FEE_QUERY = `https://barn.api.cow.fi/rinkeby/api/v1/quote`

const baseParams = {
from: ZERO_ADDRESS,
receiver: ZERO_ADDRESS,
validTo: Math.ceil(Date.now() / 1000 + 500),
appData: DEFAULT_APP_DATA,
sellTokenBalance: 'erc20',
buyTokenBalance: 'erc20',
partiallyFillable: false,
}

const getFeeQuery = ({ sellToken, buyToken, amount, kind }: Omit<FeeQuoteParams, 'chainId'>) =>
`https://protocol-rinkeby.dev.gnosisdev.com/api/v1/fee?sellToken=${sellToken}&buyToken=${buyToken}&amount=${amount}&kind=${kind}`
const mockQuoteResponse = {
quote: {
// arb props here..
sellToken: '0x6810e776880c02933d47db1b9fc05908e5386b96',
buyToken: '0x6810e776880c02933d47db1b9fc05908e5386b96',
receiver: '0x6810e776880c02933d47db1b9fc05908e5386b96',
sellAmount: '1234567890',
buyAmount: '1234567890',
validTo: 0,
appData: '0x0000000000000000000000000000000000000000000000000000000000000000',
feeAmount: '1234567890',
kind: 'buy',
partiallyFillable: true,
sellTokenBalance: 'erc20',
buyTokenBalance: 'erc20',
},
from: ZERO_ADDRESS,
}

function _assertFeeData(fee: FeeInformation | string): void {
function _assertFeeData(fee: GetQuoteResponse): void {
if (typeof fee === 'string') {
fee = JSON.parse(fee)
}
expect(fee).to.have.property('amount')
expect(fee).to.have.property('expirationDate')
expect(fee).to.have.property('quote')
expect(fee).to.have.property('expiration')
expect(fee.quote).to.have.property('feeAmount')
}

/* Fee not currently being saved in local so commenting this out
Expand Down Expand Up @@ -54,18 +84,25 @@ function _assertFeeFetched(token: string): Cypress.Chainable {

describe('Fee endpoint', () => {
it('Returns the expected info', () => {
const FEE_QUERY = getFeeQuery({
const params = {
sellToken: DEFAULT_SELL_TOKEN.address,
buyToken: DAI,
amount: parseUnits('0.1', DEFAULT_SELL_TOKEN.decimals).toString(),
kind: OrderKind.SELL,
sellAmountBeforeFee: parseUnits('0.1', DEFAULT_SELL_TOKEN.decimals).toString(),
kind: 'sell',
fromDecimals: DEFAULT_SELL_TOKEN.decimals,
toDecimals: 6,
})
// BASE PARAMS
...baseParams,
}

// GIVEN: -
// WHEN: Call fee API
cy.request(FEE_QUERY)
cy.request({
method: 'POST',
url: FEE_QUERY,
body: params,
log: true,
})
.its('body')
// THEN: The API response has the expected data
.should(_assertFeeData)
Expand All @@ -74,27 +111,19 @@ describe('Fee endpoint', () => {

describe('Fee: Complex fetch and persist fee', () => {
const INPUT_AMOUNT = '0.1'
const FEE_QUERY = getFeeQuery({
sellToken: DEFAULT_SELL_TOKEN.address,
buyToken: DAI,
amount: parseUnits(INPUT_AMOUNT, DEFAULT_SELL_TOKEN.decimals).toString(),
kind: OrderKind.SELL,
fromDecimals: DEFAULT_SELL_TOKEN.decimals,
toDecimals: 6,
})

// Needs to run first to pass because of Cypress async issues between tests
it('Re-fetched when it expires', () => {
// GIVEN: input token Fee expiration is always 6 hours from now
const SIX_HOURS = FOUR_HOURS * 1.5
const LATER_TIME = new Date(Date.now() + SIX_HOURS).toISOString()
const LATER_FEE = {
expirationDate: LATER_TIME,
amount: '0',
...mockQuoteResponse,
expiration: LATER_TIME,
}

// only override Date functions (default is to override all time based functions)
cy.stubResponse({ url: FEE_QUERY, alias: 'feeRequest', body: LATER_FEE })
cy.stubResponse({ method: 'POST', url: FEE_QUERY, alias: 'feeRequest', body: LATER_FEE })

// GIVEN: user visits app, selects 0.1 WETH as sell, DAI as buy
// and goes AFK
Expand All @@ -116,36 +145,29 @@ describe('Fee: Complex fetch and persist fee', () => {
const mockedTime = new Date($clock.details().now)

// THEN: fee time is properly stubbed and
expect(body.expirationDate).to.equal(LATER_TIME)
expect(body.expiration).to.equal(LATER_TIME)
// THEN: the mocked later date is indeed less than the new fee (read: the fee is valid)
expect(new Date(body.expirationDate)).to.be.greaterThan(mockedTime)
expect(new Date(body.expiration)).to.be.greaterThan(mockedTime)
})
})
})
})

describe('Fee: simple checks it exists', () => {
const INPUT_AMOUNT = '0.1'
const FEE_QUERY = getFeeQuery({
sellToken: DEFAULT_SELL_TOKEN.address,
buyToken: DAI,
amount: parseUnits(INPUT_AMOUNT, DEFAULT_SELL_TOKEN.decimals).toString(),
kind: OrderKind.SELL,
fromDecimals: DEFAULT_SELL_TOKEN.decimals,
toDecimals: 6,
})
const FEE_RESP = {
const QUOTE_RESP = {
...mockQuoteResponse,
// 1 min in future
expirationDate: new Date(Date.now() + 60000).toISOString(),
amount: parseUnits('0.05', DEFAULT_SELL_TOKEN.decimals).toString(),
expiration: new Date(Date.now() + 60000).toISOString(),
}

it('Fetch fee when selecting both tokens', () => {
// Stub responses from fee endpoint
cy.stubResponse({
method: 'POST',
url: FEE_QUERY,
alias: 'feeRequest',
body: FEE_RESP,
body: QUOTE_RESP,
})
// GIVEN: A user loads the swap page
// WHEN: Select DAI token as output and sells 0.1 WETH
Expand Down
12 changes: 11 additions & 1 deletion cypress-custom/support/commands.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ declare namespace Cypress {
*
* @example cy.stubResponse({ url: '/api/v1/someEndpoint/', alias: 'endpoint', body: { foo: 'foo' } })
*/
stubResponse({ url, alias, body }: { url: string; alias?: string; body?: any }): Chainable<Subject>
stubResponse({
method,
url,
alias,
body,
}: {
method: 'GET' | 'POST' | 'DELETE'
url: string
alias?: string
body?: any
}): Chainable<Subject>
}
}
4 changes: 2 additions & 2 deletions cypress-custom/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ function enterOutputAmount(tokenAddress, amount, selectToken = false) {
cy.get('#swap-currency-input .token-amount-output').type(amount.toString(), { force: true, delay: 400 })
}

function stubResponse({ url, alias = 'stubbedResponse', body }) {
cy.intercept({ method: 'GET', url }, _responseHandlerFactory(body)).as(alias)
function stubResponse({ method, url, alias = 'stubbedResponse', body }) {
cy.intercept({ method, url }, _responseHandlerFactory(body)).as(alias)
}

Cypress.Commands.add('swapClickInputToken', () => clickInputToken)
Expand Down
1 change: 1 addition & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"projectId": "yp82ef",
"baseUrl": "http://localhost:3000",
"defaultCommandTimeout": 20000,
"pageLoadTimeout": 120000,
Expand Down
2 changes: 1 addition & 1 deletion cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
// https://on.cypress.io/custom-commands
// ***********************************************

import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'
import { JsonRpcProvider } from '@ethersproject/providers'
import { Wallet } from '@ethersproject/wallet'
import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'

// todo: figure out how env vars actually work in CI
// const TEST_PRIVATE_KEY = Cypress.env('INTEGRATION_TEST_PRIVATE_KEY')
Expand Down
Loading

0 comments on commit 5d7aa61

Please sign in to comment.