Commit 89fac78e authored by Max Alekseenko's avatar Max Alekseenko

Merge branch 'main' into dapp-rating

parents 3d295216 51e0ca1c
......@@ -5,9 +5,19 @@ const RESTRICTED_MODULES = {
{ name: '@metamask/providers', message: 'Please lazy-load @metamask/providers or use useProvider hook instead' },
{ name: '@metamask/post-message-stream', message: 'Please lazy-load @metamask/post-message-stream or use useProvider hook instead' },
{ name: 'playwright/TestApp', message: 'Please use render() fixture from test() function of playwright/lib module' },
{
name: '@chakra-ui/react',
importNames: [ 'Popover', 'Menu', 'useToast' ],
message: 'Please use corresponding component or hook from ui/shared/chakra component instead',
},
{
name: 'lodash',
message: 'Please use `import [package] from \'lodash/[package]\'` instead.',
},
],
patterns: [
'icons/*',
'!lodash/*',
],
};
......
......@@ -12,6 +12,7 @@ on:
- none
- arbitrum
- base
- celo_alfajores
- gnosis
- eth
- eth_sepolia
......
......@@ -339,7 +339,9 @@
"main",
"main.L2",
"localhost",
"arbitrum",
"base",
"celo_alfajores",
"gnosis",
"eth",
"eth_goerli",
......
......@@ -15,6 +15,7 @@ const chain = Object.freeze({
secondaryCoin: {
symbol: getEnvValue('NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL'),
},
hasMultipleGasCurrencies: getEnvValue('NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES') === 'true',
tokenStandard: getEnvValue('NEXT_PUBLIC_NETWORK_TOKEN_STANDARD_NAME') || 'ERC',
rpcUrl: getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL'),
isTestnet: getEnvValue('NEXT_PUBLIC_IS_TESTNET') === 'true',
......
# Set of ENVs for Celo Alfajjores network explorer
# https://celo-alfajores.blockscout.com/
# app configuration
NEXT_PUBLIC_APP_PROTOCOL=http
NEXT_PUBLIC_APP_HOST=localhost
NEXT_PUBLIC_APP_PORT=3000
# blockchain parameters
NEXT_PUBLIC_NETWORK_NAME=Celo Alfajores
NEXT_PUBLIC_NETWORK_SHORT_NAME=Alfajores
NEXT_PUBLIC_NETWORK_ID=44787
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Celo
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=CELO
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES=true
NEXT_PUBLIC_NETWORK_RPC_URL=https://alfajores-forno.celo-testnet.org
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
NEXT_PUBLIC_IS_TESTNET=true
# api configuration
NEXT_PUBLIC_API_HOST=celo-alfajores.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/
# ui config
## homepage
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=rgba(0,0,0,1)
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=rgba(252,255,82,1)
## sidebar
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/celo-logo-light.svg
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/celo-logo-dark.svg
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/celo-icon-light.svg
NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/celo-icon-dark.svg
## footer
##views
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'LooksRare','collection_url':'https://goerli.looksrare.org/collections/{hash}','instance_url':'https://goerli.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]
## misc
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
## views
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
# app features
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_GAS_TRACKER_ENABLED=false
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_AUTH_URL=http://localhost:3000
NEXT_PUBLIC_LOGOUT_URL=https://blockscoutcom.us.auth0.com/v2/logout
NEXT_PUBLIC_MARKETPLACE_ENABLED=true
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/eth-goerli.json
NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
# NEXT_PUBLIC_STATS_API_HOST=https://stats-goerli.k8s-dev.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.k8s-dev.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info-test.k8s-dev.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs-test.k8s-dev.blockscout.com
NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/celo.png
......@@ -43,7 +43,7 @@ NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_AD_BANNER_PROVIDER=hype
NEXT_PUBLIC_AD_BANNER_PROVIDER=slise
NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-mainnet.safe.global
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
......
......@@ -91,11 +91,11 @@ brace-expansion@^1.1.7:
concat-map "0.0.1"
braces@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
version "3.0.3"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
fill-range "^7.0.1"
fill-range "^7.1.1"
color-name@^1.1.4:
version "1.1.4"
......@@ -276,10 +276,10 @@ filing-cabinet@^4.1.6:
tsconfig-paths "^4.2.0"
typescript "^5.0.4"
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"
......
......@@ -273,7 +273,7 @@ const rollupSchema = yup
.when('NEXT_PUBLIC_ROLLUP_TYPE', {
is: (value: string) => value === 'optimistic',
then: (schema) => schema.test(urlTest).required(),
otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL cannot not be used if NEXT_PUBLIC_ROLLUP_TYPE is not defined'),
otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL can be used only if NEXT_PUBLIC_ROLLUP_TYPE is set to \'optimistic\' '),
}),
});
......@@ -507,6 +507,7 @@ const schema = yup
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL: yup.string(),
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS: yup.number().integer().positive(),
NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL: yup.string(),
NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES: yup.boolean(),
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE: yup.string<NetworkVerificationType>().oneOf([ 'validation', 'mining' ]),
NEXT_PUBLIC_NETWORK_TOKEN_STANDARD_NAME: yup.string(),
NEXT_PUBLIC_IS_TESTNET: yup.boolean(),
......
......@@ -47,6 +47,7 @@ NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Explorer','baseUrl':'https://example.com/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL=GNO
NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES=true
NEXT_PUBLIC_NETWORK_ICON=https://example.com/icon.png
NEXT_PUBLIC_NETWORK_ICON_DARK=https://example.com/icon.png
NEXT_PUBLIC_NETWORK_LOGO=https://example.com/logo.png
......
......@@ -262,11 +262,11 @@ ansi-styles@^4.1.0:
color-convert "^2.0.1"
braces@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
version "3.0.3"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
fill-range "^7.0.1"
fill-range "^7.1.1"
browserslist@^4.14.5:
version "4.21.9"
......@@ -439,10 +439,10 @@ fastest-levenshtein@^1.0.12:
resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5"
integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"
......
......@@ -68,7 +68,6 @@ frontend:
NEXT_PUBLIC_LOGOUT_URL: https://blockscoutcom.us.auth0.com/v2/logout
NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs','coin_price','market_cap']"
NEXT_PUBLIC_NETWORK_RPC_URL: https://eth-sepolia.public.blastapi.io
NEXT_PUBLIC_NETWORK_ID: '11155111'
NEXT_PUBLIC_NETWORK_EXPLORERS: "[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]"
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace-categories/default.json
NEXT_PUBLIC_MARKETPLACE_FEATURED_APP: zkbob-wallet
......@@ -77,22 +76,15 @@ frontend:
NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
NEXT_PUBLIC_WEB3_WALLETS: "['token_pocket','coinbase','metamask']"
NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE: gradient_avatar
NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS: "['top_accounts']"
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: true
NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS: "['value','fee_currency','gas_price','gas_fees','burnt_fees']"
NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS: "['fee_per_gas']"
NEXT_PUBLIC_USE_NEXT_JS_PROXY: true
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: "[{'name':'LooksRare','collection_url':'https://goerli.looksrare.org/collections/{hash}','instance_url':'https://goerli.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]"
NEXT_PUBLIC_HAS_USER_OPS: true
NEXT_PUBLIC_CONTRACT_CODE_IDES: "[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]"
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER: blockscout
NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS: true
NEXT_PUBLIC_AD_BANNER_PROVIDER: getit
NEXT_PUBLIC_AD_BANNER_ADDITIONAL_PROVIDER: adbutler
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP: "{ \"id\": \"632019\", \"width\": \"728\", \"height\": \"90\" }"
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE: "{ \"id\": \"632018\", \"width\": \"320\", \"height\": \"100\" }"
NEXT_PUBLIC_AD_BANNER_PROVIDER: slise
NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED: true
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED: true
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/apps']"
envFromSecret:
NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN
......
......@@ -91,6 +91,7 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will
| NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL | `string` | Network currency symbol | - | - | `ETH` | v1.0.x+ |
| NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS | `string` | Network currency decimals | - | `18` | `6` | v1.0.x+ |
| NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL | `string` | Network secondary coin symbol. | - | - | `GNO` | v1.29.0+ |
| NEXT_PUBLIC_NETWORK_MULTIPLE_GAS_CURRENCIES | `boolean` | Set to `true` for networks where users can pay transaction fees in either the native coin or ERC-20 tokens. | - | `false` | `true` | v1.33.0+ |
| NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE | `validation` or `mining` | Verification type in the network | - | `mining` | `validation` | v1.0.x+ |
| NEXT_PUBLIC_NETWORK_TOKEN_STANDARD_NAME | `string` | Name of the standard for creating tokens | - | `ERC` | `BEP` | v1.31.0+ |
| NEXT_PUBLIC_IS_TESTNET | `boolean`| Set to true if network is testnet | - | `false` | `true` | v1.0.x+ |
......@@ -359,6 +360,7 @@ This feature is **enabled by default**. To switch it off pass `NEXT_PUBLIC_GAS_T
### Banner ads
This feature is **enabled by default** with the `slise` ads provider. To switch it off pass `NEXT_PUBLIC_AD_BANNER_PROVIDER=none`.
*Note* that the `getit` ad provider is temporary disabled.
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- |
......@@ -402,8 +404,8 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_ROLLUP_TYPE | `'optimistic' \| 'arbitrum' \| 'shibarium' \| 'zkEvm' \| 'zkSync' ` | Rollup chain type | Required | - | `'optimistic'` | v1.24.0+ |
| NEXT_PUBLIC_ROLLUP_L1_BASE_URL | `string` | Blockscout base URL for L1 network | Required | - | `'http://eth-goerli.blockscout.com'` | v1.24.0+ |
| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL | `string` | URL for L2 -> L1 withdrawals | Required only for `optimistic` rollups | - | `https://app.optimism.io/bridge/withdraw` | v1.24.0+ |
| NEXT_PUBLIC_FAULT_PROOF_ENABLED | `boolean` | Set to `true` for chains with fault proof system enabled (OP stack only) | - | - | `true` | v1.31.0+ |
| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL | `string` | URL for L2 -> L1 withdrawals (Optimistic stack only) | Required for `optimistic` rollups | - | `https://app.optimism.io/bridge/withdraw` | v1.24.0+ |
| NEXT_PUBLIC_FAULT_PROOF_ENABLED | `boolean` | Set to `true` for chains with fault proof system enabled (Optimistic stack only) | - | - | `true` | v1.31.0+ |
&nbsp;
......
<svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.5 11a7.5 7.5 0 1 1 15 0 7.5 7.5 0 0 1-15 0ZM11 1C5.477 1 1 5.477 1 11s4.477 10 10 10 10-4.477 10-10S16.523 1 11 1Zm1.25 5a1.25 1.25 0 1 0-2.5 0v5c0 .69.56 1.25 1.25 1.25h5a1.25 1.25 0 1 0 0-2.5h-3.75V6Z" fill="currentColor" stroke="transparent" stroke-width=".6" stroke-linecap="round" stroke-linejoin="round"/>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 .3C4.643.3.3 4.643.3 10c0 5.357 4.343 9.7 9.7 9.7 5.357 0 9.7-4.343 9.7-9.7 0-5.357-4.343-9.7-9.7-9.7ZM2.2 10a7.8 7.8 0 1 1 15.6 0 7.8 7.8 0 0 1-15.6 0ZM10 4.05a.95.95 0 0 0-.95.95v5c0 .525.425.95.95.95h5a.95.95 0 1 0 0-1.9h-3.75a.3.3 0 0 1-.3-.3V5a.95.95 0 0 0-.95-.95Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.392.45C3.644.163 3.984 0 4.34 0h8.038a.63.63 0 0 1 .474.225L17.54 5.61a.83.83 0 0 1 .196.544v12.308c0 .408-.141.799-.393 1.087-.25.289-.592.451-.947.451H4.34c-.356 0-.696-.162-.948-.45A1.661 1.661 0 0 1 3 18.461V1.538c0-.408.141-.799.392-1.087Zm.948 1.088h6.87v4.497c0 .388.315.702.702.702h4.485v11.725H4.34V1.538Zm8.274.59 2.791 3.205h-2.791V2.128Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.233 8.8a2.293 2.293 0 0 0-1.613.644l-.006.006-.595.591a.564.564 0 1 0 .795.8l.592-.589a1.166 1.166 0 0 1 1.649 1.648l-1.034 1.034a1.168 1.168 0 0 1-1.758-.126.564.564 0 1 0-.903.676 2.293 2.293 0 0 0 3.458.247l1.038-1.037.007-.007a2.294 2.294 0 0 0-1.63-3.887Zm-2.259 2.403a2.294 2.294 0 0 0-1.786.666l-1.037 1.037-.007.008a2.293 2.293 0 0 0 3.243 3.242l.006-.007.592-.591a.564.564 0 0 0-.797-.797l-.588.587A1.166 1.166 0 0 1 7.952 13.7l1.034-1.034a1.167 1.167 0 0 1 1.758.126.564.564 0 0 0 .903-.675 2.293 2.293 0 0 0-1.673-.914Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.5 23.75h1.25v2.5H2.5v-2.5h1.25V5A1.25 1.25 0 0 1 5 3.75h11.25A1.25 1.25 0 0 1 17.5 5v10H20a2.5 2.5 0 0 1 2.5 2.5v5a1.25 1.25 0 0 0 2.5 0v-8.75h-2.5a1.25 1.25 0 0 1-1.25-1.25V8.018l-2.071-2.072 1.767-1.767 6.188 6.187a1.244 1.244 0 0 1 .366.884V22.5a3.75 3.75 0 0 1-7.5 0v-5h-2.5v6.25Zm-11.25 0H15v-7.5H6.25v7.5Zm0-17.5v7.5H15v-7.5H6.25Z" fill="currentColor"/>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.666 15.833h.834V17.5H1.666v-1.667H2.5v-12.5a.833.833 0 0 1 .833-.833h7.5a.833.833 0 0 1 .833.833V10h1.667A1.667 1.667 0 0 1 15 11.667V15a.833.833 0 0 0 1.666 0V9.167H15a.833.833 0 0 1-.834-.834V5.345l-1.38-1.38 1.178-1.18 4.125 4.126a.831.831 0 0 1 .244.589V15a2.5 2.5 0 0 1-5 0v-3.333h-1.667v4.166Zm-7.5 0H10v-5H4.167v5Zm0-11.666v5H10v-5H4.167Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.16 3A2.16 2.16 0 0 0 3 5.16v10.18a2.16 2.16 0 0 0 2.16 2.16h10.18a2.16 2.16 0 0 0 2.16-2.16v-3.272h-1.614v3.114c0 .389-.315.704-.704.704H5.318a.705.705 0 0 1-.704-.704V5.318c0-.389.315-.704.704-.704h3.114V3H5.159Zm6.135 0a.41.41 0 0 0-.41.41v.793c0 .226.184.409.41.409h3.453l-4.244 4.245a.409.409 0 0 0 0 .578l.56.561c.16.16.42.16.58 0l4.244-4.245v3.454c0 .226.183.41.41.41h.793a.41.41 0 0 0 .409-.41V3h-6.205Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.16 3A2.16 2.16 0 0 0 3 5.16v10.18a2.16 2.16 0 0 0 2.16 2.16h10.18a2.16 2.16 0 0 0 2.16-2.16v-3.272h-1.614v3.114a.704.704 0 0 1-.704.704H5.318a.705.705 0 0 1-.704-.704V5.318c0-.389.315-.704.704-.704h3.114V3H5.159Zm6.135 0a.41.41 0 0 0-.41.41v.793a.41.41 0 0 0 .41.409h3.453l-4.244 4.245a.409.409 0 0 0 0 .578l.56.561c.16.16.42.16.58 0l4.244-4.245v3.454c0 .226.183.41.41.41h.793a.41.41 0 0 0 .409-.41V3h-6.205Z" fill="currentColor"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 31 30">
<g fill="currentColor" clip-path="url(#wallet_svg__a)">
<path d="M22.75 27.188h-15A4.688 4.688 0 0 1 3.062 22.5V9.375A.937.937 0 0 1 4 8.437h18.75a4.688 4.688 0 0 1 4.688 4.688V22.5a4.688 4.688 0 0 1-4.688 4.688ZM4.937 10.313V22.5a2.812 2.812 0 0 0 2.813 2.813h15a2.812 2.812 0 0 0 2.813-2.813v-9.375a2.812 2.812 0 0 0-2.813-2.813H4.937Z"/>
<path d="M24.625 10.312a.937.937 0 0 1-.937-.937V6.797a2.184 2.184 0 0 0-.732-1.754 1.82 1.82 0 0 0-1.565-.3L5.669 8.315a.938.938 0 0 0-.731.938.938.938 0 0 1-1.875 0 2.813 2.813 0 0 1 2.184-2.766l15.731-3.572a3.656 3.656 0 0 1 3.15.666 4.069 4.069 0 0 1 1.435 3.216v2.578a.938.938 0 0 1-.938.937ZM26.5 21.563h-6.563a3.75 3.75 0 1 1 0-7.5H26.5a.938.938 0 0 1 .938.937v5.625a.938.938 0 0 1-.938.938Zm-6.563-5.625a1.875 1.875 0 1 0 0 3.75h5.625v-3.75h-5.625Z"/>
</g>
<defs>
<clipPath id="wallet_svg__a">
<path fill="#fff" d="M.25 0h30v30h-30z"/>
</clipPath>
</defs>
<svg viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.139 20H4.83a3.847 3.847 0 0 1-3.846-3.845V5.39a.769.769 0 0 1 .77-.769h15.384a3.847 3.847 0 0 1 3.846 3.845v7.69A3.844 3.844 0 0 1 17.139 20ZM2.524 6.16v9.996a2.307 2.307 0 0 0 2.307 2.307H17.14a2.308 2.308 0 0 0 2.308-2.307v-7.69A2.306 2.306 0 0 0 17.14 6.16H2.524Z" fill="currentColor"/>
<path d="M18.677 6.159a.77.77 0 0 1-.769-.77V3.276a1.79 1.79 0 0 0-.6-1.438 1.493 1.493 0 0 0-1.284-.246l-12.9 2.93a.77.77 0 0 0-.6.769.769.769 0 0 1-1.539 0A2.306 2.306 0 0 1 2.778 3.02L15.685.091a3 3 0 0 1 2.585.546 3.338 3.338 0 0 1 1.177 2.638V5.39a.77.77 0 0 1-.77.769Zm1.539 9.227H14.83a3.077 3.077 0 0 1-2.175-5.25 3.074 3.074 0 0 1 2.175-.902h5.385a.77.77 0 0 1 .769.77v4.613a.77.77 0 0 1-.77.769Zm-5.385-4.614a1.539 1.539 0 1 0 0 3.076h4.616v-3.076H14.83Z" fill="currentColor"/>
</svg>
......@@ -60,9 +60,9 @@ export function AddressHighlightProvider({ children }: AddressHighlightProviderP
);
}
export function useAddressHighlightContext() {
export function useAddressHighlightContext(disabled?: boolean) {
const context = React.useContext(AddressHighlightContext);
if (context === undefined) {
if (context === undefined || disabled) {
return null;
}
return context;
......
......@@ -17,7 +17,7 @@ const TEST_URLS: Record<AdBannerProviders, string> = {
adbutler: 'https://servedbyadbutler.com/app.js',
hype: 'https://api.hypelab.com/v1/scripts/hp-sdk.js',
// I don't have an url for getit to test
getit: DEFAULT_URL,
// getit: DEFAULT_URL,
none: DEFAULT_URL,
};
......
......@@ -2,7 +2,7 @@ import type { UseToastOptions, ToastProps } from '@chakra-ui/react';
import { createToastFn, useChakra } from '@chakra-ui/react';
import React from 'react';
import Toast from 'ui/shared/Toast';
import Toast from 'ui/shared/chakra/Toast';
// there is no toastComponent prop in UseToastOptions type
// but these options will be passed to createRenderToast under the hood
......@@ -14,6 +14,7 @@ const defaultOptions: UseToastOptions & { toastComponent?: React.FC<ToastProps>
containerStyle: {
margin: 8,
},
variant: 'subtle',
};
export default function useToastModified() {
......
import { uniq } from 'lodash';
import _uniq from 'lodash/uniq';
import isBrowser from './isBrowser';
......@@ -27,7 +27,7 @@ export function saveToRecentKeywords(value: string) {
}
const keywordsArr = getRecentSearchKeywords();
const result = uniq([ value, ...keywordsArr ]).slice(0, MAX_KEYWORDS_NUMBER - 1);
const result = _uniq([ value, ...keywordsArr ]).slice(0, MAX_KEYWORDS_NUMBER - 1);
window.localStorage.setItem(RECENT_KEYWORDS_LS_KEY, JSON.stringify(result));
}
......
export const multiple = [
{ address: '0xA84d24bD8ACE4d349C5f8c5DeeDd8bc071Ce5e2b', name: null },
{ address: '0xc9e91eDeA9DC16604022e4E5b437Df9c64EdB05A', name: 'Diamond' },
{ address: '0x2041832c62C0F89426b48B5868146C0b1fcd23E7', name: null },
{ address: '0x5f7DC6ECcF05594429671F83cc0e42EE18bC0974', name: 'VariablePriceFacet' },
{ address: '0x7abC92E242e88e4B0d6c5Beb4Df80e94D2c8A78c', name: null },
{ address: '0x84178a0c58A860eCCFB7E3aeA64a09543062A356', name: 'MultiSaleFacet' },
{ address: '0x33aD95537e63e9f09d96dE201e10715Ed40D9400', name: 'SVGTemplatesFacet' },
{ address: '0xfd86Aa7f902185a8Df9859c25E4BF52D3DaDd9FA', name: 'ERC721AReceiverFacet' },
{ address: '0x6945a35df18e59Ce09fec4B6cD3C4F9cFE6369de', name: null },
];
......@@ -299,7 +299,7 @@ export const stabilityTx: Transaction = {
decimals: '18',
exchange_rate: '123.567',
holders: '92',
icon_url: null,
icon_url: 'https://example.com/icon.png',
name: 'Stability Gas',
symbol: 'GAS',
total_supply: '10000000000000000000000000',
......@@ -321,6 +321,24 @@ export const stabilityTx: Transaction = {
},
};
export const celoTxn: Transaction = {
...base,
celo: {
gas_token: {
address: '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1',
circulating_market_cap: null,
decimals: '18',
exchange_rate: '0.42',
holders: '205738',
icon_url: 'https://example.com/icon.png',
name: 'Celo Dollar',
symbol: 'cUSD',
total_supply: '7145754483836626799435133',
type: 'ERC-20',
},
},
};
export const base2 = {
...base,
hash: '0x02d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3193',
......
......@@ -39,7 +39,8 @@ export function ad(): CspDev.DirectiveDescriptor {
// adbutler
'servedbyadbutler.com',
`'sha256-${ Base64.stringify(sha256(connectAdbutler)) }'`,
`'sha256-${ Base64.stringify(sha256(placeAd ?? '')) }'`,
`'sha256-${ Base64.stringify(sha256(placeAd(undefined) ?? '')) }'`,
`'sha256-${ Base64.stringify(sha256(placeAd('mobile') ?? '')) }'`,
// slise
'*.slise.xyz',
......
......@@ -70,13 +70,13 @@
"chakra-react-select": "^4.4.3",
"crypto-js": "^4.2.0",
"d3": "^7.6.1",
"dappscout-iframe": "0.2.1",
"dappscout-iframe": "0.2.2",
"dayjs": "^1.11.5",
"dom-to-image": "^2.6.0",
"focus-visible": "^5.2.0",
"framer-motion": "^6.5.1",
"getit-sdk": "^1.0.4",
"gradient-avatar": "^1.0.2",
"gradient-avatar": "git+https://github.com/blockscout/gradient-avatar.git",
"graphiql": "^2.2.0",
"graphql": "^16.8.1",
"graphql-ws": "^5.11.3",
......
import type { TestFixture, Page } from '@playwright/test';
import _isEqual from 'lodash/isEqual';
import type { PublicRpcSchema } from 'viem';
import { getEnvValue } from 'configs/app/utils';
type Params = PublicRpcSchema[number];
export type MockRpcResponseFixture = (params: Params) => Promise<void>;
// WIP
const fixture: TestFixture<MockRpcResponseFixture, { page: Page }> = async({ page }, use) => {
await use(async({ Method, ReturnType }) => {
const rpcUrl = getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL');
if (!rpcUrl) {
return;
}
await page.route(rpcUrl, (route) => {
const method = route.request().method();
if (method !== 'POST') {
route.continue();
return;
}
const json = route.request().postDataJSON();
const id = json?.id;
const payload = {
id,
jsonrpc: '2.0',
method: Method,
// TODO: add params to match actual payload
};
if (_isEqual(json, payload) && id !== undefined) {
return route.fulfill({
status: 200,
body: JSON.stringify({
id,
jsonrpc: '2.0',
result: ReturnType,
}),
});
}
});
});
};
export default fixture;
......@@ -8,6 +8,7 @@ import * as mockConfigResponse from './fixtures/mockConfigResponse';
import * as mockContractReadResponse from './fixtures/mockContractReadResponse';
import * as mockEnvs from './fixtures/mockEnvs';
import * as mockFeatures from './fixtures/mockFeatures';
import * as mockRpcResponse from './fixtures/mockRpcResponse';
import * as mockTextAd from './fixtures/mockTextAd';
import * as render from './fixtures/render';
import * as socketServer from './fixtures/socketServer';
......@@ -20,6 +21,7 @@ interface Fixtures {
mockContractReadResponse: mockContractReadResponse.MockContractReadResponseFixture;
mockEnvs: mockEnvs.MockEnvsFixture;
mockFeatures: mockFeatures.MockFeaturesFixture;
mockRpcResponse: mockRpcResponse.MockRpcResponseFixture;
createSocket: socketServer.CreateSocketFixture;
injectMetaMaskProvider: injectMetaMaskProvider.InjectMetaMaskProvider;
mockTextAd: mockTextAd.MockTextAdFixture;
......@@ -33,6 +35,7 @@ const test = base.extend<Fixtures>({
mockContractReadResponse: mockContractReadResponse.default,
mockEnvs: mockEnvs.default,
mockFeatures: mockFeatures.default,
mockRpcResponse: mockRpcResponse.default,
// FIXME: for some reason Playwright does not intercept requests to text ad provider when running multiple tests in parallel
// even if we have a global request interceptor (maybe it is related to service worker issue, maybe not)
// so we have to inject mockTextAd fixture in each test and mock the response where it is needed
......
......@@ -32,6 +32,7 @@
| "clock"
| "coins/bitcoin"
| "collection"
| "contracts/proxy"
| "contracts/regular_many"
| "contracts/regular"
| "contracts/verified_many"
......
......@@ -17,7 +17,6 @@ const sizes = {
xl: defineStyle({
fontSize: '40px',
lineHeight: '48px',
letterSpacing: '-1px',
}),
lg: defineStyle({
fontSize: '32px',
......
......@@ -19,6 +19,10 @@ const semanticTokens = {
link_hovered: {
'default': 'blue.400',
},
icon_info: {
'default': 'gray.400',
_dark: 'gray.500',
},
error: {
'default': 'red.500',
_dark: 'red.500',
......
......@@ -24,9 +24,7 @@ export interface UserTags {
export type AddressParamBasic = {
hash: string;
// API doesn't return hash in this model yet
// will be fixed in the future releases
implementations: Array<Omit<AddressImplementation, 'address'>> | null;
implementations: Array<AddressImplementation> | null;
name: string | null;
is_contract: boolean;
is_verified: boolean | null;
......
......@@ -77,6 +77,10 @@ export type Transaction = {
validator_address: AddressParam;
validator_fee: string;
};
// Celo fields
celo?: {
gas_token: TokenInfo<'ERC-20'> | null;
};
// zkEvm fields
zkevm_verify_hash?: string;
zkevm_batch_number?: number;
......
import type { ArrayElement } from 'types/utils';
export const SUPPORTED_AD_BANNER_PROVIDERS = [ 'slise', 'adbutler', 'coinzilla', 'hype', 'getit', 'none' ] as const;
export const SUPPORTED_AD_BANNER_PROVIDERS = [
'slise',
'adbutler',
'coinzilla',
'hype',
// 'getit', // temporary disabled
'none',
] as const;
export type AdBannerProviders = ArrayElement<typeof SUPPORTED_AD_BANNER_PROVIDERS>;
export const SUPPORTED_AD_BANNER_ADDITIONAL_PROVIDERS = [ 'adbutler' ] as const;
......
import { Box, Text, Icon, Popover, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import { Box, Text, Icon, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import React from 'react';
// This icon doesn't work properly when it is in the sprite
......@@ -7,6 +7,7 @@ import React from 'react';
import solidityScanIcon from 'icons/brands/solidity_scan.svg';
import useApiQuery from 'lib/api/useApiQuery';
import { SOLIDITYSCAN_REPORT } from 'stubs/contract';
import Popover from 'ui/shared/chakra/Popover';
import LinkExternal from 'ui/shared/links/LinkExternal';
import SolidityscanReportButton from 'ui/shared/solidityscanReport/SolidityscanReportButton';
import SolidityscanReportDetails from 'ui/shared/solidityscanReport/SolidityscanReportDetails';
......
......@@ -2,7 +2,6 @@ import {
Flex,
Button,
chakra,
Popover,
PopoverTrigger,
PopoverBody,
PopoverContent,
......@@ -14,6 +13,7 @@ import {
import React from 'react';
import config from 'configs/app';
import Popover from 'ui/shared/chakra/Popover';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/links/LinkExternal';
......
......@@ -7,7 +7,6 @@ import {
Modal,
ModalCloseButton,
ModalContent,
Popover,
PopoverBody,
PopoverContent,
PopoverTrigger,
......@@ -22,6 +21,7 @@ import type { SmartContractExternalLibrary } from 'types/api/contract';
import useIsMobile from 'lib/hooks/useIsMobile';
import { apos } from 'lib/html-entities';
import Popover from 'ui/shared/chakra/Popover';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import IconSvg from 'ui/shared/IconSvg';
......
import {
chakra,
Popover,
PopoverBody,
PopoverContent,
PopoverTrigger,
......@@ -14,6 +13,7 @@ import {
import React from 'react';
import { times } from 'lib/html-entities';
import Popover from 'ui/shared/chakra/Popover';
import IconSvg from 'ui/shared/IconSvg';
interface Props {
......
......@@ -4,7 +4,6 @@ import {
Flex,
Grid,
Hide,
Popover,
PopoverBody,
PopoverContent,
PopoverTrigger,
......@@ -23,6 +22,7 @@ import { route } from 'nextjs-routes';
import type { ResourceError } from 'lib/api/resources';
import dayjs from 'lib/date/dayjs';
import Popover from 'ui/shared/chakra/Popover';
import EnsEntity from 'ui/shared/entities/ens/EnsEntity';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/links/LinkInternal';
......
import { Popover, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import { PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import React from 'react';
import type { FormattedData } from './types';
import Popover from 'ui/shared/chakra/Popover';
import TokenSelectButton from './TokenSelectButton';
import TokenSelectMenu from './TokenSelectMenu';
import useTokenSelect from './useTokenSelect';
......
......@@ -53,7 +53,7 @@ const TokenBalances = () => {
name="Net Worth"
value={ addressData?.exchange_rate ? `${ prefix }$${ totalUsd.toFormat(2) }` : 'N/A' }
isLoading={ addressQuery.isPending || tokenQuery.isPending }
icon={ <IconSvg name="wallet" boxSize="24px" flexShrink={ 0 } color="text_secondary"/> }
icon={ <IconSvg name="wallet" boxSize="20px" flexShrink={ 0 } color="text_secondary"/> }
/>
<TokenBalancesItem
name={ `${ currencyUnits.ether } Balance` }
......
......@@ -86,7 +86,6 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
</Skeleton>
) : data.tx_count }
</Td>
{ !isRollup && !config.UI.views.block.hiddenFields?.total_reward && (
<Td fontSize="sm">
<Skeleton isLoaded={ !isLoading } display="inline-block">{ BigNumber(data.gas_used || 0).toFormat() }</Skeleton>
<Flex mt={ 2 }>
......@@ -107,12 +106,13 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
) }
</Flex>
</Td>
) }
{ !isRollup && !config.UI.views.block.hiddenFields?.total_reward && (
<Td fontSize="sm">
<Skeleton isLoaded={ !isLoading } display="inline-block">
{ totalReward.toFixed(8) }
</Skeleton>
</Td>
) }
{ !isRollup && !config.UI.views.block.hiddenFields?.burnt_fees && (
<Td fontSize="sm">
<Flex alignItems="center" columnGap={ 2 }>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment