Merge branch 'main' of github.com:blockscout/frontend into tom2drum/issue-1035
@@ -22,7 +22,7 @@ jobs:
|
||||
code_quality:
|
||||
name: Code quality
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'WIP') && !(github.event.action == 'unlabeled' && github.event.label.name != 'WIP') }}
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip checks') && !(github.event.action == 'unlabeled' && github.event.label.name != 'skip checks') }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+-[a-z]+*' # e.g v1.2.3-alpha
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+-[a-z]+*' # e.g v1.2.3-alpha.2
|
||||
|
||||
jobs:
|
||||
checks:
|
||||
@@ -24,9 +24,29 @@ jobs:
|
||||
uses: "./.github/workflows/e2e-tests.yml"
|
||||
secrets: inherit
|
||||
|
||||
version:
|
||||
name: Pre-release version info
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
is_initial: ${{ steps.is_initial.outputs.result }}
|
||||
steps:
|
||||
- name: Determine if it is the initial version of the pre-release
|
||||
id: is_initial
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
TAG: ${{ github.ref_name }}
|
||||
with:
|
||||
script: |
|
||||
const tag = process.env.TAG;
|
||||
const REGEXP = /^v[0-9]+.[0-9]+.[0-9]+-[a-z]+((\.|-)\d+)?$/i;
|
||||
const match = tag.match(REGEXP);
|
||||
return match && !match[1] ? 'true' : 'false';
|
||||
|
||||
label_issues:
|
||||
name: Add pre-release label to issues
|
||||
uses: './.github/workflows/label-issues-in-release.yml'
|
||||
needs: [ version ]
|
||||
if: ${{ needs.version.outputs.is_initial == 'true' }}
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
label_name: 'pre-release'
|
||||
|
||||
@@ -89,6 +89,10 @@ WORKDIR /app
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
# Set the correct permission for prerender cache
|
||||
RUN mkdir .next
|
||||
RUN chown nextjs:nodejs .next
|
||||
|
||||
COPY --from=builder /app/next.config.js ./
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder /app/package.json ./package.json
|
||||
|
||||
@@ -29,6 +29,7 @@ See our [Contribution guide](./docs/CONTRIBUTING.md) for pull request protocol.
|
||||
- [Contribution guide](./docs/CONTRIBUTING.md)
|
||||
- [Making a custom build](./docs/CUSTOM_BUILD.md)
|
||||
- [Frontend migration guide](https://docs.blockscout.com/for-developers/frontend-migration)
|
||||
- [Manual deployment guide with backend and microservices](https://docs.blockscout.com/for-developers/deployment/manual-deployment-guide)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -157,8 +157,8 @@ We have 3 pre-configured projects. You can run your test with the desired projec
|
||||
|
||||
### Opening PR and getting it accepted
|
||||
|
||||
1. Push your changes and create a Pull Request. If you are still working on the task, please use "Draft Pull Request" option, so we know that it is not ready yet. In addition, you can add label "WIP" to your PR, so all CI checks will not be triggered.
|
||||
2. Once you finish your work, remove label "WIP" from PR, if it was added before, and publish PR if it was in the draft state
|
||||
1. Push your changes and create a Pull Request. If you are still working on the task, please use "Draft Pull Request" option, so we know that it is not ready yet. In addition, you can add label "skip checks" to your PR, so all CI checks will not be triggered.
|
||||
2. Once you finish your work, remove label "skip checks" from PR, if it was added before, and publish PR if it was in the draft state
|
||||
3. Make sure that all code checks and tests are successfully passed
|
||||
4. Add description to your Pull Request and link an existing issue(s) that it is fixing
|
||||
5. Request review from one or all core team members: @tom2drum, @isstuev. Our core team is committed to reviewing patches in a timely manner.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
## Description and Related Issue(s)
|
||||
|
||||
*[Provide a brief description of the changes or enhancements introduced by this pull request and explain motivation behind them. Cite any related issue(s) or bug(s) that it addresses using the [format](https://blog.github.com/2013-05-14-closing-issues-via-pull-requests/) `Fixes #123` or `Resolves #456`.]*
|
||||
|
||||
### Proposed Changes
|
||||
*[Specify the changes or additions made in this pull request. Please mention if any changes were made to the ENV variables]*
|
||||
|
||||
### Breaking or Incompatible Changes
|
||||
*[Describe any breaking or incompatible changes introduced by this pull request. Specify how users might need to modify their code or configurations to accommodate these changes.]*
|
||||
|
||||
### Additional Information
|
||||
*[Include any additional information, context, or screenshots that may be helpful for reviewers.]*
|
||||
|
||||
## Checklist for PR author
|
||||
- [ ] I have tested these changes locally.
|
||||
- [ ] I added tests to cover any new functionality, following this [guide](./CONTRIBUTING.md#writing--running-tests)
|
||||
- [ ] Whenever I fix a bug, I include a regression test to ensure that the bug does not reappear silently.
|
||||
- [ ] If I have added, changed, renamed, or removed an environment variable, I have updated the list of environment variables in the [documentation](ENVS.md) and made the necessary changes to the validator script according to the [guide](./CONTRIBUTING.md#adding-new-env-variable)
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 1.593A8.407 8.407 0 0 0 3.332 15.12c1.465-2.162 3.89-3.556 6.668-3.556 2.784 0 5.2 1.461 6.66 3.567A8.407 8.407 0 0 0 10 1.593ZM0 10C0 4.477 4.477 0 10 0s10 4.477 10 10-4.477 10-10 10S0 15.523 0 10Zm4.476 6.287c1.443 1.295 3.412 2.039 5.524 2.039a8.529 8.529 0 0 0 5.51-2.045c-1.17-1.85-3.2-3.123-5.51-3.123-2.333 0-4.363 1.225-5.524 3.129Zm3.388-8.975a2.136 2.136 0 1 1 4.272 0 2.136 2.136 0 0 1-4.272 0ZM10 3.584a3.729 3.729 0 1 0 0 7.457 3.729 3.729 0 0 0 0-7.457Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 626 B |
@@ -58,9 +58,16 @@ import type {
|
||||
} from 'types/api/token';
|
||||
import type { TokensResponse, TokensFilters, TokensSorting, TokenInstanceTransferResponse, TokensBridgedFilters } from 'types/api/tokens';
|
||||
import type { TokenTransferResponse, TokenTransferFilters } from 'types/api/tokenTransfer';
|
||||
import type { TransactionsResponseValidated, TransactionsResponsePending, Transaction, TransactionsResponseWatchlist } from 'types/api/transaction';
|
||||
import type {
|
||||
TransactionsResponseValidated,
|
||||
TransactionsResponsePending,
|
||||
Transaction,
|
||||
TransactionsResponseWatchlist,
|
||||
TransactionsSorting,
|
||||
} from 'types/api/transaction';
|
||||
import type { TTxsFilters } from 'types/api/txsFilters';
|
||||
import type { TxStateChanges } from 'types/api/txStateChanges';
|
||||
import type { VerifiedContractsSorting } from 'types/api/verifiedContracts';
|
||||
import type { VisualizedContract } from 'types/api/visualization';
|
||||
import type { WithdrawalsResponse, WithdrawalsCounters } from 'types/api/withdrawals';
|
||||
import type { ZkEvmL2TxnBatch, ZkEvmL2TxnBatchesItem, ZkEvmL2TxnBatchesResponse, ZkEvmL2TxnBatchTxs } from 'types/api/zkEvmL2TxnBatches';
|
||||
@@ -725,5 +732,7 @@ never;
|
||||
export type PaginationSorting<Q extends PaginatedResources> =
|
||||
Q extends 'tokens' ? TokensSorting :
|
||||
Q extends 'tokens_bridged' ? TokensSorting :
|
||||
Q extends 'verified_contracts' ? VerifiedContractsSorting :
|
||||
Q extends 'address_txs' ? TransactionsSorting :
|
||||
never;
|
||||
/* eslint-enable @typescript-eslint/indent */
|
||||
|
||||
@@ -61,6 +61,7 @@ Type extends EventTypes.VERIFY_TOKEN ? {
|
||||
'Action': 'Form opened' | 'Submit';
|
||||
} :
|
||||
Type extends EventTypes.WALLET_CONNECT ? {
|
||||
'Source': 'Header' | 'Smart contracts';
|
||||
'Status': 'Started' | 'Connected';
|
||||
} :
|
||||
Type extends EventTypes.CONTRACT_INTERACTION ? {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type * as Sentry from '@sentry/react';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { BrowserTracing } from '@sentry/tracing';
|
||||
|
||||
import appConfig from 'configs/app';
|
||||
@@ -90,3 +90,12 @@ export function configureScope(scope: Sentry.Scope) {
|
||||
}
|
||||
scope.setTag('app_instance', feature.instance);
|
||||
}
|
||||
|
||||
export function init() {
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sentry.init(config);
|
||||
Sentry.configureScope(configureScope);
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import * as Sentry from '@sentry/react';
|
||||
import React from 'react';
|
||||
|
||||
import { config, configureScope } from './config';
|
||||
|
||||
export default function useConfigSentry() {
|
||||
React.useEffect(() => {
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
|
||||
// gotta init sentry in browser
|
||||
Sentry.init(config);
|
||||
Sentry.configureScope(configureScope);
|
||||
}, []);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
import type { Sort } from 'types/client/txs-sort';
|
||||
|
||||
import compareBns from 'lib/bigint/compareBns';
|
||||
|
||||
const sortTxs = (sorting?: Sort) => (tx1: Transaction, tx2: Transaction) => {
|
||||
switch (sorting) {
|
||||
case 'val-desc':
|
||||
return compareBns(tx1.value, tx2.value);
|
||||
case 'val-asc':
|
||||
return compareBns(tx2.value, tx1.value);
|
||||
case 'fee-desc':
|
||||
return compareBns(tx1.fee.value || 0, tx2.fee.value || 0);
|
||||
case 'fee-asc':
|
||||
return compareBns(tx2.fee.value || 0, tx1.fee.value || 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
export default sortTxs;
|
||||
@@ -7,18 +7,19 @@ import useAdblockDetect from 'lib/hooks/useAdblockDetect';
|
||||
import useGetCsrfToken from 'lib/hooks/useGetCsrfToken';
|
||||
import * as metadata from 'lib/metadata';
|
||||
import * as mixpanel from 'lib/mixpanel';
|
||||
import useConfigSentry from 'lib/sentry/useConfigSentry';
|
||||
import { init as initSentry } from 'lib/sentry/config';
|
||||
|
||||
type Props = Route & {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
initSentry();
|
||||
|
||||
const PageNextJs = (props: Props) => {
|
||||
const { title, description, opengraph } = metadata.generate(props);
|
||||
|
||||
useGetCsrfToken();
|
||||
useAdblockDetect();
|
||||
useConfigSentry();
|
||||
|
||||
const isMixpanelInited = mixpanel.useInit();
|
||||
mixpanel.useLogPageView(isMixpanelInited);
|
||||
|
||||
@@ -58,14 +58,15 @@
|
||||
"bignumber.js": "^9.1.0",
|
||||
"blo": "^1.1.1",
|
||||
"chakra-react-select": "^4.4.3",
|
||||
"crypto-js": "^4.1.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"d3": "^7.6.1",
|
||||
"dappscout-iframe": "^0.1.0",
|
||||
"dayjs": "^1.11.5",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"framer-motion": "^6.5.1",
|
||||
"gradient-avatar": "^1.0.2",
|
||||
"graphiql": "^2.2.0",
|
||||
"graphql": "^16.6.0",
|
||||
"graphql": "^16.8.1",
|
||||
"graphql-ws": "^5.11.3",
|
||||
"js-cookie": "^3.0.1",
|
||||
"lodash": "^4.0.0",
|
||||
|
||||
@@ -17,6 +17,7 @@ import theme from 'theme';
|
||||
import AppErrorBoundary from 'ui/shared/AppError/AppErrorBoundary';
|
||||
import GoogleAnalytics from 'ui/shared/GoogleAnalytics';
|
||||
import Layout from 'ui/shared/layout/Layout';
|
||||
import Web3ModalProvider from 'ui/shared/Web3ModalProvider';
|
||||
|
||||
import 'lib/setLocale';
|
||||
|
||||
@@ -52,17 +53,19 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
||||
{ ...ERROR_SCREEN_STYLES }
|
||||
onError={ handleError }
|
||||
>
|
||||
<AppContextProvider pageProps={ pageProps }>
|
||||
<QueryClientProvider client={ queryClient }>
|
||||
<ScrollDirectionProvider>
|
||||
<SocketProvider url={ `${ config.api.socket }${ config.api.basePath }/socket/v2` }>
|
||||
{ getLayout(<Component { ...pageProps }/>) }
|
||||
</SocketProvider>
|
||||
</ScrollDirectionProvider>
|
||||
<ReactQueryDevtools buttonPosition="bottom-left" position="left"/>
|
||||
<GoogleAnalytics/>
|
||||
</QueryClientProvider>
|
||||
</AppContextProvider>
|
||||
<Web3ModalProvider>
|
||||
<AppContextProvider pageProps={ pageProps }>
|
||||
<QueryClientProvider client={ queryClient }>
|
||||
<ScrollDirectionProvider>
|
||||
<SocketProvider url={ `${ config.api.socket }${ config.api.basePath }/socket/v2` }>
|
||||
{ getLayout(<Component { ...pageProps }/>) }
|
||||
</SocketProvider>
|
||||
</ScrollDirectionProvider>
|
||||
<ReactQueryDevtools buttonPosition="bottom-left" position="left"/>
|
||||
<GoogleAnalytics/>
|
||||
</QueryClientProvider>
|
||||
</AppContextProvider>
|
||||
</Web3ModalProvider>
|
||||
</AppErrorBoundary>
|
||||
</ChakraProvider>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,8 @@ import type { NextPageWithLayout } from 'nextjs/types';
|
||||
import type { Props } from 'nextjs/getServerSideProps';
|
||||
import PageNextJs from 'nextjs/PageNextJs';
|
||||
|
||||
import LayoutApp from 'ui/shared/layout/LayoutApp';
|
||||
|
||||
const MarketplaceApp = dynamic(() => import('ui/pages/MarketplaceApp'), { ssr: false });
|
||||
|
||||
const Page: NextPageWithLayout<Props> = (props: Props) => {
|
||||
@@ -16,6 +18,14 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Page.getLayout = function getLayout(page: React.ReactElement) {
|
||||
return (
|
||||
<LayoutApp>
|
||||
{ page }
|
||||
</LayoutApp>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
||||
export { marketplace as getServerSideProps } from 'nextjs/getServerSideProps';
|
||||
|
||||
@@ -12,7 +12,7 @@ const Page: NextPage = () => {
|
||||
return (
|
||||
<PageNextJs pathname="/apps">
|
||||
<>
|
||||
<PageTitle title="Marketplace"/>
|
||||
<PageTitle title="DAppscout"/>
|
||||
<Marketplace/>
|
||||
</>
|
||||
</PageNextJs>
|
||||
|
||||
@@ -117,3 +117,12 @@ export type TransactionType = 'rootstock_remasc' |
|
||||
'coin_transfer'
|
||||
|
||||
export type TxsResponse = TransactionsResponseValidated | TransactionsResponsePending | BlockTransactionsResponse;
|
||||
|
||||
export interface TransactionsSorting {
|
||||
sort: 'value' | 'fee';
|
||||
order: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
export type TransactionsSortingField = TransactionsSorting['sort'];
|
||||
|
||||
export type TransactionsSortingValue = `${ TransactionsSortingField }-${ TransactionsSorting['order'] }`;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export interface VerifiedContractsSorting {
|
||||
sort: 'balance' | 'txs_count';
|
||||
order: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
export type VerifiedContractsSortingField = VerifiedContractsSorting['sort'];
|
||||
|
||||
export type VerifiedContractsSortingValue = `${ VerifiedContractsSortingField }-${ VerifiedContractsSorting['order'] }`;
|
||||
@@ -1 +0,0 @@
|
||||
export type Sort = 'val-desc' | 'val-asc' | 'fee-desc' | 'fee-asc' | '';
|
||||
@@ -5,7 +5,7 @@ import React from 'react';
|
||||
import type { SocketMessage } from 'lib/socket/types';
|
||||
import type { AddressFromToFilter, AddressTransactionsResponse } from 'types/api/address';
|
||||
import { AddressFromToFilterValues } from 'types/api/address';
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
import type { Transaction, TransactionsSortingField, TransactionsSortingValue, TransactionsSorting } from 'types/api/transaction';
|
||||
|
||||
import { getResourceKey } from 'lib/api/useApiQuery';
|
||||
import getFilterValueFromQuery from 'lib/getFilterValueFromQuery';
|
||||
@@ -18,7 +18,10 @@ import { generateListStub } from 'stubs/utils';
|
||||
import ActionBar from 'ui/shared/ActionBar';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
import getSortValueFromQuery from 'ui/shared/sort/getSortValueFromQuery';
|
||||
import TxsWithAPISorting from 'ui/txs/TxsWithAPISorting';
|
||||
import { SORT_OPTIONS } from 'ui/txs/useTxsSort';
|
||||
|
||||
import AddressCsvExportLink from './AddressCsvExportLink';
|
||||
import AddressTxsFilter from './AddressTxsFilter';
|
||||
@@ -53,6 +56,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
|
||||
const [ socketAlert, setSocketAlert ] = React.useState('');
|
||||
const [ newItemsCount, setNewItemsCount ] = React.useState(0);
|
||||
const [ sort, setSort ] = React.useState<TransactionsSortingValue | undefined>(getSortValueFromQuery<TransactionsSortingValue>(router.query, SORT_OPTIONS));
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const currentAddress = getQueryParamString(router.query.hash);
|
||||
@@ -63,6 +67,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
resourceName: 'address_txs',
|
||||
pathParams: { hash: currentAddress },
|
||||
filters: { filter: filterValue },
|
||||
sorting: getSortParamsFromValue<TransactionsSortingValue, TransactionsSortingField, TransactionsSorting['order']>(sort),
|
||||
scrollRef,
|
||||
options: {
|
||||
placeholderData: generateListStub<'address_txs'>(TX, 50, { next_page_params: {
|
||||
@@ -177,7 +182,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
<Pagination { ...addressTxsQuery.pagination } ml={ 8 }/>
|
||||
</ActionBar>
|
||||
) }
|
||||
<TxsContent
|
||||
<TxsWithAPISorting
|
||||
filter={ filter }
|
||||
filterValue={ filterValue }
|
||||
query={ addressTxsQuery }
|
||||
@@ -187,6 +192,8 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
socketInfoAlert={ socketAlert }
|
||||
socketInfoNum={ newItemsCount }
|
||||
top={ 80 }
|
||||
sorting={ sort }
|
||||
setSort={ setSort }
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -45,6 +45,30 @@ interface Props {
|
||||
hash: string;
|
||||
}
|
||||
|
||||
type ItemProps = {
|
||||
item: DistributionItem;
|
||||
vulnerabilities: SolidityscanReport['scan_report']['scan_summary']['issue_severity_distribution'];
|
||||
vulnerabilitiesCount: number;
|
||||
}
|
||||
|
||||
const SolidityScanReportItem = ({ item, vulnerabilities, vulnerabilitiesCount }: ItemProps) => {
|
||||
const bgBar = useColorModeValue('blackAlpha.50', 'whiteAlpha.50');
|
||||
const yetAnotherGrayColor = useColorModeValue('gray.400', 'gray.500');
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box w={ 3 } h={ 3 } bg={ item.color } borderRadius="6px" mr={ 2 }></Box>
|
||||
<Flex justifyContent="space-between" mr={ 3 }>
|
||||
<Text>{ item.name }</Text>
|
||||
<Text color={ vulnerabilities[item.id] > 0 ? 'text' : yetAnotherGrayColor }>{ vulnerabilities[item.id] }</Text>
|
||||
</Flex>
|
||||
<Box bg={ bgBar } h="10px" borderRadius="8px">
|
||||
<Box bg={ item.color } w={ vulnerabilities[item.id] / vulnerabilitiesCount } h="10px" borderRadius="8px"/>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const SolidityscanReport = ({ className, hash }: Props) => {
|
||||
const { isOpen, onToggle, onClose } = useDisclosure();
|
||||
|
||||
@@ -58,7 +82,6 @@ const SolidityscanReport = ({ className, hash }: Props) => {
|
||||
|
||||
const score = Number(data?.scan_report.scan_summary.score_v2);
|
||||
|
||||
const bgBar = useColorModeValue('blackAlpha.50', 'whiteAlpha.50');
|
||||
const chartGrayColor = useColorModeValue('gray.100', 'gray.700');
|
||||
const yetAnotherGrayColor = useColorModeValue('gray.400', 'gray.500');
|
||||
const popoverBgColor = useColorModeValue('white', 'gray.900');
|
||||
@@ -136,16 +159,7 @@ const SolidityscanReport = ({ className, hash }: Props) => {
|
||||
<Text py="7px" variant="secondary" fontSize="xs" fontWeight={ 500 }>Vulnerabilities distribution</Text>
|
||||
<Grid templateColumns="20px 1fr 100px" alignItems="center" rowGap={ 2 }>
|
||||
{ DISTRIBUTION_ITEMS.map(item => (
|
||||
<>
|
||||
<Box w={ 3 } h={ 3 } bg={ item.color } borderRadius="6px" mr={ 2 }></Box>
|
||||
<Flex justifyContent="space-between" mr={ 3 }>
|
||||
<Text>{ item.name }</Text>
|
||||
<Text color={ vulnerabilities[item.id] > 0 ? 'text' : yetAnotherGrayColor }>{ vulnerabilities[item.id] }</Text>
|
||||
</Flex>
|
||||
<Box bg={ bgBar } h="10px" borderRadius="8px">
|
||||
<Box bg={ item.color } w={ vulnerabilities[item.id] / vulnerabilitiesCount } h="10px" borderRadius="8px"/>
|
||||
</Box>
|
||||
</>
|
||||
<SolidityScanReportItem item={ item } key={ item.id } vulnerabilities={ vulnerabilities } vulnerabilitiesCount={ vulnerabilitiesCount }/>
|
||||
)) }
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
@@ -17,11 +17,11 @@ const ContractConnectWallet = () => {
|
||||
setIsModalOpening(true);
|
||||
await open();
|
||||
setIsModalOpening(false);
|
||||
mixpanel.logEvent(mixpanel.EventTypes.WALLET_CONNECT, { Status: 'Started' });
|
||||
mixpanel.logEvent(mixpanel.EventTypes.WALLET_CONNECT, { Source: 'Smart contracts', Status: 'Started' });
|
||||
}, [ open ]);
|
||||
|
||||
const handleAccountConnected = React.useCallback(({ isReconnected }: { isReconnected: boolean }) => {
|
||||
!isReconnected && mixpanel.logEvent(mixpanel.EventTypes.WALLET_CONNECT, { Status: 'Connected' });
|
||||
!isReconnected && mixpanel.logEvent(mixpanel.EventTypes.WALLET_CONNECT, { Source: 'Smart contracts', Status: 'Connected' });
|
||||
}, []);
|
||||
|
||||
const handleDisconnect = React.useCallback(() => {
|
||||
|
||||
@@ -15,6 +15,7 @@ interface Props extends MarketplaceAppPreview {
|
||||
isFavorite: boolean;
|
||||
onFavoriteClick: (id: string, isFavorite: boolean) => void;
|
||||
isLoading: boolean;
|
||||
showDisclaimer: (id: string) => void;
|
||||
}
|
||||
|
||||
const MarketplaceAppCard = ({
|
||||
@@ -30,9 +31,18 @@ const MarketplaceAppCard = ({
|
||||
isFavorite,
|
||||
onFavoriteClick,
|
||||
isLoading,
|
||||
showDisclaimer,
|
||||
}: Props) => {
|
||||
const categoriesLabel = categories.join(', ');
|
||||
|
||||
const handleClick = useCallback((event: MouseEvent) => {
|
||||
const isShown = window.localStorage.getItem('marketplace-disclaimer-shown');
|
||||
if (!isShown) {
|
||||
event.preventDefault();
|
||||
showDisclaimer(id);
|
||||
}
|
||||
}, [ showDisclaimer, id ]);
|
||||
|
||||
const handleInfoClick = useCallback((event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
onInfoClick(id);
|
||||
@@ -100,6 +110,7 @@ const MarketplaceAppCard = ({
|
||||
url={ url }
|
||||
external={ external }
|
||||
title={ title }
|
||||
onClick={ handleClick }
|
||||
/>
|
||||
</Skeleton>
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import { LinkOverlay } from '@chakra-ui/react';
|
||||
import NextLink from 'next/link';
|
||||
import React from 'react';
|
||||
import type { MouseEvent } from 'react';
|
||||
|
||||
type Props = {
|
||||
id: string;
|
||||
url: string;
|
||||
external?: boolean;
|
||||
title: string;
|
||||
onClick?: (event: MouseEvent) => void;
|
||||
}
|
||||
|
||||
const MarketplaceAppCardLink = ({ url, external, id, title }: Props) => {
|
||||
const MarketplaceAppCardLink = ({ url, external, id, title, onClick }: Props) => {
|
||||
return external ? (
|
||||
<LinkOverlay href={ url } isExternal={ true }>
|
||||
{ title }
|
||||
</LinkOverlay>
|
||||
) : (
|
||||
<NextLink href={{ pathname: '/apps/[id]', query: { id } }} passHref legacyBehavior>
|
||||
<LinkOverlay>
|
||||
<LinkOverlay onClick={ onClick }>
|
||||
{ title }
|
||||
</LinkOverlay>
|
||||
</NextLink>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Heading, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Text, Button, useColorModeValue } from '@chakra-ui/react';
|
||||
import NextLink from 'next/link';
|
||||
import React from 'react';
|
||||
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
appId: string;
|
||||
}
|
||||
|
||||
const MarketplaceDisclaimerModal = ({ isOpen, onClose, appId }: Props) => {
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const handleContinueClick = React.useCallback(() => {
|
||||
window.localStorage.setItem('marketplace-disclaimer-shown', 'true');
|
||||
}, [ ]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={ isOpen }
|
||||
onClose={ onClose }
|
||||
size={ isMobile ? 'full' : 'md' }
|
||||
isCentered
|
||||
>
|
||||
<ModalOverlay/>
|
||||
|
||||
<ModalContent>
|
||||
<ModalHeader>
|
||||
<Heading
|
||||
as="h2"
|
||||
fontSize="2xl"
|
||||
fontWeight="medium"
|
||||
lineHeight={ 1 }
|
||||
color={ useColorModeValue('blackAlpha.800', 'whiteAlpha.800') }
|
||||
>
|
||||
Disclaimer
|
||||
</Heading>
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<Text color={ useColorModeValue('gray.800', 'whiteAlpha.800') }>
|
||||
You are now accessing a third-party app. Blockscout does not own, control, maintain, or audit 3rd party apps,{ ' ' }
|
||||
and is not liable for any losses associated with these interactions. Please do so at your own risk.
|
||||
<br/><br/>
|
||||
By clicking continue, you agree that you understand the risks and have read the Disclaimer.
|
||||
</Text>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter
|
||||
display="flex"
|
||||
flexDirection="row"
|
||||
alignItems="center"
|
||||
>
|
||||
<NextLink href={{ pathname: '/apps/[id]', query: { id: appId } }} passHref legacyBehavior>
|
||||
<Button
|
||||
variant="solid"
|
||||
colorScheme="blue"
|
||||
mr={ 6 }
|
||||
py="10px"
|
||||
onClick={ handleContinueClick }
|
||||
>
|
||||
Continue to app
|
||||
</Button>
|
||||
</NextLink>
|
||||
<Button
|
||||
variant="outline"
|
||||
colorScheme="blue"
|
||||
onClick={ onClose }
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default MarketplaceDisclaimerModal;
|
||||
@@ -14,9 +14,10 @@ type Props = {
|
||||
favoriteApps: Array<string>;
|
||||
onFavoriteClick: (id: string, isFavorite: boolean) => void;
|
||||
isLoading: boolean;
|
||||
showDisclaimer: (id: string) => void;
|
||||
}
|
||||
|
||||
const MarketplaceList = ({ apps, onAppClick, favoriteApps, onFavoriteClick, isLoading }: Props) => {
|
||||
const MarketplaceList = ({ apps, onAppClick, favoriteApps, onFavoriteClick, isLoading, showDisclaimer }: Props) => {
|
||||
return apps.length > 0 ? (
|
||||
<Grid
|
||||
templateColumns={{
|
||||
@@ -41,6 +42,7 @@ const MarketplaceList = ({ apps, onAppClick, favoriteApps, onFavoriteClick, isLo
|
||||
isFavorite={ favoriteApps.includes(app.id) }
|
||||
onFavoriteClick={ onFavoriteClick }
|
||||
isLoading={ isLoading }
|
||||
showDisclaimer={ showDisclaimer }
|
||||
/>
|
||||
)) }
|
||||
</Grid>
|
||||
|
||||
@@ -29,6 +29,8 @@ export default function useMarketplace() {
|
||||
const [ selectedCategoryId, setSelectedCategoryId ] = React.useState<string>(MarketplaceCategory.ALL);
|
||||
const [ filterQuery, setFilterQuery ] = React.useState(defaultFilterQuery);
|
||||
const [ favoriteApps, setFavoriteApps ] = React.useState<Array<string>>([]);
|
||||
const [ isAppInfoModalOpen, setIsAppInfoModalOpen ] = React.useState<boolean>(false);
|
||||
const [ isDisclaimerModalOpen, setIsDisclaimerModalOpen ] = React.useState<boolean>(false);
|
||||
|
||||
const handleFavoriteClick = React.useCallback((id: string, isFavorite: boolean) => {
|
||||
const favoriteApps = getFavoriteApps();
|
||||
@@ -46,10 +48,20 @@ export default function useMarketplace() {
|
||||
|
||||
const showAppInfo = React.useCallback((id: string) => {
|
||||
setSelectedAppId(id);
|
||||
setIsAppInfoModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const showDisclaimer = React.useCallback((id: string) => {
|
||||
setSelectedAppId(id);
|
||||
setIsDisclaimerModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const debouncedFilterQuery = useDebounce(filterQuery, 500);
|
||||
const clearSelectedAppId = React.useCallback(() => setSelectedAppId(null), []);
|
||||
const clearSelectedAppId = React.useCallback(() => {
|
||||
setSelectedAppId(null);
|
||||
setIsAppInfoModalOpen(false);
|
||||
setIsDisclaimerModalOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleCategoryChange = React.useCallback((newCategory: string) => {
|
||||
setSelectedCategoryId(newCategory);
|
||||
@@ -104,6 +116,9 @@ export default function useMarketplace() {
|
||||
clearSelectedAppId,
|
||||
favoriteApps,
|
||||
onFavoriteClick: handleFavoriteClick,
|
||||
isAppInfoModalOpen,
|
||||
isDisclaimerModalOpen,
|
||||
showDisclaimer,
|
||||
}), [
|
||||
selectedCategoryId,
|
||||
categories,
|
||||
@@ -118,5 +133,8 @@ export default function useMarketplace() {
|
||||
isPlaceholderData,
|
||||
showAppInfo,
|
||||
debouncedFilterQuery,
|
||||
isAppInfoModalOpen,
|
||||
isDisclaimerModalOpen,
|
||||
showDisclaimer,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { TypedData } from 'abitype';
|
||||
import { useCallback } from 'react';
|
||||
import type { Account, SignTypedDataParameters } from 'viem';
|
||||
import { useAccount, useSendTransaction, useSwitchNetwork, useNetwork, useSignMessage, useSignTypedData } from 'wagmi';
|
||||
|
||||
import config from 'configs/app';
|
||||
|
||||
type SendTransactionArgs = {
|
||||
chainId?: number;
|
||||
mode?: 'prepared';
|
||||
to: string;
|
||||
};
|
||||
|
||||
export type SignTypedDataArgs<
|
||||
TTypedData extends
|
||||
| TypedData
|
||||
| {
|
||||
[key: string]: unknown;
|
||||
} = TypedData,
|
||||
TPrimaryType extends string = string,
|
||||
> = SignTypedDataParameters<TTypedData, TPrimaryType, Account>;
|
||||
|
||||
export default function useMarketplaceWallet() {
|
||||
const { address } = useAccount();
|
||||
const { chain } = useNetwork();
|
||||
const { sendTransactionAsync } = useSendTransaction();
|
||||
const { signMessageAsync } = useSignMessage();
|
||||
const { signTypedDataAsync } = useSignTypedData();
|
||||
const { switchNetworkAsync } = useSwitchNetwork({ chainId: Number(config.chain.id) });
|
||||
|
||||
const switchNetwork = useCallback(async() => {
|
||||
if (Number(config.chain.id) !== chain?.id) {
|
||||
await switchNetworkAsync?.();
|
||||
}
|
||||
}, [ chain, switchNetworkAsync ]);
|
||||
|
||||
const sendTransaction = useCallback(async(transaction: SendTransactionArgs) => {
|
||||
await switchNetwork();
|
||||
const tx = await sendTransactionAsync(transaction);
|
||||
return tx.hash;
|
||||
}, [ sendTransactionAsync, switchNetwork ]);
|
||||
|
||||
const signMessage = useCallback(async(message: string) => {
|
||||
await switchNetwork();
|
||||
const signature = await signMessageAsync({ message });
|
||||
return signature;
|
||||
}, [ signMessageAsync, switchNetwork ]);
|
||||
|
||||
const signTypedData = useCallback(async(typedData: SignTypedDataArgs) => {
|
||||
await switchNetwork();
|
||||
if (typedData.domain) {
|
||||
typedData.domain.chainId = Number(typedData.domain.chainId);
|
||||
}
|
||||
const signature = await signTypedDataAsync(typedData);
|
||||
return signature;
|
||||
}, [ signTypedDataAsync, switchNetwork ]);
|
||||
|
||||
return {
|
||||
address,
|
||||
sendTransaction,
|
||||
signMessage,
|
||||
signTypedData,
|
||||
};
|
||||
}
|
||||
@@ -189,7 +189,7 @@ const AddressPageContent = () => {
|
||||
<AddressQrCode address={{ hash }} isLoading={ isLoading }/>
|
||||
<AccountActionsMenu isLoading={ isLoading }/>
|
||||
<HStack ml="auto" gap={ 2 }/>
|
||||
{ addressQuery.data?.is_contract && config.UI.views.address.solidityscanEnabled && <SolidityscanReport hash={ hash }/> }
|
||||
{ addressQuery.data?.is_contract && addressQuery.data?.is_verified && config.UI.views.address.solidityscanEnabled && <SolidityscanReport hash={ hash }/> }
|
||||
<NetworkExplorers type="address" pathParam={ hash }/>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
const TAB_LIST_PROPS = {
|
||||
marginBottom: 0,
|
||||
@@ -82,7 +82,7 @@ const BlockPageContent = () => {
|
||||
|
||||
const tabs: Array<RoutedTab> = React.useMemo(() => ([
|
||||
{ id: 'index', title: 'Details', component: <BlockDetails query={ blockQuery }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsContent query={ blockTxsQuery } showBlockInfo={ false } showSocketInfo={ false }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsWithFrontendSorting query={ blockTxsQuery } showBlockInfo={ false } showSocketInfo={ false }/> },
|
||||
config.features.beaconChain.isEnabled && Boolean(blockQuery.data?.withdrawals_count) ?
|
||||
{ id: 'withdrawals', title: 'Withdrawals', component: <BlockWithdrawals blockWithdrawalsQuery={ blockWithdrawalsQuery }/> } :
|
||||
null,
|
||||
|
||||
@@ -10,6 +10,7 @@ import Transactions from 'ui/home/Transactions';
|
||||
import AdBanner from 'ui/shared/ad/AdBanner';
|
||||
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
|
||||
import SearchBar from 'ui/snippets/searchBar/SearchBar';
|
||||
import WalletMenuDesktop from 'ui/snippets/walletMenu/WalletMenuDesktop';
|
||||
|
||||
const Home = () => {
|
||||
return (
|
||||
@@ -22,7 +23,7 @@ const Home = () => {
|
||||
minW={{ base: 'unset', lg: '900px' }}
|
||||
data-label="hero plate"
|
||||
>
|
||||
<Flex mb={{ base: 6, lg: 8 }} justifyContent="space-between">
|
||||
<Flex mb={{ base: 6, lg: 8 }} justifyContent="space-between" alignItems="center">
|
||||
<Heading
|
||||
as="h1"
|
||||
size={{ base: 'md', lg: 'xl' }}
|
||||
@@ -32,8 +33,9 @@ const Home = () => {
|
||||
>
|
||||
{ config.chain.name } explorer
|
||||
</Heading>
|
||||
<Box display={{ base: 'none', lg: 'block' }}>
|
||||
{ config.features.account.isEnabled && <ProfileMenuDesktop/> }
|
||||
<Box display={{ base: 'none', lg: 'flex' }}>
|
||||
{ config.features.account.isEnabled && <ProfileMenuDesktop isHomePage/> }
|
||||
{ config.features.blockchainInteraction.isEnabled && <WalletMenuDesktop isHomePage/> }
|
||||
</Box>
|
||||
</Flex>
|
||||
<SearchBar isHomepage/>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { generateListStub } from 'stubs/utils';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
const KettleTxs = () => {
|
||||
const router = useRouter();
|
||||
@@ -31,7 +31,7 @@ const KettleTxs = () => {
|
||||
<>
|
||||
<PageTitle title="Computor transactions" withTextAd/>
|
||||
<AddressEntity address={{ hash }} mb={ 6 }/>
|
||||
<TxsContent
|
||||
<TxsWithFrontendSorting
|
||||
query={ query }
|
||||
showSocketInfo={ false }
|
||||
/>
|
||||
|
||||
@@ -5,6 +5,7 @@ import config from 'configs/app';
|
||||
import PlusIcon from 'icons/plus.svg';
|
||||
import MarketplaceAppModal from 'ui/marketplace/MarketplaceAppModal';
|
||||
import MarketplaceCategoriesMenu from 'ui/marketplace/MarketplaceCategoriesMenu';
|
||||
import MarketplaceDisclaimerModal from 'ui/marketplace/MarketplaceDisclaimerModal';
|
||||
import MarketplaceList from 'ui/marketplace/MarketplaceList';
|
||||
import FilterInput from 'ui/shared/filters/FilterInput';
|
||||
|
||||
@@ -27,6 +28,9 @@ const Marketplace = () => {
|
||||
clearSelectedAppId,
|
||||
favoriteApps,
|
||||
onFavoriteClick,
|
||||
isAppInfoModalOpen,
|
||||
isDisclaimerModalOpen,
|
||||
showDisclaimer,
|
||||
} = useMarketplace();
|
||||
|
||||
if (isError) {
|
||||
@@ -68,9 +72,10 @@ const Marketplace = () => {
|
||||
favoriteApps={ favoriteApps }
|
||||
onFavoriteClick={ onFavoriteClick }
|
||||
isLoading={ isPlaceholderData }
|
||||
showDisclaimer={ showDisclaimer }
|
||||
/>
|
||||
|
||||
{ selectedApp && (
|
||||
{ (selectedApp && isAppInfoModalOpen) && (
|
||||
<MarketplaceAppModal
|
||||
onClose={ clearSelectedAppId }
|
||||
isFavorite={ favoriteApps.includes(selectedApp.id) }
|
||||
@@ -79,6 +84,14 @@ const Marketplace = () => {
|
||||
/>
|
||||
) }
|
||||
|
||||
{ (selectedApp && isDisclaimerModalOpen) && (
|
||||
<MarketplaceDisclaimerModal
|
||||
isOpen={ isDisclaimerModalOpen }
|
||||
onClose={ clearSelectedAppId }
|
||||
appId={ selectedApp.id }
|
||||
/>
|
||||
) }
|
||||
|
||||
<Skeleton
|
||||
isLoaded={ !isPlaceholderData }
|
||||
marginTop={{ base: 8, sm: 16 }}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Box, Center, useColorMode } from '@chakra-ui/react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { DappscoutIframeProvider, useDappscoutIframe } from 'dappscout-iframe';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import type { MarketplaceAppOverview } from 'types/client/marketplace';
|
||||
|
||||
@@ -9,12 +10,12 @@ import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import type { ResourceError } from 'lib/api/resources';
|
||||
import { useAppContext } from 'lib/contexts/app';
|
||||
import useApiFetch from 'lib/hooks/useFetch';
|
||||
import * as metadata from 'lib/metadata';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
import ContentLoader from 'ui/shared/ContentLoader';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
|
||||
import useMarketplaceWallet from '../marketplace/useMarketplaceWallet';
|
||||
|
||||
const feature = config.features.marketplace;
|
||||
const configUrl = feature.isEnabled ? feature.configUrl : '';
|
||||
@@ -26,35 +27,23 @@ const IFRAME_SANDBOX_ATTRIBUTE = 'allow-forms allow-orientation-lock ' +
|
||||
|
||||
const IFRAME_ALLOW_ATTRIBUTE = 'clipboard-read; clipboard-write;';
|
||||
|
||||
const MarketplaceApp = () => {
|
||||
const ref = useRef<HTMLIFrameElement>(null);
|
||||
type Props = {
|
||||
address: string | undefined;
|
||||
data: MarketplaceAppOverview | undefined;
|
||||
isPending: boolean;
|
||||
};
|
||||
|
||||
const apiFetch = useApiFetch();
|
||||
const appProps = useAppContext();
|
||||
const router = useRouter();
|
||||
const id = getQueryParamString(router.query.id);
|
||||
|
||||
const { isPending, isError, error, data } = useQuery<unknown, ResourceError<unknown>, MarketplaceAppOverview>({
|
||||
queryKey: [ 'marketplace-apps', id ],
|
||||
queryFn: async() => {
|
||||
const result = await apiFetch<Array<MarketplaceAppOverview>, unknown>(configUrl, undefined, { resource: 'marketplace-apps' });
|
||||
if (!Array.isArray(result)) {
|
||||
throw result;
|
||||
}
|
||||
|
||||
const item = result.find((app: MarketplaceAppOverview) => app.id === id);
|
||||
if (!item) {
|
||||
throw { status: 404 };
|
||||
}
|
||||
|
||||
return item;
|
||||
},
|
||||
enabled: feature.isEnabled,
|
||||
});
|
||||
const MarketplaceAppContent = ({ address, data, isPending }: Props) => {
|
||||
const { iframeRef, isReady } = useDappscoutIframe();
|
||||
|
||||
const [ iframeKey, setIframeKey ] = useState(0);
|
||||
const [ isFrameLoading, setIsFrameLoading ] = useState(isPending);
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
useEffect(() => {
|
||||
setIframeKey((key) => key + 1);
|
||||
}, [ address ]);
|
||||
|
||||
const handleIframeLoad = useCallback(() => {
|
||||
setIsFrameLoading(false);
|
||||
}, []);
|
||||
@@ -72,9 +61,61 @@ const MarketplaceApp = () => {
|
||||
blockscoutNetworkRpc: config.chain.rpcUrl,
|
||||
};
|
||||
|
||||
ref?.current?.contentWindow?.postMessage(message, data.url);
|
||||
iframeRef?.current?.contentWindow?.postMessage(message, data.url);
|
||||
}
|
||||
}, [ isFrameLoading, data, colorMode, ref ]);
|
||||
}, [ isFrameLoading, data, colorMode, iframeRef ]);
|
||||
|
||||
return (
|
||||
<Center
|
||||
h="100vh"
|
||||
mx={{ base: -4, lg: -6 }}
|
||||
>
|
||||
{ (isFrameLoading) && (
|
||||
<ContentLoader/>
|
||||
) }
|
||||
|
||||
{ (data && isReady) && (
|
||||
<Box
|
||||
key={ iframeKey }
|
||||
allow={ IFRAME_ALLOW_ATTRIBUTE }
|
||||
ref={ iframeRef }
|
||||
sandbox={ IFRAME_SANDBOX_ATTRIBUTE }
|
||||
as="iframe"
|
||||
h="100%"
|
||||
w="100%"
|
||||
display={ isFrameLoading ? 'none' : 'block' }
|
||||
src={ data.url }
|
||||
title={ data.title }
|
||||
onLoad={ handleIframeLoad }
|
||||
/>
|
||||
) }
|
||||
</Center>
|
||||
);
|
||||
};
|
||||
|
||||
const MarketplaceApp = () => {
|
||||
const { address, sendTransaction, signMessage, signTypedData } = useMarketplaceWallet();
|
||||
|
||||
const apiFetch = useApiFetch();
|
||||
const router = useRouter();
|
||||
const id = getQueryParamString(router.query.id);
|
||||
|
||||
const { isPending, isError, error, data } = useQuery<unknown, ResourceError<unknown>, MarketplaceAppOverview>({
|
||||
queryKey: [ 'marketplace-apps', id ],
|
||||
queryFn: async() => {
|
||||
const result = await apiFetch<Array<MarketplaceAppOverview>, unknown>(configUrl, undefined, { resource: 'marketplace-apps' });
|
||||
if (!Array.isArray(result)) {
|
||||
throw result;
|
||||
}
|
||||
const item = result.find((app: MarketplaceAppOverview) => app.id === id);
|
||||
if (!item) {
|
||||
throw { status: 404 };
|
||||
}
|
||||
|
||||
return item;
|
||||
},
|
||||
enabled: feature.isEnabled,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
@@ -89,46 +130,17 @@ const MarketplaceApp = () => {
|
||||
throw new Error('Unable to load app', { cause: error });
|
||||
}
|
||||
|
||||
const backLink = React.useMemo(() => {
|
||||
const hasGoBackLink = appProps.referrer.includes('/apps');
|
||||
|
||||
if (!hasGoBackLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
label: 'Back to marketplace',
|
||||
url: appProps.referrer,
|
||||
};
|
||||
}, [ appProps.referrer ]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{ !isPending && <PageTitle title={ data.title } backLink={ backLink }/> }
|
||||
<Center
|
||||
h="100vh"
|
||||
mx={{ base: -4, lg: -12 }}
|
||||
>
|
||||
{ (isFrameLoading) && (
|
||||
<ContentLoader/>
|
||||
) }
|
||||
|
||||
{ data && (
|
||||
<Box
|
||||
allow={ IFRAME_ALLOW_ATTRIBUTE }
|
||||
ref={ ref }
|
||||
sandbox={ IFRAME_SANDBOX_ATTRIBUTE }
|
||||
as="iframe"
|
||||
h="100%"
|
||||
w="100%"
|
||||
display={ isFrameLoading ? 'none' : 'block' }
|
||||
src={ data.url }
|
||||
title={ data.title }
|
||||
onLoad={ handleIframeLoad }
|
||||
/>
|
||||
) }
|
||||
</Center>
|
||||
</>
|
||||
<DappscoutIframeProvider
|
||||
address={ address }
|
||||
appUrl={ data?.url }
|
||||
rpcUrl={ config.chain.rpcUrl }
|
||||
sendTransaction={ sendTransaction }
|
||||
signMessage={ signMessage }
|
||||
signTypedData={ signTypedData }
|
||||
>
|
||||
<MarketplaceAppContent address={ address } data={ data } isPending={ isPending }/>
|
||||
</DappscoutIframeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { TokenType } from 'types/api/token';
|
||||
import type { TokensSortingValue } from 'types/api/tokens';
|
||||
import type { TokensSortingValue, TokensSortingField, TokensSorting } from 'types/api/tokens';
|
||||
import type { RoutedTab } from 'ui/shared/Tabs/types';
|
||||
|
||||
import config from 'configs/app';
|
||||
@@ -16,11 +16,13 @@ import PopoverFilter from 'ui/shared/filters/PopoverFilter';
|
||||
import TokenTypeFilter from 'ui/shared/filters/TokenTypeFilter';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
import getSortValueFromQuery from 'ui/shared/sort/getSortValueFromQuery';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TokensList from 'ui/tokens/Tokens';
|
||||
import TokensActionBar from 'ui/tokens/TokensActionBar';
|
||||
import TokensBridgedChainsFilter from 'ui/tokens/TokensBridgedChainsFilter';
|
||||
import { getSortParamsFromValue, getSortValueFromQuery, getTokenFilterValue, getBridgedChainsFilterValue } from 'ui/tokens/utils';
|
||||
import { SORT_OPTIONS, getTokenFilterValue, getBridgedChainsFilterValue } from 'ui/tokens/utils';
|
||||
|
||||
const TAB_LIST_PROPS = {
|
||||
marginBottom: 0,
|
||||
@@ -44,7 +46,7 @@ const Tokens = () => {
|
||||
const q = getQueryParamString(router.query.q);
|
||||
|
||||
const [ searchTerm, setSearchTerm ] = React.useState<string>(q ?? '');
|
||||
const [ sort, setSort ] = React.useState<TokensSortingValue | undefined>(getSortValueFromQuery(router.query));
|
||||
const [ sort, setSort ] = React.useState<TokensSortingValue | undefined>(getSortValueFromQuery<TokensSortingValue>(router.query, SORT_OPTIONS));
|
||||
const [ tokenTypes, setTokenTypes ] = React.useState<Array<TokenType> | undefined>(getTokenFilterValue(router.query.type));
|
||||
const [ bridgeChains, setBridgeChains ] = React.useState<Array<string> | undefined>(getBridgedChainsFilterValue(router.query.chain_ids));
|
||||
|
||||
@@ -53,7 +55,7 @@ const Tokens = () => {
|
||||
const tokensQuery = useQueryWithPages({
|
||||
resourceName: tab === 'bridged' ? 'tokens_bridged' : 'tokens',
|
||||
filters: tab === 'bridged' ? { q: debouncedSearchTerm, chain_ids: bridgeChains } : { q: debouncedSearchTerm, type: tokenTypes },
|
||||
sorting: getSortParamsFromValue(sort),
|
||||
sorting: getSortParamsFromValue<TokensSortingValue, TokensSortingField, TokensSorting['order']>(sort),
|
||||
options: {
|
||||
placeholderData: generateListStub<'tokens'>(
|
||||
TOKEN_INFO_ERC_20,
|
||||
|
||||
@@ -13,8 +13,8 @@ import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWatchlist from 'ui/txs/TxsWatchlist';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
const TAB_LIST_PROPS = {
|
||||
marginBottom: 0,
|
||||
@@ -60,12 +60,13 @@ const Transactions = () => {
|
||||
{
|
||||
id: 'validated',
|
||||
title: verifiedTitle,
|
||||
component: <TxsContent query={ txsQuery } showSocketInfo={ txsQuery.pagination.page === 1 } socketInfoNum={ num } socketInfoAlert={ socketAlert }/> },
|
||||
component:
|
||||
<TxsWithFrontendSorting query={ txsQuery } showSocketInfo={ txsQuery.pagination.page === 1 } socketInfoNum={ num } socketInfoAlert={ socketAlert }/> },
|
||||
{
|
||||
id: 'pending',
|
||||
title: 'Pending',
|
||||
component: (
|
||||
<TxsContent
|
||||
<TxsWithFrontendSorting
|
||||
query={ txsQuery }
|
||||
showBlockInfo={ false }
|
||||
showSocketInfo={ txsQuery.pagination.page === 1 }
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { VerifiedContractsFilters } from 'types/api/contracts';
|
||||
import type { VerifiedContractsSorting, VerifiedContractsSortingField, VerifiedContractsSortingValue } from 'types/api/verifiedContracts';
|
||||
|
||||
import useDebounce from 'lib/hooks/useDebounce';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
@@ -16,9 +17,10 @@ import FilterInput from 'ui/shared/filters/FilterInput';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
import getSortValueFromQuery from 'ui/shared/sort/getSortValueFromQuery';
|
||||
import Sort from 'ui/shared/sort/Sort';
|
||||
import type { SortField, Sort as TSort } from 'ui/verifiedContracts/utils';
|
||||
import { SORT_OPTIONS, sortFn, getNextSortValue } from 'ui/verifiedContracts/utils';
|
||||
import { SORT_OPTIONS } from 'ui/verifiedContracts/utils';
|
||||
import VerifiedContractsCounters from 'ui/verifiedContracts/VerifiedContractsCounters';
|
||||
import VerifiedContractsFilter from 'ui/verifiedContracts/VerifiedContractsFilter';
|
||||
import VerifiedContractsList from 'ui/verifiedContracts/VerifiedContractsList';
|
||||
@@ -28,15 +30,17 @@ const VerifiedContracts = () => {
|
||||
const router = useRouter();
|
||||
const [ searchTerm, setSearchTerm ] = React.useState(getQueryParamString(router.query.q) || undefined);
|
||||
const [ type, setType ] = React.useState(getQueryParamString(router.query.filter) as VerifiedContractsFilters['filter'] || undefined);
|
||||
const [ sort, setSort ] = React.useState<TSort>();
|
||||
const [ sort, setSort ] =
|
||||
React.useState<VerifiedContractsSortingValue | undefined>(getSortValueFromQuery<VerifiedContractsSortingValue>(router.query, SORT_OPTIONS));
|
||||
|
||||
const debouncedSearchTerm = useDebounce(searchTerm || '', 300);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const { isError, isPlaceholderData, data, pagination, onFilterChange } = useQueryWithPages({
|
||||
const { isError, isPlaceholderData, data, pagination, onFilterChange, onSortingChange } = useQueryWithPages({
|
||||
resourceName: 'verified_contracts',
|
||||
filters: { q: debouncedSearchTerm, filter: type },
|
||||
sorting: getSortParamsFromValue<VerifiedContractsSortingValue, VerifiedContractsSortingField, VerifiedContractsSorting['order']>(sort),
|
||||
options: {
|
||||
placeholderData: generateListStub<'verified_contracts'>(
|
||||
VERIFIED_CONTRACT_INFO,
|
||||
@@ -67,11 +71,10 @@ const VerifiedContracts = () => {
|
||||
setType(filter);
|
||||
}, [ debouncedSearchTerm, onFilterChange ]);
|
||||
|
||||
const handleSortToggle = React.useCallback((field: SortField) => {
|
||||
return () => {
|
||||
setSort(getNextSortValue(field));
|
||||
};
|
||||
}, []);
|
||||
const handleSortChange = React.useCallback((value?: VerifiedContractsSortingValue) => {
|
||||
setSort(value);
|
||||
onSortingChange(getSortParamsFromValue(value));
|
||||
}, [ onSortingChange ]);
|
||||
|
||||
const typeFilter = <VerifiedContractsFilter onChange={ handleTypeChange } defaultValue={ type } isActive={ Boolean(type) }/>;
|
||||
|
||||
@@ -89,7 +92,7 @@ const VerifiedContracts = () => {
|
||||
<Sort
|
||||
options={ SORT_OPTIONS }
|
||||
sort={ sort }
|
||||
setSort={ setSort }
|
||||
setSort={ handleSortChange }
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -112,15 +115,13 @@ const VerifiedContracts = () => {
|
||||
</>
|
||||
);
|
||||
|
||||
const sortedData = data?.items.slice().sort(sortFn(sort));
|
||||
|
||||
const content = sortedData ? (
|
||||
const content = data?.items ? (
|
||||
<>
|
||||
<Show below="lg" ssr={ false }>
|
||||
<VerifiedContractsList data={ sortedData } isLoading={ isPlaceholderData }/>
|
||||
<VerifiedContractsList data={ data.items } isLoading={ isPlaceholderData }/>
|
||||
</Show>
|
||||
<Hide below="lg" ssr={ false }>
|
||||
<VerifiedContractsTable data={ sortedData } sort={ sort } onSortToggle={ handleSortToggle } isLoading={ isPlaceholderData }/>
|
||||
<VerifiedContractsTable data={ data.items } sort={ sort } setSorting={ handleSortChange } isLoading={ isPlaceholderData }/>
|
||||
</Hide>
|
||||
</>
|
||||
) : null;
|
||||
|
||||
@@ -14,7 +14,7 @@ import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
import ZkEvmL2TxnBatchDetails from 'ui/zkEvmL2TxnBatches/ZkEvmL2TxnBatchDetails';
|
||||
|
||||
const ZkEvmL2TxnBatch = () => {
|
||||
@@ -51,7 +51,7 @@ const ZkEvmL2TxnBatch = () => {
|
||||
|
||||
const tabs: Array<RoutedTab> = React.useMemo(() => ([
|
||||
{ id: 'index', title: 'Details', component: <ZkEvmL2TxnBatchDetails query={ batchQuery }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsContent query={ batchTxsQuery } showSocketInfo={ false }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsWithFrontendSorting query={ batchTxsQuery } showSocketInfo={ false }/> },
|
||||
].filter(Boolean)), [ batchQuery, batchTxsQuery ]);
|
||||
|
||||
const backLink = React.useMemo(() => {
|
||||
|
||||
|
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 270 KiB |
@@ -1,10 +1,10 @@
|
||||
import { SkeletonCircle, Image } from '@chakra-ui/react';
|
||||
import { SkeletonCircle, Image, Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import profileIcon from 'icons/profile.svg';
|
||||
import { useAppContext } from 'lib/contexts/app';
|
||||
import * as cookies from 'lib/cookies';
|
||||
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
|
||||
import IdenticonGithub from 'ui/shared/IdenticonGithub';
|
||||
|
||||
interface Props {
|
||||
size: number;
|
||||
@@ -34,7 +34,7 @@ const UserAvatar = ({ size }: Props) => {
|
||||
boxSize={ `${ size }px` }
|
||||
borderRadius="full"
|
||||
overflow="hidden"
|
||||
fallback={ isImageLoadError || !data?.avatar ? <IdenticonGithub size={ size } seed={ data?.email || 'randomness' } flexShrink={ 0 }/> : undefined }
|
||||
fallback={ isImageLoadError || !data?.avatar ? <Icon as={ profileIcon } boxSize={ 5 }/> : undefined }
|
||||
onError={ handleImageLoadError }
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -75,7 +75,7 @@ const Web3ModalProvider = ({ children, fallback }: Props) => {
|
||||
const web3ModalTheme = useColorModeValue('light', 'dark');
|
||||
|
||||
if (!wagmiConfig || !ethereumClient || !feature.isEnabled) {
|
||||
return typeof fallback === 'function' ? fallback() : (fallback || null);
|
||||
return typeof fallback === 'function' ? fallback() : (fallback || <>{ children }</>); // eslint-disable-line react/jsx-no-useless-fragment
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { Props } from './types';
|
||||
|
||||
import AppErrorBoundary from 'ui/shared/AppError/AppErrorBoundary';
|
||||
import HeaderAlert from 'ui/snippets/header/HeaderAlert';
|
||||
import HeaderDesktop from 'ui/snippets/header/HeaderDesktop';
|
||||
import HeaderMobile from 'ui/snippets/header/HeaderMobile';
|
||||
|
||||
import * as Layout from './components';
|
||||
|
||||
const LayoutDefault = ({ children }: Props) => {
|
||||
return (
|
||||
<Layout.Container>
|
||||
<HeaderMobile/>
|
||||
<Layout.MainArea>
|
||||
<Layout.MainColumn
|
||||
paddingTop={{ base: '138px', lg: 6 }}
|
||||
paddingX={{ base: 4, lg: 6 }}
|
||||
>
|
||||
<HeaderAlert/>
|
||||
<HeaderDesktop isMarketplaceAppPage/>
|
||||
<AppErrorBoundary>
|
||||
<Layout.Content pt={{ base: 0, lg: 6 }}>
|
||||
{ children }
|
||||
</Layout.Content>
|
||||
</AppErrorBoundary>
|
||||
</Layout.MainColumn>
|
||||
</Layout.MainArea>
|
||||
<Layout.Footer/>
|
||||
</Layout.Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default LayoutDefault;
|
||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 33 KiB |
@@ -1,16 +1,17 @@
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { Box, chakra } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const Content = ({ children }: Props) => {
|
||||
const Content = ({ children, className }: Props) => {
|
||||
return (
|
||||
<Box pt={{ base: 0, lg: '52px' }} as="main">
|
||||
<Box pt={{ base: 0, lg: '52px' }} as="main" className={ className }>
|
||||
{ children }
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Content);
|
||||
export default React.memo(chakra(Content));
|
||||
|
||||
@@ -41,7 +41,7 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasPage
|
||||
aria-label="Prev page"
|
||||
w="36px"
|
||||
icon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 }/> }
|
||||
isDisabled={ !canGoBackwards || page === 1 || isLoading }
|
||||
isDisabled={ !canGoBackwards || isLoading }
|
||||
/>
|
||||
</Skeleton>
|
||||
<Skeleton isLoaded={ !showSkeleton } display="inline-block" borderRadius="base">
|
||||
|
||||
@@ -68,7 +68,7 @@ it('returns correct data if there is only one page', async() => {
|
||||
expect(result.current.data).toEqual(responses.page_empty);
|
||||
expect(result.current.pagination).toMatchObject({
|
||||
page: 1,
|
||||
canGoBackwards: true,
|
||||
canGoBackwards: false,
|
||||
hasNextPage: false,
|
||||
isLoading: false,
|
||||
isVisible: false,
|
||||
@@ -91,7 +91,7 @@ describe('if there are multiple pages', () => {
|
||||
expect(result.current.data).toEqual(responses.page_1);
|
||||
expect(result.current.pagination).toMatchObject({
|
||||
page: 1,
|
||||
canGoBackwards: true,
|
||||
canGoBackwards: false,
|
||||
hasNextPage: true,
|
||||
isLoading: false,
|
||||
isVisible: true,
|
||||
@@ -258,7 +258,7 @@ describe('if there are multiple pages', () => {
|
||||
expect(result.current.data).toEqual(responses.page_1);
|
||||
expect(result.current.pagination).toMatchObject({
|
||||
page: 1,
|
||||
canGoBackwards: true,
|
||||
canGoBackwards: false,
|
||||
hasNextPage: true,
|
||||
isLoading: false,
|
||||
isVisible: true,
|
||||
@@ -310,7 +310,7 @@ describe('if there are multiple pages', () => {
|
||||
expect(result.current.data).toEqual(responses.page_1);
|
||||
expect(result.current.pagination).toMatchObject({
|
||||
page: 1,
|
||||
canGoBackwards: true,
|
||||
canGoBackwards: false,
|
||||
hasNextPage: true,
|
||||
isLoading: false,
|
||||
isVisible: true,
|
||||
@@ -404,7 +404,7 @@ describe('if there is page query param in URL', () => {
|
||||
expect(result.current.data).toEqual(responses.page_3);
|
||||
expect(result.current.pagination).toMatchObject({
|
||||
page: 3,
|
||||
canGoBackwards: false,
|
||||
canGoBackwards: true,
|
||||
hasNextPage: false,
|
||||
isLoading: false,
|
||||
isVisible: true,
|
||||
@@ -458,7 +458,7 @@ describe('queries with filters', () => {
|
||||
expect(result.current.data).toEqual(responses.page_filtered);
|
||||
expect(result.current.pagination).toMatchObject({
|
||||
page: 1,
|
||||
canGoBackwards: true,
|
||||
canGoBackwards: false,
|
||||
hasNextPage: true,
|
||||
isLoading: false,
|
||||
isVisible: true,
|
||||
@@ -547,7 +547,7 @@ describe('queries with sorting', () => {
|
||||
expect(result.current.data).toEqual(responses.page_sorted);
|
||||
expect(result.current.pagination).toMatchObject({
|
||||
page: 1,
|
||||
canGoBackwards: true,
|
||||
canGoBackwards: false,
|
||||
hasNextPage: false,
|
||||
isLoading: false,
|
||||
isVisible: false,
|
||||
|
||||
@@ -61,7 +61,6 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
|
||||
const [ hasPages, setHasPages ] = React.useState(page > 1);
|
||||
|
||||
const isMounted = React.useRef(false);
|
||||
const canGoBackwards = React.useRef(!router.query.page);
|
||||
const queryParams = { ...pageParams[page], ...filters, ...sorting };
|
||||
|
||||
const scrollToTop = useCallback(() => {
|
||||
@@ -107,7 +106,6 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
|
||||
let nextPageQuery: typeof router.query = { ...router.query };
|
||||
if (page === 2) {
|
||||
nextPageQuery = omit(router.query, [ 'next_page_params', 'page' ]);
|
||||
canGoBackwards.current = true;
|
||||
} else {
|
||||
nextPageQuery.next_page_params = encodeURIComponent(JSON.stringify(pageParams[page - 1]));
|
||||
nextPageQuery.page = String(page - 1);
|
||||
@@ -130,7 +128,6 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
|
||||
queryClient.removeQueries({ queryKey: [ resourceName ] });
|
||||
setPage(1);
|
||||
setPageParams({});
|
||||
canGoBackwards.current = true;
|
||||
window.setTimeout(() => {
|
||||
// FIXME after router is updated we still have inactive queries for previously visited page (e.g third), where we came from
|
||||
// so have to remove it but with some delay :)
|
||||
@@ -193,7 +190,7 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
|
||||
resetPage,
|
||||
hasPages,
|
||||
hasNextPage,
|
||||
canGoBackwards: canGoBackwards.current,
|
||||
canGoBackwards: Boolean(pageParams[page - 1]),
|
||||
isLoading: queryResult.isPlaceholderData,
|
||||
isVisible: hasPages || hasNextPage,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export default function getSortParamsFromValue<SortValue extends string, SortField extends string, SortOrder extends string>(val?: SortValue) {
|
||||
if (!val) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const sortingChunks = val.split('-') as [ SortField, SortOrder ];
|
||||
return { sort: sortingChunks[0], order: sortingChunks[1] };
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { Query } from 'nextjs-routes';
|
||||
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
|
||||
export default function getSortValueFromQuery<SortValue extends string>(query: Query, sortOptions: Array<Option<SortValue>>) {
|
||||
if (!query.sort || !query.order) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const str = query.sort + '-' + query.order;
|
||||
if (sortOptions.map(option => option.id).includes(str as SortValue)) {
|
||||
return str as SortValue;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,11 @@ import NetworkMenuButton from 'ui/snippets/networkMenu/NetworkMenuButton';
|
||||
import NetworkMenuContentMobile from 'ui/snippets/networkMenu/NetworkMenuContentMobile';
|
||||
import useNetworkMenu from 'ui/snippets/networkMenu/useNetworkMenu';
|
||||
|
||||
const Burger = () => {
|
||||
interface Props {
|
||||
isMarketplaceAppPage?: boolean;
|
||||
}
|
||||
|
||||
const Burger = ({ isMarketplaceAppPage }: Props) => {
|
||||
const iconColor = useColorModeValue('gray.600', 'white');
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const networkMenu = useNetworkMenu();
|
||||
@@ -26,7 +30,7 @@ const Burger = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box padding={ 2 } onClick={ onOpen }>
|
||||
<Box padding={ 2 } onClick={ onOpen } cursor="pointer">
|
||||
<Icon
|
||||
as={ burgerIcon }
|
||||
boxSize={ 6 }
|
||||
@@ -57,7 +61,7 @@ const Burger = () => {
|
||||
</Flex>
|
||||
{ networkMenu.isOpen ?
|
||||
<NetworkMenuContentMobile tabs={ networkMenu.availableTabs } items={ networkMenu.data }/> :
|
||||
<NavigationMobile onNavLinkClick={ onClose }/>
|
||||
<NavigationMobile onNavLinkClick={ onClose } isMarketplaceAppPage={ isMarketplaceAppPage }/>
|
||||
}
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
|
||||
@@ -2,14 +2,19 @@ import { HStack, Box } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import config from 'configs/app';
|
||||
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
|
||||
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
|
||||
import SearchBar from 'ui/snippets/searchBar/SearchBar';
|
||||
import WalletMenuDesktop from 'ui/snippets/walletMenu/WalletMenuDesktop';
|
||||
|
||||
import Burger from './Burger';
|
||||
|
||||
type Props = {
|
||||
renderSearchBar?: () => React.ReactNode;
|
||||
isMarketplaceAppPage?: boolean;
|
||||
}
|
||||
|
||||
const HeaderDesktop = ({ renderSearchBar }: Props) => {
|
||||
const HeaderDesktop = ({ renderSearchBar, isMarketplaceAppPage }: Props) => {
|
||||
|
||||
const searchBar = renderSearchBar ? renderSearchBar() : <SearchBar/>;
|
||||
|
||||
@@ -22,10 +27,19 @@ const HeaderDesktop = ({ renderSearchBar }: Props) => {
|
||||
justifyContent="center"
|
||||
gap={ 12 }
|
||||
>
|
||||
{ isMarketplaceAppPage && (
|
||||
<Box display="flex" alignItems="center" gap={ 3 }>
|
||||
<Burger isMarketplaceAppPage/>
|
||||
<NetworkLogo isCollapsed/>
|
||||
</Box>
|
||||
) }
|
||||
<Box width="100%">
|
||||
{ searchBar }
|
||||
</Box>
|
||||
{ config.features.account.isEnabled && <ProfileMenuDesktop/> }
|
||||
<Box display="flex">
|
||||
{ config.features.account.isEnabled && <ProfileMenuDesktop/> }
|
||||
{ config.features.blockchainInteraction.isEnabled && <WalletMenuDesktop/> }
|
||||
</Box>
|
||||
</HStack>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useScrollDirection } from 'lib/contexts/scrollDirection';
|
||||
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
|
||||
import ProfileMenuMobile from 'ui/snippets/profileMenu/ProfileMenuMobile';
|
||||
import SearchBar from 'ui/snippets/searchBar/SearchBar';
|
||||
import WalletMenuMobile from 'ui/snippets/walletMenu/WalletMenuMobile';
|
||||
|
||||
import Burger from './Burger';
|
||||
|
||||
@@ -47,7 +48,10 @@ const HeaderMobile = ({ isHomePage, renderSearchBar }: Props) => {
|
||||
>
|
||||
<Burger/>
|
||||
<NetworkLogo/>
|
||||
{ config.features.account.isEnabled ? <ProfileMenuMobile/> : <Box boxSize={ 10 }/> }
|
||||
<Flex columnGap={ 2 }>
|
||||
{ config.features.account.isEnabled ? <ProfileMenuMobile/> : <Box boxSize={ 10 }/> }
|
||||
{ config.features.blockchainInteraction.isEnabled && <WalletMenuMobile/> }
|
||||
</Flex>
|
||||
</Flex>
|
||||
{ !isHomePage && searchBar }
|
||||
</Box>
|
||||
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.9 KiB |
@@ -17,10 +17,11 @@ import useNavLinkStyleProps from './useNavLinkStyleProps';
|
||||
type Props = {
|
||||
item: NavGroupItem;
|
||||
onClick: () => void;
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
|
||||
const NavLinkGroup = ({ item, onClick }: Props) => {
|
||||
const styleProps = useNavLinkStyleProps({ isActive: item.isActive });
|
||||
const NavLinkGroup = ({ item, onClick, isExpanded }: Props) => {
|
||||
const styleProps = useNavLinkStyleProps({ isActive: item.isActive, isExpanded });
|
||||
|
||||
return (
|
||||
<Box as="li" listStyleType="none" w="100%" onClick={ onClick }>
|
||||
|
||||
@@ -11,9 +11,10 @@ import NavLinkGroupMobile from './NavLinkGroupMobile';
|
||||
|
||||
interface Props {
|
||||
onNavLinkClick?: () => void;
|
||||
isMarketplaceAppPage?: boolean;
|
||||
}
|
||||
|
||||
const NavigationMobile = ({ onNavLinkClick }: Props) => {
|
||||
const NavigationMobile = ({ onNavLinkClick, isMarketplaceAppPage }: Props) => {
|
||||
const { mainNavItems, accountNavItems } = useNavItems();
|
||||
|
||||
const [ openedGroupIndex, setOpenedGroupIndex ] = React.useState(-1);
|
||||
@@ -38,6 +39,8 @@ const NavigationMobile = ({ onNavLinkClick }: Props) => {
|
||||
|
||||
const openedItem = mainNavItems[openedGroupIndex];
|
||||
|
||||
const isCollapsed = isMarketplaceAppPage ? false : undefined;
|
||||
|
||||
return (
|
||||
<Flex position="relative" flexDirection="column" flexGrow={ 1 }>
|
||||
<Box
|
||||
@@ -61,9 +64,9 @@ const NavigationMobile = ({ onNavLinkClick }: Props) => {
|
||||
>
|
||||
{ mainNavItems.map((item, index) => {
|
||||
if (isGroupItem(item)) {
|
||||
return <NavLinkGroupMobile key={ item.text } item={ item } onClick={ onGroupItemOpen(index) }/>;
|
||||
return <NavLinkGroupMobile key={ item.text } item={ item } onClick={ onGroupItemOpen(index) } isExpanded={ isMarketplaceAppPage }/>;
|
||||
} else {
|
||||
return <NavLink key={ item.text } item={ item } onClick={ onNavLinkClick }/>;
|
||||
return <NavLink key={ item.text } item={ item } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>;
|
||||
}
|
||||
}) }
|
||||
</VStack>
|
||||
@@ -77,7 +80,7 @@ const NavigationMobile = ({ onNavLinkClick }: Props) => {
|
||||
borderColor="divider"
|
||||
>
|
||||
<VStack as="ul" spacing="1" alignItems="flex-start">
|
||||
{ accountNavItems.map((item) => <NavLink key={ item.text } item={ item } onClick={ onNavLinkClick }/>) }
|
||||
{ accountNavItems.map((item) => <NavLink key={ item.text } item={ item } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>) }
|
||||
</VStack>
|
||||
</Box>
|
||||
) }
|
||||
@@ -113,10 +116,10 @@ const NavigationMobile = ({ onNavLinkClick }: Props) => {
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
>
|
||||
{ item.map(subItem => <NavLink key={ subItem.text } item={ subItem } onClick={ onNavLinkClick }/>) }
|
||||
{ item.map(subItem => <NavLink key={ subItem.text } item={ subItem } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>) }
|
||||
</Box>
|
||||
) :
|
||||
<NavLink key={ item.text } item={ item } mb={ 1 } onClick={ onNavLinkClick }/>,
|
||||
<NavLink key={ item.text } item={ item } mb={ 1 } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>,
|
||||
) }
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -23,7 +23,7 @@ test('no auth', async({ mount, page }) => {
|
||||
{ hooksConfig },
|
||||
);
|
||||
|
||||
await component.locator('.identicon').click();
|
||||
await component.locator('a').click();
|
||||
expect(page.url()).toBe(`${ app.url }/auth/auth0?path=%2F`);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
import { Popover, PopoverContent, PopoverBody, PopoverTrigger, Button } from '@chakra-ui/react';
|
||||
import type { IconButtonProps } from '@chakra-ui/react';
|
||||
import { Popover, PopoverContent, PopoverBody, PopoverTrigger, IconButton, Tooltip, Box } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
|
||||
@@ -8,9 +8,16 @@ import * as mixpanel from 'lib/mixpanel/index';
|
||||
import UserAvatar from 'ui/shared/UserAvatar';
|
||||
import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent';
|
||||
|
||||
const ProfileMenuDesktop = () => {
|
||||
import useMenuButtonColors from '../useMenuButtonColors';
|
||||
|
||||
type Props = {
|
||||
isHomePage?: boolean;
|
||||
};
|
||||
|
||||
const ProfileMenuDesktop = ({ isHomePage }: Props) => {
|
||||
const { data, error, isPending } = useFetchProfileInfo();
|
||||
const loginUrl = useLoginUrl();
|
||||
const { themedBackground, themedBorderColor, themedColor } = useMenuButtonColors();
|
||||
const [ hasMenu, setHasMenu ] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -27,7 +34,7 @@ const ProfileMenuDesktop = () => {
|
||||
);
|
||||
}, []);
|
||||
|
||||
const buttonProps: Partial<ButtonProps> = (() => {
|
||||
const iconButtonProps: Partial<IconButtonProps> = (() => {
|
||||
if (hasMenu || !loginUrl) {
|
||||
return {};
|
||||
}
|
||||
@@ -39,19 +46,53 @@ const ProfileMenuDesktop = () => {
|
||||
};
|
||||
})();
|
||||
|
||||
const variant = React.useMemo(() => {
|
||||
if (hasMenu) {
|
||||
return 'subtle';
|
||||
}
|
||||
return isHomePage ? 'solid' : 'outline';
|
||||
}, [ hasMenu, isHomePage ]);
|
||||
|
||||
let iconButtonStyles: Partial<IconButtonProps> = {};
|
||||
if (hasMenu) {
|
||||
iconButtonStyles = {
|
||||
bg: isHomePage ? 'blue.50' : themedBackground,
|
||||
};
|
||||
} else if (isHomePage) {
|
||||
iconButtonStyles = {
|
||||
color: 'white',
|
||||
};
|
||||
} else {
|
||||
iconButtonStyles = {
|
||||
borderColor: themedBorderColor,
|
||||
color: themedColor,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover openDelay={ 300 } placement="bottom-end" gutter={ 10 } isLazy>
|
||||
<PopoverTrigger>
|
||||
<Button
|
||||
variant="unstyled"
|
||||
display="block"
|
||||
boxSize="50px"
|
||||
flexShrink={ 0 }
|
||||
{ ...buttonProps }
|
||||
>
|
||||
<UserAvatar size={ 50 }/>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<Tooltip
|
||||
label={ <span>Sign in to My Account to add tags,<br/>create watchlists, access API keys and more</span> }
|
||||
textAlign="center"
|
||||
padding={ 2 }
|
||||
isDisabled={ hasMenu }
|
||||
openDelay={ 300 }
|
||||
>
|
||||
<Box>
|
||||
<PopoverTrigger>
|
||||
<IconButton
|
||||
aria-label="profile menu"
|
||||
icon={ <UserAvatar size={ 20 }/> }
|
||||
variant={ variant }
|
||||
colorScheme="blue"
|
||||
boxSize="40px"
|
||||
flexShrink={ 0 }
|
||||
{ ...iconButtonProps }
|
||||
{ ...iconButtonStyles }
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
{ hasMenu && (
|
||||
<PopoverContent w="212px">
|
||||
<PopoverBody padding="24px 16px 16px 16px">
|
||||
|
||||
@@ -23,7 +23,7 @@ test('no auth', async({ mount, page }) => {
|
||||
{ hooksConfig },
|
||||
);
|
||||
|
||||
await component.locator('.identicon').click();
|
||||
await component.locator('a').click();
|
||||
expect(page.url()).toBe(`${ app.url }/auth/auth0?path=%2F`);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Box, Drawer, DrawerOverlay, DrawerContent, DrawerBody, useDisclosure, Button } from '@chakra-ui/react';
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
import { Drawer, DrawerOverlay, DrawerContent, DrawerBody, useDisclosure, IconButton } from '@chakra-ui/react';
|
||||
import type { IconButtonProps } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
|
||||
@@ -8,11 +8,13 @@ import * as mixpanel from 'lib/mixpanel/index';
|
||||
import UserAvatar from 'ui/shared/UserAvatar';
|
||||
import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent';
|
||||
|
||||
import useMenuButtonColors from '../useMenuButtonColors';
|
||||
|
||||
const ProfileMenuMobile = () => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
const { data, error, isPending } = useFetchProfileInfo();
|
||||
const loginUrl = useLoginUrl();
|
||||
const { themedBackground, themedBorderColor, themedColor } = useMenuButtonColors();
|
||||
const [ hasMenu, setHasMenu ] = React.useState(false);
|
||||
|
||||
const handleSignInClick = React.useCallback(() => {
|
||||
@@ -29,7 +31,7 @@ const ProfileMenuMobile = () => {
|
||||
}
|
||||
}, [ data, error?.status, isPending ]);
|
||||
|
||||
const buttonProps: Partial<ButtonProps> = (() => {
|
||||
const iconButtonProps: Partial<IconButtonProps> = (() => {
|
||||
if (hasMenu || !loginUrl) {
|
||||
return {};
|
||||
}
|
||||
@@ -43,17 +45,19 @@ const ProfileMenuMobile = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box padding={ 2 } onClick={ hasMenu ? onOpen : undefined }>
|
||||
<Button
|
||||
variant="unstyled"
|
||||
display="block"
|
||||
boxSize="24px"
|
||||
flexShrink={ 0 }
|
||||
{ ...buttonProps }
|
||||
>
|
||||
<UserAvatar size={ 24 }/>
|
||||
</Button>
|
||||
</Box>
|
||||
<IconButton
|
||||
aria-label="profile menu"
|
||||
icon={ <UserAvatar size={ 20 }/> }
|
||||
variant={ data?.avatar ? 'subtle' : 'outline' }
|
||||
colorScheme="gray"
|
||||
boxSize="40px"
|
||||
flexShrink={ 0 }
|
||||
bg={ data?.avatar ? themedBackground : undefined }
|
||||
color={ themedColor }
|
||||
borderColor={ !data?.avatar ? themedBorderColor : undefined }
|
||||
onClick={ hasMenu ? onOpen : undefined }
|
||||
{ ...iconButtonProps }
|
||||
/>
|
||||
{ hasMenu && (
|
||||
<Drawer
|
||||
isOpen={ isOpen }
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 27 KiB |
@@ -1,4 +1,3 @@
|
||||
import { LightMode } from '@chakra-ui/react';
|
||||
import { test as base, expect } from '@playwright/experimental-ct-react';
|
||||
import React from 'react';
|
||||
|
||||
@@ -93,9 +92,7 @@ test('search by name homepage +@dark-mode', async({ mount, page }) => {
|
||||
|
||||
await mount(
|
||||
<TestApp>
|
||||
<LightMode>
|
||||
<SearchBar isHomepage/>
|
||||
</LightMode>
|
||||
<SearchBar isHomepage/>
|
||||
</TestApp>,
|
||||
);
|
||||
await page.getByPlaceholder(/search/i).type('o');
|
||||
|
||||
@@ -132,12 +132,6 @@ const SearchBar = ({ isHomepage }: Props) => {
|
||||
<PopoverBody
|
||||
p={ 0 }
|
||||
color="chakra-body-text"
|
||||
sx={
|
||||
isHomepage ? {
|
||||
mark: { bgColor: 'green.100' },
|
||||
'*::-webkit-scrollbar-thumb': { backgroundColor: 'blackAlpha.300' },
|
||||
} : {}
|
||||
}
|
||||
>
|
||||
<Box
|
||||
maxH="50vh"
|
||||
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 42 KiB |
@@ -30,8 +30,8 @@ const TopBarStats = () => {
|
||||
<span>${ Number(data.coin_price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 }) }</span>
|
||||
</Skeleton>
|
||||
) }
|
||||
{ data?.coin_price && data.gas_prices && <TextSeparator color="divider"/> }
|
||||
{ data?.gas_prices && (
|
||||
{ data?.coin_price && config.UI.homepage.showGasTracker && <TextSeparator color="divider"/> }
|
||||
{ data?.gas_prices && config.UI.homepage.showGasTracker && (
|
||||
<Skeleton isLoaded={ !isPlaceholderData }>
|
||||
<span>Gas: { data.gas_prices.average } Gwei</span>
|
||||
</Skeleton>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { useColorModeValue } from '@chakra-ui/react';
|
||||
|
||||
export default function useMenuColors() {
|
||||
const themedBackground = useColorModeValue('blackAlpha.50', 'whiteAlpha.50');
|
||||
const themedBorderColor = useColorModeValue('gray.300', 'gray.700');
|
||||
const themedColor = useColorModeValue('blackAlpha.800', 'gray.400');
|
||||
|
||||
return { themedBackground, themedBorderColor, themedColor };
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Box, Button, Text } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
|
||||
type Props = {
|
||||
address?: string;
|
||||
disconnect?: () => void;
|
||||
};
|
||||
|
||||
const WalletMenuContent = ({ address, disconnect }: Props) => (
|
||||
<Box>
|
||||
<Text
|
||||
fontSize="sm"
|
||||
fontWeight={ 600 }
|
||||
mb={ 1 }
|
||||
{ ...getDefaultTransitionProps() }
|
||||
>
|
||||
My wallet
|
||||
</Text>
|
||||
<Text
|
||||
fontSize="sm"
|
||||
mb={ 5 }
|
||||
fontWeight={ 400 }
|
||||
color="text_secondary"
|
||||
{ ...getDefaultTransitionProps() }
|
||||
>
|
||||
Your wallet is used to interact with apps and contracts in the explorer.
|
||||
</Text>
|
||||
<AddressEntity
|
||||
address={{ hash: address }}
|
||||
noTooltip
|
||||
truncation="dynamic"
|
||||
fontSize="sm"
|
||||
fontWeight={ 700 }
|
||||
color="text"
|
||||
mb={ 6 }
|
||||
/>
|
||||
<Button size="sm" width="full" variant="outline" onClick={ disconnect }>
|
||||
Disconnect
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default WalletMenuContent;
|
||||
@@ -0,0 +1,94 @@
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
import { Popover, PopoverContent, PopoverBody, PopoverTrigger, Button, Box, useBoolean } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import AddressIdenticon from 'ui/shared/entities/address/AddressIdenticon';
|
||||
import HashStringShorten from 'ui/shared/HashStringShorten';
|
||||
import useWallet from 'ui/snippets/walletMenu/useWallet';
|
||||
import WalletMenuContent from 'ui/snippets/walletMenu/WalletMenuContent';
|
||||
|
||||
import useMenuButtonColors from '../useMenuButtonColors';
|
||||
import WalletTooltip from './WalletTooltip';
|
||||
|
||||
type Props = {
|
||||
isHomePage?: boolean;
|
||||
};
|
||||
|
||||
const WalletMenuDesktop = ({ isHomePage }: Props) => {
|
||||
const { isWalletConnected, address, connect, disconnect, isModalOpening, isModalOpen } = useWallet();
|
||||
const { themedBackground, themedBorderColor, themedColor } = useMenuButtonColors();
|
||||
const [ isPopoverOpen, setIsPopoverOpen ] = useBoolean(false);
|
||||
|
||||
const variant = React.useMemo(() => {
|
||||
if (isWalletConnected) {
|
||||
return 'subtle';
|
||||
}
|
||||
return isHomePage ? 'solid' : 'outline';
|
||||
}, [ isWalletConnected, isHomePage ]);
|
||||
|
||||
let buttonStyles: Partial<ButtonProps> = {};
|
||||
if (isWalletConnected) {
|
||||
buttonStyles = {
|
||||
bg: isHomePage ? 'blue.50' : themedBackground,
|
||||
color: isHomePage ? 'blackAlpha.800' : themedColor,
|
||||
_hover: {
|
||||
color: isHomePage ? 'blackAlpha.800' : themedColor,
|
||||
},
|
||||
};
|
||||
} else if (isHomePage) {
|
||||
buttonStyles = {
|
||||
color: 'white',
|
||||
};
|
||||
} else {
|
||||
buttonStyles = {
|
||||
borderColor: themedBorderColor,
|
||||
color: themedColor,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover
|
||||
openDelay={ 300 }
|
||||
placement="bottom-end"
|
||||
gutter={ 10 }
|
||||
isLazy
|
||||
isOpen={ isPopoverOpen }
|
||||
onClose={ setIsPopoverOpen.off }
|
||||
>
|
||||
<WalletTooltip isDisabled={ isWalletConnected }>
|
||||
<Box ml={ 2 }>
|
||||
<PopoverTrigger>
|
||||
<Button
|
||||
variant={ variant }
|
||||
colorScheme="blue"
|
||||
flexShrink={ 0 }
|
||||
isLoading={ isModalOpening || isModalOpen }
|
||||
loadingText="Connect wallet"
|
||||
onClick={ isWalletConnected ? setIsPopoverOpen.on : connect }
|
||||
fontSize="sm"
|
||||
{ ...buttonStyles }
|
||||
>
|
||||
{ isWalletConnected ? (
|
||||
<>
|
||||
<Box mr={ 2 }>
|
||||
<AddressIdenticon size={ 20 } hash={ address }/>
|
||||
</Box>
|
||||
<HashStringShorten hash={ address } isTooltipDisabled/>
|
||||
</>
|
||||
) : 'Connect wallet' }
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
</Box>
|
||||
</WalletTooltip>
|
||||
{ isWalletConnected && (
|
||||
<PopoverContent w="235px">
|
||||
<PopoverBody padding="24px 16px 16px 16px">
|
||||
<WalletMenuContent address={ address } disconnect={ disconnect }/>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
) }
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default WalletMenuDesktop;
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Drawer, DrawerOverlay, DrawerContent, DrawerBody, useDisclosure, IconButton, Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import walletIcon from 'icons/wallet.svg';
|
||||
import AddressIdenticon from 'ui/shared/entities/address/AddressIdenticon';
|
||||
import useWallet from 'ui/snippets/walletMenu/useWallet';
|
||||
import WalletMenuContent from 'ui/snippets/walletMenu/WalletMenuContent';
|
||||
|
||||
import useMenuButtonColors from '../useMenuButtonColors';
|
||||
import WalletTooltip from './WalletTooltip';
|
||||
|
||||
const WalletMenuMobile = () => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const { isWalletConnected, address, connect, disconnect, isModalOpening, isModalOpen } = useWallet();
|
||||
const { themedBackground, themedBorderColor, themedColor } = useMenuButtonColors();
|
||||
|
||||
return (
|
||||
<>
|
||||
<WalletTooltip isDisabled={ isWalletConnected } isMobile>
|
||||
<IconButton
|
||||
aria-label="wallet menu"
|
||||
icon={ isWalletConnected ?
|
||||
<AddressIdenticon size={ 20 } hash={ address }/> :
|
||||
<Icon as={ walletIcon } boxSize={ 6 }/>
|
||||
}
|
||||
variant={ isWalletConnected ? 'subtle' : 'outline' }
|
||||
colorScheme="gray"
|
||||
boxSize="40px"
|
||||
flexShrink={ 0 }
|
||||
bg={ isWalletConnected ? themedBackground : undefined }
|
||||
color={ themedColor }
|
||||
borderColor={ !isWalletConnected ? themedBorderColor : undefined }
|
||||
onClick={ isWalletConnected ? onOpen : connect }
|
||||
isLoading={ isModalOpening || isModalOpen }
|
||||
/>
|
||||
</WalletTooltip>
|
||||
{ isWalletConnected && (
|
||||
<Drawer
|
||||
isOpen={ isOpen }
|
||||
placement="right"
|
||||
onClose={ onClose }
|
||||
autoFocus={ false }
|
||||
>
|
||||
<DrawerOverlay/>
|
||||
<DrawerContent maxWidth="260px">
|
||||
<DrawerBody p={ 6 }>
|
||||
<WalletMenuContent address={ address } disconnect={ disconnect }/>
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
) }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WalletMenuMobile;
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Tooltip, useBoolean } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
isDisabled?: boolean;
|
||||
isMobile?: boolean;
|
||||
};
|
||||
|
||||
const WalletTooltip = ({ children, isDisabled, isMobile }: Props) => {
|
||||
const [ isTooltipShown, setIsTooltipShown ] = useBoolean(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
const key = `wallet-connect-tooltip-shown-${ isMobile ? 'mobile' : 'desktop' }`;
|
||||
const wasShown = window.localStorage.getItem(key);
|
||||
if (!wasShown) {
|
||||
setIsTooltipShown.on();
|
||||
window.localStorage.setItem(key, 'true');
|
||||
}
|
||||
}, [ setIsTooltipShown, isMobile ]);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
label={ <span>Your wallet is used to interact with<br/>apps and contracts in the explorer</span> }
|
||||
textAlign="center"
|
||||
padding={ 2 }
|
||||
isDisabled={ isDisabled }
|
||||
openDelay={ 300 }
|
||||
isOpen={ isTooltipShown || (isMobile ? false : undefined) }
|
||||
onClose={ setIsTooltipShown.off }
|
||||
display={ isMobile ? { base: 'flex', lg: 'none' } : { base: 'none', lg: 'flex' } }
|
||||
>
|
||||
{ children }
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default WalletTooltip;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useWeb3Modal } from '@web3modal/react';
|
||||
import React from 'react';
|
||||
import { useAccount, useDisconnect } from 'wagmi';
|
||||
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
|
||||
export default function useWallet() {
|
||||
const { open, isOpen } = useWeb3Modal();
|
||||
const { disconnect } = useDisconnect();
|
||||
const [ isModalOpening, setIsModalOpening ] = React.useState(false);
|
||||
const [ isClientLoaded, setIsClientLoaded ] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
setIsClientLoaded(true);
|
||||
}, []);
|
||||
|
||||
const handleConnect = React.useCallback(async() => {
|
||||
setIsModalOpening(true);
|
||||
await open();
|
||||
setIsModalOpening(false);
|
||||
mixpanel.logEvent(mixpanel.EventTypes.WALLET_CONNECT, { Source: 'Header', Status: 'Started' });
|
||||
}, [ open ]);
|
||||
|
||||
const handleAccountConnected = React.useCallback(({ isReconnected }: { isReconnected: boolean }) => {
|
||||
!isReconnected && mixpanel.logEvent(mixpanel.EventTypes.WALLET_CONNECT, { Source: 'Header', Status: 'Connected' });
|
||||
}, []);
|
||||
|
||||
const handleDisconnect = React.useCallback(() => {
|
||||
disconnect();
|
||||
}, [ disconnect ]);
|
||||
|
||||
const { address, isDisconnected } = useAccount({ onConnect: handleAccountConnected });
|
||||
|
||||
const isWalletConnected = isClientLoaded && !isDisconnected && address !== undefined;
|
||||
|
||||
return {
|
||||
isWalletConnected,
|
||||
address: address || '',
|
||||
connect: handleConnect,
|
||||
disconnect: handleDisconnect,
|
||||
isModalOpening,
|
||||
isModalOpen: isOpen,
|
||||
};
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import { STATS_COUNTER } from 'stubs/stats';
|
||||
import DataFetchAlert from '../shared/DataFetchAlert';
|
||||
import NumberWidget from './NumberWidget';
|
||||
|
||||
const UNITS_WITHOUT_SPACE = [ 's' ];
|
||||
|
||||
const NumberWidgetsList = () => {
|
||||
const { data, isPlaceholderData, isError } = useApiQuery('stats_counters', {
|
||||
queryOptions: {
|
||||
@@ -26,11 +28,18 @@ const NumberWidgetsList = () => {
|
||||
{
|
||||
data?.counters?.map(({ id, title, value, units, description }, index) => {
|
||||
|
||||
let unitsStr = '';
|
||||
if (UNITS_WITHOUT_SPACE.includes(units)) {
|
||||
unitsStr = units;
|
||||
} else if (units) {
|
||||
unitsStr = ' ' + units;
|
||||
}
|
||||
|
||||
return (
|
||||
<NumberWidget
|
||||
key={ id + (isPlaceholderData ? index : '') }
|
||||
label={ title }
|
||||
value={ `${ Number(value).toLocaleString(undefined, { maximumFractionDigits: 3, notation: 'compact' }) } ${ units ? units : '' }` }
|
||||
value={ `${ Number(value).toLocaleString(undefined, { maximumFractionDigits: 3, notation: 'compact' }) }${ unitsStr }` }
|
||||
isLoading={ isPlaceholderData }
|
||||
description={ description }
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { TokenType } from 'types/api/token';
|
||||
import type { TokensSortingField, TokensSortingValue, TokensSorting } from 'types/api/tokens';
|
||||
|
||||
import type { Query } from 'nextjs-routes';
|
||||
import type { TokensSortingValue } from 'types/api/tokens';
|
||||
|
||||
import config from 'configs/app';
|
||||
import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
|
||||
@@ -29,22 +27,3 @@ const bridgedTokensChainIds = (() => {
|
||||
return feature.chains.map(chain => chain.id);
|
||||
})();
|
||||
export const getBridgedChainsFilterValue = (getFilterValuesFromQuery<string>).bind(null, bridgedTokensChainIds);
|
||||
|
||||
export const getSortValueFromQuery = (query: Query): TokensSortingValue | undefined => {
|
||||
if (!query.sort || !query.order) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const str = query.sort + '-' + query.order;
|
||||
if (SORT_OPTIONS.map(option => option.id).includes(str)) {
|
||||
return str as TokensSortingValue;
|
||||
}
|
||||
};
|
||||
|
||||
export const getSortParamsFromValue = (val?: TokensSortingValue): TokensSorting | undefined => {
|
||||
if (!val) {
|
||||
return undefined;
|
||||
}
|
||||
const sortingChunks = val.split('-') as [ TokensSortingField, TokensSorting['order'] ];
|
||||
return { sort: sortingChunks[0], order: sortingChunks[1] };
|
||||
};
|
||||
|
||||
@@ -2,17 +2,23 @@ import { Box, Show, Hide } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressFromToFilter } from 'types/api/address';
|
||||
import type { Transaction, TransactionsSortingField, TransactionsSortingValue } from 'types/api/transaction';
|
||||
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import AddressCsvExportLink from 'ui/address/AddressCsvExportLink';
|
||||
import DataListDisplay from 'ui/shared/DataListDisplay';
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
|
||||
import getNextSortValue from 'ui/shared/sort/getNextSortValue';
|
||||
|
||||
import TxsHeaderMobile from './TxsHeaderMobile';
|
||||
import TxsListItem from './TxsListItem';
|
||||
import TxsTable from './TxsTable';
|
||||
import useTxsSort from './useTxsSort';
|
||||
|
||||
const SORT_SEQUENCE: Record<TransactionsSortingField, Array<TransactionsSortingValue | undefined>> = {
|
||||
value: [ 'value-desc', 'value-asc', undefined ],
|
||||
fee: [ 'fee-desc', 'fee-asc', undefined ],
|
||||
};
|
||||
|
||||
type Props = {
|
||||
// eslint-disable-next-line max-len
|
||||
@@ -26,12 +32,17 @@ type Props = {
|
||||
filterValue?: AddressFromToFilter;
|
||||
enableTimeIncrement?: boolean;
|
||||
top?: number;
|
||||
items?: Array<Transaction>;
|
||||
isPlaceholderData: boolean;
|
||||
isError: boolean;
|
||||
setSorting: (value: TransactionsSortingValue | undefined) => void;
|
||||
sort: TransactionsSortingValue | undefined;
|
||||
}
|
||||
|
||||
const TxsContent = ({
|
||||
query,
|
||||
filter,
|
||||
filterValue,
|
||||
query,
|
||||
showBlockInfo = true,
|
||||
showSocketInfo = true,
|
||||
socketInfoAlert,
|
||||
@@ -39,11 +50,20 @@ const TxsContent = ({
|
||||
currentAddress,
|
||||
enableTimeIncrement,
|
||||
top,
|
||||
items,
|
||||
isPlaceholderData,
|
||||
isError,
|
||||
setSorting,
|
||||
sort,
|
||||
}: Props) => {
|
||||
const { data, isPlaceholderData, isError, setSortByField, setSortByValue, sorting } = useTxsSort(query);
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const content = data?.items ? (
|
||||
const onSortToggle = React.useCallback((field: TransactionsSortingField) => () => {
|
||||
const value = getNextSortValue<TransactionsSortingField, TransactionsSortingValue>(SORT_SEQUENCE, field)(sort);
|
||||
setSorting(value);
|
||||
}, [ sort, setSorting ]);
|
||||
|
||||
const content = items ? (
|
||||
<>
|
||||
<Show below="lg" ssr={ false }>
|
||||
<Box>
|
||||
@@ -55,7 +75,7 @@ const TxsContent = ({
|
||||
isLoading={ isPlaceholderData }
|
||||
/>
|
||||
) }
|
||||
{ data.items.map((tx, index) => (
|
||||
{ items.map((tx, index) => (
|
||||
<TxsListItem
|
||||
key={ tx.hash + (isPlaceholderData ? index : '') }
|
||||
tx={ tx }
|
||||
@@ -69,9 +89,9 @@ const TxsContent = ({
|
||||
</Show>
|
||||
<Hide below="lg" ssr={ false }>
|
||||
<TxsTable
|
||||
txs={ data.items }
|
||||
sort={ setSortByField }
|
||||
sorting={ sorting }
|
||||
txs={ items }
|
||||
sort={ onSortToggle }
|
||||
sorting={ sort }
|
||||
showBlockInfo={ showBlockInfo }
|
||||
showSocketInfo={ showSocketInfo }
|
||||
socketInfoAlert={ socketInfoAlert }
|
||||
@@ -88,8 +108,8 @@ const TxsContent = ({
|
||||
const actionBar = isMobile ? (
|
||||
<TxsHeaderMobile
|
||||
mt={ -6 }
|
||||
sorting={ sorting }
|
||||
setSorting={ setSortByValue }
|
||||
sorting={ sort }
|
||||
setSorting={ setSorting }
|
||||
paginationProps={ query.pagination }
|
||||
showPagination={ query.pagination.isVisible }
|
||||
filterComponent={ filter }
|
||||
@@ -107,7 +127,7 @@ const TxsContent = ({
|
||||
return (
|
||||
<DataListDisplay
|
||||
isError={ isError }
|
||||
items={ data?.items }
|
||||
items={ items }
|
||||
emptyText="There are no transactions."
|
||||
content={ content }
|
||||
actionBar={ actionBar }
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
import { HStack, chakra } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { Sort as TSort } from 'types/client/txs-sort';
|
||||
import type { TransactionsSortingValue } from 'types/api/transaction';
|
||||
import type { PaginationParams } from 'ui/shared/pagination/types';
|
||||
|
||||
// import FilterInput from 'ui/shared/filters/FilterInput';
|
||||
|
||||
import ActionBar from 'ui/shared/ActionBar';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
import Sort from 'ui/shared/sort/Sort';
|
||||
|
||||
import { SORT_OPTIONS } from './useTxsSort';
|
||||
|
||||
// import TxsFilters from './TxsFilters';
|
||||
|
||||
const SORT_OPTIONS: Array<Option<TSort>> = [
|
||||
{ title: 'Default', id: undefined },
|
||||
{ title: 'Value ascending', id: 'val-asc' },
|
||||
{ title: 'Value descending', id: 'val-desc' },
|
||||
{ title: 'Fee ascending', id: 'fee-asc' },
|
||||
{ title: 'Fee descending', id: 'fee-desc' },
|
||||
];
|
||||
|
||||
type Props = {
|
||||
sorting: TSort;
|
||||
setSorting: (val: TSort | undefined) => void;
|
||||
sorting: TransactionsSortingValue | undefined;
|
||||
setSorting: (val: TransactionsSortingValue | undefined) => void;
|
||||
paginationProps: PaginationParams;
|
||||
className?: string;
|
||||
showPagination?: boolean;
|
||||
|
||||
@@ -2,8 +2,7 @@ import { Link, Table, Tbody, Tr, Th, Icon, Show, Hide } from '@chakra-ui/react';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import React from 'react';
|
||||
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
import type { Sort } from 'types/client/txs-sort';
|
||||
import type { Transaction, TransactionsSortingField, TransactionsSortingValue } from 'types/api/transaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
@@ -14,8 +13,8 @@ import TxsTableItem from './TxsTableItem';
|
||||
|
||||
type Props = {
|
||||
txs: Array<Transaction>;
|
||||
sort: (field: 'val' | 'fee') => () => void;
|
||||
sorting?: Sort;
|
||||
sort: (field: TransactionsSortingField) => () => void;
|
||||
sorting?: TransactionsSortingValue;
|
||||
top: number;
|
||||
showBlockInfo: boolean;
|
||||
showSocketInfo: boolean;
|
||||
@@ -58,9 +57,9 @@ const TxsTable = ({
|
||||
</Th>
|
||||
{ !config.UI.views.tx.hiddenFields?.value && (
|
||||
<Th width="20%" isNumeric>
|
||||
<Link onClick={ sort('val') } display="flex" justifyContent="end">
|
||||
{ sorting === 'val-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
|
||||
{ sorting === 'val-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
|
||||
<Link onClick={ sort('value') } display="flex" justifyContent="end">
|
||||
{ sorting === 'value-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
|
||||
{ sorting === 'value-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
|
||||
{ `Value ${ config.chain.currency.symbol }` }
|
||||
</Link>
|
||||
</Th>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
import useRedirectForInvalidAuthToken from 'lib/hooks/useRedirectForInvalidAuthToken';
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
type Props = {
|
||||
query: QueryWithPagesResult<'txs_watchlist'>;
|
||||
@@ -10,7 +10,7 @@ type Props = {
|
||||
|
||||
const TxsWatchlist = ({ query }: Props) => {
|
||||
useRedirectForInvalidAuthToken();
|
||||
return <TxsContent query={ query } showSocketInfo={ false }/>;
|
||||
return <TxsWithFrontendSorting query={ query } showSocketInfo={ false }/>;
|
||||
};
|
||||
|
||||
export default TxsWatchlist;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressFromToFilter } from 'types/api/address';
|
||||
import type { TransactionsSortingValue } from 'types/api/transaction';
|
||||
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
|
||||
import TxsContent from './TxsContent';
|
||||
|
||||
type Props = {
|
||||
// eslint-disable-next-line max-len
|
||||
query: QueryWithPagesResult<'address_txs'>;
|
||||
showBlockInfo?: boolean;
|
||||
showSocketInfo?: boolean;
|
||||
socketInfoAlert?: string;
|
||||
socketInfoNum?: number;
|
||||
currentAddress?: string;
|
||||
filter?: React.ReactNode;
|
||||
filterValue?: AddressFromToFilter;
|
||||
enableTimeIncrement?: boolean;
|
||||
top?: number;
|
||||
sorting: TransactionsSortingValue | undefined;
|
||||
setSort: (value?: TransactionsSortingValue) => void;
|
||||
}
|
||||
|
||||
const TxsWithAPISorting = ({
|
||||
filter,
|
||||
filterValue,
|
||||
query,
|
||||
showBlockInfo = true,
|
||||
showSocketInfo = true,
|
||||
socketInfoAlert,
|
||||
socketInfoNum,
|
||||
currentAddress,
|
||||
enableTimeIncrement,
|
||||
top,
|
||||
sorting,
|
||||
setSort,
|
||||
}: Props) => {
|
||||
|
||||
const handleSortChange = React.useCallback((value?: TransactionsSortingValue) => {
|
||||
setSort(value);
|
||||
query.onSortingChange(getSortParamsFromValue(value));
|
||||
}, [ setSort, query ]);
|
||||
|
||||
return (
|
||||
<TxsContent
|
||||
filter={ filter }
|
||||
filterValue={ filterValue }
|
||||
showBlockInfo={ showBlockInfo }
|
||||
showSocketInfo={ showSocketInfo }
|
||||
socketInfoAlert={ socketInfoAlert }
|
||||
socketInfoNum={ socketInfoNum }
|
||||
currentAddress={ currentAddress }
|
||||
enableTimeIncrement={ enableTimeIncrement }
|
||||
top={ top }
|
||||
items={ query.data?.items }
|
||||
isPlaceholderData={ query.isPlaceholderData }
|
||||
isError={ query.isError }
|
||||
setSorting={ handleSortChange }
|
||||
sort={ sorting }
|
||||
query={ query }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TxsWithAPISorting;
|
||||
@@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressFromToFilter } from 'types/api/address';
|
||||
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
|
||||
import TxsContent from './TxsContent';
|
||||
import useTxsSort from './useTxsSort';
|
||||
|
||||
type Props = {
|
||||
// eslint-disable-next-line max-len
|
||||
query: QueryWithPagesResult<'txs_validated' | 'txs_pending'> | QueryWithPagesResult<'txs_watchlist'> | QueryWithPagesResult<'block_txs'> | QueryWithPagesResult<'zkevm_l2_txn_batch_txs'>;
|
||||
showBlockInfo?: boolean;
|
||||
showSocketInfo?: boolean;
|
||||
socketInfoAlert?: string;
|
||||
socketInfoNum?: number;
|
||||
currentAddress?: string;
|
||||
filter?: React.ReactNode;
|
||||
filterValue?: AddressFromToFilter;
|
||||
enableTimeIncrement?: boolean;
|
||||
top?: number;
|
||||
}
|
||||
|
||||
const TxsWithFrontendSorting = ({
|
||||
filter,
|
||||
filterValue,
|
||||
query,
|
||||
showBlockInfo = true,
|
||||
showSocketInfo = true,
|
||||
socketInfoAlert,
|
||||
socketInfoNum,
|
||||
currentAddress,
|
||||
enableTimeIncrement,
|
||||
top,
|
||||
}: Props) => {
|
||||
const { data, isPlaceholderData, isError, setSortByValue, sorting } = useTxsSort(query);
|
||||
|
||||
return (
|
||||
<TxsContent
|
||||
filter={ filter }
|
||||
filterValue={ filterValue }
|
||||
showBlockInfo={ showBlockInfo }
|
||||
showSocketInfo={ showSocketInfo }
|
||||
socketInfoAlert={ socketInfoAlert }
|
||||
socketInfoNum={ socketInfoNum }
|
||||
currentAddress={ currentAddress }
|
||||
enableTimeIncrement={ enableTimeIncrement }
|
||||
top={ top }
|
||||
items={ data?.items }
|
||||
isPlaceholderData={ isPlaceholderData }
|
||||
isError={ isError }
|
||||
setSorting={ setSortByValue }
|
||||
sort={ sorting }
|
||||
query={ query }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TxsWithFrontendSorting;
|
||||
@@ -1,78 +1,71 @@
|
||||
import type { UseQueryResult } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
|
||||
import type { TxsResponse } from 'types/api/transaction';
|
||||
import type { Sort } from 'types/client/txs-sort';
|
||||
import type { Transaction, TransactionsSortingValue, TxsResponse } from 'types/api/transaction';
|
||||
|
||||
import type { ResourceError } from 'lib/api/resources';
|
||||
import compareBns from 'lib/bigint/compareBns';
|
||||
import * as cookies from 'lib/cookies';
|
||||
import sortTxs from 'lib/tx/sortTxs';
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
|
||||
export const SORT_OPTIONS: Array<Option<TransactionsSortingValue>> = [
|
||||
{ title: 'Default', id: undefined },
|
||||
{ title: 'Value ascending', id: 'value-asc' },
|
||||
{ title: 'Value descending', id: 'value-desc' },
|
||||
{ title: 'Fee ascending', id: 'fee-asc' },
|
||||
{ title: 'Fee descending', id: 'fee-desc' },
|
||||
];
|
||||
|
||||
type SortingValue = TransactionsSortingValue | undefined;
|
||||
|
||||
type HookResult = UseQueryResult<TxsResponse, ResourceError<unknown>> & {
|
||||
sorting: Sort;
|
||||
setSortByField: (field: 'val' | 'fee') => () => void;
|
||||
setSortByValue: (value: Sort | undefined) => void;
|
||||
sorting: SortingValue;
|
||||
setSortByValue: (value: SortingValue) => void;
|
||||
}
|
||||
|
||||
const sortTxs = (sorting: SortingValue) => (tx1: Transaction, tx2: Transaction) => {
|
||||
switch (sorting) {
|
||||
case 'value-desc':
|
||||
return compareBns(tx1.value, tx2.value);
|
||||
case 'value-asc':
|
||||
return compareBns(tx2.value, tx1.value);
|
||||
case 'fee-desc':
|
||||
return compareBns(tx1.fee.value || 0, tx2.fee.value || 0);
|
||||
case 'fee-asc':
|
||||
return compareBns(tx2.fee.value || 0, tx1.fee.value || 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
export default function useTxsSort(
|
||||
queryResult: UseQueryResult<TxsResponse, ResourceError<unknown>>,
|
||||
): HookResult {
|
||||
|
||||
const [ sorting, setSorting ] = React.useState<Sort>(cookies.get(cookies.NAMES.TXS_SORT) as Sort);
|
||||
const [ sorting, setSorting ] = React.useState<SortingValue>(cookies.get(cookies.NAMES.TXS_SORT) as SortingValue);
|
||||
|
||||
const setSortByField = React.useCallback((field: 'val' | 'fee') => () => {
|
||||
if (queryResult.isPlaceholderData) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSorting((prevVal) => {
|
||||
let newVal: Sort = '';
|
||||
if (field === 'val') {
|
||||
if (prevVal === 'val-asc') {
|
||||
newVal = '';
|
||||
} else if (prevVal === 'val-desc') {
|
||||
newVal = 'val-asc';
|
||||
} else {
|
||||
newVal = 'val-desc';
|
||||
}
|
||||
}
|
||||
if (field === 'fee') {
|
||||
if (prevVal === 'fee-asc') {
|
||||
newVal = '';
|
||||
} else if (prevVal === 'fee-desc') {
|
||||
newVal = 'fee-asc';
|
||||
} else {
|
||||
newVal = 'fee-desc';
|
||||
}
|
||||
}
|
||||
cookies.set(cookies.NAMES.TXS_SORT, newVal);
|
||||
return newVal;
|
||||
});
|
||||
}, [ queryResult.isPlaceholderData ]);
|
||||
|
||||
const setSortByValue = React.useCallback((value: Sort | undefined) => {
|
||||
setSorting((prevVal: Sort) => {
|
||||
let newVal: Sort = '';
|
||||
const setSortByValue = React.useCallback((value: SortingValue) => {
|
||||
setSorting((prevVal: SortingValue) => {
|
||||
let newVal: SortingValue = undefined;
|
||||
if (value !== prevVal) {
|
||||
newVal = value as Sort;
|
||||
newVal = value as SortingValue;
|
||||
}
|
||||
cookies.set(cookies.NAMES.TXS_SORT, newVal);
|
||||
cookies.set(cookies.NAMES.TXS_SORT, newVal ? newVal : '');
|
||||
return newVal;
|
||||
});
|
||||
}, []);
|
||||
|
||||
return React.useMemo(() => {
|
||||
if (queryResult.isError || queryResult.isPending) {
|
||||
return { ...queryResult, setSortByField, setSortByValue, sorting };
|
||||
return { ...queryResult, setSortByValue, sorting };
|
||||
}
|
||||
|
||||
return {
|
||||
...queryResult,
|
||||
data: { ...queryResult.data, items: queryResult.data.items.slice().sort(sortTxs(sorting)) },
|
||||
setSortByField,
|
||||
setSortByValue,
|
||||
sorting,
|
||||
};
|
||||
}, [ queryResult, setSortByField, setSortByValue, sorting ]);
|
||||
}, [ queryResult, setSortByValue, sorting ]);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,23 +2,30 @@ import { Table, Tbody, Tr, Th, Link, Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { VerifiedContract } from 'types/api/contracts';
|
||||
import type { VerifiedContractsSorting, VerifiedContractsSortingField, VerifiedContractsSortingValue } from 'types/api/verifiedContracts';
|
||||
|
||||
import config from 'configs/app';
|
||||
import arrowIcon from 'icons/arrows/east.svg';
|
||||
import getNextSortValue from 'ui/shared/sort/getNextSortValue';
|
||||
import { default as Thead } from 'ui/shared/TheadSticky';
|
||||
import { SORT_SEQUENCE } from 'ui/verifiedContracts/utils';
|
||||
|
||||
import type { Sort, SortField } from './utils';
|
||||
import VerifiedContractsTableItem from './VerifiedContractsTableItem';
|
||||
|
||||
interface Props {
|
||||
data: Array<VerifiedContract>;
|
||||
sort: Sort | undefined;
|
||||
onSortToggle: (field: SortField) => () => void;
|
||||
sort: VerifiedContractsSortingValue | undefined;
|
||||
setSorting: (val: VerifiedContractsSortingValue | undefined) => void;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const VerifiedContractsTable = ({ data, sort, onSortToggle, isLoading }: Props) => {
|
||||
const sortIconTransform = sort?.includes('asc') ? 'rotate(-90deg)' : 'rotate(90deg)';
|
||||
const VerifiedContractsTable = ({ data, sort, setSorting, isLoading }: Props) => {
|
||||
const sortIconTransform = sort?.includes('asc' as VerifiedContractsSorting['order']) ? 'rotate(-90deg)' : 'rotate(90deg)';
|
||||
|
||||
const onSortToggle = React.useCallback((field: VerifiedContractsSortingField) => () => {
|
||||
const value = getNextSortValue<VerifiedContractsSortingField, VerifiedContractsSortingValue>(SORT_SEQUENCE, field)(sort);
|
||||
setSorting(value);
|
||||
}, [ sort, setSorting ]);
|
||||
|
||||
return (
|
||||
<Table variant="simple" size="sm">
|
||||
@@ -32,8 +39,8 @@ const VerifiedContractsTable = ({ data, sort, onSortToggle, isLoading }: Props)
|
||||
</Link>
|
||||
</Th>
|
||||
<Th width="130px" isNumeric>
|
||||
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('txs') } columnGap={ 1 }>
|
||||
{ sort?.includes('txs') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
|
||||
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('txs_count') } columnGap={ 1 }>
|
||||
{ sort?.includes('txs_count') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
|
||||
Txs
|
||||
</Link>
|
||||
</Th>
|
||||
|
||||
@@ -1,42 +1,16 @@
|
||||
import type { VerifiedContract } from 'types/api/contracts';
|
||||
import type { VerifiedContractsSortingValue, VerifiedContractsSortingField } from 'types/api/verifiedContracts';
|
||||
|
||||
import compareBns from 'lib/bigint/compareBns';
|
||||
import { default as getNextSortValueShared } from 'ui/shared/sort/getNextSortValue';
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
|
||||
export type SortField = 'balance' | 'txs';
|
||||
export type Sort = `${ SortField }-asc` | `${ SortField }-desc`;
|
||||
|
||||
export const SORT_OPTIONS: Array<Option<Sort>> = [
|
||||
export const SORT_OPTIONS: Array<Option<VerifiedContractsSortingValue>> = [
|
||||
{ title: 'Default', id: undefined },
|
||||
{ title: 'Balance descending', id: 'balance-desc' },
|
||||
{ title: 'Balance ascending', id: 'balance-asc' },
|
||||
{ title: 'Txs count descending', id: 'txs-desc' },
|
||||
{ title: 'Txs count ascending', id: 'txs-asc' },
|
||||
{ title: 'Txs count descending', id: 'txs_count-desc' },
|
||||
{ title: 'Txs count ascending', id: 'txs_count-asc' },
|
||||
];
|
||||
|
||||
const SORT_SEQUENCE: Record<SortField, Array<Sort | undefined>> = {
|
||||
export const SORT_SEQUENCE: Record<VerifiedContractsSortingField, Array<VerifiedContractsSortingValue | undefined>> = {
|
||||
balance: [ 'balance-desc', 'balance-asc', undefined ],
|
||||
txs: [ 'txs-desc', 'txs-asc', undefined ],
|
||||
};
|
||||
|
||||
export const getNextSortValue = (getNextSortValueShared<SortField, Sort>).bind(undefined, SORT_SEQUENCE);
|
||||
|
||||
export const sortFn = (sort: Sort | undefined) => (a: VerifiedContract, b: VerifiedContract) => {
|
||||
switch (sort) {
|
||||
case 'balance-asc':
|
||||
case 'balance-desc': {
|
||||
const result = compareBns(b.coin_balance, a.coin_balance) * (sort.includes('desc') ? 1 : -1);
|
||||
return a.coin_balance === b.coin_balance ? 0 : result;
|
||||
}
|
||||
|
||||
case 'txs-asc':
|
||||
case 'txs-desc': {
|
||||
const result = ((a.tx_count || 0) > (b.tx_count || 0) ? -1 : 1) * (sort.includes('desc') ? 1 : -1);
|
||||
return a.tx_count === b.tx_count ? 0 : result;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
txs_count: [ 'txs_count-desc', 'txs_count-asc', undefined ],
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ const WatchListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) =
|
||||
},
|
||||
onSuccess: () => {
|
||||
setSwitchDisabled(false);
|
||||
showNotificationToast(!notificationEnabled);
|
||||
showNotificationToast(notificationEnabled);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.18.6"
|
||||
|
||||
"@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5":
|
||||
version "7.23.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244"
|
||||
integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.23.4"
|
||||
chalk "^2.4.2"
|
||||
|
||||
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1":
|
||||
version "7.20.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30"
|
||||
@@ -81,16 +89,7 @@
|
||||
json5 "^2.2.2"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/generator@^7.19.4":
|
||||
version "7.19.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.5.tgz#da3f4b301c8086717eee9cab14da91b1fa5dcca7"
|
||||
integrity sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.19.4"
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.20.1", "@babel/generator@^7.20.2", "@babel/generator@^7.7.2":
|
||||
"@babel/generator@^7.20.2", "@babel/generator@^7.7.2":
|
||||
version "7.20.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8"
|
||||
integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==
|
||||
@@ -99,7 +98,7 @@
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.22.0", "@babel/generator@^7.22.3":
|
||||
"@babel/generator@^7.22.0":
|
||||
version "7.22.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.3.tgz#0ff675d2edb93d7596c5f6728b52615cfc0df01e"
|
||||
integrity sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==
|
||||
@@ -109,6 +108,16 @@
|
||||
"@jridgewell/trace-mapping" "^0.3.17"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.23.6":
|
||||
version "7.23.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e"
|
||||
integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.23.6"
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
"@jridgewell/trace-mapping" "^0.3.17"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
|
||||
@@ -188,6 +197,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz#ac3a56dbada59ed969d712cf527bd8271fe3eba8"
|
||||
integrity sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==
|
||||
|
||||
"@babel/helper-environment-visitor@^7.22.20":
|
||||
version "7.22.20"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
|
||||
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
|
||||
|
||||
"@babel/helper-explode-assignable-expression@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
|
||||
@@ -203,13 +217,13 @@
|
||||
"@babel/template" "^7.18.10"
|
||||
"@babel/types" "^7.19.0"
|
||||
|
||||
"@babel/helper-function-name@^7.21.0":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4"
|
||||
integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==
|
||||
"@babel/helper-function-name@^7.23.0":
|
||||
version "7.23.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
|
||||
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
|
||||
dependencies:
|
||||
"@babel/template" "^7.20.7"
|
||||
"@babel/types" "^7.21.0"
|
||||
"@babel/template" "^7.22.15"
|
||||
"@babel/types" "^7.23.0"
|
||||
|
||||
"@babel/helper-hoist-variables@^7.18.6":
|
||||
version "7.18.6"
|
||||
@@ -218,6 +232,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.18.6"
|
||||
|
||||
"@babel/helper-hoist-variables@^7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
|
||||
integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.22.5"
|
||||
|
||||
"@babel/helper-member-expression-to-functions@^7.18.9":
|
||||
version "7.18.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
|
||||
@@ -333,6 +354,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.18.6"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.22.6":
|
||||
version "7.22.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
|
||||
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
|
||||
dependencies:
|
||||
"@babel/types" "^7.22.5"
|
||||
|
||||
"@babel/helper-string-parser@^7.19.4":
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63"
|
||||
@@ -343,11 +371,21 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd"
|
||||
integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==
|
||||
|
||||
"@babel/helper-string-parser@^7.23.4":
|
||||
version "7.23.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83"
|
||||
integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
|
||||
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.22.20":
|
||||
version "7.22.20"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
||||
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
||||
|
||||
"@babel/helper-validator-option@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
|
||||
@@ -395,26 +433,35 @@
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2":
|
||||
"@babel/highlight@^7.23.4":
|
||||
version "7.23.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b"
|
||||
integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.22.20"
|
||||
chalk "^2.4.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.2":
|
||||
version "7.20.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2"
|
||||
integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==
|
||||
|
||||
"@babel/parser@^7.18.10", "@babel/parser@^7.19.4":
|
||||
"@babel/parser@^7.18.10":
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.4.tgz#03c4339d2b8971eb3beca5252bafd9b9f79db3dc"
|
||||
integrity sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==
|
||||
|
||||
"@babel/parser@^7.20.7":
|
||||
version "7.21.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.1.tgz#a8f81ee2fe872af23faea4b17a08fcc869de7bcc"
|
||||
integrity sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg==
|
||||
|
||||
"@babel/parser@^7.21.9", "@babel/parser@^7.22.0", "@babel/parser@^7.22.4":
|
||||
"@babel/parser@^7.21.9", "@babel/parser@^7.22.0":
|
||||
version "7.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.4.tgz#a770e98fd785c231af9d93f6459d36770993fb32"
|
||||
integrity sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==
|
||||
|
||||
"@babel/parser@^7.22.15", "@babel/parser@^7.23.6":
|
||||
version "7.23.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b"
|
||||
integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
|
||||
@@ -1187,15 +1234,6 @@
|
||||
"@babel/parser" "^7.18.10"
|
||||
"@babel/types" "^7.18.10"
|
||||
|
||||
"@babel/template@^7.20.7":
|
||||
version "7.20.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8"
|
||||
integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/parser" "^7.20.7"
|
||||
"@babel/types" "^7.20.7"
|
||||
|
||||
"@babel/template@^7.21.9":
|
||||
version "7.21.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.21.9.tgz#bf8dad2859130ae46088a99c1f265394877446fb"
|
||||
@@ -1205,52 +1243,29 @@
|
||||
"@babel/parser" "^7.21.9"
|
||||
"@babel/types" "^7.21.5"
|
||||
|
||||
"@babel/traverse@^7.19.0":
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.4.tgz#f117820e18b1e59448a6c1fa9d0ff08f7ac459a8"
|
||||
integrity sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==
|
||||
"@babel/template@^7.22.15":
|
||||
version "7.22.15"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
||||
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.19.4"
|
||||
"@babel/helper-environment-visitor" "^7.18.9"
|
||||
"@babel/helper-function-name" "^7.19.0"
|
||||
"@babel/helper-hoist-variables" "^7.18.6"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/parser" "^7.19.4"
|
||||
"@babel/types" "^7.19.4"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
"@babel/code-frame" "^7.22.13"
|
||||
"@babel/parser" "^7.22.15"
|
||||
"@babel/types" "^7.22.15"
|
||||
|
||||
"@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.7.2":
|
||||
version "7.20.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8"
|
||||
integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==
|
||||
"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.22.1", "@babel/traverse@^7.7.2":
|
||||
version "7.23.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5"
|
||||
integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.20.1"
|
||||
"@babel/helper-environment-visitor" "^7.18.9"
|
||||
"@babel/helper-function-name" "^7.19.0"
|
||||
"@babel/helper-hoist-variables" "^7.18.6"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/parser" "^7.20.1"
|
||||
"@babel/types" "^7.20.0"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/traverse@^7.22.1":
|
||||
version "7.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.4.tgz#c3cf96c5c290bd13b55e29d025274057727664c0"
|
||||
integrity sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.21.4"
|
||||
"@babel/generator" "^7.22.3"
|
||||
"@babel/helper-environment-visitor" "^7.22.1"
|
||||
"@babel/helper-function-name" "^7.21.0"
|
||||
"@babel/helper-hoist-variables" "^7.18.6"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/parser" "^7.22.4"
|
||||
"@babel/types" "^7.22.4"
|
||||
debug "^4.1.0"
|
||||
"@babel/code-frame" "^7.23.5"
|
||||
"@babel/generator" "^7.23.6"
|
||||
"@babel/helper-environment-visitor" "^7.22.20"
|
||||
"@babel/helper-function-name" "^7.23.0"
|
||||
"@babel/helper-hoist-variables" "^7.22.5"
|
||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||
"@babel/parser" "^7.23.6"
|
||||
"@babel/types" "^7.23.6"
|
||||
debug "^4.3.1"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
|
||||
@@ -1262,7 +1277,7 @@
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.19.4":
|
||||
"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0":
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.4.tgz#0dd5c91c573a202d600490a35b33246fed8a41c7"
|
||||
integrity sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==
|
||||
@@ -1271,16 +1286,7 @@
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.20.7", "@babel/types@^7.21.0":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.0.tgz#1da00d89c2f18b226c9207d96edbeb79316a1819"
|
||||
integrity sha512-uR7NWq2VNFnDi7EYqiRz2Jv/VQIu38tu64Zy8TX2nQFQ6etJ9V/Rr2msW8BS132mum2rL645qpDrLtAJtVpuow==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.19.4"
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.21.4", "@babel/types@^7.21.5", "@babel/types@^7.22.0", "@babel/types@^7.22.3", "@babel/types@^7.22.4":
|
||||
"@babel/types@^7.21.4", "@babel/types@^7.21.5", "@babel/types@^7.22.0", "@babel/types@^7.22.3":
|
||||
version "7.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.4.tgz#56a2653ae7e7591365dabf20b76295410684c071"
|
||||
integrity sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==
|
||||
@@ -1289,6 +1295,15 @@
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6":
|
||||
version "7.23.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd"
|
||||
integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.23.4"
|
||||
"@babel/helper-validator-identifier" "^7.22.20"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@bcoe/v8-coverage@^0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
@@ -2429,6 +2444,348 @@
|
||||
ethereum-cryptography "^2.0.0"
|
||||
micro-ftch "^0.3.1"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/abi@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449"
|
||||
integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==
|
||||
dependencies:
|
||||
"@ethersproject/address" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/hash" "^5.7.0"
|
||||
"@ethersproject/keccak256" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/abstract-provider@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef"
|
||||
integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/networks" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
"@ethersproject/web" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/abstract-signer@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2"
|
||||
integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-provider" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/address@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37"
|
||||
integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/keccak256" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/rlp" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/base64@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c"
|
||||
integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/basex@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b"
|
||||
integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/bignumber@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2"
|
||||
integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
bn.js "^5.2.1"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/bytes@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d"
|
||||
integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/constants@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e"
|
||||
integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e"
|
||||
integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "^5.7.0"
|
||||
"@ethersproject/abstract-provider" "^5.7.0"
|
||||
"@ethersproject/abstract-signer" "^5.7.0"
|
||||
"@ethersproject/address" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/hash@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7"
|
||||
integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-signer" "^5.7.0"
|
||||
"@ethersproject/address" "^5.7.0"
|
||||
"@ethersproject/base64" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/keccak256" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/hdnode@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf"
|
||||
integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-signer" "^5.7.0"
|
||||
"@ethersproject/basex" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/pbkdf2" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/sha2" "^5.7.0"
|
||||
"@ethersproject/signing-key" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
"@ethersproject/wordlists" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/json-wallets@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360"
|
||||
integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-signer" "^5.7.0"
|
||||
"@ethersproject/address" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/hdnode" "^5.7.0"
|
||||
"@ethersproject/keccak256" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/pbkdf2" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/random" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
aes-js "3.0.0"
|
||||
scrypt-js "3.0.1"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/keccak256@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a"
|
||||
integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
js-sha3 "0.8.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/logger@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892"
|
||||
integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/networks@^5.7.0":
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6"
|
||||
integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/pbkdf2@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102"
|
||||
integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/sha2" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/properties@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30"
|
||||
integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==
|
||||
dependencies:
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]":
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb"
|
||||
integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-provider" "^5.7.0"
|
||||
"@ethersproject/abstract-signer" "^5.7.0"
|
||||
"@ethersproject/address" "^5.7.0"
|
||||
"@ethersproject/base64" "^5.7.0"
|
||||
"@ethersproject/basex" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/hash" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/networks" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/random" "^5.7.0"
|
||||
"@ethersproject/rlp" "^5.7.0"
|
||||
"@ethersproject/sha2" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
"@ethersproject/web" "^5.7.0"
|
||||
bech32 "1.1.4"
|
||||
ws "7.4.6"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/random@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c"
|
||||
integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/rlp@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304"
|
||||
integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/sha2@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb"
|
||||
integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
hash.js "1.1.7"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/signing-key@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3"
|
||||
integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
bn.js "^5.2.1"
|
||||
elliptic "6.5.4"
|
||||
hash.js "1.1.7"
|
||||
|
||||
"@ethersproject/[email protected]":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8"
|
||||
integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/keccak256" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/sha2" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/strings@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2"
|
||||
integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/transactions@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b"
|
||||
integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==
|
||||
dependencies:
|
||||
"@ethersproject/address" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/keccak256" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/rlp" "^5.7.0"
|
||||
"@ethersproject/signing-key" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1"
|
||||
integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==
|
||||
dependencies:
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/constants" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d"
|
||||
integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==
|
||||
dependencies:
|
||||
"@ethersproject/abstract-provider" "^5.7.0"
|
||||
"@ethersproject/abstract-signer" "^5.7.0"
|
||||
"@ethersproject/address" "^5.7.0"
|
||||
"@ethersproject/bignumber" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/hash" "^5.7.0"
|
||||
"@ethersproject/hdnode" "^5.7.0"
|
||||
"@ethersproject/json-wallets" "^5.7.0"
|
||||
"@ethersproject/keccak256" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/random" "^5.7.0"
|
||||
"@ethersproject/signing-key" "^5.7.0"
|
||||
"@ethersproject/transactions" "^5.7.0"
|
||||
"@ethersproject/wordlists" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/web@^5.7.0":
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae"
|
||||
integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==
|
||||
dependencies:
|
||||
"@ethersproject/base64" "^5.7.0"
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@ethersproject/[email protected]", "@ethersproject/wordlists@^5.7.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5"
|
||||
integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==
|
||||
dependencies:
|
||||
"@ethersproject/bytes" "^5.7.0"
|
||||
"@ethersproject/hash" "^5.7.0"
|
||||
"@ethersproject/logger" "^5.7.0"
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@fastify/busboy@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8"
|
||||
@@ -6944,6 +7301,11 @@ acorn@^8.8.0:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
|
||||
integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
|
||||
|
||||
[email protected]:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d"
|
||||
integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==
|
||||
|
||||
aes-js@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a"
|
||||
@@ -7207,9 +7569,9 @@ axe-core@^4.4.3:
|
||||
integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==
|
||||
|
||||
axios@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f"
|
||||
integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
|
||||
integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
@@ -7330,6 +7692,11 @@ base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
[email protected]:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
|
||||
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
|
||||
|
||||
bigint-buffer@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442"
|
||||
@@ -7378,7 +7745,12 @@ blo@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/blo/-/blo-1.1.1.tgz#ed781c5c516fba484ec8ec86105dc27f6c553209"
|
||||
integrity sha512-1uGZInlRD4X1WQP2G1QjDGwGZ8HdGgFKqnzyRdA2TYYc0MOQCmCi37RTQ8oJuI0UF6DYFKXHwV/t1kZkO/fTaA==
|
||||
|
||||
bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.2.0:
|
||||
bn.js@^4.11.9:
|
||||
version "4.12.0"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
|
||||
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
|
||||
|
||||
bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.2.0, bn.js@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
|
||||
integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
|
||||
@@ -7419,6 +7791,11 @@ braces@^3.0.2, braces@~3.0.2:
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
brorand@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||
integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
|
||||
|
||||
browserslist@^4.21.3, browserslist@^4.21.4:
|
||||
version "4.21.4"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987"
|
||||
@@ -7543,7 +7920,7 @@ chakra-react-select@^4.4.3:
|
||||
dependencies:
|
||||
react-select "5.7.0"
|
||||
|
||||
chalk@^2.0.0:
|
||||
chalk@^2.0.0, chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
@@ -7872,10 +8249,10 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypto-js@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf"
|
||||
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
|
||||
crypto-js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
|
||||
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
|
||||
|
||||
[email protected]:
|
||||
version "1.2.1"
|
||||
@@ -8220,6 +8597,15 @@ damerau-levenshtein@^1.0.8:
|
||||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
|
||||
integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
|
||||
|
||||
dappscout-iframe@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dappscout-iframe/-/dappscout-iframe-0.1.0.tgz#c971d8a8aa4fb3d64ca357700d3ac809dcdecb0d"
|
||||
integrity sha512-nL65Uuv2+r2ujELyBtw+VL6PYkUtleCvKi2XaeMiroZz6tieeUw338PEOc6cZaIfwXk59rFwNR0FZki2HnOrIA==
|
||||
dependencies:
|
||||
ethers "^5.7.2"
|
||||
react "^18.2.0"
|
||||
react-dom "^18.2.0"
|
||||
|
||||
data-uri-to-buffer@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
|
||||
@@ -8244,7 +8630,7 @@ dayjs@^1.11.5:
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
|
||||
integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
|
||||
|
||||
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
|
||||
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
@@ -8534,6 +8920,19 @@ electron-to-chromium@^1.4.251:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.276.tgz#17837b19dafcc43aba885c4689358b298c19b520"
|
||||
integrity sha512-EpuHPqu8YhonqLBXHoU6hDJCD98FCe6KDoet3/gY1qsQ6usjJoHqBH2YIVs8FXaAtHwVL8Uqa/fsYao/vq9VWQ==
|
||||
|
||||
[email protected]:
|
||||
version "6.5.4"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
|
||||
integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
|
||||
dependencies:
|
||||
bn.js "^4.11.9"
|
||||
brorand "^1.1.0"
|
||||
hash.js "^1.0.0"
|
||||
hmac-drbg "^1.0.1"
|
||||
inherits "^2.0.4"
|
||||
minimalistic-assert "^1.0.1"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
emittery@^0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"
|
||||
@@ -9143,6 +9542,42 @@ ethereum-cryptography@^2.0.0:
|
||||
"@scure/bip32" "1.3.1"
|
||||
"@scure/bip39" "1.2.1"
|
||||
|
||||
ethers@^5.7.2:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
|
||||
integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "5.7.0"
|
||||
"@ethersproject/abstract-provider" "5.7.0"
|
||||
"@ethersproject/abstract-signer" "5.7.0"
|
||||
"@ethersproject/address" "5.7.0"
|
||||
"@ethersproject/base64" "5.7.0"
|
||||
"@ethersproject/basex" "5.7.0"
|
||||
"@ethersproject/bignumber" "5.7.0"
|
||||
"@ethersproject/bytes" "5.7.0"
|
||||
"@ethersproject/constants" "5.7.0"
|
||||
"@ethersproject/contracts" "5.7.0"
|
||||
"@ethersproject/hash" "5.7.0"
|
||||
"@ethersproject/hdnode" "5.7.0"
|
||||
"@ethersproject/json-wallets" "5.7.0"
|
||||
"@ethersproject/keccak256" "5.7.0"
|
||||
"@ethersproject/logger" "5.7.0"
|
||||
"@ethersproject/networks" "5.7.1"
|
||||
"@ethersproject/pbkdf2" "5.7.0"
|
||||
"@ethersproject/properties" "5.7.0"
|
||||
"@ethersproject/providers" "5.7.2"
|
||||
"@ethersproject/random" "5.7.0"
|
||||
"@ethersproject/rlp" "5.7.0"
|
||||
"@ethersproject/sha2" "5.7.0"
|
||||
"@ethersproject/signing-key" "5.7.0"
|
||||
"@ethersproject/solidity" "5.7.0"
|
||||
"@ethersproject/strings" "5.7.0"
|
||||
"@ethersproject/transactions" "5.7.0"
|
||||
"@ethersproject/units" "5.7.0"
|
||||
"@ethersproject/wallet" "5.7.0"
|
||||
"@ethersproject/web" "5.7.1"
|
||||
"@ethersproject/wordlists" "5.7.0"
|
||||
|
||||
event-target-shim@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
||||
@@ -9763,10 +10198,10 @@ graphql-ws@^5.11.3:
|
||||
resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.11.3.tgz#eaf8e6baf669d167975cff13ad86abca4ecfe82f"
|
||||
integrity sha512-fU8zwSgAX2noXAsuFiCZ8BtXeXZOzXyK5u1LloCdacsVth4skdBMPO74EG51lBoWSIZ8beUocdpV8+cQHBODnQ==
|
||||
|
||||
graphql@^16.6.0:
|
||||
version "16.6.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb"
|
||||
integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==
|
||||
graphql@^16.8.1:
|
||||
version "16.8.1"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
|
||||
integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
|
||||
|
||||
gzip-size@^6.0.0:
|
||||
version "6.0.0"
|
||||
@@ -9821,7 +10256,7 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hash.js@^1.1.7:
|
||||
[email protected], hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
|
||||
integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
|
||||
@@ -9880,6 +10315,15 @@ highlight.js@^10.4.1, highlight.js@~10.7.0:
|
||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
||||
integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
|
||||
|
||||
hmac-drbg@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
||||
integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==
|
||||
dependencies:
|
||||
hash.js "^1.0.3"
|
||||
minimalistic-assert "^1.0.0"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
@@ -10850,6 +11294,11 @@ js-sdsl@^4.1.4:
|
||||
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0"
|
||||
integrity sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==
|
||||
|
||||
[email protected]:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
|
||||
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
@@ -11370,11 +11819,16 @@ minim@~0.23.8:
|
||||
dependencies:
|
||||
lodash "^4.15.0"
|
||||
|
||||
minimalistic-assert@^1.0.1:
|
||||
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
|
||||
integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
|
||||
|
||||
minimalistic-crypto-utils@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
|
||||
integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
|
||||
|
||||
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
@@ -11482,16 +11936,16 @@ nan@^2.14.0, nan@^2.14.1, nan@^2.17.0:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
|
||||
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
|
||||
|
||||
nanoid@^3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
||||
|
||||
nanoid@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
|
||||
nanoid@^3.3.7:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
napi-build-utils@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
|
||||
@@ -12227,21 +12681,12 @@ [email protected]:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8.4.19:
|
||||
version "8.4.21"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
|
||||
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
|
||||
postcss@^8.4.19, postcss@^8.4.23:
|
||||
version "8.4.32"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.32.tgz#1dac6ac51ab19adb21b8b34fd2d93a86440ef6c9"
|
||||
integrity sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==
|
||||
dependencies:
|
||||
nanoid "^3.3.4"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8.4.23:
|
||||
version "8.4.24"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df"
|
||||
integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==
|
||||
dependencies:
|
||||
nanoid "^3.3.6"
|
||||
nanoid "^3.3.7"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
@@ -12617,7 +13062,7 @@ react-device-detect@^2.2.3:
|
||||
dependencies:
|
||||
ua-parser-js "^1.0.33"
|
||||
|
||||
[email protected]:
|
||||
[email protected], react-dom@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
@@ -12813,7 +13258,7 @@ [email protected]:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
[email protected]:
|
||||
[email protected], react@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
@@ -13242,6 +13687,11 @@ scheduler@^0.23.0:
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
[email protected]:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312"
|
||||
integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==
|
||||
|
||||
scslre@^0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/scslre/-/scslre-0.1.6.tgz#71a2832e4bf3a9254973a04fbed90aec94f75757"
|
||||
@@ -14566,9 +15016,9 @@ which@^2.0.1, which@^2.0.2:
|
||||
isexe "^2.0.0"
|
||||
|
||||
word-wrap@^1.2.3, word-wrap@~1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
|
||||
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
||||
|
||||
wrap-ansi@^6.2.0:
|
||||
version "6.2.0"
|
||||
@@ -14601,6 +15051,11 @@ write-file-atomic@^4.0.1:
|
||||
imurmurhash "^0.1.4"
|
||||
signal-exit "^3.0.7"
|
||||
|
||||
[email protected]:
|
||||
version "7.4.6"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
|
||||
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
|
||||
|
||||
[email protected], ws@^8.5.0:
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8"
|
||||
|
||||