Skip to content

Commit

Permalink
test: add custom gas token e2e tests (#1960)
Browse files Browse the repository at this point in the history
  • Loading branch information
brtkx authored Oct 22, 2024
1 parent 0654a93 commit 5730043
Show file tree
Hide file tree
Showing 24 changed files with 624 additions and 287 deletions.
19 changes: 13 additions & 6 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
run: echo "e2eFiles=$(node .github/workflows/formatSpecfiles.js ${{ inputs.test_type }} | jq . --compact-output)" >> $GITHUB_OUTPUT

test-e2e:
name: "Test E2E - ${{ matrix.test.name }}${{ matrix.test.type == 'orbit' && ' with L3' || ''}}"
name: "${{ matrix.test.name }}${{ matrix.test.type == 'orbit-eth' && ' with L3' || matrix.test.type == 'orbit-custom' && ' with custom fee token' || ''}}"
needs: [load-e2e-files]
runs-on: ubuntu-latest
strategy:
Expand Down Expand Up @@ -91,15 +91,22 @@ jobs:
if: inputs.test_type != 'cctp'
uses: OffchainLabs/actions/run-nitro-test-node@a20a76172ce524832ac897bef2fa10a62ed81c29
with:
nitro-testnode-ref: aab133aceadec2e622f15fa438f6327e3165392d
l3-node: ${{ matrix.test.type == 'orbit' }}
no-l3-token-bridge: ${{ matrix.test.type != 'orbit' }}
nitro-testnode-ref: badbcbea9b43d46e115da4d7c9f2f57c31af8431
l3-node: ${{ matrix.test.type != 'regular' }}
no-l3-token-bridge: ${{ matrix.test.type == 'regular' }}
args: ${{ matrix.test.type == 'orbit-custom' && '--l3-fee-token' || '' }}

- name: Run e2e tests via cypress-io/github-action
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # [email protected]
with:
start: yarn start
command: "yarn test:e2e${{ (matrix.test.type == 'cctp' && ':cctp') || (matrix.test.type == 'orbit' && ':orbit') || '' }} --browser chrome"
command: >-
${{
(matrix.test.type == 'orbit-eth') && 'yarn test:e2e:orbit --browser chrome' ||
(matrix.test.type == 'orbit-custom' && 'yarn test:e2e:orbit:custom-gas-token --browser chrome') ||
(matrix.test.type == 'cctp' && 'yarn test:e2e:cctp --browser chrome') ||
'yarn test:e2e --browser chrome'
}}
wait-on: http://127.0.0.1:3000
wait-on-timeout: 120
spec: ./packages/arb-token-bridge-ui/tests/e2e/specs/*
Expand All @@ -121,7 +128,7 @@ jobs:
uses: actions/upload-artifact@v4
if: always()
with:
name: e2e-artifacts-${{ github.sha }}-${{ matrix.test.name }}-${{ (matrix.test.type == 'cctp' && 'cctp') || (matrix.test.type == 'orbit' && 'l3') || 'regular'}}
name: e2e-artifacts-${{ github.sha }}-${{ matrix.test.name }}-${{ (matrix.test.type == 'cctp' && 'cctp') || (matrix.test.type == 'orbit-eth' && 'l3') || (matrix.test.type == 'orbit-custom' && 'custom-fee-token') || 'regular'}}
path: |
./packages/arb-token-bridge-ui/cypress/videos
./packages/arb-token-bridge-ui/cypress/screenshots
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/formatSpecfiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ switch (testType) {
});
tests.push({
...spec,
type: "orbit",
type: "orbit-eth",
});
tests.push({
...spec,
type: "orbit-custom",
});
});
break;
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ It is important for any code change to pass both unit and end-to-end tests. This
./test-node.bash --init --no-simple --tokenbridge --l3node --l3-token-bridge
```

To run with a custom fee token also include the following flags:

```bash
--l3-fee-token --l3-fee-token-decimals 18
```

2. When the Nitro test-node is up and running you should see logs like `sequencer_1` and `staker-unsafe_1` in the terminal. This can take up to 10 minutes.

2. At the root of the token bridge UI:
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"lint:fix": "yarn workspace arb-token-bridge-ui lint:fix",
"test:e2e": "yarn workspace arb-token-bridge-ui env-cmd --silent --file .e2e.env yarn synpress run --configFile synpress.config.ts",
"test:e2e:cctp": "yarn test:e2e --configFile synpress.cctp.config.ts",
"test:e2e:orbit": "E2E_ORBIT=true yarn test:e2e"
"test:e2e:orbit": "E2E_ORBIT=true yarn test:e2e",
"test:e2e:orbit:custom-gas-token": "E2E_ORBIT_CUSTOM_GAS_TOKEN=true yarn test:e2e"
},
"resolutions": {
"**/@walletconnect/ethereum-provider": "2.13.1",
Expand Down
8 changes: 0 additions & 8 deletions packages/arb-token-bridge-ui/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,13 @@ import 'tippy.js/themes/light.css'

import '@rainbow-me/rainbowkit/styles.css'

import { registerLocalNetwork } from '../util/networks'
import { Layout } from '../components/common/Layout'
import { siteTitle } from './_document'

import '../styles/tailwind.css'
import '../styles/purple.css'
import { isUserRejectedError } from '../util/isUserRejectedError'

if (
process.env.NODE_ENV !== 'production' ||
process.env.NEXT_PUBLIC_IS_E2E_TEST
) {
registerLocalNetwork()
}

dayjs.extend(utc)
dayjs.extend(relativeTime)
dayjs.extend(timeZone)
Expand Down
54 changes: 39 additions & 15 deletions packages/arb-token-bridge-ui/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect } from 'react'
import React, { ComponentType, useEffect } from 'react'
import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'
import dynamic from 'next/dynamic'
import { decodeString, encodeString } from 'use-query-params'
Expand All @@ -7,7 +7,8 @@ import { registerCustomArbitrumNetwork } from '@arbitrum/sdk'
import { Loader } from '../components/common/atoms/Loader'
import {
getCustomChainsFromLocalStorage,
mapCustomChainToNetworkData
mapCustomChainToNetworkData,
registerLocalNetwork
} from '../util/networks'
import { getOrbitChains } from '../util/orbitChainsList'
import { sanitizeQueryParams } from '../hooks/useNetworks'
Expand All @@ -17,17 +18,32 @@ import {
} from '../hooks/useArbQueryParams'
import { sanitizeExperimentalFeaturesQueryParam } from '../util'

