Skip to content

Commit

Permalink
feat: add new linea mainnet network (#19326)
Browse files Browse the repository at this point in the history
* feat: add new linea mainnet network

* fix: removed unused condition + lint code

* fix: update tests + fix network tab issue

* feat: add feature toggle for linea mainnet

* fix: add feature toggle for linea mainnet

* feat: add linea mainnet logo

* update @metamask/eth-json-rpc-infura package to support linea networks

* update linea mainnet block explorer url

* fix: refactor linea mainnet feature toggle

* fix: update linea mainnet chain id and rpc url

* fix: update settings-search unit test

* fix: update linea mainnet feature flag

* fix: remove useless async function keyword for linea mainnet feature flag
  • Loading branch information
VGau authored Jun 16, 2023
1 parent 70d86ee commit e492339
Show file tree
Hide file tree
Showing 29 changed files with 175 additions and 18 deletions.
6 changes: 6 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added app/images/linea-logo-mainnet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions app/scripts/controllers/preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { setDashboardCookie } from '@metamask-institutional/portfolio-dashboard'
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network';
import { LedgerTransportTypes } from '../../../shared/constants/hardware-wallets';
import { ThemeType } from '../../../shared/constants/preferences';
import { shouldShowLineaMainnet } from '../../../shared/modules/network.utils';

export default class PreferencesController {
/**
Expand Down Expand Up @@ -69,6 +70,7 @@ export default class PreferencesController {
: LedgerTransportTypes.u2f,
transactionSecurityCheckEnabled: false,
theme: ThemeType.os,
isLineaMainnetReleased: false,
...opts.initState,
};

Expand All @@ -92,6 +94,8 @@ export default class PreferencesController {
global.setPreference = (key, value) => {
return this.setFeatureFlag(key, value);
};

this._showShouldLineaMainnetNetwork();
}
// PUBLIC METHODS

Expand Down Expand Up @@ -574,4 +578,12 @@ export default class PreferencesController {

this.store.updateState({ infuraBlocked: isBlocked });
}

/**
* A method to check is the linea mainnet network should be displayed
*/
_showShouldLineaMainnetNetwork() {
const showLineaMainnet = shouldShowLineaMainnet();
this.store.updateState({ isLineaMainnetReleased: showLineaMainnet });
}
}
3 changes: 2 additions & 1 deletion app/scripts/controllers/transactions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ export default class TransactionController extends EventEmitter {
if (
type !== NETWORK_TYPES.RPC &&
type !== NETWORK_TYPES.SEPOLIA &&
type !== NETWORK_TYPES.LINEA_GOERLI
type !== NETWORK_TYPES.LINEA_GOERLI &&
type !== NETWORK_TYPES.LINEA_MAINNET
) {
return new Common({
chain: type,
Expand Down
3 changes: 2 additions & 1 deletion development/states/navigate-txs.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@
"mainnet": "ok",
"goerli": "ok",
"sepolia": "ok",
"lineaGoerli": "ok"
"lineaGoerli": "ok",
"lineaMainnet": "ok"
}
},
"send": {
Expand Down
33 changes: 32 additions & 1 deletion shared/constants/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const NETWORK_TYPES = {
RPC: 'rpc',
SEPOLIA: 'sepolia',
LINEA_GOERLI: 'linea-goerli',
LINEA_MAINNET: 'linea-mainnet',
} as const;

/**
Expand All @@ -122,6 +123,7 @@ export const NETWORK_IDS = {
LOCALHOST: '1337',
SEPOLIA: '11155111',
LINEA_GOERLI: '59140',
LINEA_MAINNET: '59144',
} as const;

/**
Expand All @@ -148,6 +150,7 @@ export const CHAIN_IDS = {
PALM: '0x2a15c308d',
SEPOLIA: '0xaa36a7',
LINEA_GOERLI: '0xe704',
LINEA_MAINNET: '0xe708',
AURORA: '0x4e454152',
MOONBEAM: '0x504',
MOONBEAM_TESTNET: '0x507',
Expand All @@ -165,6 +168,7 @@ export const MAINNET_DISPLAY_NAME = 'Ethereum Mainnet';
export const GOERLI_DISPLAY_NAME = 'Goerli';
export const SEPOLIA_DISPLAY_NAME = 'Sepolia';
export const LINEA_GOERLI_DISPLAY_NAME = 'Linea Goerli';
export const LINEA_MAINNET_DISPLAY_NAME = 'Linea Mainnet';
export const LOCALHOST_DISPLAY_NAME = 'Localhost 8545';
export const BSC_DISPLAY_NAME = 'Binance Smart Chain';
export const POLYGON_DISPLAY_NAME = 'Polygon';
Expand Down Expand Up @@ -197,6 +201,9 @@ export const SEPOLIA_RPC_URL = getRpcUrl({ network: NETWORK_TYPES.SEPOLIA });
export const LINEA_GOERLI_RPC_URL = getRpcUrl({
network: NETWORK_TYPES.LINEA_GOERLI,
});
export const LINEA_MAINNET_RPC_URL = getRpcUrl({
network: NETWORK_TYPES.LINEA_MAINNET,
});
export const LOCALHOST_RPC_URL = 'http://localhost:8545';

/**
Expand Down Expand Up @@ -230,6 +237,7 @@ export const CURRENCY_SYMBOLS = {

export const ETH_TOKEN_IMAGE_URL = './images/eth_logo.png';
export const LINEA_GOERLI_TOKEN_IMAGE_URL = './images/linea-logo-testnet.png';
export const LINEA_MAINNET_TOKEN_IMAGE_URL = './images/linea-logo-mainnet.png';
export const TEST_ETH_TOKEN_IMAGE_URL = './images/black-eth-logo.svg';
export const BNB_TOKEN_IMAGE_URL = './images/bnb.png';
export const MATIC_TOKEN_IMAGE_URL = './images/matic-token.png';
Expand All @@ -247,6 +255,7 @@ export const INFURA_PROVIDER_TYPES = [
NETWORK_TYPES.GOERLI,
NETWORK_TYPES.SEPOLIA,
NETWORK_TYPES.LINEA_GOERLI,
NETWORK_TYPES.LINEA_MAINNET,
] as const;

export const TEST_CHAINS = [
Expand All @@ -260,7 +269,10 @@ const typedCapitalize = <K extends string>(k: K): Capitalize<K> =>
capitalize(k) as Capitalize<typeof k>;

export const TEST_NETWORK_TICKER_MAP: {
[K in Exclude<NetworkType, 'localhost' | 'mainnet' | 'rpc'>]: string;
[K in Exclude<
NetworkType,
'localhost' | 'mainnet' | 'rpc' | 'linea-mainnet'
>]: string;
} = {
[NETWORK_TYPES.GOERLI]: `${typedCapitalize(NETWORK_TYPES.GOERLI)}${
CURRENCY_SYMBOLS.ETH
Expand Down Expand Up @@ -298,6 +310,11 @@ export const BUILT_IN_NETWORKS = {
chainId: CHAIN_IDS.MAINNET,
blockExplorerUrl: `https://etherscan.io`,
},
[NETWORK_TYPES.LINEA_MAINNET]: {
networkId: NETWORK_IDS.LINEA_MAINNET,
chainId: CHAIN_IDS.LINEA_MAINNET,
blockExplorerUrl: 'https://lineascan.build',
},
[NETWORK_TYPES.LOCALHOST]: {
networkId: NETWORK_IDS.LOCALHOST,
chainId: CHAIN_IDS.LOCALHOST,
Expand All @@ -316,18 +333,21 @@ export const NETWORK_TO_NAME_MAP = {
[NETWORK_TYPES.GOERLI]: GOERLI_DISPLAY_NAME,
[NETWORK_TYPES.SEPOLIA]: SEPOLIA_DISPLAY_NAME,
[NETWORK_TYPES.LINEA_GOERLI]: LINEA_GOERLI_DISPLAY_NAME,
[NETWORK_TYPES.LINEA_MAINNET]: LINEA_MAINNET_DISPLAY_NAME,
[NETWORK_TYPES.LOCALHOST]: LOCALHOST_DISPLAY_NAME,

[NETWORK_IDS.GOERLI]: GOERLI_DISPLAY_NAME,
[NETWORK_IDS.SEPOLIA]: SEPOLIA_DISPLAY_NAME,
[NETWORK_IDS.LINEA_GOERLI]: LINEA_GOERLI_DISPLAY_NAME,
[NETWORK_IDS.MAINNET]: MAINNET_DISPLAY_NAME,
[NETWORK_IDS.LINEA_MAINNET]: LINEA_MAINNET_DISPLAY_NAME,
[NETWORK_IDS.LOCALHOST]: LOCALHOST_DISPLAY_NAME,

[CHAIN_IDS.GOERLI]: GOERLI_DISPLAY_NAME,
[CHAIN_IDS.SEPOLIA]: SEPOLIA_DISPLAY_NAME,
[CHAIN_IDS.LINEA_GOERLI]: LINEA_GOERLI_DISPLAY_NAME,
[CHAIN_IDS.MAINNET]: MAINNET_DISPLAY_NAME,
[CHAIN_IDS.LINEA_MAINNET]: LINEA_MAINNET_DISPLAY_NAME,
[CHAIN_IDS.LOCALHOST]: LOCALHOST_DISPLAY_NAME,
} as const;

Expand All @@ -336,6 +356,7 @@ export const CHAIN_ID_TO_TYPE_MAP = {
[CHAIN_IDS.GOERLI]: NETWORK_TYPES.GOERLI,
[CHAIN_IDS.SEPOLIA]: NETWORK_TYPES.SEPOLIA,
[CHAIN_IDS.LINEA_GOERLI]: NETWORK_TYPES.LINEA_GOERLI,
[CHAIN_IDS.LINEA_MAINNET]: NETWORK_TYPES.LINEA_MAINNET,
[CHAIN_IDS.LOCALHOST]: NETWORK_TYPES.LOCALHOST,
} as const;

Expand All @@ -344,12 +365,14 @@ export const CHAIN_ID_TO_RPC_URL_MAP = {
[CHAIN_IDS.SEPOLIA]: SEPOLIA_RPC_URL,
[CHAIN_IDS.LINEA_GOERLI]: LINEA_GOERLI_RPC_URL,
[CHAIN_IDS.MAINNET]: MAINNET_RPC_URL,
[CHAIN_IDS.LINEA_MAINNET]: LINEA_MAINNET_RPC_URL,
[CHAIN_IDS.LOCALHOST]: LOCALHOST_RPC_URL,
} as const;

export const CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP = {
[CHAIN_IDS.MAINNET]: ETH_TOKEN_IMAGE_URL,
[CHAIN_IDS.LINEA_GOERLI]: LINEA_GOERLI_TOKEN_IMAGE_URL,
[CHAIN_IDS.LINEA_MAINNET]: LINEA_MAINNET_TOKEN_IMAGE_URL,
[CHAIN_IDS.AVALANCHE]: AVAX_TOKEN_IMAGE_URL,
[CHAIN_IDS.BSC]: BNB_TOKEN_IMAGE_URL,
[CHAIN_IDS.POLYGON]: MATIC_TOKEN_IMAGE_URL,
Expand All @@ -367,13 +390,15 @@ export const NETWORK_ID_TO_ETHERS_NETWORK_NAME_MAP = {
[NETWORK_IDS.SEPOLIA]: NETWORK_TYPES.SEPOLIA,
[NETWORK_IDS.LINEA_GOERLI]: NETWORK_TYPES.LINEA_GOERLI,
[NETWORK_IDS.MAINNET]: NETWORK_NAMES.HOMESTEAD,
[NETWORK_IDS.LINEA_MAINNET]: NETWORK_TYPES.LINEA_MAINNET,
} as const;

export const CHAIN_ID_TO_NETWORK_ID_MAP = {
[CHAIN_IDS.MAINNET]: NETWORK_IDS.MAINNET,
[CHAIN_IDS.GOERLI]: NETWORK_IDS.GOERLI,
[CHAIN_IDS.SEPOLIA]: NETWORK_IDS.SEPOLIA,
[CHAIN_IDS.LINEA_GOERLI]: NETWORK_IDS.LINEA_GOERLI,
[CHAIN_IDS.LINEA_MAINNET]: NETWORK_IDS.LINEA_MAINNET,
[CHAIN_IDS.LOCALHOST]: NETWORK_IDS.LOCALHOST,
} as const;

Expand Down Expand Up @@ -420,6 +445,11 @@ export const ETHERSCAN_SUPPORTED_NETWORKS = {
subdomain: 'goerli',
networkId: CHAIN_ID_TO_NETWORK_ID_MAP[CHAIN_IDS.LINEA_GOERLI],
},
[CHAIN_IDS.LINEA_MAINNET]: {
domain: 'lineascan.build',
subdomain: defaultEtherscanSubdomainPrefix,
networkId: CHAIN_ID_TO_NETWORK_ID_MAP[CHAIN_IDS.LINEA_MAINNET],
},
[CHAIN_IDS.BSC]: {
domain: 'bscscan.com',
subdomain: defaultEtherscanSubdomainPrefix,
Expand Down Expand Up @@ -519,6 +549,7 @@ export const BUYABLE_CHAINS_MAP: {
| typeof CHAIN_IDS.FANTOM_TESTNET
| typeof CHAIN_IDS.MOONBEAM_TESTNET
| typeof CHAIN_IDS.LINEA_GOERLI
| typeof CHAIN_IDS.LINEA_MAINNET
| typeof CHAIN_IDS.GOERLI
>]: BuyableChainSettings;
} = {
Expand Down
4 changes: 4 additions & 0 deletions shared/modules/network.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ export function isTokenDetectionEnabledForNetwork(chainId: string | undefined) {
function isSafeInteger(value: unknown): value is number {
return Number.isSafeInteger(value);
}

export function shouldShowLineaMainnet(): boolean {
return new Date().getTime() > Date.UTC(2023, 6, 11, 18);
}
3 changes: 3 additions & 0 deletions test/e2e/fixture-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ function defaultFixture() {
trezorModel: null,
usedNetworks: {
[CHAIN_IDS.MAINNET]: true,
[CHAIN_IDS.LINEA_MAINNET]: true,
[CHAIN_IDS.GOERLI]: true,
[CHAIN_IDS.LOCALHOST]: true,
},
Expand All @@ -187,6 +188,7 @@ function defaultFixture() {
incomingTransactions: {},
incomingTxLastFetchedBlockByChainId: {
[CHAIN_IDS.MAINNET]: null,
[CHAIN_IDS.LINEA_MAINNET]: null,
[CHAIN_IDS.GOERLI]: null,
[CHAIN_IDS.SEPOLIA]: null,
[CHAIN_IDS.LINEA_GOERLI]: null,
Expand Down Expand Up @@ -329,6 +331,7 @@ function onboardingFixture() {
trezorModel: null,
usedNetworks: {
[CHAIN_IDS.MAINNET]: true,
[CHAIN_IDS.LINEA_MAINNET]: true,
[CHAIN_IDS.GOERLI]: true,
[CHAIN_IDS.LOCALHOST]: true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export default class LoadingNetworkScreen extends PureComponent {
return t('connectingToSepolia');
case NETWORK_TYPES.LINEA_GOERLI:
return t('connectingToLineaGoerli');
case NETWORK_TYPES.LINEA_MAINNET:
return t('connectingToLineaMainnet');
default:
return t('connectingTo', [providerId]);
}
Expand Down
3 changes: 3 additions & 0 deletions ui/components/component-library/text/text.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ function renderBackgroundColor(color) {
case Color.lineaGoerliInverse:
bgColor = BackgroundColor.lineaGoerli;
break;
case Color.lineaMainnetInverse:
bgColor = BackgroundColor.lineaMainnet;
break;
default:
bgColor = null;
break;
Expand Down
19 changes: 17 additions & 2 deletions ui/components/multichain/network-list-menu/network-list-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import { getCompletedOnboarding } from '../../../ducks/metamask/metamask';
import {
getCompletedOnboarding,
isLineaMainnetNetworkReleased,
} from '../../../ducks/metamask/metamask';

const UNREMOVABLE_CHAIN_IDS = [CHAIN_IDS.MAINNET, ...TEST_CHAINS];
const UNREMOVABLE_CHAIN_IDS = [
CHAIN_IDS.MAINNET,
CHAIN_IDS.LINEA_MAINNET,
...TEST_CHAINS,
];

export const NetworkListMenu = ({ onClose }) => {
const t = useI18nContext();
Expand All @@ -58,6 +65,8 @@ export const NetworkListMenu = ({ onClose }) => {

const completedOnboarding = useSelector(getCompletedOnboarding);

const lineaMainnetReleased = useSelector(isLineaMainnetNetworkReleased);

useEffect(() => {
if (showTestNetworks && !showTestNetworksRef.current) {
// Scroll to the bottom of the list
Expand All @@ -76,6 +85,12 @@ export const NetworkListMenu = ({ onClose }) => {
<>
<Box className="multichain-network-list-menu" ref={networkListRef}>
{networks.map((network, index) => {
if (
!lineaMainnetReleased &&
network.providerType === 'linea-mainnet'
) {
return null;
}
const isCurrentNetwork = currentChainId === network.chainId;
const canDeleteNetwork =
!isCurrentNetwork &&
Expand Down
3 changes: 2 additions & 1 deletion ui/components/ui/new-network-info/new-network-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import Chip from '../chip/chip';
import { setFirstTimeUsedNetwork } from '../../../store/actions';
import { NETWORK_TYPES } from '../../../../shared/constants/network';
import { Icon, IconName, Text } from '../../component-library';
import { getNetworkLabelKey } from '../../../helpers/utils/i18n-helper';

const NewNetworkInfo = () => {
const t = useContext(I18nContext);
Expand Down Expand Up @@ -95,7 +96,7 @@ const NewNetworkInfo = () => {
label={
providerConfig.type === NETWORK_TYPES.RPC
? providerConfig.nickname ?? t('privateNetwork')
: t(providerConfig.type)
: t(getNetworkLabelKey(providerConfig.type))
}
labelProps={{
color: Color.textDefault,
Expand Down
2 changes: 2 additions & 0 deletions ui/components/ui/typography/typography.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export const ValidColors = [
Color.sepoliaInverse,
Color.lineaGoerli,
Color.lineaGoerliInverse,
Color.lineaMainnet,
Color.lineaMainnetInverse,
];

export const ValidTags = [
Expand Down
2 changes: 2 additions & 0 deletions ui/css/design-system/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ $color-map: (
'sepolia-inverse': --color-network-sepolia-inverse,
'linea-goerli': --color-network-linea-goerli-default,
'linea-goerli-inverse': --color-network-linea-goerli-inverse,
'linea-mainnet': --color-network-linea-mainnet-default,
'linea-mainnet-inverse': --color-network-linea-mainnet-inverse,
'localhost': --color-network-localhost-default,
'transparent': --transparent,
'flask-purple': --color-flask-default,
Expand Down
4 changes: 3 additions & 1 deletion ui/css/utilities/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
--mainnet: #29b6af;
--inherit: inherit;
--transparent: transparent;
--color-network-linea-goerli-default: #000;
--color-network-linea-goerli-default: #61dfff;
--color-network-linea-goerli-inverse: #fcfcfc;
--color-network-linea-mainnet-default: #121212;
--color-network-linea-mainnet-inverse: #fcfcfc;
// DO NOT CHANGE
// Required for the QR reader to work properly
--qr-code-white-background: #fff;
Expand Down
4 changes: 4 additions & 0 deletions ui/ducks/metamask/metamask.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,7 @@ export function doesUserHaveALedgerAccount(state) {
return kr.type === KeyringType.ledger;
});
}

export function isLineaMainnetNetworkReleased(state) {
return state.metamask.isLineaMainnetReleased;
}
Loading

0 comments on commit e492339

Please sign in to comment.