-
Notifications
You must be signed in to change notification settings - Fork 202
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: add custom gas token e2e tests #1960
Changes from 81 commits
8c26fad
d58b2e8
591f930
b882660
60a0f25
56ff3a2
803da84
9ae9435
a664e54
6972d52
ed7b34d
d2eca87
3c84690
d2e18e2
d313756
12a2270
8283fdd
a4c18a5
65918a4
4886113
37a7ef1
067b64c
bc2c217
59575c8
b4b650f
05f2bbd
9b5ca65
9b7e665
3125d8e
f28912a
52eb29e
1053116
ecd415d
3f3b88d
e7583be
83d290a
25dfa4c
f9f632c
ebb974f
84f1d2e
d021e89
39dd637
b3a797d
bbf4134
b02242c
30ee752
a7eb5e9
10a11ae
5dba15f
6a2962f
ae8ee3f
57b7063
7e575ce
ff9704c
f5d180f
23b4c73
07a25fc
d72ee4d
4cdd228
ef46573
c67dcd5
2caaf94
89004d1
1376bbd
b9f89f7
3a83629
01a7d8e
3bb3308
c5bd311
5de44b6
c1c1d4f
9200dbe
d12583b
e1e8c5a
8010212
7a0a6e9
c85a086
a0d7974
c3e86de
18c66d2
76987d6
816c3e0
eb14269
702f391
4f040ff
a3ab216
5837521
05d02e4
50cf4f4
f08047e
d7e0104
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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: | ||
|
@@ -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' || '' }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unrelated to this line - but we must update the README.md to have the instructions to setup testnode for Custom native token' E2Es. ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated |
||
|
||
- 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' | ||
dewanshparashar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}} | ||
wait-on: http://127.0.0.1:3000 | ||
wait-on-timeout: 120 | ||
spec: ./packages/arb-token-bridge-ui/tests/e2e/specs/* | ||
|
@@ -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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Register local network is async now so we do it when importing the component. See |
||
process.env.NODE_ENV !== 'production' || | ||
process.env.NEXT_PUBLIC_IS_E2E_TEST | ||
) { | ||
registerLocalNetwork() | ||
} | ||
|
||
dayjs.extend(utc) | ||
dayjs.extend(relativeTime) | ||
dayjs.extend(timeZone) | ||
|
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' | ||
|
@@ -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' | ||
|
@@ -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() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because it's async we do it before rendering the component |
||
} | ||
|
||
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: { | ||
|
@@ -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) | ||
|
@@ -103,6 +121,12 @@ export function getServerSideProps({ | |
} | ||
} | ||
|
||
if ( | ||
process.env.NODE_ENV !== 'production' || | ||
process.env.NEXT_PUBLIC_IS_E2E_TEST | ||
) { | ||
await registerLocalNetwork() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to register networks so that it recognises L3 local and doesn't change the chain to default There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to do this twice - once while importing the component, and once during server side generation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need it server side to recognize local networks and correctly sanitize network pairs, and we need it in UI so we add them when importing the component |
||
} | ||
// it's necessary to call this before sanitization to make sure all chains are registered | ||
addOrbitChainsToArbitrumSDK() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import { StaticJsonRpcProvider } from '@ethersproject/providers' | ||
import { | ||
ArbitrumNetwork, | ||
getChildrenForNetwork, | ||
|
@@ -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 | ||
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same issue as with other local chains, different address in CI |
||
? '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' | ||
|
@@ -398,14 +436,34 @@ export const localL3NetworkRpcUrl = loadEnvironmentVariableWithFallback({ | |
fallback: 'http://127.0.0.1:3347' | ||
}) | ||
|
||
export function registerLocalNetwork() { | ||
export async function registerLocalNetwork(isLocalCustomNativeToken?: boolean) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We fetch native token to see if it exists, this way we know it's a custom native token local chain. But we also need a way to specify it e.g. in e2e synpress setup because then fetching the token will fail |
||
try { | ||
rpcURLs[defaultL1Network.chainId] = localL1NetworkRpcUrl | ||
rpcURLs[defaultL2Network.chainId] = localL2NetworkRpcUrl | ||
rpcURLs[defaultL3Network.chainId] = localL3NetworkRpcUrl | ||
|
||
registerCustomArbitrumNetwork(defaultL2Network) | ||
registerCustomArbitrumNetwork(defaultL3Network) | ||
|
||
if (typeof isLocalCustomNativeToken === 'undefined') { | ||
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}`) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a newer tag that funds the wallet with native currency on L2. You can see the change here:
OffchainLabs/nitro-testnode@badbcbe