Commit 4112b354 authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into feat/verified-tokens

parents 8963257c 28f21c4a
...@@ -28,7 +28,7 @@ jobs: ...@@ -28,7 +28,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Inject slug/short variables - name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v4 uses: rlespinasse/github-slug-action@v4.4.1
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
......
...@@ -24,7 +24,7 @@ jobs: ...@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Inject slug/short variables - name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v4 uses: rlespinasse/github-slug-action@v4.4.1
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
......
...@@ -24,7 +24,7 @@ jobs: ...@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Inject slug/short variables - name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v4 uses: rlespinasse/github-slug-action@v4.4.1
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
......
...@@ -15,9 +15,11 @@ NEXT_PUBLIC_NETWORK_LOGO= ...@@ -15,9 +15,11 @@ NEXT_PUBLIC_NETWORK_LOGO=
NEXT_PUBLIC_NETWORK_SMALL_LOGO= NEXT_PUBLIC_NETWORK_SMALL_LOGO=
NEXT_PUBLIC_NETWORK_RPC_URL=https://core.poa.network NEXT_PUBLIC_NETWORK_RPC_URL=https://core.poa.network
NEXT_PUBLIC_IS_TESTNET=true NEXT_PUBLIC_IS_TESTNET=true
NEXT_PUBLIC_IS_L2_NETWORK=false
# api config # api config
NEXT_PUBLIC_API_HOST=blockscout.com NEXT_PUBLIC_API_HOST=blockscout.com
NEXT_PUBLIC_STATS_API_HOST=https://stats-test.aws-k8s.blockscout.com NEXT_PUBLIC_STATS_API_HOST=https://stats-test.aws-k8s.blockscout.com
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info-test.aws-k8s.blockscout.com NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info-test.aws-k8s.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs-test.aws-k8s.blockscout.com NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs-test.aws-k8s.blockscout.com
...@@ -33,7 +33,7 @@ blockscout: ...@@ -33,7 +33,7 @@ blockscout:
ACCOUNT_AUTH0_CLIENT_ID: ACCOUNT_AUTH0_CLIENT_ID:
_default: ENC[AES256_GCM,data:xasZDDg1IuGbKSTm9Opjh43RcqDSzE3dMdmynP0gejo=,iv:TTRqPOkwMxAQIpmc7DklBoPdZzn3FsAprxwXtHY/KSk=,tag:ZI7zQ5zyjjYOqjzy2DyY7Q==,type:str] _default: ENC[AES256_GCM,data:xasZDDg1IuGbKSTm9Opjh43RcqDSzE3dMdmynP0gejo=,iv:TTRqPOkwMxAQIpmc7DklBoPdZzn3FsAprxwXtHY/KSk=,tag:ZI7zQ5zyjjYOqjzy2DyY7Q==,type:str]
ACCOUNT_AUTH0_CLIENT_SECRET: ACCOUNT_AUTH0_CLIENT_SECRET:
_default: ENC[AES256_GCM,data:iYnptgxESZs216/m0ArCciXfirPTxVjt5urKTATyYv3uadokC54ofzMZagG/ZVvNY48+Uxh4YGzwySyLOOM0SA==,iv:UQoZf3tesEjAJ7E5YruoZmVclsYfS5EmSo4z90wfHfE=,tag:er+hARrkCrjoQugqvRr4ow==,type:str] _default: ENC[AES256_GCM,data:jr/MLQ1Rq1xjBVAb/fZFbvak23hEcmRkh5nnG4WNCcORR+xEWhEv7ncP87ClpsfxedDN5pOcFrdUkF7u80OkKA==,iv:TIxP5v9K7mcApYmSKRByKNPwYw0djRWHojYfHvSWqZM=,tag:LSLmwapH044CEzOvlce9Og==,type:str]
ACCOUNT_AUTH0_CALLBACK_URL: ACCOUNT_AUTH0_CALLBACK_URL:
_default: ENC[AES256_GCM,data:GhyNTVlRvDpfW6swKExjVy65I3S+q6ITJWH8xp5TXuudp7hAtI4ujkYmXaa7D1BCaineTLhQ8UgHXFAgodOlrsGP1g41LIh6T2SGhrXTGGLbFw==,iv:ZflinC/h35jkrVAx0x7Z7U9mRridl85f7f6nfoc0Xts=,tag:40zL2KM9uPg/lRYv5JMxqw==,type:str] _default: ENC[AES256_GCM,data:GhyNTVlRvDpfW6swKExjVy65I3S+q6ITJWH8xp5TXuudp7hAtI4ujkYmXaa7D1BCaineTLhQ8UgHXFAgodOlrsGP1g41LIh6T2SGhrXTGGLbFw==,iv:ZflinC/h35jkrVAx0x7Z7U9mRridl85f7f6nfoc0Xts=,tag:40zL2KM9uPg/lRYv5JMxqw==,type:str]
ACCOUNT_AUTH0_LOGOUT_RETURN_URL: ACCOUNT_AUTH0_LOGOUT_RETURN_URL:
...@@ -144,8 +144,8 @@ sops: ...@@ -144,8 +144,8 @@ sops:
azure_kv: [] azure_kv: []
hc_vault: [] hc_vault: []
age: [] age: []
lastmodified: "2023-03-08T15:55:49Z" lastmodified: "2023-04-18T09:26:42Z"
mac: ENC[AES256_GCM,data:nl/CflZ5t09n3swP1vpR2rVjLVIW+H10/FCImDgeWuwt7F+0Whko3/UrPMypdfJeqiuCjWCmuynqjYqqZn2zjKabvc9bdo/RiQCyrdm7XIA+REA9XnKPnghYjkJYNm5kOLct5zif9Rq4wTfPOIpMRKnYvXrpnmiz5tE/lFXbYMw=,iv:mifwaplxQSJb5Q1CPWgR3hT5bTHTodNAoBEDKtdVLHI=,tag:rCAgVJxV52JV8O4CEZuLRg==,type:str] mac: ENC[AES256_GCM,data:4MdP3Fi3SDxyXjhyI7jogYdigziLkp7oh4M6BthtT2FuUu+XAGnONAdccxULJfXtKS6ue27BtV/pKWhdKeOqKIN23BJERqa4cFgYlyd85XAyL400/fEKEO4nCe2c9VIqNRUQls28/WkRjzRjvzQMMTIRIAJvfrJUYRpIabXWqAo=,iv:Z4shgbH8uJNuoJvmyyQjQ+fZsXuSC3nIGYb6GYO/nac=,tag:IDZvpGiZH41IwAgSidF3xQ==,type:str]
pgp: pgp:
- created_at: "2022-09-14T13:42:28Z" - created_at: "2022-09-14T13:42:28Z"
enc: | enc: |
......
...@@ -29,13 +29,13 @@ import type { BlocksResponse, BlockTransactionsResponse, Block, BlockFilters } f ...@@ -29,13 +29,13 @@ import type { BlocksResponse, BlockTransactionsResponse, Block, BlockFilters } f
import type { ChartMarketResponse, ChartTransactionResponse } from 'types/api/charts'; import type { ChartMarketResponse, ChartTransactionResponse } from 'types/api/charts';
import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod, SmartContractVerificationConfig } from 'types/api/contract'; import type { SmartContract, SmartContractReadMethod, SmartContractWriteMethod, SmartContractVerificationConfig } from 'types/api/contract';
import type { VerifiedContractsResponse, VerifiedContractsFilters, VerifiedContractsCounters } from 'types/api/contracts'; import type { VerifiedContractsResponse, VerifiedContractsFilters, VerifiedContractsCounters } from 'types/api/contracts';
import type { DepositsResponse } from 'types/api/deposits'; import type { DepositsResponse, DepositsItem } from 'types/api/deposits';
import type { IndexingStatus } from 'types/api/indexingStatus'; import type { IndexingStatus } from 'types/api/indexingStatus';
import type { InternalTransactionsResponse } from 'types/api/internalTransaction'; import type { InternalTransactionsResponse } from 'types/api/internalTransaction';
import type { LogsResponseTx, LogsResponseAddress } from 'types/api/log'; import type { LogsResponseTx, LogsResponseAddress } from 'types/api/log';
import type { OutputRootsResponse } from 'types/api/outputRoots'; import type { OutputRootsResponse } from 'types/api/outputRoots';
import type { RawTracesResponse } from 'types/api/rawTrace'; import type { RawTracesResponse } from 'types/api/rawTrace';
import type { SearchResult, SearchResultFilters } from 'types/api/search'; import type { SearchRedirectResult, SearchResult, SearchResultFilters } from 'types/api/search';
import type { Counters, StatsCharts, StatsChart, HomeStats } from 'types/api/stats'; import type { Counters, StatsCharts, StatsChart, HomeStats } from 'types/api/stats';
import type { import type {
TokenCounters, TokenCounters,
...@@ -54,7 +54,7 @@ import type { TTxsFilters } from 'types/api/txsFilters'; ...@@ -54,7 +54,7 @@ import type { TTxsFilters } from 'types/api/txsFilters';
import type { TxStateChanges } from 'types/api/txStateChanges'; import type { TxStateChanges } from 'types/api/txStateChanges';
import type { VisualizedContract } from 'types/api/visualization'; import type { VisualizedContract } from 'types/api/visualization';
import type { WithdrawalsResponse } from 'types/api/withdrawals'; import type { WithdrawalsResponse } from 'types/api/withdrawals';
import type ArrayElement from 'types/utils/ArrayElement'; import type { ArrayElement } from 'types/utils';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
...@@ -386,6 +386,9 @@ export const RESOURCES = { ...@@ -386,6 +386,9 @@ export const RESOURCES = {
homepage_blocks: { homepage_blocks: {
path: '/api/v2/main-page/blocks', path: '/api/v2/main-page/blocks',
}, },
homepage_deposits: {
path: '/api/v2/main-page/optimism-deposits',
},
homepage_txs: { homepage_txs: {
path: '/api/v2/main-page/transactions', path: '/api/v2/main-page/transactions',
}, },
...@@ -539,6 +542,7 @@ Q extends 'homepage_chart_txs' ? ChartTransactionResponse : ...@@ -539,6 +542,7 @@ Q extends 'homepage_chart_txs' ? ChartTransactionResponse :
Q extends 'homepage_chart_market' ? ChartMarketResponse : Q extends 'homepage_chart_market' ? ChartMarketResponse :
Q extends 'homepage_blocks' ? Array<Block> : Q extends 'homepage_blocks' ? Array<Block> :
Q extends 'homepage_txs' ? Array<Transaction> : Q extends 'homepage_txs' ? Array<Transaction> :
Q extends 'homepage_deposits' ? Array<DepositsItem> :
Q extends 'homepage_indexing_status' ? IndexingStatus : Q extends 'homepage_indexing_status' ? IndexingStatus :
Q extends 'stats_counters' ? Counters : Q extends 'stats_counters' ? Counters :
Q extends 'stats_lines' ? StatsCharts : Q extends 'stats_lines' ? StatsCharts :
...@@ -576,6 +580,7 @@ Q extends 'token_instance_transfers' ? TokenInstanceTransferResponse : ...@@ -576,6 +580,7 @@ Q extends 'token_instance_transfers' ? TokenInstanceTransferResponse :
Q extends 'token_inventory' ? TokenInventoryResponse : Q extends 'token_inventory' ? TokenInventoryResponse :
Q extends 'tokens' ? TokensResponse : Q extends 'tokens' ? TokensResponse :
Q extends 'search' ? SearchResult : Q extends 'search' ? SearchResult :
Q extends 'search_check_redirect' ? SearchRedirectResult :
Q extends 'contract' ? SmartContract : Q extends 'contract' ? SmartContract :
Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> : Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> :
Q extends 'contract_methods_read_proxy' ? Array<SmartContractReadMethod> : Q extends 'contract_methods_read_proxy' ? Array<SmartContractReadMethod> :
......
const old = Number.prototype.toLocaleString;
Number.prototype.toLocaleString = function(locale, ...args) {
return old.call(this, 'en', ...args);
};
export {};
...@@ -14,6 +14,7 @@ SocketMessage.TxStatusUpdate | ...@@ -14,6 +14,7 @@ SocketMessage.TxStatusUpdate |
SocketMessage.TxRawTrace | SocketMessage.TxRawTrace |
SocketMessage.NewTx | SocketMessage.NewTx |
SocketMessage.NewPendingTx | SocketMessage.NewPendingTx |
SocketMessage.NewDeposits |
SocketMessage.AddressBalance | SocketMessage.AddressBalance |
SocketMessage.AddressCurrentCoinBalance | SocketMessage.AddressCurrentCoinBalance |
SocketMessage.AddressTokenBalance | SocketMessage.AddressTokenBalance |
...@@ -42,6 +43,7 @@ export namespace SocketMessage { ...@@ -42,6 +43,7 @@ export namespace SocketMessage {
export type TxRawTrace = SocketMessageParamsGeneric<'raw_trace', RawTracesResponse>; export type TxRawTrace = SocketMessageParamsGeneric<'raw_trace', RawTracesResponse>;
export type NewTx = SocketMessageParamsGeneric<'transaction', { transaction: number }>; export type NewTx = SocketMessageParamsGeneric<'transaction', { transaction: number }>;
export type NewPendingTx = SocketMessageParamsGeneric<'pending_transaction', { pending_transaction: number }>; export type NewPendingTx = SocketMessageParamsGeneric<'pending_transaction', { pending_transaction: number }>;
export type NewDeposits = SocketMessageParamsGeneric<'deposits', { deposits: number }>;
export type AddressBalance = SocketMessageParamsGeneric<'balance', { balance: string; block_number: number; exchange_rate: string }>; export type AddressBalance = SocketMessageParamsGeneric<'balance', { balance: string; block_number: number; exchange_rate: string }>;
export type AddressCurrentCoinBalance = export type AddressCurrentCoinBalance =
SocketMessageParamsGeneric<'current_coin_balance', { coin_balance: string; block_number: number; exchange_rate: string }>; SocketMessageParamsGeneric<'current_coin_balance', { coin_balance: string; block_number: number; exchange_rate: string }>;
......
...@@ -6,12 +6,12 @@ export default function getConfirmationString(durations: Array<number>) { ...@@ -6,12 +6,12 @@ export default function getConfirmationString(durations: Array<number>) {
const [ lower, upper ] = durations.map((time) => time / 1_000); const [ lower, upper ] = durations.map((time) => time / 1_000);
if (!upper) { if (!upper) {
return `Confirmed within ${ lower } secs`; return `Confirmed within ${ lower.toLocaleString() } secs`;
} }
if (lower === 0) { if (lower === 0) {
return `Confirmed within <= ${ upper } secs`; return `Confirmed within <= ${ upper.toLocaleString() } secs`;
} }
return `Confirmed within ${ lower } - ${ upper } secs`; return `Confirmed within ${ lower.toLocaleString() } - ${ upper.toLocaleString() } secs`;
} }
...@@ -36,6 +36,7 @@ export const token: Address = { ...@@ -36,6 +36,7 @@ export const token: Address = {
name: null, name: null,
private_tags: [], private_tags: [],
watchlist_names: [], watchlist_names: [],
watchlist_address_id: null,
public_tags: [], public_tags: [],
token: tokenInfo, token: tokenInfo,
block_number_balance_updated_at: 8201413, block_number_balance_updated_at: 8201413,
...@@ -84,6 +85,7 @@ export const contract: Address = { ...@@ -84,6 +85,7 @@ export const contract: Address = {
public_tags: [ privateTag ], public_tags: [ privateTag ],
token: null, token: null,
watchlist_names: [ watchlistName ], watchlist_names: [ watchlistName ],
watchlist_address_id: 42,
}; };
export const validator: Address = { export const validator: Address = {
...@@ -113,4 +115,5 @@ export const validator: Address = { ...@@ -113,4 +115,5 @@ export const validator: Address = {
public_tags: [], public_tags: [],
token: null, token: null,
watchlist_names: [], watchlist_names: [],
watchlist_address_id: null,
}; };
...@@ -8,7 +8,12 @@ export const verified: Partial<SmartContract> = { ...@@ -8,7 +8,12 @@ export const verified: Partial<SmartContract> = {
constructor_args: 'constructor_args', constructor_args: 'constructor_args',
creation_bytecode: 'creation_bytecode', creation_bytecode: 'creation_bytecode',
deployed_bytecode: 'deployed_bytecode', deployed_bytecode: 'deployed_bytecode',
compiler_settings: 'compiler_settings', compiler_settings: {
evmVersion: 'london',
remappings: [
'@openzeppelin/=node_modules/@openzeppelin/',
],
},
evm_version: 'default', evm_version: 'default',
is_verified: true, is_verified: true,
name: 'WPOA', name: 'WPOA',
......
...@@ -39,5 +39,11 @@ export const withIndexedFields: DecodedInput = { ...@@ -39,5 +39,11 @@ export const withIndexedFields: DecodedInput = {
type: 'uint256', type: 'uint256',
value: '31567373703130350', value: '31567373703130350',
}, },
{
indexed: true,
name: 'inputArray',
type: 'uint256[2][2]',
value: [ [ '1', '1' ], [ '1', '1' ] ],
},
], ],
}; };
...@@ -242,3 +242,11 @@ export const withActionsUniswap: Transaction = { ...@@ -242,3 +242,11 @@ export const withActionsUniswap: Transaction = {
}, },
], ],
}; };
export const l2tx: Transaction = {
...base,
l1_gas_price: '82702201886',
l1_fee_scalar: '1.0',
l1_gas_used: '17060',
l1_fee: '1584574188135760',
};
...@@ -17,6 +17,8 @@ import AppError from 'ui/shared/AppError/AppError'; ...@@ -17,6 +17,8 @@ import AppError from 'ui/shared/AppError/AppError';
import ErrorBoundary from 'ui/shared/ErrorBoundary'; import ErrorBoundary from 'ui/shared/ErrorBoundary';
import GoogleAnalytics from 'ui/shared/GoogleAnalytics'; import GoogleAnalytics from 'ui/shared/GoogleAnalytics';
import 'lib/setLocale';
function MyApp({ Component, pageProps }: AppProps) { function MyApp({ Component, pageProps }: AppProps) {
useConfigSentry(); useConfigSentry();
const [ queryClient ] = useState(() => new QueryClient({ const [ queryClient ] = useState(() => new QueryClient({
......
import type { NextPage } from 'next'; import type { GetServerSideProps, NextPage } from 'next';
import Head from 'next/head'; import Head from 'next/head';
import React from 'react'; import React from 'react';
import appConfig from 'configs/app/config';
import getNetworkTitle from 'lib/networks/getNetworkTitle'; import getNetworkTitle from 'lib/networks/getNetworkTitle';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
import CsvExport from 'ui/pages/CsvExport'; import CsvExport from 'ui/pages/CsvExport';
const CsvExportPage: NextPage = () => { const CsvExportPage: NextPage = () => {
...@@ -19,4 +22,12 @@ const CsvExportPage: NextPage = () => { ...@@ -19,4 +22,12 @@ const CsvExportPage: NextPage = () => {
export default CsvExportPage; export default CsvExportPage;
export { getServerSideProps } from 'lib/next/getServerSideProps'; export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.reCaptcha.siteKey) {
return {
notFound: true,
};
}
return getServerSidePropsBase(args);
};
import type { GetServerSideProps, NextPage } from 'next'; import type { NextPage } from 'next';
import Head from 'next/head'; import Head from 'next/head';
import { route } from 'nextjs-routes';
import React from 'react'; import React from 'react';
import type { SearchRedirectResult } from 'types/api/search';
import buildUrlNode from 'lib/api/buildUrlNode';
import fetchFactory from 'lib/api/nodeFetch';
import getNetworkTitle from 'lib/networks/getNetworkTitle'; import getNetworkTitle from 'lib/networks/getNetworkTitle';
import type { Props } from 'lib/next/getServerSideProps';
import { getServerSideProps as getServerSidePropsBase } from 'lib/next/getServerSideProps';
import * as serverTiming from 'lib/next/serverTiming';
import SearchResults from 'ui/pages/SearchResults'; import SearchResults from 'ui/pages/SearchResults';
const SearchResultsPage: NextPage = () => { const SearchResultsPage: NextPage = () => {
...@@ -27,53 +19,4 @@ const SearchResultsPage: NextPage = () => { ...@@ -27,53 +19,4 @@ const SearchResultsPage: NextPage = () => {
export default SearchResultsPage; export default SearchResultsPage;
export const getServerSideProps: GetServerSideProps<Props> = async({ req, res, resolvedUrl, query }) => { export { getServerSideProps } from 'lib/next/getServerSideProps';
const start = Date.now();
try {
const q = String(query.q);
const url = buildUrlNode('search_check_redirect', undefined, { q });
const redirectsResponse = await fetchFactory(req)(url, {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore:next-line timeout property exist for AbortSignal since Node.js 17 - https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
// but @types/node has not updated their types yet, see issue https://github.com/DefinitelyTyped/DefinitelyTyped/issues/60868
signal: AbortSignal.timeout(1_000),
});
const payload = await redirectsResponse.json() as SearchRedirectResult;
if (!payload || typeof payload !== 'object' || !payload.redirect) {
throw Error();
}
const redirectUrl = (() => {
switch (payload.type) {
case 'block': {
return route({ pathname: '/block/[height]', query: { height: q } });
}
case 'address': {
return route({ pathname: '/address/[hash]', query: { hash: payload.parameter || q } });
}
case 'transaction': {
return route({ pathname: '/tx/[hash]', query: { hash: q } });
}
}
})();
if (!redirectUrl) {
throw Error();
}
return {
redirect: {
destination: redirectUrl,
permanent: false,
},
};
} catch (error) {}
const end = Date.now();
serverTiming.appendValue(res, 'query.search.check-redirect', end - start);
return getServerSidePropsBase({ req, res, resolvedUrl, query });
};
...@@ -32,6 +32,7 @@ export interface Address { ...@@ -32,6 +32,7 @@ export interface Address {
private_tags: Array<AddressTag> | null; private_tags: Array<AddressTag> | null;
public_tags: Array<AddressTag> | null; public_tags: Array<AddressTag> | null;
token: TokenInfo | null; token: TokenInfo | null;
watchlist_address_id: number | null;
watchlist_names: Array<WatchlistName> | null; watchlist_names: Array<WatchlistName> | null;
} }
......
...@@ -30,7 +30,10 @@ export interface SmartContract { ...@@ -30,7 +30,10 @@ export interface SmartContract {
file_path: string; file_path: string;
additional_sources: Array<{ file_path: string; source_code: string }>; additional_sources: Array<{ file_path: string; source_code: string }>;
external_libraries: Array<SmartContractExternalLibrary> | null; external_libraries: Array<SmartContractExternalLibrary> | null;
compiler_settings: unknown; compiler_settings?: {
evmVersion?: string;
remappings?: Array<string>;
};
verified_twin_address_hash: string | null; verified_twin_address_hash: string | null;
minimal_proxy_address_hash: string | null; minimal_proxy_address_hash: string | null;
} }
......
...@@ -7,6 +7,6 @@ export interface DecodedInput { ...@@ -7,6 +7,6 @@ export interface DecodedInput {
export interface DecodedInputParams { export interface DecodedInputParams {
name: string; name: string;
type: string; type: string;
value: string; value: string | Array<unknown> | Record<string, unknown>;
indexed?: boolean; indexed?: boolean;
} }
...@@ -42,7 +42,7 @@ export interface TokenInstance { ...@@ -42,7 +42,7 @@ export interface TokenInstance {
animation_url: string | null; animation_url: string | null;
external_app_url: string | null; external_app_url: string | null;
metadata: Record<string, unknown> | null; metadata: Record<string, unknown> | null;
owner: AddressParam; owner: AddressParam | null;
token: TokenInfo; token: TokenInfo;
} }
......
...@@ -9,16 +9,9 @@ export type TransactionRevertReason = { ...@@ -9,16 +9,9 @@ export type TransactionRevertReason = {
raw: string; raw: string;
} | DecodedInput; } | DecodedInput;
export type Transaction = ( export type Transaction = {
{ to: AddressParam | null;
to: AddressParam; created_contract: AddressParam | null;
created_contract: null;
} |
{
to: null;
created_contract: AddressParam;
}
) & {
hash: string; hash: string;
result: string; result: string;
confirmations: number; confirmations: number;
...@@ -50,6 +43,10 @@ export type Transaction = ( ...@@ -50,6 +43,10 @@ export type Transaction = (
tx_types: Array<TransactionType>; tx_types: Array<TransactionType>;
tx_tag: string | null; tx_tag: string | null;
actions: Array<TxAction>; actions: Array<TxAction>;
l1_fee?: string;
l1_fee_scalar?: string;
l1_gas_price?: string;
l1_gas_used?: string;
} }
export type TransactionsResponse = TransactionsResponseValidated | TransactionsResponsePending; export type TransactionsResponse = TransactionsResponseValidated | TransactionsResponsePending;
......
export type ArrayElement<ArrayType extends Array<unknown>> =
ArrayType extends Array<(infer ElementType)> ? ElementType : never;
export type ExcludeNull<T> = T extends null ? never : T;
export type KeysOfObjectOrNull<T> = keyof ExcludeNull<T>;
type ArrayElement<ArrayType extends Array<unknown>> =
ArrayType extends Array<(infer ElementType)> ? ElementType : never;
export default ArrayElement;
export type ExcludeNull<T> = T extends null ? never : T;
import type { ExcludeNull } from './ExcludeNull';
export type KeysOfObjectOrNull<T> = keyof ExcludeNull<T>;
...@@ -4,6 +4,7 @@ import React from 'react'; ...@@ -4,6 +4,7 @@ import React from 'react';
import type { CsvExportType } from 'types/client/address'; import type { CsvExportType } from 'types/client/address';
import appConfig from 'configs/app/config';
import svgFileIcon from 'icons/files/csv.svg'; import svgFileIcon from 'icons/files/csv.svg';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
...@@ -17,6 +18,10 @@ interface Props { ...@@ -17,6 +18,10 @@ interface Props {
const AddressCsvExportLink = ({ className, address, type }: Props) => { const AddressCsvExportLink = ({ className, address, type }: Props) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
if (!appConfig.reCaptcha.siteKey) {
return null;
}
return ( return (
<Tooltip isDisabled={ !isMobile } label="Download CSV"> <Tooltip isDisabled={ !isMobile } label="Download CSV">
<LinkInternal <LinkInternal
......
...@@ -56,6 +56,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -56,6 +56,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
implementation_name: null, implementation_name: null,
implementation_address: null, implementation_address: null,
token: null, token: null,
watchlist_address_id: null,
watchlist_names: null, watchlist_names: null,
creation_tx_hash: null, creation_tx_hash: null,
block_number_balance_updated_at: null, block_number_balance_updated_at: null,
......
...@@ -201,6 +201,7 @@ const ContractCode = ({ addressHash, noSocket }: Props) => { ...@@ -201,6 +201,7 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
isViper={ Boolean(data.is_vyper_contract) } isViper={ Boolean(data.is_vyper_contract) }
filePath={ data.file_path } filePath={ data.file_path }
additionalSource={ data.additional_sources } additionalSource={ data.additional_sources }
remappings={ data.compiler_settings?.remappings }
/> />
) } ) }
{ Boolean(data.compiler_settings) && ( { Boolean(data.compiler_settings) && (
......
...@@ -20,7 +20,7 @@ interface ResultComponentProps<T extends SmartContractMethod> { ...@@ -20,7 +20,7 @@ interface ResultComponentProps<T extends SmartContractMethod> {
interface Props<T extends SmartContractMethod> { interface Props<T extends SmartContractMethod> {
data: T; data: T;
onSubmit: (data: T, args: Array<string | Array<string>>) => Promise<ContractMethodCallResult<T>>; onSubmit: (data: T, args: Array<string | Array<unknown>>) => Promise<ContractMethodCallResult<T>>;
ResultComponent: (props: ResultComponentProps<T>) => JSX.Element | null; ResultComponent: (props: ResultComponentProps<T>) => JSX.Element | null;
isWrite?: boolean; isWrite?: boolean;
} }
...@@ -44,13 +44,23 @@ const sortFields = (data: Array<SmartContractMethodInput>) => ([ a ]: [string, s ...@@ -44,13 +44,23 @@ const sortFields = (data: Array<SmartContractMethodInput>) => ([ a ]: [string, s
}; };
const castFieldValue = (data: Array<SmartContractMethodInput>) => ([ key, value ]: [ string, string ], index: number) => { const castFieldValue = (data: Array<SmartContractMethodInput>) => ([ key, value ]: [ string, string ], index: number) => {
if (data[index].type.includes('[]')) { if (data[index].type.includes('[')) {
return [ key, parseArrayValue(value) ]; return [ key, parseArrayValue(value) ];
} }
return [ key, value ]; return [ key, value ];
}; };
const parseArrayValue = (value: string) => value.replace(/(\[|\])|\s/g, '').split(','); const parseArrayValue = (value: string) => {
try {
const parsedResult = JSON.parse(value);
if (Array.isArray(parsedResult)) {
return parsedResult;
}
throw new Error('Not an array');
} catch (error) {
return '';
}
};
const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit, ResultComponent, isWrite }: Props<T>) => { const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit, ResultComponent, isWrite }: Props<T>) => {
......
...@@ -64,7 +64,7 @@ const ContractMethodField = ({ control, name, valueType, placeholder, setValue, ...@@ -64,7 +64,7 @@ const ContractMethodField = ({ control, name, valueType, placeholder, setValue,
/> />
<InputRightElement w="auto" right={ 1 }> <InputRightElement w="auto" right={ 1 }>
{ field.value && <InputClearButton onClick={ handleClear } isDisabled={ isDisabled }/> } { field.value && <InputClearButton onClick={ handleClear } isDisabled={ isDisabled }/> }
{ hasZerosControl && <ContractMethodFieldZeroes onClick={ handleAddZeroesClick }/> } { hasZerosControl && <ContractMethodFieldZeroes onClick={ handleAddZeroesClick } isDisabled={ isDisabled }/> }
</InputRightElement> </InputRightElement>
</InputGroup> </InputGroup>
</FormControl> </FormControl>
......
...@@ -20,9 +20,10 @@ import { times } from 'lib/html-entities'; ...@@ -20,9 +20,10 @@ import { times } from 'lib/html-entities';
interface Props { interface Props {
onClick: (power: number) => void; onClick: (power: number) => void;
isDisabled?: boolean;
} }
const ContractMethodFieldZeroes = ({ onClick }: Props) => { const ContractMethodFieldZeroes = ({ onClick, isDisabled }: Props) => {
const [ selectedOption, setSelectedOption ] = React.useState<number | undefined>(18); const [ selectedOption, setSelectedOption ] = React.useState<number | undefined>(18);
const [ customValue, setCustomValue ] = React.useState<number>(); const [ customValue, setCustomValue ] = React.useState<number>();
const { isOpen, onToggle, onClose } = useDisclosure(); const { isOpen, onToggle, onClose } = useDisclosure();
...@@ -60,6 +61,7 @@ const ContractMethodFieldZeroes = ({ onClick }: Props) => { ...@@ -60,6 +61,7 @@ const ContractMethodFieldZeroes = ({ onClick }: Props) => {
colorScheme="gray" colorScheme="gray"
display="inline" display="inline"
onClick={ handleButtonClick } onClick={ handleButtonClick }
isDisabled={ isDisabled }
> >
{ times } { times }
<chakra.span>10</chakra.span> <chakra.span>10</chakra.span>
...@@ -76,6 +78,7 @@ const ContractMethodFieldZeroes = ({ onClick }: Props) => { ...@@ -76,6 +78,7 @@ const ContractMethodFieldZeroes = ({ onClick }: Props) => {
ml={ 1 } ml={ 1 }
p={ 0 } p={ 0 }
onClick={ onToggle } onClick={ onToggle }
isDisabled={ isDisabled }
> >
<Icon as={ iconEastMini } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } boxSize={ 6 }/> <Icon as={ iconEastMini } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } boxSize={ 6 }/>
</Button> </Button>
......
...@@ -38,7 +38,7 @@ const ContractRead = ({ addressHash, isProxy, isCustomAbi }: Props) => { ...@@ -38,7 +38,7 @@ const ContractRead = ({ addressHash, isProxy, isCustomAbi }: Props) => {
}, },
}); });
const handleMethodFormSubmit = React.useCallback(async(item: SmartContractReadMethod, args: Array<string | Array<string>>) => { const handleMethodFormSubmit = React.useCallback(async(item: SmartContractReadMethod, args: Array<string | Array<unknown>>) => {
return apiFetch<'contract_method_query', SmartContractQueryMethodRead>('contract_method_query', { return apiFetch<'contract_method_query', SmartContractQueryMethodRead>('contract_method_query', {
pathParams: { hash: addressHash }, pathParams: { hash: addressHash },
queryParams: { queryParams: {
......
...@@ -16,9 +16,10 @@ interface Props { ...@@ -16,9 +16,10 @@ interface Props {
isViper: boolean; isViper: boolean;
filePath?: string; filePath?: string;
additionalSource?: SmartContract['additional_sources']; additionalSource?: SmartContract['additional_sources'];
remappings?: Array<string>;
} }
const ContractSourceCode = ({ data, hasSol2Yml, address, isViper, filePath, additionalSource }: Props) => { const ContractSourceCode = ({ data, hasSol2Yml, address, isViper, filePath, additionalSource, remappings }: Props) => {
const heading = ( const heading = (
<Text fontWeight={ 500 }> <Text fontWeight={ 500 }>
<span>Contract source code</span> <span>Contract source code</span>
...@@ -56,7 +57,7 @@ const ContractSourceCode = ({ data, hasSol2Yml, address, isViper, filePath, addi ...@@ -56,7 +57,7 @@ const ContractSourceCode = ({ data, hasSol2Yml, address, isViper, filePath, addi
{ diagramLink } { diagramLink }
{ copyToClipboard } { copyToClipboard }
</Flex> </Flex>
<CodeEditor data={ editorData }/> <CodeEditor data={ editorData } remappings={ remappings }/>
</section> </section>
); );
}; };
......
...@@ -51,7 +51,7 @@ const ContractWrite = ({ addressHash, isProxy, isCustomAbi }: Props) => { ...@@ -51,7 +51,7 @@ const ContractWrite = ({ addressHash, isProxy, isCustomAbi }: Props) => {
return contract; return contract;
})(); })();
const handleMethodFormSubmit = React.useCallback(async(item: SmartContractWriteMethod, args: Array<string | Array<string>>) => { const handleMethodFormSubmit = React.useCallback(async(item: SmartContractWriteMethod, args: Array<string | Array<unknown>>) => {
if (!isConnected) { if (!isConnected) {
throw new Error('Wallet is not connected'); throw new Error('Wallet is not connected');
} }
......
...@@ -2,13 +2,18 @@ import BigNumber from 'bignumber.js'; ...@@ -2,13 +2,18 @@ import BigNumber from 'bignumber.js';
import config from 'configs/app/config'; import config from 'configs/app/config';
export const getNativeCoinValue = (value: string | Array<string>) => { export const getNativeCoinValue = (value: string | Array<unknown>) => {
const _value = Array.isArray(value) ? value[0] : value; const _value = Array.isArray(value) ? value[0] : value;
if (typeof _value !== 'string') {
return '0';
}
return BigNumber(_value).times(10 ** config.network.currency.decimals).toString(); return BigNumber(_value).times(10 ** config.network.currency.decimals).toString();
}; };
export const addZeroesAllowed = (valueType: string) => { export const addZeroesAllowed = (valueType: string) => {
if (valueType.includes('[]')) { if (valueType.includes('[')) {
return false; return false;
} }
......
...@@ -5,7 +5,7 @@ import React from 'react'; ...@@ -5,7 +5,7 @@ import React from 'react';
import starFilledIcon from 'icons/star_filled.svg'; import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg'; import starOutlineIcon from 'icons/star_outline.svg';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing'; import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
import useRedirectIfNotAuth from 'lib/hooks/useRedirectIfNotAuth'; import useRedirectIfNotAuth from 'lib/hooks/useRedirectIfNotAuth';
import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal'; import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal';
...@@ -14,23 +14,22 @@ import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal'; ...@@ -14,23 +14,22 @@ import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal';
interface Props { interface Props {
className?: string; className?: string;
hash: string; hash: string;
isAdded: boolean; watchListId: number | null;
} }
const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => { const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => {
const addModalProps = useDisclosure(); const addModalProps = useDisclosure();
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const router = useRouter(); const router = useRouter();
const redirectIfNotAuth = useRedirectIfNotAuth(); const redirectIfNotAuth = useRedirectIfNotAuth();
const watchListQuery = useApiQuery('watchlist', { queryOptions: { enabled: isAdded } });
const handleClick = React.useCallback(() => { const handleClick = React.useCallback(() => {
if (redirectIfNotAuth()) { if (redirectIfNotAuth()) {
return; return;
} }
isAdded ? deleteModalProps.onOpen() : addModalProps.onOpen(); watchListId ? deleteModalProps.onOpen() : addModalProps.onOpen();
}, [ addModalProps, deleteModalProps, isAdded, redirectIfNotAuth ]); }, [ addModalProps, deleteModalProps, watchListId, redirectIfNotAuth ]);
const handleAddOrDeleteSuccess = React.useCallback(async() => { const handleAddOrDeleteSuccess = React.useCallback(async() => {
const queryKey = getResourceKey('address', { pathParams: { hash: router.query.hash?.toString() } }); const queryKey = getResourceKey('address', { pathParams: { hash: router.query.hash?.toString() } });
...@@ -49,18 +48,15 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => { ...@@ -49,18 +48,15 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
const formData = React.useMemo(() => { const formData = React.useMemo(() => {
return { return {
address_hash: hash, address_hash: hash,
// FIXME temporary solution id: String(watchListId),
// there is no endpoint in api what can return watchlist address info by its hash
// so we look up in the whole watchlist and hope we can find a necessary item
id: watchListQuery.data?.find((address) => address.address?.hash === hash)?.id || '',
}; };
}, [ hash, watchListQuery.data ]); }, [ hash, watchListId ]);
return ( return (
<> <>
<Tooltip label={ `${ isAdded ? 'Remove address from Watch list' : 'Add address to Watch list' }` }> <Tooltip label={ `${ watchListId ? 'Remove address from Watch list' : 'Add address to Watch list' }` }>
<IconButton <IconButton
isActive={ isAdded } isActive={ Boolean(watchListId) }
className={ className } className={ className }
aria-label="edit" aria-label="edit"
variant="outline" variant="outline"
...@@ -68,7 +64,7 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => { ...@@ -68,7 +64,7 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
pl="6px" pl="6px"
pr="6px" pr="6px"
onClick={ handleClick } onClick={ handleClick }
icon={ <Icon as={ isAdded ? starFilledIcon : starOutlineIcon } boxSize={ 5 }/> } icon={ <Icon as={ watchListId ? starFilledIcon : starOutlineIcon } boxSize={ 5 }/> }
onFocusCapture={ usePreventFocusAfterModalClosing() } onFocusCapture={ usePreventFocusAfterModalClosing() }
/> />
</Tooltip> </Tooltip>
......
...@@ -83,7 +83,7 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -83,7 +83,7 @@ const TokenSelect = ({ onClick }: Props) => {
} }
<Tooltip label="Show all tokens"> <Tooltip label="Show all tokens">
<Box> <Box>
<NextLink href={{ pathname: '/address/[hash]', query: { hash: addressHash, tab: 'tokens' } }} passHref> <NextLink href={{ pathname: '/address/[hash]', query: { hash: addressHash, tab: 'tokens' } }} passHref legacyBehavior>
<IconButton <IconButton
aria-label="Show all tokens" aria-label="Show all tokens"
variant="outline" variant="outline"
......
...@@ -55,7 +55,7 @@ const AddressesListItem = ({ ...@@ -55,7 +55,7 @@ const AddressesListItem = ({
) } ) }
<HStack spacing={ 3 }> <HStack spacing={ 3 }>
<Text fontSize="sm" fontWeight={ 500 }>Txn count</Text> <Text fontSize="sm" fontWeight={ 500 }>Txn count</Text>
<Text fontSize="sm" variant="secondary">{ Number(item.tx_count).toLocaleString('en') }</Text> <Text fontSize="sm" variant="secondary">{ Number(item.tx_count).toLocaleString() }</Text>
</HStack> </HStack>
</ListItemMobile> </ListItemMobile>
); );
......
...@@ -60,7 +60,7 @@ const AddressesTableItem = ({ ...@@ -60,7 +60,7 @@ const AddressesTableItem = ({
</Td> </Td>
) } ) }
<Td isNumeric> <Td isNumeric>
<Text lineHeight="24px">{ Number(item.tx_count).toLocaleString('en') }</Text> <Text lineHeight="24px">{ Number(item.tx_count).toLocaleString() }</Text>
</Td> </Td>
</Tr> </Tr>
); );
......
...@@ -15,7 +15,7 @@ const AppLink = ({ url, external, id, title }: Props) => { ...@@ -15,7 +15,7 @@ const AppLink = ({ url, external, id, title }: Props) => {
{ title } { title }
</LinkOverlay> </LinkOverlay>
) : ( ) : (
<NextLink href={{ pathname: '/apps/[id]', query: { id } }} passHref> <NextLink href={{ pathname: '/apps/[id]', query: { id } }} passHref legacyBehavior>
<LinkOverlay> <LinkOverlay>
{ title } { title }
</LinkOverlay> </LinkOverlay>
......
...@@ -27,7 +27,7 @@ const AppModalLink = ({ url, external, id }: Props) => { ...@@ -27,7 +27,7 @@ const AppModalLink = ({ url, external, id }: Props) => {
{ ...buttonProps } { ...buttonProps }
>Launch app</Button> >Launch app</Button>
) : ( ) : (
<NextLink href={{ pathname: '/apps/[id]', query: { id } }} passHref> <NextLink href={{ pathname: '/apps/[id]', query: { id } }} passHref legacyBehavior>
<Button <Button
as="a" as="a"
{ ...buttonProps } { ...buttonProps }
......
...@@ -112,7 +112,7 @@ const BlockDetails = ({ query }: Props) => { ...@@ -112,7 +112,7 @@ const BlockDetails = ({ query }: Props) => {
title="Size" title="Size"
hint="Size of the block in bytes" hint="Size of the block in bytes"
> >
{ data.size.toLocaleString('en') } { data.size.toLocaleString() }
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="Timestamp" title="Timestamp"
......
...@@ -48,7 +48,7 @@ const BlocksListItem = ({ data, isPending, enableTimeIncrement }: Props) => { ...@@ -48,7 +48,7 @@ const BlocksListItem = ({ data, isPending, enableTimeIncrement }: Props) => {
</Flex> </Flex>
<Flex columnGap={ 2 }> <Flex columnGap={ 2 }>
<Text fontWeight={ 500 }>Size</Text> <Text fontWeight={ 500 }>Size</Text>
<Text variant="secondary">{ data.size.toLocaleString('en') } bytes</Text> <Text variant="secondary">{ data.size.toLocaleString() } bytes</Text>
</Flex> </Flex>
<Flex columnGap={ 2 }> <Flex columnGap={ 2 }>
<Text fontWeight={ 500 }>{ capitalize(getNetworkValidatorTitle()) }</Text> <Text fontWeight={ 500 }>{ capitalize(getNetworkValidatorTitle()) }</Text>
......
...@@ -53,7 +53,7 @@ const BlocksTableItem = ({ data, isPending, enableTimeIncrement }: Props) => { ...@@ -53,7 +53,7 @@ const BlocksTableItem = ({ data, isPending, enableTimeIncrement }: Props) => {
</Flex> </Flex>
<BlockTimestamp ts={ data.timestamp } isEnabled={ enableTimeIncrement }/> <BlockTimestamp ts={ data.timestamp } isEnabled={ enableTimeIncrement }/>
</Td> </Td>
<Td fontSize="sm">{ data.size.toLocaleString('en') }</Td> <Td fontSize="sm">{ data.size.toLocaleString() }</Td>
<Td fontSize="sm"> <Td fontSize="sm">
<AddressLink type="address" alias={ data.miner.name } hash={ data.miner.hash } truncation="constant" display="inline-flex" maxW="100%"/> <AddressLink type="address" alias={ data.miner.name } hash={ data.miner.hash } truncation="constant" display="inline-flex" maxW="100%"/>
</Td> </Td>
......
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import * as depositMock from 'mocks/deposits/deposits';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import LatestDeposits from './LatestDeposits';
test('default view +@mobile +@dark-mode', async({ mount, page }) => {
await page.route(buildApiUrl('homepage_deposits'), (route) => route.fulfill({
status: 200,
body: JSON.stringify(depositMock.data.items),
}));
const component = await mount(
<TestApp>
<LatestDeposits/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
import { Box, Flex, Text, Skeleton } from '@chakra-ui/react';
import { route } from 'nextjs-routes';
import React from 'react';
import type { SocketMessage } from 'lib/socket/types';
import useApiQuery from 'lib/api/useApiQuery';
import useGradualIncrement from 'lib/hooks/useGradualIncrement';
import useIsMobile from 'lib/hooks/useIsMobile';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import LinkInternal from 'ui/shared/LinkInternal';
import SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import LatestDepositsItem from './LatestDepositsItem';
import LatestDepositsItemSkeleton from './LatestDepositsItemSkeleton';
const LatestDeposits = () => {
const isMobile = useIsMobile();
const itemsCount = isMobile ? 2 : 6;
const { data, isLoading, isError } = useApiQuery('homepage_deposits');
const [ num, setNum ] = useGradualIncrement(0);
const [ socketAlert, setSocketAlert ] = React.useState('');
const handleSocketClose = React.useCallback(() => {
setSocketAlert('Connection is lost. Please reload page.');
}, []);
const handleSocketError = React.useCallback(() => {
setSocketAlert('An error has occurred while fetching new transactions. Please reload page.');
}, []);
const handleNewDepositMessage: SocketMessage.NewDeposits['handler'] = React.useCallback((payload) => {
setNum(payload.deposits);
}, [ setNum ]);
const channel = useSocketChannel({
topic: 'optimism_deposits:new_deposits',
onSocketClose: handleSocketClose,
onSocketError: handleSocketError,
isDisabled: false,
});
useSocketMessage({
channel,
event: 'deposits',
handler: handleNewDepositMessage,
});
if (isLoading) {
return (
<>
<Skeleton h="32px" w="100%" borderBottomLeftRadius={ 0 } borderBottomRightRadius={ 0 }/>
{ Array.from(Array(itemsCount)).map((item, index) => <LatestDepositsItemSkeleton key={ index }/>) }
</>
);
}
if (isError) {
return <Text mt={ 4 }>No data. Please reload page.</Text>;
}
if (data) {
const depositsUrl = route({ pathname: '/deposits' });
return (
<>
<SocketNewItemsNotice borderBottomRadius={ 0 } url={ depositsUrl } num={ num } alert={ socketAlert } type="deposit"/>
<Box mb={{ base: 3, lg: 4 }}>
{ data.slice(0, itemsCount).map((item => <LatestDepositsItem key={ item.l2_tx_hash } item={ item }/>)) }
</Box>
<Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ depositsUrl }>View all deposits</LinkInternal>
</Flex>
</>
);
}
return null;
};
export default LatestDeposits;
import {
Box,
Flex,
Grid,
Icon,
Text,
} from '@chakra-ui/react';
import { route } from 'nextjs-routes';
import React from 'react';
import type { DepositsItem } from 'types/api/deposits';
import appConfig from 'configs/app/config';
import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import useIsMobile from 'lib/hooks/useIsMobile';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
type Props = {
item: DepositsItem;
}
const LatestTxsItem = ({ item }: Props) => {
const timeAgo = dayjs(item.l1_block_timestamp).fromNow();
const isMobile = useIsMobile();
const l1BlockLink = (
<LinkExternal
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/block/[height]', query: { height: item.l1_block_number.toString() } }) }
fontWeight={ 700 }
display="inline-flex"
mr={ 2 }
>
<Icon as={ blockIcon } boxSize="30px" mr={ 1 }/>
{ item.l1_block_number }
</LinkExternal>
);
const l1TxLink = (
<LinkExternal
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
maxW="100%"
display="inline-flex"
alignItems="center"
overflow="hidden"
>
<Icon as={ txIcon } boxSize={ 6 } mr={ 1 }/>
<Box overflow="hidden" whiteSpace="nowrap"><HashStringShortenDynamic hash={ item.l1_tx_hash }/></Box>
</LinkExternal>
);
const l2TxLink = (
<LinkInternal
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
display="flex"
alignItems="center"
overflow="hidden"
w="100%"
>
<Icon as={ txIcon } boxSize={ 6 } mr={ 1 }/>
<Box w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap"><HashStringShortenDynamic hash={ item.l2_tx_hash }/></Box>
</LinkInternal>
);
const content = (() => {
if (isMobile) {
return (
<>
<Flex justifyContent="space-between" alignItems="center" mb={ 1 }>
{ l1BlockLink }
<Text variant="secondary">{ timeAgo }</Text>
</Flex>
<Grid gridTemplateColumns="56px auto">
<Text lineHeight="30px">L1 txn</Text>
{ l1TxLink }
<Text lineHeight="30px">L2 txn</Text>
{ l2TxLink }
</Grid>
</>
);
}
return (
<Grid width="100%" columnGap={ 4 } rowGap={ 2 } templateColumns="max-content max-content auto" w="100%">
{ l1BlockLink }
<Text lineHeight="30px">L1 txn</Text>
{ l1TxLink }
<Text variant="secondary">{ timeAgo }</Text>
<Text lineHeight="30px">L2 txn</Text>
{ l2TxLink }
</Grid>
);
})();
return (
<Box
width="100%"
borderTop="1px solid"
borderColor="divider"
py={ 4 }
px={{ base: 0, lg: 4 }}
_last={{ borderBottom: '1px solid', borderColor: 'divider' }}
fontSize="sm"
>
{ content }
</Box>
);
};
export default React.memo(LatestTxsItem);
import {
Box,
Flex,
Skeleton,
} from '@chakra-ui/react';
import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile';
const LatestTxsItemSkeleton = () => {
const isMobile = useIsMobile();
return (
<Box
width="100%"
borderTop="1px solid"
borderColor="divider"
py={ 4 }
px={{ base: 0, lg: 4 }}
_last={{ borderBottom: '1px solid', borderColor: 'divider' }}
>
{ isMobile && (
<>
<Flex justifyContent="space-between" alignItems="center" mt={ 1 } mb={ 4 }>
<Skeleton w="120px" h="20px"></Skeleton>
<Skeleton w="80px" h="20px"></Skeleton>
</Flex>
<Skeleton w="100%" h="20px" mb={ 2 }></Skeleton>
<Skeleton w="100%" h="20px" mb={ 2 }></Skeleton>
</>
) }
{ !isMobile && (
<>
<Flex w="100%" mb={ 2 } h="30px" alignItems="center" justifyContent="space-between">
<Skeleton w="120px" h="20px"></Skeleton>
<Skeleton w="calc(100% - 120px - 48px)" h="20px"></Skeleton>
</Flex><Flex w="100%" h="30px" alignItems="center" justifyContent="space-between">
<Skeleton w="120px" h="20px"></Skeleton>
<Skeleton w="calc(100% - 120px - 48px)" h="20px"></Skeleton>
</Flex>
</>
) }
</Box>
);
};
export default LatestTxsItemSkeleton;
import { Box, Heading, Flex, Text, Skeleton } from '@chakra-ui/react'; import { Box, Flex, Text, Skeleton } from '@chakra-ui/react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import React from 'react'; import React from 'react';
...@@ -18,10 +18,8 @@ const LatestTransactions = () => { ...@@ -18,10 +18,8 @@ const LatestTransactions = () => {
const { num, socketAlert } = useNewTxsSocket(); const { num, socketAlert } = useNewTxsSocket();
let content;
if (isLoading) { if (isLoading) {
content = ( return (
<> <>
<Skeleton h="32px" w="100%" borderBottomLeftRadius={ 0 } borderBottomRightRadius={ 0 }/> <Skeleton h="32px" w="100%" borderBottomLeftRadius={ 0 } borderBottomRightRadius={ 0 }/>
{ Array.from(Array(txsCount)).map((item, index) => <LatestTxsItemSkeleton key={ index }/>) } { Array.from(Array(txsCount)).map((item, index) => <LatestTxsItemSkeleton key={ index }/>) }
...@@ -30,12 +28,12 @@ const LatestTransactions = () => { ...@@ -30,12 +28,12 @@ const LatestTransactions = () => {
} }
if (isError) { if (isError) {
content = <Text mt={ 4 }>No data. Please reload page.</Text>; return <Text mt={ 4 }>No data. Please reload page.</Text>;
} }
if (data) { if (data) {
const txsUrl = route({ pathname: '/txs' }); const txsUrl = route({ pathname: '/txs' });
content = ( return (
<> <>
<SocketNewItemsNotice borderBottomRadius={ 0 } url={ txsUrl } num={ num } alert={ socketAlert }/> <SocketNewItemsNotice borderBottomRadius={ 0 } url={ txsUrl } num={ num } alert={ socketAlert }/>
<Box mb={{ base: 3, lg: 4 }}> <Box mb={{ base: 3, lg: 4 }}>
...@@ -48,12 +46,7 @@ const LatestTransactions = () => { ...@@ -48,12 +46,7 @@ const LatestTransactions = () => {
); );
} }
return ( return null;
<Box flexGrow={ 1 }>
<Heading as="h4" size="sm" mb={ 4 }>Latest transactions</Heading>
{ content }
</Box>
);
}; };
export default LatestTransactions; export default LatestTransactions;
...@@ -97,18 +97,20 @@ const LatestTxsItem = ({ tx }: Props) => { ...@@ -97,18 +97,20 @@ const LatestTxsItem = ({ tx }: Props) => {
mx={ 2 } mx={ 2 }
color="gray.500" color="gray.500"
/> />
<Address> { dataTo && (
<AddressIcon address={ dataTo }/> <Address>
<AddressLink <AddressIcon address={ dataTo }/>
type="address" <AddressLink
hash={ dataTo.hash } type="address"
alias={ dataTo.name } hash={ dataTo.hash }
fontWeight="500" alias={ dataTo.name }
ml={ 2 } fontWeight="500"
truncation="constant" ml={ 2 }
fontSize="sm" truncation="constant"
/> fontSize="sm"
</Address> />
</Address>
) }
</Flex> </Flex>
<Flex fontSize="sm" justifyContent="end" flexDirection={{ base: 'column', lg: 'row' }}> <Flex fontSize="sm" justifyContent="end" flexDirection={{ base: 'column', lg: 'row' }}>
<Box mr={{ base: 0, lg: 3 }} mb={{ base: 2, lg: 0 }}> <Box mr={{ base: 0, lg: 3 }} mb={{ base: 2, lg: 0 }}>
......
import { Heading, Tab, Tabs, TabList, TabPanel, TabPanels } from '@chakra-ui/react';
import React from 'react';
import appConfig from 'configs/app/config';
import LatestDeposits from 'ui/home/LatestDeposits';
import LatestTxs from 'ui/home/LatestTxs';
const TransactionsHome = () => {
if (appConfig.L2.isL2Network) {
return (
<>
<Heading as="h4" size="sm" mb={ 4 }>Transactions</Heading>
<Tabs isLazy lazyBehavior="keepMounted" defaultIndex={ 0 } variant="soft-rounded">
<TabList>
<Tab key="txn">Latest txn</Tab>
<Tab key="deposits">Deposits (L1→L2 txn)</Tab>
</TabList>
<TabPanels mt={ 4 }>
<TabPanel key="txn" p={ 0 }>
<LatestTxs/>
</TabPanel>
<TabPanel key="deposits" p={ 0 }>
<LatestDeposits/>
</TabPanel>
</TabPanels>
</Tabs>
</>
);
}
return (
<>
<Heading as="h4" size="sm" mb={ 4 }>Latest transactions</Heading>
<LatestTxs/>
</>
);
};
export default TransactionsHome;
...@@ -12,7 +12,7 @@ import TokenLogo from 'ui/shared/TokenLogo'; ...@@ -12,7 +12,7 @@ import TokenLogo from 'ui/shared/TokenLogo';
const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = { const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
id: 'daily_txs', id: 'daily_txs',
title: 'Daily transactions', title: 'Daily transactions',
value: (stats) => Number(stats.transactions_today).toLocaleString('en', { maximumFractionDigits: 2, notation: 'compact' }), value: (stats) => Number(stats.transactions_today).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
icon: <Icon as={ txIcon } boxSize={ 6 } bgColor="#56ACD1" borderRadius="base" color="white"/>, icon: <Icon as={ txIcon } boxSize={ 6 } bgColor="#56ACD1" borderRadius="base" color="white"/>,
hint: `The total daily number of transactions on the blockchain for the last month.`, hint: `The total daily number of transactions on the blockchain for the last month.`,
api: { api: {
...@@ -22,7 +22,7 @@ const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = { ...@@ -22,7 +22,7 @@ const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
.map((item) => ({ date: new Date(item.date), value: item.tx_count })) .map((item) => ({ date: new Date(item.date), value: item.tx_count }))
.sort(sortByDateDesc), .sort(sortByDateDesc),
name: 'Tx/day', name: 'Tx/day',
valueFormatter: (x: number) => x.toLocaleString('en', { maximumFractionDigits: 2, notation: 'compact' }), valueFormatter: (x: number) => x.toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
} ]), } ]),
}, },
}; };
...@@ -48,7 +48,7 @@ const coinPriceIndicator: TChainIndicator<'homepage_chart_market'> = { ...@@ -48,7 +48,7 @@ const coinPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = { const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
id: 'market_cup', id: 'market_cup',
title: 'Market cap', title: 'Market cap',
value: (stats) => '$' + Number(stats.market_cap).toLocaleString('en', { maximumFractionDigits: 0, notation: 'compact' }), value: (stats) => '$' + Number(stats.market_cap).toLocaleString(undefined, { maximumFractionDigits: 0, notation: 'compact' }),
icon: <Icon as={ globeIcon } boxSize={ 6 } bgColor="#6A5DCC" borderRadius="base" color="white"/>, icon: <Icon as={ globeIcon } boxSize={ 6 } bgColor="#6A5DCC" borderRadius="base" color="white"/>,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
hint: 'The total market value of a cryptocurrency\'s circulating supply. It is analogous to the free-float capitalization in the stock market. Market Cap = Current Price x Circulating Supply.', hint: 'The total market value of a cryptocurrency\'s circulating supply. It is analogous to the free-float capitalization in the stock market. Market Cap = Current Price x Circulating Supply.',
...@@ -59,7 +59,7 @@ const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = { ...@@ -59,7 +59,7 @@ const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
.map((item) => ({ date: new Date(item.date), value: Number(item.closing_price) * Number(response.available_supply) })) .map((item) => ({ date: new Date(item.date), value: Number(item.closing_price) * Number(response.available_supply) }))
.sort(sortByDateDesc), .sort(sortByDateDesc),
name: 'Market cap', name: 'Market cap',
valueFormatter: (x: number) => '$' + x.toLocaleString('en', { maximumFractionDigits: 0 }), valueFormatter: (x: number) => '$' + x.toLocaleString(undefined, { maximumFractionDigits: 0 }),
} ]), } ]),
}, },
}; };
......
...@@ -47,7 +47,7 @@ const Deposits = () => { ...@@ -47,7 +47,7 @@ const Deposits = () => {
return ( return (
<Text mb={{ base: 6, lg: isPaginationVisible ? 0 : 6 }} lineHeight={{ base: '24px', lg: '32px' }}> <Text mb={{ base: 6, lg: isPaginationVisible ? 0 : 6 }} lineHeight={{ base: '24px', lg: '32px' }}>
A total of { countersQuery.data.toLocaleString('en') } deposits found A total of { countersQuery.data.toLocaleString() } deposits found
</Text> </Text>
); );
})(); })();
......
...@@ -4,8 +4,8 @@ import React from 'react'; ...@@ -4,8 +4,8 @@ import React from 'react';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import ChainIndicators from 'ui/home/indicators/ChainIndicators'; import ChainIndicators from 'ui/home/indicators/ChainIndicators';
import LatestBlocks from 'ui/home/LatestBlocks'; import LatestBlocks from 'ui/home/LatestBlocks';
import LatestTxs from 'ui/home/LatestTxs';
import Stats from 'ui/home/Stats'; import Stats from 'ui/home/Stats';
import Transactions from 'ui/home/Transactions';
import AdBanner from 'ui/shared/ad/AdBanner'; import AdBanner from 'ui/shared/ad/AdBanner';
import Page from 'ui/shared/Page/Page'; import Page from 'ui/shared/Page/Page';
import ColorModeToggler from 'ui/snippets/header/ColorModeToggler'; import ColorModeToggler from 'ui/snippets/header/ColorModeToggler';
...@@ -40,7 +40,7 @@ const Home = () => { ...@@ -40,7 +40,7 @@ const Home = () => {
pl={ 4 } pl={ 4 }
> >
<ColorModeToggler trackBg="whiteAlpha.500"/> <ColorModeToggler trackBg="whiteAlpha.500"/>
<ProfileMenuDesktop/> { appConfig.isAccountSupported && <ProfileMenuDesktop/> }
</Flex> </Flex>
</Flex> </Flex>
<LightMode> <LightMode>
...@@ -52,7 +52,9 @@ const Home = () => { ...@@ -52,7 +52,9 @@ const Home = () => {
<AdBanner mt={{ base: 6, lg: 8 }} justifyContent="center"/> <AdBanner mt={{ base: 6, lg: 8 }} justifyContent="center"/>
<Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 8 }> <Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 8 }>
<LatestBlocks/> <LatestBlocks/>
<LatestTxs/> <Box flexGrow={ 1 }>
<Transactions/>
</Box>
</Flex> </Flex>
</Page> </Page>
); );
......
...@@ -49,7 +49,7 @@ const OutputRoots = () => { ...@@ -49,7 +49,7 @@ const OutputRoots = () => {
L2 output index L2 output index
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].l2_output_index } </Text>to <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].l2_output_index } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].l2_output_index } </Text> <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].l2_output_index } </Text>
(total of { countersQuery.data.toLocaleString('en') } roots) (total of { countersQuery.data.toLocaleString() } roots)
</Flex> </Flex>
); );
})(); })();
......
...@@ -62,7 +62,7 @@ test('search by address hash +@mobile', async({ mount, page }) => { ...@@ -62,7 +62,7 @@ test('search by address hash +@mobile', async({ mount, page }) => {
test('search by block number +@mobile', async({ mount, page }) => { test('search by block number +@mobile', async({ mount, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: searchMock.block1.block_number }, query: { q: String(searchMock.block1.block_number) },
}, },
}; };
await page.route(buildApiUrl('search') + `?q=${ searchMock.block1.block_number }`, (route) => route.fulfill({ await page.route(buildApiUrl('search') + `?q=${ searchMock.block1.block_number }`, (route) => route.fulfill({
......
import { Box, chakra, Table, Tbody, Tr, Th, Skeleton, Show, Hide } from '@chakra-ui/react'; import { Box, chakra, Table, Tbody, Tr, Th, Skeleton, Show, Hide } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import type { FormEvent } from 'react'; import type { FormEvent } from 'react';
import React from 'react'; import React from 'react';
...@@ -17,9 +18,29 @@ import SearchBarInput from 'ui/snippets/searchBar/SearchBarInput'; ...@@ -17,9 +18,29 @@ import SearchBarInput from 'ui/snippets/searchBar/SearchBarInput';
import useSearchQuery from 'ui/snippets/searchBar/useSearchQuery'; import useSearchQuery from 'ui/snippets/searchBar/useSearchQuery';
const SearchResultsPageContent = () => { const SearchResultsPageContent = () => {
const { query, searchTerm, debouncedSearchTerm, handleSearchTermChange } = useSearchQuery(true); const router = useRouter();
const { query, redirectCheckQuery, searchTerm, debouncedSearchTerm, handleSearchTermChange } = useSearchQuery(true);
const { data, isError, isLoading, pagination, isPaginationVisible } = query; const { data, isError, isLoading, pagination, isPaginationVisible } = query;
React.useEffect(() => {
if (redirectCheckQuery.data?.redirect && redirectCheckQuery.data.parameter) {
switch (redirectCheckQuery.data.type) {
case 'block': {
router.push({ pathname: '/block/[height]', query: { height: redirectCheckQuery.data.parameter } });
return;
}
case 'address': {
router.push({ pathname: '/address/[hash]', query: { hash: redirectCheckQuery.data.parameter } });
return;
}
case 'transaction': {
router.push({ pathname: '/tx/[hash]', query: { hash: redirectCheckQuery.data.parameter } });
return;
}
}
}
}, [ redirectCheckQuery.data, router ]);
const handleSubmit = React.useCallback((event: FormEvent<HTMLFormElement>) => { const handleSubmit = React.useCallback((event: FormEvent<HTMLFormElement>) => {
event.preventDefault(); event.preventDefault();
}, [ ]); }, [ ]);
...@@ -29,7 +50,7 @@ const SearchResultsPageContent = () => { ...@@ -29,7 +50,7 @@ const SearchResultsPageContent = () => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
if (isLoading) { if (isLoading || redirectCheckQuery.isLoading) {
return ( return (
<Box> <Box>
<SkeletonList display={{ base: 'block', lg: 'none' }}/> <SkeletonList display={{ base: 'block', lg: 'none' }}/>
...@@ -70,7 +91,7 @@ const SearchResultsPageContent = () => { ...@@ -70,7 +91,7 @@ const SearchResultsPageContent = () => {
return null; return null;
} }
const text = isLoading ? ( const text = isLoading || redirectCheckQuery.isLoading ? (
<Skeleton h={ 6 } w="280px" borderRadius="full" mb={ isPaginationVisible ? 0 : 6 }/> <Skeleton h={ 6 } w="280px" borderRadius="full" mb={ isPaginationVisible ? 0 : 6 }/>
) : ( ) : (
( (
...@@ -129,7 +150,10 @@ const SearchResultsPageContent = () => { ...@@ -129,7 +150,10 @@ const SearchResultsPageContent = () => {
return ( return (
<Page renderHeader={ renderHeader }> <Page renderHeader={ renderHeader }>
<PageTitle text="Search results"/> { isLoading || redirectCheckQuery.isLoading ?
<Skeleton h={ 10 } mb={ 6 } w="100%" maxW="222px"/> :
<PageTitle text="Search results"/>
}
{ bar } { bar }
{ content } { content }
</Page> </Page>
......
...@@ -50,7 +50,7 @@ const TxnBatches = () => { ...@@ -50,7 +50,7 @@ const TxnBatches = () => {
Tx batch (L2 block) Tx batch (L2 block)
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].l2_block_number } </Text>to <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].l2_block_number } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].l2_block_number } </Text> <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].l2_block_number } </Text>
(total of { countersQuery.data.toLocaleString('en') } batches) (total of { countersQuery.data.toLocaleString() } batches)
</Flex> </Flex>
); );
})(); })();
......
...@@ -47,7 +47,7 @@ const Withdrawals = () => { ...@@ -47,7 +47,7 @@ const Withdrawals = () => {
return ( return (
<Text mb={{ base: 6, lg: isPaginationVisible ? 0 : 6 }} lineHeight={{ base: '24px', lg: '32px' }}> <Text mb={{ base: 6, lg: isPaginationVisible ? 0 : 6 }} lineHeight={{ base: '24px', lg: '32px' }}>
A total of { countersQuery.data.toLocaleString('en') } withdrawals found A total of { countersQuery.data.toLocaleString() } withdrawals found
</Text> </Text>
); );
})(); })();
......
import { Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { AddressParam } from 'types/api/addressParams'; import type { Address } from 'types/api/address';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
...@@ -15,7 +15,7 @@ import AddressActionsMenu from 'ui/shared/AddressActions/Menu'; ...@@ -15,7 +15,7 @@ import AddressActionsMenu from 'ui/shared/AddressActions/Menu';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
interface Props { interface Props {
address: Pick<AddressParam, 'hash' | 'is_contract' | 'implementation_name' | 'watchlist_names'>; address: Pick<Address, 'hash' | 'is_contract' | 'implementation_name' | 'watchlist_names' | 'watchlist_address_id'>;
token?: TokenInfo | null; token?: TokenInfo | null;
isLinkDisabled?: boolean; isLinkDisabled?: boolean;
} }
...@@ -38,7 +38,7 @@ const AddressHeadingInfo = ({ address, token, isLinkDisabled }: Props) => { ...@@ -38,7 +38,7 @@ const AddressHeadingInfo = ({ address, token, isLinkDisabled }: Props) => {
<CopyToClipboard text={ address.hash }/> <CopyToClipboard text={ address.hash }/>
{ address.is_contract && token && <AddressAddToMetaMask ml={ 2 } token={ token }/> } { address.is_contract && token && <AddressAddToMetaMask ml={ 2 } token={ token }/> }
{ !address.is_contract && appConfig.isAccountSupported && ( { !address.is_contract && appConfig.isAccountSupported && (
<AddressFavoriteButton hash={ address.hash } isAdded={ Boolean(address.watchlist_names?.length) } ml={ 3 }/> <AddressFavoriteButton hash={ address.hash } watchListId={ address.watchlist_address_id } ml={ 3 }/>
) } ) }
<AddressQrCode hash={ address.hash } ml={ 2 }/> <AddressQrCode hash={ address.hash } ml={ 2 }/>
{ appConfig.isAccountSupported && <AddressActionsMenu/> } { appConfig.isAccountSupported && <AddressActionsMenu/> }
......
...@@ -9,7 +9,7 @@ const GasUsedToTargetRatio = ({ value }: Props) => { ...@@ -9,7 +9,7 @@ const GasUsedToTargetRatio = ({ value }: Props) => {
return ( return (
<Tooltip label="% of Gas Target"> <Tooltip label="% of Gas Target">
<Text variant="secondary"> <Text variant="secondary">
{ (value > 0 ? '+' : '') + value.toLocaleString('en', { maximumFractionDigits: 2 }) }% { (value > 0 ? '+' : '') + value.toLocaleString(undefined, { maximumFractionDigits: 2 }) }%
</Text> </Text>
</Tooltip> </Tooltip>
); );
......
...@@ -12,7 +12,7 @@ const LinkInternal = (props: LinkProps, ref: LegacyRef<HTMLAnchorElement>) => { ...@@ -12,7 +12,7 @@ const LinkInternal = (props: LinkProps, ref: LegacyRef<HTMLAnchorElement>) => {
} }
return ( return (
<NextLink href={ props.href as NextLinkProps['href'] } passHref target={ props.target }> <NextLink href={ props.href as NextLinkProps['href'] } passHref target={ props.target } legacyBehavior>
<Link { ...props } ref={ ref }/> <Link { ...props } ref={ ref }/>
</NextLink> </NextLink>
); );
......
...@@ -7,7 +7,7 @@ interface InjectedProps { ...@@ -7,7 +7,7 @@ interface InjectedProps {
} }
interface Props { interface Props {
type?: 'transaction' | 'token_transfer'; type?: 'transaction' | 'token_transfer' | 'deposit';
children?: (props: InjectedProps) => JSX.Element; children?: (props: InjectedProps) => JSX.Element;
className?: string; className?: string;
url: string; url: string;
...@@ -23,7 +23,19 @@ const SocketNewItemsNotice = ({ children, className, url, num, alert, type = 'tr ...@@ -23,7 +23,19 @@ const SocketNewItemsNotice = ({ children, className, url, num, alert, type = 'tr
return alert; return alert;
} }
const name = type === 'token_transfer' ? 'token transfer' : 'transaction'; let name;
switch (type) {
case 'token_transfer':
name = 'token transfer';
break;
case 'deposit':
name = 'deposit';
break;
default:
name = 'transaction';
break;
}
if (!num) { if (!num) {
return `scanning new ${ name }s...`; return `scanning new ${ name }s...`;
...@@ -31,7 +43,7 @@ const SocketNewItemsNotice = ({ children, className, url, num, alert, type = 'tr ...@@ -31,7 +43,7 @@ const SocketNewItemsNotice = ({ children, className, url, num, alert, type = 'tr
return ( return (
<> <>
<Link href={ url }>{ num } more { name }{ num > 1 ? 's' : '' }</Link> <Link href={ url }>{ num.toLocaleString() } more { name }{ num > 1 ? 's' : '' }</Link>
<Text whiteSpace="pre"> ha{ num > 1 ? 've' : 's' } come in</Text> <Text whiteSpace="pre"> ha{ num > 1 ? 've' : 's' } come in</Text>
</> </>
); );
......
...@@ -11,7 +11,7 @@ interface Props { ...@@ -11,7 +11,7 @@ interface Props {
const WIDTH = 50; const WIDTH = 50;
const Utilization = ({ className, value, colorScheme = 'green' }: Props) => { const Utilization = ({ className, value, colorScheme = 'green' }: Props) => {
const valueString = (clamp(value * 100 || 0, 0, 100)).toLocaleString('en', { maximumFractionDigits: 2 }) + '%'; const valueString = (clamp(value * 100 || 0, 0, 100)).toLocaleString(undefined, { maximumFractionDigits: 2 }) + '%';
const colorGrayScheme = useColorModeValue('gray.500', 'gray.400'); const colorGrayScheme = useColorModeValue('gray.500', 'gray.400');
const color = colorScheme === 'gray' ? colorGrayScheme : 'green.500'; const color = colorScheme === 'gray' ? colorGrayScheme : 'green.500';
......
...@@ -41,7 +41,7 @@ const ChartArea = ({ id, xScale, yScale, color, data, disableAnimation, ...props ...@@ -41,7 +41,7 @@ const ChartArea = ({ id, xScale, yScale, color, data, disableAnimation, ...props
.x(({ date }) => xScale(date)) .x(({ date }) => xScale(date))
.y1(({ value }) => yScale(value)) .y1(({ value }) => yScale(value))
.y0(() => yScale(yScale.domain()[0])) .y0(() => yScale(yScale.domain()[0]))
.curve(d3.curveCatmullRom); .curve(d3.curveMonotoneX);
return area(data) || undefined; return area(data) || undefined;
}, [ xScale, yScale, data ]); }, [ xScale, yScale, data ]);
......
...@@ -62,7 +62,7 @@ const ChartLine = ({ xScale, yScale, data, animation, ...props }: Props) => { ...@@ -62,7 +62,7 @@ const ChartLine = ({ xScale, yScale, data, animation, ...props }: Props) => {
const line = d3.line<TimeChartItem>() const line = d3.line<TimeChartItem>()
.x((d) => xScale(d.date)) .x((d) => xScale(d.date))
.y((d) => yScale(d.value)) .y((d) => yScale(d.value))
.curve(d3.curveCatmullRom); .curve(d3.curveMonotoneX);
return ( return (
<path <path
......
...@@ -72,7 +72,7 @@ export default function useTimeChartController({ data, width, height }: Props) { ...@@ -72,7 +72,7 @@ export default function useTimeChartController({ data, width, height }: Props) {
return format(d as Date); return format(d as Date);
}; };
const yTickFormat = () => (d: d3.AxisDomain) => Number(d).toLocaleString('en', { maximumFractionDigits: 3, notation: 'compact' }); const yTickFormat = () => (d: d3.AxisDomain) => Number(d).toLocaleString(undefined, { maximumFractionDigits: 3, notation: 'compact' });
return { return {
xTickFormat, xTickFormat,
......
...@@ -101,7 +101,7 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr ...@@ -101,7 +101,7 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
/> />
</Flex> </Flex>
<Text variant="secondary" mt={ 1 }> <Text variant="secondary" mt={ 1 }>
{ file.size.toLocaleString('en', { notation: 'compact', maximumFractionDigits: 2, unit: 'byte', unitDisplay: 'narrow', style: 'unit' }) } { file.size.toLocaleString(undefined, { notation: 'compact', maximumFractionDigits: 2, unit: 'byte', unitDisplay: 'narrow', style: 'unit' }) }
</Text> </Text>
</Box> </Box>
</Flex> </Flex>
......
...@@ -155,19 +155,37 @@ const LogDecodedInputData = ({ data }: Props) => { ...@@ -155,19 +155,37 @@ const LogDecodedInputData = ({ data }: Props) => {
</> </>
) } ) }
{ data.parameters.map(({ name, type, value, indexed }, index) => { { data.parameters.map(({ name, type, value, indexed }, index) => {
return ( const content = (() => {
<TableRow key={ name } name={ name } type={ type } isLast={ index === data.parameters.length - 1 } indexed={ indexed }> if (type === 'address' && typeof value === 'string') {
{ type === 'address' ? ( return (
<Address justifyContent="space-between"> <Address justifyContent="space-between">
<AddressLink type="address" hash={ value }/> <AddressLink type="address" hash={ value }/>
<CopyToClipboard text={ value }/> <CopyToClipboard text={ value }/>
</Address> </Address>
) : ( );
}
if (typeof value === 'object') {
const text = JSON.stringify(value, undefined, 4);
return (
<Flex alignItems="flex-start" justifyContent="space-between" whiteSpace="normal" wordBreak="break-all"> <Flex alignItems="flex-start" justifyContent="space-between" whiteSpace="normal" wordBreak="break-all">
<Text>{ String(value) }</Text> <div>{ text }</div>
<CopyToClipboard text={ value }/> <CopyToClipboard text={ text }/>
</Flex> </Flex>
) } );
}
return (
<Flex alignItems="flex-start" justifyContent="space-between" whiteSpace="normal" wordBreak="break-all">
<Text>{ value }</Text>
<CopyToClipboard text={ value }/>
</Flex>
);
})();
return (
<TableRow key={ name } name={ name } type={ type } isLast={ index === data.parameters.length - 1 } indexed={ indexed }>
{ content }
</TableRow> </TableRow>
); );
}) } }) }
......
...@@ -35,9 +35,10 @@ const EDITOR_HEIGHT = 500; ...@@ -35,9 +35,10 @@ const EDITOR_HEIGHT = 500;
interface Props { interface Props {
data: Array<File>; data: Array<File>;
remappings?: Array<string>;
} }
const CodeEditor = ({ data }: Props) => { const CodeEditor = ({ data, remappings }: Props) => {
const [ instance, setInstance ] = React.useState<Monaco | undefined>(); const [ instance, setInstance ] = React.useState<Monaco | undefined>();
const [ editor, setEditor ] = React.useState<monaco.editor.IStandaloneCodeEditor | undefined>(); const [ editor, setEditor ] = React.useState<monaco.editor.IStandaloneCodeEditor | undefined>();
const [ index, setIndex ] = React.useState(0); const [ index, setIndex ] = React.useState(0);
...@@ -136,15 +137,23 @@ const CodeEditor = ({ data }: Props) => { ...@@ -136,15 +137,23 @@ const CodeEditor = ({ data }: Props) => {
const target = event.target as HTMLSpanElement; const target = event.target as HTMLSpanElement;
const isImportLink = target.classList.contains('import-link'); const isImportLink = target.classList.contains('import-link');
if (isImportLink) { if (isImportLink) {
const path = target.innerText; const path = [
const fullPath = getFullPathOfImportedFile(data[index].file_path, path); target.previousElementSibling as HTMLSpanElement,
target,
target.nextElementSibling as HTMLSpanElement,
]
.filter((element) => element?.classList.contains('import-link'))
.map((element: HTMLSpanElement) => element.innerText)
.join('');
const fullPath = getFullPathOfImportedFile(data[index].file_path, path, remappings);
const fileIndex = data.findIndex((file) => file.file_path === fullPath); const fileIndex = data.findIndex((file) => file.file_path === fullPath);
if (fileIndex > -1) { if (fileIndex > -1) {
event.stopPropagation(); event.stopPropagation();
handleSelectFile(fileIndex); handleSelectFile(fileIndex);
} }
} }
}, [ data, handleSelectFile, index, isMetaPressed, isMobile ]); }, [ data, handleSelectFile, index, isMetaPressed, isMobile, remappings ]);
const handleKeyDown = React.useCallback((event: React.KeyboardEvent) => { const handleKeyDown = React.useCallback((event: React.KeyboardEvent) => {
isMetaKey(event) && setIsMetaPressed(true); isMetaKey(event) && setIsMetaPressed(true);
...@@ -165,12 +174,10 @@ const CodeEditor = ({ data }: Props) => { ...@@ -165,12 +174,10 @@ const CodeEditor = ({ data }: Props) => {
'.highlight': { '.highlight': {
backgroundColor: themeColors['custom.findMatchHighlightBackground'], backgroundColor: themeColors['custom.findMatchHighlightBackground'],
}, },
'&&.meta-pressed .import-link': { '&&.meta-pressed .import-link:hover, &&.meta-pressed .import-link:hover + .import-link': {
_hover: { color: themeColors['custom.fileLink.hoverForeground'],
color: themeColors['custom.fileLink.hoverForeground'], textDecoration: 'underline',
textDecoration: 'underline', cursor: 'pointer',
cursor: 'pointer',
},
}, },
}), [ editorWidth, themeColors ]); }), [ editorWidth, themeColors ]);
......
...@@ -2,7 +2,7 @@ import { Box, chakra } from '@chakra-ui/react'; ...@@ -2,7 +2,7 @@ import { Box, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { SearchResult } from './types'; import type { SearchResult } from './types';
import type ArrayElement from 'types/utils/ArrayElement'; import type { ArrayElement } from 'types/utils';
import useThemeColors from './utils/useThemeColors'; import useThemeColors from './utils/useThemeColors';
......
import type * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import type * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
export default function addFileImportDecorations(model: monaco.editor.ITextModel) { export default function addFileImportDecorations(model: monaco.editor.ITextModel) {
const matches = model.findMatches('^import (\'|")((\\/|\\.)(\\w|\\.|\\/|-)+)(\'|")', false, true, false, null, true); const options: monaco.editor.IModelDecorationOptions = {
const decorations: Array<monaco.editor.IModelDeltaDecoration> = matches.map(({ range }) => ({ inlineClassName: 'import-link',
hoverMessage: {
value: 'Cmd/Win + click to open file',
},
};
const regularImportMatches = model.findMatches('^import (\'|")(.+)(\'|")', false, true, false, null, true);
const regularImportDecorations: Array<monaco.editor.IModelDeltaDecoration> = regularImportMatches.map(({ range }) => ({
range: { range: {
...range, ...range,
startColumn: range.startColumn + 8, startColumn: range.startColumn + 8,
endColumn: range.endColumn - 1, endColumn: range.endColumn - 1,
}, },
options: { options,
inlineClassName: 'import-link', }));
hoverMessage: {
value: 'Cmd/Win + click to open file', const namedImportMatches = model.findMatches('(^import \\{.+\\} from )(\'|")(.+)(\'|")', false, true, false, null, true);
}, const namedImportDecorations: Array<monaco.editor.IModelDeltaDecoration> = namedImportMatches.map(({ range, matches }) => ({
range: {
...range,
startColumn: range.startColumn + (Array.isArray(matches) ? matches?.[1]?.length + 1 : 0),
endColumn: range.endColumn - 1,
}, },
options,
})); }));
model.deltaDecorations([], decorations);
model.deltaDecorations([], regularImportDecorations.concat(namedImportDecorations));
} }
...@@ -18,20 +18,32 @@ it('returns undefined if imported file is outside the base file folder', () => { ...@@ -18,20 +18,32 @@ it('returns undefined if imported file is outside the base file folder', () => {
expect(result).toBeUndefined(); expect(result).toBeUndefined();
}); });
it('returns unmodified path if it is already absolute', () => { describe('returns unmodified path if it is already absolute', () => {
const result = getFullPathOfImportedFile( it('with prefix', () => {
'/index.sol', const result = getFullPathOfImportedFile(
'/abc/contract.sol', '/index.sol',
); '/abc/contract.sol',
);
expect(result).toBe('/abc/contract.sol');
expect(result).toBe('/abc/contract.sol');
});
it('without prefix', () => {
const result = getFullPathOfImportedFile(
'/index.sol',
'abc/contract.sol',
);
expect(result).toBe('/abc/contract.sol');
});
}); });
it('returns undefined for external path', () => { it('correctly manages remappings', () => {
const result = getFullPathOfImportedFile( const result = getFullPathOfImportedFile(
'/index.sol', '/index.sol',
'https://github.com/ethereum/dapp/contract.sol', 'node_modules/@openzeppelin/contracts/access/AccessControl.sol',
[ '@ensdomains/=node_modules/@ensdomains/', '@openzeppelin/=node_modules/@openzeppelin/' ],
); );
expect(result).toBeUndefined(); expect(result).toBe('/node_modules/@openzeppelin/contracts/access/AccessControl.sol');
}); });
import stripLeadingSlash from 'lib/stripLeadingSlash'; import stripLeadingSlash from 'lib/stripLeadingSlash';
export default function getFullPathOfImportedFile(baseFilePath: string, importedFilePath: string) { export default function getFullPathOfImportedFile(baseFilePath: string, importedFilePath: string, remappings?: Array<string>) {
if (importedFilePath[0] === '/') {
return importedFilePath;
}
if (importedFilePath[0] !== '.') { if (importedFilePath[0] !== '.') {
return; let result = importedFilePath;
if (remappings && remappings.length > 0) {
const [ alias, target ] = remappings.map((item) => item.split('=')).find(([ key ]) => importedFilePath.startsWith(key)) || [];
if (alias) {
result = importedFilePath.replace(alias, target);
}
}
return result[0] === '/' ? result : '/' + result;
} }
const baseFileChunks = stripLeadingSlash(baseFilePath).split('/'); const baseFileChunks = stripLeadingSlash(baseFilePath).split('/');
......
import type { FileTree } from '../types'; import type { FileTree } from '../types';
import type ArrayElement from 'types/utils/ArrayElement'; import type { ArrayElement } from 'types/utils';
export default function sortFileTree(a: ArrayElement<FileTree>, b: ArrayElement<FileTree>) { export default function sortFileTree(a: ArrayElement<FileTree>, b: ArrayElement<FileTree>) {
if ('children' in a && !('children' in b)) { if ('children' in a && !('children' in b)) {
......
import { Icon, Box, Flex, Drawer, DrawerOverlay, DrawerContent, DrawerBody, useColorModeValue, useDisclosure } from '@chakra-ui/react'; import { Icon, Box, Flex, Drawer, DrawerOverlay, DrawerContent, DrawerBody, useColorModeValue, useDisclosure } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import appConfig from 'configs/app/config';
import burgerIcon from 'icons/burger.svg'; import burgerIcon from 'icons/burger.svg';
import testnetIcon from 'icons/testnet.svg'; import testnetIcon from 'icons/testnet.svg';
import NavigationMobile from 'ui/snippets/navigation/NavigationMobile'; import NavigationMobile from 'ui/snippets/navigation/NavigationMobile';
...@@ -45,11 +46,13 @@ const Burger = () => { ...@@ -45,11 +46,13 @@ const Burger = () => {
<Icon as={ testnetIcon } h="14px" w="auto" color="red.400" alignSelf="flex-start"/> <Icon as={ testnetIcon } h="14px" w="auto" color="red.400" alignSelf="flex-start"/>
<Flex alignItems="center" justifyContent="space-between"> <Flex alignItems="center" justifyContent="space-between">
<NetworkLogo onClick={ handleNetworkLogoClick }/> <NetworkLogo onClick={ handleNetworkLogoClick }/>
<NetworkMenuButton { appConfig.featuredNetworks.length > 0 ? (
isMobile <NetworkMenuButton
isActive={ isNetworkMenuOpened } isMobile
onClick={ handleNetworkMenuButtonClick } isActive={ isNetworkMenuOpened }
/> onClick={ handleNetworkMenuButtonClick }
/>
) : <Box boxSize={ 9 }/> }
</Flex> </Flex>
{ isNetworkMenuOpened ? <NetworkMenuContentMobile/> : <NavigationMobile/> } { isNetworkMenuOpened ? <NetworkMenuContentMobile/> : <NavigationMobile/> }
</DrawerBody> </DrawerBody>
......
import { HStack, Box, Flex, useColorModeValue } from '@chakra-ui/react'; import { HStack, Box, Flex, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import appConfig from 'configs/app/config';
import { useScrollDirection } from 'lib/contexts/scrollDirection'; import { useScrollDirection } from 'lib/contexts/scrollDirection';
import IndexingAlert from 'ui/home/IndexingAlert'; import IndexingAlert from 'ui/home/IndexingAlert';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo'; import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
...@@ -43,7 +44,7 @@ const Header = ({ isHomePage, renderSearchBar }: Props) => { ...@@ -43,7 +44,7 @@ const Header = ({ isHomePage, renderSearchBar }: Props) => {
> >
<Burger/> <Burger/>
<NetworkLogo/> <NetworkLogo/>
<ProfileMenuMobile/> { appConfig.isAccountSupported ? <ProfileMenuMobile/> : <Box boxSize={ 10 }/> }
</Flex> </Flex>
{ !isHomePage && searchBar } { !isHomePage && searchBar }
</Box> </Box>
...@@ -66,7 +67,7 @@ const Header = ({ isHomePage, renderSearchBar }: Props) => { ...@@ -66,7 +67,7 @@ const Header = ({ isHomePage, renderSearchBar }: Props) => {
{ searchBar } { searchBar }
</Box> </Box>
<ColorModeToggler/> <ColorModeToggler/>
<ProfileMenuDesktop/> { appConfig.isAccountSupported && <ProfileMenuDesktop/> }
</HStack> </HStack>
) } ) }
</Box> </Box>
......
...@@ -71,7 +71,7 @@ const NavLink = ({ item, isCollapsed, px, className }: Props) => { ...@@ -71,7 +71,7 @@ const NavLink = ({ item, isCollapsed, px, className }: Props) => {
{ /* why not NextLink in all cases? since prev UI and new one are hosting in the same domain and global routing is managed by nginx */ } { /* why not NextLink in all cases? since prev UI and new one are hosting in the same domain and global routing is managed by nginx */ }
{ /* we have to hard reload page on every transition between urls from different part of the app */ } { /* we have to hard reload page on every transition between urls from different part of the app */ }
{ isInternalItem(item) && item.isNewUi ? ( { isInternalItem(item) && item.isNewUi ? (
<NextLink href={ item.nextRoute } passHref> <NextLink href={ item.nextRoute } passHref legacyBehavior>
{ content } { content }
</NextLink> </NextLink>
) : content } ) : content }
......
...@@ -77,7 +77,7 @@ const NavigationDesktop = () => { ...@@ -77,7 +77,7 @@ const NavigationDesktop = () => {
transitionTimingFunction="ease" transitionTimingFunction="ease"
> >
<NetworkLogo isCollapsed={ isCollapsed }/> <NetworkLogo isCollapsed={ isCollapsed }/>
<NetworkMenu isCollapsed={ isCollapsed }/> { appConfig.featuredNetworks.length > 0 && <NetworkMenu isCollapsed={ isCollapsed }/> }
</Box> </Box>
<Box as="nav" mt={ 8 } w="100%"> <Box as="nav" mt={ 8 } w="100%">
<VStack as="ul" spacing="1" alignItems="flex-start"> <VStack as="ul" spacing="1" alignItems="flex-start">
......
...@@ -67,7 +67,7 @@ const NavigationMobile = () => { ...@@ -67,7 +67,7 @@ const NavigationMobile = () => {
}) } }) }
</VStack> </VStack>
</Box> </Box>
{ isAuth && ( { hasAccount && (
<Box <Box
as="nav" as="nav"
mt={ 6 } mt={ 6 }
......
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import useDebounce from 'lib/hooks/useDebounce'; import useDebounce from 'lib/hooks/useDebounce';
import useQueryWithPages from 'lib/hooks/useQueryWithPages'; import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import useUpdateValueEffect from 'lib/hooks/useUpdateValueEffect'; import useUpdateValueEffect from 'lib/hooks/useUpdateValueEffect';
import getQueryParamString from 'lib/router/getQueryParamString';
export default function useSearchQuery(isSearchPage = false) { export default function useSearchQuery(isSearchPage = false) {
const router = useRouter(); const router = useRouter();
const initialValue = isSearchPage ? String(router.query.q || '') : ''; const q = React.useRef(getQueryParamString(router.query.q));
const initialValue = isSearchPage ? q.current : '';
const [ searchTerm, setSearchTerm ] = React.useState(initialValue); const [ searchTerm, setSearchTerm ] = React.useState(initialValue);
...@@ -19,6 +22,11 @@ export default function useSearchQuery(isSearchPage = false) { ...@@ -19,6 +22,11 @@ export default function useSearchQuery(isSearchPage = false) {
options: { enabled: debouncedSearchTerm.trim().length > 0 }, options: { enabled: debouncedSearchTerm.trim().length > 0 },
}); });
const redirectCheckQuery = useApiQuery('search_check_redirect', {
queryParams: { q: q.current },
queryOptions: { enabled: isSearchPage && Boolean(q) },
});
useUpdateValueEffect(() => { useUpdateValueEffect(() => {
if (isSearchPage) { if (isSearchPage) {
query.onFilterChange({ q: debouncedSearchTerm }); query.onFilterChange({ q: debouncedSearchTerm });
...@@ -30,5 +38,6 @@ export default function useSearchQuery(isSearchPage = false) { ...@@ -30,5 +38,6 @@ export default function useSearchQuery(isSearchPage = false) {
debouncedSearchTerm, debouncedSearchTerm,
handleSearchTermChange: setSearchTerm, handleSearchTermChange: setSearchTerm,
query, query,
redirectCheckQuery,
}; };
} }
...@@ -31,7 +31,7 @@ const NumberWidgetsList = () => { ...@@ -31,7 +31,7 @@ const NumberWidgetsList = () => {
<NumberWidget <NumberWidget
key={ id } key={ id }
label={ title } label={ title }
value={ `${ Number(value).toLocaleString('en', { maximumFractionDigits: 3, notation: 'compact' }) } ${ units ? units : '' }` } value={ `${ Number(value).toLocaleString(undefined, { maximumFractionDigits: 3, notation: 'compact' }) } ${ units ? units : '' }` }
/> />
); );
}) } }) }
......
...@@ -42,6 +42,7 @@ const TokenContractInfo = ({ tokenQuery }: Props) => { ...@@ -42,6 +42,7 @@ const TokenContractInfo = ({ tokenQuery }: Props) => {
is_contract: true, is_contract: true,
implementation_name: null, implementation_name: null,
watchlist_names: [], watchlist_names: [],
watchlist_address_id: null,
}; };
return ( return (
......
...@@ -53,7 +53,7 @@ const TokenDetails = ({ tokenQuery, verifiedInfoQuery, isVerifiedInfoEnabled }: ...@@ -53,7 +53,7 @@ const TokenDetails = ({ tokenQuery, verifiedInfoQuery, isVerifiedInfoEnabled }:
const tab: TokenTabs = item === 'token_holders_count' ? 'holders' : 'token_transfers'; const tab: TokenTabs = item === 'token_holders_count' ? 'holders' : 'token_transfers';
return <Link onClick={ changeUrlAndScroll(tab) }>{ itemValue }</Link>; return <Link onClick={ changeUrlAndScroll(tab) }>{ Number(itemValue).toLocaleString() }</Link>;
}, [ tokenCountersQuery.data, changeUrlAndScroll ]); }, [ tokenCountersQuery.data, changeUrlAndScroll ]);
if (tokenQuery.isError) { if (tokenQuery.isError) {
...@@ -89,7 +89,7 @@ const TokenDetails = ({ tokenQuery, verifiedInfoQuery, isVerifiedInfoEnabled }: ...@@ -89,7 +89,7 @@ const TokenDetails = ({ tokenQuery, verifiedInfoQuery, isVerifiedInfoEnabled }:
marketcap = totalValue?.usd; marketcap = totalValue?.usd;
totalSupplyValue = totalValue?.valueStr; totalSupplyValue = totalValue?.valueStr;
} else { } else {
totalSupplyValue = Number(totalSupply).toLocaleString('en'); totalSupplyValue = Number(totalSupply).toLocaleString();
} }
const divider = ( const divider = (
......
...@@ -26,7 +26,7 @@ const NFTItem = ({ item }: Props) => { ...@@ -26,7 +26,7 @@ const NFTItem = ({ item }: Props) => {
fontWeight={ 500 } fontWeight={ 500 }
lineHeight="20px" lineHeight="20px"
> >
<NextLink href={{ pathname: '/token/[hash]/instance/[id]', query: { hash: item.token.address, id: item.id } }} passHref> <NextLink href={{ pathname: '/token/[hash]/instance/[id]', query: { hash: item.token.address, id: item.id } }} passHref legacyBehavior>
<LinkOverlay> <LinkOverlay>
<NftMedia <NftMedia
mb="18px" mb="18px"
......
...@@ -83,6 +83,7 @@ const TokenInstanceContent = () => { ...@@ -83,6 +83,7 @@ const TokenInstanceContent = () => {
is_contract: true, is_contract: true,
implementation_name: null, implementation_name: null,
watchlist_names: [], watchlist_names: [],
watchlist_address_id: null,
}; };
const appLink = (() => { const appLink = (() => {
if (!tokenInstanceQuery.data.external_app_url) { if (!tokenInstanceQuery.data.external_app_url) {
......
...@@ -60,16 +60,18 @@ const TokenInstanceDetails = ({ data, scrollRef }: Props) => { ...@@ -60,16 +60,18 @@ const TokenInstanceDetails = ({ data, scrollRef }: Props) => {
> >
<TokenSnippet hash={ data.token.address } name={ data.token.name }/> <TokenSnippet hash={ data.token.address } name={ data.token.name }/>
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem { data.owner && (
title="Owner" <DetailsInfoItem
hint="Current owner of this token instance" title="Owner"
> hint="Current owner of this token instance"
<Address> >
<AddressIcon address={ data.owner }/> <Address>
<AddressLink type="address" hash={ data.owner.hash } ml={ 2 }/> <AddressIcon address={ data.owner }/>
<CopyToClipboard text={ data.owner.hash }/> <AddressLink type="address" hash={ data.owner.hash } ml={ 2 }/>
</Address> <CopyToClipboard text={ data.owner.hash }/>
</DetailsInfoItem> </Address>
</DetailsInfoItem>
) }
<TokenInstanceCreatorAddress hash={ data.token.address }/> <TokenInstanceCreatorAddress hash={ data.token.address }/>
<DetailsInfoItem <DetailsInfoItem
title="Token ID" title="Token ID"
......
...@@ -77,7 +77,7 @@ const TokensTableItem = ({ ...@@ -77,7 +77,7 @@ const TokensTableItem = ({
) } ) }
<HStack spacing={ 3 }> <HStack spacing={ 3 }>
<Text fontSize="sm" fontWeight={ 500 }>Holders</Text> <Text fontSize="sm" fontWeight={ 500 }>Holders</Text>
<Text fontSize="sm" variant="secondary">{ holders }</Text> <Text fontSize="sm" variant="secondary">{ Number(holders).toLocaleString() }</Text>
</HStack> </HStack>
</ListItemMobile> </ListItemMobile>
); );
......
...@@ -71,7 +71,7 @@ const TokensTableItem = ({ ...@@ -71,7 +71,7 @@ const TokensTableItem = ({
<Td isNumeric maxWidth="300px" width="300px"> <Td isNumeric maxWidth="300px" width="300px">
<Text fontSize="sm" lineHeight="24px" fontWeight={ 500 }>{ totalValue?.usd ? `$${ totalValue.usd }` : '-' }</Text> <Text fontSize="sm" lineHeight="24px" fontWeight={ 500 }>{ totalValue?.usd ? `$${ totalValue.usd }` : '-' }</Text>
</Td> </Td>
<Td isNumeric><Text fontSize="sm" lineHeight="24px" fontWeight={ 500 }>{ holders }</Text></Td> <Td isNumeric><Text fontSize="sm" lineHeight="24px" fontWeight={ 500 }>{ Number(holders).toLocaleString() }</Text></Td>
</Tr> </Tr>
); );
}; };
......
...@@ -2,6 +2,7 @@ import { test, expect } from '@playwright/experimental-ct-react'; ...@@ -2,6 +2,7 @@ import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react'; import React from 'react';
import * as txMock from 'mocks/txs/tx'; import * as txMock from 'mocks/txs/tx';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp'; import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl'; import buildApiUrl from 'playwright/utils/buildApiUrl';
import insertAdPlaceholder from 'playwright/utils/insertAdPlaceholder'; import insertAdPlaceholder from 'playwright/utils/insertAdPlaceholder';
...@@ -141,3 +142,28 @@ test('with actions uniswap +@mobile +@dark-mode', async({ mount, page }) => { ...@@ -141,3 +142,28 @@ test('with actions uniswap +@mobile +@dark-mode', async({ mount, page }) => {
await insertAdPlaceholder(page); await insertAdPlaceholder(page);
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
const l2Test = test.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_IS_L2_NETWORK', value: 'true' },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
l2Test('l2', async({ mount, page }) => {
await page.route(API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(txMock.l2tx),
}));
const component = await mount(
<TestApp>
<TxDetails/>
</TestApp>,
{ hooksConfig },
);
await insertAdPlaceholder(page);
await expect(component).toHaveScreenshot();
});
...@@ -86,21 +86,21 @@ const TxDetails = () => { ...@@ -86,21 +86,21 @@ const TxDetails = () => {
const toAddress = data.to ? data.to : data.created_contract; const toAddress = data.to ? data.to : data.created_contract;
const addressToTags = [ const addressToTags = [
...toAddress.private_tags || [], ...toAddress?.private_tags || [],
...toAddress.public_tags || [], ...toAddress?.public_tags || [],
...toAddress.watchlist_names || [], ...toAddress?.watchlist_names || [],
].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>); ].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>);
const actionsExist = data.actions && data.actions.length > 0; const actionsExist = data.actions && data.actions.length > 0;
const executionSuccessBadge = toAddress.is_contract && data.result === 'success' ? ( const executionSuccessBadge = toAddress?.is_contract && data.result === 'success' ? (
<Tooltip label="Contract execution completed"> <Tooltip label="Contract execution completed">
<chakra.span display="inline-flex" ml={ 2 } mr={ 1 }> <chakra.span display="inline-flex" ml={ 2 } mr={ 1 }>
<Icon as={ successIcon } boxSize={ 4 } color={ executionSuccessIconColor } cursor="pointer"/> <Icon as={ successIcon } boxSize={ 4 } color={ executionSuccessIconColor } cursor="pointer"/>
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
) : null; ) : null;
const executionFailedBadge = toAddress.is_contract && Boolean(data.status) && data.result !== 'success' ? ( const executionFailedBadge = toAddress?.is_contract && Boolean(data.status) && data.result !== 'success' ? (
<Tooltip label="Error occurred during contract execution"> <Tooltip label="Error occurred during contract execution">
<chakra.span display="inline-flex" ml={ 2 } mr={ 1 }> <chakra.span display="inline-flex" ml={ 2 } mr={ 1 }>
<Icon as={ errorIcon } boxSize={ 4 } color="error" cursor="pointer"/> <Icon as={ errorIcon } boxSize={ 4 } color="error" cursor="pointer"/>
...@@ -214,29 +214,35 @@ const TxDetails = () => { ...@@ -214,29 +214,35 @@ const TxDetails = () => {
flexWrap={{ base: 'wrap', lg: 'nowrap' }} flexWrap={{ base: 'wrap', lg: 'nowrap' }}
columnGap={ 3 } columnGap={ 3 }
> >
{ data.to && data.to.hash ? ( { toAddress ? (
<Address alignItems="center"> <>
<AddressIcon address={ toAddress }/> { data.to && data.to.hash ? (
<AddressLink type="address" ml={ 2 } hash={ toAddress.hash }/> <Address alignItems="center">
{ executionSuccessBadge } <AddressIcon address={ toAddress }/>
{ executionFailedBadge } <AddressLink type="address" ml={ 2 } hash={ toAddress.hash }/>
<CopyToClipboard text={ toAddress.hash }/> { executionSuccessBadge }
</Address> { executionFailedBadge }
<CopyToClipboard text={ toAddress.hash }/>
</Address>
) : (
<Flex width={{ base: '100%', lg: 'auto' }} whiteSpace="pre" alignItems="center">
<span>[Contract </span>
<AddressLink type="address" hash={ toAddress.hash }/>
<span> created]</span>
{ executionSuccessBadge }
{ executionFailedBadge }
<CopyToClipboard text={ toAddress.hash }/>
</Flex>
) }
{ toAddress.name && <Text>{ toAddress.name }</Text> }
{ addressToTags.length > 0 && (
<Flex columnGap={ 3 }>
{ addressToTags }
</Flex>
) }
</>
) : ( ) : (
<Flex width={{ base: '100%', lg: 'auto' }} whiteSpace="pre" alignItems="center"> <span>[ Contract creation ]</span>
<span>[Contract </span>
<AddressLink type="address" hash={ toAddress.hash }/>
<span> created]</span>
{ executionSuccessBadge }
{ executionFailedBadge }
<CopyToClipboard text={ toAddress.hash }/>
</Flex>
) }
{ toAddress.name && <Text>{ toAddress.name }</Text> }
{ addressToTags.length > 0 && (
<Flex columnGap={ 3 }>
{ addressToTags }
</Flex>
) } ) }
</DetailsInfoItem> </DetailsInfoItem>
{ data.token_transfers && <TxDetailsTokenTransfers data={ data.token_transfers } txHash={ data.hash }/> } { data.token_transfers && <TxDetailsTokenTransfers data={ data.token_transfers } txHash={ data.hash }/> }
...@@ -318,6 +324,49 @@ const TxDetails = () => { ...@@ -318,6 +324,49 @@ const TxDetails = () => {
/> />
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
{ appConfig.L2.isL2Network && (
<>
{ data.l1_gas_used && (
<DetailsInfoItem
title="L1 gas used by txn"
hint="L1 gas used by transaction"
>
<Text>{ BigNumber(data.l1_gas_used).toFormat() }</Text>
</DetailsInfoItem>
) }
{ data.l1_gas_price && (
<DetailsInfoItem
title="L1 gas price"
hint="L1 gas price"
>
<Text mr={ 1 }>{ BigNumber(data.l1_gas_price).dividedBy(WEI).toFixed() } { appConfig.network.currency.symbol }</Text>
<Text variant="secondary">({ BigNumber(data.l1_gas_price).dividedBy(WEI_IN_GWEI).toFixed() } Gwei)</Text>
</DetailsInfoItem>
) }
{ data.l1_fee && (
<DetailsInfoItem
title="L1 fee"
// eslint-disable-next-line max-len
hint={ `L1 Data Fee which is used to cover the L1 "security" cost from the batch submission mechanism. In combination with L2 execution fee, L1 fee makes the total amount of fees that a transaction pays.` }
>
<CurrencyValue
value={ data.l1_fee }
currency={ appConfig.network.currency.symbol }
exchangeRate={ data.exchange_rate }
flexWrap="wrap"
/>
</DetailsInfoItem>
) }
{ data.l1_fee_scalar && (
<DetailsInfoItem
title="L1 fee scalar"
hint="A Dynamic overhead (fee scalar) premium, which serves as a buffer in case L1 prices rapidly increase."
>
<Text>{ data.l1_fee_scalar }</Text>
</DetailsInfoItem>
) }
</>
) }
<GridItem colSpan={{ base: undefined, lg: 2 }}> <GridItem colSpan={{ base: undefined, lg: 2 }}>
<Element name="TxDetails__cutLink"> <Element name="TxDetails__cutLink">
<Link <Link
......
...@@ -3,7 +3,7 @@ import BigNumber from 'bignumber.js'; ...@@ -3,7 +3,7 @@ import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { TxStateChange, TxStateChangeTokenErc1155, TxStateChangeTokenErc1155Single, TxStateChangeTokenErc721 } from 'types/api/txStateChanges'; import type { TxStateChange, TxStateChangeTokenErc1155, TxStateChangeTokenErc1155Single, TxStateChangeTokenErc721 } from 'types/api/txStateChanges';
import type ArrayElement from 'types/utils/ArrayElement'; import type { ArrayElement } from 'types/utils';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import { ZERO_ADDRESS } from 'lib/consts'; import { ZERO_ADDRESS } from 'lib/consts';
......
...@@ -112,17 +112,19 @@ const TxsListItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement }: ...@@ -112,17 +112,19 @@ const TxsListItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement }:
color="gray.500" color="gray.500"
/> />
) } ) }
<Address maxWidth={ `calc((100% - ${ currentAddress ? TAG_WIDTH + 16 : ARROW_WIDTH + 8 }px)/2)` }> { dataTo ? (
<AddressIcon address={ dataTo }/> <Address maxWidth={ `calc((100% - ${ currentAddress ? TAG_WIDTH + 16 : ARROW_WIDTH + 8 }px)/2)` }>
<AddressLink <AddressIcon address={ dataTo }/>
type="address" <AddressLink
hash={ dataTo.hash } type="address"
alias={ dataTo.name } hash={ dataTo.hash }
fontWeight="500" alias={ dataTo.name }
ml={ 2 } fontWeight="500"
isDisabled={ isIn } ml={ 2 }
/> isDisabled={ isIn }
</Address> />
</Address>
) : '-' }
</Flex> </Flex>
<Box mt={ 2 }> <Box mt={ 2 }>
<Text as="span">Value { appConfig.network.currency.symbol } </Text> <Text as="span">Value { appConfig.network.currency.symbol } </Text>
......
...@@ -39,7 +39,7 @@ type Props = { ...@@ -39,7 +39,7 @@ type Props = {
const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement }: Props) => { const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement }: Props) => {
const dataTo = tx.to ? tx.to : tx.created_contract; const dataTo = tx.to ? tx.to : tx.created_contract;
const isOut = Boolean(currentAddress && currentAddress === tx.from.hash); const isOut = Boolean(currentAddress && currentAddress === tx.from.hash);
const isIn = Boolean(currentAddress && currentAddress === dataTo.hash); const isIn = Boolean(currentAddress && currentAddress === dataTo?.hash);
const timeAgo = useTimeAgoIncrement(tx.timestamp, enableTimeIncrement); const timeAgo = useTimeAgoIncrement(tx.timestamp, enableTimeIncrement);
...@@ -50,12 +50,12 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement } ...@@ -50,12 +50,12 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement }
</Address> </Address>
); );
const addressTo = ( const addressTo = dataTo ? (
<Address> <Address>
<AddressIcon address={ dataTo }/> <AddressIcon address={ dataTo }/>
<AddressLink type="address" hash={ dataTo.hash } alias={ dataTo.name } fontWeight="500" ml={ 2 } truncation="constant" isDisabled={ isIn }/> <AddressLink type="address" hash={ dataTo.hash } alias={ dataTo.name } fontWeight="500" ml={ 2 } truncation="constant" isDisabled={ isIn }/>
</Address> </Address>
); ) : '-';
return ( return (
<Tr <Tr
......
...@@ -18,10 +18,10 @@ const VerifiedContractsCountersItem = ({ name, total, new24 }: Props) => { ...@@ -18,10 +18,10 @@ const VerifiedContractsCountersItem = ({ name, total, new24 }: Props) => {
> >
<Text variant="secondary" fontSize="xs">{ name }</Text> <Text variant="secondary" fontSize="xs">{ name }</Text>
<Flex alignItems="baseline"> <Flex alignItems="baseline">
<Text fontWeight={ 600 } mr={ 2 } fontSize="lg">{ Number(total).toLocaleString('en') }</Text> <Text fontWeight={ 600 } mr={ 2 } fontSize="lg">{ Number(total).toLocaleString() }</Text>
{ Number(new24) > 0 && ( { Number(new24) > 0 && (
<> <>
<Text fontWeight={ 600 } mr={ 1 } fontSize="lg" color="green.500">+{ Number(new24).toLocaleString('en') }</Text> <Text fontWeight={ 600 } mr={ 1 } fontSize="lg" color="green.500">+{ Number(new24).toLocaleString() }</Text>
<Text variant="secondary" fontSize="sm">(24h)</Text> <Text variant="secondary" fontSize="sm">(24h)</Text>
</> </>
) } ) }
......
...@@ -3187,82 +3187,62 @@ ...@@ -3187,82 +3187,62 @@
resolved "https://registry.yarnpkg.com/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz#c15791112db68dd9315d329d652b7e797f737655" resolved "https://registry.yarnpkg.com/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz#c15791112db68dd9315d329d652b7e797f737655"
integrity sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q== integrity sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q==
"@next/env@12.2.5": "@next/env@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.5.tgz#d908c57b35262b94db3e431e869b72ac3e1ad3e3" resolved "https://registry.yarnpkg.com/@next/env/-/env-13.3.0.tgz#cc2e49f03060a4684ce7ec7fd617a21bc5b9edba"
integrity sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw== integrity sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==
"@next/eslint-plugin-next@12.3.1": "@next/eslint-plugin-next@13.3.0":
version "12.3.1" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.1.tgz#b821f27b0f175954d8d18e5d323fce040ecc79a6" resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-13.3.0.tgz#3a4742b0817575cc0dd4d152cb10363584c215ac"
integrity sha512-sw+lTf6r6P0j+g/n9y4qdWWI2syPqZx+uc0+B/fRENqfR3KpSid6MIKqc9gNwGhJASazEQ5b3w8h4cAET213jw== integrity sha512-wuGN5qSEjSgcq9fVkH0Y/qIPFjnZtW3ZPwfjJOn7l/rrf6y8J24h/lo61kwqunTyzZJm/ETGfGVU9PUs8cnzEA==
dependencies: dependencies:
glob "7.1.7" glob "7.1.7"
"@next/swc-android-arm-eabi@12.2.5": "@next/swc-darwin-arm64@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz#903a5479ab4c2705d9c08d080907475f7bacf94d" resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.0.tgz#38f18e0639cd4c7edc6a38d4b83fe00f38eea4f2"
integrity sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA== integrity sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==
"@next/swc-android-arm64@12.2.5": "@next/swc-darwin-x64@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz#2f9a98ec4166c7860510963b31bda1f57a77c792" resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.0.tgz#b670ed1fd1d231aa21279173ec52e3ad56dc6aeb"
integrity sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg== integrity sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==
"@next/swc-darwin-arm64@12.2.5": "@next/swc-linux-arm64-gnu@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.0.tgz#b114935f6b4c94c123f6cac55a4823d483209ba5"
integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg== integrity sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==
"@next/swc-darwin-x64@12.2.5": "@next/swc-linux-arm64-musl@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz#2e44dd82b2b7fef88238d1bc4d3bead5884cedfd" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.0.tgz#67a57309f8761c7d00d629d6785d56ed0567a0d2"
integrity sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A== integrity sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==
"@next/swc-freebsd-x64@12.2.5": "@next/swc-linux-x64-gnu@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz#e24e75d8c2581bfebc75e4f08f6ddbd116ce9dbd" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.0.tgz#11bd2bea7c00b40be111c0dd16e71171f3792086"
integrity sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw== integrity sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==
"@next/swc-linux-arm-gnueabihf@12.2.5": "@next/swc-linux-x64-musl@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz#46d8c514d834d2b5f67086013f0bd5e3081e10b9" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.0.tgz#d57e99f85890799b78719c3ea32a4624de8d701b"
integrity sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg== integrity sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==
"@next/swc-linux-arm64-gnu@12.2.5": "@next/swc-win32-arm64-msvc@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz#91f725ac217d3a1f4f9f53b553615ba582fd3d9f" resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.0.tgz#0c209aa35d1c88b01e78259a89cd68f4139b5093"
integrity sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ== integrity sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==
"@next/swc-linux-arm64-musl@12.2.5": "@next/swc-win32-ia32-msvc@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz#e627e8c867920995810250303cd9b8e963598383" resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.0.tgz#52ae74da1dd6d840c3743923367d27ed013803dd"
integrity sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg== integrity sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==
"@next/swc-linux-x64-gnu@12.2.5": "@next/swc-win32-x64-msvc@13.3.0":
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz#83a5e224fbc4d119ef2e0f29d0d79c40cc43887e" resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.0.tgz#db7b55fee834dc8c2c484c696469e65bae2ee770"
integrity sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw== integrity sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==
"@next/swc-linux-x64-musl@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz#be700d48471baac1ec2e9539396625584a317e95"
integrity sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==
"@next/swc-win32-arm64-msvc@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz#a93e958133ad3310373fda33a79aa10af2a0aa97"
integrity sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==
"@next/swc-win32-ia32-msvc@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz#4f5f7ba0a98ff89a883625d4af0125baed8b2e19"
integrity sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==
"@next/swc-win32-x64-msvc@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4"
integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==
"@noble/ed25519@^1.7.0": "@noble/ed25519@^1.7.0":
version "1.7.1" version "1.7.1"
...@@ -3305,6 +3285,18 @@ ...@@ -3305,6 +3285,18 @@
resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec" resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec"
integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug== integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug==
"@pkgr/utils@^2.3.1":
version "2.3.1"
resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03"
integrity sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==
dependencies:
cross-spawn "^7.0.3"
is-glob "^4.0.3"
open "^8.4.0"
picocolors "^1.0.0"
tiny-glob "^0.2.9"
tslib "^2.4.0"
"@playwright/experimental-ct-react@1.31.0": "@playwright/experimental-ct-react@1.31.0":
version "1.31.0" version "1.31.0"
resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-react/-/experimental-ct-react-1.31.0.tgz#26bab075d4f3b18a249b11c3c7f29311ab7d3ad9" resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-react/-/experimental-ct-react-1.31.0.tgz#26bab075d4f3b18a249b11c3c7f29311ab7d3ad9"
...@@ -3966,10 +3958,10 @@ ...@@ -3966,10 +3958,10 @@
"@svgr/plugin-jsx" "^6.5.1" "@svgr/plugin-jsx" "^6.5.1"
"@svgr/plugin-svgo" "^6.5.1" "@svgr/plugin-svgo" "^6.5.1"
"@swc/helpers@0.4.3": "@swc/helpers@0.4.14":
version "0.4.3" version "0.4.14"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74"
integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA== integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==
dependencies: dependencies:
tslib "^2.4.0" tslib "^2.4.0"
...@@ -4689,24 +4681,16 @@ ...@@ -4689,24 +4681,16 @@
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/parser@^5.21.0": "@typescript-eslint/parser@^5.42.0":
version "5.40.0" version "5.59.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.40.0.tgz#432bddc1fe9154945660f67c1ba6d44de5014840" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.0.tgz#0ad7cd019346cc5d150363f64869eca10ca9977c"
integrity sha512-Ah5gqyX2ySkiuYeOIDg7ap51/b63QgWZA7w6AHtFrag7aH0lRQPbLzUjk0c9o5/KZ6JRkTTDKShL4AUrQa6/hw== integrity sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.40.0" "@typescript-eslint/scope-manager" "5.59.0"
"@typescript-eslint/types" "5.40.0" "@typescript-eslint/types" "5.59.0"
"@typescript-eslint/typescript-estree" "5.40.0" "@typescript-eslint/typescript-estree" "5.59.0"
debug "^4.3.4" debug "^4.3.4"
"@typescript-eslint/scope-manager@5.40.0":
version "5.40.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.40.0.tgz#d6ea782c8e3a2371ba3ea31458dcbdc934668fc4"
integrity sha512-d3nPmjUeZtEWRvyReMI4I1MwPGC63E8pDoHy0BnrYjnJgilBD3hv7XOiETKLY/zTwI7kCnBDf2vWTRUVpYw0Uw==
dependencies:
"@typescript-eslint/types" "5.40.0"
"@typescript-eslint/visitor-keys" "5.40.0"
"@typescript-eslint/scope-manager@5.45.0": "@typescript-eslint/scope-manager@5.45.0":
version "5.45.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz#7a4ac1bfa9544bff3f620ab85947945938319a96" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz#7a4ac1bfa9544bff3f620ab85947945938319a96"
...@@ -4723,6 +4707,14 @@ ...@@ -4723,6 +4707,14 @@
"@typescript-eslint/types" "5.53.0" "@typescript-eslint/types" "5.53.0"
"@typescript-eslint/visitor-keys" "5.53.0" "@typescript-eslint/visitor-keys" "5.53.0"
"@typescript-eslint/scope-manager@5.59.0":
version "5.59.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz#86501d7a17885710b6716a23be2e93fc54a4fe8c"
integrity sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==
dependencies:
"@typescript-eslint/types" "5.59.0"
"@typescript-eslint/visitor-keys" "5.59.0"
"@typescript-eslint/type-utils@5.53.0": "@typescript-eslint/type-utils@5.53.0":
version "5.53.0" version "5.53.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz#41665449935ba9b4e6a1ba6e2a3f4b2c31d6cf97" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz#41665449935ba9b4e6a1ba6e2a3f4b2c31d6cf97"
...@@ -4733,11 +4725,6 @@ ...@@ -4733,11 +4725,6 @@
debug "^4.3.4" debug "^4.3.4"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/types@5.40.0":
version "5.40.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.40.0.tgz#8de07e118a10b8f63c99e174a3860f75608c822e"
integrity sha512-V1KdQRTXsYpf1Y1fXCeZ+uhjW48Niiw0VGt4V8yzuaDTU8Z1Xl7yQDyQNqyAFcVhpYXIVCEuxSIWTsLDpHgTbw==
"@typescript-eslint/types@5.45.0": "@typescript-eslint/types@5.45.0":
version "5.45.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.45.0.tgz#794760b9037ee4154c09549ef5a96599621109c5" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.45.0.tgz#794760b9037ee4154c09549ef5a96599621109c5"
...@@ -4748,18 +4735,10 @@ ...@@ -4748,18 +4735,10 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.53.0.tgz#f79eca62b97e518ee124086a21a24f3be267026f" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.53.0.tgz#f79eca62b97e518ee124086a21a24f3be267026f"
integrity sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A== integrity sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==
"@typescript-eslint/typescript-estree@5.40.0": "@typescript-eslint/types@5.59.0":
version "5.40.0" version "5.59.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.0.tgz#e305e6a5d65226efa5471ee0f12e0ffaab6d3075" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.0.tgz#3fcdac7dbf923ec5251545acdd9f1d42d7c4fe32"
integrity sha512-b0GYlDj8TLTOqwX7EGbw2gL5EXS2CPEWhF9nGJiGmEcmlpNBjyHsTwbqpyIEPVpl6br4UcBOYlcI2FJVtJkYhg== integrity sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==
dependencies:
"@typescript-eslint/types" "5.40.0"
"@typescript-eslint/visitor-keys" "5.40.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.45.0": "@typescript-eslint/typescript-estree@5.45.0":
version "5.45.0" version "5.45.0"
...@@ -4787,6 +4766,19 @@ ...@@ -4787,6 +4766,19 @@
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.59.0":
version "5.59.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz#8869156ee1dcfc5a95be3ed0e2809969ea28e965"
integrity sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==
dependencies:
"@typescript-eslint/types" "5.59.0"
"@typescript-eslint/visitor-keys" "5.59.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.53.0": "@typescript-eslint/utils@5.53.0":
version "5.53.0" version "5.53.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.53.0.tgz#e55eaad9d6fffa120575ffaa530c7e802f13bce8" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.53.0.tgz#e55eaad9d6fffa120575ffaa530c7e802f13bce8"
...@@ -4815,14 +4807,6 @@ ...@@ -4815,14 +4807,6 @@
eslint-utils "^3.0.0" eslint-utils "^3.0.0"
semver "^7.3.7" semver "^7.3.7"
"@typescript-eslint/visitor-keys@5.40.0":
version "5.40.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.0.tgz#dd2d38097f68e0d2e1e06cb9f73c0173aca54b68"
integrity sha512-ijJ+6yig+x9XplEpG2K6FUdJeQGGj/15U3S56W9IqXKJqleuD7zJ2AX/miLezwxpd7ZxDAqO87zWufKg+RPZyQ==
dependencies:
"@typescript-eslint/types" "5.40.0"
eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@5.45.0": "@typescript-eslint/visitor-keys@5.45.0":
version "5.45.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz#e0d160e9e7fdb7f8da697a5b78e7a14a22a70528" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz#e0d160e9e7fdb7f8da697a5b78e7a14a22a70528"
...@@ -4839,6 +4823,14 @@ ...@@ -4839,6 +4823,14 @@
"@typescript-eslint/types" "5.53.0" "@typescript-eslint/types" "5.53.0"
eslint-visitor-keys "^3.3.0" eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@5.59.0":
version "5.59.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz#a59913f2bf0baeb61b5cfcb6135d3926c3854365"
integrity sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==
dependencies:
"@typescript-eslint/types" "5.59.0"
eslint-visitor-keys "^3.3.0"
"@vitejs/plugin-react@^3.1.0": "@vitejs/plugin-react@^3.1.0":
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz#d1091f535eab8b83d6e74034d01e27d73c773240" resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz#d1091f535eab8b83d6e74034d01e27d73c773240"
...@@ -5988,6 +5980,13 @@ bufferutil@^4.0.1: ...@@ -5988,6 +5980,13 @@ bufferutil@^4.0.1:
dependencies: dependencies:
node-gyp-build "^4.3.0" node-gyp-build "^4.3.0"
busboy@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
dependencies:
streamsearch "^1.1.0"
call-bind@^1.0.0, call-bind@^1.0.2: call-bind@^1.0.0, call-bind@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
...@@ -6011,11 +6010,16 @@ camelcase@^6.2.0: ...@@ -6011,11 +6010,16 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001332, caniuse-lite@^1.0.30001400: caniuse-lite@^1.0.30001400:
version "1.0.30001418" version "1.0.30001418"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz#5f459215192a024c99e3e3a53aac310fc7cf24e6" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz#5f459215192a024c99e3e3a53aac310fc7cf24e6"
integrity sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg== integrity sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==
caniuse-lite@^1.0.30001406:
version "1.0.30001480"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz#9bbd35ee44c2480a1e3a3b9f4496f5066817164a"
integrity sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==
chakra-react-select@^4.4.3: chakra-react-select@^4.4.3:
version "4.4.3" version "4.4.3"
resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.4.3.tgz#678fcb25b90b9f977628694d1a9d49d072e01128" resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.4.3.tgz#678fcb25b90b9f977628694d1a9d49d072e01128"
...@@ -6139,6 +6143,11 @@ cli-truncate@^3.1.0: ...@@ -6139,6 +6143,11 @@ cli-truncate@^3.1.0:
slice-ansi "^5.0.0" slice-ansi "^5.0.0"
string-width "^5.0.0" string-width "^5.0.0"
client-only@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
cliui@^5.0.0: cliui@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
...@@ -6840,6 +6849,11 @@ deepmerge@^4.2.2, deepmerge@~4.2.2: ...@@ -6840,6 +6849,11 @@ deepmerge@^4.2.2, deepmerge@~4.2.2:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
define-lazy-prop@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
define-properties@^1.1.3, define-properties@^1.1.4: define-properties@^1.1.3, define-properties@^1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
...@@ -7088,7 +7102,7 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1, end-of-stream@^1.4.4: ...@@ -7088,7 +7102,7 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1, end-of-stream@^1.4.4:
dependencies: dependencies:
once "^1.4.0" once "^1.4.0"
enhanced-resolve@^5.10.0: enhanced-resolve@^5.10.0, enhanced-resolve@^5.12.0:
version "5.12.0" version "5.12.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634"
integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==
...@@ -7298,16 +7312,16 @@ escodegen@^2.0.0: ...@@ -7298,16 +7312,16 @@ escodegen@^2.0.0:
optionalDependencies: optionalDependencies:
source-map "~0.6.1" source-map "~0.6.1"
eslint-config-next@^12.3.0: eslint-config-next@13.3.0:
version "12.3.1" version "13.3.0"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.1.tgz#5d4eb0b7903cea81fd0d5106601d3afb0a453ff4" resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-13.3.0.tgz#c302fbecfe2b976ea306f7622af637ef9d9e3802"
integrity sha512-EN/xwKPU6jz1G0Qi6Bd/BqMnHLyRAL0VsaQaWA7F3KkjAgZHi4f1uL1JKGWNxdQpHTW/sdGONBd0bzxUka/DJg== integrity sha512-6YEwmFBX0VjBd3ODGW9df0Is0FLaRFdMN8eAahQG9CN6LjQ28J8AFr19ngxqMSg7Qv6Uca/3VeeBosJh1bzu0w==
dependencies: dependencies:
"@next/eslint-plugin-next" "12.3.1" "@next/eslint-plugin-next" "13.3.0"
"@rushstack/eslint-patch" "^1.1.3" "@rushstack/eslint-patch" "^1.1.3"
"@typescript-eslint/parser" "^5.21.0" "@typescript-eslint/parser" "^5.42.0"
eslint-import-resolver-node "^0.3.6" eslint-import-resolver-node "^0.3.6"
eslint-import-resolver-typescript "^2.7.1" eslint-import-resolver-typescript "^3.5.2"
eslint-plugin-import "^2.26.0" eslint-plugin-import "^2.26.0"
eslint-plugin-jsx-a11y "^6.5.1" eslint-plugin-jsx-a11y "^6.5.1"
eslint-plugin-react "^7.31.7" eslint-plugin-react "^7.31.7"
...@@ -7321,16 +7335,19 @@ eslint-import-resolver-node@^0.3.6: ...@@ -7321,16 +7335,19 @@ eslint-import-resolver-node@^0.3.6:
debug "^3.2.7" debug "^3.2.7"
resolve "^1.20.0" resolve "^1.20.0"
eslint-import-resolver-typescript@^2.7.1: eslint-import-resolver-typescript@^3.5.2:
version "2.7.1" version "3.5.5"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz#a90a4a1c80da8d632df25994c4c5fdcdd02b8751" resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz#0a9034ae7ed94b254a360fbea89187b60ea7456d"
integrity sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ== integrity sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==
dependencies: dependencies:
debug "^4.3.4" debug "^4.3.4"
glob "^7.2.0" enhanced-resolve "^5.12.0"
eslint-module-utils "^2.7.4"
get-tsconfig "^4.5.0"
globby "^13.1.3"
is-core-module "^2.11.0"
is-glob "^4.0.3" is-glob "^4.0.3"
resolve "^1.22.0" synckit "^0.8.5"
tsconfig-paths "^3.14.1"
eslint-module-utils@^2.7.3: eslint-module-utils@^2.7.3:
version "2.7.4" version "2.7.4"
...@@ -7339,6 +7356,13 @@ eslint-module-utils@^2.7.3: ...@@ -7339,6 +7356,13 @@ eslint-module-utils@^2.7.3:
dependencies: dependencies:
debug "^3.2.7" debug "^3.2.7"
eslint-module-utils@^2.7.4:
version "2.8.0"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
dependencies:
debug "^3.2.7"
eslint-plugin-es5@^1.5.0: eslint-plugin-es5@^1.5.0:
version "1.5.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-es5/-/eslint-plugin-es5-1.5.0.tgz#aab19af3d4798f7924bba309bc4f87087280fbba" resolved "https://registry.yarnpkg.com/eslint-plugin-es5/-/eslint-plugin-es5-1.5.0.tgz#aab19af3d4798f7924bba309bc4f87087280fbba"
...@@ -7864,7 +7888,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: ...@@ -7864,7 +7888,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-glob@^3.2.9: fast-glob@^3.2.11, fast-glob@^3.2.9:
version "3.2.12" version "3.2.12"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
...@@ -8204,6 +8228,11 @@ get-symbol-description@^1.0.0: ...@@ -8204,6 +8228,11 @@ get-symbol-description@^1.0.0:
call-bind "^1.0.2" call-bind "^1.0.2"
get-intrinsic "^1.1.1" get-intrinsic "^1.1.1"
get-tsconfig@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.5.0.tgz#6d52d1c7b299bd3ee9cd7638561653399ac77b0f"
integrity sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==
glob-parent@^5.1.2, glob-parent@~5.1.2: glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
...@@ -8247,7 +8276,7 @@ glob@7.1.7: ...@@ -8247,7 +8276,7 @@ glob@7.1.7:
once "^1.3.0" once "^1.3.0"
path-is-absolute "^1.0.0" path-is-absolute "^1.0.0"
glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: glob@^7.1.3, glob@^7.1.4:
version "7.2.3" version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
...@@ -8289,6 +8318,11 @@ globalthis@^1.0.3: ...@@ -8289,6 +8318,11 @@ globalthis@^1.0.3:
dependencies: dependencies:
define-properties "^1.1.3" define-properties "^1.1.3"
globalyzer@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
globby@^11.1.0: globby@^11.1.0:
version "11.1.0" version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
...@@ -8301,6 +8335,17 @@ globby@^11.1.0: ...@@ -8301,6 +8335,17 @@ globby@^11.1.0:
merge2 "^1.4.1" merge2 "^1.4.1"
slash "^3.0.0" slash "^3.0.0"
globby@^13.1.3:
version "13.1.4"
resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.4.tgz#2f91c116066bcec152465ba36e5caa4a13c01317"
integrity sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==
dependencies:
dir-glob "^3.0.1"
fast-glob "^3.2.11"
ignore "^5.2.0"
merge2 "^1.4.1"
slash "^4.0.0"
globrex@^0.1.2: globrex@^0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
...@@ -8691,6 +8736,13 @@ is-ci@^2.0.0: ...@@ -8691,6 +8736,13 @@ is-ci@^2.0.0:
dependencies: dependencies:
ci-info "^2.0.0" ci-info "^2.0.0"
is-core-module@^2.11.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4"
integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==
dependencies:
has "^1.0.3"
is-core-module@^2.8.1, is-core-module@^2.9.0: is-core-module@^2.8.1, is-core-module@^2.9.0:
version "2.10.0" version "2.10.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed"
...@@ -8710,7 +8762,7 @@ is-decimal@^1.0.0: ...@@ -8710,7 +8762,7 @@ is-decimal@^1.0.0:
resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5"
integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==
is-docker@^2.0.0: is-docker@^2.0.0, is-docker@^2.1.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
...@@ -8905,7 +8957,7 @@ is-what@^4.1.6: ...@@ -8905,7 +8957,7 @@ is-what@^4.1.6:
resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.7.tgz#c41dc1d2d2d6a9285c624c2505f61849c8b1f9cc" resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.7.tgz#c41dc1d2d2d6a9285c624c2505f61849c8b1f9cc"
integrity sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ== integrity sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==
is-wsl@^2.1.1: is-wsl@^2.1.1, is-wsl@^2.2.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
...@@ -10038,31 +10090,27 @@ next-transpile-modules@^10.0.0: ...@@ -10038,31 +10090,27 @@ next-transpile-modules@^10.0.0:
dependencies: dependencies:
enhanced-resolve "^5.10.0" enhanced-resolve "^5.10.0"
next@12.2.5: next@13.3.0:
version "12.2.5" version "13.3.0"
resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717" resolved "https://registry.yarnpkg.com/next/-/next-13.3.0.tgz#40632d303d74fc8521faa0a5bf4a033a392749b1"
integrity sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA== integrity sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==
dependencies: dependencies:
"@next/env" "12.2.5" "@next/env" "13.3.0"
"@swc/helpers" "0.4.3" "@swc/helpers" "0.4.14"
caniuse-lite "^1.0.30001332" busboy "1.6.0"
caniuse-lite "^1.0.30001406"
postcss "8.4.14" postcss "8.4.14"
styled-jsx "5.0.4" styled-jsx "5.1.1"
use-sync-external-store "1.2.0"
optionalDependencies: optionalDependencies:
"@next/swc-android-arm-eabi" "12.2.5" "@next/swc-darwin-arm64" "13.3.0"
"@next/swc-android-arm64" "12.2.5" "@next/swc-darwin-x64" "13.3.0"
"@next/swc-darwin-arm64" "12.2.5" "@next/swc-linux-arm64-gnu" "13.3.0"
"@next/swc-darwin-x64" "12.2.5" "@next/swc-linux-arm64-musl" "13.3.0"
"@next/swc-freebsd-x64" "12.2.5" "@next/swc-linux-x64-gnu" "13.3.0"
"@next/swc-linux-arm-gnueabihf" "12.2.5" "@next/swc-linux-x64-musl" "13.3.0"
"@next/swc-linux-arm64-gnu" "12.2.5" "@next/swc-win32-arm64-msvc" "13.3.0"
"@next/swc-linux-arm64-musl" "12.2.5" "@next/swc-win32-ia32-msvc" "13.3.0"
"@next/swc-linux-x64-gnu" "12.2.5" "@next/swc-win32-x64-msvc" "13.3.0"
"@next/swc-linux-x64-musl" "12.2.5"
"@next/swc-win32-arm64-msvc" "12.2.5"
"@next/swc-win32-ia32-msvc" "12.2.5"
"@next/swc-win32-x64-msvc" "12.2.5"
nextjs-routes@^1.0.8: nextjs-routes@^1.0.8:
version "1.0.8" version "1.0.8"
...@@ -10310,6 +10358,15 @@ open@^7.4.2: ...@@ -10310,6 +10358,15 @@ open@^7.4.2:
is-docker "^2.0.0" is-docker "^2.0.0"
is-wsl "^2.1.1" is-wsl "^2.1.1"
open@^8.4.0:
version "8.4.2"
resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==
dependencies:
define-lazy-prop "^2.0.0"
is-docker "^2.1.1"
is-wsl "^2.2.0"
optionator@^0.8.1: optionator@^0.8.1:
version "0.8.3" version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
...@@ -11718,6 +11775,11 @@ slash@^3.0.0: ...@@ -11718,6 +11775,11 @@ slash@^3.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
slash@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
slice-ansi@^3.0.0: slice-ansi@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
...@@ -11831,6 +11893,11 @@ stream-shift@^1.0.0: ...@@ -11831,6 +11893,11 @@ stream-shift@^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
streamsearch@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
strict-uri-encode@^2.0.0: strict-uri-encode@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
...@@ -12036,10 +12103,12 @@ style-value-types@5.0.0: ...@@ -12036,10 +12103,12 @@ style-value-types@5.0.0:
hey-listen "^1.0.8" hey-listen "^1.0.8"
tslib "^2.1.0" tslib "^2.1.0"
styled-jsx@5.0.4: styled-jsx@5.1.1:
version "5.0.4" version "5.1.1"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ== integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
dependencies:
client-only "0.0.1"
stylis@4.1.3: stylis@4.1.3:
version "4.1.3" version "4.1.3"
...@@ -12190,6 +12259,14 @@ symbol-tree@^3.2.4: ...@@ -12190,6 +12259,14 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
synckit@^0.8.5:
version "0.8.5"
resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3"
integrity sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==
dependencies:
"@pkgr/utils" "^2.3.1"
tslib "^2.5.0"
tabbable@^4.0.0: tabbable@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261"
...@@ -12252,6 +12329,14 @@ thread-stream@^2.0.0: ...@@ -12252,6 +12329,14 @@ thread-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
tiny-glob@^0.2.9:
version "0.2.9"
resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2"
integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==
dependencies:
globalyzer "0.1.0"
globrex "^0.1.2"
tiny-invariant@^1.0.6: tiny-invariant@^1.0.6:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
...@@ -12385,7 +12470,7 @@ tslib@2.4.0, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4. ...@@ -12385,7 +12470,7 @@ tslib@2.4.0, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tslib@^2.3.0: tslib@^2.3.0, tslib@^2.5.0:
version "2.5.0" version "2.5.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
......
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