Skip to content

Commit

Permalink
fix: clearer actions, and wrap sleep in act (#28)
Browse files Browse the repository at this point in the history
* build: clean up actions

* fix: wrap sleep in act

* lint: lint more globally

* fix: actions

* lint: space at end of json
  • Loading branch information
zzmp authored Nov 9, 2022
1 parent 72ca822 commit 613da85
Show file tree
Hide file tree
Showing 11 changed files with 2,633 additions and 152 deletions.
23 changes: 5 additions & 18 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,16 @@ on:

jobs:
run-linters:
name: Run linters
name: Lint
runs-on: ubuntu-latest

steps:
- name: Check out Git repository
uses: actions/checkout@v2

- name: Set up node
uses: actions/setup-node@v2
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
registry-url: https://registry.npmjs.org

- name: Install dependencies
run: yarn install --frozen-lockfile
- run: yarn install --frozen-lockfile

- name: Run linter
- name: Lint
run: yarn lint

- name: Run linters
uses: wearerequired/lint-action@v1
with:
github_token: ${{ secrets.github_token }}
prettier: true
auto_fix: true
prettier_extensions: 'css,html,js,json,jsx,md,sass,scss,ts,tsx,vue,yaml,yml'
41 changes: 0 additions & 41 deletions .github/workflows/publish.yml

This file was deleted.

34 changes: 34 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Release
on:
# manual trigger
workflow_dispatch:

jobs:
deploy:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
registry-url: https://registry.npmjs.org

- run: yarn install --frozen-lockfile
- run: yarn postinstall
- run: yarn build

- run: yarn test
env:
INFURA_PROJECT_ID: ${{ secrets.INFURA_PROJECT_ID }}
INFURA_PROJECT_SECRET: ${{ secrets.INFURA_PROJECT_SECRET }}
- run: yarn test:e2e
env:
INFURA_PROJECT_ID: ${{ secrets.INFURA_PROJECT_ID }}
INFURA_PROJECT_SECRET: ${{ secrets.INFURA_PROJECT_SECRET }}

- run: yarn release
env:
NPM_CONFIG_USERCONFIG: /dev/null
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
27 changes: 12 additions & 15 deletions .github/workflows/unit-tests.yml → .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,27 @@ on:
jobs:
tests:
name: Tests

runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup node
uses: actions/setup-node@v2
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
registry-url: https://registry.npmjs.org

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Compile contracts
run: yarn contracts:compile
- run: yarn install --frozen-lockfile
- run: yarn postinstall
- run: yarn build

- name: Run tests
- name: Unit tests
run: yarn test
env:
INFURA_PROJECT_ID: ${{ secrets.INFURA_PROJECT_ID }}
INFURA_PROJECT_SECRET: ${{ secrets.INFURA_PROJECT_SECRET }}

- name: Run Build
run: yarn build
- name: Integration tests
run: yarn test:e2e
env:
INFURA_PROJECT_ID: ${{ secrets.INFURA_PROJECT_ID }}
INFURA_PROJECT_SECRET: ${{ secrets.INFURA_PROJECT_SECRET }}

15 changes: 15 additions & 0 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"branches": "main",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
[
"@semantic-release/git",
{
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
"@semantic-release/github",
"@semantic-release/npm"
]
}
16 changes: 9 additions & 7 deletions integration-tests/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import '@testing-library/jest-dom'
import { render, screen, waitFor } from '@testing-library/react'
import { act, render, screen, waitFor } from '@testing-library/react'
import { BigNumber } from '@ethersproject/bignumber'
import React from 'react'
import { App } from './App'
Expand All @@ -18,30 +18,32 @@ describe('Use multicall in test application', () => {

it('Performs a single contract multicall query', async () => {
render(<App />)

// Check that block timestamp is correctly retrieved from block
const timestamp1 = await waitFor(() => screen.getByTestId('blockTimestamp'), { timeout: 20_000 /* 20 seconds */ })
const timestamp1 = await waitFor(() => screen.getByTestId('blockTimestamp'), { timeout: 20_000 })
expect(timestamp1 && timestamp1?.textContent).toBeTruthy()
const value1 = parseInt(timestamp1.textContent!, 10) * 1000
const now1 = Date.now()
expect(now1 - value1).toBeLessThan(MAX_BLOCK_AGE)

// Wait for an updated block timestamp
await sleep(20_000 /* 20 seconds */)
await act(() => sleep(12_000))

// Check that the block timestamp has updated correctly
const timestamp2 = await waitFor(() => screen.getByTestId('blockTimestamp'), { timeout: 1_000 /* 1 second */ })
const timestamp2 = await waitFor(() => screen.getByTestId('blockTimestamp'), { timeout: 1_000 })
expect(timestamp2 && timestamp2.textContent).toBeTruthy()
const value2 = parseInt(timestamp1.textContent!, 10) * 1000
const now2 = Date.now()
expect(now2 - value2).toBeLessThan(MAX_BLOCK_AGE)
}, 50_000 /* 50 seconds */)
}, 35_000)

it('Performs a multi contract multicall query', async () => {
render(<App />)

// Check that max token balance is correctly retrieved
const balance = await waitFor(() => screen.getByTestId('maxTokenBalance'), { timeout: 20_000 /* 20 seconds */ })
const balance = await waitFor(() => screen.getByTestId('maxTokenBalance'), { timeout: 20_000 })
expect(balance && balance?.textContent).toBeTruthy()
const value1 = BigNumber.from(balance.textContent)
expect(value1.gt(0)).toBeTruthy()
}, 25_000 /* 25 seconds */)
}, 25_000)
})
30 changes: 13 additions & 17 deletions integration-tests/MultichainApp.test.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import '@testing-library/jest-dom'
import { act } from 'react-dom/test-utils'
import { render, screen, waitFor } from '@testing-library/react'
import { act, render, screen, waitFor } from '@testing-library/react'
import React from 'react'
import { MultichainApp } from './MultichainApp'
import { sleep } from './utils'