const App = dynamic(() => import('../components/App/App'), {
ssr: false,
loading: () => (
<>
<div className="h-12 w-full lg:h-16" />
<div className="fixed inset-0 m-auto h-[44px] w-[44px]">
<Loader size="large" color="white" />
</div>
</>
)
})
const App = dynamic(
() => {
return new Promise<{ default: ComponentType }>(async resolve => {
if (
process.env.NODE_ENV !== 'production' ||
process.env.NEXT_PUBLIC_IS_E2E_TEST
) {
await registerLocalNetwork()
}

const AppComponent = await import('../components/App/App')
resolve(AppComponent)
})
},
{
ssr: false,
loading: () => (
<>
<div className="h-12 w-full lg:h-16" />
<div className="fixed inset-0 m-auto h-[44px] w-[44px]">
<Loader size="large" color="white" />
</div>
</>
)
}
)

function getDestinationWithSanitizedQueryParams(
sanitized: {
Expand Down Expand Up @@ -89,9 +105,11 @@ function addOrbitChainsToArbitrumSDK() {
)
}

export function getServerSideProps({
export async function getServerSideProps({
query
}: GetServerSidePropsContext): GetServerSidePropsResult<Record<string, never>> {
}: GetServerSidePropsContext): Promise<
GetServerSidePropsResult<Record<string, never>>
> {
const sourceChainId = decodeChainQueryParam(query.sourceChain)
const destinationChainId = decodeChainQueryParam(query.destinationChain)
const experiments = decodeString(query.experiments)
Expand All @@ -103,6 +121,12 @@ export function getServerSideProps({
}
}

if (
process.env.NODE_ENV !== 'production' ||
process.env.NEXT_PUBLIC_IS_E2E_TEST
) {
await registerLocalNetwork()
}
// it's necessary to call this before sanitization to make sure all chains are registered
addOrbitChainsToArbitrumSDK()

Expand Down
7 changes: 7 additions & 0 deletions packages/arb-token-bridge-ui/src/util/TokenUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ function getErc20DataCache(params: GetErc20DataCacheParams): Erc20Data | null
function getErc20DataCache(
params?: GetErc20DataCacheParams
): Erc20DataCache | (Erc20Data | null) {
if (
typeof window === 'undefined' ||
typeof window.localStorage === 'undefined'
) {
return null
}

const cache: Erc20DataCache = JSON.parse(
// intentionally using || instead of ?? for it to work with an empty string
localStorage.getItem(erc20DataCacheLocalStorageKey) || '{}'
Expand Down
62 changes: 60 additions & 2 deletions packages/arb-token-bridge-ui/src/util/networks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { StaticJsonRpcProvider } from '@ethersproject/providers'
import {
ArbitrumNetwork,
getChildrenForNetwork,
Expand All @@ -9,6 +10,7 @@ import {
import { loadEnvironmentVariableWithFallback } from './index'
import { getBridgeUiConfigForChain } from './bridgeUiConfig'
import { chainIdToInfuraUrl } from './infura'
import { fetchErc20Data } from './TokenUtils'

export enum ChainId {
// L1
Expand Down Expand Up @@ -385,6 +387,42 @@ export const defaultL3Network: ArbitrumNetwork = {
}
}

export const defaultL3CustomGasTokenNetwork: ArbitrumNetwork = {
chainId: 333333,
parentChainId: ChainId.ArbitrumLocal,
confirmPeriodBlocks: 20,
ethBridge: {
bridge: '0xA584795e24628D9c067A6480b033C9E96281fcA3',
inbox: '0xDcA690902d3154886Ec259308258D10EA5450996',
outbox: '0xda243bD61B011024FC923164db75Dde198AC6175',
rollup: process.env.NEXT_PUBLIC_IS_E2E_TEST
? '0x17d70d77AAEe46ACDF8b87BB2f085f36f63eC638'
: '0x7a23F33C1C384eFc11b8Cf207420c464ba2959CC',
sequencerInbox: '0x16c54EE2015CD824415c2077F4103f444E00A8cb'
},
nativeToken: '0xE069078bA9ACCE4eeAE609d8754515Cf13dd6706',
isCustom: true,
isTestnet: true,
name: 'L3 Local',
retryableLifetimeSeconds: 604800,
tokenBridge: {
parentCustomGateway: '0xCe02eA568090ae7d5184B0a98df90f6aa69C1552',
parentErc20Gateway: '0x59156b0596689D965Ba707E160e5370AF22461a0',
parentGatewayRouter: '0x0C085152C2799834fc1603533ff6916fa1FdA302',
parentMultiCall: '0x20a3627Dcc53756E38aE3F92717DE9B23617b422',
parentProxyAdmin: '0x1A61102c26ad3f64bA715B444C93388491fd8E68',
parentWeth: '0xA1abD387192e3bb4e84D3109181F9f005aBaF5CA',
parentWethGateway: '0x59156b0596689D965Ba707E160e5370AF22461a0',
childCustomGateway: '0xD4816AeF8f85A3C1E01Cd071a81daD4fa941625f',
childErc20Gateway: '0xaa7d51aFFEeB32d99b1CB2fd6d81D7adA4a896e8',
childGatewayRouter: '0x8B6BC759226f8Fe687c8aD8Cc0DbF85E095e9297',
childMultiCall: '0x052B15c8Ff0544287AE689C4F2FC53A3905d7Db3',
childProxyAdmin: '0x36C56eC2CF3a3f53db9F01d0A5Ae84b36fb0A1e2',
childWeth: '0x0000000000000000000000000000000000000000',
childWethGateway: '0x0000000000000000000000000000000000000000'
}
}

export const localL1NetworkRpcUrl = loadEnvironmentVariableWithFallback({
env: process.env.NEXT_PUBLIC_LOCAL_ETHEREUM_RPC_URL,
fallback: 'http://127.0.0.1:8545'
Expand All @@ -398,14 +436,34 @@ export const localL3NetworkRpcUrl = loadEnvironmentVariableWithFallback({
fallback: 'http://127.0.0.1:3347'
})

export function registerLocalNetwork() {
export async function registerLocalNetwork() {
try {
rpcURLs[defaultL1Network.chainId] = localL1NetworkRpcUrl
rpcURLs[defaultL2Network.chainId] = localL2NetworkRpcUrl
rpcURLs[defaultL3Network.chainId] = localL3NetworkRpcUrl

registerCustomArbitrumNetwork(defaultL2Network)
registerCustomArbitrumNetwork(defaultL3Network)

let isLocalCustomNativeToken = false

try {
const data = await fetchErc20Data({
address: defaultL3CustomGasTokenNetwork.nativeToken!,
provider: new StaticJsonRpcProvider(localL2NetworkRpcUrl)
})
if (data.symbol === 'TN') {
isLocalCustomNativeToken = true
}
} catch (e) {
// not the native token
isLocalCustomNativeToken = false
}

registerCustomArbitrumNetwork(
isLocalCustomNativeToken
? defaultL3CustomGasTokenNetwork
: defaultL3Network
)
} catch (error: any) {
console.error(`Failed to register local network: ${error.message}`)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@ import { ChainId, ChainWithRpcUrl, explorerUrls, rpcURLs } from '../networks'
import { getBridgeUiConfigForChain } from '../bridgeUiConfig'

export function chainToWagmiChain(chain: ChainWithRpcUrl): Chain {
const { nativeTokenData } = getBridgeUiConfigForChain(chain.chainId)
let { nativeTokenData } = getBridgeUiConfigForChain(chain.chainId)

if (chain.chainId === ChainId.L3Local) {
nativeTokenData = chain.nativeToken
? {
name: 'testnode',
symbol: 'TN',
decimals: 18
}
: ether
}

return {
id: chain.chainId,
Expand Down
Loading

0 comments on commit 5730043

Please sign in to comment.