const MAX_BLOCK_AGE = 600_000 // 10 minutes

function parseTimestamp(value: string | null) {
if (!value) throw new Error('No timestamp to parse')
return value.split(',').map((v) => parseInt(v, 10) * 1000)
}

describe('Use multicall in test multichain application', () => {
it('Renders correctly initially', () => {
act(() => {
render(<MultichainApp />)
})
render(<MultichainApp />)
const h1 = screen.getByText('Hello Multichain Multicall') // H1 in Home
expect(h1).toBeTruthy()
const missing = screen.queryByText('Does Not Exist')
expect(missing).toBeFalsy()
})

it('Performs a multichain single contract multicall query', async () => {
act(() => {
render(<MultichainApp />)
})
render(<MultichainApp />)

// Check that block timestamp is correctly retrieved from block
const timestamps1 = await waitFor(() => screen.getByTestId('blockTimestamps'), { timeout: 20_000 /* 20 seconds */ })
const timestamps1 = await waitFor(() => screen.getByTestId('blockTimestamps'), { timeout: 20_000 })
expect(timestamps1 && timestamps1?.textContent).toBeTruthy()
const values1 = parseTimestamp(timestamps1.textContent)
const now1 = Date.now()
Expand All @@ -32,20 +33,15 @@ describe('Use multicall in test multichain application', () => {
expect(now1 - values1[1]).toBeLessThan(MAX_BLOCK_AGE)

// Wait for an updated block timestamp
await sleep(20_000 /* 20 seconds */)
await act(() => sleep(12_000))

// Check that the block timestamp has updated correctly
const timestamps2 = await waitFor(() => screen.getByTestId('blockTimestamps'), { timeout: 1_000 /* 1 second */ })
const timestamps2 = await waitFor(() => screen.getByTestId('blockTimestamps'), { timeout: 1_000 })
expect(timestamps2 && timestamps2.textContent).toBeTruthy()
const values2 = parseTimestamp(timestamps2.textContent)
const now2 = Date.now()
expect(values2.length).toEqual(2)
expect(now2 - values2[0]).toBeLessThan(MAX_BLOCK_AGE)
expect(now2 - values2[1]).toBeLessThan(MAX_BLOCK_AGE)
}, 50_000 /* 50 seconds */)
}, 35_000)
})

function parseTimestamp(value: string | null) {
if (!value) throw new Error('No timestamp to parse')
return value.split(',').map((v) => parseInt(v, 10) * 1000)
}
5 changes: 3 additions & 2 deletions integration-tests/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const ERC20Interface = new Interface(ERC20_ABI)
export function useContract(chainId: ChainId) {
return useMemo(() => {
return new Contract(MULTICALL_ADDRESS, MulticallABI, getProvider(chainId)) as UniswapInterfaceMulticall
}, [])
}, [chainId])
}

export function useLatestBlock(provider: JsonRpcProvider) {
Expand Down Expand Up @@ -63,7 +63,7 @@ export function useCurrentBlockTimestampMultichain(
result[chainId] = MULTICALL_ADDRESS
return result
}, {} as Record<number, string>)
}, [])
}, [chainIds])

const chainToCallState = useMultiChainSingleContractSingleData(
chainToBlock,
Expand All @@ -79,6 +79,7 @@ export function useMaxTokenBalance(chainId: ChainId, blockNumber: number | undef
const { contracts, accounts } = useMemo(
() => ({
// The first element is intentionally empty to test sparse arrays; see https://github.com/Uniswap/redux-multicall/pull/21.
// eslint-disable-next-line no-sparse-arrays
contracts: [, USDC_ADDRESS, USDT_ADDRESS, DAI_ADDRESS],
accounts: [NULL_ADDRESS],
}),
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export function sleep(milliseconds: number) {
return new Promise((resolve) => setTimeout(() => resolve(true), milliseconds))
export function sleep(milliseconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(() => resolve(undefined), milliseconds))
}
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@
"scripts": {
"contracts:compile": "typechain --target ethers-v5 --out-dir src/abi/types './node_modules/@uniswap/v3-periphery/artifacts/contracts/**/*Multicall*.json'",
"postinstall": "yarn contracts:compile",
"lint": "tsdx lint",
"test": "tsdx test --runInBand",
"lint": "tsdx lint .",
"test": "tsdx test src",
"test:e2e": "tsdx test integration-tests",
"build": "tsdx build",
"prepublishOnly": "tsdx build"
"prepublishOnly": "tsdx build",
"release": "semantic-release"
},
"devDependencies": {
"@ethersproject/abi": "5",
"@ethersproject/bignumber": "5",
"@ethersproject/contracts": "5",
"@ethersproject/providers": "5",
"@reduxjs/toolkit": "^1.6.2",
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
"@testing-library/jest-dom": "^5.15.1",
"@testing-library/react": "^12.1.2",
"@typechain/ethers-v5": "^7.2.0",
Expand All @@ -45,6 +49,7 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.5",
"semantic-release": "^19.0.5",
"tsdx": "^0.14.1",
"typechain": "^5.2.0"
},
Expand Down
Loading

0 comments on commit 613da85

Please sign in to comment.