From a9a639d82996f54986add04a70d0c9fd19877b68 Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Fri, 22 Nov 2024 14:04:54 +0100 Subject: [PATCH 01/92] [Human App] feat: implement loading state on resign btn for a specific job (#2800) --- .../jobs/components/my-jobs-table-actions.tsx | 47 ++++++++++++++++++ .../my-jobs/desktop/my-jobs-table.tsx | 48 ++++--------------- .../my-jobs/mobile/my-jobs-table-mobile.tsx | 32 ++----------- 3 files changed, 58 insertions(+), 69 deletions(-) create mode 100644 packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx new file mode 100644 index 0000000000..c29fa9a14f --- /dev/null +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx @@ -0,0 +1,47 @@ +/* eslint-disable camelcase -- ...*/ +import { Link, useParams } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { useRejectTaskMutation } from '@/api/services/worker/reject-task'; +import { TableButton } from '@/components/ui/table-button'; +import { RejectButton } from '@/pages/worker/jobs/components/reject-button'; +import type { MyJob } from '@/api/services/worker/my-jobs-data'; + +interface MyJobsTableRejectActionProps { + job: MyJob; +} + +export function MyJobsTableActions({ job }: MyJobsTableRejectActionProps) { + const { t } = useTranslation(); + const { mutate: rejectTaskMutation, isPending: isRejectPending } = + useRejectTaskMutation(); + const { address: oracleAddress } = useParams<{ address: string }>(); + const buttonDisabled = job.status !== 'active' || isRejectPending; + + if (!job.url) { + return null; + } + + return ( + <> + + {t('worker.jobs.solve')} + + { + rejectTaskMutation({ + oracle_address: oracleAddress ?? '', + assignment_id: job.assignment_id, + }); + }} + /> + + ); +} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx index 1a5432e0cb..a6b44d0684 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx @@ -2,7 +2,7 @@ import { t } from 'i18next'; import { useEffect, useMemo, useState } from 'react'; import Grid from '@mui/material/Grid'; -import { Link, useParams } from 'react-router-dom'; +import { useParams } from 'react-router-dom'; import { MaterialReactTable, useMaterialReactTable, @@ -27,22 +27,18 @@ import { MyJobsRewardAmountSort } from '@/pages/worker/jobs/components/my-jobs/d import { MyJobsStatusFilter } from '@/pages/worker/jobs/components/my-jobs/desktop/my-jobs-status-filter'; import { MyJobsExpiresAtSort } from '@/pages/worker/jobs/components/my-jobs/desktop/my-jobs-expires-at-sort'; import { MyJobsNetworkFilter } from '@/pages/worker/jobs/components/my-jobs/desktop/my-jobs-network-filter'; -import { TableButton } from '@/components/ui/table-button'; -import { useRejectTaskMutation } from '@/api/services/worker/reject-task'; -import { RejectButton } from '@/pages/worker/jobs/components/reject-button'; import { useColorMode } from '@/hooks/use-color-mode'; import { createTableDarkMode } from '@/styles/create-table-dark-mode'; import { colorPalette as lightModeColorPalette } from '@/styles/color-palette'; import type { JobType } from '@/smart-contracts/EthKVStore/config'; import { EscrowAddressSearchForm } from '@/pages/worker/jobs/components/escrow-address-search-form'; import { useRefreshTasksMutation } from '@/api/services/worker/refresh-tasks'; +import { MyJobsTableActions } from '../../my-jobs-table-actions'; const getColumnsDefinition = ({ - resignJob, refreshData, isRefreshTasksPending, }: { - resignJob: (assignment_id: string) => void; refreshData: () => void; isRefreshTasksPending: boolean; }): MRT_ColumnDef[] => [ @@ -186,33 +182,11 @@ const getColumnsDefinition = ({ header: t('worker.jobs.refresh'), size: 100, enableSorting: true, - Cell: (props) => { - const { url, assignment_id, status } = props.row.original; - const buttonDisabled = status !== 'active'; - return ( - - {url ? ( - <> - - {t('worker.jobs.solve')} - - { - if (buttonDisabled) return; - resignJob(assignment_id); - }} - /> - - ) : null} - - ); - }, + Cell: (props) => ( + + + + ), muiTableHeadCellProps: () => ({ component: (props) => { return ( @@ -257,12 +231,12 @@ export function MyJobsTable() { resetFilterParams, } = useMyJobsFilterStore(); const { data: tableData, status: tableStatus } = useGetMyJobsData(); + const memoizedTableDataResults = useMemo( () => tableData?.results ?? [], [tableData?.results] ); - const { mutate: rejectTaskMutation } = useRejectTaskMutation(); const { mutate: refreshTasksMutation, isPending: isRefreshTasksPending } = useRefreshTasksMutation(); const { address: oracle_address } = useParams<{ address: string }>(); @@ -272,11 +246,6 @@ export function MyJobsTable() { pageSize: 5, }); - const rejectTask = (address: string) => { - return (assignment_id: string) => { - rejectTaskMutation({ oracle_address: address, assignment_id }); - }; - }; const refreshTasks = (address: string) => { return () => { refreshTasksMutation({ oracle_address: address }); @@ -303,7 +272,6 @@ export function MyJobsTable() { const table = useMaterialReactTable({ columns: getColumnsDefinition({ - resignJob: rejectTask(oracle_address ?? ''), refreshData: refreshTasks(oracle_address ?? ''), isRefreshTasksPending, }), diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx index 955eea2e03..545413c5ae 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx @@ -2,17 +2,14 @@ import { Grid, List, Paper, Stack, Typography } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { useEffect, useState, type Dispatch, type SetStateAction } from 'react'; -import { Link, useParams } from 'react-router-dom'; +import { useParams } from 'react-router-dom'; import { Button } from '@/components/ui/button'; import { FiltersButtonIcon, RefreshIcon } from '@/components/ui/icons'; import { formatDate } from '@/shared/helpers/format-date'; import { Loader } from '@/components/ui/loader'; import { Alert } from '@/components/ui/alert'; import { getNetworkName } from '@/smart-contracts/get-network-name'; -import { TableButton } from '@/components/ui/table-button'; import { useJobsFilterStore } from '@/hooks/use-jobs-filter-store'; -import { RejectButton } from '@/pages/worker/jobs/components/reject-button'; -import { useRejectTaskMutation } from '@/api/services/worker/reject-task'; import type { MyJob } from '@/api/services/worker/my-jobs-data'; import { useInfiniteGetMyJobsData } from '@/api/services/worker/my-jobs-data'; import { defaultErrorMessage } from '@/shared/helpers/default-error-message'; @@ -26,6 +23,7 @@ import type { JobType } from '@/smart-contracts/EthKVStore/config'; import { EscrowAddressSearchForm } from '@/pages/worker/jobs/components/escrow-address-search-form'; import { colorPalette as lightModeColorPalette } from '@/styles/color-palette'; import { useRefreshTasksMutation } from '@/api/services/worker/refresh-tasks'; +import { MyJobsTableActions } from '../../my-jobs-table-actions'; interface MyJobsTableMobileProps { setIsMobileFilterDrawerOpen: Dispatch>; @@ -49,7 +47,6 @@ export function MyJobsTableMobile({ hasNextPage, } = useInfiniteGetMyJobsData(); - const { mutate: rejectTaskMutation } = useRejectTaskMutation(); const { mutate: refreshTasksMutation, isPending: isRefreshTasksPending } = useRefreshTasksMutation(); const { setSearchEscrowAddress } = useJobsFilterStore(); @@ -132,7 +129,6 @@ export function MyJobsTableMobile({ ) : null} {allPages.map((d) => { - const buttonDisabled = d.status !== 'active'; return ( - {d.url ? ( - <> - - {t('worker.jobs.solve')} - - { - if (buttonDisabled) return; - rejectTaskMutation({ - oracle_address: oracle_address ?? '', - assignment_id: d.assignment_id, - }); - }} - /> - - ) : null} + From 44638af2f7ec42c3b8c7d3b15b31f49a46aefa3a Mon Sep 17 00:00:00 2001 From: Arseny Boykov <36469655+Bobronium@users.noreply.github.com> Date: Fri, 22 Nov 2024 20:00:46 +0100 Subject: [PATCH 02/92] [Exchange Oracle] Add `iou_threshold` for polygon tasks and enable single shape mode (#2832) * [Exchange Oracle] Add PolygonTaskBuilder * [Exchange Oracle] Enable single shape mode for polygons * [Exchange Oracle] Move iou_threshold to cvat config * [Exchange Oracle] Add CVAT_QUALITY_RETRIEVAL_TIMEOUT to .env.template * Fix the env variable name Co-authored-by: Maxim Zhiltsov --------- Co-authored-by: Maxim Zhiltsov --- .../cvat/exchange-oracle/src/.env.template | 1 + .../cvat/exchange-oracle/src/core/config.py | 3 +++ .../exchange-oracle/src/handlers/job_creation.py | 14 +++++++++----- .../cvat/exchange-oracle/src/utils/assignments.py | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/examples/cvat/exchange-oracle/src/.env.template b/packages/examples/cvat/exchange-oracle/src/.env.template index e05b60cf0d..dcaf62111f 100644 --- a/packages/examples/cvat/exchange-oracle/src/.env.template +++ b/packages/examples/cvat/exchange-oracle/src/.env.template @@ -77,6 +77,7 @@ CVAT_IOU_THRESHOLD= CVAT_OKS_SIGMA= CVAT_EXPORT_TIMEOUT= CVAT_IMPORT_TIMEOUT= +CVAT_POLYGONS_IOU_THRESHOLD= # Storage Config (S3/GCS) diff --git a/packages/examples/cvat/exchange-oracle/src/core/config.py b/packages/examples/cvat/exchange-oracle/src/core/config.py index 7bd41e0624..efd4b9c848 100644 --- a/packages/examples/cvat/exchange-oracle/src/core/config.py +++ b/packages/examples/cvat/exchange-oracle/src/core/config.py @@ -195,6 +195,9 @@ class CvatConfig: cvat_iou_threshold = float(os.environ.get("CVAT_IOU_THRESHOLD", 0.8)) cvat_oks_sigma = float(os.environ.get("CVAT_OKS_SIGMA", 0.1)) + cvat_polygons_iou_threshold = float(os.environ.get("CVAT_POLYGONS_IOU_THRESHOLD", 0.5)) + "`iou_threshold` parameter for quality settings in polygons tasks" + cvat_incoming_webhooks_url = os.environ.get("CVAT_INCOMING_WEBHOOKS_URL") cvat_webhook_secret = os.environ.get("CVAT_WEBHOOK_SECRET", "thisisasamplesecret") diff --git a/packages/examples/cvat/exchange-oracle/src/handlers/job_creation.py b/packages/examples/cvat/exchange-oracle/src/handlers/job_creation.py index c97102d4d1..2385d00774 100644 --- a/packages/examples/cvat/exchange-oracle/src/handlers/job_creation.py +++ b/packages/examples/cvat/exchange-oracle/src/handlers/job_creation.py @@ -550,6 +550,12 @@ def build(self): return super().build() +class PolygonTaskBuilder(SimpleTaskBuilder): + def _setup_quality_settings(self, task_id: int, **overrides) -> None: + values = {"iou_threshold": Config.cvat_config.cvat_polygons_iou_threshold, **overrides} + super()._setup_quality_settings(task_id, **values) + + class BoxesFromPointsTaskBuilder(_TaskBuilderBase): def __init__(self, manifest: TaskManifest, escrow_address: str, chain_id: int) -> None: super().__init__(manifest=manifest, escrow_address=escrow_address, chain_id=chain_id) @@ -2836,12 +2842,10 @@ def create_task(escrow_address: str, chain_id: int) -> None: manifest = parse_manifest(get_escrow_manifest(chain_id, escrow_address)) - if manifest.annotation.type in [ - TaskTypes.image_boxes, - TaskTypes.image_label_binary, - TaskTypes.image_polygons, - ]: + if manifest.annotation.type in [TaskTypes.image_boxes, TaskTypes.image_label_binary]: builder_type = SimpleTaskBuilder + elif manifest.annotation.type is TaskTypes.image_polygons: + builder_type = PolygonTaskBuilder elif manifest.annotation.type in [TaskTypes.image_points]: builder_type = PointsTaskBuilder elif manifest.annotation.type in [TaskTypes.image_boxes_from_points]: diff --git a/packages/examples/cvat/exchange-oracle/src/utils/assignments.py b/packages/examples/cvat/exchange-oracle/src/utils/assignments.py index 70f48bba85..ceeebfc150 100644 --- a/packages/examples/cvat/exchange-oracle/src/utils/assignments.py +++ b/packages/examples/cvat/exchange-oracle/src/utils/assignments.py @@ -17,6 +17,7 @@ def compose_assignment_url(task_id: int, job_id: int, *, project: Project) -> st TaskTypes.image_skeletons_from_boxes, TaskTypes.image_boxes_from_points, TaskTypes.image_points, + TaskTypes.image_polygons, ]: query_params = "?defaultWorkspace=single_shape" From 6fd2bc96af291540a7a36ad146b0dc3a465d1d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:40:32 +0100 Subject: [PATCH 03/92] Remove unused fields from job details (#2836) --- .../client/src/pages/Job/JobDetail/index.tsx | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx index 587a61e53c..544dc98057 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx @@ -137,8 +137,6 @@ export default function JobDetail() { label="Paid Out HMT" value={`${data.details.paidOut.toString()} HMT`} /> - - @@ -198,21 +196,25 @@ export default function JobDetail() { value={data.manifest.submissionsRequired} /> - + + - - - From 1887cb080ca360aa775722dbb3bfb3bd3c4c32dd Mon Sep 17 00:00:00 2001 From: KacperKoza343 <165884432+KacperKoza343@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:42:36 +0100 Subject: [PATCH 04/92] [Human App] feat: adjust status chip colors on my jobs table (#2734) --- .../src/api/services/worker/my-jobs-data.ts | 19 +++++++++++- .../src/hooks/use-jobs-filter-store.tsx | 11 ++----- .../src/hooks/use-my-jobs-filter-store.tsx | 14 ++------- .../desktop/available-jobs-status-filter.tsx | 30 ------------------- .../available-jobs-status-filter-mobile.tsx | 4 +-- .../worker/jobs/components/drawer-mobile.tsx | 7 +++-- .../jobs/components/my-jobs-table-actions.tsx | 4 +-- .../my-jobs/desktop/my-jobs-button.tsx | 19 ------------ .../my-jobs/desktop/my-jobs-status-filter.tsx | 8 ++--- .../my-jobs/desktop/my-jobs-table.tsx | 21 ++----------- .../mobile/my-jobs-status-filter-mobile.tsx | 8 ++--- .../my-jobs/mobile/my-jobs-table-mobile.tsx | 6 +++- .../worker/jobs/components/status-chip.tsx | 28 +++++++++++++++++ .../jobs/helpers/get-chip-status-color.ts | 21 +++++++++++++ 14 files changed, 93 insertions(+), 107 deletions(-) delete mode 100644 packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-status-filter.tsx delete mode 100644 packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-button.tsx create mode 100644 packages/apps/human-app/frontend/src/pages/worker/jobs/components/status-chip.tsx create mode 100644 packages/apps/human-app/frontend/src/pages/worker/jobs/helpers/get-chip-status-color.ts diff --git a/packages/apps/human-app/frontend/src/api/services/worker/my-jobs-data.ts b/packages/apps/human-app/frontend/src/api/services/worker/my-jobs-data.ts index 4bb0c5e2f2..139541950c 100644 --- a/packages/apps/human-app/frontend/src/api/services/worker/my-jobs-data.ts +++ b/packages/apps/human-app/frontend/src/api/services/worker/my-jobs-data.ts @@ -9,12 +9,29 @@ import { createPaginationSchema } from '@/shared/helpers/create-pagination-schem import type { MyJobsFilterStoreProps } from '@/hooks/use-my-jobs-filter-store'; import { useMyJobsFilterStore } from '@/hooks/use-my-jobs-filter-store'; +export enum MyJobStatus { + ACTIVE = 'ACTIVE', + CANCELED = 'CANCELED', + COMPLETED = 'COMPLETED', + VALIDATION = 'VALIDATION', + EXPIRED = 'EXPIRED', + REJECTED = 'REJECTED', +} + +export const UNKNOWN_JOB_STATUS = 'UNKNOWN'; + const myJobSchema = z.object({ assignment_id: z.string(), escrow_address: z.string(), chain_id: z.number(), job_type: z.string(), - status: z.string(), + status: z.string().transform((value) => { + try { + return z.nativeEnum(MyJobStatus).parse(value.toUpperCase()); + } catch (error) { + return UNKNOWN_JOB_STATUS; + } + }), reward_amount: z.string(), reward_token: z.string(), created_at: z.string(), diff --git a/packages/apps/human-app/frontend/src/hooks/use-jobs-filter-store.tsx b/packages/apps/human-app/frontend/src/hooks/use-jobs-filter-store.tsx index b515257f48..30c2652078 100644 --- a/packages/apps/human-app/frontend/src/hooks/use-jobs-filter-store.tsx +++ b/packages/apps/human-app/frontend/src/hooks/use-jobs-filter-store.tsx @@ -1,6 +1,7 @@ /* eslint-disable camelcase -- api params*/ import { create } from 'zustand'; import type { PageSize } from '@/shared/types/entity.type'; +import { MyJobStatus } from '@/api/services/worker/my-jobs-data'; export interface JobsFilterStoreProps { filterParams: { @@ -14,13 +15,7 @@ export interface JobsFilterStoreProps { network?: 'MATIC' | 'POLYGON'; // TODO add allowed job types job_type?: string; - status?: - | 'active' - | 'completed' - | 'canceled' - | 'validation' - | 'expired' - | 'rejected'; + status?: MyJobStatus; escrow_address?: string; page: number; page_size: PageSize; @@ -40,7 +35,7 @@ const initialFiltersState = { page: 0, page_size: 5, fields: ['reward_amount', 'job_description', 'reward_token'], - status: 'active', + status: MyJobStatus.ACTIVE, escrow_address: '', } satisfies Pick< JobsFilterStoreProps['filterParams'], diff --git a/packages/apps/human-app/frontend/src/hooks/use-my-jobs-filter-store.tsx b/packages/apps/human-app/frontend/src/hooks/use-my-jobs-filter-store.tsx index 6d657af15a..35ad37e526 100644 --- a/packages/apps/human-app/frontend/src/hooks/use-my-jobs-filter-store.tsx +++ b/packages/apps/human-app/frontend/src/hooks/use-my-jobs-filter-store.tsx @@ -1,17 +1,7 @@ /* eslint-disable camelcase -- api params*/ import { create } from 'zustand'; import type { PageSize } from '@/shared/types/entity.type'; - -export const jobStatuses = [ - 'active', - 'completed', - 'canceled', - 'validation', - 'expired', - 'rejected', -] as const; - -type JobStatus = (typeof jobStatuses)[number]; +import { type MyJobStatus } from '@/api/services/worker/my-jobs-data'; export interface MyJobsFilterStoreProps { filterParams: { @@ -23,7 +13,7 @@ export interface MyJobsFilterStoreProps { | 'expires_at' | 'created_at'; job_type?: string; - status?: JobStatus; + status?: MyJobStatus; escrow_address?: string; page: number; page_size: PageSize; diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-status-filter.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-status-filter.tsx deleted file mode 100644 index 3f215b22b1..0000000000 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-status-filter.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import capitalize from 'lodash/capitalize'; -import { jobStatuses } from '@/hooks/use-my-jobs-filter-store'; -import { Filtering } from '@/components/ui/table/table-header-menu.tsx/filtering'; -import { useJobsFilterStore } from '@/hooks/use-jobs-filter-store'; - -export function AvailableJobsStatusFilter() { - const { setFilterParams, filterParams } = useJobsFilterStore(); - - return ( - { - setFilterParams({ - ...filterParams, - status: undefined, - }); - }} - filteringOptions={jobStatuses.map((status) => ({ - name: capitalize(status), - option: status, - }))} - isChecked={(status) => status === filterParams.status} - setFiltering={(status) => { - setFilterParams({ - ...filterParams, - status, - }); - }} - /> - ); -} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx index efcb13c5d7..af413edd7b 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx @@ -1,7 +1,7 @@ import capitalize from 'lodash/capitalize'; -import { jobStatuses } from '@/hooks/use-my-jobs-filter-store'; import { Filtering } from '@/components/ui/table/table-header-menu.tsx/filtering'; import { useJobsFilterStore } from '@/hooks/use-jobs-filter-store'; +import { MyJobStatus } from '@/api/services/worker/my-jobs-data'; export function AvailableJobsStatusFilterMobile() { const { setFilterParams, filterParams } = useJobsFilterStore(); @@ -15,7 +15,7 @@ export function AvailableJobsStatusFilterMobile() { page: 0, }); }} - filteringOptions={jobStatuses.map((status) => ({ + filteringOptions={Object.values(MyJobStatus).map((status) => ({ name: capitalize(status), option: status, }))} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx index e7beecfb3c..9e4e88ce71 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx @@ -20,6 +20,7 @@ import { AvailableJobsNetworkFilterMobile } from '@/pages/worker/jobs/components import { AvailableJobsStatusFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile'; import { AvailableJobsJobTypeFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-job-type-filter-mobile'; import { useColorMode } from '@/hooks/use-color-mode'; +import { MyJobStatus } from '@/api/services/worker/my-jobs-data'; interface DrawerMobileProps { selectedTab: string; @@ -226,7 +227,7 @@ export function DrawerMobile({ key={crypto.randomUUID()} > { handleCheckboxClick('status', 'validation'); }} @@ -241,7 +242,7 @@ export function DrawerMobile({ key={crypto.randomUUID()} > { handleCheckboxClick('status', 'expired'); }} @@ -256,7 +257,7 @@ export function DrawerMobile({ key={crypto.randomUUID()} > { handleCheckboxClick('status', 'rejected'); }} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx index c29fa9a14f..57c45c6170 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import { useRejectTaskMutation } from '@/api/services/worker/reject-task'; import { TableButton } from '@/components/ui/table-button'; import { RejectButton } from '@/pages/worker/jobs/components/reject-button'; -import type { MyJob } from '@/api/services/worker/my-jobs-data'; +import { MyJobStatus, type MyJob } from '@/api/services/worker/my-jobs-data'; interface MyJobsTableRejectActionProps { job: MyJob; @@ -15,7 +15,7 @@ export function MyJobsTableActions({ job }: MyJobsTableRejectActionProps) { const { mutate: rejectTaskMutation, isPending: isRejectPending } = useRejectTaskMutation(); const { address: oracleAddress } = useParams<{ address: string }>(); - const buttonDisabled = job.status !== 'active' || isRejectPending; + const buttonDisabled = job.status !== MyJobStatus.ACTIVE || isRejectPending; if (!job.url) { return null; diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-button.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-button.tsx deleted file mode 100644 index 5fcb335055..0000000000 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-button.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useTranslation } from 'react-i18next'; -import { TableButton } from '@/components/ui/table-button'; - -interface MyJobsButtonProps { - status: string; -} - -export function MyJobsButton({ status }: MyJobsButtonProps) { - // TODO add correct implementation depending on job status - const { t } = useTranslation(); - if (status === 'resign') { - return {t('worker.jobs.resign')}; - } - if (status === 'active') { - return {t('worker.jobs.solve')}; - } - - return {t('worker.jobs.solve')}; -} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-status-filter.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-status-filter.tsx index 30d501227e..a0f3d9ba43 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-status-filter.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-status-filter.tsx @@ -1,9 +1,7 @@ import capitalize from 'lodash/capitalize'; -import { - jobStatuses, - useMyJobsFilterStore, -} from '@/hooks/use-my-jobs-filter-store'; +import { useMyJobsFilterStore } from '@/hooks/use-my-jobs-filter-store'; import { Filtering } from '@/components/ui/table/table-header-menu.tsx/filtering'; +import { MyJobStatus } from '@/api/services/worker/my-jobs-data'; export function MyJobsStatusFilter() { const { setFilterParams, filterParams } = useMyJobsFilterStore(); @@ -16,7 +14,7 @@ export function MyJobsStatusFilter() { status: undefined, }); }} - filteringOptions={jobStatuses.map((status) => ({ + filteringOptions={Object.values(MyJobStatus).map((status) => ({ name: capitalize(status), option: status, }))} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx index a6b44d0684..8b664a8411 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-table.tsx @@ -8,7 +8,6 @@ import { useMaterialReactTable, type MRT_ColumnDef, } from 'material-react-table'; -import { Box, Typography } from '@mui/material'; import RefreshIcon from '@mui/icons-material/Refresh'; import { TableHeaderCell } from '@/components/ui/table/table-header-cell'; import { @@ -29,10 +28,10 @@ import { MyJobsExpiresAtSort } from '@/pages/worker/jobs/components/my-jobs/desk import { MyJobsNetworkFilter } from '@/pages/worker/jobs/components/my-jobs/desktop/my-jobs-network-filter'; import { useColorMode } from '@/hooks/use-color-mode'; import { createTableDarkMode } from '@/styles/create-table-dark-mode'; -import { colorPalette as lightModeColorPalette } from '@/styles/color-palette'; import type { JobType } from '@/smart-contracts/EthKVStore/config'; import { EscrowAddressSearchForm } from '@/pages/worker/jobs/components/escrow-address-search-form'; import { useRefreshTasksMutation } from '@/api/services/worker/refresh-tasks'; +import { StatusChip } from '@/pages/worker/jobs/components/status-chip'; import { MyJobsTableActions } from '../../my-jobs-table-actions'; const getColumnsDefinition = ({ @@ -146,23 +145,7 @@ const getColumnsDefinition = ({ enableSorting: true, Cell: (props) => { const status = props.row.original.status; - return ( - - - {status} - - - ); + return ; }, muiTableHeadCellProps: () => ({ component: (props) => { diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-status-filter-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-status-filter-mobile.tsx index 9019ef364e..ebf5706735 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-status-filter-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-status-filter-mobile.tsx @@ -1,9 +1,7 @@ import capitalize from 'lodash/capitalize'; -import { - jobStatuses, - useMyJobsFilterStore, -} from '@/hooks/use-my-jobs-filter-store'; +import { useMyJobsFilterStore } from '@/hooks/use-my-jobs-filter-store'; import { Filtering } from '@/components/ui/table/table-header-menu.tsx/filtering'; +import { MyJobStatus } from '@/api/services/worker/my-jobs-data'; export function MyJobsStatusFilterMobile() { const { setFilterParams, filterParams } = useMyJobsFilterStore(); @@ -17,7 +15,7 @@ export function MyJobsStatusFilterMobile() { page: 0, }); }} - filteringOptions={jobStatuses.map((status) => ({ + filteringOptions={Object.values(MyJobStatus).map((status) => ({ name: capitalize(status), option: status, }))} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx index 545413c5ae..5434d9b395 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-table-mobile.tsx @@ -23,6 +23,7 @@ import type { JobType } from '@/smart-contracts/EthKVStore/config'; import { EscrowAddressSearchForm } from '@/pages/worker/jobs/components/escrow-address-search-form'; import { colorPalette as lightModeColorPalette } from '@/styles/color-palette'; import { useRefreshTasksMutation } from '@/api/services/worker/refresh-tasks'; +import { getChipStatusColor } from '@/pages/worker/jobs/helpers/get-chip-status-color'; import { MyJobsTableActions } from '../../my-jobs-table-actions'; interface MyJobsTableMobileProps { @@ -170,7 +171,10 @@ export function MyJobsTableMobile({ + + {status} + + + ); +} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/helpers/get-chip-status-color.ts b/packages/apps/human-app/frontend/src/pages/worker/jobs/helpers/get-chip-status-color.ts new file mode 100644 index 0000000000..856d055f7b --- /dev/null +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/helpers/get-chip-status-color.ts @@ -0,0 +1,21 @@ +import { + MyJobStatus, + type UNKNOWN_JOB_STATUS, +} from '@/api/services/worker/my-jobs-data'; +import { type ColorPalette } from '@/styles/color-palette'; + +export function getChipStatusColor( + status: MyJobStatus | typeof UNKNOWN_JOB_STATUS, + colorPalette: ColorPalette +) { + switch (status) { + case MyJobStatus.ACTIVE: + return colorPalette.secondary.main; + case MyJobStatus.COMPLETED: + return colorPalette.success.main; + case MyJobStatus.VALIDATION: + return colorPalette.error.light; + default: + return colorPalette.error.main; + } +} From ce752b2cebb44fcff68c0b483708dbff881a88d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:43:55 +0100 Subject: [PATCH 05/92] chore(deps): bump actions/dependency-review-action from 4.4.0 to 4.5.0 (#2837) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.4.0 to 4.5.0. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/v4.4.0...v4.5.0) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-dependency-review.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-dependency-review.yaml b/.github/workflows/ci-dependency-review.yaml index 1d6a00677b..860a59df2b 100644 --- a/.github/workflows/ci-dependency-review.yaml +++ b/.github/workflows/ci-dependency-review.yaml @@ -11,4 +11,4 @@ jobs: - name: "Checkout Repository" uses: actions/checkout@v4.1.1 - name: "Dependency Review" - uses: actions/dependency-review-action@v4.4.0 + uses: actions/dependency-review-action@v4.5.0 From c76b33df924c4bc61cc84f8b3c157ff713bc11ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:44:18 +0100 Subject: [PATCH 06/92] chore(deps-dev): bump xdeployer from 3.0.0 to 3.1.6 (#2838) Bumps [xdeployer](https://github.com/pcaversaccio/xdeployer) from 3.0.0 to 3.1.6. - [Release notes](https://github.com/pcaversaccio/xdeployer/releases) - [Commits](https://github.com/pcaversaccio/xdeployer/compare/v3.0.0...v3.1.6) --- updated-dependencies: - dependency-name: xdeployer dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/core/package.json | 2 +- yarn.lock | 39 +++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 55c65220e0..c3eb589907 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -75,7 +75,7 @@ "solidity-coverage": "^0.8.2", "tenderly": "^0.9.1", "typechain": "^8.3.2", - "xdeployer": "3.0.0" + "xdeployer": "3.1.6" }, "lint-staged": { "*.sol": [ diff --git a/yarn.lock b/yarn.lock index 48301e73a2..00513ef31e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18675,7 +18675,16 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18792,7 +18801,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18806,6 +18815,13 @@ strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -20920,7 +20936,7 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20938,6 +20954,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -20974,10 +20999,10 @@ ws@7.4.6, ws@8.13.0, ws@8.17.1, ws@8.18.0, ws@^7.4.5, ws@^7.4.6, ws@^7.5.1, ws@^ resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== -xdeployer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdeployer/-/xdeployer-3.0.0.tgz#f39753c52fbeea10877652f99dc70cce47e814e5" - integrity sha512-YG5YsprDGDF3tXw9zDizsp2EdoEy8FYtl1ta72yaOnmCgbkP6DWAvwhavr59xfapWJg8cLqGasxa9h5YwL1TOA== +xdeployer@3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/xdeployer/-/xdeployer-3.1.6.tgz#91b3061bd814bf65456782ea4bf5895bc382847c" + integrity sha512-bG7p5I5sfX8K8hUb8/U+48kNm9vxDRdJd+YS9ZYwzx+HWGqkLp1zG5c2wMwskQkpeQ+pzWCm0EF4AOL8SffE5w== xml-name-validator@^4.0.0: version "4.0.0" From ccdc1b32fabd5f6c1d7b20700e417d3494f19237 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:44:39 +0100 Subject: [PATCH 07/92] chore(deps): bump stripe from 17.3.1 to 17.4.0 (#2839) Bumps [stripe](https://github.com/stripe/stripe-node) from 17.3.1 to 17.4.0. - [Release notes](https://github.com/stripe/stripe-node/releases) - [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md) - [Commits](https://github.com/stripe/stripe-node/compare/v17.3.1...v17.4.0) --- updated-dependencies: - dependency-name: stripe dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/job-launcher/server/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index 65a77519e0..3d5befccd7 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -55,7 +55,7 @@ "pg": "8.12.0", "reflect-metadata": "^0.2.2", "rxjs": "^7.2.0", - "stripe": "^17.2.1", + "stripe": "^17.4.0", "typeorm": "^0.3.17", "typeorm-naming-strategies": "^4.1.0", "zxcvbn": "^4.4.2" diff --git a/yarn.lock b/yarn.lock index 00513ef31e..dd5ae2ee5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18880,10 +18880,10 @@ strip-literal@^2.0.0: dependencies: js-tokens "^9.0.0" -stripe@^17.2.1: - version "17.3.1" - resolved "https://registry.yarnpkg.com/stripe/-/stripe-17.3.1.tgz#901e91e85f6bdbbe10094debab13ef2a9d4c0fc0" - integrity sha512-E9/u+GFBPkYnTmfFCoKX3+gP4R3SkZoGunHe4cw9J+sqkj5uxpLFf1LscuI9BuEyIQ0PFAgPTHavgQwRtOvnag== +stripe@^17.4.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/stripe/-/stripe-17.4.0.tgz#6eb6f7808b616ae8ef76320da0f0ee07085b15a2" + integrity sha512-sQQGZguPxe7/QYXJKtDpfzT2OAH9F8nyE2SOsVdTU793iiU33/dpaKgWaJEGJm8396Yy/6NvTLblgdHlueGLhA== dependencies: "@types/node" ">=8.1.0" qs "^6.11.0" From f5033177db64ef08050b999fd9f2b68db68887c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:45:01 +0100 Subject: [PATCH 08/92] chore(deps): bump react-hook-form from 7.53.1 to 7.53.2 (#2840) Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.53.1 to 7.53.2. - [Release notes](https://github.com/react-hook-form/react-hook-form/releases) - [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md) - [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.53.1...v7.53.2) --- updated-dependencies: - dependency-name: react-hook-form dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/human-app/frontend/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/apps/human-app/frontend/package.json b/packages/apps/human-app/frontend/package.json index cef47c90a5..8113235eae 100644 --- a/packages/apps/human-app/frontend/package.json +++ b/packages/apps/human-app/frontend/package.json @@ -39,7 +39,7 @@ "query-string": "^9.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-hook-form": "^7.53.1", + "react-hook-form": "^7.53.2", "react-i18next": "^15.1.0", "react-imask": "^7.4.0", "react-number-format": "^5.3.4", diff --git a/yarn.lock b/yarn.lock index dd5ae2ee5f..88c77ab656 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17242,10 +17242,10 @@ react-fast-compare@^2.0.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== -react-hook-form@^7.53.1: - version "7.53.1" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.1.tgz#3f2cd1ed2b3af99416a4ac674da2d526625add67" - integrity sha512-6aiQeBda4zjcuaugWvim9WsGqisoUk+etmFEsSUMm451/Ic8L/UAb7sRtMj3V+Hdzm6mMjU1VhiSzYUZeBm0Vg== +react-hook-form@^7.53.2: + version "7.53.2" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.2.tgz#6fa37ae27330af81089baadd7f322cc987b8e2ac" + integrity sha512-YVel6fW5sOeedd1524pltpHX+jgU2u3DSDtXEaBORNdqiNrsX/nUI/iGXONegttg0mJVnfrIkiV0cmTU6Oo2xw== react-i18next@^15.1.0: version "15.1.0" From bc2e6a4d97e834b6980de055111e5771022211b3 Mon Sep 17 00:00:00 2001 From: mpblocky <185767042+mpblocky@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:58:48 +0100 Subject: [PATCH 09/92] [Human App] fix: refresh token race condition (#2824) --- .../human-app/frontend/src/api/api-client.ts | 1 - .../frontend/src/api/fetch-refresh-token.ts | 29 ++++++++++ .../human-app/frontend/src/api/fetcher.ts | 56 ++++++++++--------- .../common/use-access-token-refresh.ts | 22 ++------ .../src/api/services/worker/sign-in/schema.ts | 19 +++++++ .../services/worker/{ => sign-in}/sign-in.ts | 26 +-------- .../src/api/services/worker/sign-in/types.ts | 9 +++ .../src/auth-web3/web3-auth-context.tsx | 2 +- .../frontend/src/auth/auth-context.tsx | 2 +- .../src/pages/worker/sign-in.page.tsx | 8 +-- .../shared/helpers/browser-auth-provider.ts | 7 ++- .../src/shared/types/browser-auth-provider.ts | 2 +- 12 files changed, 107 insertions(+), 76 deletions(-) create mode 100644 packages/apps/human-app/frontend/src/api/fetch-refresh-token.ts create mode 100644 packages/apps/human-app/frontend/src/api/services/worker/sign-in/schema.ts rename packages/apps/human-app/frontend/src/api/services/worker/{ => sign-in}/sign-in.ts (53%) create mode 100644 packages/apps/human-app/frontend/src/api/services/worker/sign-in/types.ts diff --git a/packages/apps/human-app/frontend/src/api/api-client.ts b/packages/apps/human-app/frontend/src/api/api-client.ts index f4671d4cbe..59d6dd5fe2 100644 --- a/packages/apps/human-app/frontend/src/api/api-client.ts +++ b/packages/apps/human-app/frontend/src/api/api-client.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-cycle -- cause by refresh token retry import { createFetcher } from '@/api/fetcher'; import { env } from '@/shared/env'; diff --git a/packages/apps/human-app/frontend/src/api/fetch-refresh-token.ts b/packages/apps/human-app/frontend/src/api/fetch-refresh-token.ts new file mode 100644 index 0000000000..b0a4c33c58 --- /dev/null +++ b/packages/apps/human-app/frontend/src/api/fetch-refresh-token.ts @@ -0,0 +1,29 @@ +import { apiPaths } from '@/api/api-paths'; +import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; +import { signInSuccessResponseSchema } from '@/api/services/worker/sign-in/schema'; + +export const fetchTokenRefresh = async (baseUrl: string) => { + const response = await fetch( + `${baseUrl}${apiPaths.worker.obtainAccessToken.path}`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + // eslint-disable-next-line camelcase -- camel case defined by api + refresh_token: browserAuthProvider.getRefreshToken(), + }), + } + ); + + if (!response.ok) { + return null; + } + + const data: unknown = await response.json(); + + const refetchAccessTokenSuccess = signInSuccessResponseSchema.parse(data); + + return refetchAccessTokenSuccess; +}; diff --git a/packages/apps/human-app/frontend/src/api/fetcher.ts b/packages/apps/human-app/frontend/src/api/fetcher.ts index dbe36a87bf..8a1c19ce8b 100644 --- a/packages/apps/human-app/frontend/src/api/fetcher.ts +++ b/packages/apps/human-app/frontend/src/api/fetcher.ts @@ -1,12 +1,10 @@ import merge from 'lodash/merge'; import { ZodError, type ZodType, type ZodTypeDef } from 'zod'; import type { ResponseError } from '@/shared/types/global.type'; -import type { SignInSuccessResponse } from '@/api/services/worker/sign-in'; -// eslint-disable-next-line import/no-cycle -- cause by refresh token retry -import { signInSuccessResponseSchema } from '@/api/services/worker/sign-in'; -import { apiClient } from '@/api/api-client'; -import { apiPaths } from '@/api/api-paths'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; +import { env } from '@/shared/env'; +import { type SignInSuccessResponse } from '@/api/services/worker/sign-in/types'; +import { fetchTokenRefresh } from './fetch-refresh-token'; const appendHeader = ( fetcherOptionsWithDefaults: RequestInit | undefined, @@ -67,6 +65,29 @@ export type FetcherOptions = export type FetcherUrl = string | URL; +let refreshPromise: Promise | null = null; + +export async function refreshToken(): Promise<{ + access_token: string; + refresh_token: string; +} | null> { + if (!refreshPromise) { + refreshPromise = fetchTokenRefresh(env.VITE_API_URL); + } + + const result = await refreshPromise; + + refreshPromise = null; + + if (result) { + browserAuthProvider.signIn(result, browserAuthProvider.authType); + } else { + browserAuthProvider.signOut({ triggerSignOutSubscriptions: true }); + } + + return result; +} + export function createFetcher(defaultFetcherConfig?: { options?: RequestInit | (() => RequestInit); baseUrl: FetcherUrl | (() => FetcherUrl); @@ -153,33 +174,16 @@ export function createFetcher(defaultFetcherConfig?: { fetcherOptions.authenticated && fetcherOptions.withAuthRetry ) { - let refetchAccessTokenSuccess: SignInSuccessResponse | undefined; - try { - refetchAccessTokenSuccess = await apiClient( - apiPaths.worker.obtainAccessToken.path, - { - successSchema: signInSuccessResponseSchema, - options: { - method: 'POST', - body: JSON.stringify({ - // eslint-disable-next-line camelcase -- camel case defined by api - refresh_token: browserAuthProvider.getRefreshToken(), - }), - }, - } - ); - browserAuthProvider.signIn( - refetchAccessTokenSuccess, - browserAuthProvider.authType - ); - } catch { - browserAuthProvider.signOut({ triggerSignOutSubscriptions: true }); + const refetchAccessTokenSuccess = await refreshToken(); + + if (!refetchAccessTokenSuccess) { return; } const newHeaders = appendHeader(fetcherOptionsWithDefaults, { Authorization: `Bearer ${refetchAccessTokenSuccess.access_token}`, }); + response = await fetch(fetcherUrl, newHeaders); if (!response.ok) { diff --git a/packages/apps/human-app/frontend/src/api/services/common/use-access-token-refresh.ts b/packages/apps/human-app/frontend/src/api/services/common/use-access-token-refresh.ts index 8af49cd94a..054e59a0d9 100644 --- a/packages/apps/human-app/frontend/src/api/services/common/use-access-token-refresh.ts +++ b/packages/apps/human-app/frontend/src/api/services/common/use-access-token-refresh.ts @@ -1,13 +1,11 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; -import { apiClient } from '@/api/api-client'; -import { apiPaths } from '@/api/api-paths'; -import { signInSuccessResponseSchema } from '@/api/services/worker/sign-in'; import { useAuth } from '@/auth/use-auth'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; import type { AuthType } from '@/shared/types/browser-auth-provider'; import { useWeb3Auth } from '@/auth-web3/use-web3-auth'; import { routerPaths } from '@/router/router-paths'; +import { refreshToken } from '@/api/fetcher'; export function useAccessTokenRefresh() { const queryClient = useQueryClient(); @@ -32,19 +30,11 @@ export function useAccessTokenRefresh() { throwExpirationModalOnSignOut?: boolean; }) => { try { - const refetchAccessTokenSuccess = await apiClient( - apiPaths.worker.obtainAccessToken.path, - { - successSchema: signInSuccessResponseSchema, - options: { - method: 'POST', - body: JSON.stringify({ - // eslint-disable-next-line camelcase -- camel case defined by api - refresh_token: browserAuthProvider.getRefreshToken(), - }), - }, - } - ); + const refetchAccessTokenSuccess = await refreshToken(); + + if (!refetchAccessTokenSuccess) { + throw new Error('Failed to refresh access token.'); + } if (authType === 'web2') { signInWeb2(refetchAccessTokenSuccess); diff --git a/packages/apps/human-app/frontend/src/api/services/worker/sign-in/schema.ts b/packages/apps/human-app/frontend/src/api/services/worker/sign-in/schema.ts new file mode 100644 index 0000000000..2002a3a5e0 --- /dev/null +++ b/packages/apps/human-app/frontend/src/api/services/worker/sign-in/schema.ts @@ -0,0 +1,19 @@ +import { z } from 'zod'; +import { t } from 'i18next'; + +export const signInDtoSchema = z.object({ + email: z.string().email(t('validation.invalidEmail')), + password: z + .string() + .min(1, t('validation.passwordMissing')) + .max(50, t('validation.max', { count: 50 })), + // eslint-disable-next-line camelcase -- export vite config + h_captcha_token: z.string().min(1, t('validation.captcha')).default('token'), +}); + +export const signInSuccessResponseSchema = z.object({ + // eslint-disable-next-line camelcase -- data from api + access_token: z.string(), + // eslint-disable-next-line camelcase -- data from api + refresh_token: z.string(), +}); diff --git a/packages/apps/human-app/frontend/src/api/services/worker/sign-in.ts b/packages/apps/human-app/frontend/src/api/services/worker/sign-in/sign-in.ts similarity index 53% rename from packages/apps/human-app/frontend/src/api/services/worker/sign-in.ts rename to packages/apps/human-app/frontend/src/api/services/worker/sign-in/sign-in.ts index a5e142e4f8..c12984f8ca 100644 --- a/packages/apps/human-app/frontend/src/api/services/worker/sign-in.ts +++ b/packages/apps/human-app/frontend/src/api/services/worker/sign-in/sign-in.ts @@ -1,33 +1,11 @@ -import { z } from 'zod'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; -import { t } from 'i18next'; -// eslint-disable-next-line import/no-cycle -- cause by refresh token retry import { apiClient } from '@/api/api-client'; import { apiPaths } from '@/api/api-paths'; import { routerPaths } from '@/router/router-paths'; import { useAuth } from '@/auth/use-auth'; - -export const signInDtoSchema = z.object({ - email: z.string().email(t('validation.invalidEmail')), - password: z - .string() - .min(1, t('validation.passwordMissing')) - .max(50, t('validation.max', { count: 50 })), - // eslint-disable-next-line camelcase -- export vite config - h_captcha_token: z.string().min(1, t('validation.captcha')).default('token'), -}); - -export type SignInDto = z.infer; - -export const signInSuccessResponseSchema = z.object({ - // eslint-disable-next-line camelcase -- data from api - access_token: z.string(), - // eslint-disable-next-line camelcase -- data from api - refresh_token: z.string(), -}); - -export type SignInSuccessResponse = z.infer; +import { type SignInDto } from './types'; +import { signInSuccessResponseSchema } from './schema'; function signInMutationFn(data: SignInDto) { return apiClient(apiPaths.worker.signIn.path, { diff --git a/packages/apps/human-app/frontend/src/api/services/worker/sign-in/types.ts b/packages/apps/human-app/frontend/src/api/services/worker/sign-in/types.ts new file mode 100644 index 0000000000..6f5dbeae11 --- /dev/null +++ b/packages/apps/human-app/frontend/src/api/services/worker/sign-in/types.ts @@ -0,0 +1,9 @@ +import { type z } from 'zod'; +import { + type signInDtoSchema, + type signInSuccessResponseSchema, +} from './schema'; + +export type SignInDto = z.infer; + +export type SignInSuccessResponse = z.infer; diff --git a/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx b/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx index 1f1a2a9014..2d93dbc4b0 100644 --- a/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx +++ b/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx @@ -3,7 +3,7 @@ import { useState, createContext, useEffect } from 'react'; import { jwtDecode } from 'jwt-decode'; import { z } from 'zod'; import { useQueryClient } from '@tanstack/react-query'; -import type { SignInSuccessResponse } from '@/api/services/worker/sign-in'; +import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/sign-in'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; import { useModalStore } from '@/components/ui/modal/modal.store'; diff --git a/packages/apps/human-app/frontend/src/auth/auth-context.tsx b/packages/apps/human-app/frontend/src/auth/auth-context.tsx index cf9ead3acd..0e2452bcac 100644 --- a/packages/apps/human-app/frontend/src/auth/auth-context.tsx +++ b/packages/apps/human-app/frontend/src/auth/auth-context.tsx @@ -3,7 +3,7 @@ import { useState, createContext, useEffect } from 'react'; import { jwtDecode } from 'jwt-decode'; import { z } from 'zod'; import { useQueryClient } from '@tanstack/react-query'; -import type { SignInSuccessResponse } from '@/api/services/worker/sign-in'; +import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/sign-in'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; import { useModalStore } from '@/components/ui/modal/modal.store'; diff --git a/packages/apps/human-app/frontend/src/pages/worker/sign-in.page.tsx b/packages/apps/human-app/frontend/src/pages/worker/sign-in.page.tsx index dec5f1007e..f242dd6138 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/sign-in.page.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/sign-in.page.tsx @@ -9,11 +9,7 @@ import { PageCard } from '@/components/ui/page-card'; import { Input } from '@/components/data-entry/input'; import { Button } from '@/components/ui/button'; import { Password } from '@/components/data-entry/password/password'; -import type { SignInDto } from '@/api/services/worker/sign-in'; -import { - signInDtoSchema, - useSignInMutation, -} from '@/api/services/worker/sign-in'; +import { useSignInMutation } from '@/api/services/worker/sign-in/sign-in'; import { FetchError } from '@/api/fetcher'; import { routerPaths } from '@/router/router-paths'; import { defaultErrorMessage } from '@/shared/helpers/default-error-message'; @@ -21,6 +17,8 @@ import { Alert } from '@/components/ui/alert'; import { FormCaptcha } from '@/components/h-captcha'; import { useResetMutationErrors } from '@/hooks/use-reset-mutation-errors'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; +import { type SignInDto } from '@/api/services/worker/sign-in/types'; +import { signInDtoSchema } from '@/api/services/worker/sign-in/schema'; function formattedSignInErrorMessage(unknownError: unknown) { if (unknownError instanceof FetchError && unknownError.status === 400) { diff --git a/packages/apps/human-app/frontend/src/shared/helpers/browser-auth-provider.ts b/packages/apps/human-app/frontend/src/shared/helpers/browser-auth-provider.ts index b256cd4fba..14cd0a5d08 100644 --- a/packages/apps/human-app/frontend/src/shared/helpers/browser-auth-provider.ts +++ b/packages/apps/human-app/frontend/src/shared/helpers/browser-auth-provider.ts @@ -1,4 +1,5 @@ /* eslint-disable camelcase -- ...*/ +import { type SignInSuccessResponse } from '@/api/services/worker/sign-in/types'; import type { BrowserAuthProvider } from '@/shared/types/browser-auth-provider'; const accessTokenKey = btoa('access_token'); @@ -9,7 +10,11 @@ const userDataKey = btoa('extendable_user_data'); const browserAuthProvider: BrowserAuthProvider = { isAuthenticated: false, authType: 'web2', - signIn({ access_token, refresh_token }, authType, signOutSubscription) { + signIn( + { access_token, refresh_token }: SignInSuccessResponse, + authType, + signOutSubscription + ) { browserAuthProvider.isAuthenticated = true; browserAuthProvider.authType = authType; localStorage.setItem(accessTokenKey, btoa(access_token)); diff --git a/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts b/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts index d3a27b1f12..75412f6252 100644 --- a/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts +++ b/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts @@ -1,4 +1,4 @@ -import type { SignInSuccessResponse } from '@/api/services/worker/sign-in'; +import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/sign-in'; import type { Web3UserData } from '@/auth-web3/web3-auth-context'; import type { UserData } from '@/auth/auth-context'; From b5886e3eae716aa7a103f700d04f9d0e961850c9 Mon Sep 17 00:00:00 2001 From: mpblocky <185767042+mpblocky@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:00:10 +0100 Subject: [PATCH 10/92] [Human App] fix: metamask error from walletconnect (#2794) --- packages/apps/human-app/frontend/package.json | 10 +- .../frontend/src/contexts/wallet-connect.tsx | 121 +-- .../frontend/src/hooks/use-web3-provider.tsx | 15 +- .../frontend/src/smart-contracts/chains.ts | 9 +- yarn.lock | 826 ++++++++---------- 5 files changed, 450 insertions(+), 531 deletions(-) diff --git a/packages/apps/human-app/frontend/package.json b/packages/apps/human-app/frontend/package.json index 8113235eae..1a6d0ad4e3 100644 --- a/packages/apps/human-app/frontend/package.json +++ b/packages/apps/human-app/frontend/package.json @@ -23,12 +23,10 @@ "@human-protocol/sdk": "*", "@mui/icons-material": "^6.1.1", "@mui/material": "^5.16.7", + "@reown/appkit": "1.3.2", + "@reown/appkit-adapter-wagmi": "1.3.2", "@synaps-io/verify-sdk": "^4.0.45", - "@tanstack/react-query": "^5.60.5", - "@walletconnect/ethereum-provider": "^2.16.1", - "@walletconnect/modal": "^2.6.2", - "@web3modal/ethers": "^5.1.5", - "@web3modal/scaffold-utils": "^4.1.11", + "@tanstack/react-query": "^5.61.0", "date-fns": "^4.1.0", "ethers": "^6.12.0", "i18next": "^23.8.2", @@ -44,7 +42,9 @@ "react-imask": "^7.4.0", "react-number-format": "^5.3.4", "react-router-dom": "^6.22.0", + "viem": "^2.21.44", "vite-plugin-svgr": "^4.2.0", + "wagmi": "2.12.29", "zod": "^3.22.4", "zustand": "^4.5.0" }, diff --git a/packages/apps/human-app/frontend/src/contexts/wallet-connect.tsx b/packages/apps/human-app/frontend/src/contexts/wallet-connect.tsx index 89febe5407..7a972859a7 100644 --- a/packages/apps/human-app/frontend/src/contexts/wallet-connect.tsx +++ b/packages/apps/human-app/frontend/src/contexts/wallet-connect.tsx @@ -1,16 +1,19 @@ -import { - createWeb3Modal, - defaultConfig, - useWeb3Modal, - useWeb3ModalAccount, -} from '@web3modal/ethers/react'; import type { JsonRpcSigner, BrowserProvider, Eip1193Provider } from 'ethers'; import React, { createContext, useEffect, useState } from 'react'; -import type { UseMutationResult } from '@tanstack/react-query'; -import { useWeb3Provider } from '@/hooks/use-web3-provider'; +import { type UseMutationResult } from '@tanstack/react-query'; +import { + useAppKit, + useAppKitAccount, + useAppKitNetwork, + createAppKit, + type AppKitOptions, +} from '@reown/appkit/react'; +import { WagmiProvider } from 'wagmi'; +import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'; +import { polygonAmoy, polygon } from '@reown/appkit/networks'; import { env } from '@/shared/env'; import type { ResponseError } from '@/shared/types/global.type'; -import { chains } from '@/smart-contracts/chains'; +import { useWeb3Provider } from '@/hooks/use-web3-provider'; import { JsonRpcError } from '@/smart-contracts/json-rpc-error'; const projectId = env.VITE_WALLET_CONNECT_PROJECT_ID; @@ -22,15 +25,13 @@ const metadata = { icons: env.VITE_DAPP_ICONS, }; -const ethersConfig = defaultConfig({ - metadata, -}); -createWeb3Modal({ - ethersConfig, - chains, +const networks: AppKitOptions['networks'] = [polygon, polygonAmoy]; + +const wagmiAdapter = new WagmiAdapter({ + networks, projectId, - enableAnalytics: true, }); + export interface CommonWalletConnectContext { openModal: () => Promise; web3ProviderMutation: UseMutationResult< @@ -47,7 +48,7 @@ export interface CommonWalletConnectContext { interface ConnectedAccount { isConnected: true; chainId: number; - address: `0x${string}`; + address: string; signMessage: (message: string) => Promise; } @@ -70,6 +71,13 @@ export const WalletConnectContext = createContext< | null >(null); +createAppKit({ + adapters: [wagmiAdapter], + networks, + projectId, + metadata, +}); + export function WalletConnectProvider({ children, }: { @@ -77,8 +85,9 @@ export function WalletConnectProvider({ }) { const [initializing, setInitializing] = useState(true); const web3ProviderMutation = useWeb3Provider(); - const { open } = useWeb3Modal(); - const { address, chainId, isConnected } = useWeb3ModalAccount(); + const { open } = useAppKit(); + const { address, isConnected } = useAppKitAccount(); + const { chainId } = useAppKitNetwork(); const openModal = async () => { await open(); @@ -94,32 +103,17 @@ export function WalletConnectProvider({ }, [web3ProviderMutation]); return ( - { - try { - const signature = - await web3ProviderMutation.data.signer.signMessage(message); - return signature; - } catch (error) { - throw new JsonRpcError(error); - } - }, - initializing, - } - : { - isConnected: false, - web3ProviderMutation, - openModal, - signMessage: async (message: string) => { - if (web3ProviderMutation.data) { + + { try { const signature = await web3ProviderMutation.data.signer.signMessage( @@ -129,14 +123,33 @@ export function WalletConnectProvider({ } catch (error) { throw new JsonRpcError(error); } - } - return Promise.resolve(undefined); - }, - initializing, - } - } - > - {children} - + }, + initializing, + } + : { + isConnected: false, + web3ProviderMutation, + openModal, + signMessage: async (message: string) => { + if (web3ProviderMutation.data) { + try { + const signature = + await web3ProviderMutation.data.signer.signMessage( + message + ); + return signature; + } catch (error) { + throw new JsonRpcError(error); + } + } + return Promise.resolve(undefined); + }, + initializing, + } + } + > + {children} + + ); } diff --git a/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx b/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx index 16017c827c..3f4dc7bba9 100644 --- a/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx +++ b/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx @@ -1,11 +1,8 @@ import { useMutation } from '@tanstack/react-query'; -import { - useWeb3ModalAccount, - useWeb3ModalProvider, -} from '@web3modal/ethers/react'; import type { Eip1193Provider } from 'ethers'; import { BrowserProvider } from 'ethers'; import { useEffect } from 'react'; +import { useAppKitNetwork, useAppKitProvider } from '@reown/appkit/react'; import { checkNetwork } from '@/smart-contracts/check-network'; const getSignerAndProvider = async (walletProvider: Eip1193Provider) => { @@ -21,16 +18,16 @@ const getSignerAndProvider = async (walletProvider: Eip1193Provider) => { }; export function useWeb3Provider() { - const { chainId } = useWeb3ModalAccount(); - const { walletProvider } = useWeb3ModalProvider(); + const { chainId } = useAppKitNetwork(); + const { walletProvider } = useAppKitProvider('eip155'); + const useSignerAndProviderMutation = useMutation({ mutationFn: getSignerAndProvider, }); useEffect(() => { - if (walletProvider) { - useSignerAndProviderMutation.mutate(walletProvider); - } + useSignerAndProviderMutation.mutate(walletProvider); + // eslint-disable-next-line react-hooks/exhaustive-deps -- not nesseccary }, [walletProvider, chainId]); diff --git a/packages/apps/human-app/frontend/src/smart-contracts/chains.ts b/packages/apps/human-app/frontend/src/smart-contracts/chains.ts index 94e4c3c707..5a737c7697 100644 --- a/packages/apps/human-app/frontend/src/smart-contracts/chains.ts +++ b/packages/apps/human-app/frontend/src/smart-contracts/chains.ts @@ -4,7 +4,6 @@ // Thanks to that we can get addresses for selected chain with getContractAddress // function -import type { Chain } from '@web3modal/scaffold-utils/ethers'; import { MainnetContracts, TestnetContracts, @@ -12,6 +11,14 @@ import { } from '@/smart-contracts/contracts'; import { env } from '@/shared/env'; +export interface Chain { + rpcUrl: string; + explorerUrl: string; + currency: string; + name: string; + chainId: number; +} + export type ChainWithAddresses = Chain & { addresses: ContractsAddresses; }; diff --git a/yarn.lock b/yarn.lock index 88c77ab656..8dfefd7490 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1230,18 +1230,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@coinbase/wallet-sdk@4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.0.3.tgz#fd52dd4c168c35979c7b3294018a6f78d163a593" - integrity sha512-y/OGEjlvosikjfB+wk+4CVb9OxD1ob9cidEBLI5h8Hxaf/Qoob2XoVT1uvhtAzBx34KpGYSd+alKvh/GCRre4Q== - dependencies: - buffer "^6.0.3" - clsx "^1.2.1" - eventemitter3 "^5.0.1" - keccak "^3.0.3" - preact "^10.16.0" - sha.js "^2.4.11" - "@coinbase/wallet-sdk@4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.1.0.tgz#3224a102b724dcb1a63005f371d596ae2999953b" @@ -1252,6 +1240,17 @@ eventemitter3 "^5.0.1" preact "^10.16.0" +"@coinbase/wallet-sdk@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.2.1.tgz#040acf57dda03cb1f0c1313e7f627c4808f365ff" + integrity sha512-5bKucgWcogXpFNQdahdr7ApNe/bgVeUDHPXO+5O1XPuFctA8V8+cyF6ANLwPWvHJEMBOPsMhIeqDIVmMzHYmaw== + dependencies: + "@noble/hashes" "^1.4.0" + clsx "^1.2.1" + eventemitter3 "^5.0.1" + preact "^10.24.2" + vitest "^2.1.2" + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -4116,6 +4115,130 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.20.0.tgz#03554155b45d8b529adf635b2f6ad1165d70d8b4" integrity sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg== +"@reown/appkit-adapter-wagmi@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-adapter-wagmi/-/appkit-adapter-wagmi-1.3.2.tgz#54a12df940e32db171c61f8772ddd31061a81b2f" + integrity sha512-hyBJ8mqX58RNlG1TEe9sL5DpfaPLP7i2bhGq7a1zp5LJb3bMmXbAtKOsc4gH3HjBQBxNNacqyYCwK5snMWFKrg== + dependencies: + "@reown/appkit" "1.3.2" + "@reown/appkit-common" "1.3.2" + "@reown/appkit-core" "1.3.2" + "@reown/appkit-polyfills" "1.3.2" + "@reown/appkit-scaffold-ui" "1.3.2" + "@reown/appkit-siwe" "1.3.2" + "@reown/appkit-ui" "1.3.2" + "@reown/appkit-utils" "1.3.2" + "@reown/appkit-wallet" "1.3.2" + "@walletconnect/universal-provider" "2.17.0" + "@walletconnect/utils" "2.17.0" + valtio "1.11.2" + +"@reown/appkit-common@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-common/-/appkit-common-1.3.2.tgz#db9ce8babba0f0303991acbd86d11b71c5db6eb8" + integrity sha512-U/IJSfKFTGm92rlpSp7yV9iefJQjXpp9Z9BzUiyqLTEYX5ZzGHrV69riho5NlLHQRx58qeD1rGbPuz8CqXF6hg== + dependencies: + bignumber.js "9.1.2" + dayjs "1.11.10" + viem "2.x" + +"@reown/appkit-core@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-core/-/appkit-core-1.3.2.tgz#1da867f24b2e8b1f5b7454dbfe4cb6a776f69799" + integrity sha512-A8v7rIMogFs4vDEweWRE7uUCtnp9EjTn8dyezmC8ebelo5M1GbqzhoWlqi8FiVNjESY/fOjCcEVCw6q1h8S8sQ== + dependencies: + "@reown/appkit-common" "1.3.2" + "@reown/appkit-wallet" "1.3.2" + "@walletconnect/universal-provider" "2.17.0" + valtio "1.11.2" + viem "2.x" + +"@reown/appkit-polyfills@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-polyfills/-/appkit-polyfills-1.3.2.tgz#d44b9e3e86d151c2a3f18c47c6f793e112d11d38" + integrity sha512-vS9jRZTLdzhqJllK5iUNnAlyo/veug80S/n7HsPexWrU9haTfs06wHxSpvfwYuqo9sff6wNz7LEiP0atVf9+IA== + dependencies: + buffer "6.0.3" + +"@reown/appkit-scaffold-ui@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.3.2.tgz#e67bd663188db4ea8805b04f60e0d47d2ae2628c" + integrity sha512-G7VXnN7tphcoYV/bGmL9DBK9xSc1tnBGsQVf8VFrtMu0zVEgJ/oCe1iyk9F+/ctoWug7hwhRX8/ts0UXW5eP/Q== + dependencies: + "@reown/appkit-common" "1.3.2" + "@reown/appkit-core" "1.3.2" + "@reown/appkit-siwe" "1.3.2" + "@reown/appkit-ui" "1.3.2" + "@reown/appkit-utils" "1.3.2" + "@reown/appkit-wallet" "1.3.2" + lit "3.1.0" + +"@reown/appkit-siwe@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-siwe/-/appkit-siwe-1.3.2.tgz#1caa2c83d58c8eba9bf525b4be0988e3abb605f5" + integrity sha512-D0XraLV/8rTGAC+WF6KQcaUWs4cJI3Rw1iPFKh4LTNrIYn1d8gflbvk1rV1YrAzPFaNr/hguYySI/iTASixS5A== + dependencies: + "@reown/appkit-common" "1.3.2" + "@reown/appkit-core" "1.3.2" + "@reown/appkit-ui" "1.3.2" + "@reown/appkit-utils" "1.3.2" + "@reown/appkit-wallet" "1.3.2" + "@walletconnect/utils" "2.17.0" + lit "3.1.0" + valtio "1.11.2" + +"@reown/appkit-ui@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-ui/-/appkit-ui-1.3.2.tgz#1bae7cdc58be923cc5813b7ee2b134418cb34f53" + integrity sha512-aQcXEAil0eBNbhcQveD3b0XEBV2xz1MgVq++XPnyrelxNkm+uCDI55tH1Kg0xiOoPrd50aEJiHPJOTrEMmjbMg== + dependencies: + lit "3.1.0" + qrcode "1.5.3" + +"@reown/appkit-utils@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-utils/-/appkit-utils-1.3.2.tgz#d313890e31e19ace3d73324d405e023c1cebbf97" + integrity sha512-9a/gi5QeZZkTDT56tLBZu4cOrFLHh/93qtqV5UE7NPqlncpQbE2bfVLq64tnvkbhE1WXoyQM4s4xrL0k8Wtlgw== + dependencies: + "@reown/appkit-common" "1.3.2" + "@reown/appkit-core" "1.3.2" + "@reown/appkit-polyfills" "1.3.2" + "@reown/appkit-wallet" "1.3.2" + "@walletconnect/logger" "2.1.2" + "@walletconnect/universal-provider" "2.17.0" + valtio "1.11.2" + viem "2.x" + +"@reown/appkit-wallet@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-wallet/-/appkit-wallet-1.3.2.tgz#df75fb992f8c91d5ef3abd2899bf50abee964c53" + integrity sha512-TnybfBU6vVjm27lMd7VOWd6I632nOqBfex5QL4I8Zgyy1wLugcSQgybZk8LjSKzaW+U9G9yqHXXhFK9iW6/zaQ== + dependencies: + "@reown/appkit-common" "1.3.2" + "@reown/appkit-polyfills" "1.3.2" + "@walletconnect/logger" "2.1.2" + zod "3.22.4" + +"@reown/appkit@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@reown/appkit/-/appkit-1.3.2.tgz#6fd3680b3ca4e809aa3463bcbe6753ed3a679738" + integrity sha512-Kv/mdI2iddot8sB5NzFLVob1fCdK6q2Y6dfyiBL93sXiJv6W5LxNOPOGdTdFOxTHcTHm/OV9nlrmLa1ZIn7ZSg== + dependencies: + "@reown/appkit-common" "1.3.2" + "@reown/appkit-core" "1.3.2" + "@reown/appkit-polyfills" "1.3.2" + "@reown/appkit-scaffold-ui" "1.3.2" + "@reown/appkit-siwe" "1.3.2" + "@reown/appkit-ui" "1.3.2" + "@reown/appkit-utils" "1.3.2" + "@reown/appkit-wallet" "1.3.2" + "@walletconnect/types" "2.17.0" + "@walletconnect/universal-provider" "2.17.0" + "@walletconnect/utils" "2.17.0" + bs58 "6.0.0" + valtio "1.11.2" + viem "2.x" + "@repeaterjs/repeater@3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca" @@ -4853,6 +4976,13 @@ dependencies: "@tanstack/query-core" "5.60.5" +"@tanstack/react-query@^5.61.0": + version "5.61.0" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.61.0.tgz#73473feb37aa28ceb410e297ee060e18f06f88e0" + integrity sha512-SBzV27XAeCRBOQ8QcC94w2H1Md0+LI0gTWwc3qRJoaGuewKn5FNW4LSqwPFJZVEItfhMfGT7RpZuSFXjTi12pQ== + dependencies: + "@tanstack/query-core" "5.60.6" + "@tanstack/react-table@8.20.5": version "8.20.5" resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.20.5.tgz#19987d101e1ea25ef5406dce4352cab3932449d8" @@ -6208,6 +6338,25 @@ "@vitest/utils" "1.6.0" chai "^4.3.10" +"@vitest/expect@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.5.tgz#5a6afa6314cae7a61847927bb5bc038212ca7381" + integrity sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q== + dependencies: + "@vitest/spy" "2.1.5" + "@vitest/utils" "2.1.5" + chai "^5.1.2" + tinyrainbow "^1.2.0" + +"@vitest/mocker@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.5.tgz#54ee50648bc0bb606dfc58e13edfacb8b9208324" + integrity sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ== + dependencies: + "@vitest/spy" "2.1.5" + estree-walker "^3.0.3" + magic-string "^0.30.12" + "@vitest/pretty-format@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.4.tgz#fc31993bdc1ef5a6c1a4aa6844e7ba55658a4f9f" @@ -6215,6 +6364,13 @@ dependencies: tinyrainbow "^1.2.0" +"@vitest/pretty-format@2.1.5", "@vitest/pretty-format@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.5.tgz#bc79b8826d4a63dc04f2a75d2944694039fa50aa" + integrity sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw== + dependencies: + tinyrainbow "^1.2.0" + "@vitest/runner@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.6.0.tgz#a6de49a96cb33b0e3ba0d9064a3e8d6ce2f08825" @@ -6224,6 +6380,14 @@ p-limit "^5.0.0" pathe "^1.1.1" +"@vitest/runner@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.5.tgz#4d5e2ba2dfc0af74e4b0f9f3f8be020559b26ea9" + integrity sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g== + dependencies: + "@vitest/utils" "2.1.5" + pathe "^1.1.2" + "@vitest/snapshot@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.6.0.tgz#deb7e4498a5299c1198136f56e6e0f692e6af470" @@ -6233,6 +6397,15 @@ pathe "^1.1.1" pretty-format "^29.7.0" +"@vitest/snapshot@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.5.tgz#a09a8712547452a84e08b3ec97b270d9cc156b4f" + integrity sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg== + dependencies: + "@vitest/pretty-format" "2.1.5" + magic-string "^0.30.12" + pathe "^1.1.2" + "@vitest/spy@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.6.0.tgz#362cbd42ccdb03f1613798fde99799649516906d" @@ -6240,6 +6413,13 @@ dependencies: tinyspy "^2.2.0" +"@vitest/spy@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.5.tgz#f790d1394a5030644217ce73562e92465e83147e" + integrity sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw== + dependencies: + tinyspy "^3.0.2" + "@vitest/ui@^2.1.1": version "2.1.4" resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-2.1.4.tgz#fcd0928c1d24301e4e5c2d3783150a0c391966ff" @@ -6272,6 +6452,15 @@ loupe "^3.1.2" tinyrainbow "^1.2.0" +"@vitest/utils@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.5.tgz#0e19ce677c870830a1573d33ee86b0d6109e9546" + integrity sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg== + dependencies: + "@vitest/pretty-format" "2.1.5" + loupe "^3.1.2" + tinyrainbow "^1.2.0" + "@wagmi/connectors@5.3.4": version "5.3.4" resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-5.3.4.tgz#a39218fbd11f0f93cb9af697b1d982e74b647adb" @@ -6284,6 +6473,18 @@ "@walletconnect/ethereum-provider" "2.17.0" cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3" +"@wagmi/connectors@5.3.7": + version "5.3.7" + resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-5.3.7.tgz#6a7fc28cfe773e770aa8f8d385241d153361525c" + integrity sha512-Sn/umWtA4yGZ5A2rPMufdh9f83kpeIBA7ZIV0zg3oJn60PP3iZNB/zjEmWWi/v9eOPT4sgo0R5aRm+uD+QvxRQ== + dependencies: + "@coinbase/wallet-sdk" "4.2.1" + "@metamask/sdk" "0.30.1" + "@safe-global/safe-apps-provider" "0.18.3" + "@safe-global/safe-apps-sdk" "9.1.0" + "@walletconnect/ethereum-provider" "2.17.0" + cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3" + "@wagmi/core@2.14.2": version "2.14.2" resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-2.14.2.tgz#0697e13ac1dbf3bbec3f79d0bdffa4e7ee290dcf" @@ -6293,27 +6494,14 @@ mipd "0.0.7" zustand "5.0.0" -"@walletconnect/core@2.16.1": - version "2.16.1" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.16.1.tgz#019b181387792e0d284e75074b961b48193d9b6a" - integrity sha512-UlsnEMT5wwFvmxEjX8s4oju7R3zadxNbZgsFeHEsjh7uknY2zgmUe1Lfc5XU6zyPb1Jx7Nqpdx1KN485ee8ogw== +"@wagmi/core@2.14.4": + version "2.14.4" + resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-2.14.4.tgz#e46711867f3b94d6ffb908aaa46dc03acbeb0a4f" + integrity sha512-XYMvdjKJdr1GAjYDj8lBX+cFs5xC4+s5/w3VwouA2or+VW/ityOA1cL7ihHuHHVxs8N9Mmd9SFjA1+lHFQUKPw== dependencies: - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/jsonrpc-ws-connection" "1.0.14" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.16.1" - "@walletconnect/utils" "2.16.1" - events "3.3.0" - lodash.isequal "4.5.0" - uint8arrays "3.1.0" + eventemitter3 "5.0.1" + mipd "0.0.7" + zustand "5.0.0" "@walletconnect/core@2.17.0": version "2.17.0" @@ -6337,29 +6525,6 @@ lodash.isequal "4.5.0" uint8arrays "3.1.0" -"@walletconnect/core@2.17.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.17.2.tgz#877dc03f190d7b262bff8ce346330fdf1019cd83" - integrity sha512-O9VUsFg78CbvIaxfQuZMsHcJ4a2Z16DRz/O4S+uOAcGKhH/i/ln8hp864Tb+xRvifWSzaZ6CeAVxk657F+pscA== - dependencies: - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/jsonrpc-ws-connection" "1.0.14" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/utils" "2.17.2" - "@walletconnect/window-getters" "1.0.1" - events "3.3.0" - lodash.isequal "4.5.0" - uint8arrays "3.1.0" - "@walletconnect/environment@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" @@ -6367,22 +6532,6 @@ dependencies: tslib "1.14.1" -"@walletconnect/ethereum-provider@2.16.1": - version "2.16.1" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.16.1.tgz#4fb8a1df39104ad3fbd02579233e796f432f6d35" - integrity sha512-oD7DNCssUX3plS5gGUZ9JQ63muQB/vxO68X6RzD2wd8gBsYtSPw4BqYFc7KTO6dUizD6gfPirw32yW2pTvy92w== - dependencies: - "@walletconnect/jsonrpc-http-connection" "1.0.8" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/modal" "2.6.2" - "@walletconnect/sign-client" "2.16.1" - "@walletconnect/types" "2.16.1" - "@walletconnect/universal-provider" "2.16.1" - "@walletconnect/utils" "2.16.1" - events "3.3.0" - "@walletconnect/ethereum-provider@2.17.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.17.0.tgz#d74feaaed6180a6799e96760d7ee867ff3a083d2" @@ -6399,23 +6548,6 @@ "@walletconnect/utils" "2.17.0" events "3.3.0" -"@walletconnect/ethereum-provider@^2.16.1": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.17.2.tgz#7ac8091daf65f33c9f77cb08f524246c638e9e66" - integrity sha512-o4aL4KkUKT+n0iDwGzC6IY4bl+9n8bwOeT2KwifaVHsFw/irhtRPlsAQQH4ezOiPyk8cri1KN9dPk/YeU0pe6w== - dependencies: - "@walletconnect/jsonrpc-http-connection" "1.0.8" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/modal" "2.7.0" - "@walletconnect/sign-client" "2.17.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/universal-provider" "2.17.2" - "@walletconnect/utils" "2.17.2" - events "3.3.0" - "@walletconnect/events@1.0.1", "@walletconnect/events@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/events/-/events-1.0.1.tgz#2b5f9c7202019e229d7ccae1369a9e86bda7816c" @@ -6496,13 +6628,6 @@ "@walletconnect/safe-json" "^1.0.2" pino "7.11.0" -"@walletconnect/modal-core@2.6.2": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@walletconnect/modal-core/-/modal-core-2.6.2.tgz#d73e45d96668764e0c8668ea07a45bb8b81119e9" - integrity sha512-cv8ibvdOJQv2B+nyxP9IIFdxvQznMz8OOr/oR/AaUZym4hjXNL/l1a2UlSQBXrVjo3xxbouMxLb3kBsHoYP2CA== - dependencies: - valtio "1.11.2" - "@walletconnect/modal-core@2.7.0": version "2.7.0" resolved "https://registry.yarnpkg.com/@walletconnect/modal-core/-/modal-core-2.7.0.tgz#73c13c3b7b0abf9ccdbac9b242254a86327ce0a4" @@ -6510,16 +6635,6 @@ dependencies: valtio "1.11.2" -"@walletconnect/modal-ui@2.6.2": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@walletconnect/modal-ui/-/modal-ui-2.6.2.tgz#fa57c087c57b7f76aaae93deab0f84bb68b59cf9" - integrity sha512-rbdstM1HPGvr7jprQkyPggX7rP4XiCG85ZA+zWBEX0dVQg8PpAgRUqpeub4xQKDgY7pY/xLRXSiCVdWGqvG2HA== - dependencies: - "@walletconnect/modal-core" "2.6.2" - lit "2.8.0" - motion "10.16.2" - qrcode "1.5.3" - "@walletconnect/modal-ui@2.7.0": version "2.7.0" resolved "https://registry.yarnpkg.com/@walletconnect/modal-ui/-/modal-ui-2.7.0.tgz#dbbb7ee46a5a25f7d39db622706f2d197b268cbb" @@ -6530,15 +6645,7 @@ motion "10.16.2" qrcode "1.5.3" -"@walletconnect/modal@2.6.2": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.6.2.tgz#4b534a836f5039eeb3268b80be7217a94dd12651" - integrity sha512-eFopgKi8AjKf/0U4SemvcYw9zlLpx9njVN8sf6DAkowC2Md0gPU/UNEbH1Wwj407pEKnEds98pKWib1NN1ACoA== - dependencies: - "@walletconnect/modal-core" "2.6.2" - "@walletconnect/modal-ui" "2.6.2" - -"@walletconnect/modal@2.7.0", "@walletconnect/modal@^2.6.2": +"@walletconnect/modal@2.7.0": version "2.7.0" resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.7.0.tgz#55f969796d104cce1205f5f844d8f8438b79723a" integrity sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw== @@ -6572,21 +6679,6 @@ dependencies: tslib "1.14.1" -"@walletconnect/sign-client@2.16.1": - version "2.16.1" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.16.1.tgz#94a2f630ba741bd180f540c53576c5ceaace4857" - integrity sha512-s2Tx2n2duxt+sHtuWXrN9yZVaHaYqcEcjwlTD+55/vs5NUPlISf+fFmZLwSeX1kUlrSBrAuxPUcqQuRTKcjLOA== - dependencies: - "@walletconnect/core" "2.16.1" - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "2.1.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.16.1" - "@walletconnect/utils" "2.16.1" - events "3.3.0" - "@walletconnect/sign-client@2.17.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.17.0.tgz#efe811b1bb10082d964e2f0378aaa1b40f424503" @@ -6602,21 +6694,6 @@ "@walletconnect/utils" "2.17.0" events "3.3.0" -"@walletconnect/sign-client@2.17.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.17.2.tgz#b8bd125d7c34a67916745ebbdbbc834db5518c8b" - integrity sha512-/wigdCIQjlBXSWY43Id0IPvZ5biq4HiiQZti8Ljvx408UYjmqcxcBitbj2UJXMYkid7704JWAB2mw32I1HgshQ== - dependencies: - "@walletconnect/core" "2.17.2" - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "2.1.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/utils" "2.17.2" - events "3.3.0" - "@walletconnect/time@1.0.2", "@walletconnect/time@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@walletconnect/time/-/time-1.0.2.tgz#6c5888b835750ecb4299d28eecc5e72c6d336523" @@ -6624,18 +6701,6 @@ dependencies: tslib "1.14.1" -"@walletconnect/types@2.16.1": - version "2.16.1" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.16.1.tgz#6583d458d3f7b1919d482ba516ccb7878ec8c91f" - integrity sha512-9P4RG4VoDEF+yBF/n2TF12gsvT/aTaeZTVDb/AOayafqiPnmrQZMKmNCJJjq1sfdsDcHXFcZWMGsuCeSJCmrXA== - dependencies: - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - events "3.3.0" - "@walletconnect/types@2.17.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.17.0.tgz#20eda5791e3172f8ab9146caa3f317701d4b3232" @@ -6648,33 +6713,6 @@ "@walletconnect/logger" "2.1.2" events "3.3.0" -"@walletconnect/types@2.17.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.17.2.tgz#f9afff242563be33f377de689b03b482f5b20aee" - integrity sha512-j/+0WuO00lR8ntu7b1+MKe/r59hNwYLFzW0tTmozzhfAlDL+dYwWasDBNq4AH8NbVd7vlPCQWmncH7/6FVtOfQ== - dependencies: - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - events "3.3.0" - -"@walletconnect/universal-provider@2.16.1": - version "2.16.1" - resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.16.1.tgz#6d52c41c7388e01f89007956a1117748ab9a11e4" - integrity sha512-q/tyWUVNenizuClEiaekx9FZj/STU1F3wpDK4PUIh3xh+OmUI5fw2dY3MaNDjyb5AyrS0M8BuQDeuoSuOR/Q7w== - dependencies: - "@walletconnect/jsonrpc-http-connection" "1.0.8" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "2.1.2" - "@walletconnect/sign-client" "2.16.1" - "@walletconnect/types" "2.16.1" - "@walletconnect/utils" "2.16.1" - events "3.3.0" - "@walletconnect/universal-provider@2.17.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.17.0.tgz#c9d4bbd9b8f0e41b500b2488ccbc207dc5f7a170" @@ -6690,46 +6728,6 @@ "@walletconnect/utils" "2.17.0" events "3.3.0" -"@walletconnect/universal-provider@2.17.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.17.2.tgz#f4627dd9b66db3bacc31864584112868be23bf08" - integrity sha512-yIWDhBODRa9J349d/i1sObzon0vy4n+7R3MvGQQYaU1EVrV+WfoGSRsu8U7rYsL067/MAUu9t/QrpPblaSbz7g== - dependencies: - "@walletconnect/events" "1.0.1" - "@walletconnect/jsonrpc-http-connection" "1.0.8" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - "@walletconnect/sign-client" "2.17.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/utils" "2.17.2" - events "3.3.0" - lodash "4.17.21" - -"@walletconnect/utils@2.16.1": - version "2.16.1" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.16.1.tgz#2099cc2bd16b0edc32022f64aa2c2c323b45d1d4" - integrity sha512-aoQirVoDoiiEtYeYDtNtQxFzwO/oCrz9zqeEEXYJaAwXlGVTS34KFe7W3/Rxd/pldTYKFOZsku2EzpISfH8Wsw== - dependencies: - "@stablelib/chacha20poly1305" "1.0.1" - "@stablelib/hkdf" "1.0.1" - "@stablelib/random" "1.0.2" - "@stablelib/sha256" "1.0.1" - "@stablelib/x25519" "1.0.3" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.16.1" - "@walletconnect/window-getters" "1.0.1" - "@walletconnect/window-metadata" "1.0.1" - detect-browser "5.3.0" - elliptic "^6.5.7" - query-string "7.1.3" - uint8arrays "3.1.0" - "@walletconnect/utils@2.17.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.17.0.tgz#02b3af0b80d0c1a994d692d829d066271b04d071" @@ -6752,32 +6750,6 @@ query-string "7.1.3" uint8arrays "3.1.0" -"@walletconnect/utils@2.17.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.17.2.tgz#b4b12e3f5ebbfd883b2a5c87fb818e53501dc7ea" - integrity sha512-T7eLRiuw96fgwUy2A5NZB5Eu87ukX8RCVoO9lji34RFV4o2IGU9FhTEWyd4QQKI8OuQRjSknhbJs0tU0r0faPw== - dependencies: - "@ethersproject/hash" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@stablelib/chacha20poly1305" "1.0.1" - "@stablelib/hkdf" "1.0.1" - "@stablelib/random" "1.0.2" - "@stablelib/sha256" "1.0.1" - "@stablelib/x25519" "1.0.3" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/window-getters" "1.0.1" - "@walletconnect/window-metadata" "1.0.1" - detect-browser "5.3.0" - elliptic "6.6.0" - query-string "7.1.3" - uint8arrays "3.1.0" - "@walletconnect/window-getters@1.0.1", "@walletconnect/window-getters@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" @@ -6793,161 +6765,6 @@ "@walletconnect/window-getters" "^1.0.1" tslib "1.14.1" -"@web3modal/base@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/base/-/base-5.1.11.tgz#11beaca17fd0193d249174fb20da7bbb605abb2c" - integrity sha512-wJCsqQ1FG0Isiv0Exaz2Sv+FpijVmNPNay+sGdV5HP2SpBAR/1xxHca2/vLBdACX7rYAFAj723DYQE0fmUpIaw== - dependencies: - "@walletconnect/utils" "2.16.1" - "@web3modal/common" "5.1.11" - "@web3modal/core" "5.1.11" - "@web3modal/polyfills" "5.1.11" - "@web3modal/scaffold-ui" "5.1.11" - "@web3modal/scaffold-utils" "5.1.11" - "@web3modal/siwe" "5.1.11" - "@web3modal/ui" "5.1.11" - "@web3modal/wallet" "5.1.11" - optionalDependencies: - borsh "0.7.0" - bs58 "5.0.0" - -"@web3modal/common@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@web3modal/common/-/common-4.2.3.tgz#76748206f56294124b9841e00fbbfc5d09ab8c4c" - integrity sha512-n0lvhoRjViqxmkgpy+iEM6E3HBylUgdxUDJU4hUxGmmrbGZGEP7USBRnQOEgXLqLCtWvxKjUAO33JBV/De+Osw== - dependencies: - bignumber.js "9.1.2" - dayjs "1.11.10" - -"@web3modal/common@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/common/-/common-5.1.11.tgz#29f6a0df6d6e1df7c3adb619efab08a6f20d4eab" - integrity sha512-YfSklKjjiM1RGxFTQm3ycYZ2Ktb6vswt9eg8lGXRknxN+SC7bCtuvgtyyCO0Z9/f9dPMOGIAmoJ/y6WHXWQqcg== - dependencies: - bignumber.js "9.1.2" - dayjs "1.11.10" - -"@web3modal/core@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@web3modal/core/-/core-4.2.3.tgz#13c26e93e6328df76565abe421a4fce38d793d30" - integrity sha512-UykKZTELBpb6ey+IV6fkHWsLkjrIdILmRYzhlznyTPbm9qX5pOR9tH0Z3QGUo7YPFmUqMRH1tC9Irsr3SgIbbw== - dependencies: - "@web3modal/common" "4.2.3" - "@web3modal/wallet" "4.2.3" - valtio "1.11.2" - -"@web3modal/core@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/core/-/core-5.1.11.tgz#96406333c00ca949dbd1e8469e05b65d9c15551e" - integrity sha512-ugUVFVml1vVW+V7yxkn/AYYdrUJzn4ulFbDlxDMpmukKY6sDYLMMGAJ84O8ZC/OPyC7009NYd3mKZurxEyWkHw== - dependencies: - "@web3modal/common" "5.1.11" - "@web3modal/wallet" "5.1.11" - valtio "1.11.2" - -"@web3modal/ethers@^5.1.5": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/ethers/-/ethers-5.1.11.tgz#19ff7a069ae6c33061274a138bc4d114211c3776" - integrity sha512-xxZqk9nfrS96Wvver5ArrmxJ/uPdnEY/qduaSbpv9g6jlmbLNFrB3mREQJd7P05XKkVghWpDHmqsKLoRhZfKMQ== - dependencies: - "@coinbase/wallet-sdk" "4.0.3" - "@walletconnect/ethereum-provider" "2.16.1" - "@walletconnect/utils" "2.16.1" - "@web3modal/base" "5.1.11" - "@web3modal/common" "5.1.11" - "@web3modal/polyfills" "5.1.11" - "@web3modal/scaffold-utils" "5.1.11" - "@web3modal/siwe" "5.1.11" - "@web3modal/wallet" "5.1.11" - valtio "1.11.2" - -"@web3modal/polyfills@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@web3modal/polyfills/-/polyfills-4.2.3.tgz#9119fc5e3d32ed7706cc3506173b13a975946428" - integrity sha512-RiGxh2hMLSD1s2aTjoejNK/UL377CJhGf5tzmdF1m5xsYHpil+Dnulpio8Yojnm27cOqQD+QiaYUKnHOxErLjQ== - dependencies: - buffer "6.0.3" - -"@web3modal/polyfills@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/polyfills/-/polyfills-5.1.11.tgz#15f946e22c8d97dd43edc6fa8b7ff724c80e613d" - integrity sha512-BDIDYA2LGTCquahbZ+wyWQy4IBOPeKVSgt4ZpFir1fnVJUPkEluSwZStcKLtCzQvxJgER1sLicUrjJQHF36TOg== - dependencies: - buffer "6.0.3" - -"@web3modal/scaffold-ui@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/scaffold-ui/-/scaffold-ui-5.1.11.tgz#8e0e30c5da898b23b63dc4da5b9682d6ce99ca67" - integrity sha512-fBqzd7DStUaEjtdbEU86rzY4XIgt8c8JN8oxS/xnUEopmjFYvBLCCVEfbTkZyJrRvAAphz7+oS4TVzXw9k6t5A== - dependencies: - "@web3modal/common" "5.1.11" - "@web3modal/core" "5.1.11" - "@web3modal/scaffold-utils" "5.1.11" - "@web3modal/siwe" "5.1.11" - "@web3modal/ui" "5.1.11" - "@web3modal/wallet" "5.1.11" - lit "3.1.0" - -"@web3modal/scaffold-utils@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/scaffold-utils/-/scaffold-utils-5.1.11.tgz#85d880ca2ddea253ffb2f9fbccb9c9c3922ad107" - integrity sha512-4bcYpQ3oxak5mDZMW5/7ayrhpaJHy6dCfUio15AGPHnQlFjkqcfSuuG0Io8Oj8VUXcK2UBLch9YiEDz4Xgce9Q== - dependencies: - "@web3modal/common" "5.1.11" - "@web3modal/core" "5.1.11" - "@web3modal/polyfills" "5.1.11" - "@web3modal/wallet" "5.1.11" - valtio "1.11.2" - -"@web3modal/scaffold-utils@^4.1.11": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@web3modal/scaffold-utils/-/scaffold-utils-4.2.3.tgz#5eb990c127d8b51aad1da0e7322ead752f3544b3" - integrity sha512-z6t0ggYg1/8hpaKHUm77z2VyacjIZEZTI8IHSQYmHuRFGu5oDPJeAr1thr475JXdoGLYr08hwquZyed/ZINAvw== - dependencies: - "@web3modal/core" "4.2.3" - "@web3modal/polyfills" "4.2.3" - valtio "1.11.2" - -"@web3modal/siwe@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/siwe/-/siwe-5.1.11.tgz#f68a43e7d5c5417ebfb85f82ce3478db4c5bc780" - integrity sha512-1aKEtMosACyY0SRjHjdcA/g3bRtMojTxlK7S/T6zBk57X/P3xcEZq9J8UM73plmGewjZdLaqGMgv6B/k/WleZQ== - dependencies: - "@walletconnect/utils" "2.16.1" - "@web3modal/common" "5.1.11" - "@web3modal/core" "5.1.11" - "@web3modal/scaffold-utils" "5.1.11" - "@web3modal/ui" "5.1.11" - "@web3modal/wallet" "5.1.11" - lit "3.1.0" - valtio "1.11.2" - -"@web3modal/ui@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/ui/-/ui-5.1.11.tgz#1bb5bdf3a54bbdf7d0068fdb65a46bc921da160c" - integrity sha512-L0L+2YOK+ONx+W7GPtkSdKZuAQ8cjcS5N8kp+WZzKOMUTeDLuXKtSnES4p/ShOVmkpV6qB8r0pPA9xgFh1D3ow== - dependencies: - lit "3.1.0" - qrcode "1.5.3" - -"@web3modal/wallet@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@web3modal/wallet/-/wallet-4.2.3.tgz#6b3317c7af60427b54417d0c9736fe4b5115fdb4" - integrity sha512-V+VpwmhQl9qeJMpzNkjpAaxercAsrr1O9oGRjrjD+c0q72NfdcbTalWSbjSQmqabI1M6N06Hw94FkAQuEfVGsg== - dependencies: - "@web3modal/polyfills" "4.2.3" - zod "3.22.4" - -"@web3modal/wallet@5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@web3modal/wallet/-/wallet-5.1.11.tgz#3118bb1fa370436c252d7d97c731eac585cdb8a7" - integrity sha512-/ooQZXK1h7LGBUemebldYPAV2oJAgxkgSiCMoHWynhuS0LO3BzhOhGL+jV19w4iU81bS1GSNFTxYT9LL6Scesw== - dependencies: - "@walletconnect/logger" "2.1.2" - "@web3modal/common" "5.1.11" - "@web3modal/polyfills" "5.1.11" - zod "3.22.4" - "@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": version "1.12.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" @@ -7717,6 +7534,11 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + ast-types-flow@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" @@ -7969,10 +7791,10 @@ base-x@^3.0.2: dependencies: safe-buffer "^5.0.1" -base-x@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" - integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== +base-x@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.0.tgz#6d835ceae379130e1a4cb846a70ac4746f28ea9b" + integrity sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ== base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" @@ -8097,15 +7919,6 @@ body-parser@1.20.3, body-parser@^1.20.0, body-parser@^1.20.2: type-is "~1.6.18" unpipe "1.0.0" -borsh@0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" - integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== - dependencies: - bn.js "^5.2.0" - bs58 "^4.0.0" - text-encoding-utf-8 "^1.0.2" - bowser@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" @@ -8273,12 +8086,12 @@ bs-logger@0.x, bs-logger@^0.2.6: dependencies: fast-json-stable-stringify "2.x" -bs58@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" - integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== +bs58@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" + integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw== dependencies: - base-x "^4.0.0" + base-x "^5.0.0" bs58@^4.0.0: version "4.0.1" @@ -8622,6 +8435,17 @@ chai@^4.3.10, chai@^4.5.0: pathval "^1.1.1" type-detect "^4.1.0" +chai@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d" + integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + chalk-template@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b" @@ -8701,6 +8525,11 @@ check-error@^1.0.2, check-error@^1.0.3: dependencies: get-func-name "^2.0.2" +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + chokidar@3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -9661,7 +9490,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@~4.3.1, debug@~4.3.2, debug@~4.3.6: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7, debug@~4.3.1, debug@~4.3.2, debug@~4.3.6: version "4.3.7" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== @@ -9732,6 +9561,11 @@ deep-eql@^4.0.1, deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -10114,7 +9948,7 @@ elliptic@6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -elliptic@6.6.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.5, elliptic@^6.5.7: +elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.5, elliptic@^6.5.7: version "6.6.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== @@ -10337,7 +10171,7 @@ es-module-lexer@1.4.1: resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== -es-module-lexer@^1.2.1: +es-module-lexer@^1.2.1, es-module-lexer@^1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== @@ -11222,6 +11056,11 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== +expect-type@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75" + integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA== + expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" @@ -14798,7 +14637,7 @@ loupe@^2.3.6, loupe@^2.3.7: dependencies: get-func-name "^2.0.1" -loupe@^3.1.2: +loupe@^3.1.0, loupe@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240" integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg== @@ -14861,6 +14700,13 @@ magic-string@0.30.8: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +magic-string@^0.30.12: + version "0.30.13" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.13.tgz#92438e3ff4946cf54f18247c981e5c161c46683c" + integrity sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + magic-string@^0.30.3, magic-string@^0.30.5: version "0.30.12" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60" @@ -16508,6 +16354,11 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pathval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" + integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== + pause@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" @@ -16806,7 +16657,7 @@ postgres-range@^1.1.1: resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== -preact@^10.16.0: +preact@^10.16.0, preact@^10.24.2: version "10.24.3" resolved "https://registry.yarnpkg.com/preact/-/preact-10.24.3.tgz#086386bd47071e3b45410ef20844c21e23828f64" integrity sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA== @@ -18581,6 +18432,11 @@ std-env@^3.5.0, std-env@^3.7.0: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== +std-env@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" + integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== + stdout-stream@^1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" @@ -18675,16 +18531,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18801,7 +18648,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18815,13 +18662,6 @@ strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -19176,11 +19016,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-encoding-utf-8@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" - integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -19274,11 +19109,16 @@ tiny-warning@^1.0.2: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -tinybench@^2.5.1: +tinybench@^2.5.1, tinybench@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== +tinyexec@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98" + integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ== + tinyglobby@^0.2.9: version "0.2.10" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.10.tgz#e712cf2dc9b95a1f5c5bbd159720e15833977a0f" @@ -19292,6 +19132,11 @@ tinypool@^0.8.3: resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.4.tgz#e217fe1270d941b39e98c625dcecebb1408c9aa8" integrity sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ== +tinypool@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2" + integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA== + tinyrainbow@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" @@ -19302,6 +19147,11 @@ tinyspy@^2.2.0: resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1" integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A== +tinyspy@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" + integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== + tldts-core@^6.1.58: version "6.1.58" resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.58.tgz#f0b5c1fcb2e214f558c7cb380fb1e6f4b2459d8b" @@ -20283,6 +20133,21 @@ viem@2.x, viem@^2.1.1: webauthn-p256 "0.0.10" ws "8.18.0" +viem@^2.21.44: + version "2.21.50" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.50.tgz#a645a7fb4a017c644712b905e03ab533b7e24ea7" + integrity sha512-WHB8NmkaForODuSALb0Ai3E296aEigzYSE+pzB9Y0cTNJeiZT8rpkdxxUFYfjwFMnPkz2tivqrSpuw3hO5TH6w== + dependencies: + "@noble/curves" "1.6.0" + "@noble/hashes" "1.5.0" + "@scure/bip32" "1.5.0" + "@scure/bip39" "1.4.0" + abitype "1.0.6" + isows "1.0.6" + ox "0.1.2" + webauthn-p256 "0.0.10" + ws "8.18.0" + vite-node@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.6.0.tgz#2c7e61129bfecc759478fa592754fd9704aaba7f" @@ -20294,6 +20159,17 @@ vite-node@1.6.0: picocolors "^1.0.0" vite "^5.0.0" +vite-node@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.5.tgz#cf28c637b2ebe65921f3118a165b7cf00a1cdf19" + integrity sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w== + dependencies: + cac "^6.7.14" + debug "^4.3.7" + es-module-lexer "^1.5.4" + pathe "^1.1.2" + vite "^5.0.0" + vite-plugin-node-polyfills@^0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz#d0afcf82eb985fc02244620d7cec1ddd1c6e0864" @@ -20348,6 +20224,32 @@ vitest@^1.2.2, vitest@^1.6.0: vite-node "1.6.0" why-is-node-running "^2.2.2" +vitest@^2.1.2: + version "2.1.5" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.5.tgz#a93b7b84a84650130727baae441354e6df118148" + integrity sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A== + dependencies: + "@vitest/expect" "2.1.5" + "@vitest/mocker" "2.1.5" + "@vitest/pretty-format" "^2.1.5" + "@vitest/runner" "2.1.5" + "@vitest/snapshot" "2.1.5" + "@vitest/spy" "2.1.5" + "@vitest/utils" "2.1.5" + chai "^5.1.2" + debug "^4.3.7" + expect-type "^1.1.0" + magic-string "^0.30.12" + pathe "^1.1.2" + std-env "^3.8.0" + tinybench "^2.9.0" + tinyexec "^0.3.1" + tinypool "^1.0.1" + tinyrainbow "^1.2.0" + vite "^5.0.0" + vite-node "2.1.5" + why-is-node-running "^2.3.0" + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -20377,6 +20279,15 @@ wabt@1.0.24: resolved "https://registry.yarnpkg.com/wabt/-/wabt-1.0.24.tgz#c02e0b5b4503b94feaf4a30a426ef01c1bea7c6c" integrity sha512-8l7sIOd3i5GWfTWciPL0+ff/FK/deVK2Q6FN+MPz4vfUcD78i2M/49XJTwF6aml91uIiuXJEsLKWMB2cw/mtKg== +wagmi@2.12.29: + version "2.12.29" + resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-2.12.29.tgz#5695df91169033833faadb3497a8ab440e682772" + integrity sha512-g8wf4oGTxtrwgbpi1NcRvidx7ZRsSMb2LB53Qk3I2Pr7s4m11y1fNYb15PfQpDIHdX7eaXM5OC6/NhVFB0diiQ== + dependencies: + "@wagmi/connectors" "5.3.7" + "@wagmi/core" "2.14.4" + use-sync-external-store "1.2.0" + wagmi@^2.12.8: version "2.12.26" resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-2.12.26.tgz#dc8f04d6733fb0c452dac67d93ceddd0b4d2fedc" @@ -20884,7 +20795,7 @@ which@^1.1.1, which@^1.3.1: dependencies: isexe "^2.0.0" -why-is-node-running@^2.2.2: +why-is-node-running@^2.2.2, why-is-node-running@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== @@ -20936,7 +20847,7 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20954,15 +20865,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 6868a0d60eccdbbde6ba906a89d8277f6d4d81a5 Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Mon, 25 Nov 2024 18:47:23 +0300 Subject: [PATCH 11/92] [Human App] fix: invalid imports of auth schema (#2842) --- .../apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx | 2 +- packages/apps/human-app/frontend/src/auth/auth-context.tsx | 2 +- .../frontend/src/shared/types/browser-auth-provider.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx b/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx index 2d93dbc4b0..9c63b56989 100644 --- a/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx +++ b/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx @@ -3,7 +3,7 @@ import { useState, createContext, useEffect } from 'react'; import { jwtDecode } from 'jwt-decode'; import { z } from 'zod'; import { useQueryClient } from '@tanstack/react-query'; -import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/sign-in'; +import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/types'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; import { useModalStore } from '@/components/ui/modal/modal.store'; diff --git a/packages/apps/human-app/frontend/src/auth/auth-context.tsx b/packages/apps/human-app/frontend/src/auth/auth-context.tsx index 0e2452bcac..8b62bd39d4 100644 --- a/packages/apps/human-app/frontend/src/auth/auth-context.tsx +++ b/packages/apps/human-app/frontend/src/auth/auth-context.tsx @@ -3,7 +3,7 @@ import { useState, createContext, useEffect } from 'react'; import { jwtDecode } from 'jwt-decode'; import { z } from 'zod'; import { useQueryClient } from '@tanstack/react-query'; -import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/sign-in'; +import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/types'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; import { useModalStore } from '@/components/ui/modal/modal.store'; diff --git a/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts b/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts index 75412f6252..a0e069b342 100644 --- a/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts +++ b/packages/apps/human-app/frontend/src/shared/types/browser-auth-provider.ts @@ -1,4 +1,4 @@ -import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/sign-in'; +import type { SignInSuccessResponse } from '@/api/services/worker/sign-in/types'; import type { Web3UserData } from '@/auth-web3/web3-auth-context'; import type { UserData } from '@/auth/auth-context'; From ab367476b9488d217e9c831df43895ee30b721df Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Mon, 25 Nov 2024 19:16:51 +0300 Subject: [PATCH 12/92] [Human App] feat: ui-configuration endpoint (#2841) * feat: add ui configuration module * refactor: get rid of chain ids in oracles response --- .../src/api/services/worker/oracles.ts | 11 +++---- .../apps/human-app/server/src/app.module.ts | 2 ++ .../src/modules/cron-job/cron-job.service.ts | 20 ++++++------ .../cron-job/spec/cron-job.service.spec.ts | 16 +++++----- .../model/oracle-discovery.model.ts | 15 +-------- .../oracle-discovery.controller.ts | 7 ++-- .../oracle-discovery.service.ts | 22 ++++++------- .../spec/oracle-discovery.controller.spec.ts | 4 +-- .../spec/oracle-discovery.fixture.ts | 31 +++++++----------- .../spec/oracle-discovery.service.spec.ts | 4 +-- .../ui-configuration.controller.spec.ts | 32 +++++++++++++++++++ .../ui-configuration.controller.ts | 23 +++++++++++++ .../ui-configuration/ui-configuration.dto.ts | 9 ++++++ .../ui-configuration.module.ts | 7 ++++ 14 files changed, 122 insertions(+), 81 deletions(-) create mode 100644 packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts create mode 100644 packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts create mode 100644 packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts create mode 100644 packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts diff --git a/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts b/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts index 87ce2cd38a..a5aa7f7c9a 100644 --- a/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts +++ b/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts @@ -16,10 +16,7 @@ const OracleSchema = z.object({ registrationInstructions: z.string().optional().nullable(), }); -const OraclesDiscoverSuccessSchema = z.object({ - oracles: z.array(OracleSchema), - chainIdsEnabled: z.array(z.string()), -}); +const OraclesDiscoverySuccessSchema = z.array(OracleSchema); export type Oracle = z.infer & { name: string; @@ -62,17 +59,17 @@ export async function getOracles({ ? `?${stringifyUrlQueryObject({ selected_job_types })}` : ''; - const result = await apiClient( + const results = await apiClient( `${apiPaths.worker.oracles.path}${queryParams}`, { - successSchema: OraclesDiscoverSuccessSchema, + successSchema: OraclesDiscoverySuccessSchema, options: { method: 'GET' }, }, signal ); oracles = oracles.concat( - result.oracles.map((oracle) => ({ + results.map((oracle) => ({ ...oracle, name: oracleUrlToNameMap.get(oracle.url) ?? '', })) diff --git a/packages/apps/human-app/server/src/app.module.ts b/packages/apps/human-app/server/src/app.module.ts index 131af0ada1..35c816d192 100644 --- a/packages/apps/human-app/server/src/app.module.ts +++ b/packages/apps/human-app/server/src/app.module.ts @@ -42,6 +42,7 @@ import { CronJobModule } from './modules/cron-job/cron-job.module'; import { EnvironmentConfigService } from './common/config/environment-config.service'; import { ForbidUnauthorizedHostMiddleware } from './common/middleware/host-check.middleware'; import { HealthModule } from './modules/health/health.module'; +import { UiConfigurationModule } from './modules/ui-configuration/ui-configuration.module'; const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false'); @@ -122,6 +123,7 @@ const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false'); TokenRefreshModule, CronJobModule, HealthModule, + UiConfigurationModule, ], controllers: [ AppController, diff --git a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts index 1a34914156..10b1ce5c9d 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts @@ -13,7 +13,7 @@ import { JOB_DISCOVERY_CACHE_KEY } from '../../common/constants/cache'; import { OracleDiscoveryService } from '../oracle-discovery/oracle-discovery.service'; import { OracleDiscoveryCommand, - OracleDiscoveryResponse, + OracleDiscoveryResult, } from '../oracle-discovery/model/oracle-discovery.model'; import { WorkerService } from '../user-worker/worker.service'; import { JobDiscoveryFieldName } from '../../common/enums/global-common'; @@ -48,11 +48,9 @@ export class CronJobService { this.logger.log('CRON START'); const oracleDiscoveryCommand: OracleDiscoveryCommand = {}; - const oracles = ( - await this.oracleDiscoveryService.processOracleDiscovery( - oracleDiscoveryCommand, - ) - ).oracles; + const oracles = await this.oracleDiscoveryService.processOracleDiscovery( + oracleDiscoveryCommand, + ); if (!oracles || oracles.length < 1) return; @@ -86,7 +84,7 @@ export class CronJobService { this.logger.log('CRON END'); } - async updateJobsListCache(oracle: OracleDiscoveryResponse, token: string) { + async updateJobsListCache(oracle: OracleDiscoveryResult, token: string) { try { let allResults: JobsDiscoveryResponseItem[] = []; @@ -138,13 +136,13 @@ export class CronJobService { } private async updateOracleInCache( - oracleData: OracleDiscoveryResponse, - updates: Partial, + oracleData: OracleDiscoveryResult, + updates: Partial, ) { const updatedOracle = { ...oracleData, ...updates }; const chainId = oracleData.chainId; const cachedOracles = - await this.cacheManager.get(chainId); + await this.cacheManager.get(chainId); if (cachedOracles) { const updatedOracles = cachedOracles.map((oracle) => @@ -158,7 +156,7 @@ export class CronJobService { } } - private async handleJobListError(oracleData: OracleDiscoveryResponse) { + private async handleJobListError(oracleData: OracleDiscoveryResult) { const retriesCount = oracleData.retriesCount || 0; const newExecutionsToSkip = Math.min( (oracleData.executionsToSkip || 0) + Math.pow(2, retriesCount), diff --git a/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts b/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts index 729829f35a..ee12e94f13 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts @@ -11,7 +11,7 @@ import { } from '../../../modules/jobs-discovery/model/jobs-discovery.model'; import { JOB_DISCOVERY_CACHE_KEY } from '../../../common/constants/cache'; import { JobStatus } from '../../../common/enums/global-common'; -import { OracleDiscoveryResponse } from '../../../modules/oracle-discovery/model/oracle-discovery.model'; +import { OracleDiscoveryResult } from '../../../modules/oracle-discovery/model/oracle-discovery.model'; import { SchedulerRegistry } from '@nestjs/schedule'; import { generateOracleDiscoveryResponseBody } from '../../../modules/oracle-discovery/spec/oracle-discovery.fixture'; @@ -157,7 +157,7 @@ describe('CronJobService', () => { password: configServiceMock.password, }); expect(updateJobsListCacheSpy).toHaveBeenCalledWith( - oraclesDiscovery.oracles[0], + oraclesDiscovery[0], 'Bearer token', ); }); @@ -165,7 +165,7 @@ describe('CronJobService', () => { describe('updateJobsListCache', () => { it('should fetch all jobs and update the cache', async () => { - const oracle: OracleDiscoveryResponse = { + const oracle: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', chainId: '137', @@ -193,7 +193,7 @@ describe('CronJobService', () => { }); it('should handle errors and call handleJobListError', async () => { - const oracle: OracleDiscoveryResponse = { + const oracle: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', chainId: '137', @@ -219,7 +219,7 @@ describe('CronJobService', () => { }); it('should reset retries count after successful job fetch', async () => { - const oracle: OracleDiscoveryResponse = { + const oracle: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', chainId: '137', @@ -319,7 +319,7 @@ describe('CronJobService', () => { describe('updateOracleInCache', () => { it('should update oracle in cache', async () => { - const oracleData: OracleDiscoveryResponse = { + const oracleData: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', chainId: '137', @@ -344,7 +344,7 @@ describe('CronJobService', () => { describe('handleJobListError', () => { it('should increment retries count and executions to skip but not exceed the limit', async () => { - const oracleData: OracleDiscoveryResponse = { + const oracleData: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', chainId: '137', @@ -364,7 +364,7 @@ describe('CronJobService', () => { }); it('should increment retries count and executions to skip', async () => { - const oracleData: OracleDiscoveryResponse = { + const oracleData: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', chainId: '137', diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts index f15a61c5fc..27c50e6ad3 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts @@ -4,7 +4,7 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsArray, IsOptional } from 'class-validator'; import { Exclude, Transform } from 'class-transformer'; -export class OracleDiscoveryResponse implements IOperator { +export class OracleDiscoveryResult implements IOperator { @ApiProperty({ description: 'Address of the oracle operator' }) address: string; @@ -55,19 +55,6 @@ export class OracleDiscoveryResponse implements IOperator { this.registrationInstructions = registrationInstructions; } } - -export class OracleDiscoveryResponseDto { - @ApiProperty({ - type: [OracleDiscoveryResponse], - description: 'List of discovered oracles', - }) - oracles: OracleDiscoveryResponse[]; - @ApiProperty({ - type: [String], - description: 'Chain ids where oracles haven been discovered', - }) - chainIdsEnabled: string[]; -} export class OracleDiscoveryDto { @ApiPropertyOptional({ type: [String] }) @IsArray() diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts index 259d250025..66782d6cc4 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts @@ -12,8 +12,7 @@ import { OracleDiscoveryService } from './oracle-discovery.service'; import { OracleDiscoveryCommand, OracleDiscoveryDto, - OracleDiscoveryResponse, - OracleDiscoveryResponseDto, + OracleDiscoveryResult, } from './model/oracle-discovery.model'; import { InjectMapper } from '@automapper/nestjs'; import { Mapper } from '@automapper/core'; @@ -30,13 +29,13 @@ export class OracleDiscoveryController { @Get('/oracles') @ApiOperation({ summary: 'Oracles discovery' }) @ApiOkResponse({ - type: OracleDiscoveryResponse, + type: Array, description: 'List of oracles', }) @UsePipes(new ValidationPipe()) public async getOracles( @Query() dto: OracleDiscoveryDto, - ): Promise { + ): Promise { if (!this.environmentConfigService.jobsDiscoveryFlag) { throw new HttpException( 'Oracles discovery is disabled', diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts index 8eb006a4cc..9e9b42cd6b 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts @@ -1,8 +1,7 @@ import { Inject, Injectable, Logger } from '@nestjs/common'; import { OracleDiscoveryCommand, - OracleDiscoveryResponse, - OracleDiscoveryResponseDto, + OracleDiscoveryResult, } from './model/oracle-discovery.model'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; @@ -20,7 +19,7 @@ export class OracleDiscoveryService { async processOracleDiscovery( command: OracleDiscoveryCommand, - ): Promise { + ): Promise { const address = this.configService.reputationOracleAddress; const chainIds = this.configService.chainIdsEnabled; const oraclesForChainIds = await Promise.all( @@ -29,10 +28,7 @@ export class OracleDiscoveryService { ), ); - const response: OracleDiscoveryResponseDto = { - oracles: [], - chainIdsEnabled: this.configService.chainIdsEnabled, - }; + const oracles: OracleDiscoveryResult[] = []; for (const oraclesForChainId of oraclesForChainIds) { for (const oracle of oraclesForChainId) { if (command.selectedJobTypes?.length) { @@ -50,19 +46,19 @@ export class OracleDiscoveryService { } } - response.oracles.push(oracle); + oracles.push(oracle); } } - return response; + return oracles; } private async findOraclesByChainId( chainId: string, address: string, - ): Promise { + ): Promise { try { - const cachedOracles: OracleDiscoveryResponse[] | undefined = + const cachedOracles: OracleDiscoveryResult[] | undefined = await this.cacheManager.get(chainId); if (cachedOracles) { @@ -76,13 +72,13 @@ export class OracleDiscoveryService { Role.ExchangeOracle, ); - const oraclesWithRetryData: OracleDiscoveryResponse[] = []; + const oraclesWithRetryData: OracleDiscoveryResult[] = []; for (const operator of operators) { const isOperatorValid = !!operator.url; if (isOperatorValid) { oraclesWithRetryData.push( - new OracleDiscoveryResponse( + new OracleDiscoveryResult( operator.address, chainId, operator.role, diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts index 98c94e0a01..fa5215d28e 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts @@ -7,7 +7,7 @@ import { oracleDiscoveryServiceMock } from './oracle-discovery.service.mock'; import { OracleDiscoveryCommand, OracleDiscoveryDto, - OracleDiscoveryResponseDto, + OracleDiscoveryResult, } from '../model/oracle-discovery.model'; import { generateOracleDiscoveryResponseBody } from './oracle-discovery.fixture'; import { OracleDiscoveryProfile } from '../oracle-discovery.mapper.profile'; @@ -68,7 +68,7 @@ describe('OracleDiscoveryController', () => { const commandFixture = { selectedJobTypes: ['job-type-1', 'job-type-2'], } as OracleDiscoveryCommand; - const result: OracleDiscoveryResponseDto = + const result: OracleDiscoveryResult[] = await controller.getOracles(dtoFixture); const expectedResponse = generateOracleDiscoveryResponseBody(); expect(serviceMock.processOracleDiscovery).toHaveBeenCalledWith( diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts index 2a205f5db7..e948bba2e3 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts @@ -1,9 +1,9 @@ import { OracleDiscoveryCommand, - OracleDiscoveryResponse, + OracleDiscoveryResult, } from '../model/oracle-discovery.model'; -const response1: OracleDiscoveryResponse = { +const response1: OracleDiscoveryResult = { address: '0xd06eac24a0c47c776Ce6826A93162c4AfC029047', chainId: '4200', role: 'role1', @@ -14,7 +14,7 @@ const response1: OracleDiscoveryResponse = { registrationNeeded: true, registrationInstructions: 'https://instructions.com', }; -const response2: OracleDiscoveryResponse = { +const response2: OracleDiscoveryResult = { address: '0xd10c3402155c058D78e4D5fB5f50E125F06eb39d', chainId: '4200', role: 'role2', @@ -24,7 +24,7 @@ const response2: OracleDiscoveryResponse = { registrationNeeded: false, registrationInstructions: undefined, }; -const response3: OracleDiscoveryResponse = { +const response3: OracleDiscoveryResult = { address: '0xd83422155c058D78e4D5fB5f50E125F06eb39d', chainId: '4200', role: 'role3', @@ -35,7 +35,7 @@ const response3: OracleDiscoveryResponse = { registrationNeeded: false, registrationInstructions: undefined, }; -const response4: OracleDiscoveryResponse = { +const response4: OracleDiscoveryResult = { address: '0xd83422155c058D78e4D5fB5f50E125F06eb39d', chainId: '4201', role: 'role3', @@ -56,26 +56,17 @@ export function generateGetReputationNetworkOperatorsResponseByChainId( } export function generateOracleDiscoveryResponseBodyByChainId(chainId: string) { - return { - oracles: [response1, response3, response4].filter( - (oracle) => oracle.chainId === chainId, - ), - chainIdsEnabled: ['4200', '4201'], - }; + return [response1, response3, response4].filter( + (oracle) => oracle.chainId === chainId, + ); } export function generateOracleDiscoveryResponseBody() { - return { - oracles: [response1, response3, response4], - chainIdsEnabled: ['4200', '4201'], - }; + return [response1, response3, response4]; } export function generateOracleDiscoveryResponseBodyByJobType() { - return { - oracles: [response3, response4], - chainIdsEnabled: ['4200', '4201'], - }; + return [response3, response4]; } export const filledCommandFixture = { @@ -85,4 +76,4 @@ export const emptyCommandFixture = { selectedJobTypes: [], } as OracleDiscoveryCommand; export const notSetCommandFixture = {} as OracleDiscoveryCommand; -export const errorResponse = { chainIdsEnabled: ['4200', '4201'], oracles: [] }; +export const errorResponse = []; diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts index 8f0b2788fe..df2cefc595 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts @@ -84,7 +84,7 @@ describe('OracleDiscoveryService', () => { jest .spyOn(cacheManager, 'get') .mockResolvedValueOnce( - generateOracleDiscoveryResponseBodyByChainId(chainId).oracles, + generateOracleDiscoveryResponseBodyByChainId(chainId), ); }); @@ -113,7 +113,7 @@ describe('OracleDiscoveryService', () => { expect(cacheManager.get).toHaveBeenCalledWith(chainId); expect(cacheManager.set).toHaveBeenCalledWith( chainId, - generateOracleDiscoveryResponseBodyByChainId(chainId).oracles, + generateOracleDiscoveryResponseBodyByChainId(chainId), TTL, ); expect(OperatorUtils.getReputationNetworkOperators).toHaveBeenCalledWith( diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts new file mode 100644 index 0000000000..d0ba594643 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts @@ -0,0 +1,32 @@ +import { ConfigModule } from '@nestjs/config'; +import { Test, TestingModule } from '@nestjs/testing'; +import { UiConfigurationController } from './ui-configuration.controller'; +import { EnvironmentConfigService } from '../../common/config/environment-config.service'; + +process.env.CHAIN_IDS_ENABLED = '15,42'; + +describe('UiConfigurationController', () => { + let controller: UiConfigurationController; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [ + ConfigModule.forRoot({ + envFilePath: '.env', + isGlobal: true, + }), + ], + providers: [EnvironmentConfigService], + controllers: [UiConfigurationController], + }).compile(); + + controller = module.get( + UiConfigurationController, + ); + }); + + it('should return proper config', async () => { + const result = await controller.getConfig(); + expect(result.chainIdsEnabled).toEqual(['15', '42']); + }); +}); diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts new file mode 100644 index 0000000000..8c419c5fcf --- /dev/null +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts @@ -0,0 +1,23 @@ +import { Controller, Get } from '@nestjs/common'; +import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { EnvironmentConfigService } from '../../common/config/environment-config.service'; +import { UiConfigResponseDto } from './ui-configuration.dto'; + +@Controller() +@ApiTags('UI-Configuration') +export class UiConfigurationController { + constructor( + private readonly environmentConfigService: EnvironmentConfigService, + ) {} + @Get('/ui-config') + @ApiOperation({ summary: 'Retrieve UI configuration' }) + @ApiOkResponse({ + type: UiConfigResponseDto, + description: 'UI Configuration object', + }) + public async getConfig(): Promise { + return { + chainIdsEnabled: this.environmentConfigService.chainIdsEnabled, + }; + } +} diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts new file mode 100644 index 0000000000..18331806da --- /dev/null +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts @@ -0,0 +1,9 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class UiConfigResponseDto { + @ApiProperty({ + type: [String], + description: 'Chain ids enabled for the application', + }) + chainIdsEnabled: string[]; +} diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts new file mode 100644 index 0000000000..d14d2d39bd --- /dev/null +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { UiConfigurationController } from './ui-configuration.controller'; + +@Module({ + controllers: [UiConfigurationController], +}) +export class UiConfigurationModule {} From e4072375284a48efe6296b61458552724f617dfe Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:13:18 +0300 Subject: [PATCH 13/92] [Human App] Implemented oracle filter (#2697) * Implemented oracle filter * Reverted changes in rep oracle service * Resolved comments * Improved oracle discrovery service * Updated comment * Convert all chainIds values to type ChainId (#2765) * Updated method name * Fixed lint * Removed console.log * implemented unit test for processOracleDiscovery * Updated function name --------- Co-authored-by: portuu3 --- packages/apps/human-app/server/.env.example | 1 + .../config/environment-config.service.spec.ts | 60 ++++++++++++++++ .../config/environment-config.service.ts | 23 +++++- .../integrations/kv-store/kv-store.gateway.ts | 34 +++++++++ .../src/modules/cron-job/cron-job.service.ts | 3 +- .../cron-job/spec/cron-job.service.spec.ts | 22 +++--- .../spec/jobs-discovery.controller.spec.ts | 3 +- .../model/oracle-discovery.model.ts | 6 +- .../oracle-discovery.module.ts | 2 + .../oracle-discovery.service.ts | 72 ++++++++++++------- .../spec/oracle-discovery.controller.spec.ts | 3 +- .../spec/oracle-discovery.fixture.ts | 23 +++--- .../spec/oracle-discovery.service.spec.ts | 50 +++++++++++-- .../ui-configuration.controller.spec.ts | 8 ++- .../ui-configuration/ui-configuration.dto.ts | 5 +- 15 files changed, 250 insertions(+), 65 deletions(-) create mode 100644 packages/apps/human-app/server/src/common/config/environment-config.service.spec.ts diff --git a/packages/apps/human-app/server/.env.example b/packages/apps/human-app/server/.env.example index 96424edb0d..cc6083d8eb 100644 --- a/packages/apps/human-app/server/.env.example +++ b/packages/apps/human-app/server/.env.example @@ -20,6 +20,7 @@ CACHE_TTL_USER_STATS= # number, example: 86400 CACHE_TTL_EXCHANGE_ORACLE_URL= # number: example 86400 CACHE_TTL_HCAPTCHA_USER_STATS= # number: example 86400 CACHE_TTL_DAILY_HMT_SPENT= # number: example 86400 +CACHE_TTL_JOB_TYPES= # number: example 86400 # E2E TESTING E2E_TESTING_EMAIL_ADDRESS= # string E2E_TESTING_PASSWORD= # string diff --git a/packages/apps/human-app/server/src/common/config/environment-config.service.spec.ts b/packages/apps/human-app/server/src/common/config/environment-config.service.spec.ts new file mode 100644 index 0000000000..09a419b3be --- /dev/null +++ b/packages/apps/human-app/server/src/common/config/environment-config.service.spec.ts @@ -0,0 +1,60 @@ +import { ConfigService } from '@nestjs/config'; +import { Test, TestingModule } from '@nestjs/testing'; +import { EnvironmentConfigService } from './environment-config.service'; +import { ChainId } from '@human-protocol/sdk'; + +describe('EnvironmentConfigService', () => { + let service: EnvironmentConfigService; + let configService: ConfigService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + EnvironmentConfigService, + { + provide: ConfigService, + useValue: { + getOrThrow: jest.fn(), + }, + }, + ], + }).compile(); + + service = module.get(EnvironmentConfigService); + configService = module.get(ConfigService); + }); + + it('should return an array of valid ChainIds when CHAIN_IDS_ENABLED is valid', () => { + (configService.getOrThrow as jest.Mock).mockReturnValue('1, 4, 80002'); + + const result = service.chainIdsEnabled; + + expect(result).toEqual([ + ChainId.MAINNET, + ChainId.RINKEBY, + ChainId.POLYGON_AMOY, + ]); + }); + + it('should ignore invalid chain IDs and only return valid ChainIds', () => { + (configService.getOrThrow as jest.Mock).mockReturnValue( + '1, 4, 99999, 80002', + ); + + const result = service.chainIdsEnabled; + + expect(result).toEqual([ + ChainId.MAINNET, + ChainId.RINKEBY, + ChainId.POLYGON_AMOY, + ]); + }); + + it('should return an empty array if CHAIN_IDS_ENABLED is empty', () => { + (configService.getOrThrow as jest.Mock).mockReturnValue(''); + + const result = service.chainIdsEnabled; + + expect(result).toEqual([]); + }); +}); diff --git a/packages/apps/human-app/server/src/common/config/environment-config.service.ts b/packages/apps/human-app/server/src/common/config/environment-config.service.ts index ff55260d6e..4a81f4468b 100644 --- a/packages/apps/human-app/server/src/common/config/environment-config.service.ts +++ b/packages/apps/human-app/server/src/common/config/environment-config.service.ts @@ -1,5 +1,6 @@ import { ConfigService } from '@nestjs/config'; import { Injectable } from '@nestjs/common'; +import { ChainId } from '@human-protocol/sdk'; const DEFAULT_CACHE_TTL_HCAPTCHA_USER_STATS = 12 * 60 * 60; const DEFAULT_CACHE_TTL_ORACLE_STATS = 12 * 60 * 60; @@ -12,6 +13,7 @@ const DEFAULT_CORS_ALLOWED_HEADERS = 'Content-Type,Authorization,X-Requested-With,Accept,Origin'; const DEFAULT_CACHE_TTL_EXCHANGE_ORACLE_URL = 24 * 60 * 60; const DEFAULT_MAX_EXECUTIONS_TO_SKIP = 32; +const DEFAULT_CACHE_TTL_JOB_TYPES = 24 * 60 * 60; const DEFAULT_CACHE_TTL_EXCHANGE_ORACLE_REGISTRATION_NEEDED = 24 * 60 * 60; @Injectable() @@ -216,6 +218,17 @@ export class EnvironmentConfigService { ); } + /** + * The cache time-to-live (TTL) for job types. + * Default: 24 hours + */ + get cacheTtlJobTypes(): number { + return this.configService.get( + 'CACHE_TTL_JOB_TYPES', + DEFAULT_CACHE_TTL_JOB_TYPES, + ); + } + /** * The cache time-to-live (TTL) for exchange oracle registration needed. * Default: 24 hours @@ -261,9 +274,15 @@ export class EnvironmentConfigService { * The list of enabled chain IDs. * Required */ - get chainIdsEnabled(): string[] { + get chainIdsEnabled(): ChainId[] { const chainIds = this.configService.getOrThrow('CHAIN_IDS_ENABLED'); - return chainIds.split(',').map((id) => id.trim()); + return chainIds + .split(',') + .map((id) => parseInt(id.trim(), 10)) + .filter( + (id): id is ChainId => + !isNaN(id) && Object.values(ChainId).includes(id), + ); } /** diff --git a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts index d82bf2a996..33e515b7dc 100644 --- a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts @@ -51,4 +51,38 @@ export class KvStoreGateway { return fetchedData; } } + + async getJobTypesByAddress( + chainId: ChainId, + address: string, + ): Promise { + const key = `jobTypes:${address}`; + const cachedData: string | undefined = await this.cacheManager.get(key); + if (cachedData) { + return cachedData; + } + + let jobTypes: string; + try { + jobTypes = await KVStoreUtils.get(chainId, address, KVStoreKeys.jobTypes); + } catch (e) { + if (e.toString().includes('Error: Invalid address')) { + throw new HttpException( + `Unable to retrieve job types from address: ${address}`, + 400, + ); + } else { + throw new Error(`Error while fetching job types from kv-store: ${e}`); + } + } + + if (!jobTypes || jobTypes === '') { + return; + } else { + await this.cacheManager.set(key, jobTypes, { + ttl: this.configService.cacheTtlJobTypes, + } as any); + return jobTypes; + } + } } diff --git a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts index 10b1ce5c9d..711c2ede55 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts @@ -140,7 +140,8 @@ export class CronJobService { updates: Partial, ) { const updatedOracle = { ...oracleData, ...updates }; - const chainId = oracleData.chainId; + + const chainId = oracleData.chainId?.toString(); const cachedOracles = await this.cacheManager.get(chainId); diff --git a/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts b/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts index ee12e94f13..9d43beb509 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts @@ -14,6 +14,7 @@ import { JobStatus } from '../../../common/enums/global-common'; import { OracleDiscoveryResult } from '../../../modules/oracle-discovery/model/oracle-discovery.model'; import { SchedulerRegistry } from '@nestjs/schedule'; import { generateOracleDiscoveryResponseBody } from '../../../modules/oracle-discovery/spec/oracle-discovery.fixture'; +import { ChainId } from '@human-protocol/sdk'; jest.mock('cron', () => { return { @@ -53,7 +54,7 @@ describe('CronJobService', () => { email: 'human-app@hmt.ai', password: 'Test1234*', cacheTtlOracleDiscovery: 600, - chainIdsEnabled: ['137', '1'], + chainIdsEnabled: [ChainId.POLYGON, ChainId.MAINNET], jobsDiscoveryFlag: false, maxExecutionToSkip: 32, }; @@ -168,7 +169,7 @@ describe('CronJobService', () => { const oracle: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', - chainId: '137', + chainId: ChainId.POLYGON, retriesCount: 0, executionsToSkip: 0, }; @@ -196,7 +197,7 @@ describe('CronJobService', () => { const oracle: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', - chainId: '137', + chainId: ChainId.POLYGON, retriesCount: 0, executionsToSkip: 0, }; @@ -222,7 +223,7 @@ describe('CronJobService', () => { const oracle: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', - chainId: '137', + chainId: ChainId.POLYGON, retriesCount: 3, executionsToSkip: 0, }; @@ -322,7 +323,7 @@ describe('CronJobService', () => { const oracleData: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', - chainId: '137', + chainId: ChainId.POLYGON, retriesCount: 5, executionsToSkip: 2, }; @@ -335,7 +336,7 @@ describe('CronJobService', () => { }); expect(cacheManagerMock.set).toHaveBeenCalledWith( - oracleData.chainId, + oracleData.chainId.toString(), [{ ...oracleData, retriesCount: 0, executionsToSkip: 0 }], configServiceMock.cacheTtlOracleDiscovery, ); @@ -347,7 +348,8 @@ describe('CronJobService', () => { const oracleData: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', - chainId: '137', + + chainId: ChainId.POLYGON, retriesCount: 6, executionsToSkip: 0, }; @@ -357,7 +359,7 @@ describe('CronJobService', () => { await (service as any).handleJobListError(oracleData); expect(cacheManagerMock.set).toHaveBeenCalledWith( - oracleData.chainId, + oracleData.chainId.toString(), [{ ...oracleData, retriesCount: 7, executionsToSkip: 32 }], configServiceMock.cacheTtlOracleDiscovery, ); @@ -367,7 +369,7 @@ describe('CronJobService', () => { const oracleData: OracleDiscoveryResult = { address: 'mockAddress1', role: 'validator', - chainId: '137', + chainId: ChainId.POLYGON, retriesCount: 2, executionsToSkip: 0, }; @@ -377,7 +379,7 @@ describe('CronJobService', () => { await (service as any).handleJobListError(oracleData); expect(cacheManagerMock.set).toHaveBeenCalledWith( - oracleData.chainId, + oracleData.chainId.toString(), [{ ...oracleData, retriesCount: 3, executionsToSkip: 4 }], configServiceMock.cacheTtlOracleDiscovery, ); diff --git a/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts b/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts index fe4279cd1d..6e3b8b6b35 100644 --- a/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts @@ -16,6 +16,7 @@ import { CommonConfigModule } from '../../../common/config/common-config.module' import { ConfigModule } from '@nestjs/config'; import { EnvironmentConfigService } from '../../../common/config/environment-config.service'; import { HttpException, HttpStatus } from '@nestjs/common'; +import { ChainId } from '@human-protocol/sdk'; describe('JobsDiscoveryController', () => { let controller: JobsDiscoveryController; @@ -24,7 +25,7 @@ describe('JobsDiscoveryController', () => { email: 'human-app@hmt.ai', password: 'Test1234*', cacheTtlOracleDiscovery: 600, - chainIdsEnabled: ['137', '1'], + chainIdsEnabled: [ChainId.POLYGON, ChainId.MAINNET], jobsDiscoveryFlag: true, }; diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts index 27c50e6ad3..77b0feb75d 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts @@ -1,4 +1,4 @@ -import { IOperator } from '@human-protocol/sdk'; +import { ChainId, IOperator } from '@human-protocol/sdk'; import { AutoMap } from '@automapper/classes'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsArray, IsOptional } from 'class-validator'; @@ -9,7 +9,7 @@ export class OracleDiscoveryResult implements IOperator { address: string; @ApiProperty({ description: 'Chain ID where the oracle is registered' }) - chainId: string; + chainId: ChainId; @ApiPropertyOptional({ description: 'Role of the oracle operator' }) role?: string; @@ -39,7 +39,7 @@ export class OracleDiscoveryResult implements IOperator { constructor( address: string, - chainId: string, + chainId: ChainId, role?: string, url?: string, jobTypes?: string[], diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.module.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.module.ts index 308783287b..67b8eb8f6d 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.module.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.module.ts @@ -1,8 +1,10 @@ import { Module } from '@nestjs/common'; import { OracleDiscoveryService } from './oracle-discovery.service'; import { OracleDiscoveryProfile } from './oracle-discovery.mapper.profile'; +import { KvStoreModule } from '../../integrations/kv-store/kv-store.module'; @Module({ + imports: [KvStoreModule], providers: [OracleDiscoveryService, OracleDiscoveryProfile], exports: [OracleDiscoveryService], }) diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts index 9e9b42cd6b..cc6f71a626 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts @@ -5,8 +5,9 @@ import { } from './model/oracle-discovery.model'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; -import { IOperator, OperatorUtils, Role } from '@human-protocol/sdk'; +import { ChainId, OperatorUtils, Role } from '@human-protocol/sdk'; import { EnvironmentConfigService } from '../../common/config/environment-config.service'; +import { KvStoreGateway } from '../../integrations/kv-store/kv-store.gateway'; @Injectable() export class OracleDiscoveryService { @@ -15,6 +16,7 @@ export class OracleDiscoveryService { constructor( @Inject(CACHE_MANAGER) private cacheManager: Cache, private configService: EnvironmentConfigService, + private kvStoreGateway: KvStoreGateway, ) {} async processOracleDiscovery( @@ -22,10 +24,18 @@ export class OracleDiscoveryService { ): Promise { const address = this.configService.reputationOracleAddress; const chainIds = this.configService.chainIdsEnabled; + const oraclesForChainIds = await Promise.all( - chainIds.map(async (chainId) => - this.findOraclesByChainId(chainId, address), - ), + chainIds.map(async (chainId) => { + const jobTypes = ( + (await this.kvStoreGateway.getJobTypesByAddress(chainId, address)) ?? + '' + ) + .split(',') + .map((job) => job.trim().toLowerCase()); + + return this.findOraclesByChainIdAndJobTypes(chainId, address, jobTypes); + }), ); const oracles: OracleDiscoveryResult[] = []; @@ -53,31 +63,32 @@ export class OracleDiscoveryService { return oracles; } - private async findOraclesByChainId( - chainId: string, + private async findOraclesByChainIdAndJobTypes( + chainId: ChainId, address: string, + jobTypes: string[], ): Promise { try { - const cachedOracles: OracleDiscoveryResult[] | undefined = - await this.cacheManager.get(chainId); - - if (cachedOracles) { - return cachedOracles; - } + const cachedOracles = await this.cacheManager.get< + OracleDiscoveryResult[] + >(chainId.toString()); + if (cachedOracles) return cachedOracles; - const operators: IOperator[] = - await OperatorUtils.getReputationNetworkOperators( - Number(chainId), - address, - Role.ExchangeOracle, - ); + const operators = await OperatorUtils.getReputationNetworkOperators( + Number(chainId), + address, + Role.ExchangeOracle, + ); - const oraclesWithRetryData: OracleDiscoveryResult[] = []; - for (const operator of operators) { - const isOperatorValid = !!operator.url; + const jobTypeSet = new Set(jobTypes.map((j) => j.toLowerCase())); - if (isOperatorValid) { - oraclesWithRetryData.push( + const oraclesWithRetryData: OracleDiscoveryResult[] = operators + .filter( + (operator) => + operator.url && this.hasJobTypes(operator.jobTypes, jobTypeSet), + ) + .map( + (operator) => new OracleDiscoveryResult( operator.address, chainId, @@ -87,12 +98,10 @@ export class OracleDiscoveryService { operator.registrationNeeded, operator.registrationInstructions, ), - ); - } - } + ); await this.cacheManager.set( - chainId, + chainId.toString(), oraclesWithRetryData, this.configService.cacheTtlOracleDiscovery, ); @@ -103,4 +112,13 @@ export class OracleDiscoveryService { return []; } } + + private hasJobTypes( + oracleJobTypes: string[] | undefined, + jobTypeSet: Set, + ) { + return oracleJobTypes + ? oracleJobTypes.some((job) => jobTypeSet.has(job.toLowerCase())) + : false; + } } diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts index fa5215d28e..1aab6707e1 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts @@ -15,6 +15,7 @@ import { EnvironmentConfigService } from '../../../common/config/environment-con import { CommonConfigModule } from '../../../common/config/common-config.module'; import { ConfigModule } from '@nestjs/config'; import { HttpException, HttpStatus } from '@nestjs/common'; +import { ChainId } from '@human-protocol/sdk'; describe('OracleDiscoveryController', () => { let controller: OracleDiscoveryController; @@ -23,7 +24,7 @@ describe('OracleDiscoveryController', () => { email: 'human-app@hmt.ai', password: 'Test1234*', cacheTtlOracleDiscovery: 600, - chainIdsEnabled: ['137', '1'], + chainIdsEnabled: [ChainId.POLYGON, ChainId.MAINNET], jobsDiscoveryFlag: true, }; diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts index e948bba2e3..27269ec273 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts @@ -1,3 +1,4 @@ +import { ChainId } from '@human-protocol/sdk'; import { OracleDiscoveryCommand, OracleDiscoveryResult, @@ -5,7 +6,7 @@ import { const response1: OracleDiscoveryResult = { address: '0xd06eac24a0c47c776Ce6826A93162c4AfC029047', - chainId: '4200', + chainId: ChainId.POLYGON_AMOY, role: 'role1', url: 'common-url', jobTypes: ['job-type-3'], @@ -16,7 +17,7 @@ const response1: OracleDiscoveryResult = { }; const response2: OracleDiscoveryResult = { address: '0xd10c3402155c058D78e4D5fB5f50E125F06eb39d', - chainId: '4200', + chainId: ChainId.POLYGON_AMOY, role: 'role2', jobTypes: ['job-type-1', 'job-type-3', 'job-type-4'], retriesCount: 0, @@ -26,7 +27,7 @@ const response2: OracleDiscoveryResult = { }; const response3: OracleDiscoveryResult = { address: '0xd83422155c058D78e4D5fB5f50E125F06eb39d', - chainId: '4200', + chainId: ChainId.POLYGON_AMOY, role: 'role3', url: 'common-url', jobTypes: ['job-type-2'], @@ -37,7 +38,7 @@ const response3: OracleDiscoveryResult = { }; const response4: OracleDiscoveryResult = { address: '0xd83422155c058D78e4D5fB5f50E125F06eb39d', - chainId: '4201', + chainId: ChainId.MOONBASE_ALPHA, role: 'role3', url: 'common-url', jobTypes: ['job-type-1', 'job-type-3', 'job-type-4'], @@ -48,14 +49,14 @@ const response4: OracleDiscoveryResult = { }; export function generateGetReputationNetworkOperatorsResponseByChainId( - chainId: string, + chainId: ChainId, ) { return [response1, response2, response3, response4].filter( (oracle) => oracle.chainId === chainId, ); } -export function generateOracleDiscoveryResponseBodyByChainId(chainId: string) { +export function generateOracleDiscoveryResponseBodyByChainId(chainId: ChainId) { return [response1, response3, response4].filter( (oracle) => oracle.chainId === chainId, ); @@ -65,12 +66,16 @@ export function generateOracleDiscoveryResponseBody() { return [response1, response3, response4]; } -export function generateOracleDiscoveryResponseBodyByJobType() { - return [response3, response4]; +export function generateOracleDiscoveryResponseBodyByJobType(jobType: string) { + return [response1, response3, response4].filter( + (oracle) => + oracle.jobTypes !== undefined && oracle.jobTypes.indexOf(jobType) >= 0, + ); } +export const reputationOracleSupportedJobTypes = 'job-type-1, job-type-4'; export const filledCommandFixture = { - selectedJobTypes: ['job-type-1', 'job-type-2'], + selectedJobTypes: ['job-type-1'], } as OracleDiscoveryCommand; export const emptyCommandFixture = { selectedJobTypes: [], diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts index df2cefc595..771f7dfc75 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts @@ -1,4 +1,4 @@ -import { OperatorUtils } from '@human-protocol/sdk'; +import { ChainId, OperatorUtils } from '@human-protocol/sdk'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { ConfigModule } from '@nestjs/config'; import { Test } from '@nestjs/testing'; @@ -16,6 +16,7 @@ import { generateOracleDiscoveryResponseBodyByJobType, notSetCommandFixture, } from './oracle-discovery.fixture'; +import { KvStoreGateway } from '../../../integrations/kv-store/kv-store.gateway'; jest.mock('@human-protocol/sdk', () => { const actualSdk = jest.requireActual('@human-protocol/sdk'); @@ -29,11 +30,13 @@ jest.mock('@human-protocol/sdk', () => { describe('OracleDiscoveryService', () => { const EXCHANGE_ORACLE = 'Exchange Oracle'; - const EXPECTED_CHAIN_IDS = ['4200', '4201']; + const EXPECTED_CHAIN_IDS = [ChainId.POLYGON_AMOY, ChainId.MOONBASE_ALPHA]; const REPUTATION_ORACLE_ADDRESS = 'the_oracle'; const TTL = '300'; + const JOB_TYPES = 'job-type-1, job-type-2, job-type-3'; let oracleDiscoveryService: OracleDiscoveryService; let cacheManager: Cache; + let kvStoreGateway: KvStoreGateway; beforeEach(async () => { const module = await Test.createTestingModule({ @@ -45,6 +48,12 @@ describe('OracleDiscoveryService', () => { }), ], providers: [ + { + provide: KvStoreGateway, + useValue: { + getJobTypesByAddress: jest.fn().mockReturnValue(JOB_TYPES), + }, + }, { provide: EnvironmentConfigService, useValue: { @@ -68,6 +77,7 @@ describe('OracleDiscoveryService', () => { OracleDiscoveryService, ); cacheManager = module.get(CACHE_MANAGER); + kvStoreGateway = module.get(KvStoreGateway); }); afterEach(() => { @@ -110,9 +120,9 @@ describe('OracleDiscoveryService', () => { expect(result).toEqual(generateOracleDiscoveryResponseBody()); EXPECTED_CHAIN_IDS.forEach((chainId) => { - expect(cacheManager.get).toHaveBeenCalledWith(chainId); + expect(cacheManager.get).toHaveBeenCalledWith(chainId.toString()); expect(cacheManager.set).toHaveBeenCalledWith( - chainId, + chainId.toString(), generateOracleDiscoveryResponseBodyByChainId(chainId), TTL, ); @@ -137,7 +147,9 @@ describe('OracleDiscoveryService', () => { const result = await oracleDiscoveryService.processOracleDiscovery(filledCommandFixture); - expect(result).toEqual(generateOracleDiscoveryResponseBodyByJobType()); + expect(result).toEqual( + generateOracleDiscoveryResponseBodyByJobType('job-type-1'), + ); }); it('should not filter responses if selectedJobTypes is empty', async () => { @@ -174,7 +186,7 @@ describe('OracleDiscoveryService', () => { expect(result).toEqual(errorResponse); expect(loggerErrorSpy).toHaveBeenCalledWith( - `Error processing chainId 4200:`, + `Error processing chainId ${ChainId.POLYGON_AMOY}:`, error, ); }); @@ -190,7 +202,31 @@ describe('OracleDiscoveryService', () => { expect(result).toEqual(errorResponse); EXPECTED_CHAIN_IDS.forEach((chainId) => { - expect(cacheManager.get).toHaveBeenCalledWith(chainId); + expect(cacheManager.get).toHaveBeenCalledWith(chainId.toString()); + }); + }); + + it('should return only relevant oracles based on supported job types', async () => { + jest + .spyOn(kvStoreGateway, 'getJobTypesByAddress') + .mockResolvedValueOnce('job-type-1'); + jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(undefined); + + EXPECTED_CHAIN_IDS.forEach((chainId) => { + jest + .spyOn(OperatorUtils, 'getReputationNetworkOperators') + .mockResolvedValueOnce( + generateGetReputationNetworkOperatorsResponseByChainId(chainId), + ); + }); + + const result = await oracleDiscoveryService.processOracleDiscovery({}); + + const expectedResponse = generateOracleDiscoveryResponseBodyByJobType('job-type-1'); + expect(result).toEqual(expectedResponse); + + result.forEach((oracle) => { + expect(oracle.jobTypes).toContain('job-type-1'); }); }); }); diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts index d0ba594643..95e4889355 100644 --- a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts @@ -2,8 +2,9 @@ import { ConfigModule } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { UiConfigurationController } from './ui-configuration.controller'; import { EnvironmentConfigService } from '../../common/config/environment-config.service'; +import { ChainId } from '@human-protocol/sdk'; -process.env.CHAIN_IDS_ENABLED = '15,42'; +process.env.CHAIN_IDS_ENABLED = '80002,11155111'; describe('UiConfigurationController', () => { let controller: UiConfigurationController; @@ -27,6 +28,9 @@ describe('UiConfigurationController', () => { it('should return proper config', async () => { const result = await controller.getConfig(); - expect(result.chainIdsEnabled).toEqual(['15', '42']); + expect(result.chainIdsEnabled).toEqual([ + ChainId.POLYGON_AMOY, + ChainId.SEPOLIA, + ]); }); }); diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts index 18331806da..552149478a 100644 --- a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts @@ -1,9 +1,10 @@ +import { ChainId } from '@human-protocol/sdk'; import { ApiProperty } from '@nestjs/swagger'; export class UiConfigResponseDto { @ApiProperty({ - type: [String], + type: [ChainId], description: 'Chain ids enabled for the application', }) - chainIdsEnabled: string[]; + chainIdsEnabled: ChainId[]; } From 49ffa9efc2231bb3b30e1aee9a4bb8f1f27c6c45 Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:58:58 +0300 Subject: [PATCH 14/92] [Dashboard] Available networks endpoint (#2779) * Updated configs * Implemented available networks feature * Updated env example * Changed DEFAULT_NETWORK_USAGE_FILTER_MONTHS * Lint fixed * Added new constants * Added check to not cache data from subgraph for disabled networks * Migrate to network config service * Removed unused module --- packages/apps/dashboard/server/.env.example | 2 + packages/apps/dashboard/server/.gitignore | 5 +- packages/apps/dashboard/server/jest.config.ts | 15 ++ packages/apps/dashboard/server/package.json | 6 +- .../src/common/config/env-config.service.ts | 18 ++ .../config/network-config.service.spec.ts | 217 ++++++++++++++++++ .../common/config/network-config.service.ts | 89 ++++++- .../src/common/config/redis-config.service.ts | 1 + .../src/modules/details/details.service.ts | 9 +- .../src/modules/stats/stats.controller.ts | 22 +- .../server/src/modules/stats/stats.module.ts | 1 + .../server/src/modules/stats/stats.service.ts | 18 +- .../human-protocol-sdk/src/statistics.ts | 4 +- 13 files changed, 384 insertions(+), 23 deletions(-) create mode 100644 packages/apps/dashboard/server/jest.config.ts create mode 100644 packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts diff --git a/packages/apps/dashboard/server/.env.example b/packages/apps/dashboard/server/.env.example index 195f6ef5a0..73e98cca79 100644 --- a/packages/apps/dashboard/server/.env.example +++ b/packages/apps/dashboard/server/.env.example @@ -11,6 +11,8 @@ HMT_PRICE_SOURCE_API_KEY= HMT_PRICE_FROM= HMT_PRICE_TO= HCAPTCHA_API_KEY= +NETWORK_USAGE_FILTER_MONTHS= +NETWORKS_AVAILABLE_CACHE_TTL= # Redis REDIS_HOST=localhost diff --git a/packages/apps/dashboard/server/.gitignore b/packages/apps/dashboard/server/.gitignore index 336f365e64..6a917ab004 100644 --- a/packages/apps/dashboard/server/.gitignore +++ b/packages/apps/dashboard/server/.gitignore @@ -35,4 +35,7 @@ lerna-debug.log* !.vscode/extensions.json # Redis Data -/redis_data \ No newline at end of file +/redis_data + +.env.development +.env.production \ No newline at end of file diff --git a/packages/apps/dashboard/server/jest.config.ts b/packages/apps/dashboard/server/jest.config.ts new file mode 100644 index 0000000000..48caa9a34e --- /dev/null +++ b/packages/apps/dashboard/server/jest.config.ts @@ -0,0 +1,15 @@ +module.exports = { + coverageDirectory: '../coverage', + collectCoverageFrom: ['**/*.(t|j)s'], + moduleFileExtensions: ['js', 'json', 'ts'], + rootDir: 'src', + testEnvironment: 'node', + testRegex: '.*\\.spec\\.ts$', + transform: { + '^.+\\.(t)s$': 'ts-jest', + }, + moduleNameMapper: { + '^uuid$': require.resolve('uuid'), + '^typeorm$': require.resolve('typeorm'), + }, +}; diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index d6d50dadc8..37421f539f 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -12,7 +12,11 @@ "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand" }, "dependencies": { "@human-protocol/sdk": "*", diff --git a/packages/apps/dashboard/server/src/common/config/env-config.service.ts b/packages/apps/dashboard/server/src/common/config/env-config.service.ts index 2e5cd0b655..d600003f87 100644 --- a/packages/apps/dashboard/server/src/common/config/env-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/env-config.service.ts @@ -14,6 +14,10 @@ const DEFAULT_HCAPTCHA_STATS_FILE = 'hcaptchaStats.json'; export const HCAPTCHA_STATS_START_DATE = '2022-07-01'; export const HCAPTCHA_STATS_API_START_DATE = '2024-09-14'; export const HMT_STATS_START_DATE = '2021-04-06'; +export const MINIMUM_HMT_TRANSFERS = 5; +export const DEFAULT_NETWORK_USAGE_FILTER_MONTHS = 1; +export const DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL = 2 * 60; +export const MINIMUM_ESCROWS_COUNT = 1; @Injectable() export class EnvironmentConfigService { @@ -81,4 +85,18 @@ export class EnvironmentConfigService { get reputationSource(): string { return this.configService.getOrThrow('REPUTATION_SOURCE_URL'); } + + get networkUsageFilterMonths(): number { + return this.configService.get( + 'NETWORK_USAGE_FILTER_MONTHS', + DEFAULT_NETWORK_USAGE_FILTER_MONTHS, + ); + } + + get networkAvailableCacheTtl(): number { + return this.configService.get( + 'NETWORKS_AVAILABLE_CACHE_TTL', + DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL, + ); + } } diff --git a/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts b/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts new file mode 100644 index 0000000000..9116d86992 --- /dev/null +++ b/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts @@ -0,0 +1,217 @@ +import { createMock } from '@golevelup/ts-jest'; +import { Test, TestingModule } from '@nestjs/testing'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { Cache } from 'cache-manager'; +import { Logger } from '@nestjs/common'; +import { StatisticsClient } from '@human-protocol/sdk'; +import { EnvironmentConfigService } from '../../common/config/env-config.service'; +import { ChainId, NETWORKS } from '@human-protocol/sdk'; +import { MainnetsId } from '../../common/utils/constants'; +import { HttpService } from '@nestjs/axios'; +import { NetworkConfigService } from './network-config.service'; +import { ConfigService } from '@nestjs/config'; + +jest.mock('@human-protocol/sdk', () => ({ + ...jest.requireActual('@human-protocol/sdk'), + StatisticsClient: jest.fn(), +})); + +describe('NetworkConfigService', () => { + let networkConfigService: NetworkConfigService; + let cacheManager: Cache; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + NetworkConfigService, + { provide: HttpService, useValue: createMock() }, + { + provide: CACHE_MANAGER, + useValue: { + get: jest.fn(), + set: jest.fn(), + }, + }, + { + provide: EnvironmentConfigService, + useValue: { + networkUsageFilterMonths: 3, + networkAvailableCacheTtl: 1000, + }, + }, + ConfigService, + Logger, + ], + }).compile(); + + networkConfigService = + module.get(NetworkConfigService); + cacheManager = module.get(CACHE_MANAGER); + }); + + it('should regenerate network list when cache TTL expires', async () => { + const mockNetworkList = [ + ChainId.MAINNET, + ChainId.BSC_MAINNET, + ChainId.POLYGON, + ChainId.XLAYER, + ChainId.MOONBEAM, + ChainId.CELO, + ChainId.AVALANCHE, + ]; + + // Step 1: Initial request - populate cache + jest.spyOn(cacheManager, 'get').mockResolvedValue(null); + jest.spyOn(cacheManager, 'set').mockResolvedValue(undefined); + + const mockStatisticsClient = { + getHMTDailyData: jest + .fn() + .mockResolvedValue([{ totalTransactionCount: 7 }]), + getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), + }; + (StatisticsClient as jest.Mock).mockImplementation( + () => mockStatisticsClient, + ); + + // First call should populate cache + const firstCallResult = await networkConfigService.getAvailableNetworks(); + + expect(firstCallResult).toEqual(mockNetworkList); + expect(cacheManager.set).toHaveBeenCalledWith( + 'available-networks', + mockNetworkList, + 1000, + ); + + // Step 2: Simulate TTL expiration by returning null from cache + jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(null); + + // Second call after TTL should re-generate the network list + const secondCallResult = await networkConfigService.getAvailableNetworks(); + expect(secondCallResult).toEqual(mockNetworkList); + + // Ensure the cache is set again with the regenerated network list + expect(cacheManager.set).toHaveBeenCalledWith( + 'available-networks', + mockNetworkList, + 1000, + ); + }); + + it('should return cached networks if available', async () => { + const cachedNetworks = [ChainId.MAINNET, ChainId.POLYGON]; + jest.spyOn(cacheManager, 'get').mockResolvedValue(cachedNetworks); + + const result = await networkConfigService.getAvailableNetworks(); + expect(result).toEqual(cachedNetworks); + expect(cacheManager.get).toHaveBeenCalledWith('available-networks'); + }); + + it('should fetch and filter available networks correctly', async () => { + jest.spyOn(cacheManager, 'get').mockResolvedValue(null); + const mockStatisticsClient = { + getHMTDailyData: jest + .fn() + .mockResolvedValue([ + { totalTransactionCount: 4 }, + { totalTransactionCount: 3 }, + ]), + getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), + }; + (StatisticsClient as jest.Mock).mockImplementation( + () => mockStatisticsClient, + ); + + const result = await networkConfigService.getAvailableNetworks(); + expect(result).toEqual( + expect.arrayContaining([ChainId.MAINNET, ChainId.POLYGON]), + ); + + expect(cacheManager.set).toHaveBeenCalledWith( + 'available-networks', + result, + 1000, + ); + }); + + it('should exclude networks without sufficient HMT transfers', async () => { + jest.spyOn(cacheManager, 'get').mockResolvedValue(null); + const mockStatisticsClient = { + getHMTDailyData: jest + .fn() + .mockResolvedValue([{ totalTransactionCount: 2 }]), + getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), + }; + (StatisticsClient as jest.Mock).mockImplementation( + () => mockStatisticsClient, + ); + + const result = await networkConfigService.getAvailableNetworks(); + expect(result).toEqual([]); + }); + + it('should handle missing network configuration gracefully', async () => { + jest.spyOn(cacheManager, 'get').mockResolvedValue(null); + + const originalNetworkConfig = NETWORKS[MainnetsId.MAINNET]; + NETWORKS[MainnetsId.MAINNET] = undefined; + + const mockStatisticsClient = { + getHMTDailyData: jest + .fn() + .mockResolvedValue([ + { totalTransactionCount: 3 }, + { totalTransactionCount: 3 }, + ]), + getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), + }; + (StatisticsClient as jest.Mock).mockImplementation( + () => mockStatisticsClient, + ); + + const result = await networkConfigService.getAvailableNetworks(); + + expect(result).not.toContain(MainnetsId.MAINNET); + expect(result).toEqual(expect.arrayContaining([])); + + NETWORKS[MainnetsId.MAINNET] = originalNetworkConfig; + }); + + it('should handle errors in getHMTDailyData gracefully', async () => { + jest.spyOn(cacheManager, 'get').mockResolvedValue(null); + const mockStatisticsClient = { + getHMTDailyData: jest + .fn() + .mockRejectedValue(new Error('Failed to fetch HMT data')), + getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), + }; + (StatisticsClient as jest.Mock).mockImplementation( + () => mockStatisticsClient, + ); + + const result = await networkConfigService.getAvailableNetworks(); + expect(result).toEqual([]); + }); + + it('should handle errors in getEscrowStatistics gracefully', async () => { + jest.spyOn(cacheManager, 'get').mockResolvedValue(null); + const mockStatisticsClient = { + getHMTDailyData: jest + .fn() + .mockResolvedValue([ + { totalTransactionCount: 3 }, + { totalTransactionCount: 2 }, + ]), + getEscrowStatistics: jest + .fn() + .mockRejectedValue(new Error('Failed to fetch escrow stats')), + }; + (StatisticsClient as jest.Mock).mockImplementation( + () => mockStatisticsClient, + ); + + const result = await networkConfigService.getAvailableNetworks(); + expect(result).toEqual([]); + }); +}); diff --git a/packages/apps/dashboard/server/src/common/config/network-config.service.ts b/packages/apps/dashboard/server/src/common/config/network-config.service.ts index 6437fbacdd..fbbe48aa3c 100644 --- a/packages/apps/dashboard/server/src/common/config/network-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/network-config.service.ts @@ -1,12 +1,20 @@ -import { ChainId } from '@human-protocol/sdk'; -import { Injectable } from '@nestjs/common'; +import { ChainId, NETWORKS, StatisticsClient } from '@human-protocol/sdk'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Web3Env } from '../enums/web3'; import { LOCALHOST_CHAIN_IDS, MAINNET_CHAIN_IDS, + MainnetsId, TESTNET_CHAIN_IDS, } from '../utils/constants'; +import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager'; +import { AVAILABLE_NETWORKS_CACHE_KEY } from './redis-config.service'; +import { + EnvironmentConfigService, + MINIMUM_ESCROWS_COUNT, + MINIMUM_HMT_TRANSFERS, +} from './env-config.service'; export interface TokensList { [key: string]: string | undefined; @@ -23,8 +31,13 @@ interface NetworkMapDto { @Injectable() export class NetworkConfigService { private readonly networkMap: NetworkMapDto; + private readonly logger = new Logger(NetworkConfigService.name); - constructor(private configService: ConfigService) { + constructor( + @Inject(CACHE_MANAGER) private cacheManager: Cache, + private readonly envConfigService: EnvironmentConfigService, + private configService: ConfigService, + ) { this.networkMap = { ...(this.configService.get('RPC_URL_ETHEREUM') && { ethereum: { @@ -115,4 +128,74 @@ export class NetworkConfigService { get networks(): NetworkDto[] { return Object.values(this.networkMap).map((network) => network); } + + public async getAvailableNetworks(): Promise { + const cachedNetworks = await this.cacheManager.get( + AVAILABLE_NETWORKS_CACHE_KEY, + ); + + if (cachedNetworks) { + return cachedNetworks; + } + + const currentMonth = new Date(); + const oneMonthAgo = new Date(currentMonth); + oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); + + const filterDate = new Date(currentMonth); + filterDate.setMonth( + filterDate.getMonth() - this.envConfigService.networkUsageFilterMonths, + ); + + const availableNetworks = []; + + for (const networkKey of Object.values(MainnetsId)) { + const chainId = MainnetsId[networkKey as keyof typeof MainnetsId]; + + const networkConfig = NETWORKS[chainId]; + + if (!networkConfig) { + continue; + } + + const statisticsClient = new StatisticsClient(networkConfig); + + try { + const hmtData = await statisticsClient.getHMTDailyData({ + from: new Date(Math.floor(filterDate.getTime() / 1000) * 1000), + }); + const escrowStats = await statisticsClient.getEscrowStatistics({ + from: new Date(Math.floor(oneMonthAgo.getTime() / 1000) * 1000), + }); + + // Calculate total HMT transaction count across the period + const totalTransactionCount = hmtData.reduce( + (sum, day) => sum + day.totalTransactionCount, + 0, + ); + + // At least 1 escrow created in the last month + const recentEscrowsCreated = + escrowStats.totalEscrows >= MINIMUM_ESCROWS_COUNT; + // Total HMT transactions > MINIMUM_HMT_TRANSFERS in the last X months + const sufficientHMTTransfers = + totalTransactionCount > MINIMUM_HMT_TRANSFERS; + + if (recentEscrowsCreated && sufficientHMTTransfers) { + availableNetworks.push(chainId); + } + } catch (error) { + this.logger.error( + `Error processing network ${networkKey} (Chain ID: ${chainId}): ${error.message}`, + ); + } + } + + await this.cacheManager.set( + AVAILABLE_NETWORKS_CACHE_KEY, + availableNetworks, + this.envConfigService.networkAvailableCacheTtl, + ); + return availableNetworks; + } } diff --git a/packages/apps/dashboard/server/src/common/config/redis-config.service.ts b/packages/apps/dashboard/server/src/common/config/redis-config.service.ts index 4db8bec59b..09b15ff2b7 100644 --- a/packages/apps/dashboard/server/src/common/config/redis-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/redis-config.service.ts @@ -7,6 +7,7 @@ const DEFAULT_CACHE_HMT_PRICE_TTL = 60; const DEFAULT_CACHE_HMT_GENERAL_STATS_TTL = 2 * 60; const DEFAULT_HMT_PRICE_CACHE_KEY = 'hmt-price'; const DEFAULT_HMT_GENERAL_STATS_CACHE_KEY = 'hmt-general'; +export const AVAILABLE_NETWORKS_CACHE_KEY = 'available-networks'; export const HCAPTCHA_PREFIX = 'hcaptcha-'; export const HMT_PREFIX = 'hmt-'; diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index a885167c0f..48bad063e7 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -1,5 +1,4 @@ import { plainToInstance } from 'class-transformer'; -import { MainnetsId } from '../../common/utils/constants'; import { BadRequestException, Injectable, Logger } from '@nestjs/common'; import { ChainId, @@ -149,9 +148,7 @@ export class DetailsService { public async getBestLeadersByRole(chainId?: ChainId): Promise { const chainIds = !chainId - ? (Object.values(MainnetsId).filter( - (value) => typeof value === 'number', - ) as number[]) + ? await this.networkConfig.getAvailableNetworks() : [chainId]; const leadersByRole: { [role: string]: LeaderDto } = {}; @@ -187,9 +184,7 @@ export class DetailsService { public async getAllLeaders(chainId?: ChainId): Promise { const chainIds = !chainId - ? (Object.values(MainnetsId).filter( - (value) => typeof value === 'number', - ) as number[]) + ? await this.networkConfig.getAvailableNetworks() : [chainId]; const allLeaders: LeaderDto[] = []; diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts b/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts index 22fafe4c88..62625544f5 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts @@ -10,11 +10,16 @@ import { import { HmtDailyStatsResponseDto } from './dto/hmt.dto'; import { DateValidationPipe } from '../../common/pipes/date-validation.pipe'; import { HmtGeneralStatsDto } from './dto/hmt-general-stats.dto'; +import { ChainId } from '@human-protocol/sdk'; +import { NetworkConfigService } from '../../common/config/network-config.service'; @ApiTags('Stats') @Controller('/stats') export class StatsController { - constructor(private readonly statsService: StatsService) {} + constructor( + private readonly statsService: StatsService, + private readonly networkConfigService: NetworkConfigService, + ) {} @Get('/hmt-price') @HttpCode(200) @@ -127,4 +132,19 @@ export class StatsController { const results = await this.statsService.hmtDailyStats(from, to); return { from, to, results }; } + + @Get('/available-networks') + @HttpCode(200) + @ApiOperation({ + summary: 'Get available networks with recent usage', + description: 'Endpoint to return networks filtered by recent activity.', + }) + @ApiResponse({ + status: 200, + description: 'Networks retrieved successfully', + type: Array, + }) + public async getAvailableNetworks(): Promise { + return this.networkConfigService.getAvailableNetworks(); + } } diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.module.ts b/packages/apps/dashboard/server/src/modules/stats/stats.module.ts index cc544f36d4..efaea6cf81 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.module.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.module.ts @@ -8,6 +8,7 @@ import { StorageModule } from '../storage/storage.module'; @Module({ imports: [HttpModule, StorageModule], controllers: [StatsController], + exports: [StatsService], providers: [StatsService], }) export class StatsModule {} diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts index fcba3eb728..2085758bd7 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts @@ -18,11 +18,11 @@ import { import { HCAPTCHA_STATS_START_DATE } from '../../common/config/env-config.service'; import { HcaptchaDailyStats, HcaptchaStats } from './dto/hcaptcha.dto'; import { HmtGeneralStatsDto } from './dto/hmt-general-stats.dto'; -import { MainnetsId } from '../../common/utils/constants'; import { DailyHMTData } from '@human-protocol/sdk/dist/graphql'; import { CachedHMTData } from './stats.interface'; import { HmtDailyStatsData } from './dto/hmt.dto'; import { StorageService } from '../storage/storage.service'; +import { NetworkConfigService } from '../../common/config/network-config.service'; @Injectable() export class StatsService implements OnModuleInit { @@ -30,6 +30,7 @@ export class StatsService implements OnModuleInit { constructor( @Inject(CACHE_MANAGER) private cacheManager: Cache, private readonly redisConfigService: RedisConfigService, + private readonly networkConfigService: NetworkConfigService, private readonly envConfigService: EnvironmentConfigService, private readonly httpService: HttpService, private readonly storageService: StorageService, @@ -177,9 +178,9 @@ export class StatsService implements OnModuleInit { totalHolders: 0, totalTransactions: 0, }; - for (const network of Object.values(MainnetsId).filter( - (value) => typeof value === 'number', - ) as number[]) { + const availableNetworks = + await this.networkConfigService.getAvailableNetworks(); + for (const network of availableNetworks) { const statisticsClient = new StatisticsClient(NETWORKS[network]); const generalStats = await statisticsClient.getHMTStatistics(); aggregatedStats.totalHolders += generalStats.totalHolders; @@ -216,13 +217,12 @@ export class StatsService implements OnModuleInit { const dailyData: Record = {}; const monthlyData: Record = {}; + const availableNetworks = + await this.networkConfigService.getAvailableNetworks(); + // Fetch daily data for each network await Promise.all( - ( - Object.values(MainnetsId).filter( - (value) => typeof value === 'number', - ) as number[] - ).map(async (network) => { + availableNetworks.map(async (network) => { const statisticsClient = new StatisticsClient(NETWORKS[network]); let skip = 0; let fetchedRecords: DailyHMTData[] = []; diff --git a/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts b/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts index f19fb95b20..f221eb1241 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts @@ -149,7 +149,9 @@ export class StatisticsClient { }); return { - totalEscrows: +escrowStatistics.totalEscrowCount, + totalEscrows: escrowStatistics?.totalEscrowCount + ? +escrowStatistics.totalEscrowCount + : 0, dailyEscrowsData: eventDayDatas.map((eventDayData) => ({ timestamp: new Date(+eventDayData.timestamp * 1000), escrowsTotal: +eventDayData.dailyEscrowCount, From d38e1d92aad26f69c27c9f9308b951bdfe06d127 Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Tue, 26 Nov 2024 18:16:57 +0300 Subject: [PATCH 15/92] [Human App] fix: ui configuration response dto (#2846) --- .../server/src/integrations/kv-store/kv-store.gateway.ts | 5 ++--- .../oracle-discovery/spec/oracle-discovery.service.spec.ts | 3 ++- .../src/modules/ui-configuration/ui-configuration.dto.ts | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts index 33e515b7dc..42812754da 100644 --- a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts @@ -79,9 +79,8 @@ export class KvStoreGateway { if (!jobTypes || jobTypes === '') { return; } else { - await this.cacheManager.set(key, jobTypes, { - ttl: this.configService.cacheTtlJobTypes, - } as any); + await this.cacheManager.set(key, jobTypes, this.configService.cacheTtlJobTypes); + return jobTypes; } } diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts index 771f7dfc75..6184473528 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts @@ -222,7 +222,8 @@ describe('OracleDiscoveryService', () => { const result = await oracleDiscoveryService.processOracleDiscovery({}); - const expectedResponse = generateOracleDiscoveryResponseBodyByJobType('job-type-1'); + const expectedResponse = + generateOracleDiscoveryResponseBodyByJobType('job-type-1'); expect(result).toEqual(expectedResponse); result.forEach((oracle) => { diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts index 552149478a..864757461b 100644 --- a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts @@ -3,8 +3,10 @@ import { ApiProperty } from '@nestjs/swagger'; export class UiConfigResponseDto { @ApiProperty({ - type: [ChainId], + type: [Number], description: 'Chain ids enabled for the application', + enum: ChainId, + enumName: 'ChainId', }) chainIdsEnabled: ChainId[]; } From ebc4df64179826385afa9fb6a25a98687f2bcf71 Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:07:31 +0100 Subject: [PATCH 16/92] fix start:prod script (#2849) --- packages/apps/dashboard/server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 37421f539f..8d0b68e7e1 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -11,7 +11,7 @@ "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", + "start:prod": "node dist/src/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", From f745ece5826daa569c792b1e82cb131ec8780fe1 Mon Sep 17 00:00:00 2001 From: mpblocky <185767042+mpblocky@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:09:24 +0100 Subject: [PATCH 17/92] [Human App] fix: remove token clearing on welcome page render (#2844) --- .../human-app/frontend/src/auth-web3/web3-auth-context.tsx | 1 + .../src/pages/homepage/components/operator-signin.tsx | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx b/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx index 9c63b56989..731453f24a 100644 --- a/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx +++ b/packages/apps/human-app/frontend/src/auth-web3/web3-auth-context.tsx @@ -103,6 +103,7 @@ export function Web3AuthProvider({ children }: { children: React.ReactNode }) { browserAuthProvider.signOut({ triggerSignOutSubscriptions: throwExpirationModal, }); + setWeb3AuthState({ user: null, status: 'idle' }); }; diff --git a/packages/apps/human-app/frontend/src/pages/homepage/components/operator-signin.tsx b/packages/apps/human-app/frontend/src/pages/homepage/components/operator-signin.tsx index 6693b2b817..8f019034a2 100644 --- a/packages/apps/human-app/frontend/src/pages/homepage/components/operator-signin.tsx +++ b/packages/apps/human-app/frontend/src/pages/homepage/components/operator-signin.tsx @@ -20,11 +20,6 @@ export function OperatorSignIn() { const { user, signOut } = useWeb3Auth(); const modalWasOpened = useRef(false); - useEffect(() => { - signOut(false); - // eslint-disable-next-line react-hooks/exhaustive-deps -- ... - }, []); - useEffect(() => { if (isConnected && modalWasOpened.current) { signInMutation({ address, type: PrepareSignatureType.SignIn }); @@ -64,6 +59,7 @@ export function OperatorSignIn() { fullWidth onClick={() => { modalWasOpened.current = true; + signOut(); void openModal(); }} size="large" From 470bf0daa76437ba604481198983a7d8a3dfa467 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Tue, 26 Nov 2024 20:28:19 +0300 Subject: [PATCH 18/92] [CVAT] Allow manifest changes in recording oracle (#2850) * Allow manifest changes in recording oracle * Fix linter * Fix test * Remove .env from test dockerfile * Ignore nonexistent .env --- .../dockerfiles/test.Dockerfile | 2 + .../dockerfiles/test.Dockerfile | 2 + .../src/core/annotation_meta.py | 15 +- .../handlers/process_intermediate_results.py | 21 +- .../cvat/recording-oracle/tests/conftest.py | 14 +- .../services/test_validation_service.py | 232 +++++++++++++++++- .../recording-oracle/tests/utils/constants.py | 2 + 7 files changed, 270 insertions(+), 18 deletions(-) diff --git a/packages/examples/cvat/exchange-oracle/dockerfiles/test.Dockerfile b/packages/examples/cvat/exchange-oracle/dockerfiles/test.Dockerfile index d15dbae339..f2341c8d22 100644 --- a/packages/examples/cvat/exchange-oracle/dockerfiles/test.Dockerfile +++ b/packages/examples/cvat/exchange-oracle/dockerfiles/test.Dockerfile @@ -14,4 +14,6 @@ RUN poetry config virtualenvs.create false \ COPY . . +RUN rm -f ./src/.env + CMD ["pytest", "-W", "ignore::DeprecationWarning", "-v"] \ No newline at end of file diff --git a/packages/examples/cvat/recording-oracle/dockerfiles/test.Dockerfile b/packages/examples/cvat/recording-oracle/dockerfiles/test.Dockerfile index 23b9a9dc1d..591d0cb769 100644 --- a/packages/examples/cvat/recording-oracle/dockerfiles/test.Dockerfile +++ b/packages/examples/cvat/recording-oracle/dockerfiles/test.Dockerfile @@ -14,4 +14,6 @@ RUN poetry config virtualenvs.create false \ COPY . . +RUN rm -f ./src/.env + CMD ["pytest", "-W", "ignore::DeprecationWarning", "-W", "ignore::RuntimeWarning", "-W", "ignore::UserWarning", "-v"] \ No newline at end of file diff --git a/packages/examples/cvat/recording-oracle/src/core/annotation_meta.py b/packages/examples/cvat/recording-oracle/src/core/annotation_meta.py index 2aa237378a..3e67161e1e 100644 --- a/packages/examples/cvat/recording-oracle/src/core/annotation_meta.py +++ b/packages/examples/cvat/recording-oracle/src/core/annotation_meta.py @@ -1,8 +1,13 @@ -from collections.abc import Iterator -from pathlib import Path +from __future__ import annotations + +from pathlib import Path # noqa: TCH003 +from typing import TYPE_CHECKING from pydantic import BaseModel +if TYPE_CHECKING: + from collections.abc import Collection, Iterator + ANNOTATION_RESULTS_METAFILE_NAME = "annotation_meta.json" RESULTING_ANNOTATIONS_FILE = "resulting_annotations.zip" @@ -24,5 +29,7 @@ def job_frame_range(self) -> Iterator[int]: class AnnotationMeta(BaseModel): jobs: list[JobMeta] - def skip_jobs(self, job_ids: list[int]): - return AnnotationMeta(jobs=[job for job in self.jobs if job.job_id not in job_ids]) + def skip_assignments(self, assignment_ids: Collection[int]) -> AnnotationMeta: + return AnnotationMeta( + jobs=[job for job in self.jobs if job.assignment_id not in assignment_ids] + ) diff --git a/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py b/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py index 6587a6d185..e40fce9906 100644 --- a/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py +++ b/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py @@ -375,13 +375,12 @@ def process_intermediate_results( # noqa: PLR0912 ), # should not happen, but waiting should not block processing ) if task: - # skip jobs that have already been accepted on the previous epochs - accepted_cvat_job_ids = [ - validation_result.job.cvat_id + # Skip assignments that were validated earlier + validated_assignment_ids = { + validation_result.assignment_id for validation_result in db_service.get_task_validation_results(session, task.id) - if validation_result.annotation_quality >= manifest.validation.min_quality - ] - unchecked_jobs_meta = meta.skip_jobs(accepted_cvat_job_ids) + } + unchecked_jobs_meta = meta.skip_assignments(validated_assignment_ids) else: # Recording Oracle task represents all CVAT tasks related with the escrow task_id = db_service.create_task(session, escrow_address=escrow_address, chain_id=chain_id) @@ -566,6 +565,16 @@ def process_intermediate_results( # noqa: PLR0912 else: assignment_validation_result_id = assignment_validation_result.id + # We consider only the last assignment as final even if there were assignments with higher + # quality score. The reason for this is that during escrow annotation there are various + # task changes possible, for instance: + # - GT can be changed in the middle of the task annotation + # - manifest can be updated with different quality parameters + # etc. It can be considered more of a development or testing conditions so far, + # according to the current system requirements, but it's likely to be + # a normal requirement in the future. + # Therefore, we use the logic: only the last job assignment can be considered + # a final annotation result, regardless of the assignment quality. job_final_result_ids[job.id] = assignment_validation_result_id task_jobs = task.jobs diff --git a/packages/examples/cvat/recording-oracle/tests/conftest.py b/packages/examples/cvat/recording-oracle/tests/conftest.py index f39f40a8ca..306d4f3368 100644 --- a/packages/examples/cvat/recording-oracle/tests/conftest.py +++ b/packages/examples/cvat/recording-oracle/tests/conftest.py @@ -2,9 +2,10 @@ import pytest from fastapi.testclient import TestClient +from sqlalchemy.orm import Session from src import app -from src.db import Base, engine +from src.db import Base, SessionLocal, engine @pytest.fixture(autouse=True) @@ -17,3 +18,14 @@ def db(): def client() -> Generator: with TestClient(app) as c: yield c + + +@pytest.fixture +def session() -> Generator[Session, None, None]: + session = SessionLocal() + + try: + yield session + finally: + session.rollback() + session.close() diff --git a/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py b/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py index c56f478721..29bf0884cf 100644 --- a/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py +++ b/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py @@ -1,9 +1,21 @@ +import io import random import unittest import uuid +from contextlib import ExitStack +from logging import Logger +from types import SimpleNamespace +from unittest import mock +from sqlalchemy.orm import Session + +from src.core.annotation_meta import AnnotationMeta, JobMeta +from src.core.manifest import TaskManifest, parse_manifest from src.core.types import Networks +from src.core.validation_results import ValidationFailure, ValidationSuccess +from src.cvat import api_calls as cvat_api from src.db import SessionLocal +from src.handlers.process_intermediate_results import process_intermediate_results from src.services.validation import ( create_job, create_task, @@ -16,19 +28,19 @@ get_validation_result_by_assignment_id, ) +from tests.utils.constants import ESCROW_ADDRESS, WALLET_ADDRESS1 + class ServiceIntegrationTest(unittest.TestCase): def setUp(self): random.seed(42) self.session = SessionLocal() - self.escrow_address = "0x" + "".join([str(random.randint(0, 9)) for _ in range(40)]) + self.escrow_address = ESCROW_ADDRESS self.chain_id = Networks.localhost self.cvat_id = 0 - self.annotator_wallet_address = "0x" + "".join( - [str(random.randint(0, 9)) for _ in range(40)] - ) + self.annotator_wallet_address = WALLET_ADDRESS1 self.annotation_quality = 0.9 - self.assigment_id = str(uuid.uuid4()) + self.assignment_id = str(uuid.uuid4()) def tearDown(self): self.session.close() @@ -67,12 +79,218 @@ def test_create_and_get_validation_result(self): job_id, self.annotator_wallet_address, self.annotation_quality, - self.assigment_id, + self.assignment_id, ) - vr = get_validation_result_by_assignment_id(self.session, self.assigment_id) + vr = get_validation_result_by_assignment_id(self.session, self.assignment_id) assert vr.id == vr_id vrs = get_task_validation_results(self.session, task_id) assert len(vrs) == 1 assert vrs[0] == vr + + +class TestManifestChange: + @staticmethod + def _generate_manifest(*, min_quality: float = 0.8) -> TaskManifest: + data = { + "data": {"data_url": "http://localhost:9010/datasets/sample"}, + "annotation": { + "labels": [{"name": "person"}], + "description": "", + "user_guide": "", + "type": "image_points", + "job_size": 10, + }, + "validation": { + "min_quality": min_quality, + "val_size": 2, + "gt_url": "http://localhost:9010/datasets/sample/annotations/sample_gt.json", + }, + "job_bounty": "0.0001", + } + + return parse_manifest(data) + + def test_can_handle_lowered_quality_requirements_in_manifest(self, session: Session): + escrow_address = ESCROW_ADDRESS + chain_id = Networks.localhost + + min_quality1 = 0.8 + min_quality2 = 0.5 + frame_count = 10 + + manifest = self._generate_manifest(min_quality=min_quality1) + + cvat_task_id = 1 + cvat_job_id = 1 + annotator1 = WALLET_ADDRESS1 + + assignment1_id = f"0x{0:040d}" + assignment1_quality = 0.7 + + assignment2_id = f"0x{1:040d}" + assignment2_quality = 0.6 + + # create a validation input + with ExitStack() as common_lock_es: + logger = mock.Mock(Logger) + + mock_make_cloud_client = common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.make_cloud_client") + ) + mock_make_cloud_client.return_value.download_file = mock.Mock(return_value=b"") + + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.BucketAccessInfo.parse_obj") + ) + + mock_get_task_validation_layout = common_lock_es.enter_context( + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_task_validation_layout" + ) + ) + mock_get_task_validation_layout.return_value = mock.Mock( + cvat_api.models.ITaskValidationLayoutRead, + honeypot_frames=[0, 1], + honeypot_real_frames=[0, 1], + ) + + mock_get_task_data_meta = common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.cvat_api.get_task_data_meta") + ) + mock_get_task_data_meta.return_value = mock.Mock( + cvat_api.models.IDataMetaRead, + frames=[SimpleNamespace(name=f"frame_{i}.jpg") for i in range(frame_count)], + ) + + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.dm.Dataset.import_from") + ) + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.extract_zip_archive") + ) + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.write_dir_to_zip_archive") + ) + + def patched_prepare_merged_dataset(self): + self._updated_merged_dataset_archive = io.BytesIO() + + common_lock_es.enter_context( + mock.patch( + "src.handlers.process_intermediate_results._TaskValidator._prepare_merged_dataset", + patched_prepare_merged_dataset, + ) + ) + + annotation_meta = AnnotationMeta( + jobs=[ + JobMeta( + job_id=cvat_job_id, + task_id=cvat_task_id, + annotation_filename="", + annotator_wallet_address=annotator1, + assignment_id=assignment1_id, + start_frame=0, + stop_frame=manifest.annotation.job_size + manifest.validation.val_size, + ) + ] + ) + + with ( + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_task_quality_report" + ) as mock_get_task_quality_report, + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_quality_report_data" + ) as mock_get_quality_report_data, + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_jobs_quality_reports" + ) as mock_get_jobs_quality_reports, + ): + mock_get_task_quality_report.return_value = mock.Mock( + cvat_api.models.IQualityReport, id=1 + ) + mock_get_quality_report_data.return_value = mock.Mock( + cvat_api.QualityReportData, + frame_results={ + "0": mock.Mock(annotations=mock.Mock(accuracy=assignment1_quality)), + "1": mock.Mock(annotations=mock.Mock(accuracy=assignment1_quality)), + }, + ) + mock_get_jobs_quality_reports.return_value = [ + mock.Mock( + cvat_api.models.IQualityReport, + job_id=1, + summary=mock.Mock(accuracy=assignment1_quality), + ), + ] + + vr1 = process_intermediate_results( + session, + escrow_address=escrow_address, + chain_id=chain_id, + meta=annotation_meta, + merged_annotations=io.BytesIO(), + manifest=manifest, + logger=logger, + ) + + assert isinstance(vr1, ValidationFailure) + assert len(vr1.rejected_jobs) == 1 + + manifest.validation.min_quality = min_quality2 + + annotation_meta.jobs[0].assignment_id = assignment2_id + + with ( + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_task_quality_report" + ) as mock_get_task_quality_report, + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_quality_report_data" + ) as mock_get_quality_report_data, + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_jobs_quality_reports" + ) as mock_get_jobs_quality_reports, + ): + mock_get_task_quality_report.return_value = mock.Mock( + cvat_api.models.IQualityReport, id=2 + ) + mock_get_quality_report_data.return_value = mock.Mock( + cvat_api.QualityReportData, + frame_results={ + "0": mock.Mock(annotations=mock.Mock(accuracy=assignment2_quality)), + "1": mock.Mock(annotations=mock.Mock(accuracy=assignment2_quality)), + }, + ) + mock_get_jobs_quality_reports.return_value = [ + mock.Mock( + cvat_api.models.IQualityReport, + job_id=1, + summary=mock.Mock(accuracy=assignment2_quality), + ), + ] + + vr2 = process_intermediate_results( + session, + escrow_address=escrow_address, + chain_id=chain_id, + meta=annotation_meta, + merged_annotations=io.BytesIO(), + manifest=manifest, + logger=logger, + ) + + assert isinstance(vr2, ValidationSuccess) + assert vr2.job_results[cvat_job_id] == assignment2_quality + + assert len(vr2.validation_meta.jobs) == 1 + assert len(vr2.validation_meta.results) == 2 + assert ( + vr2.validation_meta.results[ + vr2.validation_meta.jobs[0].final_result_id + ].annotation_quality + == assignment2_quality + ) diff --git a/packages/examples/cvat/recording-oracle/tests/utils/constants.py b/packages/examples/cvat/recording-oracle/tests/utils/constants.py index 75c05b1b14..90af4374a6 100644 --- a/packages/examples/cvat/recording-oracle/tests/utils/constants.py +++ b/packages/examples/cvat/recording-oracle/tests/utils/constants.py @@ -98,3 +98,5 @@ -----END PGP PUBLIC KEY BLOCK----- """ ) + +WALLET_ADDRESS1 = "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed" From 2b49179ba579eb5c93d2bfdf26e97a96e73bcb7d Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Wed, 27 Nov 2024 12:02:41 +0300 Subject: [PATCH 19/92] [Dashboard] fix: properly filter dashboard stats values (#2847) --- packages/apps/dashboard/server/docker-compose.yml | 2 +- .../apps/dashboard/server/src/modules/stats/stats.service.ts | 4 ++-- packages/apps/human-app/server/docker-compose.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/apps/dashboard/server/docker-compose.yml b/packages/apps/dashboard/server/docker-compose.yml index 7cd8879212..6258fe800c 100644 --- a/packages/apps/dashboard/server/docker-compose.yml +++ b/packages/apps/dashboard/server/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.8' +name: 'dashboard-server' services: redis: diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts index 2085758bd7..34b653c953 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts @@ -352,7 +352,7 @@ export class StatsService implements OnModuleInit { }), ); - return stats.filter((stat): stat is HcaptchaDailyStats => stat !== null); + return stats.filter(Boolean); } public async hCaptchaGeneralStats(): Promise { @@ -417,6 +417,6 @@ export class StatsService implements OnModuleInit { }), ); - return stats.filter((stat): stat is HmtDailyStatsData => stat !== null); + return stats.filter(Boolean); } } diff --git a/packages/apps/human-app/server/docker-compose.yml b/packages/apps/human-app/server/docker-compose.yml index 7b9c3d7c24..70b3f4db38 100644 --- a/packages/apps/human-app/server/docker-compose.yml +++ b/packages/apps/human-app/server/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.8' +name: 'human-app-server' services: human-app: From efe591b273d7444d0fc17e8ffabd46cdae8805e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Wed, 27 Nov 2024 12:52:07 +0100 Subject: [PATCH 20/92] Integrate Dashboard Metrics (#2853) --- .../src/components/Dashboard/JobsGraph.tsx | 117 ++++++++---------- .../components/Dashboard/LiquidityData.tsx | 62 ++++------ .../Dashboard/WorkersPerformance.tsx | 96 -------------- .../client/src/pages/Dashboard/index.tsx | 25 ++-- .../job-launcher/client/src/services/stats.ts | 7 ++ .../job-launcher/client/src/types/index.ts | 29 +++++ 6 files changed, 125 insertions(+), 211 deletions(-) delete mode 100644 packages/apps/job-launcher/client/src/components/Dashboard/WorkersPerformance.tsx create mode 100644 packages/apps/job-launcher/client/src/services/stats.ts diff --git a/packages/apps/job-launcher/client/src/components/Dashboard/JobsGraph.tsx b/packages/apps/job-launcher/client/src/components/Dashboard/JobsGraph.tsx index 7de631b536..4d3ad44d5b 100644 --- a/packages/apps/job-launcher/client/src/components/Dashboard/JobsGraph.tsx +++ b/packages/apps/job-launcher/client/src/components/Dashboard/JobsGraph.tsx @@ -8,21 +8,7 @@ import { Tooltip, XAxis, } from 'recharts'; - -const JOBS_DATA = [ - { date: '2022-07-31', value: 2181348 }, - { date: '2022-08-31', value: 2537442 }, - { date: '2022-09-30', value: 7014852 }, - { date: '2022-10-31', value: 42615432 }, - { date: '2022-11-30', value: 88708986 }, - { date: '2022-12-31', value: 203793543 }, - { date: '2023-01-31', value: 209093427 }, - { date: '2023-02-28', value: 237012318 }, - { date: '2023-03-31', value: 212012559 }, - { date: '2023-04-30', value: 182462076 }, - { date: '2023-05-31', value: 148126905 }, - { date: '2023-06-30', value: 147005424 }, -]; +import { JobStatisticsDto } from '../../types'; const CustomTooltip = ({ active, payload, label }: any) => { if (active && payload && payload.length) { @@ -36,56 +22,30 @@ const CustomTooltip = ({ active, payload, label }: any) => { }} > - {dayjs(label).format('YY/MM')} + {dayjs(label).format('YY/MM/DD')} - - - Jobs Launched - - - 35,845 - - - - - Jobs Completed - - - 35,845 - - - - - Jobs Failed - - - 35,845 - - - - - Jobs Pending - - - 35,845 - - - - - Jobs Canceled - - - 35,845 - - + {payload.map((entry: any) => ( + + + Jobs {entry.name.charAt(0).toUpperCase() + entry.name.slice(1)} + + + {entry.value} + + + ))} ); @@ -94,10 +54,15 @@ const CustomTooltip = ({ active, payload, label }: any) => { return null; }; -export const JobsGraph = () => { +export const JobsGraph = ({ + stats, +}: { + stats: JobStatisticsDto | undefined; +}) => { const theme = useTheme(); const navigate = useNavigate(); - const data = []; + + const data = stats?.jobsByStatusPerDay || []; return ( @@ -106,10 +71,10 @@ export const JobsGraph = () => { {data.length > 0 ? ( - + { axisLine={false} tickLine={false} interval="preserveStartEnd" - ticks={[ - JOBS_DATA[0].date, - JOBS_DATA[JOBS_DATA.length - 1].date, - ]} + ticks={[data[0].date, data[data.length - 1].date]} tick={{ fill: '#320A8D', fontSize: '12px', fontFamily: 'Inter', }} - tickFormatter={(value: any) => dayjs(value).format('MMM D')} + tickFormatter={(value: string) => dayjs(value).format('MMM D')} tickMargin={12} padding={{ left: 10, right: 10 }} /> @@ -136,17 +98,36 @@ export const JobsGraph = () => { content={} /> + + + ) : ( - No data to show at the moment, data will be available once job are + No data to show at the moment, data will be available once jobs are created + ) : isCardExpired(card.expMonth, card.expYear) ? ( + + ) : ( + + )} + handleOpenDeleteModal(card)}> + + + + + ))} + {cards.length === 0 && ( + No cards to show + )} + + {selectedCard && ( + setIsDeleteModalOpen(false)} + cardId={selectedCard.id} + isDefault={selectedCard.default} + hasMultipleCards={cards.length > 1} + onSuccess={handleDeleteSuccess} + openAddCreditCardModal={openAddCreditCardModal} + /> + )} + + ); +}; + +export default CardList; diff --git a/packages/apps/job-launcher/client/src/components/CreditCard/CardSetupForm.tsx b/packages/apps/job-launcher/client/src/components/CreditCard/CardSetupForm.tsx new file mode 100644 index 0000000000..fdde3590a1 --- /dev/null +++ b/packages/apps/job-launcher/client/src/components/CreditCard/CardSetupForm.tsx @@ -0,0 +1,115 @@ +import { LoadingButton } from '@mui/lab'; +import { Box, Checkbox, FormControlLabel, Grid } from '@mui/material'; +import { + PaymentElement, + useElements, + useStripe, +} from '@stripe/react-stripe-js'; +import { useState } from 'react'; +import { useSnackbar } from '../../providers/SnackProvider'; +import * as paymentService from '../../services/payment'; +import { useAppDispatch } from '../../state'; +import { fetchUserBalanceAsync } from '../../state/auth/reducer'; + +interface CardSetupFormProps { + onComplete: () => void; +} + +export const CardSetupForm: React.FC = ({ onComplete }) => { + const stripe = useStripe(); + const elements = useElements(); + const [isLoading, setIsLoading] = useState(false); + + const [defaultCard, setDefaultCard] = useState(false); + const dispatch = useAppDispatch(); + const { showError } = useSnackbar(); + + const handleCardSetup = async () => { + if (!stripe || !elements) { + showError('Stripe.js has not yet loaded.'); + return; + } + + // Trigger form validation and card details collection + const { error: submitError } = await elements.submit(); + if (submitError) { + showError(submitError); + return; + } + + setIsLoading(true); + try { + const clientSecret = await paymentService.createSetupIntent(); + + if (!clientSecret) { + throw new Error('Failed to create SetupIntent.'); + } + + const { error: stripeError, setupIntent } = await stripe.confirmSetup({ + elements, + clientSecret, + confirmParams: { + return_url: window.location.href, + }, + redirect: 'if_required', + }); + + if (stripeError) { + throw stripeError; + } + + const success = await paymentService.confirmSetupIntent( + setupIntent?.id ?? '', + defaultCard, + ); + + if (!success) { + throw new Error('Card setup confirmation failed.'); + } + + dispatch(fetchUserBalanceAsync()); + onComplete(); + } catch (err: any) { + showError(err.message || 'An error occurred while setting up the card.'); + } + setIsLoading(false); + }; + + return ( + + + + + + setDefaultCard(e.target.checked)} + /> + } + label="Set this card as default payment method" + sx={{ mt: 2 }} + /> + + + + Add Credit Card + + + + + ); +}; diff --git a/packages/apps/job-launcher/client/src/components/CreditCard/DeleteCardModal.tsx b/packages/apps/job-launcher/client/src/components/CreditCard/DeleteCardModal.tsx new file mode 100644 index 0000000000..2255f2c6e3 --- /dev/null +++ b/packages/apps/job-launcher/client/src/components/CreditCard/DeleteCardModal.tsx @@ -0,0 +1,214 @@ +import CloseIcon from '@mui/icons-material/Close'; +import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'; +import { + Box, + Button, + Dialog, + IconButton, + Typography, + useTheme, + Alert, +} from '@mui/material'; +import { useState } from 'react'; +import { useSnackbar } from '../../providers/SnackProvider'; +import { deleteUserCard } from '../../services/payment'; + +const DeleteCardModal = ({ + open, + onClose, + cardId, + isDefault = false, + hasMultipleCards = false, + onSuccess, + openAddCreditCardModal, +}: { + open: boolean; + onClose: () => void; + cardId: string; + isDefault?: boolean; + hasMultipleCards?: boolean; + onSuccess: () => void; + openAddCreditCardModal: (open: boolean) => void; +}) => { + const theme = useTheme(); + const { showError } = useSnackbar(); + + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); // Para manejar el error del backend + + const handleDelete = async () => { + try { + setIsLoading(true); + await deleteUserCard(cardId); + onSuccess(); + } catch (error: any) { + if ( + error.response?.status === 400 && + error.response?.data?.message === + 'Cannot delete the default payment method in use' + ) { + setError( + 'The credit card you’re trying to remove is currently in use to prevent potential misuse in your most recently launched job.', + ); + } else { + showError('Error deleting card'); + } + } finally { + setIsLoading(false); + } + }; + + return ( + + + + + Delete Credit Card? + + + + + + + + + {error ? ( + + {error} + + To proceed with the removal, please: + +
    +
  • + Wait 24 hours while we verify that your dataset does not + contain abusive content. +
  • +
  • + Alternatively, set a different card as your default payment + method. +
  • +
+ + +   + + +
+ ) : ( + <> + {isDefault && hasMultipleCards ? ( + + }> + + This credit card is set as default! + + + + This card can only be deleted if you choose another card as + default. + + + +   + + + + ) : ( + + + Are you sure you want to delete this credit card from your + account? + + + + + + + )} + + )} +
+
+
+ ); +}; + +export default DeleteCardModal; diff --git a/packages/apps/job-launcher/client/src/components/CreditCard/SelectCardModal.tsx b/packages/apps/job-launcher/client/src/components/CreditCard/SelectCardModal.tsx new file mode 100644 index 0000000000..d4a60dc1d6 --- /dev/null +++ b/packages/apps/job-launcher/client/src/components/CreditCard/SelectCardModal.tsx @@ -0,0 +1,111 @@ +import CloseIcon from '@mui/icons-material/Close'; +import { + Box, + Button, + Dialog, + IconButton, + Typography, + useTheme, +} from '@mui/material'; +import { useState } from 'react'; +import { CardData } from '../../types'; +import { CardIcon } from '../Icons/CardIcon'; + +const SelectCardModal = ({ + open, + onClose, + cards, + onSelect, +}: { + open: boolean; + onClose: () => void; + cards: CardData[]; + onSelect: (card: CardData) => void; +}) => { + const theme = useTheme(); + const [selectedCardId, setSelectedCardId] = useState(null); + + return ( + + + + + Select Credit Card + + + + + + + + + + {cards.map((card) => ( + setSelectedCardId(card.id)} + > + + **** **** **** {card.last4} + + Exp. date {card.expMonth}/{card.expYear} + + + ))} + + + + + + + ); +}; + +export default SelectCardModal; diff --git a/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx b/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx index 5cc530a74e..f5bb59585c 100644 --- a/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx +++ b/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx @@ -192,6 +192,7 @@ export const AuthHeader = () => { cursor: 'pointer', }} to="/profile/transactions" + onClick={handleClose} > My transactions @@ -203,6 +204,7 @@ export const AuthHeader = () => { cursor: 'pointer', }} to="/profile/settings" + onClick={handleClose} > Settings diff --git a/packages/apps/job-launcher/client/src/components/Icons/CryptoIcon.tsx b/packages/apps/job-launcher/client/src/components/Icons/CryptoIcon.tsx new file mode 100644 index 0000000000..8b133f6f74 --- /dev/null +++ b/packages/apps/job-launcher/client/src/components/Icons/CryptoIcon.tsx @@ -0,0 +1,15 @@ +import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; +import { FC } from 'react'; + +export const CryptoIcon: FC = (props) => { + return ( + + + + ); +}; diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx index 498e9cddcb..44dd1859be 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx @@ -3,49 +3,45 @@ import { KVStoreKeys, NETWORKS } from '@human-protocol/sdk'; import { LoadingButton } from '@mui/lab'; import { Box, - BoxProps, Button, Checkbox, FormControl, FormControlLabel, Grid, + InputAdornment, Link, Stack, TextField, Typography, } from '@mui/material'; -import { styled } from '@mui/material/styles'; -import { - CardCvcElement, - CardExpiryElement, - CardNumberElement, - useElements, - useStripe, -} from '@stripe/react-stripe-js'; +import { useElements, useStripe } from '@stripe/react-stripe-js'; import { useEffect, useMemo, useState } from 'react'; + import { Address } from 'viem'; import { useReadContract } from 'wagmi'; +import AddCardModal from '../../../components/CreditCard/AddCardModal'; +import SelectCardModal from '../../../components/CreditCard/SelectCardModal'; +import { CardIcon } from '../../../components/Icons/CardIcon'; +import SuccessModal from '../../../components/SuccessModal'; import { CURRENCY } from '../../../constants/payment'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; -import * as jobService from '../../../services/job'; -import * as paymentService from '../../../services/payment'; +import { + createCvatJob, + createFortuneJob, + createHCaptchaJob, +} from '../../../services/job'; +import { + confirmFiatPayment, + createFiatPayment, + getFee, + getOperatorAddress, + getUserBillingInfo, + getUserCards, +} from '../../../services/payment'; import { useAppDispatch, useAppSelector } from '../../../state'; import { fetchUserBalanceAsync } from '../../../state/auth/reducer'; -import { JobType } from '../../../types'; - -const StripeElement = styled(Box)( - (props) => ({ - border: '1px solid rgba(50,10,141,0.5)', - borderRadius: '4px', - height: '56px', - padding: '18px 16px', - pointerEvents: props.disabled ? 'none' : 'auto', - opacity: props.disabled ? 0.2 : 1, - '&:focus-within': { - borderColor: '#32108D', - }, - }), -); +import { CardData, JobType } from '../../../types'; +import BillingDetailsModal from '../../BillingDetails/BillingDetailsModal'; export const FiatPayForm = ({ onStart, @@ -58,30 +54,57 @@ export const FiatPayForm = ({ }) => { const stripe = useStripe(); const elements = useElements(); - const { jobRequest, goToPrevStep } = useCreateJobPageUI(); const { user } = useAppSelector((state) => state.auth); const dispatch = useAppDispatch(); - - const [payWithAccountBalance, setPayWithAccountBalance] = useState(false); - const [isLoading, setIsLoading] = useState(false); - const [paymentData, setPaymentData] = useState({ - amount: '', - name: '', - }); const [jobLauncherAddress, setJobLauncherAddress] = useState(); const [minFee, setMinFee] = useState(0.01); + const [cards, setCards] = useState([]); + const [selectedCard, setSelectedCard] = useState(null); + const [isSelectCardModalOpen, setIsSelectCardModalOpen] = useState(false); + const [amount, setAmount] = useState(''); + const [payWithAccountBalance, setPayWithAccountBalance] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const { jobRequest, goToPrevStep } = useCreateJobPageUI(); + const [isAddCardOpen, setIsAddCardOpen] = useState(false); + const [isSuccessOpen, setIsSuccessOpen] = useState(false); + const [successMessage, setSuccessMessage] = useState(''); + const [isBillingDetailsOpen, setIsBillingDetailsOpen] = useState(false); + const [openBillingAfterAddCard, setOpenBillingAfterAddCard] = useState(false); useEffect(() => { const fetchJobLauncherData = async () => { - const address = await paymentService.getOperatorAddress(); - const fee = await paymentService.getFee(); + const address = await getOperatorAddress(); + const fee = await getFee(); setJobLauncherAddress(address); setMinFee(fee); }; + const fetchBillingInfo = async () => { + try { + const data = await getUserBillingInfo(); + if (!data || !data.name || !data.address) + setOpenBillingAfterAddCard(true); + } catch { + setOpenBillingAfterAddCard(true); + } + }; + fetchJobLauncherData(); + fetchCards(); + fetchBillingInfo(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const fetchCards = async () => { + const data = await getUserCards(); + setCards(data); + + const defaultCard = data.find((card: CardData) => card.default); + if (defaultCard) { + setSelectedCard(defaultCard); + } + }; + const { data: jobLauncherFee } = useReadContract({ address: NETWORKS[jobRequest.chainId!]?.kvstoreAddress as Address, abi: KVStoreABI, @@ -94,7 +117,7 @@ export const FiatPayForm = ({ }, }); - const fundAmount = paymentData.amount ? Number(paymentData.amount) : 0; + const fundAmount = amount ? Number(amount) : 0; const feeAmount = Math.max( minFee, fundAmount * (Number(jobLauncherFee) / 100), @@ -114,81 +137,36 @@ export const FiatPayForm = ({ return totalAmount - accountAmount; }, [payWithAccountBalance, totalAmount, accountAmount]); - const cardElementsDisabled = useMemo(() => { - if (paymentData.amount) { - return creditCardPayAmount <= 0; - } else { - if (payWithAccountBalance) return true; - return false; - } - }, [paymentData, payWithAccountBalance, creditCardPayAmount]); - - const handlePaymentDataFormFieldChange = ( - fieldName: string, - fieldValue: any, - ) => { - setPaymentData({ ...paymentData, [fieldName]: fieldValue }); + const handleSuccessAction = (message: string) => { + setSuccessMessage(message); + setIsSuccessOpen(true); }; const handlePay = async () => { if (!stripe || !elements) { - // Stripe.js has not yet loaded. - // Make sure to disable form submission until Stripe.js has loaded. - // eslint-disable-next-line no-console - console.error('Stripe.js has not yet loaded.'); + onError('Stripe.js has not yet loaded.'); return; } + onStart(); setIsLoading(true); try { - if (creditCardPayAmount > 0) { - if (!paymentData.name) { - throw new Error('Please enter name on card.'); - } - - // Stripe elements validation - const cardNumber = elements.getElement(CardNumberElement) as any; - const cardExpiry = elements.getElement(CardExpiryElement) as any; - const cardCvc = elements.getElement(CardCvcElement) as any; - - if (!cardNumber || !cardExpiry || !cardCvc) { - throw new Error('Card elements are not initialized'); - } - if (cardNumber._invalid || cardNumber._empty) { - throw new Error('Your card number is incomplete.'); - } - if (cardExpiry._invalid || cardExpiry._empty) { - throw new Error("Your card's expiration date is incomplete."); - } - if (cardCvc._invalid || cardCvc._empty) { - throw new Error("Your card's security code is incomplete."); - } - - // send payment if creditCardPayment > 0 - const clientSecret = await paymentService.createFiatPayment({ + if (creditCardPayAmount > 0 && selectedCard) { + const clientSecret = await createFiatPayment({ amount: creditCardPayAmount, - currency: CURRENCY.usd, + currency: 'usd', + paymentMethodId: selectedCard.id, }); - // stripe payment const { error: stripeError, paymentIntent } = - await stripe.confirmCardPayment(clientSecret, { - payment_method: { - card: cardNumber, - billing_details: { - name: paymentData.name, - }, - }, - }); + await stripe.confirmCardPayment(clientSecret); + if (stripeError) { throw stripeError; } - // confirm payment - const success = await paymentService.confirmFiatPayment( - paymentIntent.id, - ); + const success = await confirmFiatPayment(paymentIntent.id); if (!success) { throw new Error('Payment confirmation failed.'); @@ -201,30 +179,26 @@ export const FiatPayForm = ({ if (!chainId) return; if (jobType === JobType.Fortune && fortuneRequest) { - await jobService.createFortuneJob( + await createFortuneJob( chainId, fortuneRequest, fundAmount, CURRENCY.usd, ); } else if (jobType === JobType.CVAT && cvatRequest) { - await jobService.createCvatJob( - chainId, - cvatRequest, - fundAmount, - CURRENCY.usd, - ); + await createCvatJob(chainId, cvatRequest, fundAmount, CURRENCY.usd); } else if (jobType === JobType.HCAPTCHA && hCaptchaRequest) { - await jobService.createHCaptchaJob(chainId, hCaptchaRequest); + await createHCaptchaJob(chainId, hCaptchaRequest); } + // Update balance and finish payment dispatch(fetchUserBalanceAsync()); onFinish(); } catch (err) { onError(err); + } finally { + setIsLoading(false); } - - setIsLoading(false); }; return ( @@ -254,45 +228,54 @@ export const FiatPayForm = ({ /> - - - - - - - - - - - - - - - - - - handlePaymentDataFormFieldChange('name', e.target.value) - } - disabled={cardElementsDisabled} - /> - - handlePaymentDataFormFieldChange('amount', e.target.value) - } + onChange={(e) => setAmount(e.target.value)} + sx={{ mb: 2 }} /> + {selectedCard ? ( + + + + ), + endAdornment: ( + + + + ), + }} + sx={{ mb: 2 }} + /> + ) : ( + + )} @@ -324,18 +307,6 @@ export const FiatPayForm = ({ )} - {/* - Amount due - {totalAmount} USD - */} - {/* - Fees - - ({JOB_LAUNCHER_FEE}%) {feeAmount} USD - - */} Pay now @@ -434,7 +395,59 @@ export const FiatPayForm = ({ Terms & conditions + + setIsSelectCardModalOpen(false)} + cards={cards} + onSelect={(card) => { + setSelectedCard(card); + setIsSelectCardModalOpen(false); + }} + /> + setIsAddCardOpen(false)} + onComplete={() => { + handleSuccessAction('Your card has been successfully added.'); + fetchCards(); + }} + /> + { + if (openBillingAfterAddCard) { + setIsBillingDetailsOpen(true); + } + setIsSuccessOpen(false); + }} + message={successMessage} + /> + + setIsBillingDetailsOpen(false)} + billingInfo={{ + name: '', + email: '', + address: { + city: '', + country: '', + postalCode: '', + line: '', + }, + vat: '', + vatType: '', + }} + setBillingInfo={(info) => { + handleSuccessAction( + 'Your billing details have been successfully updated.', + ); + }} + /> ); }; + +export default FiatPayForm; diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx index 06e1674778..c9598bc1a8 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx @@ -1,6 +1,6 @@ import { Box } from '@mui/material'; -import React, { useState } from 'react'; -import { StyledTabs, StyledTab } from '../../../components/Tabs'; +import { useState } from 'react'; +import { StyledTab, StyledTabs } from '../../../components/Tabs'; import { IS_TESTNET } from '../../../constants/chains'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; import { useSnackbar } from '../../../providers/SnackProvider'; diff --git a/packages/apps/job-launcher/client/src/components/Payment/PaymentTable.tsx b/packages/apps/job-launcher/client/src/components/Payment/PaymentTable.tsx new file mode 100644 index 0000000000..ae784fc6a7 --- /dev/null +++ b/packages/apps/job-launcher/client/src/components/Payment/PaymentTable.tsx @@ -0,0 +1,238 @@ +import AccountBalanceWalletOutlinedIcon from '@mui/icons-material/AccountBalanceWalletOutlined'; +import CurrencyExchangeOutlinedIcon from '@mui/icons-material/CurrencyExchangeOutlined'; +import DownloadIcon from '@mui/icons-material/Download'; +import MoneyOffCsredOutlinedIcon from '@mui/icons-material/MoneyOffCsredOutlined'; +import SaveAltOutlinedIcon from '@mui/icons-material/SaveAltOutlined'; +import { Box, Chip, IconButton, Typography } from '@mui/material'; +import copy from 'copy-to-clipboard'; +import { useState } from 'react'; +import CreditCardFilledIcon from '../../assets/CreditCardFilled.svg'; +import { CopyLinkIcon } from '../../components/Icons/CopyLinkIcon'; +import { Table } from '../../components/Table'; +import { paymentSource, paymentType } from '../../constants/payment'; +import { usePayments } from '../../hooks/usePayments'; +import { useSnackbar } from '../../providers/SnackProvider'; +import { getReceipt } from '../../services/payment'; +import { CardIcon } from '../Icons/CardIcon'; +import { CryptoIcon } from '../Icons/CryptoIcon'; + +export const PaymentTable = ({ rows = 10 }: { rows?: number }) => { + const { showError } = useSnackbar(); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(rows); + + const { data, isLoading } = usePayments({ + page: page, + pageSize: rowsPerPage, + }); + const handleChangePage = (event: any, newPage: number) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event: any) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + }; + + const downloadReceipt = async (paymentId: string) => { + try { + const invoiceUrl = await getReceipt(paymentId); + window.open(invoiceUrl); + } catch (error) { + showError('Error downloading invoice'); + } + }; + + const renderPaymentStatus = (status: string) => { + let color; + let label; + + switch (status) { + case 'succeeded': + color = 'success'; + label = 'Completed'; + break; + case 'failed': + color = 'error'; + label = 'Failed'; + break; + case 'pending': + color = 'warning'; + label = 'Pending'; + break; + default: + color = 'default'; + label = status; + } + + return ( + + ); + }; + + return ( + new Date(createdAt).toLocaleString(), + }, + { + id: 'amount', + label: 'Amount USD', + sortable: true, + render: ({ amount, rate }) => + `$${Number(amount) > 0 ? Number(amount * rate).toFixed(2) : (Number(amount * rate) * -1).toFixed(2)}`, + }, + { + id: 'type', + label: 'Payment Type', + sortable: false, + render: ({ type }) => ( + + {type === 'deposit' ? ( + + ) : type === 'refund' ? ( + + ) : type === 'withdrawal' ? ( + Jobs + ) : ( + + )} + {paymentType[type]} + + ), + }, + { + id: 'source', + label: 'Payment Method', + sortable: false, + render: ({ source }) => ( + + {source === 'fiat' ? ( + + ) : source === 'balance' ? ( + + ) : ( + + )} + {paymentSource[source]} + + ), + }, + { + id: 'escrowAddress', + label: 'Escrow Address', + sortable: false, + render: ({ escrowAddress }) => + escrowAddress ? ( + + {escrowAddress} + copy(escrowAddress)} + > + + + + ) : ( + + {escrowAddress} + - + + ), + }, + { + id: 'status', + label: 'Payment Status', + sortable: false, + render: ({ status }) => renderPaymentStatus(status), + }, + { + id: 'invoice', + label: '', + render: ({ transaction, source, type }) => + source === 'fiat' && type === 'deposit' ? ( + + downloadReceipt(transaction)} + > + + + + ) : ( + '' + ), + }, + ]} + data={data} + loading={isLoading} + page={page} + rowsPerPage={rowsPerPage} + onPageChange={handleChangePage} + onRowsPerPageChange={handleChangeRowsPerPage} + emptyCell={ + <> + + There are no payments at the moment + + + } + /> + ); +}; + +export default PaymentTable; diff --git a/packages/apps/job-launcher/client/src/components/SuccessModal/index.tsx b/packages/apps/job-launcher/client/src/components/SuccessModal/index.tsx new file mode 100644 index 0000000000..78603704eb --- /dev/null +++ b/packages/apps/job-launcher/client/src/components/SuccessModal/index.tsx @@ -0,0 +1,91 @@ +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import CloseIcon from '@mui/icons-material/Close'; +import { + Box, + Button, + Dialog, + IconButton, + Typography, + useTheme, +} from '@mui/material'; + +const SuccessModal = ({ + open, + onClose, + message, +}: { + open: boolean; + onClose: () => void; + message: string; +}) => { + const theme = useTheme(); + + return ( + + + + + Success! + + + + + + + + + + + + + {message} + + + + + + ); +}; + +export default SuccessModal; diff --git a/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx b/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx index 065b5e6182..2c40289b12 100644 --- a/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx +++ b/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx @@ -1,24 +1,26 @@ import { LoadingButton } from '@mui/lab'; import { Box, + Button, FormControl, Grid, + InputAdornment, Link, TextField, Typography, } from '@mui/material'; -import { - CardCvcElement, - CardExpiryElement, - CardNumberElement, - useElements, - useStripe, -} from '@stripe/react-stripe-js'; -import React, { useState } from 'react'; +import { useElements, useStripe } from '@stripe/react-stripe-js'; +import { useEffect, useState } from 'react'; import { useSnackbar } from '../../providers/SnackProvider'; import * as paymentService from '../../services/payment'; import { useAppDispatch } from '../../state'; import { fetchUserBalanceAsync } from '../../state/auth/reducer'; +import { CardData } from '../../types'; +import BillingDetailsModal from '../BillingDetails/BillingDetailsModal'; +import AddCardModal from '../CreditCard/AddCardModal'; +import SelectCardModal from '../CreditCard/SelectCardModal'; +import { CardIcon } from '../Icons/CardIcon'; +import SuccessModal from '../SuccessModal'; import { TopUpSuccess } from './TopUpSuccess'; export const FiatTopUpForm = () => { @@ -27,51 +29,72 @@ export const FiatTopUpForm = () => { const [isLoading, setIsLoading] = useState(false); const [isSuccess, setIsSuccess] = useState(false); const [amount, setAmount] = useState(); - const [name, setName] = useState(); const dispatch = useAppDispatch(); const { showError } = useSnackbar(); + const [cards, setCards] = useState([]); + const [selectedCard, setSelectedCard] = useState(null); + const [isSelectCardModalOpen, setIsSelectCardModalOpen] = useState(false); + const [isAddCardOpen, setIsAddCardOpen] = useState(false); + const [isSuccessOpen, setIsSuccessOpen] = useState(false); + const [openBillingAfterAddCard, setOpenBillingAfterAddCard] = useState(false); + const [successMessage, setSuccessMessage] = useState(''); + const [isBillingDetailsOpen, setIsBillingDetailsOpen] = useState(false); + + useEffect(() => { + const fetchBillingInfo = async () => { + try { + const data = await paymentService.getUserBillingInfo(); + if (!data || !data.name || !data.address) + setOpenBillingAfterAddCard(true); + } catch { + setOpenBillingAfterAddCard(true); + } + }; + + fetchCards(); + fetchBillingInfo(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const fetchCards = async () => { + const data = await paymentService.getUserCards(); + setCards(data); + + const defaultCard = data.find((card: CardData) => card.default); + if (defaultCard) { + setSelectedCard(defaultCard); + } + }; + + const handleSuccessAction = (message: string) => { + setSuccessMessage(message); + setIsSuccessOpen(true); + }; const handleTopUpAccount = async () => { - if (!stripe || !elements) { - // Stripe.js has not yet loaded. - // Make sure to disable form submission until Stripe.js has loaded. - // eslint-disable-next-line no-console - console.error('Stripe.js has not yet loaded.'); + if (!stripe || !elements || !selectedCard) { + showError('Stripe.js has not yet loaded.'); + return; + } + // Trigger form validation and wallet collection + const { error: submitError } = await elements.submit(); + if (submitError) { + showError(submitError); return; } setIsLoading(true); try { - const cardNumber = elements.getElement(CardNumberElement) as any; - const cardExpiry = elements.getElement(CardExpiryElement) as any; - const cardCvc = elements.getElement(CardCvcElement) as any; - if (!cardNumber || !cardExpiry || !cardCvc) { - throw new Error('Card elements are not initialized'); - } - if (cardNumber._invalid || cardNumber._empty) { - throw new Error('Your card number is incomplete.'); - } - if (cardExpiry._invalid || cardExpiry._empty) { - throw new Error("Your card's expiration date is incomplete."); - } - if (cardCvc._invalid || cardCvc._empty) { - throw new Error("Your card's security code is incomplete."); - } - // get client secret const clientSecret = await paymentService.createFiatPayment({ amount: Number(amount), currency: 'usd', + paymentMethodId: selectedCard.id, }); // stripe payment const { error: stripeError, paymentIntent } = - await stripe.confirmCardPayment(clientSecret, { - payment_method: { - card: cardNumber, - billing_details: { name }, - }, - }); + await stripe.confirmCardPayment(clientSecret); if (stripeError) { throw stripeError; @@ -88,7 +111,7 @@ export const FiatTopUpForm = () => { setIsSuccess(true); } catch (err: any) { - showError(err); + showError(err.message || 'An error occurred while setting up the card.'); setIsSuccess(false); } setIsLoading(false); @@ -99,51 +122,6 @@ export const FiatTopUpForm = () => { ) : ( - - - - - - - - - - - - - - - - - setName(e.target.value)} - /> - { value={amount} type="number" onChange={(e) => setAmount(e.target.value)} + sx={{ mb: 2 }} /> + {selectedCard ? ( + + + + ), + endAdornment: ( + + + + ), + }} + sx={{ mb: 2 }} + /> + ) : ( + + )} @@ -164,7 +180,7 @@ export const FiatTopUpForm = () => { size="large" onClick={handleTopUpAccount} loading={isLoading} - disabled={!amount || !name} + disabled={!amount || !selectedCard} > Top up account @@ -180,6 +196,56 @@ export const FiatTopUpForm = () => { + + setIsSelectCardModalOpen(false)} + cards={cards} + onSelect={(card) => { + setSelectedCard(card); + setIsSelectCardModalOpen(false); + }} + /> + setIsAddCardOpen(false)} + onComplete={() => { + handleSuccessAction('Your card has been successfully added.'); + fetchCards(); + }} + /> + { + if (openBillingAfterAddCard) { + setIsBillingDetailsOpen(true); + } + setIsSuccessOpen(false); + }} + message={successMessage} + /> + + setIsBillingDetailsOpen(false)} + billingInfo={{ + name: '', + email: '', + address: { + city: '', + country: '', + postalCode: '', + line: '', + }, + vat: '', + vatType: '', + }} + setBillingInfo={(info) => { + handleSuccessAction( + 'Your billing details have been successfully updated.', + ); + }} + /> ); }; diff --git a/packages/apps/job-launcher/client/src/constants/payment.ts b/packages/apps/job-launcher/client/src/constants/payment.ts index 8c7f69fe2c..f266ce6842 100644 --- a/packages/apps/job-launcher/client/src/constants/payment.ts +++ b/packages/apps/job-launcher/client/src/constants/payment.ts @@ -4,3 +4,688 @@ export const CURRENCY = { hmt: 'hmt', usd: 'usd', }; + +export const paymentType: { [key: string]: string } = { + deposit: 'Deposit', + refund: 'Refund', + withdrawal: 'Launch Job', + slash: 'Slash', +}; + +export const paymentSource: { [key: string]: string } = { + fiat: 'Credit Card', + crypto: 'Crypto', + balance: 'Balance', +}; + +export enum Country { + AF = 'af', + AL = 'al', + DZ = 'dz', + AS = 'as', + AD = 'ad', + AO = 'ao', + AI = 'ai', + AQ = 'aq', + AG = 'ag', + AR = 'ar', + AM = 'am', + AW = 'aw', + AC = 'ac', + AU = 'au', + AT = 'at', + AZ = 'az', + BS = 'bs', + BH = 'bh', + BD = 'bd', + BB = 'bb', + BY = 'by', + BE = 'be', + BZ = 'bz', + BJ = 'bj', + BM = 'bm', + BT = 'bt', + BO = 'bo', + BQ = 'bq', + BA = 'ba', + BW = 'bw', + BV = 'bv', + BR = 'br', + IO = 'io', + BN = 'bn', + BG = 'bg', + BF = 'bf', + BI = 'bi', + KH = 'kh', + CM = 'cm', + CA = 'ca', + IC = 'ic', + CV = 'cv', + KY = 'ky', + CF = 'cf', + EA = 'ea', + TD = 'td', + CL = 'cl', + CN = 'cn', + CX = 'cx', + CP = 'cp', + CC = 'cc', + CO = 'co', + KM = 'km', + CK = 'ck', + CR = 'cr', + CI = 'ci', + HR = 'hr', + CU = 'cu', + CW = 'cw', + CY = 'cy', + CZ = 'cz', + CD = 'cd', + DK = 'dk', + DG = 'dg', + DJ = 'dj', + DM = 'dm', + DO = 'do', + TL = 'tl', + EC = 'ec', + EG = 'eg', + SV = 'sv', + GQ = 'gq', + ER = 'er', + EE = 'ee', + ET = 'et', + EU = 'eu', + FK = 'fk', + FO = 'fo', + FJ = 'fj', + FI = 'fi', + FR = 'fr', + FX = 'fx', + GF = 'gf', + PF = 'pf', + TF = 'tf', + GA = 'ga', + GM = 'gm', + GE = 'ge', + DE = 'de', + GH = 'gh', + GI = 'gi', + GR = 'gr', + GL = 'gl', + GD = 'gd', + GP = 'gp', + GU = 'gu', + GT = 'gt', + GG = 'gg', + GN = 'gn', + GW = 'gw', + GY = 'gy', + HT = 'ht', + HM = 'hm', + HN = 'hn', + HK = 'hk', + HU = 'hu', + IS = 'is', + IN = 'in', + ID = 'id', + IR = 'ir', + IQ = 'iq', + IE = 'ie', + IM = 'im', + IL = 'il', + IT = 'it', + JM = 'jm', + JP = 'jp', + JE = 'je', + JO = 'jo', + KZ = 'kz', + KE = 'ke', + KI = 'ki', + KP = 'kp', + KR = 'kr', + KW = 'kw', + KG = 'kg', + LA = 'la', + LV = 'lv', + LB = 'lb', + LS = 'ls', + LR = 'lr', + LY = 'ly', + LI = 'li', + LT = 'lt', + LU = 'lu', + MO = 'mo', + MK = 'mk', + MG = 'mg', + MW = 'mw', + MY = 'my', + ML = 'ml', + MT = 'mt', + MH = 'mh', + MQ = 'mq', + MR = 'mr', + MU = 'mu', + YT = 'yt', + MX = 'mx', + FM = 'fm', + MD = 'md', + MC = 'mc', + MN = 'mn', + ME = 'me', + MS = 'ms', + MA = 'ma', + MZ = 'mz', + MM = 'mm', + NA = 'na', + NR = 'nr', + NP = 'np', + NL = 'nl', + NC = 'nc', + NZ = 'nz', + NI = 'ni', + NE = 'ne', + NG = 'ng', + NU = 'nu', + NF = 'nf', + MP = 'mp', + NO = 'no', + OM = 'om', + PK = 'pk', + PW = 'pw', + PS = 'ps', + PA = 'pa', + PG = 'pg', + PY = 'py', + PE = 'pe', + PH = 'ph', + PN = 'pn', + PL = 'pl', + PT = 'pt', + PR = 'pr', + QA = 'qa', + RE = 're', + RO = 'ro', + RU = 'ru', + RW = 'rw', + BL = 'bl', + SH = 'sh', + KN = 'kn', + LC = 'lc', + MF = 'mf', + PM = 'pm', + VC = 'vc', + WS = 'ws', + SM = 'sm', + ST = 'st', + SA = 'sa', + SN = 'sn', + RS = 'rs', + SC = 'sc', + SL = 'sl', + SG = 'sg', + SX = 'sx', + SK = 'sk', + SI = 'si', + SB = 'sb', + SO = 'so', + ZA = 'za', + GS = 'gs', + SS = 'ss', + ES = 'es', + LK = 'lk', + SD = 'sd', + SR = 'sr', + SJ = 'sj', + SZ = 'sz', + SE = 'se', + CH = 'ch', + SY = 'sy', + TW = 'tw', + TJ = 'tj', + TZ = 'tz', + TH = 'th', + TG = 'tg', + TK = 'tk', + TO = 'to', + TT = 'tt', + TN = 'tn', + TR = 'tr', + TM = 'tm', + TC = 'tc', + TV = 'tv', + UG = 'ug', + UA = 'ua', + AE = 'ae', + GB = 'gb', + US = 'us', + UM = 'um', + UY = 'uy', + UZ = 'uz', + VU = 'vu', + VA = 'va', + VE = 've', + VN = 'vn', + WF = 'wf', + EH = 'eh', + YE = 'ye', + ZM = 'zm', + ZW = 'zw', +} + +export const countryOptions: { [key: string]: string } = { + [Country.AF]: 'Afghanistan', + [Country.AL]: 'Albania', + [Country.DZ]: 'Algeria', + [Country.AS]: 'American Samoa', + [Country.AD]: 'Andorra', + [Country.AO]: 'Angola', + [Country.AI]: 'Anguilla', + [Country.AQ]: 'Antarctica', + [Country.AG]: 'Antigua and Barbuda', + [Country.AR]: 'Argentina', + [Country.AM]: 'Armenia', + [Country.AW]: 'Aruba', + [Country.AC]: 'Ascension Island', + [Country.AU]: 'Australia', + [Country.AT]: 'Austria', + [Country.AZ]: 'Azerbaijan', + [Country.BS]: 'Bahamas', + [Country.BH]: 'Bahrain', + [Country.BD]: 'Bangladesh', + [Country.BB]: 'Barbados', + [Country.BY]: 'Belarus', + [Country.BE]: 'Belgium', + [Country.BZ]: 'Belize', + [Country.BJ]: 'Benin', + [Country.BM]: 'Bermuda', + [Country.BT]: 'Bhutan', + [Country.BO]: 'Bolivia', + [Country.BQ]: 'Bonaire, Sint Eustatius and Saba', + [Country.BA]: 'Bosnia and Herzegovina', + [Country.BW]: 'Botswana', + [Country.BV]: 'Bouvet Island', + [Country.BR]: 'Brazil', + [Country.IO]: 'British Indian Ocean Territory', + [Country.BN]: 'Brunei Darussalam', + [Country.BG]: 'Bulgaria', + [Country.BF]: 'Burkina Faso', + [Country.BI]: 'Burundi', + [Country.KH]: 'Cambodia', + [Country.CM]: 'Cameroon', + [Country.CA]: 'Canada', + [Country.IC]: 'Canary Islands', + [Country.CV]: 'Cape Verde', + [Country.KY]: 'Cayman Islands', + [Country.CF]: 'Central African Republic', + [Country.EA]: 'Ceuta and Melilla', + [Country.TD]: 'Chad', + [Country.CL]: 'Chile', + [Country.CN]: 'China', + [Country.CX]: 'Christmas Island', + [Country.CP]: 'Clipperton Island', + [Country.CC]: 'Cocos (Keeling) Islands', + [Country.CO]: 'Colombia', + [Country.KM]: 'Comoros', + [Country.CK]: 'Cook Islands', + [Country.CR]: 'Costa Rica', + [Country.CI]: "Côte d'Ivoire", + [Country.HR]: 'Croatia', + [Country.CU]: 'Cuba', + [Country.CW]: 'Curaçao', + [Country.CY]: 'Cyprus', + [Country.CZ]: 'Czechia', + [Country.CD]: 'Democratic Republic of the Congo', + [Country.DK]: 'Denmark', + [Country.DG]: 'Diego Garcia', + [Country.DJ]: 'Djibouti', + [Country.DM]: 'Dominica', + [Country.DO]: 'Dominican Republic', + [Country.TL]: 'Timor-Leste', + [Country.EC]: 'Ecuador', + [Country.EG]: 'Egypt', + [Country.SV]: 'El Salvador', + [Country.GQ]: 'Equatorial Guinea', + [Country.ER]: 'Eritrea', + [Country.EE]: 'Estonia', + [Country.ET]: 'Ethiopia', + [Country.EU]: 'European Union', + [Country.FK]: 'Falkland Islands', + [Country.FO]: 'Faroe Islands', + [Country.FJ]: 'Fiji', + [Country.FI]: 'Finland', + [Country.FR]: 'France', + [Country.FX]: 'Metropolitan France', + [Country.GF]: 'French Guiana', + [Country.PF]: 'French Polynesia', + [Country.TF]: 'French Southern Territories', + [Country.GA]: 'Gabon', + [Country.GM]: 'Gambia', + [Country.GE]: 'Georgia', + [Country.DE]: 'Germany', + [Country.GH]: 'Ghana', + [Country.GI]: 'Gibraltar', + [Country.GR]: 'Greece', + [Country.GL]: 'Greenland', + [Country.GD]: 'Grenada', + [Country.GP]: 'Guadeloupe', + [Country.GU]: 'Guam', + [Country.GT]: 'Guatemala', + [Country.GG]: 'Guernsey', + [Country.GN]: 'Guinea', + [Country.GW]: 'Guinea-Bissau', + [Country.GY]: 'Guyana', + [Country.HT]: 'Haiti', + [Country.HM]: 'Heard Island and McDonald Islands', + [Country.HN]: 'Honduras', + [Country.HK]: 'Hong Kong', + [Country.HU]: 'Hungary', + [Country.IS]: 'Iceland', + [Country.IN]: 'India', + [Country.ID]: 'Indonesia', + [Country.IR]: 'Iran', + [Country.IQ]: 'Iraq', + [Country.IE]: 'Ireland', + [Country.IM]: 'Isle of Man', + [Country.IL]: 'Israel', + [Country.IT]: 'Italy', + [Country.JM]: 'Jamaica', + [Country.JP]: 'Japan', + [Country.JE]: 'Jersey', + [Country.JO]: 'Jordan', + [Country.KZ]: 'Kazakhstan', + [Country.KE]: 'Kenya', + [Country.KI]: 'Kiribati', + [Country.KP]: 'North Korea', + [Country.KR]: 'South Korea', + [Country.KW]: 'Kuwait', + [Country.KG]: 'Kyrgyzstan', + [Country.LA]: 'Laos', + [Country.LV]: 'Latvia', + [Country.LB]: 'Lebanon', + [Country.LS]: 'Lesotho', + [Country.LR]: 'Liberia', + [Country.LY]: 'Libya', + [Country.LI]: 'Liechtenstein', + [Country.LT]: 'Lithuania', + [Country.LU]: 'Luxembourg', + [Country.MO]: 'Macao', + [Country.MK]: 'North Macedonia', + [Country.MG]: 'Madagascar', + [Country.MW]: 'Malawi', + [Country.MY]: 'Malaysia', + [Country.ML]: 'Mali', + [Country.MT]: 'Malta', + [Country.MH]: 'Marshall Islands', + [Country.MQ]: 'Martinique', + [Country.MR]: 'Mauritania', + [Country.MU]: 'Mauritius', + [Country.YT]: 'Mayotte', + [Country.MX]: 'Mexico', + [Country.FM]: 'Micronesia', + [Country.MD]: 'Moldova', + [Country.MC]: 'Monaco', + [Country.MN]: 'Mongolia', + [Country.ME]: 'Montenegro', + [Country.MS]: 'Montserrat', + [Country.MA]: 'Morocco', + [Country.MZ]: 'Mozambique', + [Country.MM]: 'Myanmar', + [Country.NA]: 'Namibia', + [Country.NR]: 'Nauru', + [Country.NP]: 'Nepal', + [Country.NL]: 'Netherlands', + [Country.NC]: 'New Caledonia', + [Country.NZ]: 'New Zealand', + [Country.NI]: 'Nicaragua', + [Country.NE]: 'Niger', + [Country.NG]: 'Nigeria', + [Country.NU]: 'Niue', + [Country.NF]: 'Norfolk Island', + [Country.MP]: 'Northern Mariana Islands', + [Country.NO]: 'Norway', + [Country.OM]: 'Oman', + [Country.PK]: 'Pakistan', + [Country.PW]: 'Palau', + [Country.PS]: 'Palestine', + [Country.PA]: 'Panama', + [Country.PG]: 'Papua New Guinea', + [Country.PY]: 'Paraguay', + [Country.PE]: 'Peru', + [Country.PH]: 'Philippines', + [Country.PN]: 'Pitcairn Islands', + [Country.PL]: 'Poland', + [Country.PT]: 'Portugal', + [Country.PR]: 'Puerto Rico', + [Country.QA]: 'Qatar', + [Country.RE]: 'Réunion', + [Country.RO]: 'Romania', + [Country.RU]: 'Russia', + [Country.RW]: 'Rwanda', + [Country.BL]: 'Saint Barthélemy', + [Country.SH]: 'Saint Helena, Ascension and Tristan da Cunha', + [Country.KN]: 'Saint Kitts and Nevis', + [Country.LC]: 'Saint Lucia', + [Country.MF]: 'Saint Martin', + [Country.PM]: 'Saint Pierre and Miquelon', + [Country.VC]: 'Saint Vincent and the Grenadines', + [Country.WS]: 'Samoa', + [Country.SM]: 'San Marino', + [Country.ST]: 'Sao Tome and Principe', + [Country.SA]: 'Saudi Arabia', + [Country.SN]: 'Senegal', + [Country.RS]: 'Serbia', + [Country.SC]: 'Seychelles', + [Country.SL]: 'Sierra Leone', + [Country.SG]: 'Singapore', + [Country.SK]: 'Slovakia', + [Country.SI]: 'Slovenia', + [Country.SB]: 'Solomon Islands', + [Country.SO]: 'Somalia', + [Country.ZA]: 'South Africa', + [Country.GS]: 'South Georgia and the South Sandwich Islands', + [Country.SS]: 'South Sudan', + [Country.ES]: 'Spain', + [Country.LK]: 'Sri Lanka', + [Country.SD]: 'Sudan', + [Country.SR]: 'Suriname', + [Country.SJ]: 'Svalbard and Jan Mayen', + [Country.SE]: 'Sweden', + [Country.CH]: 'Switzerland', + [Country.SY]: 'Syria', + [Country.TW]: 'Taiwan', + [Country.TJ]: 'Tajikistan', + [Country.TZ]: 'Tanzania', + [Country.TH]: 'Thailand', + [Country.TG]: 'Togo', + [Country.TK]: 'Tokelau', + [Country.TO]: 'Tonga', + [Country.TT]: 'Trinidad and Tobago', + [Country.TN]: 'Tunisia', + [Country.TR]: 'Turkey', + [Country.TM]: 'Turkmenistan', + [Country.TC]: 'Turks and Caicos Islands', + [Country.TV]: 'Tuvalu', + [Country.UG]: 'Uganda', + [Country.UA]: 'Ukraine', + [Country.AE]: 'United Arab Emirates', + [Country.GB]: 'United Kingdom', + [Country.US]: 'United States', + [Country.UM]: 'United States Minor Outlying Islands', + [Country.UY]: 'Uruguay', + [Country.UZ]: 'Uzbekistan', + [Country.VU]: 'Vanuatu', + [Country.VA]: 'Vatican City', + [Country.VE]: 'Venezuela', + [Country.VN]: 'Vietnam', + [Country.WF]: 'Wallis and Futuna', + [Country.EH]: 'Western Sahara', + [Country.YE]: 'Yemen', + [Country.ZM]: 'Zambia', + [Country.ZW]: 'Zimbabwe', +}; + +export enum VatType { + AD_NRT = 'ad_nrt', + AE_TRN = 'ae_trn', + AR_CUIT = 'ar_cuit', + AU_ABN = 'au_abn', + AU_ARN = 'au_arn', + BG_UIC = 'bg_uic', + BH_VAT = 'bh_vat', + BO_TIN = 'bo_tin', + BR_CNPJ = 'br_cnpj', + BR_CPF = 'br_cpf', + BY_TIN = 'by_tin', + CA_BN = 'ca_bn', + CA_GST_HST = 'ca_gst_hst', + CA_PST_BC = 'ca_pst_bc', + CA_PST_MB = 'ca_pst_mb', + CA_PST_SK = 'ca_pst_sk', + CA_QST = 'ca_qst', + CH_UID = 'ch_uid', + CH_VAT = 'ch_vat', + CL_TIN = 'cl_tin', + CN_TIN = 'cn_tin', + CO_NIT = 'co_nit', + CR_TIN = 'cr_tin', + DE_STN = 'de_stn', + DO_RCN = 'do_rcn', + EC_RUC = 'ec_ruc', + EG_TIN = 'eg_tin', + ES_CIF = 'es_cif', + EU_OSS_VAT = 'eu_oss_vat', + EU_VAT = 'eu_vat', + GB_VAT = 'gb_vat', + GE_VAT = 'ge_vat', + HK_BR = 'hk_br', + HR_OIB = 'hr_oib', + HU_TIN = 'hu_tin', + ID_NPWP = 'id_npwp', + IL_VAT = 'il_vat', + IN_GST = 'in_gst', + IS_VAT = 'is_vat', + JP_CN = 'jp_cn', + JP_RN = 'jp_rn', + JP_TRN = 'jp_trn', + KE_PIN = 'ke_pin', + KR_BRN = 'kr_brn', + KZ_BIN = 'kz_bin', + LI_UID = 'li_uid', + MA_VAT = 'ma_vat', + MD_VAT = 'md_vat', + MX_RFC = 'mx_rfc', + MY_FRP = 'my_frp', + MY_ITN = 'my_itn', + MY_SST = 'my_sst', + NG_TIN = 'ng_tin', + NO_VAT = 'no_vat', + NO_VOEC = 'no_voec', + NZ_GST = 'nz_gst', + OM_VAT = 'om_vat', + PE_RUC = 'pe_ruc', + PH_TIN = 'ph_tin', + RO_TIN = 'ro_tin', + RS_PIB = 'rs_pib', + RU_INN = 'ru_inn', + RU_KPP = 'ru_kpp', + SA_VAT = 'sa_vat', + SG_GST = 'sg_gst', + SG_UEN = 'sg_uen', + SI_TIN = 'si_tin', + SV_NIT = 'sv_nit', + TH_VAT = 'th_vat', + TR_TIN = 'tr_tin', + TW_VAT = 'tw_vat', + TZ_VAT = 'tz_vat', + UA_VAT = 'ua_vat', + US_EIN = 'us_ein', + UY_RUC = 'uy_ruc', + UZ_TIN = 'uz_tin', + UZ_VAT = 'uz_vat', + VE_RIF = 've_rif', + VN_TIN = 'vn_tin', + ZA_VAT = 'za_vat', +} + +export const vatTypeOptions: { [key: string]: string } = { + [VatType.AD_NRT]: 'Andorran NRT', + [VatType.AE_TRN]: 'UAE TRN', + [VatType.AR_CUIT]: 'Argentinian CUIT', + [VatType.AU_ABN]: 'Australian ABN', + [VatType.AU_ARN]: 'Australian ARN', + [VatType.BG_UIC]: 'Bulgarian UIC', + [VatType.BH_VAT]: 'Bahraini VAT', + [VatType.BO_TIN]: 'Bolivian TIN', + [VatType.BR_CNPJ]: 'Brazilian CNPJ', + [VatType.BR_CPF]: 'Brazilian CPF', + [VatType.BY_TIN]: 'Belarusian TIN', + [VatType.CA_BN]: 'Canadian BN', + [VatType.CA_GST_HST]: 'Canadian GST/HST', + [VatType.CA_PST_BC]: 'Canadian PST BC', + [VatType.CA_PST_MB]: 'Canadian PST MB', + [VatType.CA_PST_SK]: 'Canadian PST SK', + [VatType.CA_QST]: 'Canadian QST', + [VatType.CH_UID]: 'Swiss UID', + [VatType.CH_VAT]: 'Swiss VAT', + [VatType.CL_TIN]: 'Chilean TIN', + [VatType.CN_TIN]: 'Chinese TIN', + [VatType.CO_NIT]: 'Colombian NIT', + [VatType.CR_TIN]: 'Costa Rican TIN', + [VatType.DE_STN]: 'German STN', + [VatType.DO_RCN]: 'Dominican RCN', + [VatType.EC_RUC]: 'Ecuadorian RUC', + [VatType.EG_TIN]: 'Egyptian TIN', + [VatType.ES_CIF]: 'Spanish CIF', + [VatType.EU_OSS_VAT]: 'EU OSS VAT', + [VatType.EU_VAT]: 'EU VAT', + [VatType.GB_VAT]: 'British VAT', + [VatType.GE_VAT]: 'Georgian VAT', + [VatType.HK_BR]: 'Hong Kong BR', + [VatType.HR_OIB]: 'Croatian OIB', + [VatType.HU_TIN]: 'Hungarian TIN', + [VatType.ID_NPWP]: 'Indonesian NPWP', + [VatType.IL_VAT]: 'Israeli VAT', + [VatType.IN_GST]: 'Indian GST', + [VatType.IS_VAT]: 'Icelandic VAT', + [VatType.JP_CN]: 'Japanese CN', + [VatType.JP_RN]: 'Japanese RN', + [VatType.JP_TRN]: 'Japanese TRN', + [VatType.KE_PIN]: 'Kenyan PIN', + [VatType.KR_BRN]: 'South Korean BRN', + [VatType.KZ_BIN]: 'Kazakh BIN', + [VatType.LI_UID]: 'Liechtenstein UID', + [VatType.MA_VAT]: 'Moroccan VAT', + [VatType.MD_VAT]: 'Moldovan VAT', + [VatType.MX_RFC]: 'Mexican RFC', + [VatType.MY_FRP]: 'Malaysian FRP', + [VatType.MY_ITN]: 'Malaysian ITN', + [VatType.MY_SST]: 'Malaysian SST', + [VatType.NG_TIN]: 'Nigerian TIN', + [VatType.NO_VAT]: 'Norwegian VAT', + [VatType.NO_VOEC]: 'Norwegian VOEC', + [VatType.NZ_GST]: 'New Zealand GST', + [VatType.OM_VAT]: 'Omani VAT', + [VatType.PE_RUC]: 'Peruvian RUC', + [VatType.PH_TIN]: 'Philippine TIN', + [VatType.RO_TIN]: 'Romanian TIN', + [VatType.RS_PIB]: 'Serbian PIB', + [VatType.RU_INN]: 'Russian INN', + [VatType.RU_KPP]: 'Russian KPP', + [VatType.SA_VAT]: 'Saudi VAT', + [VatType.SG_GST]: 'Singaporean GST', + [VatType.SG_UEN]: 'Singaporean UEN', + [VatType.SI_TIN]: 'Slovenian TIN', + [VatType.SV_NIT]: 'Salvadoran NIT', + [VatType.TH_VAT]: 'Thai VAT', + [VatType.TR_TIN]: 'Turkish TIN', + [VatType.TW_VAT]: 'Taiwanese VAT', + [VatType.TZ_VAT]: 'Tanzanian VAT', + [VatType.UA_VAT]: 'Ukrainian VAT', + [VatType.US_EIN]: 'American EIN', + [VatType.UY_RUC]: 'Uruguayan RUC', + [VatType.UZ_TIN]: 'Uzbek TIN', + [VatType.UZ_VAT]: 'Uzbek VAT', + [VatType.VE_RIF]: 'Venezuelan RIF', + [VatType.VN_TIN]: 'Vietnamese TIN', + [VatType.ZA_VAT]: 'South African VAT', +}; diff --git a/packages/apps/job-launcher/client/src/hooks/usePayments.ts b/packages/apps/job-launcher/client/src/hooks/usePayments.ts new file mode 100644 index 0000000000..45ef31d085 --- /dev/null +++ b/packages/apps/job-launcher/client/src/hooks/usePayments.ts @@ -0,0 +1,22 @@ +import useSWR from 'swr'; +import * as paymentService from '../services/payment'; + +export const usePayments = ({ + page, + pageSize, +}: { + page?: number; + pageSize?: number; +}) => { + return useSWR(`human-protocol-Payments--${page}-${pageSize}`, async () => { + try { + const payments = await paymentService.getPayments({ + page, + pageSize, + }); + return payments; + } catch (err) { + return []; + } + }); +}; diff --git a/packages/apps/job-launcher/client/src/main.tsx b/packages/apps/job-launcher/client/src/main.tsx index 61ee3993ec..0148d40d7b 100644 --- a/packages/apps/job-launcher/client/src/main.tsx +++ b/packages/apps/job-launcher/client/src/main.tsx @@ -48,7 +48,10 @@ loadStripe(publishableKey).then((stripePromise) => { - + diff --git a/packages/apps/job-launcher/client/src/pages/Profile/Settings/index.tsx b/packages/apps/job-launcher/client/src/pages/Profile/Settings/index.tsx new file mode 100644 index 0000000000..df91fedd35 --- /dev/null +++ b/packages/apps/job-launcher/client/src/pages/Profile/Settings/index.tsx @@ -0,0 +1,230 @@ +import { + Box, + Button, + Card, + CardContent, + Divider, + Grid, + Typography, +} from '@mui/material'; +import { useEffect, useState } from 'react'; +import BillingDetailsModal from '../../../components/BillingDetails/BillingDetailsModal'; +import AddCardModal from '../../../components/CreditCard/AddCardModal'; +import CardList from '../../../components/CreditCard/CardList'; +import { PaymentTable } from '../../../components/Payment/PaymentTable'; +import SuccessModal from '../../../components/SuccessModal'; +import { countryOptions, vatTypeOptions } from '../../../constants/payment'; +import { useSnackbar } from '../../../providers/SnackProvider'; +import { getUserBillingInfo, getUserCards } from '../../../services/payment'; +import { BillingInfo, CardData } from '../../../types'; + +const Settings = () => { + const { showError } = useSnackbar(); + const [isAddCardOpen, setIsAddCardOpen] = useState(false); + const [isEditBillingOpen, setIsEditBillingOpen] = useState(false); + const [isSuccessOpen, setIsSuccessOpen] = useState(false); + const [openBillingAfterAddCard, setOpenBillingAfterAddCard] = useState(false); + const [successMessage, setSuccessMessage] = useState(''); + const [cards, setCards] = useState([]); + const [billingInfo, setBillingInfo] = useState({ + name: '', + email: '', + address: { + city: '', + country: '', + postalCode: '', + line: '', + }, + vat: '', + vatType: '', + }); + + const fetchCards = async () => { + try { + const data = await getUserCards(); + setCards(data); + } catch (error) { + showError('Error fetching cards'); + } + }; + + const fetchBillingInfo = async () => { + try { + const data = await getUserBillingInfo(); + setBillingInfo({ ...billingInfo, ...data }); + } catch (error) { + showError('Error fetching billing info'); + } + }; + + useEffect(() => { + fetchCards(); + fetchBillingInfo(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const handleSuccessAction = (message: string) => { + setSuccessMessage(message); + setIsSuccessOpen(true); + }; + + return ( + + + + Settings + + + + + {/* Billing Info card */} + + + + + + + + Billing Details + + + Add/edit your billing details. + + + + + + + Details + + Full Name / Company Name: {billingInfo?.name} + + Email: {billingInfo?.email} + Address: {billingInfo?.address.line} + + Postal code: {billingInfo?.address.postalCode} + + City: {billingInfo?.address.city} + + Country: {countryOptions[billingInfo?.address.country]} + + + VAT Type: {vatTypeOptions[billingInfo?.vatType]} + + VAT Number: {billingInfo?.vat} + + + + + + + {/* Payment Details card */} + + + + + + + + Payment Details + + + Manage your credit cards and payment options + + + + + + + + handleSuccessAction(message)} + openAddCreditCardModal={setIsAddCardOpen} + /> + + + + + + + + + + + + + Payments + + + + + + + + + setIsAddCardOpen(false)} + onComplete={() => { + handleSuccessAction('Your card has been successfully added.'); + fetchCards(); + if (!billingInfo.name || !billingInfo.address) + setOpenBillingAfterAddCard(true); + }} + /> + + setIsEditBillingOpen(false)} + billingInfo={billingInfo} + setBillingInfo={(info) => { + setBillingInfo(info); + handleSuccessAction( + 'Your billing details have been successfully updated.', + ); + }} + /> + + { + if (openBillingAfterAddCard) setIsEditBillingOpen(true); + setIsSuccessOpen(false); + }} + message={successMessage} + /> + + ); +}; + +export default Settings; diff --git a/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx b/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx index 0ef2a3efbb..a96d27ab0b 100644 --- a/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx @@ -1,5 +1,5 @@ import { Box, Typography } from '@mui/material'; -import React, { useState } from 'react'; +import { useState } from 'react'; import { StyledTab, StyledTabs } from '../../../components/Tabs'; import { CryptoTopUpForm } from '../../../components/TopUpAccount/CryptoTopUpForm'; import { FiatTopUpForm } from '../../../components/TopUpAccount/FiatTopUpForm'; diff --git a/packages/apps/job-launcher/client/src/pages/Profile/Transactions/index.tsx b/packages/apps/job-launcher/client/src/pages/Profile/Transactions/index.tsx new file mode 100644 index 0000000000..8b3234317c --- /dev/null +++ b/packages/apps/job-launcher/client/src/pages/Profile/Transactions/index.tsx @@ -0,0 +1,29 @@ +import { Box, Grid, Typography } from '@mui/material'; +import { PaymentTable } from '../../../components/Payment/PaymentTable'; + +const Transactions = () => { + return ( + + + + Transactions + + + + + + + + + + ); +}; + +export default Transactions; diff --git a/packages/apps/job-launcher/client/src/services/payment.ts b/packages/apps/job-launcher/client/src/services/payment.ts index 629510570d..a04f2ced88 100644 --- a/packages/apps/job-launcher/client/src/services/payment.ts +++ b/packages/apps/job-launcher/client/src/services/payment.ts @@ -1,9 +1,30 @@ import { WalletClient } from 'viem'; import { PAYMENT_SIGNATURE_KEY } from '../constants/payment'; -import { CryptoPaymentRequest, FiatPaymentRequest } from '../types'; +import { + BillingInfo, + CryptoPaymentRequest, + FiatPaymentRequest, +} from '../types'; import api from '../utils/api'; +export const createSetupIntent = async () => { + const { data } = await api.post('/payment/fiat/setup-card'); + return data; +}; + +export const confirmSetupIntent = async ( + setupIntentId: string, + defaultCard: boolean, +) => { + const { data } = await api.post('/payment/fiat/confirm-card', { + setupId: setupIntentId, + defaultCard, + }); + + return data; +}; + export const createCryptoPayment = async ( signer: WalletClient, body: CryptoPaymentRequest, @@ -54,3 +75,42 @@ export const getOperatorAddress = async () => { return data; }; + +export const getUserCards = async () => { + const { data } = await api.get('/payment/fiat/cards'); + return data; +}; + +export const deleteUserCard = async (cardId: string) => { + await api.delete(`/payment/fiat/card?paymentMethodId=${cardId}`); +}; + +export const setUserDefaultCard = async (cardId: string) => { + await api.patch('/payment/fiat/default-card', { paymentMethodId: cardId }); +}; + +export const getUserBillingInfo = async () => { + const { data } = await api.get('/payment/fiat/billing-info'); + return data; +}; + +export const editUserBillingInfo = async (body: BillingInfo) => { + await api.patch('/payment/fiat/billing-info', body); +}; + +export const getPayments = async ({ + page, + pageSize, +}: { + page?: number; + pageSize?: number; +}) => { + const queryString = `page=${page}&page_size=${pageSize}&sort=desc&sort_field=created_at`; + const { data } = await api.get(`/payment/payments?${queryString}`); + return data; +}; + +export const getReceipt = async (paymentId: string) => { + const response = await api.get(`/payment/receipt/${paymentId}`); + return response.data; +}; diff --git a/packages/apps/job-launcher/client/src/types/index.ts b/packages/apps/job-launcher/client/src/types/index.ts index 1040517ba9..17ebc9aac7 100644 --- a/packages/apps/job-launcher/client/src/types/index.ts +++ b/packages/apps/job-launcher/client/src/types/index.ts @@ -31,6 +31,7 @@ export type CryptoPaymentRequest = { export type FiatPaymentRequest = { amount: number; currency: string; + paymentMethodId: string; }; export type CreateFortuneJobRequest = { @@ -300,6 +301,30 @@ export type Qualification = { expires_at: string; }; +export type CardData = { + id: string; + last4: string; + brand: string; + expMonth: number; + expYear: number; + default: boolean; +}; + +export type BillingInfo = { + name: string; + email?: string; + address: Address; + vat: string; + vatType: string; +}; + +type Address = { + city: string; + country: string; + line: string; + postalCode: string; +}; + export type JobCountDto = { totalJobs: number; launched: number; diff --git a/packages/apps/job-launcher/server/src/common/config/env-schema.ts b/packages/apps/job-launcher/server/src/common/config/env-schema.ts index 3f4c2d4d69..6cda78114e 100644 --- a/packages/apps/job-launcher/server/src/common/config/env-schema.ts +++ b/packages/apps/job-launcher/server/src/common/config/env-schema.ts @@ -8,6 +8,7 @@ export const envValidator = Joi.object({ FE_URL: Joi.string(), MAX_RETRY_COUNT: Joi.number(), MINIMUM_FEE_USD: Joi.number(), + // ABUSE_AMOUNT: Joi.number(), // Auth JWT_PRIVATE_KEY: Joi.string().required(), JWT_PUBLIC_KEY: Joi.string().required(), diff --git a/packages/apps/job-launcher/server/src/common/config/server-config.service.ts b/packages/apps/job-launcher/server/src/common/config/server-config.service.ts index 8709a92f48..29525db690 100644 --- a/packages/apps/job-launcher/server/src/common/config/server-config.service.ts +++ b/packages/apps/job-launcher/server/src/common/config/server-config.service.ts @@ -74,4 +74,10 @@ export class ServerConfigService { get coingeckoApiKey(): string | undefined { return this.configService.get('COINGECKO_API_KEY'); } + /** + * The amount to charge abusive users. + */ + // get abuseAmount(): number { + // return +this.configService.get('ABUSE_AMOUNT', 10000); + // } } diff --git a/packages/apps/job-launcher/server/src/common/constants/errors.ts b/packages/apps/job-launcher/server/src/common/constants/errors.ts index 36f94028f5..0db17b4093 100644 --- a/packages/apps/job-launcher/server/src/common/constants/errors.ts +++ b/packages/apps/job-launcher/server/src/common/constants/errors.ts @@ -32,6 +32,7 @@ export enum ErrorWebhook { NotFound = 'Webhook not found', UrlNotFound = 'Webhook URL not found', NotCreated = 'Webhook has not been created', + InvalidEscrow = 'Invalid escrow data provided', } /** @@ -87,11 +88,16 @@ export enum ErrorToken { */ export enum ErrorPayment { NotFound = 'Payment not found', + InvoiceNotFound = 'Invoice not found', NotSuccess = 'Unsuccessful payment', IntentNotCreated = 'Payment intent not created', - ClientSecretDoesNotExist = 'Payment intent was not created', + CardNotAssigned = 'Card not assigned', + SetupNotFound = 'Setup not found', + ClientSecretDoesNotExist = 'Client secret does not exist', CustomerNotFound = 'Customer not found', CustomerNotCreated = 'Customer not created', + PaymentMethodInUse = 'Cannot delete the default payment method in use', + PaymentMethodAssociationFailed = 'Payment method association failed', IncorrectAmount = 'Incorrect amount', TransactionAlreadyExists = 'Transaction already exists', TransactionNotFoundByHash = 'Transaction not found by hash', diff --git a/packages/apps/job-launcher/server/src/common/enums/cron-job.ts b/packages/apps/job-launcher/server/src/common/enums/cron-job.ts index 38d17f9cf7..c9de542055 100644 --- a/packages/apps/job-launcher/server/src/common/enums/cron-job.ts +++ b/packages/apps/job-launcher/server/src/common/enums/cron-job.ts @@ -5,4 +5,5 @@ export enum CronJobType { CancelEscrow = 'cancel-escrow', ProcessPendingWebhook = 'process-pending-webhook', SyncJobStatuses = 'sync-job-statuses', + // Abuse = 'abuse', } diff --git a/packages/apps/job-launcher/server/src/common/enums/job.ts b/packages/apps/job-launcher/server/src/common/enums/job.ts index dd668085da..461c3da6b7 100644 --- a/packages/apps/job-launcher/server/src/common/enums/job.ts +++ b/packages/apps/job-launcher/server/src/common/enums/job.ts @@ -166,7 +166,7 @@ export enum WorkerLanguage { ZU = 'zu', } -export enum WorkerLocation { +export enum Country { AF = 'af', AL = 'al', DZ = 'dz', diff --git a/packages/apps/job-launcher/server/src/common/enums/payment.ts b/packages/apps/job-launcher/server/src/common/enums/payment.ts index e89e51a7c8..6da116125d 100644 --- a/packages/apps/job-launcher/server/src/common/enums/payment.ts +++ b/packages/apps/job-launcher/server/src/common/enums/payment.ts @@ -62,6 +62,7 @@ export enum PaymentType { DEPOSIT = 'deposit', REFUND = 'refund', WITHDRAWAL = 'withdrawal', + // SLASH = 'slash', } export enum PaymentStatus { @@ -75,3 +76,91 @@ export enum StripePaymentStatus { REQUIRES_PAYMENT_METHOD = 'requires_payment_method', SUCCEEDED = 'succeeded', } + +export enum PaymentSortField { + CREATED_AT = 'created_at', + AMOUNT = 'amount', +} + +export enum VatType { + AD_NRT = 'ad_nrt', + AE_TRN = 'ae_trn', + AR_CUIT = 'ar_cuit', + AU_ABN = 'au_abn', + AU_ARN = 'au_arn', + BG_UIC = 'bg_uic', + BH_VAT = 'bh_vat', + BO_TIN = 'bo_tin', + BR_CNPJ = 'br_cnpj', + BR_CPF = 'br_cpf', + BY_TIN = 'by_tin', + CA_BN = 'ca_bn', + CA_GST_HST = 'ca_gst_hst', + CA_PST_BC = 'ca_pst_bc', + CA_PST_MB = 'ca_pst_mb', + CA_PST_SK = 'ca_pst_sk', + CA_QST = 'ca_qst', + CH_UID = 'ch_uid', + CH_VAT = 'ch_vat', + CL_TIN = 'cl_tin', + CN_TIN = 'cn_tin', + CO_NIT = 'co_nit', + CR_TIN = 'cr_tin', + DE_STN = 'de_stn', + DO_RCN = 'do_rcn', + EC_RUC = 'ec_ruc', + EG_TIN = 'eg_tin', + ES_CIF = 'es_cif', + EU_OSS_VAT = 'eu_oss_vat', + EU_VAT = 'eu_vat', + GB_VAT = 'gb_vat', + GE_VAT = 'ge_vat', + HK_BR = 'hk_br', + HR_OIB = 'hr_oib', + HU_TIN = 'hu_tin', + ID_NPWP = 'id_npwp', + IL_VAT = 'il_vat', + IN_GST = 'in_gst', + IS_VAT = 'is_vat', + JP_CN = 'jp_cn', + JP_RN = 'jp_rn', + JP_TRN = 'jp_trn', + KE_PIN = 'ke_pin', + KR_BRN = 'kr_brn', + KZ_BIN = 'kz_bin', + LI_UID = 'li_uid', + MA_VAT = 'ma_vat', + MD_VAT = 'md_vat', + MX_RFC = 'mx_rfc', + MY_FRP = 'my_frp', + MY_ITN = 'my_itn', + MY_SST = 'my_sst', + NG_TIN = 'ng_tin', + NO_VAT = 'no_vat', + NO_VOEC = 'no_voec', + NZ_GST = 'nz_gst', + OM_VAT = 'om_vat', + PE_RUC = 'pe_ruc', + PH_TIN = 'ph_tin', + RO_TIN = 'ro_tin', + RS_PIB = 'rs_pib', + RU_INN = 'ru_inn', + RU_KPP = 'ru_kpp', + SA_VAT = 'sa_vat', + SG_GST = 'sg_gst', + SG_UEN = 'sg_uen', + SI_TIN = 'si_tin', + SV_NIT = 'sv_nit', + TH_VAT = 'th_vat', + TR_TIN = 'tr_tin', + TW_VAT = 'tw_vat', + TZ_VAT = 'tz_vat', + UA_VAT = 'ua_vat', + US_EIN = 'us_ein', + UY_RUC = 'uy_ruc', + UZ_TIN = 'uz_tin', + UZ_VAT = 'uz_vat', + VE_RIF = 've_rif', + VN_TIN = 'vn_tin', + ZA_VAT = 'za_vat', +} diff --git a/packages/apps/job-launcher/server/src/common/enums/webhook.ts b/packages/apps/job-launcher/server/src/common/enums/webhook.ts index 70fd5bca60..07132b86b4 100644 --- a/packages/apps/job-launcher/server/src/common/enums/webhook.ts +++ b/packages/apps/job-launcher/server/src/common/enums/webhook.ts @@ -4,6 +4,7 @@ export enum EventType { ESCROW_COMPLETED = 'escrow_completed', TASK_CREATION_FAILED = 'task_creation_failed', ESCROW_FAILED = 'escrow_failed', + // ABUSE_DETECTED = 'abuse_detected', } export enum OracleType { diff --git a/packages/apps/job-launcher/server/src/database/migrations/1731504887456-abuse.ts b/packages/apps/job-launcher/server/src/database/migrations/1731504887456-abuse.ts new file mode 100644 index 0000000000..e11705bc5e --- /dev/null +++ b/packages/apps/job-launcher/server/src/database/migrations/1731504887456-abuse.ts @@ -0,0 +1,149 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class Abuse1731504887456 implements MigrationInterface { + name = 'Abuse1731504887456'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "hmt"."users" + ADD "stripe_customer_id" character varying + `); + await queryRunner.query(` + ALTER TABLE "hmt"."users" + ADD CONSTRAINT "UQ_5ffbe395603641c29e8ce9b4c97" UNIQUE ("stripe_customer_id") + `); + await queryRunner.query(` + ALTER TYPE "hmt"."payments_type_enum" + RENAME TO "payments_type_enum_old" + `); + await queryRunner.query(` + CREATE TYPE "hmt"."payments_type_enum" AS ENUM('deposit', 'refund', 'withdrawal', 'slash') + `); + await queryRunner.query(` + ALTER TABLE "hmt"."payments" + ALTER COLUMN "type" TYPE "hmt"."payments_type_enum" USING "type"::"text"::"hmt"."payments_type_enum" + `); + await queryRunner.query(` + DROP TYPE "hmt"."payments_type_enum_old" + `); + await queryRunner.query(` + DROP INDEX "hmt"."IDX_012a8481fc9980fcc49f3f0dc2" + `); + await queryRunner.query(` + ALTER TYPE "hmt"."webhook_event_type_enum" + RENAME TO "webhook_event_type_enum_old" + `); + await queryRunner.query(` + CREATE TYPE "hmt"."webhook_event_type_enum" AS ENUM( + 'escrow_created', + 'escrow_canceled', + 'escrow_completed', + 'task_creation_failed', + 'escrow_failed', + 'abuse_detected' + ) + `); + await queryRunner.query(` + ALTER TABLE "hmt"."webhook" + ALTER COLUMN "event_type" TYPE "hmt"."webhook_event_type_enum" USING "event_type"::"text"::"hmt"."webhook_event_type_enum" + `); + await queryRunner.query(` + DROP TYPE "hmt"."webhook_event_type_enum_old" + `); + await queryRunner.query(` + ALTER TYPE "hmt"."cron-jobs_cron_job_type_enum" + RENAME TO "cron-jobs_cron_job_type_enum_old" + `); + await queryRunner.query(` + CREATE TYPE "hmt"."cron-jobs_cron_job_type_enum" AS ENUM( + 'create-escrow', + 'setup-escrow', + 'fund-escrow', + 'cancel-escrow', + 'process-pending-webhook', + 'sync-job-statuses', + 'abuse' + ) + `); + await queryRunner.query(` + ALTER TABLE "hmt"."cron-jobs" + ALTER COLUMN "cron_job_type" TYPE "hmt"."cron-jobs_cron_job_type_enum" USING "cron_job_type"::"text"::"hmt"."cron-jobs_cron_job_type_enum" + `); + await queryRunner.query(` + DROP TYPE "hmt"."cron-jobs_cron_job_type_enum_old" + `); + await queryRunner.query(` + CREATE UNIQUE INDEX "IDX_012a8481fc9980fcc49f3f0dc2" ON "hmt"."webhook" ("chain_id", "escrow_address", "event_type") + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + DROP INDEX "hmt"."IDX_012a8481fc9980fcc49f3f0dc2" + `); + await queryRunner.query(` + CREATE TYPE "hmt"."cron-jobs_cron_job_type_enum_old" AS ENUM( + 'create-escrow', + 'setup-escrow', + 'fund-escrow', + 'cancel-escrow', + 'process-pending-webhook', + 'sync-job-statuses' + ) + `); + await queryRunner.query(` + ALTER TABLE "hmt"."cron-jobs" + ALTER COLUMN "cron_job_type" TYPE "hmt"."cron-jobs_cron_job_type_enum_old" USING "cron_job_type"::"text"::"hmt"."cron-jobs_cron_job_type_enum_old" + `); + await queryRunner.query(` + DROP TYPE "hmt"."cron-jobs_cron_job_type_enum" + `); + await queryRunner.query(` + ALTER TYPE "hmt"."cron-jobs_cron_job_type_enum_old" + RENAME TO "cron-jobs_cron_job_type_enum" + `); + await queryRunner.query(` + CREATE TYPE "hmt"."webhook_event_type_enum_old" AS ENUM( + 'escrow_created', + 'escrow_canceled', + 'escrow_completed', + 'task_creation_failed', + 'escrow_failed' + ) + `); + await queryRunner.query(` + ALTER TABLE "hmt"."webhook" + ALTER COLUMN "event_type" TYPE "hmt"."webhook_event_type_enum_old" USING "event_type"::"text"::"hmt"."webhook_event_type_enum_old" + `); + await queryRunner.query(` + DROP TYPE "hmt"."webhook_event_type_enum" + `); + await queryRunner.query(` + ALTER TYPE "hmt"."webhook_event_type_enum_old" + RENAME TO "webhook_event_type_enum" + `); + await queryRunner.query(` + CREATE UNIQUE INDEX "IDX_012a8481fc9980fcc49f3f0dc2" ON "hmt"."webhook" ("chain_id", "escrow_address", "event_type") + `); + await queryRunner.query(` + CREATE TYPE "hmt"."payments_type_enum_old" AS ENUM('deposit', 'refund', 'withdrawal') + `); + await queryRunner.query(` + ALTER TABLE "hmt"."payments" + ALTER COLUMN "type" TYPE "hmt"."payments_type_enum_old" USING "type"::"text"::"hmt"."payments_type_enum_old" + `); + await queryRunner.query(` + DROP TYPE "hmt"."payments_type_enum" + `); + await queryRunner.query(` + ALTER TYPE "hmt"."payments_type_enum_old" + RENAME TO "payments_type_enum" + `); + await queryRunner.query(` + ALTER TABLE "hmt"."users" DROP CONSTRAINT "UQ_5ffbe395603641c29e8ce9b4c97" + `); + await queryRunner.query(` + ALTER TABLE "hmt"."users" DROP COLUMN "stripe_customer_id" + `); + } +} diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts index e5d041b059..eb59c06d6b 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts @@ -79,6 +79,7 @@ describe('CronJobService', () => { webhookRepository: WebhookRepository, storageService: StorageService, jobService: JobService, + // paymentService: PaymentService, jobRepository: JobRepository; const signerMock = { @@ -152,6 +153,7 @@ describe('CronJobService', () => { }).compile(); service = module.get(CronJobService); + // paymentService = module.get(PaymentService); jobService = module.get(JobService); jobRepository = module.get(JobRepository); repository = module.get(CronJobRepository); @@ -857,7 +859,7 @@ describe('CronJobService', () => { }; jest - .spyOn(webhookRepository, 'findByStatus') + .spyOn(webhookRepository, 'findByStatusAndType') .mockResolvedValue([webhookEntity1 as any, webhookEntity2 as any]); sendWebhookMock = jest.spyOn(webhookService as any, 'sendWebhook'); @@ -1055,4 +1057,148 @@ describe('CronJobService', () => { ); }); }); + + // describe('processAbuseCronJob', () => { + // let sendWebhookMock: any; + // let cronJobEntityMock: Partial; + // let webhookEntity: Partial, jobEntity: Partial; + + // beforeEach(() => { + // cronJobEntityMock = { + // cronJobType: CronJobType.Abuse, + // startedAt: new Date(), + // }; + + // webhookEntity = { + // id: 1, + // chainId: ChainId.LOCALHOST, + // escrowAddress: MOCK_ADDRESS, + // status: WebhookStatus.PENDING, + // waitUntil: new Date(), + // retriesCount: 0, + // }; + + // jobEntity = { + // id: 1, + // chainId: ChainId.LOCALHOST, + // escrowAddress: MOCK_ADDRESS, + // status: JobStatus.PENDING, + // }; + + // jest + // .spyOn(webhookRepository, 'findByStatusAndType') + // .mockResolvedValue([webhookEntity as any]); + + // sendWebhookMock = jest.spyOn(webhookService as any, 'sendWebhook'); + // sendWebhookMock.mockResolvedValue(true); + + // jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); + + // jest.spyOn(repository, 'findOneByType').mockResolvedValue(null); + // jest + // .spyOn(repository, 'createUnique') + // .mockResolvedValue(cronJobEntityMock as any); + // jest + // .spyOn(jobRepository, 'findOneByChainIdAndEscrowAddress') + // .mockResolvedValue(jobEntity as any); + // jest + // .spyOn(jobService, 'processEscrowCancellation') + // .mockResolvedValue(null as any); + // jest.spyOn(paymentService, 'createSlash').mockResolvedValue(null as any); + // }); + + // afterEach(() => { + // jest.restoreAllMocks(); + // }); + + // it('should not run if cron job is already running', async () => { + // jest.spyOn(service, 'isCronJobRunning').mockResolvedValueOnce(true); + + // const startCronJobMock = jest.spyOn(service, 'startCronJob'); + + // await service.processAbuse(); + + // expect(startCronJobMock).not.toHaveBeenCalled(); + // }); + + // it('should create cron job entity to lock the process', async () => { + // jest + // .spyOn(service, 'startCronJob') + // .mockResolvedValueOnce(cronJobEntityMock as any); + + // await service.processAbuse(); + + // expect(service.startCronJob).toHaveBeenCalledWith(CronJobType.Abuse); + // }); + + // it('should slash for all of the pending webhooks', async () => { + // await service.processAbuse(); + + // expect(jobRepository.updateOne).toHaveBeenCalled(); + // expect(jobEntity.status).toBe(JobStatus.CANCELED); + // expect(webhookRepository.updateOne).toHaveBeenCalled(); + // expect(webhookEntity.status).toBe(WebhookStatus.COMPLETED); + // }); + + // it('should increase retriesCount by 1 if no job is found', async () => { + // jest + // .spyOn(jobRepository, 'findOneByChainIdAndEscrowAddress') + // .mockResolvedValue(null); + // await service.processAbuse(); + + // expect(webhookRepository.updateOne).toHaveBeenCalled(); + // expect(webhookEntity.status).toBe(WebhookStatus.PENDING); + // expect(webhookEntity.retriesCount).toBe(1); + // expect(webhookEntity.waitUntil).toBeInstanceOf(Date); + // }); + + // it('should increase retriesCount by 1 if processEscrowCancellation fails', async () => { + // jest + // .spyOn(jobService, 'processEscrowCancellation') + // .mockRejectedValueOnce(new Error()); + // await service.processAbuse(); + + // expect(webhookRepository.updateOne).toHaveBeenCalled(); + // expect(webhookEntity.status).toBe(WebhookStatus.PENDING); + // expect(webhookEntity.retriesCount).toBe(1); + // expect(webhookEntity.waitUntil).toBeInstanceOf(Date); + // }); + + // it('should increase retriesCount by 1 if createSlash fails', async () => { + // jest + // .spyOn(paymentService, 'createSlash') + // .mockRejectedValueOnce(new Error()); + // await service.processAbuse(); + + // expect(webhookRepository.updateOne).toHaveBeenCalled(); + // expect(webhookEntity.status).toBe(WebhookStatus.PENDING); + // expect(webhookEntity.retriesCount).toBe(1); + // expect(webhookEntity.waitUntil).toBeInstanceOf(Date); + // }); + + // it('should mark webhook as failed if retriesCount exceeds threshold', async () => { + // jest + // .spyOn(jobService, 'processEscrowCancellation') + // .mockRejectedValueOnce(new Error()); + + // webhookEntity.retriesCount = MOCK_MAX_RETRY_COUNT; + + // await service.processAbuse(); + + // expect(webhookRepository.updateOne).toHaveBeenCalled(); + // expect(webhookEntity.status).toBe(WebhookStatus.FAILED); + // }); + + // it('should complete the cron job entity to unlock', async () => { + // jest + // .spyOn(service, 'completeCronJob') + // .mockResolvedValueOnce(cronJobEntityMock as any); + + // await service.processAbuse(); + + // expect(service.completeCronJob).toHaveBeenCalledWith( + // cronJobEntityMock as any, + // ); + // }); + // }); }); diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts index cff79ccd85..5b49958b4d 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts @@ -1,7 +1,11 @@ import { HttpStatus, Injectable, Logger } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; import { CronJobType } from '../../common/enums/cron-job'; -import { ErrorCronJob, ErrorEscrow } from '../../common/constants/errors'; +import { + ErrorCronJob, + ErrorEscrow, + // ErrorJob, +} from '../../common/constants/errors'; import { CronJobEntity } from './cron-job.entity'; import { CronJobRepository } from './cron-job.repository'; @@ -290,8 +294,9 @@ export class CronJobService { const cronJob = await this.startCronJob(CronJobType.ProcessPendingWebhook); try { - const webhookEntities = await this.webhookRepository.findByStatus( + const webhookEntities = await this.webhookRepository.findByStatusAndType( WebhookStatus.PENDING, + EventType.ESCROW_CREATED, ); for (const webhookEntity of webhookEntities) { @@ -313,6 +318,68 @@ export class CronJobService { await this.completeCronJob(cronJob); } + // @Cron('*/5 * * * *') + /** + * Process an abuse webhook. + * @returns {Promise} - Returns a promise that resolves when the operation is complete. + */ + // public async processAbuse(): Promise { + // const isCronJobRunning = await this.isCronJobRunning(CronJobType.Abuse); + + // if (isCronJobRunning) { + // return; + // } + + // this.logger.log('Abuse START'); + // const cronJob = await this.startCronJob(CronJobType.Abuse); + + // try { + // const webhookEntities = await this.webhookRepository.findByStatusAndType( + // WebhookStatus.PENDING, + // EventType.ABUSE_DETECTED, + // ); + + // for (const webhookEntity of webhookEntities) { + // try { + // const jobEntity = + // await this.jobRepository.findOneByChainIdAndEscrowAddress( + // webhookEntity.chainId, + // webhookEntity.escrowAddress, + // ); + // if (!jobEntity) { + // this.logger.log(ErrorJob.NotFound, JobService.name); + // throw new ControlledError( + // ErrorJob.NotFound, + // HttpStatus.BAD_REQUEST, + // ); + // } + // if ( + // jobEntity.escrowAddress && + // jobEntity.status !== JobStatus.CANCELED + // ) { + // await this.jobService.processEscrowCancellation(jobEntity); + // jobEntity.status = JobStatus.CANCELED; + // await this.jobRepository.updateOne(jobEntity); + // } + // await this.paymentService.createSlash(jobEntity); + // } catch (err) { + // this.logger.error( + // `Error slashing escrow (address: ${webhookEntity.escrowAddress}, chainId: ${webhookEntity.chainId}: ${err.message}`, + // ); + // await this.webhookService.handleWebhookError(webhookEntity); + // continue; + // } + // webhookEntity.status = WebhookStatus.COMPLETED; + // await this.webhookRepository.updateOne(webhookEntity); + // } + // } catch (e) { + // this.logger.error(e); + // } + + // this.logger.log('Abuse STOP'); + // await this.completeCronJob(cronJob); + // } + @Cron('30 */2 * * * *') /** * Process a job that syncs job statuses. diff --git a/packages/apps/job-launcher/server/src/modules/job/job.dto.ts b/packages/apps/job-launcher/server/src/modules/job/job.dto.ts index 29587eff4b..6ec0a1bd61 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.dto.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.dto.ts @@ -31,7 +31,7 @@ import { JobStatusFilter, WorkerBrowser, WorkerLanguage, - WorkerLocation, + Country, } from '../../common/enums/job'; import { Transform } from 'class-transformer'; import { AWSRegions, StorageProviders } from '../../common/enums/storage'; @@ -560,12 +560,12 @@ export class JobCaptchaAdvancedDto { workerLanguage?: WorkerLanguage; @ApiProperty({ - enum: WorkerLocation, - name: 'workerocation', + enum: Country, + name: 'worker_location', }) - @IsEnumCaseInsensitive(WorkerLocation) + @IsEnumCaseInsensitive(Country) @IsOptional() - workerLocation?: WorkerLocation; + workerLocation?: Country; @ApiProperty({ enum: WorkerBrowser, diff --git a/packages/apps/job-launcher/server/src/modules/job/job.repository.ts b/packages/apps/job-launcher/server/src/modules/job/job.repository.ts index a95cd73671..cd2c13d088 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.repository.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.repository.ts @@ -2,7 +2,7 @@ import { ChainId } from '@human-protocol/sdk'; import { Injectable } from '@nestjs/common'; import { ServerConfigService } from '../../common/config/server-config.service'; import { SortDirection } from '../../common/enums/collection'; -import { DataSource, In, LessThanOrEqual } from 'typeorm'; +import { DataSource, In, LessThanOrEqual, Not } from 'typeorm'; import { JobSortField, JobStatus, @@ -18,6 +18,7 @@ import { JobCountDto, } from '../statistic/statistic.dto'; import { convertToDatabaseSortDirection } from '../../database/database.utils'; +import { PaymentSource } from 'src/common/enums/payment'; @Injectable() export class JobRepository extends BaseRepository { @@ -82,6 +83,21 @@ export class JobRepository extends BaseRepository { }); } + public async findActiveByUserAndPaymentSource( + userId: number, + paymentSource: PaymentSource, + ): Promise { + return this.find({ + where: { + userId, + status: Not(In([JobStatus.COMPLETED, JobStatus.CANCELED])), + payment: { + source: paymentSource, + }, + }, + }); + } + public async fetchFiltered( data: GetJobsDto, userId: number, diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts index f7276de4d5..eb95d24d99 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts @@ -36,7 +36,7 @@ import { JobStatusFilter, WorkerBrowser, WorkerLanguage, - WorkerLocation, + Country, } from '../../common/enums/job'; import { MOCK_ADDRESS, @@ -1714,7 +1714,7 @@ describe('JobService', () => { maxRequests: 4, advanced: { workerLanguage: WorkerLanguage.EN, - workerLocation: WorkerLocation.FR, + workerLocation: Country.FR, targetBrowser: WorkerBrowser.DESKTOP, }, annotations: { diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts index e7463f7017..9f180d50e2 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts @@ -8,6 +8,9 @@ import { UseGuards, Headers, HttpStatus, + Patch, + Delete, + Param, } from '@nestjs/common'; import { ApiBearerAuth, @@ -20,16 +23,23 @@ import { JwtAuthGuard } from '../../common/guards'; import { RequestWithUser } from '../../common/types'; import { + BillingInfoDto, + BillingInfoUpdateDto, + CardConfirmDto, + GetPaymentsDto, GetRateDto, PaymentCryptoCreateDto, + PaymentDto, PaymentFiatConfirmDto, PaymentFiatCreateDto, + PaymentMethodIdDto, } from './payment.dto'; import { PaymentService } from './payment.service'; import { HEADER_SIGNATURE_KEY } from '../../common/constants'; import { ControlledError } from '../../common/errors/controlled'; import { ServerConfigService } from '../../common/config/server-config.service'; import { RateService } from './rate.service'; +import { PageDto } from '../../common/pagination/pagination.dto'; // import { WhitelistAuthGuard } from 'src/common/guards/whitelist.auth'; @ApiBearerAuth() @@ -43,6 +53,152 @@ export class PaymentController { private readonly rateService: RateService, ) {} + @ApiOperation({ + summary: 'Create a crypto payment', + description: 'Endpoint to create a new crypto payment.', + }) + @ApiBody({ type: PaymentCryptoCreateDto }) + @ApiResponse({ + status: 200, + description: 'Crypto payment created successfully', + type: Boolean, + }) + @ApiResponse({ + status: 400, + description: 'Bad Request. Invalid input parameters.', + }) + @ApiResponse({ + status: 401, + description: 'Unauthorized. Missing or invalid credentials.', + }) + @ApiResponse({ + status: 404, + description: 'Not Found. Could not find the requested content.', + }) + @ApiResponse({ + status: 409, + description: 'Conflict. Conflict with the current state of the server.', + }) + // Disabled until billing system is active + // @UseGuards(WhitelistAuthGuard) + @Post('/crypto') + public async createCryptoPayment( + @Headers(HEADER_SIGNATURE_KEY) signature: string, + @Body() data: PaymentCryptoCreateDto, + @Request() req: RequestWithUser, + ): Promise { + return this.paymentService.createCryptoPayment( + req.user.id, + data, + signature, + ); + } + + @ApiOperation({ + summary: 'Get exchange rates', + description: 'Endpoint to get exchange rates.', + }) + @ApiResponse({ + status: 200, + description: 'Exchange rates retrieved successfully', + type: Number, + }) + @ApiResponse({ + status: 401, + description: 'Unauthorized. Missing or invalid credentials.', + }) + @ApiResponse({ + status: 404, + description: 'Not Found. Could not find the requested content.', + }) + @Get('/rates') + public async getRate(@Query() data: GetRateDto): Promise { + try { + return this.rateService.getRate(data.from, data.to); + } catch (e) { + throw new ControlledError( + 'Error getting rates', + HttpStatus.CONFLICT, + e.stack, + ); + } + } + + @ApiOperation({ + summary: 'Get Job Launcher minimum fee', + description: 'Endpoint to get Job Launcher minimum fee in USD.', + }) + @ApiResponse({ + status: 200, + description: 'Minimum fee retrieved successfully', + type: Number, + }) + @ApiResponse({ + status: 401, + description: 'Unauthorized. Missing or invalid credentials.', + }) + @ApiResponse({ + status: 404, + description: 'Not Found. Could not find the requested content.', + }) + @Get('/min-fee') + public async getMinFee(): Promise { + return this.serverConfigService.minimunFeeUsd; + } + + @ApiOperation({ + summary: 'Assign a card to a user', + description: 'Endpoint to assign a card to an user.', + }) + @ApiResponse({ + status: 200, + description: 'Payment created successfully', + type: String, + }) + @ApiResponse({ + status: 401, + description: 'Unauthorized. Missing or invalid credentials.', + }) + @ApiResponse({ + status: 404, + description: 'Not Found. Could not find the requested content.', + }) + @Post('/fiat/setup-card') + public async assignCard(@Request() req: RequestWithUser): Promise { + return this.paymentService.createCustomerAndAssignCard(req.user); + } + + @ApiOperation({ + summary: 'Confirm a card', + description: + 'Endpoint to confirm that a card was successfully assigned to an user.', + }) + @ApiBody({ type: PaymentFiatConfirmDto }) + @ApiResponse({ + status: 200, + description: 'Card confirmed successfully', + type: Boolean, + }) + @ApiResponse({ + status: 400, + description: 'Bad Request. Invalid input parameters.', + }) + @ApiResponse({ + status: 401, + description: 'Unauthorized. Missing or invalid credentials.', + }) + @ApiResponse({ + status: 404, + description: 'Not Found. Could not find the requested content.', + }) + @Post('/fiat/confirm-card') + public async confirmSetupCard( + @Request() req: RequestWithUser, + @Body() data: CardConfirmDto, + ): Promise { + return this.paymentService.confirmCard(req.user, data); + } + @ApiOperation({ summary: 'Create a fiat payment', description: 'Endpoint to create a new fiat payment.', @@ -70,7 +226,7 @@ export class PaymentController { @Body() data: PaymentFiatCreateDto, @Request() req: RequestWithUser, ): Promise { - return this.paymentService.createFiatPayment(req.user.id, data); + return this.paymentService.createFiatPayment(req.user, data); } @ApiOperation({ @@ -104,95 +260,141 @@ export class PaymentController { } @ApiOperation({ - summary: 'Create a crypto payment', - description: 'Endpoint to create a new crypto payment.', + summary: 'List user cards', + description: 'Fetches all cards associated with the user.', }) - @ApiBody({ type: PaymentCryptoCreateDto }) @ApiResponse({ status: 200, - description: 'Crypto payment created successfully', - type: Boolean, + description: 'Cards retrieved successfully', + type: Array, }) - @ApiResponse({ - status: 400, - description: 'Bad Request. Invalid input parameters.', + @Get('/fiat/cards') + public async listPaymentMethods(@Request() req: RequestWithUser) { + return this.paymentService.listUserPaymentMethods(req.user); + } + + @ApiOperation({ + summary: 'Delete a card', + description: + 'Deletes a specific card. If the card is the default payment method and is in use, returns an error.', }) @ApiResponse({ - status: 401, - description: 'Unauthorized. Missing or invalid credentials.', + status: 200, + description: 'Card deleted successfully', }) @ApiResponse({ - status: 404, - description: 'Not Found. Could not find the requested content.', + status: 400, + description: 'Cannot delete default card that is in use by a job.', + }) + @Delete('/fiat/card') + public async deleteCard( + @Request() req: RequestWithUser, + @Query() data: PaymentMethodIdDto, + ): Promise { + await this.paymentService.deletePaymentMethod( + req.user, + data.paymentMethodId, + ); + } + + @ApiOperation({ + summary: 'Get user billing information', + description: 'Fetches the billing information associated with the user.', }) @ApiResponse({ - status: 409, - description: 'Conflict. Conflict with the current state of the server.', + status: 200, + description: 'Billing information retrieved successfully', + type: BillingInfoDto, }) - // Disabled until billing system is active - // @UseGuards(WhitelistAuthGuard) - @Post('/crypto') - public async createCryptoPayment( - @Headers(HEADER_SIGNATURE_KEY) signature: string, - @Body() data: PaymentCryptoCreateDto, + @Get('/fiat/billing-info') + public async getBillingInfo( @Request() req: RequestWithUser, - ): Promise { - return this.paymentService.createCryptoPayment( - req.user.id, - data, - signature, - ); + ): Promise { + return this.paymentService.getUserBillingInfo(req.user); } @ApiOperation({ - summary: 'Get exchange rates', - description: 'Endpoint to get exchange rates.', + summary: 'Edit user billing information', + description: 'Updates the billing information associated with the user.', }) + @ApiBody({ type: BillingInfoUpdateDto }) @ApiResponse({ status: 200, - description: 'Exchange rates retrieved successfully', - type: Number, + description: 'Billing information updated successfully', + }) + @Patch('/fiat/billing-info') + public async editBillingInfo( + @Request() req: RequestWithUser, + @Body() data: BillingInfoUpdateDto, + ): Promise { + await this.paymentService.updateUserBillingInfo(req.user, data); + } + + @ApiOperation({ + summary: 'Change default payment method', + description: + 'Sets a specific card as the default payment method for the user.', }) @ApiResponse({ - status: 401, - description: 'Unauthorized. Missing or invalid credentials.', + status: 200, + description: 'Default payment method updated successfully', }) @ApiResponse({ - status: 404, - description: 'Not Found. Could not find the requested content.', + status: 400, + description: 'Cannot set the specified card as default.', }) - @Get('/rates') - public async getRate(@Query() data: GetRateDto): Promise { - try { - return this.rateService.getRate(data.from, data.to); - } catch (e) { - throw new ControlledError( - 'Error getting rates', - HttpStatus.CONFLICT, - e.stack, - ); - } + @ApiBody({ type: PaymentMethodIdDto }) + @Patch('/fiat/default-card') + public async changeDefaultCard( + @Request() req: RequestWithUser, + @Body() data: PaymentMethodIdDto, + ): Promise { + await this.paymentService.changeDefaultPaymentMethod( + req.user, + data.paymentMethodId, + ); } @ApiOperation({ - summary: 'Get Job Launcher minimum fee', - description: 'Endpoint to get Job Launcher minimum fee in USD.', + summary: 'Get all payments', + description: + 'Endpoint to retrieve all payments for the authenticated user.', }) @ApiResponse({ status: 200, - description: 'Minimum fee retrieved successfully', - type: Number, + description: 'Payments retrieved successfully', + type: [PaymentDto], }) @ApiResponse({ status: 401, description: 'Unauthorized. Missing or invalid credentials.', }) + @Get('/payments') + async getAllPayments( + @Query() data: GetPaymentsDto, + @Request() req: RequestWithUser, + ): Promise> { + return this.paymentService.getAllPayments(data, req.user.id); + } + + @ApiOperation({ + summary: 'Get receipt for a payment', + description: 'Endpoint to retrieve the receipt for a specific payment.', + }) + @ApiResponse({ + status: 200, + description: 'Receipt retrieved successfully', + type: String, + }) @ApiResponse({ status: 404, - description: 'Not Found. Could not find the requested content.', + description: 'Not Found. Could not find the requested payment or receipt.', }) - @Get('/min-fee') - public async getMinFee(): Promise { - return this.serverConfigService.minimunFeeUsd; + @Get('/receipt/:paymentId') + async getReceipt( + @Param('paymentId') paymentId: string, + @Request() req: RequestWithUser, + ) { + return this.paymentService.getReceipt(paymentId, req.user); } } diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.dto.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.dto.ts index bb34cd9028..b7d30b39e0 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.dto.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.dto.ts @@ -1,8 +1,25 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNumber, IsString, Min } from 'class-validator'; -import { Currency } from '../../common/enums/payment'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { + IsBoolean, + IsEnum, + IsNumber, + IsObject, + IsOptional, + IsString, + Min, +} from 'class-validator'; +import { + Currency, + PaymentSortField, + PaymentSource, + PaymentStatus, + PaymentType, + VatType, +} from '../../common/enums/payment'; import { ChainId } from '@human-protocol/sdk'; import { IsEnumCaseInsensitive } from '../../common/decorators'; +import { Country } from '../../common/enums/job'; +import { PageOptionsDto } from '../../common/pagination/pagination.dto'; export class PaymentFiatConfirmDto { @ApiProperty({ name: 'payment_id' }) @@ -21,6 +38,12 @@ export class PaymentFiatCreateDto { }) @IsEnumCaseInsensitive(Currency) public currency: Currency; + + @ApiProperty({ + name: 'payment_method_id', + }) + @IsString() + public paymentMethodId: string; } export class PaymentCryptoCreateDto { @@ -36,6 +59,16 @@ export class PaymentCryptoCreateDto { public transactionHash: string; } +export class CardConfirmDto { + @ApiProperty({ name: 'payment_id' }) + @IsString() + public setupId: string; + + @ApiPropertyOptional({ name: 'default_card', default: false }) + @IsBoolean() + public defaultCard = false; +} + export class GetRateDto { @ApiProperty() @IsString() @@ -47,12 +80,156 @@ export class GetRateDto { } export class PaymentRefundCreateDto { + @ApiPropertyOptional({ name: 'refund_amount' }) @IsNumber() public refundAmount: number; + @ApiPropertyOptional({ name: 'user_id' }) @IsNumber() public userId: number; + @ApiPropertyOptional({ name: 'job_id' }) @IsNumber() public jobId: number; } + +export class AddressDto { + @ApiPropertyOptional() + @IsOptional() + @IsString() + public city?: string; + + @ApiPropertyOptional({ enum: Country }) + @IsOptional() + @IsEnum(Country) + public country?: string; + + @ApiPropertyOptional() + @IsOptional() + @IsString() + public line?: string; + + @ApiPropertyOptional({ name: 'postal_code' }) + @IsOptional() + @IsString() + public postalCode?: string; +} + +export class BillingInfoUpdateDto { + @ApiPropertyOptional() + @IsOptional() + @IsString() + public name?: string; + + @ApiPropertyOptional() + @IsOptional() + @IsObject() + public address?: AddressDto; + + @ApiPropertyOptional() + @IsOptional() + @IsString() + public vat?: string; + + @ApiPropertyOptional({ name: 'vat_type', enum: VatType }) + @IsOptional() + @IsEnum(VatType) + public vatType?: VatType; +} + +export class BillingInfoDto extends BillingInfoUpdateDto { + @ApiProperty() + @IsString() + public email?: string; +} + +export class PaymentMethodIdDto { + @ApiProperty({ name: 'payment_method_id' }) + @IsString() + public paymentMethodId: string; +} + +export class CardDto { + @ApiProperty() + @IsString() + public id: string; + + @ApiProperty({ name: 'last_4' }) + @IsString() + public last4: string; + + @ApiProperty() + @IsString() + public brand: string; + + @ApiProperty({ name: 'exp_month' }) + @IsNumber() + public expMonth: number; + + @ApiProperty({ name: 'exp_year' }) + @IsNumber() + public expYear: number; + + @ApiProperty() + @IsBoolean() + public default: boolean; +} + +export class GetPaymentsDto extends PageOptionsDto { + @ApiPropertyOptional({ + name: 'sort_field', + enum: PaymentSortField, + default: PaymentSortField.CREATED_AT, + }) + @IsOptional() + @IsEnum(PaymentSortField) + sortField?: PaymentSortField = PaymentSortField.CREATED_AT; +} + +export class PaymentDto { + @ApiProperty() + @IsNumber() + public amount: number; + + @ApiProperty() + @IsNumber() + public rate: number; + + @ApiProperty() + @IsString() + public currency: string; + + @ApiProperty({ enum: PaymentType }) + @IsEnum(PaymentType) + public type: PaymentType; + + @ApiProperty({ enum: PaymentSource }) + @IsEnum(PaymentSource) + public source: PaymentSource; + + @ApiProperty({ enum: PaymentStatus }) + @IsEnum(PaymentStatus) + public status: PaymentStatus; + + @ApiProperty({ + description: + 'Transaction hash for crypto payments or Stripe payment ID for fiat payments', + }) + @IsString() + @IsOptional() + public transaction?: string; + + @ApiProperty({ + name: 'escrow_address', + description: 'Escrow address associated with the payment (if applicable)', + }) + @IsString() + @IsOptional() + public escrowAddress?: string; + + @ApiProperty({ + name: 'created_at', + }) + @IsString() + public createdAt: string; +} diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.interface.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.interface.ts new file mode 100644 index 0000000000..a9b4d8650f --- /dev/null +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.interface.ts @@ -0,0 +1,6 @@ +import { PaymentEntity } from './payment.entity'; + +export interface ListResult { + entities: PaymentEntity[]; + itemCount: number; +} diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.module.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.module.ts index fc2d37f002..bbf2d841cc 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.module.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.module.ts @@ -11,11 +11,15 @@ import { HttpModule } from '@nestjs/axios'; import { Web3Module } from '../web3/web3.module'; import { RateService } from './rate.service'; import { WhitelistModule } from '../whitelist/whitelist.module'; +import { JobEntity } from '../job/job.entity'; +import { UserEntity } from '../user/user.entity'; +import { JobRepository } from '../job/job.repository'; +import { UserRepository } from '../user/user.repository'; @Module({ imports: [ HttpModule, - TypeOrmModule.forFeature([PaymentEntity]), + TypeOrmModule.forFeature([PaymentEntity, JobEntity, UserEntity]), ConfigModule, Web3Module, WhitelistModule, @@ -34,7 +38,13 @@ import { WhitelistModule } from '../whitelist/whitelist.module'; }), ], controllers: [PaymentController], - providers: [PaymentService, PaymentRepository, RateService], + providers: [ + PaymentService, + PaymentRepository, + RateService, + JobRepository, + UserRepository, + ], exports: [PaymentService, PaymentRepository, RateService], }) export class PaymentModule {} diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.repository.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.repository.ts index 5271b668c2..d3bcfdeb20 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.repository.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.repository.ts @@ -4,6 +4,9 @@ import { DataSource } from 'typeorm'; import { PaymentStatus } from '../../common/enums/payment'; import { BaseRepository } from '../../database/base.repository'; import { PaymentEntity } from './payment.entity'; +import { ListResult } from '../payment/payment.interface'; +import { GetPaymentsDto } from './payment.dto'; +import { convertToDatabaseSortDirection } from '../../database/database.utils'; @Injectable() export class PaymentRepository extends BaseRepository { @@ -34,4 +37,24 @@ export class PaymentRepository extends BaseRepository { }, }); } + + public async fetchFiltered( + data: GetPaymentsDto, + userId: number, + ): Promise { + const queryBuilder = this.createQueryBuilder('payment'); + queryBuilder.leftJoinAndSelect('payment.job', 'job'); + + const dbSortDirection = convertToDatabaseSortDirection(data.sort); + queryBuilder.orderBy(`payment.${data.sortField}`, dbSortDirection); + + queryBuilder.where('payment.userId = :userId', { userId }); + + queryBuilder.offset(data.skip).limit(data.pageSize); + + const itemCount = await queryBuilder.getCount(); + const entities = await queryBuilder.getMany(); + + return { entities, itemCount }; + } } diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.service.spec.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.service.spec.ts index 2f822e30aa..2fa64dbece 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.service.spec.ts @@ -13,11 +13,13 @@ import { } from '../../common/constants/errors'; import { Currency, + PaymentSortField, PaymentSource, PaymentStatus, PaymentType, StripePaymentStatus, TokenId, + VatType, } from '../../common/enums/payment'; import { TX_CONFIRMATION_TRESHOLD } from '../../common/constants'; import { @@ -27,6 +29,7 @@ import { MOCK_TRANSACTION_HASH, mockConfig, } from '../../../test/constants'; +import { ServerConfigService } from '../../common/config/server-config.service'; import { Web3Service } from '../web3/web3.service'; import { HMToken__factory } from '@human-protocol/core/typechain-types'; import { ChainId, NETWORKS } from '@human-protocol/sdk'; @@ -38,6 +41,11 @@ import { StripeConfigService } from '../../common/config/stripe-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { ControlledError } from '../../common/errors/controlled'; import { RateService } from './rate.service'; +import { UserRepository } from '../user/user.repository'; +import { JobRepository } from '../job/job.repository'; +import { GetPaymentsDto } from './payment.dto'; +import { SortDirection } from '../../common/enums/collection'; +import { Country } from '../../common/enums/job'; jest.mock('@human-protocol/sdk'); @@ -49,6 +57,7 @@ describe('PaymentService', () => { let stripe: Stripe; let paymentService: PaymentService; let paymentRepository: PaymentRepository; + let userRepository: UserRepository; const signerMock = { address: MOCK_ADDRESS, @@ -76,6 +85,14 @@ describe('PaymentService', () => { provide: PaymentRepository, useValue: createMock(), }, + { + provide: UserRepository, + useValue: createMock(), + }, + { + provide: JobRepository, + useValue: createMock(), + }, { provide: Web3Service, useValue: { @@ -92,74 +109,136 @@ describe('PaymentService', () => { }, }, NetworkConfigService, + ServerConfigService, ], }).compile(); paymentService = moduleRef.get(PaymentService); paymentRepository = moduleRef.get(PaymentRepository); - - const stripeCustomersCreateMock = jest.fn(); - const stripePaymentIntentsCreateMock = jest.fn(); - const stripePaymentIntentsRetrieveMock = jest.fn(); + userRepository = moduleRef.get(UserRepository); stripe = { customers: { - create: stripeCustomersCreateMock, + create: jest.fn(), + update: jest.fn(), + listPaymentMethods: jest.fn(), + listTaxIds: jest.fn(), + createTaxId: jest.fn(), + retrieve: jest.fn(), }, paymentIntents: { - create: stripePaymentIntentsCreateMock, - retrieve: stripePaymentIntentsRetrieveMock, + create: jest.fn(), + retrieve: jest.fn(), + update: jest.fn(), + }, + setupIntents: { + create: jest.fn(), + retrieve: jest.fn(), + }, + paymentMethods: { + retrieve: jest.fn(), + detach: jest.fn(), + }, + charges: { + retrieve: jest.fn(), + }, + invoices: { + create: jest.fn(), + finalizeInvoice: jest.fn(), + }, + invoiceItems: { + create: jest.fn(), }, } as any; paymentService['stripe'] = stripe; - - jest - .spyOn(stripe.customers, 'create') - .mockImplementation(stripeCustomersCreateMock); - jest - .spyOn(stripe.paymentIntents, 'create') - .mockImplementation(stripePaymentIntentsCreateMock); - jest - .spyOn(stripe.paymentIntents, 'retrieve') - .mockImplementation(stripePaymentIntentsRetrieveMock); }); describe('createFiatPayment', () => { - let createPaymentIntentMock: any, findOneMock: any; + let createInvoiceMock: any, + createInvoiceItemMock: any, + finalizeInvoiceMock: any, + retrievePaymentIntentMock: any, + updatePaymentIntentMock: any, + findOneMock: any; beforeEach(() => { findOneMock = jest.spyOn(paymentRepository, 'findOneByTransaction'); - createPaymentIntentMock = jest.spyOn(stripe.paymentIntents, 'create'); + createInvoiceMock = jest.spyOn(stripe.invoices, 'create'); + createInvoiceItemMock = jest.spyOn(stripe.invoiceItems, 'create'); + finalizeInvoiceMock = jest.spyOn(stripe.invoices, 'finalizeInvoice'); + retrievePaymentIntentMock = jest.spyOn(stripe.paymentIntents, 'retrieve'); + updatePaymentIntentMock = jest.spyOn(stripe.paymentIntents, 'update'); }); afterEach(() => { - expect(createPaymentIntentMock).toHaveBeenCalledTimes(1); - createPaymentIntentMock.mockRestore(); + expect(createInvoiceMock).toHaveBeenCalledTimes(1); + expect(createInvoiceItemMock).toHaveBeenCalledTimes(1); + expect(finalizeInvoiceMock).toHaveBeenCalledTimes(1); + expect(retrievePaymentIntentMock).toHaveBeenCalledTimes(1); + expect(updatePaymentIntentMock).toHaveBeenCalledTimes(1); + createInvoiceMock.mockRestore(); + createInvoiceItemMock.mockRestore(); + finalizeInvoiceMock.mockRestore(); + retrievePaymentIntentMock.mockRestore(); + updatePaymentIntentMock.mockRestore(); }); it('should create a fiat payment successfully', async () => { const dto = { amount: 100, currency: Currency.USD, + paymentMethodId: 'pm_123', }; - const userId = 1; + const user = { + id: 1, + stripeCustomerId: 'cus_123', + }; const paymentIntent = { + id: 'pi_123', client_secret: 'clientSecret123', }; - createPaymentIntentMock.mockResolvedValue(paymentIntent); - findOneMock.mockResolvedValue(null); + const invoice = { + id: 'id', + payment_intent: paymentIntent.id, + }; + + createInvoiceMock.mockResolvedValue(invoice as any); + finalizeInvoiceMock.mockResolvedValue(invoice as any); + retrievePaymentIntentMock.mockResolvedValue(paymentIntent as any); + jest + .spyOn(stripe.paymentIntents, 'retrieve') + .mockResolvedValue(paymentIntent as any); + jest + .spyOn(paymentRepository, 'findOneByTransaction') + .mockResolvedValue(null); + jest + .spyOn(paymentRepository, 'createUnique') + .mockResolvedValue(undefined as any); - const result = await paymentService.createFiatPayment(userId, dto); + const result = await paymentService.createFiatPayment(user as any, dto); - expect(createPaymentIntentMock).toHaveBeenCalledWith({ - amount: dto.amount * 100, - currency: dto.currency, - }); expect(result).toEqual(paymentIntent.client_secret); + expect(stripe.invoices.create).toHaveBeenCalledWith({ + currency: Currency.USD, + customer: 'cus_123', + auto_advance: false, + payment_settings: { + payment_method_types: ['card'], + }, + }); + expect(stripe.invoiceItems.create).toHaveBeenCalledWith({ + customer: 'cus_123', + amount: 10000, + invoice: invoice.id, + description: 'Top up', + }); + expect(stripe.paymentIntents.update).toHaveBeenCalledWith('pi_123', { + payment_method: 'pm_123', + }); }); it('should throw a bad request exception if transaction already exist', async () => { @@ -167,21 +246,40 @@ describe('PaymentService', () => { const dto = { amount: 100, currency: Currency.USD, + paymentMethodId: 'pm_123', }; - const userId = 1; + const user = { + id: 1, + paymentInfo: { + customerId: 'test', + paymentMethodId: 'test', + }, + }; const paymentIntent = { + id: 'pi_123', client_secret: 'clientSecret123', }; - createPaymentIntentMock.mockResolvedValue(paymentIntent); + const invoice = { + id: 'id', + payment_intent: paymentIntent.id, + }; + + createInvoiceMock.mockResolvedValue(invoice as any); + finalizeInvoiceMock.mockResolvedValue(invoice as any); + retrievePaymentIntentMock.mockResolvedValue(paymentIntent as any); + jest + .spyOn(stripe.paymentIntents, 'retrieve') + .mockResolvedValue(paymentIntent as any); + findOneMock.mockResolvedValue({ transaction: paymentIntent.client_secret, } as PaymentEntity); await expect( - paymentService.createFiatPayment(userId, dto), + paymentService.createFiatPayment(user as any, dto), ).rejects.toThrow( new ControlledError( ErrorPayment.TransactionAlreadyExists, @@ -190,19 +288,37 @@ describe('PaymentService', () => { ); }); - it('should throw a bad request exception if the payment intent creation fails', async () => { + it('should throw a bad request exception if the invoice creation fails', async () => { 0; const dto = { amount: 100, currency: Currency.USD, + paymentMethodId: 'pm_123', }; - const userId = 1; + const user = { + id: 1, + paymentInfo: { + customerId: 'test', + paymentMethodId: 'test', + }, + }; - createPaymentIntentMock.mockResolvedValue(); + const paymentIntent = { + id: 'pi_123', + }; + + const invoice = { + id: 'id', + payment_intent: paymentIntent.id, + }; + + createInvoiceMock.mockResolvedValue(invoice as any); + finalizeInvoiceMock.mockResolvedValue(invoice as any); + retrievePaymentIntentMock.mockResolvedValue(paymentIntent as any); await expect( - paymentService.createFiatPayment(userId, dto), + paymentService.createFiatPayment(user as any, dto), ).rejects.toThrow( new ControlledError( ErrorPayment.ClientSecretDoesNotExist, @@ -785,4 +901,628 @@ describe('PaymentService', () => { ).rejects.toThrow(new DatabaseError('', '')); }); }); + + describe('createCustomerAndAssignCard', () => { + it('should create a customer and assign a card successfully', async () => { + const user = { + id: 1, + email: 'test@hmt.ai', + stripeCustomerId: null, + }; + + const paymentIntent = { + client_secret: 'clientSecret123', + }; + + jest + .spyOn(stripe.customers, 'create') + .mockResolvedValue({ id: 'cus_123' } as any); + jest + .spyOn(stripe.setupIntents, 'create') + .mockResolvedValue(paymentIntent as any); + + const result = await paymentService.createCustomerAndAssignCard( + user as any, + ); + + expect(result).toEqual(paymentIntent.client_secret); + expect(stripe.customers.create).toHaveBeenCalledWith({ + email: user.email, + }); + expect(stripe.setupIntents.create).toHaveBeenCalledWith({ + automatic_payment_methods: { enabled: true }, + customer: 'cus_123', + }); + }); + + it('should throw a bad request exception if the customer creation fails', async () => { + const user = { + id: 1, + email: 'test@hmt.ai', + stripeCustomerId: undefined, + }; + jest.spyOn(stripe.customers, 'create').mockRejectedValue(new Error()); + + await expect( + paymentService.createCustomerAndAssignCard(user as any), + ).rejects.toThrow( + new ControlledError( + ErrorPayment.CustomerNotCreated, + HttpStatus.NOT_FOUND, + ), + ); + }); + + it('should throw a bad request exception if the setup intent creation fails', async () => { + const user = { + id: 1, + email: 'test@hmt.ai', + }; + + jest + .spyOn(stripe.customers, 'create') + .mockResolvedValue({ id: 1 } as any); + + jest.spyOn(stripe.setupIntents, 'create').mockRejectedValue(new Error()); + + await expect( + paymentService.createCustomerAndAssignCard(user as any), + ).rejects.toThrow(ErrorPayment.CardNotAssigned); + }); + + it('should throw a bad request exception if the client secret does not exists', async () => { + const user = { + id: 1, + email: 'test@hmt.ai', + }; + + jest + .spyOn(stripe.customers, 'create') + .mockResolvedValue({ id: 1 } as any); + jest + .spyOn(stripe.setupIntents, 'create') + .mockResolvedValue(undefined as any); + + await expect( + paymentService.createCustomerAndAssignCard(user as any), + ).rejects.toThrow(ErrorPayment.ClientSecretDoesNotExist); + }); + }); + + describe('confirmCard', () => { + it('should confirm a card and update user stripeCustomerId successfully', async () => { + const user = { + id: 1, + email: 'test@hmt.ai', + stripeCustomerId: null, + }; + + const setupMock = { + customer: 'cus_123', + payment_method: 'pm_123', + }; + + jest + .spyOn(stripe.setupIntents, 'retrieve') + .mockResolvedValue(setupMock as any); + jest.spyOn(stripe.customers, 'update').mockResolvedValue(null as any); + jest + .spyOn(userRepository, 'updateOne') + .mockResolvedValue(undefined as any); + + const result = await paymentService.confirmCard(user as any, { + setupId: 'setup_123', + defaultCard: false, + }); + + expect(result).toBeTruthy(); + expect(userRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + stripeCustomerId: 'cus_123', + }), + ); + expect(stripe.setupIntents.retrieve).toHaveBeenCalledWith('setup_123'); + expect(stripe.customers.update).toHaveBeenCalledWith('cus_123', { + invoice_settings: { + default_payment_method: 'pm_123', + }, + }); + }); + + it('should fail if setupId is not in Stripe', async () => { + const user = { + id: 1, + email: 'test@hmt.ai', + }; + + jest + .spyOn(stripe.setupIntents, 'retrieve') + .mockResolvedValue(undefined as any); + + await expect( + paymentService.confirmCard(user as any, { + setupId: '1', + defaultCard: false, + }), + ).rejects.toThrow(ErrorPayment.SetupNotFound); + }); + }); + + // describe('createSlash', () => { + // it('should charge user credit card and create slash payments successfully', async () => { + // const user = { + // id: 1, + // email: 'test@hmt.ai', + // stripeCustomerId: 'cus_123', + // }; + + // const jobEntity = { + // id: 1, + // user: user, + // userId: user.id, + // }; + + // const paymentIntent = { + // id: 'pi_123', + // client_secret: 'clientSecret123', + // }; + + // jest.spyOn(userRepository, 'findById').mockResolvedValue(user as any); + // jest + // .spyOn(stripe.paymentIntents, 'create') + // .mockResolvedValue(paymentIntent as any); + + // const result = await paymentService.createSlash(jobEntity as any); + + // expect(result).toBe(undefined); + // expect(stripe.paymentIntents.create).toHaveBeenCalledWith({ + // amount: expect.any(Number), + // currency: Currency.USD, + // customer: 'cus_123', + // off_session: true, + // confirm: true, + // }); + // expect(paymentRepository.createUnique).toHaveBeenCalledTimes(2); + // }); + + // it('should fail if user does not have payment info', async () => { + // const user = { + // id: 1, + // email: 'test@hmt.ai', + // }; + + // const jobEntity = { + // id: 1, + // user: user, + // userId: user.id, + // }; + + // jest + // .spyOn(userRepository, 'findById') + // .mockResolvedValue(undefined as any); + + // await expect( + // paymentService.createSlash(jobEntity as any), + // ).rejects.toThrow(ErrorPayment.CustomerNotFound); + // }); + + // it('should fail if stripe create payment intent fails', async () => { + // const user = { + // id: 1, + // email: 'test@hmt.ai', + // }; + + // const jobEntity = { + // id: 1, + // user: user, + // userId: user.id, + // }; + + // jest.spyOn(userRepository, 'findById').mockResolvedValue(user as any); + // jest.spyOn(stripe.paymentIntents, 'create').mockResolvedValue({} as any); + + // await expect( + // paymentService.createSlash(jobEntity as any), + // ).rejects.toThrow(ErrorPayment.ClientSecretDoesNotExist); + // }); + // }); + + describe('listUserPaymentMethods', () => { + it('should list user payment methods successfully', async () => { + const user = { + id: 1, + stripeCustomerId: 'cus_123', + }; + + const paymentMethods = { + data: [ + { id: 'pm_123', card: { brand: 'visa', last4: '4242' } }, + { id: 'pm_456', card: { brand: 'mastercard', last4: '5555' } }, + ], + }; + + jest + .spyOn(stripe.customers, 'listPaymentMethods') + .mockResolvedValue(paymentMethods as any); + jest + .spyOn(paymentService as any, 'getDefaultPaymentMethod') + .mockResolvedValue('pm_123'); + + const result = await paymentService.listUserPaymentMethods(user as any); + + expect(result).toHaveLength(2); + expect(result[0]).toEqual({ + id: 'pm_123', + brand: 'visa', + last4: '4242', + default: true, + }); + expect(result[1]).toEqual({ + id: 'pm_456', + brand: 'mastercard', + last4: '5555', + default: false, + }); + }); + }); + + describe('deletePaymentMethod', () => { + it('should delete a payment method successfully', async () => { + const user = { + id: 1, + stripeCustomerId: 'cus_123', + }; + + jest + .spyOn(stripe.paymentMethods, 'retrieve') + .mockResolvedValue({ id: 'pm_123' } as any); + jest + .spyOn(paymentService as any, 'getDefaultPaymentMethod') + .mockResolvedValue('pm_456'); + jest + .spyOn(paymentService as any, 'isPaymentMethodInUse') + .mockResolvedValue(false); + jest.spyOn(stripe.paymentMethods, 'detach').mockResolvedValue({} as any); + + await paymentService.deletePaymentMethod(user as any, 'pm_123'); + + expect(stripe.paymentMethods.detach).toHaveBeenCalledWith('pm_123'); + }); + + it('should throw an error when trying to delete the default payment method in use', async () => { + const user = { + id: 1, + stripeCustomerId: 'cus_123', + }; + + jest + .spyOn(stripe.paymentMethods, 'retrieve') + .mockResolvedValue({ id: 'pm_123' } as any); + jest + .spyOn(paymentService as any, 'getDefaultPaymentMethod') + .mockResolvedValue('pm_123'); + jest + .spyOn(paymentService as any, 'isPaymentMethodInUse') + .mockResolvedValue(true); + + await expect( + paymentService.deletePaymentMethod(user as any, 'pm_123'), + ).rejects.toThrow( + new ControlledError( + ErrorPayment.PaymentMethodInUse, + HttpStatus.BAD_REQUEST, + ), + ); + }); + }); + + describe('getUserBillingInfo', () => { + it('should get user billing info successfully', async () => { + const user = { + id: 1, + stripeCustomerId: 'cus_123', + }; + + const taxIds = { + data: [{ type: VatType.EU_VAT, value: 'DE123456789' }], + }; + + const customer = { + name: 'John Doe', + email: 'john@example.com', + address: { + country: Country.DE, + postal_code: '12345', + city: 'Berlin', + line1: 'Street 1', + }, + }; + + jest + .spyOn(stripe.customers, 'listTaxIds') + .mockResolvedValue(taxIds as any); + jest + .spyOn(stripe.customers, 'retrieve') + .mockResolvedValue(customer as any); + + const result = await paymentService.getUserBillingInfo(user as any); + + expect(result).toEqual({ + name: 'John Doe', + email: 'john@example.com', + vat: 'DE123456789', + vatType: VatType.EU_VAT, + address: { + country: Country.DE, + postalCode: '12345', + city: 'Berlin', + line: 'Street 1', + }, + }); + }); + }); + + describe('updateUserBillingInfo', () => { + it('should update user billing info successfully', async () => { + const user = { + id: 1, + stripeCustomerId: 'cus_123', + }; + + const updateBillingInfoDto = { + name: 'John Doe', + email: 'john@example.com', + vat: 'DE123456789', + vatType: VatType.EU_VAT, + address: { + country: 'DE', + postalCode: '12345', + city: 'Berlin', + line: 'Street 1', + }, + }; + + jest + .spyOn(stripe.customers, 'listTaxIds') + .mockResolvedValue({ data: [] } as any); + jest.spyOn(stripe.customers, 'createTaxId').mockResolvedValue({} as any); + jest.spyOn(stripe.customers, 'update').mockResolvedValue({} as any); + + await paymentService.updateUserBillingInfo( + user as any, + updateBillingInfoDto, + ); + + expect(stripe.customers.createTaxId).toHaveBeenCalledWith('cus_123', { + type: VatType.EU_VAT, + value: 'DE123456789', + }); + expect(stripe.customers.update).toHaveBeenCalledWith('cus_123', { + name: 'John Doe', + email: 'john@example.com', + address: { + country: 'DE', + postal_code: '12345', + city: 'Berlin', + line1: 'Street 1', + }, + }); + }); + }); + + describe('changeDefaultPaymentMethod', () => { + it('should change the default payment method successfully', async () => { + const user = { + id: 1, + stripeCustomerId: 'cus_123', + }; + + jest.spyOn(stripe.customers, 'update').mockResolvedValue({} as any); + + await paymentService.changeDefaultPaymentMethod(user as any, 'pm_123'); + + expect(stripe.customers.update).toHaveBeenCalledWith('cus_123', { + invoice_settings: { default_payment_method: 'pm_123' }, + }); + }); + }); + + describe('getAllPayments', () => { + let fetchFilteredMock: jest.SpyInstance; + + beforeEach(() => { + fetchFilteredMock = jest.spyOn(paymentRepository, 'fetchFiltered'); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should retrieve and map all payments successfully', async () => { + const userId = 1; + const dto: GetPaymentsDto = { + page: 0, + pageSize: 10, + sortField: PaymentSortField.CREATED_AT, + sort: SortDirection.DESC, + skip: 10, + }; + + const mockEntities = [ + { + amount: 100, + rate: 1.5, + currency: 'usd', + type: PaymentType.DEPOSIT, + source: PaymentSource.FIAT, + status: PaymentStatus.SUCCEEDED, + transaction: 'tx_123', + createdAt: new Date('2023-10-01T00:00:00Z'), + job: { escrowAddress: '0x123' }, + }, + { + amount: -50, + rate: 1.5, + currency: 'usd', + type: PaymentType.WITHDRAWAL, + source: PaymentSource.CRYPTO, + status: PaymentStatus.SUCCEEDED, + transaction: 'tx_456', + createdAt: new Date('2023-10-02T00:00:00Z'), + job: null, + }, + ]; + + const mockResult = { + entities: mockEntities, + itemCount: 2, + }; + + fetchFilteredMock.mockResolvedValue(mockResult); + + const result = await paymentService.getAllPayments(dto, userId); + + const expectedPayments = [ + { + amount: 100, + rate: 1.5, + currency: 'usd', + type: PaymentType.DEPOSIT, + source: PaymentSource.FIAT, + status: PaymentStatus.SUCCEEDED, + transaction: 'tx_123', + createdAt: '2023-10-01T00:00:00.000Z', + escrowAddress: '0x123', + }, + { + amount: -50, + rate: 1.5, + currency: 'usd', + type: PaymentType.WITHDRAWAL, + source: PaymentSource.CRYPTO, + status: PaymentStatus.SUCCEEDED, + transaction: 'tx_456', + createdAt: '2023-10-02T00:00:00.000Z', + escrowAddress: undefined, + }, + ]; + + expect(result).toEqual({ + page: dto.page, + pageSize: dto.pageSize, + results: expectedPayments, + totalPages: 1, + totalResults: 2, + }); + + expect(fetchFilteredMock).toHaveBeenCalledWith(dto, userId); + }); + + it('should return an empty result if no payments are found', async () => { + const userId = 1; + const dto: GetPaymentsDto = { + page: 0, + pageSize: 10, + sortField: PaymentSortField.CREATED_AT, + sort: SortDirection.DESC, + skip: 10, + }; + + fetchFilteredMock.mockResolvedValue({ + entities: [], + itemCount: 0, + }); + + const result = await paymentService.getAllPayments(dto, userId); + + expect(result).toEqual({ + page: dto.page, + pageSize: dto.pageSize, + results: [], + totalPages: 0, + totalResults: 0, + }); + + expect(fetchFilteredMock).toHaveBeenCalledWith(dto, userId); + }); + + it('should throw an error if the repository fails', async () => { + const userId = 1; + const dto: GetPaymentsDto = { + page: 0, + pageSize: 10, + sortField: PaymentSortField.CREATED_AT, + sort: SortDirection.DESC, + skip: 10, + }; + + fetchFilteredMock.mockRejectedValue(new Error('Database error')); + + await expect(paymentService.getAllPayments(dto, userId)).rejects.toThrow( + new Error('Database error'), + ); + + expect(fetchFilteredMock).toHaveBeenCalledWith(dto, userId); + }); + }); + + describe('getReceipt', () => { + let retrievePaymentIntentMock: jest.SpyInstance; + let retrieveChargeMock: jest.SpyInstance; + + beforeEach(() => { + retrievePaymentIntentMock = jest.spyOn(stripe.paymentIntents, 'retrieve'); + retrieveChargeMock = jest.spyOn(stripe.charges, 'retrieve'); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should return the receipt URL if payment intent and charge exist', async () => { + const paymentId = 'pi_123'; + const user = { stripeCustomerId: 'cus_123' } as any; + + retrievePaymentIntentMock.mockResolvedValue({ + customer: 'cus_123', + latest_charge: 'ch_123', + } as any); + + retrieveChargeMock.mockResolvedValue({ + receipt_url: 'https://receipt.url', + } as any); + + const result = await paymentService.getReceipt(paymentId, user); + expect(result).toEqual('https://receipt.url'); + expect(retrievePaymentIntentMock).toHaveBeenCalledWith(paymentId); + expect(retrieveChargeMock).toHaveBeenCalledWith('ch_123'); + }); + + it('should throw a NOT_FOUND error if payment intent does not exist', async () => { + const paymentId = 'pi_123'; + const user = { stripeCustomerId: 'cus_123' } as any; + + retrievePaymentIntentMock.mockResolvedValue(null); + + await expect(paymentService.getReceipt(paymentId, user)).rejects.toThrow( + new ControlledError(ErrorPayment.NotFound, HttpStatus.NOT_FOUND), + ); + }); + + it('should throw a NOT_FOUND error if charge does not exist', async () => { + const paymentId = 'pi_123'; + const user = { stripeCustomerId: 'cus_123' } as any; + + retrievePaymentIntentMock.mockResolvedValue({ + customer: 'cus_123', + latest_charge: 'ch_123', + } as any); + + retrieveChargeMock.mockResolvedValue(null); + + await expect(paymentService.getReceipt(paymentId, user)).rejects.toThrow( + new ControlledError(ErrorPayment.NotFound, HttpStatus.NOT_FOUND), + ); + }); + }); }); diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts index d514202ee4..3d7c75ab4b 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts @@ -1,10 +1,17 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { HttpStatus, Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { ethers } from 'ethers'; import { ErrorPayment } from '../../common/constants/errors'; import { PaymentRepository } from './payment.repository'; import { + AddressDto, + BillingInfoDto, + CardConfirmDto, + CardDto, + GetPaymentsDto, PaymentCryptoCreateDto, + PaymentDto, PaymentFiatConfirmDto, PaymentFiatCreateDto, PaymentRefundCreateDto, @@ -16,6 +23,7 @@ import { PaymentType, StripePaymentStatus, TokenId, + VatType, } from '../../common/enums/payment'; import { TX_CONFIRMATION_TRESHOLD } from '../../common/constants'; import { NetworkConfigService } from '../../common/config/network-config.service'; @@ -31,6 +39,12 @@ import { verifySignature } from '../../common/utils/signature'; import { PaymentEntity } from './payment.entity'; import { ControlledError } from '../../common/errors/controlled'; import { RateService } from './rate.service'; +import { UserEntity } from '../user/user.entity'; +// import { JobEntity } from '../job/job.entity'; +import { ServerConfigService } from '../../common/config/server-config.service'; +import { UserRepository } from '../user/user.repository'; +import { JobRepository } from '../job/job.repository'; +import { PageDto } from '../../common/pagination/pagination.dto'; @Injectable() export class PaymentService { @@ -41,8 +55,11 @@ export class PaymentService { private readonly networkConfigService: NetworkConfigService, private readonly web3Service: Web3Service, private readonly paymentRepository: PaymentRepository, + private readonly userRepository: UserRepository, + private readonly jobRepository: JobRepository, private stripeConfigService: StripeConfigService, private rateService: RateService, + private serverConfigService: ServerConfigService, ) { this.stripe = new Stripe(this.stripeConfigService.secretKey, { apiVersion: this.stripeConfigService.apiVersion as any, @@ -54,19 +71,140 @@ export class PaymentService { }); } + public async createCustomerAndAssignCard(user: UserEntity): Promise { + // Creates a new Stripe customer if the user does not already have one. + // It then initiates a SetupIntent to link a payment method (card) to the customer. + let setupIntent: Stripe.Response; + let customerId: string = user.stripeCustomerId; + + if (!user.stripeCustomerId) { + try { + // Create a new customer in Stripe and assign the ID to the user. + customerId = ( + await this.stripe.customers.create({ + email: user.email, + }) + ).id; + } catch (error) { + this.logger.log(error.message, PaymentService.name); + throw new ControlledError( + ErrorPayment.CustomerNotCreated, + HttpStatus.BAD_REQUEST, + ); + } + } + try { + // Create a SetupIntent to manage and confirm card setup. + setupIntent = await this.stripe.setupIntents.create({ + automatic_payment_methods: { + enabled: true, + }, + customer: customerId, + }); + } catch (error) { + this.logger.log(error.message, PaymentService.name); + throw new ControlledError( + ErrorPayment.CardNotAssigned, + HttpStatus.BAD_REQUEST, + ); + } + + // Ensure the SetupIntent contains a client secret for completing the card setup process. + if (!setupIntent?.client_secret) { + this.logger.log( + ErrorPayment.ClientSecretDoesNotExist, + PaymentService.name, + ); + throw new ControlledError( + ErrorPayment.ClientSecretDoesNotExist, + HttpStatus.NOT_FOUND, + ); + } + + return setupIntent.client_secret; + } + + public async confirmCard( + user: UserEntity, + data: CardConfirmDto, + ): Promise { + // Confirms the card setup using the Stripe SetupIntent and sets it as the default payment method if requested. + const setup = await this.stripe.setupIntents.retrieve(data.setupId); + + if (!setup) { + this.logger.log(ErrorPayment.SetupNotFound, PaymentService.name); + throw new ControlledError( + ErrorPayment.SetupNotFound, + HttpStatus.NOT_FOUND, + ); + } + if (data.defaultCard || !user.stripeCustomerId) { + // Update Stripe customer settings to use this payment method by default. + await this.stripe.customers.update(setup.customer, { + invoice_settings: { + default_payment_method: setup.payment_method, + }, + }); + } + if (!user.stripeCustomerId) { + // Assign the Stripe customer ID to the user if it does not exist yet. + user.stripeCustomerId = setup.customer as string; + await this.userRepository.updateOne(user); + } + + return true; + } + public async createFiatPayment( - userId: number, + user: UserEntity, dto: PaymentFiatCreateDto, ): Promise { + // Creates an invoice for fiat currency and associates it with a payment intent. const { amount, currency } = dto; const amountInCents = Math.ceil(mul(amount, 100)); - const params: Stripe.PaymentIntentCreateParams = { - amount: amountInCents, + + let invoice = await this.stripe.invoices.create({ + customer: user.stripeCustomerId, currency: currency, - }; + auto_advance: false, + payment_settings: { + payment_method_types: ['card'], + }, + }); + + await this.stripe.invoiceItems.create({ + customer: user.stripeCustomerId, + amount: amountInCents, + invoice: invoice.id, + description: 'Top up', + }); + + // Finalize the invoice to prepare it for payment. + invoice = await this.stripe.invoices.finalizeInvoice(invoice.id); + + if (!invoice.payment_intent) { + throw new ControlledError( + ErrorPayment.IntentNotCreated, + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + + const paymentIntent = await this.stripe.paymentIntents.retrieve( + invoice.payment_intent as string, + ); - const paymentIntent = await this.stripe.paymentIntents.create(params); + try { + // Associate the payment method with the payment intent. + await this.stripe.paymentIntents.update(paymentIntent.id, { + payment_method: dto.paymentMethodId, + }); + } catch { + throw new ControlledError( + ErrorPayment.PaymentMethodAssociationFailed, + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } if (!paymentIntent?.client_secret) { throw new ControlledError( @@ -75,6 +213,7 @@ export class PaymentService { ); } + // Check if the transaction already exists to prevent duplicates. const paymentEntity = await this.paymentRepository.findOneByTransaction( paymentIntent.id, ); @@ -86,11 +225,12 @@ export class PaymentService { ); } + // Record the payment details in the system. const rate = await this.rateService.getRate(currency, Currency.USD); const newPaymentEntity = new PaymentEntity(); Object.assign(newPaymentEntity, { - userId, + userId: user.id, source: PaymentSource.FIAT, type: PaymentType.DEPOSIT, amount: div(amountInCents, 100), @@ -108,6 +248,7 @@ export class PaymentService { userId: number, data: PaymentFiatConfirmDto, ): Promise { + // Confirms a fiat payment based on the PaymentIntent ID and updates its status in the system. const paymentData = await this.stripe.paymentIntents.retrieve( data.paymentId, ); @@ -119,6 +260,8 @@ export class PaymentService { const paymentEntity = await this.paymentRepository.findOneByTransaction( data.paymentId, ); + + // Validate payment details against the recorded transaction data. if ( !paymentEntity || paymentEntity.userId !== userId || @@ -143,6 +286,7 @@ export class PaymentService { return false; // TODO: Handling other cases } + // Update the payment entity to reflect successful payment. paymentEntity.status = PaymentStatus.SUCCEEDED; await this.paymentRepository.updateOne(paymentEntity); @@ -290,4 +434,284 @@ export class PaymentService { }); await this.paymentRepository.createUnique(paymentEntity); } + + // public async createSlash(job: JobEntity): Promise { + // const amount = this.serverConfigService.abuseAmount, + // currency = Currency.USD; + + // const user = await this.userRepository.findById(job.userId); + // if (!user) { + // this.logger.log(ErrorPayment.CustomerNotFound, PaymentService.name); + // throw new ControlledError( + // ErrorPayment.CustomerNotFound, + // HttpStatus.BAD_REQUEST, + // ); + // } + + // const amountInCents = Math.ceil(mul(amount, 100)); + // const params: Stripe.PaymentIntentCreateParams = { + // amount: amountInCents, + // currency: currency, + // customer: user.stripeCustomerId, + // off_session: true, + // confirm: true, + // }; + + // const paymentIntent = await this.stripe.paymentIntents.create(params); + + // if (!paymentIntent?.client_secret) { + // this.logger.log( + // ErrorPayment.ClientSecretDoesNotExist, + // PaymentService.name, + // ); + // throw new ControlledError( + // ErrorPayment.ClientSecretDoesNotExist, + // HttpStatus.BAD_REQUEST, + // ); + // } + + // const newPaymentEntity = new PaymentEntity(); + // Object.assign(newPaymentEntity, { + // userId: job.user.id, + // source: PaymentSource.FIAT, + // type: PaymentType.DEPOSIT, + // amount: div(amountInCents, 100), + // currency, + // rate: 1, + // transaction: paymentIntent.id, + // status: PaymentStatus.SUCCEEDED, + // }); + // await this.paymentRepository.createUnique(newPaymentEntity); + + // Object.assign(newPaymentEntity, { + // userId: job.user.id, + // source: PaymentSource.FIAT, + // type: PaymentType.SLASH, + // amount: div(-amountInCents, 100), + // currency, + // rate: 1, + // transaction: null, + // status: PaymentStatus.SUCCEEDED, + // }); + // await this.paymentRepository.createUnique(newPaymentEntity); + + // return; + // } + + async listUserPaymentMethods(user: UserEntity) { + if (!user.stripeCustomerId) { + throw new ControlledError( + ErrorPayment.CustomerNotFound, + HttpStatus.BAD_REQUEST, + ); + } + + // List all the payment methods (cards) associated with the user's Stripe account + const paymentMethods = await this.stripe.customers.listPaymentMethods( + user.stripeCustomerId, + { + type: 'card', + limit: 100, + }, + ); + + const cards: CardDto[] = []; + // Get the default payment method for the user + const defaultPaymentMethod = await this.getDefaultPaymentMethod( + user.stripeCustomerId, + ); + + for (const paymentMethod of paymentMethods.data) { + const card = new CardDto(); + card.id = paymentMethod.id; + card.brand = paymentMethod.card?.brand as string; + card.last4 = paymentMethod.card?.last4 as string; + card.expMonth = paymentMethod.card?.exp_month as number; + card.expYear = paymentMethod.card?.exp_year as number; + card.default = defaultPaymentMethod === paymentMethod.id; + cards.push(card); + } + return cards; + } + + async deletePaymentMethod(user: UserEntity, paymentMethodId: string) { + // Retrieve the payment method to be detached + const paymentMethod = + await this.stripe.paymentMethods.retrieve(paymentMethodId); + + // Check if the payment method is the default one and in use for the user + if ( + paymentMethod.id === + (await this.getDefaultPaymentMethod(user.stripeCustomerId)) && + (await this.isPaymentMethodInUse(user.id)) + ) { + throw new ControlledError( + ErrorPayment.PaymentMethodInUse, + HttpStatus.BAD_REQUEST, + ); + } + + // Detach the payment method from the user's account + return this.stripe.paymentMethods.detach(paymentMethodId); + } + + async getUserBillingInfo(user: UserEntity) { + if (!user.stripeCustomerId) { + throw new ControlledError( + ErrorPayment.CustomerNotFound, + HttpStatus.BAD_REQUEST, + ); + } + + // Retrieve the customer's tax IDs and customer information + const taxIds = await this.stripe.customers.listTaxIds( + user.stripeCustomerId, + ); + + const customer = await this.stripe.customers.retrieve( + user.stripeCustomerId, + ); + + const userBillingInfo = new BillingInfoDto(); + if ((customer as Stripe.Customer).address) { + const address = new AddressDto(); + address.country = ( + (customer as Stripe.Customer).address?.country as string + ).toLowerCase(); + address.postalCode = (customer as Stripe.Customer).address + ?.postal_code as string; + address.city = (customer as Stripe.Customer).address?.city as string; + address.line = (customer as Stripe.Customer).address?.line1 as string; + userBillingInfo.address = address; + } + userBillingInfo.name = (customer as Stripe.Customer)?.name as string; + userBillingInfo.email = (customer as Stripe.Customer)?.email as string; + userBillingInfo.vat = taxIds.data[0]?.value; + userBillingInfo.vatType = taxIds.data[0]?.type as VatType; + return userBillingInfo; + } + + async updateUserBillingInfo( + user: UserEntity, + updateBillingInfoDto: BillingInfoDto, + ) { + // If the VAT or VAT type has changed, update it in Stripe + if (updateBillingInfoDto.vat && updateBillingInfoDto.vatType) { + const existingTaxIds = await this.stripe.customers.listTaxIds( + user.stripeCustomerId, + ); + + // Delete any existing tax IDs before adding the new one + for (const taxId of existingTaxIds.data) { + await this.stripe.customers.deleteTaxId( + user.stripeCustomerId, + taxId.id, + ); + } + + // Create the new VAT tax ID + await this.stripe.customers.createTaxId(user.stripeCustomerId, { + type: updateBillingInfoDto.vatType, + value: updateBillingInfoDto.vat, + }); + } + + // If there are changes to the address, name, or email, update them + if ( + updateBillingInfoDto.address || + updateBillingInfoDto.name || + updateBillingInfoDto.email + ) { + return this.stripe.customers.update(user.stripeCustomerId, { + address: { + line1: updateBillingInfoDto.address?.line, + city: updateBillingInfoDto.address?.city, + country: updateBillingInfoDto.address?.country, + postal_code: updateBillingInfoDto.address?.postalCode, + }, + name: updateBillingInfoDto.name, + email: updateBillingInfoDto.email, + }); + } + } + + async changeDefaultPaymentMethod(user: UserEntity, cardId: string) { + // Update the user's default payment method in Stripe + return this.stripe.customers.update(user.stripeCustomerId, { + invoice_settings: { default_payment_method: cardId }, + }); + } + + private async getDefaultPaymentMethod( + customerId: string, + ): Promise { + if (!customerId) { + throw new ControlledError( + ErrorPayment.CustomerNotFound, + HttpStatus.BAD_REQUEST, + ); + } + + // Retrieve the customer from Stripe and return the default payment method + const customer = await this.stripe.customers.retrieve(customerId); + return (customer as Stripe.Customer).invoice_settings + .default_payment_method as string; + } + + private async isPaymentMethodInUse(userId: number): Promise { + // Check if the payment method is currently in use by any active jobs + return ( + ( + await this.jobRepository.findActiveByUserAndPaymentSource( + userId, + PaymentSource.FIAT, + ) + ).length == 0 + ); + } + + public async getAllPayments( + data: GetPaymentsDto, + userId: number, + ): Promise> { + const { entities, itemCount } = await this.paymentRepository.fetchFiltered( + data, + userId, + ); + + const payments: PaymentDto[] = entities.map((payment) => { + return { + amount: payment.amount, + rate: payment.rate, + currency: payment.currency, + type: payment.type, + source: payment.source, + status: payment.status, + transaction: payment.transaction, + createdAt: payment.createdAt.toISOString(), + escrowAddress: payment.job ? payment.job.escrowAddress : undefined, + }; + }); + + return new PageDto(data.page!, data.pageSize!, itemCount, payments); + } + + async getReceipt(paymentId: string, user: UserEntity): Promise { + // Retrieve the payment intent using the provided payment ID + const paymentIntent = await this.stripe.paymentIntents.retrieve(paymentId); + + if (!paymentIntent || paymentIntent.customer !== user.stripeCustomerId) { + throw new ControlledError(ErrorPayment.NotFound, HttpStatus.NOT_FOUND); + } + + // Retrieve the charge for the payment intent and ensure it has a receipt URL + const charge = await this.stripe.charges.retrieve( + paymentIntent.latest_charge as string, + ); + if (!charge || !charge.receipt_url) { + throw new ControlledError(ErrorPayment.NotFound, HttpStatus.NOT_FOUND); + } + + return charge.receipt_url; + } } diff --git a/packages/apps/job-launcher/server/src/modules/user/user.entity.ts b/packages/apps/job-launcher/server/src/modules/user/user.entity.ts index 6ca2cbe00e..f67be393be 100644 --- a/packages/apps/job-launcher/server/src/modules/user/user.entity.ts +++ b/packages/apps/job-launcher/server/src/modules/user/user.entity.ts @@ -28,6 +28,9 @@ export class UserEntity extends BaseEntity implements IUser { }) public status: UserStatus; + @Column({ type: 'varchar', nullable: true, unique: true }) + public stripeCustomerId: string; + @OneToMany(() => JobEntity, (job) => job.user) public jobs: JobEntity[]; diff --git a/packages/apps/job-launcher/server/src/modules/webhook/webhook.controller.spec.ts b/packages/apps/job-launcher/server/src/modules/webhook/webhook.controller.spec.ts index 320de4deab..9585a0dbf5 100644 --- a/packages/apps/job-launcher/server/src/modules/webhook/webhook.controller.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/webhook/webhook.controller.spec.ts @@ -34,10 +34,12 @@ import { MOCK_STRIPE_API_VERSION, MOCK_STRIPE_APP_INFO_URL, MOCK_STRIPE_SECRET_KEY, + MOCK_MAX_RETRY_COUNT, } from '../../../test/constants'; import { ServerConfigService } from '../../common/config/server-config.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { ControlledError } from '../../common/errors/controlled'; +import { JobRepository } from '../job/job.repository'; jest.mock('@human-protocol/sdk'); @@ -108,6 +110,29 @@ describe('WebhookController', () => { provide: WebhookRepository, useValue: createMock(), }, + { + provide: JobRepository, + useValue: createMock(), + }, + { + provide: ConfigService, + useValue: { + get: jest.fn((key: string) => { + switch (key) { + case 'HOST': + return '127.0.0.1'; + case 'PORT': + return 5000; + case 'WEB3_PRIVATE_KEY': + return MOCK_PRIVATE_KEY; + case 'MAX_RETRY_COUNT': + return MOCK_MAX_RETRY_COUNT; + default: + return null; + } + }), + }, + }, { provide: HttpService, useValue: createMock(), diff --git a/packages/apps/job-launcher/server/src/modules/webhook/webhook.module.ts b/packages/apps/job-launcher/server/src/modules/webhook/webhook.module.ts index d3221f22d3..dab2beb310 100644 --- a/packages/apps/job-launcher/server/src/modules/webhook/webhook.module.ts +++ b/packages/apps/job-launcher/server/src/modules/webhook/webhook.module.ts @@ -9,17 +9,19 @@ import { Web3Module } from '../web3/web3.module'; import { HttpModule } from '@nestjs/axios'; import { JobModule } from '../job/job.module'; import { WebhookController } from './webhook.controller'; +import { JobEntity } from '../job/job.entity'; +import { JobRepository } from '../job/job.repository'; @Module({ imports: [ - TypeOrmModule.forFeature([WebhookEntity]), + TypeOrmModule.forFeature([WebhookEntity, JobEntity]), ConfigModule, JobModule, Web3Module, HttpModule, ], controllers: [WebhookController], - providers: [Logger, WebhookService, WebhookRepository], + providers: [Logger, WebhookService, WebhookRepository, JobRepository], exports: [WebhookService], }) export class WebhookModule {} diff --git a/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts b/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts index 35d7bc8ef6..bf5dfd1537 100644 --- a/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts +++ b/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts @@ -3,7 +3,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { BaseRepository } from '../../database/base.repository'; import { DataSource, LessThanOrEqual } from 'typeorm'; import { ServerConfigService } from '../../common/config/server-config.service'; -import { WebhookStatus } from '../../common/enums/webhook'; +import { EventType, WebhookStatus } from '../../common/enums/webhook'; import { WebhookEntity } from './webhook.entity'; @Injectable() @@ -15,11 +15,14 @@ export class WebhookRepository extends BaseRepository { ) { super(WebhookEntity, dataSource); } - - public findByStatus(status: WebhookStatus): Promise { + public findByStatusAndType( + status: WebhookStatus, + type: EventType, + ): Promise { return this.find({ where: { status: status, + eventType: type, retriesCount: LessThanOrEqual(this.serverConfigService.maxRetryCount), waitUntil: LessThanOrEqual(new Date()), }, diff --git a/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.spec.ts b/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.spec.ts index 92803d9ea0..0a93382dd4 100644 --- a/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.spec.ts @@ -28,6 +28,8 @@ import { HttpStatus } from '@nestjs/common'; import { ServerConfigService } from '../../common/config/server-config.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { ControlledError } from '../../common/errors/controlled'; +import { JobRepository } from '../job/job.repository'; +// import { JobRequestType } from '../../common/enums/job'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), @@ -41,6 +43,7 @@ describe('WebhookService', () => { webhookRepository: WebhookRepository, web3Service: Web3Service, jobService: JobService, + // jobRepository: JobRepository, httpService: HttpService; const signerMock = { @@ -80,6 +83,10 @@ describe('WebhookService', () => { provide: JobService, useValue: createMock(), }, + { + provide: JobRepository, + useValue: createMock(), + }, { provide: HttpService, useValue: createMock() }, ], }).compile(); @@ -89,6 +96,7 @@ describe('WebhookService', () => { web3Service = moduleRef.get(Web3Service); httpService = moduleRef.get(HttpService); jobService = moduleRef.get(JobService); + // jobRepository = moduleRef.get(JobRepository); }); afterEach(() => { @@ -334,6 +342,22 @@ describe('WebhookService', () => { expect(jobService.escrowFailedWebhook).toHaveBeenCalledWith(webhook); }); + // it('should handle an incoming abused escrow webhook', async () => { + // const webhook: WebhookDataDto = { + // chainId, + // escrowAddress, + // eventType: EventType.ABUSE_DETECTED, + // }; + + // jest.spyOn(webhookService, 'createIncomingWebhook'); + + // expect(await webhookService.handleWebhook(webhook)).toBe(undefined); + + // expect(webhookService.createIncomingWebhook).toHaveBeenCalledWith( + // webhook, + // ); + // }); + it('should return an error when the event type is invalid', async () => { const webhook: WebhookDataDto = { chainId, @@ -349,4 +373,47 @@ describe('WebhookService', () => { ); }); }); + + // describe('createIncomingWebhook', () => { + // it('should create a new incoming webhook', async () => { + // const dto = { + // chainId: ChainId.LOCALHOST, + // escrowAddress: '', + // }; + + // jest + // .spyOn(jobRepository, 'findOneByChainIdAndEscrowAddress') + // .mockResolvedValue({ requestType: JobRequestType.FORTUNE } as any); + // jest + // .spyOn(jobService, 'getOracleType') + // .mockReturnValue(OracleType.FORTUNE); + // const result = await webhookService.createIncomingWebhook(dto as any); + + // expect(result).toBe(undefined); + // expect(webhookRepository.createUnique).toHaveBeenCalledWith({ + // chainId: ChainId.LOCALHOST, + // escrowAddress: '', + // hasSignature: false, + // oracleType: OracleType.FORTUNE, + // retriesCount: 0, + // status: WebhookStatus.PENDING, + // waitUntil: expect.any(Date), + // }); + // }); + + // it('should create a new incoming webhook', async () => { + // const dto = { + // chainId: ChainId.LOCALHOST, + // escrowAddress: '', + // }; + + // jest + // .spyOn(jobRepository, 'findOneByChainIdAndEscrowAddress') + // .mockResolvedValue(undefined as any); + + // await expect( + // webhookService.createIncomingWebhook(dto as any), + // ).rejects.toThrow(ErrorWebhook.InvalidEscrow); + // }); + // }); }); diff --git a/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts b/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts index f0e37be14a..0f4f36ec73 100644 --- a/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts +++ b/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts @@ -22,6 +22,7 @@ import { CaseConverter } from '../../common/utils/case-converter'; import { EventType } from '../../common/enums/webhook'; import { JobService } from '../job/job.service'; import { ControlledError } from '../../common/errors/controlled'; +import { JobRepository } from '../job/job.repository'; @Injectable() export class WebhookService { constructor( @@ -29,6 +30,7 @@ export class WebhookService { private readonly web3Service: Web3Service, private readonly webhookRepository: WebhookRepository, private readonly jobService: JobService, + private readonly jobRepository: JobRepository, private readonly commonConfigSerice: ServerConfigService, private readonly web3ConfigService: Web3ConfigService, private readonly httpService: HttpService, @@ -141,6 +143,10 @@ export class WebhookService { await this.jobService.escrowFailedWebhook(webhook); break; + // case EventType.ABUSE_DETECTED: + // await this.createIncomingWebhook(webhook); + // break; + default: throw new ControlledError( `Invalid webhook event type: ${webhook.eventType}`, @@ -148,4 +154,27 @@ export class WebhookService { ); } } + + // public async createIncomingWebhook(webhook: WebhookDataDto): Promise { + // const jobEntity = await this.jobRepository.findOneByChainIdAndEscrowAddress( + // webhook.chainId, + // webhook.escrowAddress, + // ); + + // if (!jobEntity) { + // throw new ControlledError( + // ErrorWebhook.InvalidEscrow, + // HttpStatus.BAD_REQUEST, + // ); + // } + + // const webhookEntity = new WebhookEntity(); + // Object.assign(webhookEntity, webhook); + // webhookEntity.oracleType = this.jobService.getOracleType( + // jobEntity.requestType, + // ); + // webhookEntity.hasSignature = false; + + // this.webhookRepository.createUnique(webhookEntity); + // } } From 1b5faa99e9359fc820897a447cb34f2ffd6fbfe2 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Thu, 28 Nov 2024 17:56:28 +0300 Subject: [PATCH 25/92] [CVAT] Refactor and fix honeypot rerolls (#2860) * Refactor and fix honeypot rerolls * Fix and satisfy linter * Add test * Fix and refactor tests --- .../handlers/process_intermediate_results.py | 122 ++++---- .../services/test_validation_service.py | 289 ++++++++++++++++-- .../recording-oracle/tests/utils/helpers.py | 24 ++ 3 files changed, 356 insertions(+), 79 deletions(-) create mode 100644 packages/examples/cvat/recording-oracle/tests/utils/helpers.py diff --git a/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py b/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py index e40fce9906..725c54501d 100644 --- a/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py +++ b/packages/examples/cvat/recording-oracle/src/handlers/process_intermediate_results.py @@ -54,14 +54,12 @@ _RejectedJobs = dict[int, DatasetValidationError] - -_TaskIdToValidationLayout = dict[int, dict] -_TaskIdToHoneypotsMapping = dict[int, dict] -_TaskIdToSequenceOfFrameNames = dict[int, list[str]] - _HoneypotFrameId = int _ValidationFrameId = int _HoneypotFrameToValFrame = dict[_HoneypotFrameId, _ValidationFrameId] +_TaskIdToValidationLayout = dict[int, cvat_api.models.ITaskValidationLayoutRead] +_TaskIdToHoneypotsMapping = dict[int, _HoneypotFrameToValFrame] +_TaskIdToFrameNames = dict[int, list[str]] @dataclass @@ -72,7 +70,7 @@ class _ValidationResult: gt_stats: GtStats task_id_to_val_layout: _TaskIdToValidationLayout task_id_to_honeypots_mapping: _TaskIdToHoneypotsMapping - task_id_to_sequence_of_frame_names: _TaskIdToSequenceOfFrameNames + task_id_to_frame_names: _TaskIdToFrameNames T = TypeVar("T") @@ -349,9 +347,7 @@ def validate(self) -> _ValidationResult: gt_stats=self._require_field(self._gt_stats), task_id_to_val_layout=self._require_field(self._task_id_to_val_layout), task_id_to_honeypots_mapping=self._require_field(self._task_id_to_honeypots_mapping), - task_id_to_sequence_of_frame_names=self._require_field( - self._task_id_to_sequence_of_frame_names - ), + task_id_to_frame_names=self._require_field(self._task_id_to_sequence_of_frame_names), ) @@ -436,16 +432,16 @@ def process_intermediate_results( # noqa: PLR0912 for rejected_job_id in rejected_job_ids: job_frame_range = job_id_to_frame_range[rejected_job_id] cvat_task_id = job_id_to_task_id[rejected_job_id] - honeypots_mapping = validation_result.task_id_to_honeypots_mapping[cvat_task_id] - job_honeypots = set(honeypots_mapping.keys()) & set(job_frame_range) + task_honeypots_mapping = validation_result.task_id_to_honeypots_mapping[ + cvat_task_id + ] + job_honeypots = sorted(set(task_honeypots_mapping.keys()) & set(job_frame_range)) validation_frames = [ val_frame - for honeypot, val_frame in honeypots_mapping.items() + for honeypot, val_frame in task_honeypots_mapping.items() if honeypot in job_honeypots ] - sorted_task_frame_names = validation_result.task_id_to_sequence_of_frame_names[ - cvat_task_id - ] + sorted_task_frame_names = validation_result.task_id_to_frame_names[cvat_task_id] for val_frame in validation_frames: val_frame_name = sorted_task_frame_names[val_frame] @@ -458,84 +454,98 @@ def process_intermediate_results( # noqa: PLR0912 val_frame ) - for cvat_task_id, val_frame_ids in cvat_task_id_to_failed_val_frames.items(): + for cvat_task_id, task_bad_validation_frames in cvat_task_id_to_failed_val_frames.items(): task_validation_layout = validation_result.task_id_to_val_layout[cvat_task_id] - intersection = val_frame_ids & set(task_validation_layout.disabled_frames) - if intersection: + task_disabled_bad_frames = ( + set(task_validation_layout.disabled_frames) & task_bad_validation_frames + ) + if task_disabled_bad_frames: logger.error( "Logical error occurred while disabling validation frames " - f"for the task({task_id}). Frames {intersection} " + f"for the task({task_id}). Frames {task_disabled_bad_frames} " "are already disabled." ) - updated_disable_frames = task_validation_layout.disabled_frames + list(val_frame_ids) - non_disabled_frames = list( - set(task_validation_layout.validation_frames) - set(updated_disable_frames) + task_updated_disabled_frames = list( + set(task_validation_layout.disabled_frames) | set(task_bad_validation_frames) + ) + task_good_validation_frames = list( + set(task_validation_layout.validation_frames) - set(task_updated_disabled_frames) ) - if len(non_disabled_frames) < task_validation_layout.frames_per_job_count: + if len(task_good_validation_frames) < task_validation_layout.frames_per_job_count: should_complete = True logger.info( f"Validation for escrow_address={escrow_address}: " "Too few validation frames left " f"(required: {task_validation_layout.frames_per_job_count}, " - f"left: {len(non_disabled_frames)}) for the task({cvat_task_id}), " + f"left: {len(task_good_validation_frames)}) for the task({cvat_task_id}), " "stopping annotation" ) break - updated_task_honeypot_real_frames = task_validation_layout.honeypot_real_frames.copy() + task_honeypot_to_index: dict[int, int] = { + honeypot: i for i, honeypot in enumerate(task_validation_layout.honeypot_frames) + } # honeypot -> list index - # validation frames may be repeated - task_honeypot_real_frames_index: dict[int, list[int]] = {} - for idx, f in enumerate(updated_task_honeypot_real_frames): - task_honeypot_real_frames_index.setdefault(f, []).append(idx) + task_honeypots_mapping = validation_result.task_id_to_honeypots_mapping[cvat_task_id] - rejected_jobs_for_task = [ + task_rejected_jobs = [ j for j in unchecked_jobs_meta.jobs if j.job_id in rejected_job_ids and j.task_id == cvat_task_id ] - for job in rejected_jobs_for_task: + task_updated_honeypot_real_frames = task_validation_layout.honeypot_real_frames.copy() + for job in task_rejected_jobs: job_frame_range = job.job_frame_range - honeypots_mapping = validation_result.task_id_to_honeypots_mapping[cvat_task_id] - job_honeypots = set(honeypots_mapping.keys()) & set(job_frame_range) - - validation_frames_to_replace = [ - honeypots_mapping[honeypot] - for honeypot in job_honeypots - if honeypots_mapping[honeypot] in val_frame_ids - ] - valid_used_validation_frames = [ - honeypots_mapping[honeypot] - for honeypot in job_honeypots - if honeypots_mapping[honeypot] not in validation_frames_to_replace - ] + job_honeypots = sorted(set(task_honeypots_mapping.keys()) & set(job_frame_range)) + + job_honeypots_to_replace = [] + job_validation_frames_to_replace = [] + job_validation_frames_to_keep = [] + for honeypot in job_honeypots: + validation_frame = task_honeypots_mapping[honeypot] + if validation_frame in task_bad_validation_frames: + job_honeypots_to_replace.append(honeypot) + job_validation_frames_to_replace.append(validation_frame) + else: + job_validation_frames_to_keep.append(validation_frame) # choose new unique validation frames for the job - assert not (set(validation_frames_to_replace) & set(non_disabled_frames)) - available_validation_frames = list( - set(non_disabled_frames) - set(valid_used_validation_frames) + assert not ( + set(job_validation_frames_to_replace) & set(task_good_validation_frames) ) + job_available_validation_frames = list( + set(task_good_validation_frames) - set(job_validation_frames_to_keep) + ) + rng = np.random.Generator(np.random.MT19937()) - new_validation_frames = rng.choice( - available_validation_frames, + new_job_validation_frames = rng.choice( + job_available_validation_frames, replace=False, - size=len(validation_frames_to_replace), + size=len(job_validation_frames_to_replace), ).tolist() - for prev_val_frame, new_val_frame in zip( - validation_frames_to_replace, new_validation_frames, strict=True + for honeypot, new_validation_frame in zip( + job_honeypots_to_replace, new_job_validation_frames, strict=True ): - idx = task_honeypot_real_frames_index[prev_val_frame].pop(0) - updated_task_honeypot_real_frames[idx] = new_val_frame + honeypot_index = task_honeypot_to_index[honeypot] + task_updated_honeypot_real_frames[honeypot_index] = new_validation_frame + + # Make sure honeypots do not repeat in jobs + assert len( + { + task_updated_honeypot_real_frames[task_honeypot_to_index[honeypot]] + for honeypot in job_honeypots + } + ) == len(job_honeypots) cvat_api.update_task_validation_layout( cvat_task_id, - disabled_frames=updated_disable_frames, - honeypot_real_frames=updated_task_honeypot_real_frames, + disabled_frames=task_updated_disabled_frames, + honeypot_real_frames=task_updated_honeypot_real_frames, ) if logger.isEnabledFor(logging.DEBUG): diff --git a/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py b/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py index 29bf0884cf..ca238bb777 100644 --- a/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py +++ b/packages/examples/cvat/recording-oracle/tests/integration/services/test_validation_service.py @@ -1,4 +1,5 @@ import io +import math import random import unittest import uuid @@ -7,10 +8,12 @@ from types import SimpleNamespace from unittest import mock +import numpy as np +import pytest +from datumaro.util import take_by from sqlalchemy.orm import Session from src.core.annotation_meta import AnnotationMeta, JobMeta -from src.core.manifest import TaskManifest, parse_manifest from src.core.types import Networks from src.core.validation_results import ValidationFailure, ValidationSuccess from src.cvat import api_calls as cvat_api @@ -29,6 +32,7 @@ ) from tests.utils.constants import ESCROW_ADDRESS, WALLET_ADDRESS1 +from tests.utils.helpers import generate_manifest class ServiceIntegrationTest(unittest.TestCase): @@ -91,27 +95,6 @@ def test_create_and_get_validation_result(self): class TestManifestChange: - @staticmethod - def _generate_manifest(*, min_quality: float = 0.8) -> TaskManifest: - data = { - "data": {"data_url": "http://localhost:9010/datasets/sample"}, - "annotation": { - "labels": [{"name": "person"}], - "description": "", - "user_guide": "", - "type": "image_points", - "job_size": 10, - }, - "validation": { - "min_quality": min_quality, - "val_size": 2, - "gt_url": "http://localhost:9010/datasets/sample/annotations/sample_gt.json", - }, - "job_bounty": "0.0001", - } - - return parse_manifest(data) - def test_can_handle_lowered_quality_requirements_in_manifest(self, session: Session): escrow_address = ESCROW_ADDRESS chain_id = Networks.localhost @@ -120,7 +103,7 @@ def test_can_handle_lowered_quality_requirements_in_manifest(self, session: Sess min_quality2 = 0.5 frame_count = 10 - manifest = self._generate_manifest(min_quality=min_quality1) + manifest = generate_manifest(min_quality=min_quality1) cvat_task_id = 1 cvat_job_id = 1 @@ -294,3 +277,263 @@ def patched_prepare_merged_dataset(self): ].annotation_quality == assignment2_quality ) + + +class TestValidationLogic: + @pytest.mark.parametrize("seed", range(50)) + def test_can_change_bad_honeypots_in_jobs(self, session: Session, seed: int): + escrow_address = ESCROW_ADDRESS + chain_id = Networks.localhost + + # max excluded = job count * val per job / max val repeats => + # val count must be >= max_excluded + val per job + max_validation_frame_uses = 2 + frame_count = 32 + validation_frames_per_job = 4 + validation_frames_count = 12 + job_size = 5 + assert ( + validation_frames_count + >= math.ceil((frame_count - validation_frames_count) / job_size) + * validation_frames_per_job + // max_validation_frame_uses + + validation_frames_per_job + ) + + manifest = generate_manifest( + min_quality=0.8, job_size=job_size, validation_frames_per_job=validation_frames_per_job + ) + + ( + _, + task_frame_names, + task_validation_frames, + task_honeypots, + task_honeypot_real_frames, + jobs, + ) = self._generate_task_frames( + frame_count, + validation_frames_count, + job_size, + validation_frames_per_job, + seed=seed, + max_validation_frame_uses=max_validation_frame_uses, + ) + job_frame_ranges = self._get_job_frame_ranges(jobs) + + cvat_task_id = 1 + + annotator1 = WALLET_ADDRESS1 + assignment1_id = f"0x{0:040d}" + + # create a validation input + with ExitStack() as common_lock_es: + logger = mock.Mock(Logger) + + common_lock_es.enter_context( + mock.patch( + "src.core.config.Config.validation.gt_ban_threshold", max_validation_frame_uses + ) + ) + + mock_make_cloud_client = common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.make_cloud_client") + ) + mock_make_cloud_client.return_value.download_file = mock.Mock(return_value=b"") + + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.BucketAccessInfo.parse_obj") + ) + + mock_get_task_validation_layout = common_lock_es.enter_context( + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_task_validation_layout" + ) + ) + mock_get_task_validation_layout.return_value = mock.Mock( + cvat_api.models.ITaskValidationLayoutRead, + frames_per_job_count=validation_frames_per_job, + validation_frames=task_validation_frames, + disabled_frames=[], + honeypot_count=len(task_honeypots), + honeypot_frames=task_honeypots, + honeypot_real_frames=task_honeypot_real_frames, + ) + + mock_get_task_data_meta = common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.cvat_api.get_task_data_meta") + ) + mock_get_task_data_meta.return_value = mock.Mock( + cvat_api.models.IDataMetaRead, + frames=[SimpleNamespace(name=name) for name in task_frame_names], + ) + + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.dm.Dataset.import_from") + ) + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.extract_zip_archive") + ) + common_lock_es.enter_context( + mock.patch("src.handlers.process_intermediate_results.write_dir_to_zip_archive") + ) + + def patched_prepare_merged_dataset(self): + self._updated_merged_dataset_archive = io.BytesIO() + + common_lock_es.enter_context( + mock.patch( + "src.handlers.process_intermediate_results._TaskValidator._prepare_merged_dataset", + patched_prepare_merged_dataset, + ) + ) + + annotation_meta = AnnotationMeta( + jobs=[ + JobMeta( + job_id=1 + i, + task_id=cvat_task_id, + annotation_filename="", + annotator_wallet_address=annotator1, + assignment_id=assignment1_id, + start_frame=job_start, + stop_frame=job_stop, + ) + for i, (job_start, job_stop) in enumerate(job_frame_ranges) + ] + ) + + rng = np.random.Generator(np.random.MT19937(seed)) + rng.shuffle(annotation_meta.jobs) + + with ( + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_task_quality_report" + ) as mock_get_task_quality_report, + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_quality_report_data" + ) as mock_get_quality_report_data, + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.get_jobs_quality_reports" + ) as mock_get_jobs_quality_reports, + mock.patch( + "src.handlers.process_intermediate_results.cvat_api.update_task_validation_layout" + ) as mock_update_task_validation_layout, + ): + mock_get_task_quality_report.return_value = mock.Mock( + cvat_api.models.IQualityReport, id=1 + ) + + mock_get_quality_report_data.return_value = mock.Mock( + cvat_api.QualityReportData, + frame_results={ + str(honeypot_frame): mock.Mock(annotations=mock.Mock(accuracy=0)) + for honeypot_frame in task_honeypots + }, + ) + + mock_get_jobs_quality_reports.return_value = [ + mock.Mock( + cvat_api.models.IQualityReport, + job_id=1 + i, + summary=mock.Mock(accuracy=0), + ) + for i in range(len(jobs)) + ] + + vr = process_intermediate_results( + session, + escrow_address=escrow_address, + chain_id=chain_id, + meta=annotation_meta, + merged_annotations=io.BytesIO(), + manifest=manifest, + logger=logger, + ) + + assert isinstance(vr, ValidationFailure) + + assert mock_update_task_validation_layout.call_count == 1 + + updated_disabled_frames = mock_update_task_validation_layout.call_args.kwargs[ + "disabled_frames" + ] + assert all(v in task_validation_frames for v in updated_disabled_frames) + + updated_honeypot_real_frames = mock_update_task_validation_layout.call_args.kwargs[ + "honeypot_real_frames" + ] + + for job_start, job_stop in job_frame_ranges: + job_honeypot_positions = [ + i + for i, v in enumerate(task_honeypots) + if v in range(job_start, job_stop + 1) + ] + job_updated_honeypots = [ + updated_honeypot_real_frames[i] for i in job_honeypot_positions + ] + assert sorted(job_updated_honeypots) == sorted(set(job_updated_honeypots)) + + def _get_job_frame_ranges(self, jobs) -> list[tuple[int, int]]: + job_frame_ranges = [] + job_start = 0 + for job_frames in jobs: + job_stop = job_start + len(job_frames) - 1 + job_frame_ranges.append((job_start, job_stop)) + job_start = job_stop + 1 + + return job_frame_ranges + + def _generate_task_frames( + self, + frame_count, + validation_frames_count, + job_size, + validation_frames_per_job, + seed, + max_validation_frame_uses=None, + ): + rng = np.random.Generator(np.random.MT19937(seed)) + task_frames = list(range(frame_count)) + task_validation_frames = task_frames[-validation_frames_count:] + task_real_frames = [] + task_honeypots = [] + task_honeypot_real_frames = [] + validation_frame_uses = {vf: 0 for vf in task_validation_frames} + jobs = [] + for job_real_frames in take_by( + task_frames[: frame_count - validation_frames_count], job_size + ): + available_validation_frames = [ + vf + for vf in task_validation_frames + if not max_validation_frame_uses + or validation_frame_uses[vf] < max_validation_frame_uses + ] + job_validation_frames = rng.choice( + available_validation_frames, validation_frames_per_job, replace=False + ).tolist() + + job_real_frames = job_real_frames + job_validation_frames + rng.shuffle(job_real_frames) + + jobs.append(job_real_frames) + + job_start_frame = len(task_real_frames) + task_real_frames.extend(job_real_frames) + + for i, v in enumerate(job_real_frames): + if v in job_validation_frames: + task_honeypots.append(i + job_start_frame) + task_honeypot_real_frames.append(v) + + task_frame_names = list(map(str, task_real_frames)) + return ( + task_real_frames, + task_frame_names, + task_validation_frames, + task_honeypots, + task_honeypot_real_frames, + jobs, + ) diff --git a/packages/examples/cvat/recording-oracle/tests/utils/helpers.py b/packages/examples/cvat/recording-oracle/tests/utils/helpers.py new file mode 100644 index 0000000000..5e1da94bac --- /dev/null +++ b/packages/examples/cvat/recording-oracle/tests/utils/helpers.py @@ -0,0 +1,24 @@ +from src.core.manifest import TaskManifest, parse_manifest + + +def generate_manifest( + *, min_quality: float = 0.8, job_size: int = 10, validation_frames_per_job: int = 2 +) -> TaskManifest: + data = { + "data": {"data_url": "http://localhost:9010/datasets/sample"}, + "annotation": { + "labels": [{"name": "person"}], + "description": "", + "user_guide": "", + "type": "image_points", + "job_size": job_size, + }, + "validation": { + "min_quality": min_quality, + "val_size": validation_frames_per_job, + "gt_url": "http://localhost:9010/datasets/sample/annotations/sample_gt.json", + }, + "job_bounty": "0.0001", + } + + return parse_manifest(data) From 245f1adf1823a1d12e8d6b2da63c1079295d5f45 Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:57:57 +0100 Subject: [PATCH 26/92] [render preview] Subgraph and contract upgrades (#2576) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Subgraph] Removed reputation from leader entity (#2450) * Removed reputation from leader entity * Merge branch 'subgraph-upgrades' into feature/sdk/remove-reputation-from-leader-entity --------- Co-authored-by: eugenvoronov * [Subgraph][SDK] Add registration data to leaders entity (#2451) * Add registration data to leaders entity * Add registration info to getReputationNetworkOperators --------- Co-authored-by: Francisco López * [SDK] Added reputation networks (#2429) * Added reputation networks * Removed reputation network * Handled null value * Updated unit test --------- Co-authored-by: portuu3 * [Human App] Add registration info to oracles discovery response (#2452) * Add registration data to leaders entity * Add registration info to getReputationNetworkOperators * Add wether registration is required to oracles discovery response * Implemented reputation networks using SDK (#2458) * [Subgraph] Remove eth_calls (#2397) * Add events for data being read with eth_calls in subgraph * Create new events to allow compatibility with old events * Remove setupEventCount and rename SetupEvent to PendingEvent in Subgraph * feat: add events and cancel method for erc20 token support (#2408) * feat: add events and cancel method for erc20 token support * fix: contract changes * feat: sdk update * feat: update sdk doc * update subgraph * update doc * update doc * revert doc summary delete * remove create_and_setup_escrow function * remove abort function * fix cvat test * fix cvat test * fix cvat e2e * apply optimization * remove Payout event * fix docs sdk files path * regenerate doc * [HUMAN App client] Add registration step (#2518) * Add logic to register users in oracles * Fix failing tests --------- Co-authored-by: portuu3 * [Subgraph][SDK] Refactor transactions (#2572) * Refactor transactions in subgraph * Update SDK * Add compatibility with new transactions in dashboard server * Add test for withdraw event * Fix job launcher tests * Solve errors on building human app frontend * contract and subgraph deployment for sepolia * replace subgraph deployment id * subgraph transactions refactor * refactor transactions indexing * Update subgraph tests to new transactions * Revert "[HUMAN App client] Add registration step (#2517)" This reverts commit 26ebc9b28a36c3df058440e057142c8a1ab96a6a. * Revert "[Human App] Add registration info to oracles discovery response (#2452)" This reverts commit 712232a6bb1f793538e8817ce7dbf08d6e77e37f. * Revert "[Subgraph][SDK] Add registration data to leaders entity (#2451)" This reverts commit cc79357b2d980255de2ab6ae8f6af6edc327809b. * fix tests and lint errors * add missing property to subgraph schema * [Dashboard] Hyperlink role to oracle website (#2676) * Hyperlink role to oracle website * Created website field in Leader data in Subgraph and used it for hiperlink in dashboard * [CORE][SDK] Remove allocation from Staking contract (#2651) * Remove allocation from Staking contract and update SDK * Updated subgraph tests * Added withdrawFees to staking events * enable staking events as main trx * Update SDKs with the new transaction format * Update Makefile * Update docker-compose.yml * Remove event tests for the events that have been removed * Contracts upgrade * Contracts upgrade * Refactor Job Launcher to remove allocation * Improve Staking and Escrow contracts * Fix failing tests in python SDK --------- Co-authored-by: portuu3 * Update payout.service.ts * fix migration after enums conversion to lower case * deploy contracts and subgraph on sepolia * Update staking contract to UUPS upgradeable * add change staking address and minimum stake to escrow factory * Remove upgradeable from Staking contract and update openzeppelin version to others contracts * Fix failing tests * Improve methods usage in EscrowFactory contract * update deployment scripts and deploy new staking contract * undo breaking change @openzeppelin/contracts-upgradeable upgrade and redeploy sepolia contracts * update contracts deployment cd and deploy new sepolia subgraph * Undo openzeppelin contract-upgradeable package update * trigger preview * add description * add usdc support to sepolia * remove private key and update doc * deploy new contracts to bsc testnet * deploy amoy * fix faucet test * fix lint issues --------- Co-authored-by: eugenvoronov Co-authored-by: Francisco López Co-authored-by: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Co-authored-by: Francisco López <50665615+flopez7@users.noreply.github.com> Co-authored-by: Eric Lee Co-authored-by: Eric Lee <98655210+leric7@users.noreply.github.com> --- .github/workflows/cd-deploy-contracts.yaml | 42 +- ...human_protocol_sdk.escrow.escrow_client.md | 162 +- docs/sdk/python/human_protocol_sdk.escrow.md | 5 +- docs/sdk/python/human_protocol_sdk.kvstore.md | 10 + docs/sdk/python/human_protocol_sdk.md | 9 +- ...an_protocol_sdk.operator.operator_utils.md | 10 +- docs/sdk/python/human_protocol_sdk.staking.md | 6 - ...man_protocol_sdk.staking.staking_client.md | 162 +- .../python/human_protocol_sdk.transaction.md | 2 + ...tocol_sdk.transaction.transaction_utils.md | 10 +- docs/sdk/python/human_protocol_sdk.utils.md | 7 - docs/sdk/python/index.md | 1 - .../base/classes/BaseEthersClient.md | 10 +- .../encryption/classes/Encryption.md | 10 +- .../encryption/classes/EncryptionUtils.md | 16 +- docs/sdk/typescript/enums/README.md | 14 + .../typescript/enums/enumerations/ChainId.md | 197 ++ .../enums/enumerations/OrderDirection.md | 27 + .../typescript/escrow/classes/EscrowClient.md | 238 +- .../typescript/escrow/classes/EscrowUtils.md | 28 +- docs/sdk/typescript/graphql/types/README.md | 34 + .../types/type-aliases/DailyEscrowData.md | 39 + .../types/type-aliases/DailyHMTData.md | 35 + .../types/type-aliases/DailyPaymentData.md | 31 + .../types/type-aliases/DailyTaskData.md | 27 + .../types/type-aliases/DailyWorkerData.md | 23 + .../graphql/types/type-aliases/EscrowData.md | 91 + .../types/type-aliases/EscrowStatistics.md | 23 + .../type-aliases/EscrowStatisticsData.md | 55 + .../types/type-aliases/EventDayData.md | 87 + .../graphql/types/type-aliases/HMTHolder.md | 23 + .../types/type-aliases/HMTHolderData.md | 23 + .../types/type-aliases/HMTStatistics.md | 27 + .../types/type-aliases/HMTStatisticsData.md | 39 + .../graphql/types/type-aliases/IMData.md | 13 + .../types/type-aliases/IMDataEntity.md | 23 + .../graphql/types/type-aliases/KVStoreData.md | 39 + .../types/type-aliases/PaymentStatistics.md | 19 + .../graphql/types/type-aliases/PayoutData.md | 35 + .../type-aliases/RewardAddedEventData.md | 31 + .../graphql/types/type-aliases/StatusEvent.md | 31 + .../types/type-aliases/TaskStatistics.md | 19 + .../types/type-aliases/WorkerStatistics.md | 19 + docs/sdk/typescript/interfaces/README.md | 31 + .../interfaces/interfaces/IEscrowConfig.md | 87 + .../interfaces/interfaces/IEscrowsFilter.md | 143 + .../interfaces/IHMTHoldersParams.md | 63 + .../interfaces/interfaces/IKVStore.md | 27 + .../interfaces/interfaces/IKeyPair.md | 47 + .../interfaces/interfaces/ILeader.md | 197 ++ .../interfaces/interfaces/ILeaderSubgraph.md | 269 ++ .../interfaces/interfaces/ILeadersFilter.md | 27 + .../interfaces/interfaces/IOperator.md | 67 + .../interfaces/IOperatorSubgraph.md | 91 + .../interfaces/interfaces/IPagination.md | 44 + .../interfaces/interfaces/IPayoutFilter.md | 47 + .../interfaces/IReputationNetwork.md | 37 + .../interfaces/IReputationNetworkSubgraph.md | 49 + .../interfaces/interfaces/IReward.md | 27 + .../interfaces/IStatisticsFilter.md | 73 + .../interfaces/interfaces/ITransaction.md | 117 + .../interfaces/ITransactionsFilter.md | 123 + .../interfaces/InternalTransaction.md | 77 + .../kvstore/classes/KVStoreClient.md | 20 +- .../kvstore/classes/KVStoreUtils.md | 20 +- docs/sdk/typescript/modules.md | 4 + .../operator/classes/OperatorUtils.md | 32 +- .../staking/classes/StakingClient.md | 224 +- .../statistics/classes/StatisticsClient.md | 56 +- .../storage/classes/StorageClient.md | 20 +- .../transaction/classes/TransactionUtils.md | 16 +- docs/sdk/typescript/types/README.md | 22 + .../types/enumerations/EscrowStatus.md | 81 + .../types/type-aliases/EscrowCancel.md | 29 + .../types/type-aliases/EscrowWithdraw.md | 35 + .../types/type-aliases/NetworkData.md | 83 + .../types/type-aliases/StorageCredentials.md | 33 + .../types/type-aliases/StorageParams.md | 43 + .../types/type-aliases/UploadFile.md | 35 + .../src/modules/details/details.service.ts | 4 +- .../src/modules/details/dto/leader.dto.ts | 7 + .../modules/details/dto/transaction.dto.ts | 13 + packages/apps/dashboard/ui-2024/src/App.tsx | 22 +- .../src/assets/styles/color-palette.ts | 118 +- .../components/Breadcrumbs/Breadcrumbs.tsx | 40 +- .../src/components/Charts/AreaChart.tsx | 730 ++--- .../components/Charts/CustomChartTooltip.tsx | 148 +- .../src/components/Charts/CustomXAxisTick.tsx | 28 +- .../src/components/Charts/ToggleCharts.tsx | 150 +- .../src/components/Clipboard/Clipboard.tsx | 98 +- .../CustomTooltip/CustomTooltip.tsx | 2 +- .../src/components/DataEntry/DatePicker.tsx | 138 +- .../components/DataEntry/ToggleButtons.tsx | 98 +- .../ui-2024/src/components/Footer/Footer.tsx | 138 +- .../ui-2024/src/components/Header/Header.tsx | 274 +- .../src/components/Home/FormatNumber.tsx | 46 +- .../src/components/Home/GraphSwiper.tsx | 118 +- .../src/components/Home/SmallGraph.tsx | 222 +- .../src/components/Icons/AvalancheIcon.tsx | 56 +- .../Icons/BinanceSmartChainIcon.tsx | 2 +- .../ui-2024/src/components/Icons/CeloIcon.tsx | 46 +- .../src/components/Icons/DiscordIcon.tsx | 10 +- .../components/Icons/EscrowAddressIcon.tsx | 412 +-- .../src/components/Icons/EthereumIcon.tsx | 62 +- .../components/Icons/ExchangeOracleIcon.tsx | 58 +- .../src/components/Icons/HumanIcon.tsx | 2 +- .../src/components/Icons/JobLauncher.tsx | 58 +- .../src/components/Icons/LeaderboardIcon.tsx | 378 +-- .../src/components/Icons/LogoBlockIcon.tsx | 150 +- .../components/Icons/LogoBlockIconMobile.tsx | 56 +- .../components/Icons/MoonbaseAlphaIcon.tsx | 2 +- .../src/components/Icons/MoonbeamIcon.tsx | 16 +- .../src/components/Icons/PolygonIcon.tsx | 16 +- .../src/components/Icons/RecordingOracle.tsx | 98 +- .../src/components/Icons/ReputationOracle.tsx | 118 +- .../src/components/Icons/WalletIcon.tsx | 352 +-- .../src/components/Icons/XLayerIcon.tsx | 144 +- .../ui-2024/src/components/Loader/index.tsx | 24 +- .../src/components/NetworkIcon/index.tsx | 64 +- .../components/NothingFound/NothingFound.tsx | 26 +- .../components/PageWrapper/PageWrapper.tsx | 38 +- .../ui-2024/src/components/Search/Search.tsx | 458 +-- .../src/components/Search/TopBarSearch.tsx | 440 +-- .../ui-2024/src/components/Search/index.ts | 2 +- .../SearchResults/AbbreviateClipboard.tsx | 96 +- .../SearchResults/TitleSectionWrapper.tsx | 90 +- .../src/components/ShadowIcon/ShadowIcon.tsx | 22 +- .../src/components/ShadowIcon/index.ts | 2 +- .../Leaderboard/components/AddressCell.tsx | 20 +- .../Leaderboard/components/ChainCell.tsx | 26 +- .../Leaderboard/components/EntityIcon.tsx | 28 +- .../components/ReputationLabel.tsx | 66 +- .../Leaderboard/components/SelectNetwork.tsx | 116 +- .../Leaderboard/components/TextCell.tsx | 22 +- .../src/features/Leaderboard/index.tsx | 92 +- .../ui-2024/src/helpers/abbreviateValue.ts | 12 +- .../apps/dashboard/ui-2024/src/helpers/env.ts | 66 +- .../ui-2024/src/helpers/formatDate.ts | 2 +- .../ui-2024/src/helpers/formatHMTDecimals.ts | 32 +- .../ui-2024/src/helpers/formatNumber.ts | 14 +- packages/apps/dashboard/ui-2024/src/main.tsx | 24 +- .../ui-2024/src/pages/Graph/Graph.tsx | 86 +- .../ui-2024/src/pages/Home/HMTPrice.tsx | 26 +- .../ui-2024/src/pages/Home/Holders.tsx | 26 +- .../dashboard/ui-2024/src/pages/Home/Home.tsx | 218 +- .../ui-2024/src/pages/Home/Leaderboard.tsx | 20 +- .../src/pages/Home/TotalNumberOfTasks.tsx | 26 +- .../src/pages/Home/TotalTransactions.tsx | 30 +- .../ui-2024/src/pages/Leaderboard/index.tsx | 34 +- .../EscrowAddress/EscrowAddress.tsx | 258 +- .../EscrowAddress/HMTBalance.tsx | 46 +- .../SearchResults/RoleDetails/RoleDetails.tsx | 707 +++-- .../RoleDetailsEscrowsTable.tsx | 180 +- .../tableComponents/EscrowsTableBody.tsx | 152 +- .../EscrowsTableBodyContainer.tsx | 42 +- .../src/pages/SearchResults/SearchResults.tsx | 276 +- .../WalletAddress/WalletAddress.tsx | 152 +- .../WalletAddressTransactionsTable.tsx | 156 +- .../cells/TransactionTableCellMethod.tsx | 76 +- .../cells/TransactionTableCellValue.tsx | 26 +- .../tableComponents/TransactionsTableBody.tsx | 124 +- .../TransactionsTableBodyContainer.tsx | 42 +- .../tableComponents/TransactionsTableHead.tsx | 162 +- .../ui-2024/src/services/api-paths.ts | 60 +- .../src/services/api/use-address-details.tsx | 164 +- .../src/services/api/use-escrows-details.tsx | 128 +- .../src/services/api/use-general-stats.tsx | 26 +- .../api/use-graph-page-chart-data.tsx | 226 +- .../api/use-hcaptcha-general-stats.tsx | 30 +- .../src/services/api/use-hmt-price.tsx | 24 +- .../api/use-leaderboard-all-details.tsx | 38 +- .../services/api/use-leaderboard-details.tsx | 83 +- .../services/api/use-transaction-details.tsx | 126 +- .../ui-2024/src/services/global.type.ts | 6 +- .../src/services/handle-error-message.ts | 20 +- .../ui-2024/src/services/http-service.ts | 2 +- .../ui-2024/src/services/validate-response.ts | 30 +- packages/apps/dashboard/ui-2024/src/theme.tsx | 496 ++-- .../ui-2024/src/utils/config/networks.ts | 14 +- .../utils/hooks/use-escrows-details-dto.ts | 172 +- .../hooks/use-graph-page-chart-params.tsx | 180 +- .../ui-2024/src/utils/hooks/use-is-mobile.tsx | 16 +- .../src/utils/hooks/use-leaderboard-search.ts | 34 +- .../hooks/use-transactions-details-dto.ts | 176 +- .../src/utils/hooks/use-wallet-search.ts | 52 +- .../apps/dashboard/ui-2024/vite.config.ts | 42 +- packages/apps/faucet/server/.env.example | 2 +- .../faucet/server/src/services/web3.spec.ts | 2 +- .../src/modules/job/job.service.spec.ts | 4 +- .../apps/human-app/frontend/.eslintrc.cjs | 1 + .../api/services/common/prepare-signature.ts | 1 - .../src/api/services/operator/get-stats.ts | 1 - .../frontend/src/smart-contracts/chains.ts | 2 +- packages/apps/human-app/server/package.json | 2 +- .../integrations/kv-store/kv-store.gateway.ts | 6 +- .../src/components/CardTextRow/index.tsx | 17 +- .../src/components/TokenSelect/index.tsx | 29 +- .../client/src/constants/chains.ts | 44 +- .../client/src/constants/index.tsx | 4 +- .../client/src/pages/Job/JobDetail/index.tsx | 38 +- .../job-launcher/client/src/utils/index.ts | 7 + .../common/config/network-config.service.ts | 1 + .../server/src/common/constants/index.ts | 2 +- .../server/src/common/enums/job.ts | 2 +- .../1730895674938-JobStatusFunded.ts | 61 + .../modules/cron-job/cron-job.service.spec.ts | 6 +- .../src/modules/cron-job/cron-job.service.ts | 4 +- .../server/src/modules/job/job.dto.ts | 20 - .../server/src/modules/job/job.repository.ts | 2 +- .../src/modules/job/job.service.spec.ts | 32 +- .../server/src/modules/job/job.service.ts | 22 +- .../job/routing-protocol.service.spec.ts | 10 +- .../src/modules/web3/web3.service.spec.ts | 61 +- .../server/src/modules/web3/web3.service.ts | 25 +- .../apps/reputation-oracle/server/README.md | 7 + .../src/modules/payout/payout.service.ts | 1 + packages/core/.openzeppelin/bsc-testnet.json | 149 + packages/core/.openzeppelin/sepolia.json | 732 +++++ .../core/.openzeppelin/unknown-80002.json | 149 + packages/core/README.md | 6 - packages/core/contracts/Escrow.sol | 262 +- packages/core/contracts/EscrowFactory.sol | 77 +- packages/core/contracts/RewardPool.sol | 147 - packages/core/contracts/Staking.sol | 500 +--- .../core/contracts/interfaces/IEscrow.sol | 15 +- .../core/contracts/interfaces/IRewardPool.sol | 29 - .../core/contracts/interfaces/IStaking.sol | 78 +- packages/core/contracts/libs/Stakes.sol | 84 +- .../core/contracts/test/EscrowFactoryV0.sol | 76 +- packages/core/contracts/test/USDT.sol | 11 + packages/core/contracts/utils/Math.sol | 183 -- .../core/contracts/utils/SignedSafeMath.sol | 104 - packages/core/hardhat.config.ts | 10 +- packages/core/scripts/deploy-proxies.ts | 23 +- packages/core/scripts/deploy.ts | 38 +- packages/core/scripts/update-history-files.ts | 6 +- packages/core/scripts/upgrade-proxies.ts | 60 +- packages/core/test/Escrow-USDT.ts | 979 +++++++ packages/core/test/Escrow.ts | 341 ++- packages/core/test/EscrowFactory.ts | 117 +- packages/core/test/MetaHumanGovernor.ts | 2 +- packages/core/test/RewardPool.ts | 343 --- packages/core/test/Staking.ts | 630 ++-- .../tests/integration/chain/test_escrow.py | 9 + .../test_process_exchange_oracle_webhooks.py | 4 +- .../tests/utils/setup_escrow.py | 9 +- .../sdk/python/human-protocol-sdk/README.md | 22 +- .../docs/human_protocol_sdk.kvstore.rst | 1 + .../human_protocol_sdk/constants.py | 31 +- .../escrow/escrow_client.py | 234 +- .../human_protocol_sdk/gql/operator.py | 5 +- .../human_protocol_sdk/gql/statistics.py | 2 - .../human_protocol_sdk/gql/transaction.py | 19 +- .../operator/operator_utils.py | 66 +- .../human_protocol_sdk/staking/__init__.py | 2 +- .../staking/staking_client.py | 239 +- .../transaction/transaction_utils.py | 36 + .../human_protocol_sdk/utils.py | 12 - .../escrow/test_escrow_client.py | 481 ++-- .../operator/test_operator_utils.py | 49 +- .../staking/test_staking_client.py | 210 -- .../transaction/test_transaction_utils.py | 24 + .../human-protocol-sdk/package.json | 6 +- .../human-protocol-sdk/src/constants.ts | 57 +- .../human-protocol-sdk/src/encryption.ts | 2 +- .../human-protocol-sdk/src/escrow.ts | 222 +- .../src/graphql/queries/operator.ts | 4 +- .../src/graphql/queries/statistics.ts | 2 - .../src/graphql/queries/transaction.ts | 23 +- .../human-protocol-sdk/src/graphql/types.ts | 2 - .../human-protocol-sdk/src/interfaces.ts | 30 +- .../human-protocol-sdk/src/kvstore.ts | 2 +- .../human-protocol-sdk/src/operator.ts | 19 + .../human-protocol-sdk/src/staking.ts | 187 +- .../human-protocol-sdk/src/types.ts | 22 +- .../human-protocol-sdk/test/escrow.test.ts | 397 ++- .../human-protocol-sdk/test/kvstore.test.ts | 2 +- .../human-protocol-sdk/test/operator.test.ts | 22 +- .../human-protocol-sdk/test/staking.test.ts | 266 +- .../test/transaction.test.ts | 18 +- packages/sdk/typescript/subgraph/.gitignore | 4 +- .../sdk/typescript/subgraph/config/amoy.json | 4 +- .../subgraph/config/bsc-testnet.json | 4 +- .../typescript/subgraph/config/sepolia.json | 8 +- packages/sdk/typescript/subgraph/package.json | 4 +- .../sdk/typescript/subgraph/schema.graphql | 85 +- .../typescript/subgraph/src/mapping/Escrow.ts | 355 --- .../subgraph/src/mapping/EscrowFactory.ts | 21 +- .../subgraph/src/mapping/EscrowTemplate.ts | 735 +++++ .../subgraph/src/mapping/HMTokenTemplate.ts | 79 +- .../subgraph/src/mapping/KVStore.ts | 24 +- .../subgraph/src/mapping/RewardPool.ts | 24 - .../{Staking.ts => StakingTemplate.ts} | 104 +- .../subgraph/src/mapping/legacy/Escrow.ts | 53 +- .../src/mapping/legacy/EscrowFactory.ts | 11 +- .../subgraph/src/mapping/utils/dayUpdates.ts | 1 - .../subgraph/src/mapping/utils/event.ts | 6 + .../subgraph/src/mapping/utils/transaction.ts | 119 +- .../sdk/typescript/subgraph/template.yaml | 40 +- .../escrow-factory/escrow-factory.test.ts | 19 +- .../subgraph/tests/escrow-factory/fixtures.ts | 11 +- .../subgraph/tests/escrow/escrow.test.ts | 678 ++++- .../subgraph/tests/escrow/fixtures.ts | 188 ++ .../typescript/subgraph/tests/hmt/fixtures.ts | 42 +- .../typescript/subgraph/tests/hmt/hmt.test.ts | 189 +- .../subgraph/tests/kvstore/fixtures.ts | 12 +- .../subgraph/tests/kvstore/kvstore.test.ts | 145 +- .../escrow-factory/escrow-factory.test.ts | 12 +- .../tests/legacy/escrow-factory/fixtures.ts | 11 +- .../tests/legacy/escrow/escrow.test.ts | 27 +- .../subgraph/tests/legacy/escrow/fixtures.ts | 16 + .../subgraph/tests/reward-pool/fixtures.ts | 40 - .../tests/reward-pool/reward-pool.test.ts | 172 -- .../subgraph/tests/staking/fixtures.ts | 128 +- .../subgraph/tests/staking/staking.test.ts | 453 +-- .../sdk/typescript/subgraph/tests/utils.ts | 11 + scripts/fortune/docker-compose.yml | 3 +- yarn.lock | 2557 +++++++++-------- 318 files changed, 16961 insertions(+), 13109 deletions(-) create mode 100644 docs/sdk/typescript/enums/README.md create mode 100644 docs/sdk/typescript/enums/enumerations/ChainId.md create mode 100644 docs/sdk/typescript/enums/enumerations/OrderDirection.md create mode 100644 docs/sdk/typescript/graphql/types/README.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/IMData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md create mode 100644 docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md create mode 100644 docs/sdk/typescript/interfaces/README.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IKVStore.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IKeyPair.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/ILeader.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IOperator.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IPagination.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IReward.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/ITransaction.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md create mode 100644 docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md create mode 100644 docs/sdk/typescript/types/README.md create mode 100644 docs/sdk/typescript/types/enumerations/EscrowStatus.md create mode 100644 docs/sdk/typescript/types/type-aliases/EscrowCancel.md create mode 100644 docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md create mode 100644 docs/sdk/typescript/types/type-aliases/NetworkData.md create mode 100644 docs/sdk/typescript/types/type-aliases/StorageCredentials.md create mode 100644 docs/sdk/typescript/types/type-aliases/StorageParams.md create mode 100644 docs/sdk/typescript/types/type-aliases/UploadFile.md create mode 100644 packages/apps/job-launcher/client/src/utils/index.ts create mode 100644 packages/apps/job-launcher/server/src/database/migrations/1730895674938-JobStatusFunded.ts create mode 100644 packages/core/.openzeppelin/sepolia.json delete mode 100644 packages/core/contracts/RewardPool.sol delete mode 100644 packages/core/contracts/interfaces/IRewardPool.sol create mode 100644 packages/core/contracts/test/USDT.sol delete mode 100644 packages/core/contracts/utils/Math.sol delete mode 100644 packages/core/contracts/utils/SignedSafeMath.sol create mode 100644 packages/core/test/Escrow-USDT.ts delete mode 100644 packages/core/test/RewardPool.ts delete mode 100644 packages/sdk/typescript/subgraph/src/mapping/Escrow.ts create mode 100644 packages/sdk/typescript/subgraph/src/mapping/EscrowTemplate.ts delete mode 100644 packages/sdk/typescript/subgraph/src/mapping/RewardPool.ts rename packages/sdk/typescript/subgraph/src/mapping/{Staking.ts => StakingTemplate.ts} (70%) delete mode 100644 packages/sdk/typescript/subgraph/tests/reward-pool/fixtures.ts delete mode 100644 packages/sdk/typescript/subgraph/tests/reward-pool/reward-pool.test.ts create mode 100644 packages/sdk/typescript/subgraph/tests/utils.ts diff --git a/.github/workflows/cd-deploy-contracts.yaml b/.github/workflows/cd-deploy-contracts.yaml index 8907e114a4..cd70acca2b 100644 --- a/.github/workflows/cd-deploy-contracts.yaml +++ b/.github/workflows/cd-deploy-contracts.yaml @@ -9,12 +9,6 @@ on: escrowFactory: description: 'deploy escrow factory' required: true - staking: - description: 'deploy staking' - required: true - rewardPool: - description: 'deploy reward pool' - required: true jobs: deploy-contracts: @@ -51,63 +45,43 @@ jobs: run: | case ${{ github.event.inputs.network }} in "sepolia") - echo "escrow_factory=0xD6D347ba6987519B4e42EcED43dF98eFf5465a23" >> $GITHUB_OUTPUT - echo "staking=0x2B9C5EC6220BA8Ad08CB51A60FFdbC6a6235B203" >> $GITHUB_OUTPUT - echo "reward_pool=0xAFf5a986A530ff839d49325A5dF69F96627E8D29" >> $GITHUB_OUTPUT + echo "escrow_factory=0x5987A5558d961ee674efe4A8c8eB7B1b5495D3bf" >> $GITHUB_OUTPUT echo "private_key=TESTNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "polygon") echo "escrow_factory=0xBDBfD2cC708199C5640C6ECdf3B0F4A4C67AdfcB" >> $GITHUB_OUTPUT - echo "staking=0xcbAd56bE3f504E98bd70875823d3CC0242B7bB29" >> $GITHUB_OUTPUT - echo "reward_pool=0x1371057BAec59944B924A7963F2EeCF43ff94CE4" >> $GITHUB_OUTPUT echo "private_key=MAINNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "polygonAmoy") echo "escrow_factory=0xAFf5a986A530ff839d49325A5dF69F96627E8D29" >> $GITHUB_OUTPUT - echo "staking=0xCc0AF0635aa19fE799B6aFDBe28fcFAeA7f00a60" >> $GITHUB_OUTPUT - echo "reward_pool=0xd866bCEFf6D0F77E1c3EAE28230AE6C79b03fDa7" >> $GITHUB_OUTPUT echo "private_key=TESTNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "bsc") echo "escrow_factory=0x92FD968AcBd521c232f5fB8c33b342923cC72714" >> $GITHUB_OUTPUT - echo "staking=0xdFbB79dC35a3A53741be54a2C9b587d6BafAbd1C" >> $GITHUB_OUTPUT - echo "reward_pool=0xf376443BCc6d4d4D63eeC086bc4A9E4a83878e0e" >> $GITHUB_OUTPUT echo "private_key=MAINNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "bscTestnet") echo "escrow_factory=0x2bfA592DBDaF434DDcbb893B1916120d181DAD18" >> $GITHUB_OUTPUT - echo "staking=0x5517fE916Fe9F8dB15B0DDc76ebDf0BdDCd4ed18" >> $GITHUB_OUTPUT - echo "reward_pool=0xB0A0500103eCEc431b73F6BAd923F0a2774E6e29" >> $GITHUB_OUTPUT echo "private_key=TESTNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "moonbeam") echo "escrow_factory=0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a" >> $GITHUB_OUTPUT - echo "staking=0x05398211bA2046E296fBc9a9D3EB49e3F15C3123" >> $GITHUB_OUTPUT - echo "reward_pool=0x4A5963Dd6792692e9147EdC7659936b96251917a" >> $GITHUB_OUTPUT echo "private_key=MAINNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "moonbaseAlpha") echo "escrow_factory=0x5e622FF522D81aa426f082bDD95210BC25fCA7Ed" >> $GITHUB_OUTPUT - echo "staking=0xBFC7009F3371F93F3B54DdC8caCd02914a37495c" >> $GITHUB_OUTPUT - echo "reward_pool=0xf46B45Df3d956369726d8Bd93Ba33963Ab692920" >> $GITHUB_OUTPUT echo "private_key=TESTNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "mainnet") echo "escrow_factory=0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a" >> $GITHUB_OUTPUT - echo "staking=0x05398211bA2046E296fBc9a9D3EB49e3F15C3123" >> $GITHUB_OUTPUT - echo "reward_pool=0x4A5963Dd6792692e9147EdC7659936b96251917a" >> $GITHUB_OUTPUT echo "private_key=MAINNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "avalanche") echo "escrow_factory=0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a" >> $GITHUB_OUTPUT - echo "staking=0x05398211bA2046E296fBc9a9D3EB49e3F15C3123" >> $GITHUB_OUTPUT - echo "reward_pool=0x4A5963Dd6792692e9147EdC7659936b96251917a" >> $GITHUB_OUTPUT echo "private_key=MAINNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; "avalancheFujiTestnet") echo "escrow_factory=0x56C2ba540726ED4f46E7a134b6b9Ee9C867FcF92" >> $GITHUB_OUTPUT - echo "staking=0x9890473B0b93E24d6D1a8Dfb739D577C6f25FFd3" >> $GITHUB_OUTPUT - echo "reward_pool=0x5517fE916Fe9F8dB15B0DDc76ebDf0BdDCd4ed18" >> $GITHUB_OUTPUT echo "private_key=TESTNET_PRIVATE_KEY" >> $GITHUB_OUTPUT ;; *) @@ -116,30 +90,18 @@ jobs: ;; esac - name: Upgrade Proxies - if: github.event.inputs.escrowFactory == 'true' || github.event.inputs.staking == 'true' || github.event.inputs.rewardPool== 'true' + if: github.event.inputs.escrowFactory == 'true' run: yarn upgrade:proxy --network ${{ github.event.inputs.network }} working-directory: ./packages/core env: PRIVATE_KEY: ${{ secrets[steps.networks.outputs.private_key] }} DEPLOY_ESCROW_FACTORY: ${{ github.event.inputs.escrowFactory }} - DEPLOY_STAKING: ${{ github.event.inputs.staking }} - DEPLOY_REWARD_POOL: ${{ github.event.inputs.rewardPool }} ESCROW_FACTORY_ADDRESS: ${{ steps.networks.outputs.escrow_factory }} - STAKING_ADDRESS: ${{ steps.networks.outputs.staking }} - REWARD_POOL_ADDRESS: ${{ steps.networks.outputs.reward_pool }} - name: Verify Escrow Factory Proxy if: always() && github.event.inputs.escrowFactory == 'true' run: npx hardhat verify --network ${{ github.event.inputs.network }} ${{ steps.networks.outputs.escrow_factory }} working-directory: ./packages/core - - name: Verify Staking Proxy - if: always() && github.event.inputs.staking == 'true' - run: npx hardhat verify --network ${{ github.event.inputs.network }} ${{ steps.networks.outputs.staking }} - working-directory: ./packages/core - - name: Verify Reward Pool Proxy - if: always() && github.event.inputs.rewardPool== 'true' - run: npx hardhat verify --network ${{ github.event.inputs.network }} ${{ steps.networks.outputs.reward_pool }} - working-directory: ./packages/core #Commit changes to develop - name: Check for Changes if: always() diff --git a/docs/sdk/python/human_protocol_sdk.escrow.escrow_client.md b/docs/sdk/python/human_protocol_sdk.escrow.escrow_client.md index b39a33bce7..aa21abc1ef 100644 --- a/docs/sdk/python/human_protocol_sdk.escrow.escrow_client.md +++ b/docs/sdk/python/human_protocol_sdk.escrow.escrow_client.md @@ -73,45 +73,6 @@ Initializes a Escrow instance. * **Parameters:** **web3** (`Web3`) – The Web3 object -#### abort(escrow_address, tx_options=None) - -Cancels the specified escrow, -sends the balance to the canceler and selfdestructs the escrow contract. - -* **Parameters:** - * **escrow_address** (`str`) – Address of the escrow to abort - * **tx_options** (`Optional`[`TxParams`]) – (Optional) Additional transaction parameters -* **Return type:** - `None` -* **Returns:** - None -* **Raises:** - [**EscrowClientError**](#human_protocol_sdk.escrow.escrow_client.EscrowClientError) – If an error occurs while checking the parameters -* **Example:** - ```python - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - escrow_client.abort("0x62dD51230A30401C455c8398d06F85e4EaB6309f") - ``` - #### add_trusted_handlers(escrow_address, handlers, tx_options=None) Adds an array of addresses to the trusted handlers list. @@ -158,7 +119,7 @@ Adds an array of addresses to the trusted handlers list. ) ``` -#### bulk_payout(escrow_address, recipients, amounts, final_results_url, final_results_hash, txId, tx_options=None) +#### bulk_payout(escrow_address, recipients, amounts, final_results_url, final_results_hash, txId, force_complete=False, tx_options=None) Pays out the amounts specified to the workers and sets the URL of the final results file. @@ -169,6 +130,7 @@ Pays out the amounts specified to the workers and sets the URL of the final resu * **final_results_url** (`str`) – Final results file url * **final_results_hash** (`str`) – Final results file hash * **txId** (`Decimal`) – Serial number of the bulks + * **force_complete** (`Optional`[`bool`]) – (Optional) Indicates if remaining balance should be transferred to the escrow creator * **tx_options** (`Optional`[`TxParams`]) – (Optional) Additional transaction parameters * **Return type:** `None` @@ -301,67 +263,6 @@ Sets the status of an escrow to completed. escrow_client.complete("0x62dD51230A30401C455c8398d06F85e4EaB6309f") ``` -#### create_and_setup_escrow(token_address, trusted_handlers, job_requester_id, escrow_config) - -Creates and sets up an escrow. - -* **Parameters:** - * **token_address** (`str`) – Token to use for pay outs - * **trusted_handlers** (`List`[`str`]) – Array of addresses that can perform actions on the contract - * **job_requester_id** (`str`) – The id of the job requester - * **escrow_config** ([`EscrowConfig`](#human_protocol_sdk.escrow.escrow_client.EscrowConfig)) – Object containing all the necessary information to setup an escrow -* **Return type:** - `str` -* **Returns:** - The address of the escrow created -* **Raises:** - [**EscrowClientError**](#human_protocol_sdk.escrow.escrow_client.EscrowClientError) – If an error occurs while checking the parameters -* **Example:** - ```python - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - token_address = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4' - trusted_handlers = [ - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' - ] - job_requester_id = 'job-requester' - escrow_config = EscrowConfig( - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - 10, - 10, - 10, - "htttp://localhost/manifest.json", - "b5dad76bf6772c0f07fd5e048f6e75a5f86ee079", - ) - escrow_address = escrow_client.create_and_setup_escrow( - token_address, - trusted_handlers, - job_requester_id, - escrow_config - ) - ``` - #### create_escrow(token_address, trusted_handlers, job_requester_id, tx_options=None) Creates an escrow contract that uses the token passed to pay oracle fees and reward workers. @@ -882,6 +783,52 @@ Stores the results url. ) ``` +#### withdraw(escrow_address, token_address, tx_options=None) + +Withdraws additional tokens in the escrow to the canceler. + +* **Parameters:** + * **escrow_address** (`str`) – Address of the escrow to withdraw + * **token_address** (`str`) – Address of the token to withdraw + * **tx_options** (`Optional`[`TxParams`]) – (Optional) Additional transaction parameters +* **Return type:** + [`EscrowWithdraw`](#human_protocol_sdk.escrow.escrow_client.EscrowWithdraw) +* **Returns:** + EscrowWithdraw: + An instance of the EscrowWithdraw class containing details of the withdrawal transaction, + including the transaction hash and the token address and amount withdrawn. +* **Raises:** + * [**EscrowClientError**](#human_protocol_sdk.escrow.escrow_client.EscrowClientError) – If an error occurs while checking the parameters + * [**EscrowClientError**](#human_protocol_sdk.escrow.escrow_client.EscrowClientError) – If the transfer event associated with the withdrawal + is not found in the transaction logs +* **Example:** + ```python + from eth_typing import URI + from web3 import Web3 + from web3.middleware import construct_sign_and_send_raw_middleware + from web3.providers.auto import load_provider_from_uri + + from human_protocol_sdk.escrow import EscrowClient + + def get_w3_with_priv_key(priv_key: str): + w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) + gas_payer = w3.eth.account.from_key(priv_key) + w3.eth.default_account = gas_payer.address + w3.middleware_onion.add( + construct_sign_and_send_raw_middleware(gas_payer), + "construct_sign_and_send_raw_middleware", + ) + return (w3, gas_payer) + + (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') + escrow_client = EscrowClient(w3) + + escrow_cancel_data = escrow_client.withdraw( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4" + ) + ``` + ### *exception* human_protocol_sdk.escrow.escrow_client.EscrowClientError Bases: `Exception` @@ -905,3 +852,16 @@ Initializes a Escrow instance. * **reputation_oracle_fee** (`Decimal`) – Fee percentage of the Reputation Oracle * **manifest_url** (`str`) – Manifest file url * **hash** (`str`) – Manifest file hash + +### *class* human_protocol_sdk.escrow.escrow_client.EscrowWithdraw(tx_hash, token_address, amount_withdrawn) + +Bases: `object` + +#### \_\_init_\_(tx_hash, token_address, amount_withdrawn) + +Represents the result of an escrow cancellation transaction. + +* **Parameters:** + * **tx_hash** (`str`) – The hash of the transaction associated with the escrow withdrawal. + * **token_address** (`str`) – The address of the token used for the withdrawal. + * **amount_withdrawn** (`any`) – The amount withdrawn from the escrow. diff --git a/docs/sdk/python/human_protocol_sdk.escrow.md b/docs/sdk/python/human_protocol_sdk.escrow.md index b7cfbd1674..aa29ac1288 100644 --- a/docs/sdk/python/human_protocol_sdk.escrow.md +++ b/docs/sdk/python/human_protocol_sdk.escrow.md @@ -12,12 +12,10 @@ obtain information from both the contracts and subgraph. * [`EscrowCancel.__init__()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowCancel.__init__) * [`EscrowClient`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient) * [`EscrowClient.__init__()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.__init__) - * [`EscrowClient.abort()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.abort) * [`EscrowClient.add_trusted_handlers()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.add_trusted_handlers) * [`EscrowClient.bulk_payout()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.bulk_payout) * [`EscrowClient.cancel()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.cancel) * [`EscrowClient.complete()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.complete) - * [`EscrowClient.create_and_setup_escrow()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.create_and_setup_escrow) * [`EscrowClient.create_escrow()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.create_escrow) * [`EscrowClient.fund()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.fund) * [`EscrowClient.get_balance()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.get_balance) @@ -34,9 +32,12 @@ obtain information from both the contracts and subgraph. * [`EscrowClient.get_token_address()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.get_token_address) * [`EscrowClient.setup()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.setup) * [`EscrowClient.store_results()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.store_results) + * [`EscrowClient.withdraw()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient.withdraw) * [`EscrowClientError`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClientError) * [`EscrowConfig`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowConfig) * [`EscrowConfig.__init__()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowConfig.__init__) + * [`EscrowWithdraw`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowWithdraw) + * [`EscrowWithdraw.__init__()`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowWithdraw.__init__) * [human_protocol_sdk.escrow.escrow_utils module](human_protocol_sdk.escrow.escrow_utils.md) * [Code Example](human_protocol_sdk.escrow.escrow_utils.md#code-example) * [Module](human_protocol_sdk.escrow.escrow_utils.md#module) diff --git a/docs/sdk/python/human_protocol_sdk.kvstore.md b/docs/sdk/python/human_protocol_sdk.kvstore.md index 93eb4096d5..1f516754d6 100644 --- a/docs/sdk/python/human_protocol_sdk.kvstore.md +++ b/docs/sdk/python/human_protocol_sdk.kvstore.md @@ -13,3 +13,13 @@ This module allows the contract interaction with the key value storage on chain. * [`KVStoreClient.set_bulk()`](human_protocol_sdk.kvstore.kvstore_client.md#human_protocol_sdk.kvstore.kvstore_client.KVStoreClient.set_bulk) * [`KVStoreClient.set_file_url_and_hash()`](human_protocol_sdk.kvstore.kvstore_client.md#human_protocol_sdk.kvstore.kvstore_client.KVStoreClient.set_file_url_and_hash) * [`KVStoreClientError`](human_protocol_sdk.kvstore.kvstore_client.md#human_protocol_sdk.kvstore.kvstore_client.KVStoreClientError) +* [human_protocol_sdk.kvstore.kvstore_utils module](human_protocol_sdk.kvstore.kvstore_utils.md) + * [Code Example](human_protocol_sdk.kvstore.kvstore_utils.md#code-example) + * [Module](human_protocol_sdk.kvstore.kvstore_utils.md#module) + * [`KVStoreData`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreData) + * [`KVStoreData.__init__()`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreData.__init__) + * [`KVStoreUtils`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreUtils) + * [`KVStoreUtils.get()`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreUtils.get) + * [`KVStoreUtils.get_file_url_and_verify_hash()`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreUtils.get_file_url_and_verify_hash) + * [`KVStoreUtils.get_kvstore_data()`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreUtils.get_kvstore_data) + * [`KVStoreUtils.get_public_key()`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreUtils.get_public_key) diff --git a/docs/sdk/python/human_protocol_sdk.md b/docs/sdk/python/human_protocol_sdk.md index e40e0800f9..6e9d0c4f79 100644 --- a/docs/sdk/python/human_protocol_sdk.md +++ b/docs/sdk/python/human_protocol_sdk.md @@ -40,6 +40,7 @@ * [`EscrowClient`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient) * [`EscrowClientError`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClientError) * [`EscrowConfig`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowConfig) + * [`EscrowWithdraw`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowWithdraw) * [human_protocol_sdk.escrow.escrow_utils module](human_protocol_sdk.escrow.escrow_utils.md) * [Code Example](human_protocol_sdk.escrow.escrow_utils.md#code-example) * [Module](human_protocol_sdk.escrow.escrow_utils.md#module) @@ -53,6 +54,11 @@ * [Module](human_protocol_sdk.kvstore.kvstore_client.md#module) * [`KVStoreClient`](human_protocol_sdk.kvstore.kvstore_client.md#human_protocol_sdk.kvstore.kvstore_client.KVStoreClient) * [`KVStoreClientError`](human_protocol_sdk.kvstore.kvstore_client.md#human_protocol_sdk.kvstore.kvstore_client.KVStoreClientError) + * [human_protocol_sdk.kvstore.kvstore_utils module](human_protocol_sdk.kvstore.kvstore_utils.md) + * [Code Example](human_protocol_sdk.kvstore.kvstore_utils.md#code-example) + * [Module](human_protocol_sdk.kvstore.kvstore_utils.md#module) + * [`KVStoreData`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreData) + * [`KVStoreUtils`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreUtils) * [human_protocol_sdk.kvstore.kvstore_utils module](human_protocol_sdk.kvstore.kvstore_utils.md) * [Code Example](human_protocol_sdk.kvstore.kvstore_utils.md#code-example) * [Module](human_protocol_sdk.kvstore.kvstore_utils.md#module) @@ -79,7 +85,6 @@ * [human_protocol_sdk.staking.staking_client module](human_protocol_sdk.staking.staking_client.md) * [Code Example](human_protocol_sdk.staking.staking_client.md#code-example) * [Module](human_protocol_sdk.staking.staking_client.md#module) - * [`AllocationData`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.AllocationData) * [`StakingClient`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient) * [`StakingClientError`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClientError) * [human_protocol_sdk.statistics package](human_protocol_sdk.statistics.md) @@ -115,6 +120,7 @@ * [human_protocol_sdk.transaction.transaction_utils module](human_protocol_sdk.transaction.transaction_utils.md) * [Code Example](human_protocol_sdk.transaction.transaction_utils.md#code-example) * [Module](human_protocol_sdk.transaction.transaction_utils.md#module) + * [`InternalTransaction`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.InternalTransaction) * [`TransactionData`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionData) * [`TransactionUtils`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtils) * [`TransactionUtilsError`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtilsError) @@ -198,7 +204,6 @@ * [`get_factory_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_factory_interface) * [`get_hmt_balance()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_hmt_balance) * [`get_kvstore_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_kvstore_interface) - * [`get_reward_pool_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_reward_pool_interface) * [`get_staking_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_staking_interface) * [`handle_transaction()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.handle_transaction) * [`parse_transfer_transaction()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.parse_transfer_transaction) diff --git a/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md b/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md index e78f3eed6f..24c72c6fea 100644 --- a/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md +++ b/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md @@ -17,11 +17,11 @@ print( ## Module -### *class* human_protocol_sdk.operator.operator_utils.LeaderData(chain_id, id, address, amount_staked, amount_allocated, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reputation, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, url=None, job_types=None, registration_needed=None, registration_instructions=None) +### *class* human_protocol_sdk.operator.operator_utils.LeaderData(chain_id, id, address, amount_staked, amount_allocated, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, reputation_networks=None) Bases: `object` -#### \_\_init_\_(chain_id, id, address, amount_staked, amount_allocated, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reputation, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, url=None, job_types=None, registration_needed=None, registration_instructions=None) +#### \_\_init_\_(chain_id, id, address, amount_staked, amount_allocated, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, reputation_networks=None) Initializes an LeaderData instance. @@ -35,7 +35,6 @@ Initializes an LeaderData instance. * **locked_until_timestamp** (`int`) – Locked until timestamp * **amount_withdrawn** (`int`) – Amount withdrawn * **amount_slashed** (`int`) – Amount slashed - * **reputation** (`int`) – Reputation * **reward** (`int`) – Reward * **amount_jobs_processed** (`int`) – Amount of jobs launched * **role** (`Optional`[`str`]) – Role @@ -44,8 +43,9 @@ Initializes an LeaderData instance. * **webhook_url** (`Optional`[`str`]) – Webhook url * **url** (`Optional`[`str`]) – Url * **job_types** (`Optional`[`List`[`str`]]) – Job types - * **registration_needed** (`Optional`[`bool`]) – True, - * **registration_instructions** (`Optional`[`str`]) – Instructions url, + * **registration_needed** (`Optional`[`bool`]) – True + * **registration_instructions** (`Optional`[`str`]) – Instructions url + * **reputation_networks** (`Optional`[`List`[`str`]]) – List of reputation networks ### *class* human_protocol_sdk.operator.operator_utils.LeaderFilter(chain_id, role=None) diff --git a/docs/sdk/python/human_protocol_sdk.staking.md b/docs/sdk/python/human_protocol_sdk.staking.md index 80244a941c..8392395af5 100644 --- a/docs/sdk/python/human_protocol_sdk.staking.md +++ b/docs/sdk/python/human_protocol_sdk.staking.md @@ -8,15 +8,9 @@ obtain staking information from both the contracts and subgraph. * [human_protocol_sdk.staking.staking_client module](human_protocol_sdk.staking.staking_client.md) * [Code Example](human_protocol_sdk.staking.staking_client.md#code-example) * [Module](human_protocol_sdk.staking.staking_client.md#module) - * [`AllocationData`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.AllocationData) - * [`AllocationData.__init__()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.AllocationData.__init__) * [`StakingClient`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient) * [`StakingClient.__init__()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.__init__) - * [`StakingClient.allocate()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.allocate) * [`StakingClient.approve_stake()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.approve_stake) - * [`StakingClient.close_allocation()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.close_allocation) - * [`StakingClient.distribute_reward()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.distribute_reward) - * [`StakingClient.get_allocation()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.get_allocation) * [`StakingClient.slash()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.slash) * [`StakingClient.stake()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.stake) * [`StakingClient.unstake()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.unstake) diff --git a/docs/sdk/python/human_protocol_sdk.staking.staking_client.md b/docs/sdk/python/human_protocol_sdk.staking.staking_client.md index ffe8e02e37..57b9ffcc69 100644 --- a/docs/sdk/python/human_protocol_sdk.staking.staking_client.md +++ b/docs/sdk/python/human_protocol_sdk.staking.staking_client.md @@ -48,26 +48,11 @@ staking_client = StakingClient(w3) ## Module -### *class* human_protocol_sdk.staking.staking_client.AllocationData(escrow_address, staker, tokens, created_at, closed_at) - -Bases: `object` - -#### \_\_init_\_(escrow_address, staker, tokens, created_at, closed_at) - -Initializes an AllocationData instance. - -* **Parameters:** - * **escrow_address** (`str`) – Escrow address - * **staker** (`str`) – Staker address - * **tokens** (`str`) – Amount allocated - * **created_at** (`str`) – Creation date - * **closed_at** (`str`) – Closing date - ### *class* human_protocol_sdk.staking.staking_client.StakingClient(w3) Bases: `object` -A class used to manage staking, and allocation on the HUMAN network. +A class used to manage staking on the HUMAN network. #### \_\_init_\_(w3) @@ -76,48 +61,6 @@ Initializes a Staking instance * **Parameters:** **w3** (`Web3`) – Web3 instance -#### allocate(escrow_address, amount, tx_options=None) - -Allocates HMT token to the escrow. - -* **Parameters:** - * **escrow_address** (`str`) – Address of the escrow - * **amount** (`Decimal`) – Amount to allocate - * **tx_options** (`Optional`[`TxParams`]) – (Optional) Additional transaction parameters -* **Return type:** - `None` -* **Returns:** - None -* **Validate:** - - Amount must be greater than 0 - - Escrow address must be valid - - Amount must be less than or equal to the staked amount (on-chain) -* **Example:** - ```python - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - staking_client.allocate('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount) - ``` - #### approve_stake(amount, tx_options=None) Approves HMT token for Staking. @@ -157,109 +100,6 @@ Approves HMT token for Staking. staking_client.approve_stake(amount) ``` -#### close_allocation(escrow_address, tx_options=None) - -Closes allocated HMT token from the escrow. - -* **Parameters:** - * **escrow_address** (`str`) – Address of the escrow - * **tx_options** (`Optional`[`TxParams`]) – (Optional) Additional transaction parameters -* **Return type:** - `None` -* **Returns:** - None -* **Validate:** - - Escrow address must be valid - - Escrow should be cancelled / completed (on-chain) -* **Example:** - ```python - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - staking_client.close_allocation('0x62dD51230A30401C455c8398d06F85e4EaB6309f') - ``` - -#### distribute_reward(escrow_address, tx_options=None) - -Pays out rewards to the slashers for the specified escrow address. - -* **Parameters:** - * **escrow_address** (`str`) – Address of the escrow - * **tx_options** (`Optional`[`TxParams`]) – (Optional) Additional transaction parameters -* **Return type:** - `None` -* **Returns:** - None -* **Validate:** - - Escrow address must be valid -* **Example:** - ```python - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - staking_client.distribute_reward('0x62dD51230A30401C455c8398d06F85e4EaB6309f') - ``` - -#### get_allocation(escrow_address) - -Gets the allocation info for the specified escrow. - -* **Parameters:** - **escrow_address** (`str`) – Address of the escrow -* **Return type:** - `Optional`[[`AllocationData`](#human_protocol_sdk.staking.staking_client.AllocationData)] -* **Returns:** - Allocation info if escrow exists, otherwise None -* **Example:** - ```python - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - staking_client = StakingClient(w3) - - allocation = staking_client.get_allocation( - '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - ) - ``` - #### slash(slasher, staker, escrow_address, amount, tx_options=None) Slashes HMT token. diff --git a/docs/sdk/python/human_protocol_sdk.transaction.md b/docs/sdk/python/human_protocol_sdk.transaction.md index 58fb7d7b25..e9e877208c 100644 --- a/docs/sdk/python/human_protocol_sdk.transaction.md +++ b/docs/sdk/python/human_protocol_sdk.transaction.md @@ -8,6 +8,8 @@ both the contracts and subgraph. * [human_protocol_sdk.transaction.transaction_utils module](human_protocol_sdk.transaction.transaction_utils.md) * [Code Example](human_protocol_sdk.transaction.transaction_utils.md#code-example) * [Module](human_protocol_sdk.transaction.transaction_utils.md#module) + * [`InternalTransaction`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.InternalTransaction) + * [`InternalTransaction.__init__()`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.InternalTransaction.__init__) * [`TransactionData`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionData) * [`TransactionData.__init__()`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionData.__init__) * [`TransactionUtils`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtils) diff --git a/docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md b/docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md index ce1a533e1d..2d6bfb9064 100644 --- a/docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md +++ b/docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md @@ -23,11 +23,17 @@ print( ## Module -### *class* human_protocol_sdk.transaction.transaction_utils.TransactionData(chain_id, block, tx_hash, from_address, to_address, timestamp, value, method) +### *class* human_protocol_sdk.transaction.transaction_utils.InternalTransaction(from_address, to_address, value, method, receiver, escrow, token) Bases: `object` -#### \_\_init_\_(chain_id, block, tx_hash, from_address, to_address, timestamp, value, method) +#### \_\_init_\_(from_address, to_address, value, method, receiver, escrow, token) + +### *class* human_protocol_sdk.transaction.transaction_utils.TransactionData(chain_id, block, tx_hash, from_address, to_address, timestamp, value, method, receiver, escrow, token, internal_transactions) + +Bases: `object` + +#### \_\_init_\_(chain_id, block, tx_hash, from_address, to_address, timestamp, value, method, receiver, escrow, token, internal_transactions) ### *class* human_protocol_sdk.transaction.transaction_utils.TransactionUtils diff --git a/docs/sdk/python/human_protocol_sdk.utils.md b/docs/sdk/python/human_protocol_sdk.utils.md index adc9d4cc71..2b4f5d7d81 100644 --- a/docs/sdk/python/human_protocol_sdk.utils.md +++ b/docs/sdk/python/human_protocol_sdk.utils.md @@ -50,13 +50,6 @@ Retrieve the KVStore interface. * **Returns:** The KVStore interface of smart contract. -### human_protocol_sdk.utils.get_reward_pool_interface() - -Retrieve the RewardPool interface. - -* **Returns:** - The RewardPool interface of smart contract. - ### human_protocol_sdk.utils.get_staking_interface() Retrieve the Staking interface. diff --git a/docs/sdk/python/index.md b/docs/sdk/python/index.md index ad9f71ed98..b0c6143ea2 100644 --- a/docs/sdk/python/index.md +++ b/docs/sdk/python/index.md @@ -72,7 +72,6 @@ pip install human-protocol-sdk[agreement] * [`get_factory_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_factory_interface) * [`get_hmt_balance()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_hmt_balance) * [`get_kvstore_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_kvstore_interface) - * [`get_reward_pool_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_reward_pool_interface) * [`get_staking_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_staking_interface) * [`handle_transaction()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.handle_transaction) * [`parse_transfer_transaction()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.parse_transfer_transaction) diff --git a/docs/sdk/typescript/base/classes/BaseEthersClient.md b/docs/sdk/typescript/base/classes/BaseEthersClient.md index 4c7a391fa9..025f3ee132 100644 --- a/docs/sdk/typescript/base/classes/BaseEthersClient.md +++ b/docs/sdk/typescript/base/classes/BaseEthersClient.md @@ -30,7 +30,7 @@ This class is used as a base class for other clients making on-chain calls. The Signer or Provider object to interact with the Ethereum network -• **networkData**: `NetworkData` +• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) The network information required to connect to the contracts @@ -40,17 +40,17 @@ The network information required to connect to the contracts #### Defined in -[base.ts:20](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L20) +[base.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L20) ## Properties ### networkData -> **networkData**: `NetworkData` +> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -60,4 +60,4 @@ The network information required to connect to the contracts #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) diff --git a/docs/sdk/typescript/encryption/classes/Encryption.md b/docs/sdk/typescript/encryption/classes/Encryption.md index f0a3e07b5e..b15ad69cbc 100644 --- a/docs/sdk/typescript/encryption/classes/Encryption.md +++ b/docs/sdk/typescript/encryption/classes/Encryption.md @@ -65,7 +65,7 @@ The private key. #### Defined in -[encryption.ts:52](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L52) +[encryption.ts:52](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L52) ## Methods @@ -117,7 +117,7 @@ const resultMessage = await encription.decrypt('message'); #### Defined in -[encryption.ts:179](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L179) +[encryption.ts:179](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L179) *** @@ -153,7 +153,7 @@ const resultMessage = await encription.sign('message'); #### Defined in -[encryption.ts:216](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L216) +[encryption.ts:216](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L216) *** @@ -218,7 +218,7 @@ const resultMessage = await encription.signAndEncrypt('message', publicKeys); #### Defined in -[encryption.ts:128](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L128) +[encryption.ts:128](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L128) *** @@ -246,4 +246,4 @@ Optional: The passphrase for the private key. #### Defined in -[encryption.ts:63](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L63) +[encryption.ts:63](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L63) diff --git a/docs/sdk/typescript/encryption/classes/EncryptionUtils.md b/docs/sdk/typescript/encryption/classes/EncryptionUtils.md index db254180a5..a42bc83af4 100644 --- a/docs/sdk/typescript/encryption/classes/EncryptionUtils.md +++ b/docs/sdk/typescript/encryption/classes/EncryptionUtils.md @@ -56,6 +56,8 @@ Message to encrypt. • **publicKeys**: `string`[] +Array of public keys to use for encryption. + #### Returns `Promise`\<`string`\> @@ -97,13 +99,13 @@ const result = await EncriptionUtils.encrypt('message', publicKeys); #### Defined in -[encryption.ts:421](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L421) +[encryption.ts:421](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L421) *** ### generateKeyPair() -> `static` **generateKeyPair**(`name`, `email`, `passphrase`): `Promise`\<`IKeyPair`\> +> `static` **generateKeyPair**(`name`, `email`, `passphrase`): `Promise`\<[`IKeyPair`](../../interfaces/interfaces/IKeyPair.md)\> This function generates a key pair for encryption and decryption. @@ -123,7 +125,7 @@ Passphrase to encrypt the private key. Optional. #### Returns -`Promise`\<`IKeyPair`\> +`Promise`\<[`IKeyPair`](../../interfaces/interfaces/IKeyPair.md)\> Key pair generated. @@ -152,7 +154,7 @@ const result = await EncriptionUtils.generateKeyPair(name, email, passphrase); #### Defined in -[encryption.ts:359](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L359) +[encryption.ts:359](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L359) *** @@ -184,7 +186,7 @@ const signedData = await EncriptionUtils.getSignedData('message'); #### Defined in -[encryption.ts:316](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L316) +[encryption.ts:316](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L316) *** @@ -232,7 +234,7 @@ if (isEncrypted) { #### Defined in -[encryption.ts:470](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L470) +[encryption.ts:470](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L470) *** @@ -280,4 +282,4 @@ const result = await EncriptionUtils.verify('message', publicKey); #### Defined in -[encryption.ts:283](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L283) +[encryption.ts:283](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L283) diff --git a/docs/sdk/typescript/enums/README.md b/docs/sdk/typescript/enums/README.md new file mode 100644 index 0000000000..3aad554085 --- /dev/null +++ b/docs/sdk/typescript/enums/README.md @@ -0,0 +1,14 @@ +[**@human-protocol/sdk**](../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../modules.md) / enums + +# enums + +## Index + +### Enumerations + +- [ChainId](enumerations/ChainId.md) +- [OrderDirection](enumerations/OrderDirection.md) diff --git a/docs/sdk/typescript/enums/enumerations/ChainId.md b/docs/sdk/typescript/enums/enumerations/ChainId.md new file mode 100644 index 0000000000..9ddfef832d --- /dev/null +++ b/docs/sdk/typescript/enums/enumerations/ChainId.md @@ -0,0 +1,197 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [enums](../README.md) / ChainId + +# Enumeration: ChainId + +## Enumeration Members + +### ALL + +> **ALL**: `-1` + +#### Defined in + +[enums.ts:2](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L2) + +*** + +### AVALANCHE + +> **AVALANCHE**: `43114` + +#### Defined in + +[enums.ts:15](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L15) + +*** + +### AVALANCHE\_TESTNET + +> **AVALANCHE\_TESTNET**: `43113` + +#### Defined in + +[enums.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L14) + +*** + +### BSC\_MAINNET + +> **BSC\_MAINNET**: `56` + +#### Defined in + +[enums.ts:7](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L7) + +*** + +### BSC\_TESTNET + +> **BSC\_TESTNET**: `97` + +#### Defined in + +[enums.ts:8](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L8) + +*** + +### CELO + +> **CELO**: `42220` + +#### Defined in + +[enums.ts:16](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L16) + +*** + +### CELO\_ALFAJORES + +> **CELO\_ALFAJORES**: `44787` + +#### Defined in + +[enums.ts:17](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L17) + +*** + +### GOERLI + +> **GOERLI**: `5` + +#### Defined in + +[enums.ts:5](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L5) + +*** + +### LOCALHOST + +> **LOCALHOST**: `1338` + +#### Defined in + +[enums.ts:19](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L19) + +*** + +### MAINNET + +> **MAINNET**: `1` + +#### Defined in + +[enums.ts:3](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L3) + +*** + +### MOONBASE\_ALPHA + +> **MOONBASE\_ALPHA**: `1287` + +#### Defined in + +[enums.ts:13](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L13) + +*** + +### MOONBEAM + +> **MOONBEAM**: `1284` + +#### Defined in + +[enums.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L12) + +*** + +### POLYGON + +> **POLYGON**: `137` + +#### Defined in + +[enums.ts:9](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L9) + +*** + +### POLYGON\_AMOY + +> **POLYGON\_AMOY**: `80002` + +#### Defined in + +[enums.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L11) + +*** + +### POLYGON\_MUMBAI + +> **POLYGON\_MUMBAI**: `80001` + +#### Defined in + +[enums.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L10) + +*** + +### RINKEBY + +> **RINKEBY**: `4` + +#### Defined in + +[enums.ts:4](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L4) + +*** + +### SEPOLIA + +> **SEPOLIA**: `11155111` + +#### Defined in + +[enums.ts:6](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L6) + +*** + +### XLAYER + +> **XLAYER**: `196` + +#### Defined in + +[enums.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L20) + +*** + +### XLAYER\_TESTNET + +> **XLAYER\_TESTNET**: `195` + +#### Defined in + +[enums.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L18) diff --git a/docs/sdk/typescript/enums/enumerations/OrderDirection.md b/docs/sdk/typescript/enums/enumerations/OrderDirection.md new file mode 100644 index 0000000000..eb4b89ac14 --- /dev/null +++ b/docs/sdk/typescript/enums/enumerations/OrderDirection.md @@ -0,0 +1,27 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [enums](../README.md) / OrderDirection + +# Enumeration: OrderDirection + +## Enumeration Members + +### ASC + +> **ASC**: `"asc"` + +#### Defined in + +[enums.ts:24](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L24) + +*** + +### DESC + +> **DESC**: `"desc"` + +#### Defined in + +[enums.ts:25](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L25) diff --git a/docs/sdk/typescript/escrow/classes/EscrowClient.md b/docs/sdk/typescript/escrow/classes/EscrowClient.md index d929f464cf..24cab9fbfc 100644 --- a/docs/sdk/typescript/escrow/classes/EscrowClient.md +++ b/docs/sdk/typescript/escrow/classes/EscrowClient.md @@ -92,7 +92,9 @@ const escrowClient = await EscrowClient.build(provider); The Runner object to interact with the Ethereum network -• **networkData**: `NetworkData` +• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) + +The network information required to connect to the Escrow contract #### Returns @@ -104,13 +106,13 @@ The Runner object to interact with the Ethereum network #### Defined in -[escrow.ts:129](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L129) +[escrow.ts:136](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L136) ## Properties ### networkData -> **networkData**: `NetworkData` +> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) #### Inherited from @@ -118,7 +120,7 @@ The Runner object to interact with the Ethereum network #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -132,61 +134,15 @@ The Runner object to interact with the Ethereum network #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) ## Methods -### abort() - -> **abort**(`escrowAddress`, `txOptions`?): `Promise`\<`void`\> - -This function cancels the specified escrow, sends the balance to the canceler and selfdestructs the escrow contract. - -#### Parameters - -• **escrowAddress**: `string` - -Address of the escrow. - -• **txOptions?**: `Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Job Launcher or trusted handler can call it. - -```ts -import { Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY' - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -await escrowClient.abort('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -#### Defined in - -[escrow.ts:837](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L837) - -*** - ### addTrustedHandlers() > **addTrustedHandlers**(`escrowAddress`, `trustedHandlers`, `txOptions`?): `Promise`\<`void`\> -This function sets the status of an escrow to completed. +This function adds an array of addresses to the trusted handlers list. #### Parameters @@ -229,13 +185,13 @@ await escrowClient.addTrustedHandlers('0x62dD51230A30401C455c8398d06F85e4EaB6309 #### Defined in -[escrow.ts:885](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L885) +[escrow.ts:802](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L802) *** ### bulkPayOut() -> **bulkPayOut**(`escrowAddress`, `recipients`, `amounts`, `finalResultsUrl`, `finalResultsHash`, `txOptions`?): `Promise`\<`void`\> +> **bulkPayOut**(`escrowAddress`, `recipients`, `amounts`, `finalResultsUrl`, `finalResultsHash`, `forceComplete`, `txOptions`?): `Promise`\<`void`\> This function pays out the amounts specified to the workers and sets the URL of the final results file. @@ -261,6 +217,10 @@ Final results file url. Final results file hash. +• **forceComplete**: `boolean` = `false` + +Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). + • **txOptions?**: `Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -296,13 +256,13 @@ await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', reci #### Defined in -[escrow.ts:650](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L650) +[escrow.ts:595](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L595) *** ### cancel() -> **cancel**(`escrowAddress`, `txOptions`?): `Promise`\<`EscrowCancel`\> +> **cancel**(`escrowAddress`, `txOptions`?): `Promise`\<[`EscrowCancel`](../../types/type-aliases/EscrowCancel.md)\> This function cancels the specified escrow and sends the balance to the canceler. @@ -318,7 +278,7 @@ Additional transaction parameters (optional, defaults to an empty object). #### Returns -`Promise`\<`EscrowCancel`\> +`Promise`\<[`EscrowCancel`](../../types/type-aliases/EscrowCancel.md)\> Returns the escrow cancellation data including transaction hash and refunded amount. Throws error if any. @@ -342,7 +302,7 @@ await escrowClient.cancel('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); #### Defined in -[escrow.ts:753](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L753) +[escrow.ts:716](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L716) *** @@ -388,74 +348,7 @@ await escrowClient.complete('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); #### Defined in -[escrow.ts:592](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L592) - -*** - -### createAndSetupEscrow() - -> **createAndSetupEscrow**(`tokenAddress`, `trustedHandlers`, `jobRequesterId`, `escrowConfig`): `Promise`\<`string`\> - -This function creates and sets up an escrow. - -#### Parameters - -• **tokenAddress**: `string` - -Token address to use for pay outs. - -• **trustedHandlers**: `string`[] - -Array of addresses that can perform actions on the contract. - -• **jobRequesterId**: `string` - -Job Requester Id - -• **escrowConfig**: `IEscrowConfig` - -Configuration object with escrow settings. - -#### Returns - -`Promise`\<`string`\> - -Returns the address of the escrow created. - -**Code example** - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY' - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -const tokenAddress = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4'; -const trustedHandlers = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; -const jobRequesterId = "job-requester-id"; - -const escrowConfig = { - recordingOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - reputationOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - exchangeOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - recordingOracleFee: bigint.from('10'), - reputationOracleFee: bigint.from('10'), - exchangeOracleFee: bigint.from('10'), - manifestUrl: 'htttp://localhost/manifest.json', - manifestHash: 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079', -}; - -const escrowAddress = await escrowClient.createAndSetupEscrow(tokenAddress, trustedHandlers, jobRequesterId, escrowConfig); -``` - -#### Defined in - -[escrow.ts:415](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L415) +[escrow.ts:536](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L536) *** @@ -512,7 +405,7 @@ const escrowAddress = await escrowClient.createEscrow(tokenAddress, trustedHandl #### Defined in -[escrow.ts:209](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L209) +[escrow.ts:216](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L216) *** @@ -561,7 +454,7 @@ await escrowClient.fund('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); #### Defined in -[escrow.ts:463](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L463) +[escrow.ts:407](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L407) *** @@ -599,7 +492,7 @@ const balance = await escrowClient.getBalance('0x62dD51230A30401C455c8398d06F85e #### Defined in -[escrow.ts:940](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L940) +[escrow.ts:950](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L950) *** @@ -637,7 +530,7 @@ const oracleAddress = await escrowClient.getExchangeOracleAddress('0x62dD51230A3 #### Defined in -[escrow.ts:1320](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1320) +[escrow.ts:1336](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1336) *** @@ -675,7 +568,7 @@ const factoryAddress = await escrowClient.getFactoryAddress('0x62dD51230A30401C4 #### Defined in -[escrow.ts:1358](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1358) +[escrow.ts:1374](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1374) *** @@ -713,7 +606,7 @@ const intemediateResultsUrl = await escrowClient.getIntermediateResultsUrl('0x62 #### Defined in -[escrow.ts:1092](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1092) +[escrow.ts:1108](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1108) *** @@ -751,7 +644,7 @@ const jobLauncherAddress = await escrowClient.getJobLauncherAddress('0x62dD51230 #### Defined in -[escrow.ts:1244](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1244) +[escrow.ts:1260](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1260) *** @@ -789,7 +682,7 @@ const manifestHash = await escrowClient.getManifestHash('0x62dD51230A30401C455c8 #### Defined in -[escrow.ts:978](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L978) +[escrow.ts:994](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L994) *** @@ -827,7 +720,7 @@ const manifestUrl = await escrowClient.getManifestUrl('0x62dD51230A30401C455c839 #### Defined in -[escrow.ts:1016](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1016) +[escrow.ts:1032](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1032) *** @@ -865,7 +758,7 @@ const oracleAddress = await escrowClient.getRecordingOracleAddress('0x62dD51230A #### Defined in -[escrow.ts:1206](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1206) +[escrow.ts:1222](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1222) *** @@ -903,7 +796,7 @@ const oracleAddress = await escrowClient.getReputationOracleAddress('0x62dD51230 #### Defined in -[escrow.ts:1282](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1282) +[escrow.ts:1298](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1298) *** @@ -941,13 +834,13 @@ const resultsUrl = await escrowClient.getResultsUrl('0x62dD51230A30401C455c8398d #### Defined in -[escrow.ts:1054](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1054) +[escrow.ts:1070](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1070) *** ### getStatus() -> **getStatus**(`escrowAddress`): `Promise`\<`EscrowStatus`\> +> **getStatus**(`escrowAddress`): `Promise`\<[`EscrowStatus`](../../types/enumerations/EscrowStatus.md)\> This function returns the current status of the escrow. @@ -959,7 +852,7 @@ Address of the escrow. #### Returns -`Promise`\<`EscrowStatus`\> +`Promise`\<[`EscrowStatus`](../../types/enumerations/EscrowStatus.md)\> Current status of the escrow. @@ -979,7 +872,7 @@ const status = await escrowClient.getStatus('0x62dD51230A30401C455c8398d06F85e4E #### Defined in -[escrow.ts:1168](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1168) +[escrow.ts:1184](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1184) *** @@ -1017,7 +910,7 @@ const tokenAddress = await escrowClient.getTokenAddress('0x62dD51230A30401C455c8 #### Defined in -[escrow.ts:1130](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1130) +[escrow.ts:1146](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1146) *** @@ -1033,7 +926,7 @@ This function sets up the parameters of the escrow. Address of the escrow to set up. -• **escrowConfig**: `IEscrowConfig` +• **escrowConfig**: [`IEscrowConfig`](../../interfaces/interfaces/IEscrowConfig.md) Escrow configuration parameters. @@ -1078,7 +971,7 @@ await escrowClient.setup(escrowAddress, escrowConfig); #### Defined in -[escrow.ts:290](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L290) +[escrow.ts:297](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L297) *** @@ -1132,7 +1025,60 @@ await storeResults.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'h #### Defined in -[escrow.ts:528](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L528) +[escrow.ts:472](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L472) + +*** + +### withdraw() + +> **withdraw**(`escrowAddress`, `tokenAddress`, `txOptions`?): `Promise`\<[`EscrowWithdraw`](../../types/type-aliases/EscrowWithdraw.md)\> + +This function withdraws additional tokens in the escrow to the canceler. + +#### Parameters + +• **escrowAddress**: `string` + +Address of the escrow to withdraw. + +• **tokenAddress**: `string` + +Address of the token to withdraw. + +• **txOptions?**: `Overrides` = `{}` + +Additional transaction parameters (optional, defaults to an empty object). + +#### Returns + +`Promise`\<[`EscrowWithdraw`](../../types/type-aliases/EscrowWithdraw.md)\> + +Returns the escrow withdrawal data including transaction hash and withdrawal amount. Throws error if any. + +**Code example** + +> Only Job Launcher or a trusted handler can call it. + +```ts +import { ethers, Wallet, providers } from 'ethers'; +import { EscrowClient } from '@human-protocol/sdk'; + +const rpcUrl = 'YOUR_RPC_URL'; +const privateKey = 'YOUR_PRIVATE_KEY' + +const provider = new providers.JsonRpcProvider(rpcUrl); +const signer = new Wallet(privateKey, provider); +const escrowClient = await EscrowClient.build(signer); + +await escrowClient.withdraw( + '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4' +); +``` + +#### Defined in + +[escrow.ts:868](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L868) *** @@ -1164,4 +1110,4 @@ Thrown if the network's chainId is not supported #### Defined in -[escrow.ts:147](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L147) +[escrow.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L154) diff --git a/docs/sdk/typescript/escrow/classes/EscrowUtils.md b/docs/sdk/typescript/escrow/classes/EscrowUtils.md index c7926bf18a..4cec75c0b5 100644 --- a/docs/sdk/typescript/escrow/classes/EscrowUtils.md +++ b/docs/sdk/typescript/escrow/classes/EscrowUtils.md @@ -50,7 +50,7 @@ const escrowAddresses = new EscrowUtils.getEscrows({ ### getEscrow() -> `static` **getEscrow**(`chainId`, `escrowAddress`): `Promise`\<`EscrowData`\> +> `static` **getEscrow**(`chainId`, `escrowAddress`): `Promise`\<[`EscrowData`](../../graphql/types/type-aliases/EscrowData.md)\> This function returns the escrow data for a given address. @@ -105,7 +105,7 @@ type EscrowData = { #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) Network in which the escrow has been deployed @@ -115,7 +115,7 @@ Address of the escrow #### Returns -`Promise`\<`EscrowData`\> +`Promise`\<[`EscrowData`](../../graphql/types/type-aliases/EscrowData.md)\> Escrow data @@ -129,13 +129,13 @@ const escrowData = new EscrowUtils.getEscrow(ChainId.POLYGON_AMOY, "0x1234567890 #### Defined in -[escrow.ts:1640](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1640) +[escrow.ts:1656](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1656) *** ### getEscrows() -> `static` **getEscrows**(`filter`): `Promise`\<`EscrowData`[]\> +> `static` **getEscrows**(`filter`): `Promise`\<[`EscrowData`](../../graphql/types/type-aliases/EscrowData.md)[]\> This function returns an array of escrows based on the specified filter parameters. @@ -224,13 +224,13 @@ type EscrowData = { #### Parameters -• **filter**: `IEscrowsFilter` +• **filter**: [`IEscrowsFilter`](../../interfaces/interfaces/IEscrowsFilter.md) Filter parameters. #### Returns -`Promise`\<`EscrowData`[]\> +`Promise`\<[`EscrowData`](../../graphql/types/type-aliases/EscrowData.md)[]\> List of escrows that match the filter. @@ -250,13 +250,13 @@ const escrowDatas = await EscrowUtils.getEscrows(filters); #### Defined in -[escrow.ts:1514](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1514) +[escrow.ts:1530](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1530) *** ### getStatusEvents() -> `static` **getStatusEvents**(`chainId`, `statuses`?, `from`?, `to`?, `launcher`?, `first`?, `skip`?, `orderDirection`?): `Promise`\<`StatusEvent`[]\> +> `static` **getStatusEvents**(`chainId`, `statuses`?, `from`?, `to`?, `launcher`?, `first`?, `skip`?, `orderDirection`?): `Promise`\<[`StatusEvent`](../../graphql/types/type-aliases/StatusEvent.md)[]\> This function returns the status events for a given set of networks within an optional date range. @@ -305,11 +305,11 @@ type Status = { #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) List of network IDs to query for status events. -• **statuses?**: `EscrowStatus`[] +• **statuses?**: [`EscrowStatus`](../../types/enumerations/EscrowStatus.md)[] Optional array of statuses to query for. If not provided, queries for all statuses. @@ -333,13 +333,13 @@ Optional number of transactions per page. Default is 10. Optional number of transactions to skip. Default is 0. -• **orderDirection?**: `OrderDirection` +• **orderDirection?**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) Optional order of the results. Default is DESC. #### Returns -`Promise`\<`StatusEvent`[]\> +`Promise`\<[`StatusEvent`](../../graphql/types/type-aliases/StatusEvent.md)[]\> - Array of status events with their corresponding statuses. @@ -363,4 +363,4 @@ import { ChainId, EscrowUtils, EscrowStatus } from '@human-protocol/sdk'; #### Defined in -[escrow.ts:1738](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1738) +[escrow.ts:1754](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1754) diff --git a/docs/sdk/typescript/graphql/types/README.md b/docs/sdk/typescript/graphql/types/README.md new file mode 100644 index 0000000000..03598a4471 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/README.md @@ -0,0 +1,34 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / graphql/types + +# graphql/types + +## Index + +### Type Aliases + +- [DailyEscrowData](type-aliases/DailyEscrowData.md) +- [DailyHMTData](type-aliases/DailyHMTData.md) +- [DailyPaymentData](type-aliases/DailyPaymentData.md) +- [DailyTaskData](type-aliases/DailyTaskData.md) +- [DailyWorkerData](type-aliases/DailyWorkerData.md) +- [EscrowData](type-aliases/EscrowData.md) +- [EscrowStatistics](type-aliases/EscrowStatistics.md) +- [EscrowStatisticsData](type-aliases/EscrowStatisticsData.md) +- [EventDayData](type-aliases/EventDayData.md) +- [HMTHolder](type-aliases/HMTHolder.md) +- [HMTHolderData](type-aliases/HMTHolderData.md) +- [HMTStatistics](type-aliases/HMTStatistics.md) +- [HMTStatisticsData](type-aliases/HMTStatisticsData.md) +- [IMData](type-aliases/IMData.md) +- [IMDataEntity](type-aliases/IMDataEntity.md) +- [KVStoreData](type-aliases/KVStoreData.md) +- [PaymentStatistics](type-aliases/PaymentStatistics.md) +- [PayoutData](type-aliases/PayoutData.md) +- [RewardAddedEventData](type-aliases/RewardAddedEventData.md) +- [StatusEvent](type-aliases/StatusEvent.md) +- [TaskStatistics](type-aliases/TaskStatistics.md) +- [WorkerStatistics](type-aliases/WorkerStatistics.md) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md new file mode 100644 index 0000000000..ce76bb4093 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md @@ -0,0 +1,39 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / DailyEscrowData + +# Type Alias: DailyEscrowData + +> **DailyEscrowData**: `object` + +## Type declaration + +### escrowsCancelled + +> **escrowsCancelled**: `number` + +### escrowsPaid + +> **escrowsPaid**: `number` + +### escrowsPending + +> **escrowsPending**: `number` + +### escrowsSolved + +> **escrowsSolved**: `number` + +### escrowsTotal + +> **escrowsTotal**: `number` + +### timestamp + +> **timestamp**: `Date` + +## Defined in + +[graphql/types.ts:83](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L83) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md new file mode 100644 index 0000000000..87bc73cdc7 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md @@ -0,0 +1,35 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / DailyHMTData + +# Type Alias: DailyHMTData + +> **DailyHMTData**: `object` + +## Type declaration + +### dailyUniqueReceivers + +> **dailyUniqueReceivers**: `number` + +### dailyUniqueSenders + +> **dailyUniqueSenders**: `number` + +### timestamp + +> **timestamp**: `Date` + +### totalTransactionAmount + +> **totalTransactionAmount**: `bigint` + +### totalTransactionCount + +> **totalTransactionCount**: `number` + +## Defined in + +[graphql/types.ts:127](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L127) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md new file mode 100644 index 0000000000..c0ced96a7b --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md @@ -0,0 +1,31 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / DailyPaymentData + +# Type Alias: DailyPaymentData + +> **DailyPaymentData**: `object` + +## Type declaration + +### averageAmountPerWorker + +> **averageAmountPerWorker**: `bigint` + +### timestamp + +> **timestamp**: `Date` + +### totalAmountPaid + +> **totalAmountPaid**: `bigint` + +### totalCount + +> **totalCount**: `number` + +## Defined in + +[graphql/types.ts:106](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L106) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md new file mode 100644 index 0000000000..d98df89ab9 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md @@ -0,0 +1,27 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / DailyTaskData + +# Type Alias: DailyTaskData + +> **DailyTaskData**: `object` + +## Type declaration + +### tasksSolved + +> **tasksSolved**: `number` + +### tasksTotal + +> **tasksTotal**: `number` + +### timestamp + +> **timestamp**: `Date` + +## Defined in + +[graphql/types.ts:148](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L148) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md new file mode 100644 index 0000000000..fbc5f60316 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md @@ -0,0 +1,23 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / DailyWorkerData + +# Type Alias: DailyWorkerData + +> **DailyWorkerData**: `object` + +## Type declaration + +### activeWorkers + +> **activeWorkers**: `number` + +### timestamp + +> **timestamp**: `Date` + +## Defined in + +[graphql/types.ts:97](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L97) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md new file mode 100644 index 0000000000..9d06032f8d --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md @@ -0,0 +1,91 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / EscrowData + +# Type Alias: EscrowData + +> **EscrowData**: `object` + +## Type declaration + +### address + +> **address**: `string` + +### amountPaid + +> **amountPaid**: `string` + +### balance + +> **balance**: `string` + +### chainId + +> **chainId**: `number` + +### count + +> **count**: `string` + +### createdAt + +> **createdAt**: `string` + +### exchangeOracle? + +> `optional` **exchangeOracle**: `string` + +### factoryAddress + +> **factoryAddress**: `string` + +### finalResultsUrl? + +> `optional` **finalResultsUrl**: `string` + +### id + +> **id**: `string` + +### intermediateResultsUrl? + +> `optional` **intermediateResultsUrl**: `string` + +### launcher + +> **launcher**: `string` + +### manifestHash? + +> `optional` **manifestHash**: `string` + +### manifestUrl? + +> `optional` **manifestUrl**: `string` + +### recordingOracle? + +> `optional` **recordingOracle**: `string` + +### reputationOracle? + +> `optional` **reputationOracle**: `string` + +### status + +> **status**: `string` + +### token + +> **token**: `string` + +### totalFundedAmount + +> **totalFundedAmount**: `string` + +## Defined in + +[graphql/types.ts:3](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L3) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md new file mode 100644 index 0000000000..d8181e5caf --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md @@ -0,0 +1,23 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / EscrowStatistics + +# Type Alias: EscrowStatistics + +> **EscrowStatistics**: `object` + +## Type declaration + +### dailyEscrowsData + +> **dailyEscrowsData**: [`DailyEscrowData`](DailyEscrowData.md)[] + +### totalEscrows + +> **totalEscrows**: `number` + +## Defined in + +[graphql/types.ts:92](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L92) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md new file mode 100644 index 0000000000..0e41420d7b --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md @@ -0,0 +1,55 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / EscrowStatisticsData + +# Type Alias: EscrowStatisticsData + +> **EscrowStatisticsData**: `object` + +## Type declaration + +### bulkPayoutEventCount + +> **bulkPayoutEventCount**: `string` + +### cancelledStatusEventCount + +> **cancelledStatusEventCount**: `string` + +### completedStatusEventCount + +> **completedStatusEventCount**: `string` + +### fundEventCount + +> **fundEventCount**: `string` + +### paidStatusEventCount + +> **paidStatusEventCount**: `string` + +### partialStatusEventCount + +> **partialStatusEventCount**: `string` + +### pendingStatusEventCount + +> **pendingStatusEventCount**: `string` + +### storeResultsEventCount + +> **storeResultsEventCount**: `string` + +### totalEscrowCount + +> **totalEscrowCount**: `string` + +### totalEventCount + +> **totalEventCount**: `string` + +## Defined in + +[graphql/types.ts:42](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L42) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md b/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md new file mode 100644 index 0000000000..0dc23fc21b --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md @@ -0,0 +1,87 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / EventDayData + +# Type Alias: EventDayData + +> **EventDayData**: `object` + +## Type declaration + +### dailyBulkPayoutEventCount + +> **dailyBulkPayoutEventCount**: `string` + +### dailyCancelledStatusEventCount + +> **dailyCancelledStatusEventCount**: `string` + +### dailyCompletedStatusEventCount + +> **dailyCompletedStatusEventCount**: `string` + +### dailyEscrowCount + +> **dailyEscrowCount**: `string` + +### dailyFundEventCount + +> **dailyFundEventCount**: `string` + +### dailyHMTTransferAmount + +> **dailyHMTTransferAmount**: `string` + +### dailyHMTTransferCount + +> **dailyHMTTransferCount**: `string` + +### dailyPaidStatusEventCount + +> **dailyPaidStatusEventCount**: `string` + +### dailyPartialStatusEventCount + +> **dailyPartialStatusEventCount**: `string` + +### dailyPayoutAmount + +> **dailyPayoutAmount**: `string` + +### dailyPayoutCount + +> **dailyPayoutCount**: `string` + +### dailyPendingStatusEventCount + +> **dailyPendingStatusEventCount**: `string` + +### dailyStoreResultsEventCount + +> **dailyStoreResultsEventCount**: `string` + +### dailyTotalEventCount + +> **dailyTotalEventCount**: `string` + +### dailyUniqueReceivers + +> **dailyUniqueReceivers**: `string` + +### dailyUniqueSenders + +> **dailyUniqueSenders**: `string` + +### dailyWorkerCount + +> **dailyWorkerCount**: `string` + +### timestamp + +> **timestamp**: `string` + +## Defined in + +[graphql/types.ts:55](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L55) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md new file mode 100644 index 0000000000..c670fa9a86 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md @@ -0,0 +1,23 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / HMTHolder + +# Type Alias: HMTHolder + +> **HMTHolder**: `object` + +## Type declaration + +### address + +> **address**: `string` + +### balance + +> **balance**: `bigint` + +## Defined in + +[graphql/types.ts:122](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L122) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md new file mode 100644 index 0000000000..d4bbc27612 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md @@ -0,0 +1,23 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / HMTHolderData + +# Type Alias: HMTHolderData + +> **HMTHolderData**: `object` + +## Type declaration + +### address + +> **address**: `string` + +### balance + +> **balance**: `string` + +## Defined in + +[graphql/types.ts:117](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L117) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md new file mode 100644 index 0000000000..6b3c091d07 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md @@ -0,0 +1,27 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / HMTStatistics + +# Type Alias: HMTStatistics + +> **HMTStatistics**: `object` + +## Type declaration + +### totalHolders + +> **totalHolders**: `number` + +### totalTransferAmount + +> **totalTransferAmount**: `bigint` + +### totalTransferCount + +> **totalTransferCount**: `number` + +## Defined in + +[graphql/types.ts:135](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L135) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md new file mode 100644 index 0000000000..294b5b1644 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md @@ -0,0 +1,39 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / HMTStatisticsData + +# Type Alias: HMTStatisticsData + +> **HMTStatisticsData**: `object` + +## Type declaration + +### holders + +> **holders**: `string` + +### totalApprovalEventCount + +> **totalApprovalEventCount**: `string` + +### totalBulkApprovalEventCount + +> **totalBulkApprovalEventCount**: `string` + +### totalBulkTransferEventCount + +> **totalBulkTransferEventCount**: `string` + +### totalTransferEventCount + +> **totalTransferEventCount**: `string` + +### totalValueTransfered + +> **totalValueTransfered**: `string` + +## Defined in + +[graphql/types.ts:33](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L33) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/IMData.md b/docs/sdk/typescript/graphql/types/type-aliases/IMData.md new file mode 100644 index 0000000000..a9a537a0fd --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/IMData.md @@ -0,0 +1,13 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / IMData + +# Type Alias: IMData + +> **IMData**: `Record`\<`string`, [`IMDataEntity`](IMDataEntity.md)\> + +## Defined in + +[graphql/types.ts:146](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L146) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md b/docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md new file mode 100644 index 0000000000..5ee027f977 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md @@ -0,0 +1,23 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / IMDataEntity + +# Type Alias: IMDataEntity + +> **IMDataEntity**: `object` + +## Type declaration + +### served + +> **served**: `number` + +### solved + +> **solved**: `number` + +## Defined in + +[graphql/types.ts:141](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L141) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md b/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md new file mode 100644 index 0000000000..acb5759c07 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md @@ -0,0 +1,39 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / KVStoreData + +# Type Alias: KVStoreData + +> **KVStoreData**: `object` + +## Type declaration + +### address + +> **address**: `string` + +### block + +> **block**: `number` + +### id + +> **id**: `string` + +### key + +> **key**: `string` + +### timestamp + +> **timestamp**: `Date` + +### value + +> **value**: `string` + +## Defined in + +[graphql/types.ts:165](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L165) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md new file mode 100644 index 0000000000..481d9804f2 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md @@ -0,0 +1,19 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / PaymentStatistics + +# Type Alias: PaymentStatistics + +> **PaymentStatistics**: `object` + +## Type declaration + +### dailyPaymentsData + +> **dailyPaymentsData**: [`DailyPaymentData`](DailyPaymentData.md)[] + +## Defined in + +[graphql/types.ts:113](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L113) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md b/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md new file mode 100644 index 0000000000..09233b84e7 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md @@ -0,0 +1,35 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / PayoutData + +# Type Alias: PayoutData + +> **PayoutData**: `object` + +## Type declaration + +### amount + +> **amount**: `string` + +### createdAt + +> **createdAt**: `string` + +### escrowAddress + +> **escrowAddress**: `string` + +### id + +> **id**: `string` + +### recipient + +> **recipient**: `string` + +## Defined in + +[graphql/types.ts:25](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L25) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md b/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md new file mode 100644 index 0000000000..ecaf6b5230 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md @@ -0,0 +1,31 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / RewardAddedEventData + +# Type Alias: RewardAddedEventData + +> **RewardAddedEventData**: `object` + +## Type declaration + +### amount + +> **amount**: `string` + +### escrowAddress + +> **escrowAddress**: `string` + +### slasher + +> **slasher**: `string` + +### staker + +> **staker**: `string` + +## Defined in + +[graphql/types.ts:76](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L76) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md b/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md new file mode 100644 index 0000000000..8e61dd6cf1 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md @@ -0,0 +1,31 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / StatusEvent + +# Type Alias: StatusEvent + +> **StatusEvent**: `object` + +## Type declaration + +### chainId + +> **chainId**: [`ChainId`](../../../enums/enumerations/ChainId.md) + +### escrowAddress + +> **escrowAddress**: `string` + +### status + +> **status**: `string` + +### timestamp + +> **timestamp**: `number` + +## Defined in + +[graphql/types.ts:158](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L158) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md new file mode 100644 index 0000000000..d0b80fa355 --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md @@ -0,0 +1,19 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / TaskStatistics + +# Type Alias: TaskStatistics + +> **TaskStatistics**: `object` + +## Type declaration + +### dailyTasksData + +> **dailyTasksData**: [`DailyTaskData`](DailyTaskData.md)[] + +## Defined in + +[graphql/types.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L154) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md new file mode 100644 index 0000000000..f2531743df --- /dev/null +++ b/docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md @@ -0,0 +1,19 @@ +[**@human-protocol/sdk**](../../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / WorkerStatistics + +# Type Alias: WorkerStatistics + +> **WorkerStatistics**: `object` + +## Type declaration + +### dailyWorkersData + +> **dailyWorkersData**: [`DailyWorkerData`](DailyWorkerData.md)[] + +## Defined in + +[graphql/types.ts:102](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L102) diff --git a/docs/sdk/typescript/interfaces/README.md b/docs/sdk/typescript/interfaces/README.md new file mode 100644 index 0000000000..d499b126ba --- /dev/null +++ b/docs/sdk/typescript/interfaces/README.md @@ -0,0 +1,31 @@ +[**@human-protocol/sdk**](../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../modules.md) / interfaces + +# interfaces + +## Index + +### Interfaces + +- [IEscrowConfig](interfaces/IEscrowConfig.md) +- [IEscrowsFilter](interfaces/IEscrowsFilter.md) +- [IHMTHoldersParams](interfaces/IHMTHoldersParams.md) +- [IKeyPair](interfaces/IKeyPair.md) +- [IKVStore](interfaces/IKVStore.md) +- [ILeader](interfaces/ILeader.md) +- [ILeadersFilter](interfaces/ILeadersFilter.md) +- [ILeaderSubgraph](interfaces/ILeaderSubgraph.md) +- [InternalTransaction](interfaces/InternalTransaction.md) +- [IOperator](interfaces/IOperator.md) +- [IOperatorSubgraph](interfaces/IOperatorSubgraph.md) +- [IPagination](interfaces/IPagination.md) +- [IPayoutFilter](interfaces/IPayoutFilter.md) +- [IReputationNetwork](interfaces/IReputationNetwork.md) +- [IReputationNetworkSubgraph](interfaces/IReputationNetworkSubgraph.md) +- [IReward](interfaces/IReward.md) +- [IStatisticsFilter](interfaces/IStatisticsFilter.md) +- [ITransaction](interfaces/ITransaction.md) +- [ITransactionsFilter](interfaces/ITransactionsFilter.md) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md new file mode 100644 index 0000000000..c1ef061547 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md @@ -0,0 +1,87 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IEscrowConfig + +# Interface: IEscrowConfig + +## Properties + +### exchangeOracle + +> **exchangeOracle**: `string` + +#### Defined in + +[interfaces.ts:81](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L81) + +*** + +### exchangeOracleFee + +> **exchangeOracleFee**: `bigint` + +#### Defined in + +[interfaces.ts:84](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L84) + +*** + +### manifestHash + +> **manifestHash**: `string` + +#### Defined in + +[interfaces.ts:86](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L86) + +*** + +### manifestUrl + +> **manifestUrl**: `string` + +#### Defined in + +[interfaces.ts:85](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L85) + +*** + +### recordingOracle + +> **recordingOracle**: `string` + +#### Defined in + +[interfaces.ts:79](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L79) + +*** + +### recordingOracleFee + +> **recordingOracleFee**: `bigint` + +#### Defined in + +[interfaces.ts:82](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L82) + +*** + +### reputationOracle + +> **reputationOracle**: `string` + +#### Defined in + +[interfaces.ts:80](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L80) + +*** + +### reputationOracleFee + +> **reputationOracleFee**: `bigint` + +#### Defined in + +[interfaces.ts:83](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L83) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md new file mode 100644 index 0000000000..508bce135a --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md @@ -0,0 +1,143 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IEscrowsFilter + +# Interface: IEscrowsFilter + +## Extends + +- [`IPagination`](IPagination.md) + +## Properties + +### chainId + +> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) + +#### Defined in + +[interfaces.ts:75](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L75) + +*** + +### exchangeOracle? + +> `optional` **exchangeOracle**: `string` + +#### Defined in + +[interfaces.ts:70](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L70) + +*** + +### first? + +> `optional` **first**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`first`](IPagination.md#first) + +#### Defined in + +[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) + +*** + +### from? + +> `optional` **from**: `Date` + +#### Defined in + +[interfaces.ts:73](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L73) + +*** + +### jobRequesterId? + +> `optional` **jobRequesterId**: `string` + +#### Defined in + +[interfaces.ts:71](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L71) + +*** + +### launcher? + +> `optional` **launcher**: `string` + +#### Defined in + +[interfaces.ts:67](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L67) + +*** + +### orderDirection? + +> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) + +#### Inherited from + +[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) + +#### Defined in + +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) + +*** + +### recordingOracle? + +> `optional` **recordingOracle**: `string` + +#### Defined in + +[interfaces.ts:69](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L69) + +*** + +### reputationOracle? + +> `optional` **reputationOracle**: `string` + +#### Defined in + +[interfaces.ts:68](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L68) + +*** + +### skip? + +> `optional` **skip**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) + +#### Defined in + +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) + +*** + +### status? + +> `optional` **status**: [`EscrowStatus`](../../types/enumerations/EscrowStatus.md) + +#### Defined in + +[interfaces.ts:72](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L72) + +*** + +### to? + +> `optional` **to**: `Date` + +#### Defined in + +[interfaces.ts:74](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L74) diff --git a/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md b/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md new file mode 100644 index 0000000000..c9b5533d93 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md @@ -0,0 +1,63 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IHMTHoldersParams + +# Interface: IHMTHoldersParams + +## Extends + +- [`IPagination`](IPagination.md) + +## Properties + +### address? + +> `optional` **address**: `string` + +#### Defined in + +[interfaces.ts:102](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L102) + +*** + +### first? + +> `optional` **first**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`first`](IPagination.md#first) + +#### Defined in + +[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) + +*** + +### orderDirection? + +> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) + +#### Inherited from + +[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) + +#### Defined in + +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) + +*** + +### skip? + +> `optional` **skip**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) + +#### Defined in + +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) diff --git a/docs/sdk/typescript/interfaces/interfaces/IKVStore.md b/docs/sdk/typescript/interfaces/interfaces/IKVStore.md new file mode 100644 index 0000000000..377dc0e1a0 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IKVStore.md @@ -0,0 +1,27 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IKVStore + +# Interface: IKVStore + +## Properties + +### key + +> **key**: `string` + +#### Defined in + +[interfaces.ts:113](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L113) + +*** + +### value + +> **value**: `string` + +#### Defined in + +[interfaces.ts:114](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L114) diff --git a/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md b/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md new file mode 100644 index 0000000000..366d9b9dcc --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md @@ -0,0 +1,47 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IKeyPair + +# Interface: IKeyPair + +## Properties + +### passphrase + +> **passphrase**: `string` + +#### Defined in + +[interfaces.ts:92](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L92) + +*** + +### privateKey + +> **privateKey**: `string` + +#### Defined in + +[interfaces.ts:90](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L90) + +*** + +### publicKey + +> **publicKey**: `string` + +#### Defined in + +[interfaces.ts:91](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L91) + +*** + +### revocationCertificate? + +> `optional` **revocationCertificate**: `string` + +#### Defined in + +[interfaces.ts:93](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L93) diff --git a/docs/sdk/typescript/interfaces/interfaces/ILeader.md b/docs/sdk/typescript/interfaces/interfaces/ILeader.md new file mode 100644 index 0000000000..b3664a5ab8 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/ILeader.md @@ -0,0 +1,197 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ILeader + +# Interface: ILeader + +## Properties + +### address + +> **address**: `string` + +#### Defined in + +[interfaces.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L12) + +*** + +### amountJobsProcessed + +> **amountJobsProcessed**: `bigint` + +#### Defined in + +[interfaces.ts:19](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L19) + +*** + +### amountLocked + +> **amountLocked**: `bigint` + +#### Defined in + +[interfaces.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L14) + +*** + +### amountSlashed + +> **amountSlashed**: `bigint` + +#### Defined in + +[interfaces.ts:17](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L17) + +*** + +### amountStaked + +> **amountStaked**: `bigint` + +#### Defined in + +[interfaces.ts:13](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L13) + +*** + +### amountWithdrawn + +> **amountWithdrawn**: `bigint` + +#### Defined in + +[interfaces.ts:16](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L16) + +*** + +### chainId + +> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) + +#### Defined in + +[interfaces.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L11) + +*** + +### fee? + +> `optional` **fee**: `bigint` + +#### Defined in + +[interfaces.ts:21](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L21) + +*** + +### id + +> **id**: `string` + +#### Defined in + +[interfaces.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L10) + +*** + +### jobTypes? + +> `optional` **jobTypes**: `string`[] + +#### Defined in + +[interfaces.ts:25](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L25) + +*** + +### lockedUntilTimestamp + +> **lockedUntilTimestamp**: `bigint` + +#### Defined in + +[interfaces.ts:15](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L15) + +*** + +### publicKey? + +> `optional` **publicKey**: `string` + +#### Defined in + +[interfaces.ts:22](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L22) + +*** + +### registrationInstructions? + +> `optional` **registrationInstructions**: `string` + +#### Defined in + +[interfaces.ts:27](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L27) + +*** + +### registrationNeeded? + +> `optional` **registrationNeeded**: `boolean` + +#### Defined in + +[interfaces.ts:26](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L26) + +*** + +### reputationNetworks? + +> `optional` **reputationNetworks**: `string`[] + +#### Defined in + +[interfaces.ts:28](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L28) + +*** + +### reward + +> **reward**: `bigint` + +#### Defined in + +[interfaces.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L18) + +*** + +### role? + +> `optional` **role**: `string` + +#### Defined in + +[interfaces.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L20) + +*** + +### url? + +> `optional` **url**: `string` + +#### Defined in + +[interfaces.ts:24](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L24) + +*** + +### webhookUrl? + +> `optional` **webhookUrl**: `string` + +#### Defined in + +[interfaces.ts:23](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L23) diff --git a/docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md b/docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md new file mode 100644 index 0000000000..674be64789 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md @@ -0,0 +1,269 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ILeaderSubgraph + +# Interface: ILeaderSubgraph + +## Extends + +- `Omit`\<[`ILeader`](ILeader.md), `"jobTypes"` \| `"reputationNetworks"`\> + +## Properties + +### address + +> **address**: `string` + +#### Inherited from + +`Omit.address` + +#### Defined in + +[interfaces.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L12) + +*** + +### amountJobsProcessed + +> **amountJobsProcessed**: `bigint` + +#### Inherited from + +`Omit.amountJobsProcessed` + +#### Defined in + +[interfaces.ts:19](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L19) + +*** + +### amountLocked + +> **amountLocked**: `bigint` + +#### Inherited from + +`Omit.amountLocked` + +#### Defined in + +[interfaces.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L14) + +*** + +### amountSlashed + +> **amountSlashed**: `bigint` + +#### Inherited from + +`Omit.amountSlashed` + +#### Defined in + +[interfaces.ts:17](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L17) + +*** + +### amountStaked + +> **amountStaked**: `bigint` + +#### Inherited from + +`Omit.amountStaked` + +#### Defined in + +[interfaces.ts:13](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L13) + +*** + +### amountWithdrawn + +> **amountWithdrawn**: `bigint` + +#### Inherited from + +`Omit.amountWithdrawn` + +#### Defined in + +[interfaces.ts:16](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L16) + +*** + +### chainId + +> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) + +#### Inherited from + +`Omit.chainId` + +#### Defined in + +[interfaces.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L11) + +*** + +### fee? + +> `optional` **fee**: `bigint` + +#### Inherited from + +`Omit.fee` + +#### Defined in + +[interfaces.ts:21](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L21) + +*** + +### id + +> **id**: `string` + +#### Inherited from + +`Omit.id` + +#### Defined in + +[interfaces.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L10) + +*** + +### jobTypes? + +> `optional` **jobTypes**: `string` + +#### Defined in + +[interfaces.ts:33](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L33) + +*** + +### lockedUntilTimestamp + +> **lockedUntilTimestamp**: `bigint` + +#### Inherited from + +`Omit.lockedUntilTimestamp` + +#### Defined in + +[interfaces.ts:15](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L15) + +*** + +### publicKey? + +> `optional` **publicKey**: `string` + +#### Inherited from + +`Omit.publicKey` + +#### Defined in + +[interfaces.ts:22](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L22) + +*** + +### registrationInstructions? + +> `optional` **registrationInstructions**: `string` + +#### Inherited from + +`Omit.registrationInstructions` + +#### Defined in + +[interfaces.ts:27](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L27) + +*** + +### registrationNeeded? + +> `optional` **registrationNeeded**: `boolean` + +#### Inherited from + +`Omit.registrationNeeded` + +#### Defined in + +[interfaces.ts:26](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L26) + +*** + +### reputationNetworks? + +> `optional` **reputationNetworks**: `object`[] + +#### Defined in + +[interfaces.ts:34](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L34) + +*** + +### reward + +> **reward**: `bigint` + +#### Inherited from + +`Omit.reward` + +#### Defined in + +[interfaces.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L18) + +*** + +### role? + +> `optional` **role**: `string` + +#### Inherited from + +`Omit.role` + +#### Defined in + +[interfaces.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L20) + +*** + +### url? + +> `optional` **url**: `string` + +#### Inherited from + +`Omit.url` + +#### Defined in + +[interfaces.ts:24](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L24) + +*** + +### webhookUrl? + +> `optional` **webhookUrl**: `string` + +#### Inherited from + +`Omit.webhookUrl` + +#### Defined in + +[interfaces.ts:23](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L23) diff --git a/docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md b/docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md new file mode 100644 index 0000000000..ff63886a6f --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md @@ -0,0 +1,27 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ILeadersFilter + +# Interface: ILeadersFilter + +## Properties + +### chainId + +> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) + +#### Defined in + +[interfaces.ts:38](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L38) + +*** + +### role? + +> `optional` **role**: `string` + +#### Defined in + +[interfaces.ts:39](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L39) diff --git a/docs/sdk/typescript/interfaces/interfaces/IOperator.md b/docs/sdk/typescript/interfaces/interfaces/IOperator.md new file mode 100644 index 0000000000..4225706e07 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IOperator.md @@ -0,0 +1,67 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IOperator + +# Interface: IOperator + +## Properties + +### address + +> **address**: `string` + +#### Defined in + +[interfaces.ts:54](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L54) + +*** + +### jobTypes? + +> `optional` **jobTypes**: `string`[] + +#### Defined in + +[interfaces.ts:57](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L57) + +*** + +### registrationInstructions? + +> `optional` **registrationInstructions**: `string` + +#### Defined in + +[interfaces.ts:59](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L59) + +*** + +### registrationNeeded? + +> `optional` **registrationNeeded**: `boolean` + +#### Defined in + +[interfaces.ts:58](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L58) + +*** + +### role? + +> `optional` **role**: `string` + +#### Defined in + +[interfaces.ts:55](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L55) + +*** + +### url? + +> `optional` **url**: `string` + +#### Defined in + +[interfaces.ts:56](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L56) diff --git a/docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md b/docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md new file mode 100644 index 0000000000..1d4de67f0f --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md @@ -0,0 +1,91 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IOperatorSubgraph + +# Interface: IOperatorSubgraph + +## Extends + +- `Omit`\<[`IOperator`](IOperator.md), `"jobTypes"`\> + +## Properties + +### address + +> **address**: `string` + +#### Inherited from + +`Omit.address` + +#### Defined in + +[interfaces.ts:54](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L54) + +*** + +### jobTypes? + +> `optional` **jobTypes**: `string` + +#### Defined in + +[interfaces.ts:63](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L63) + +*** + +### registrationInstructions? + +> `optional` **registrationInstructions**: `string` + +#### Inherited from + +`Omit.registrationInstructions` + +#### Defined in + +[interfaces.ts:59](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L59) + +*** + +### registrationNeeded? + +> `optional` **registrationNeeded**: `boolean` + +#### Inherited from + +`Omit.registrationNeeded` + +#### Defined in + +[interfaces.ts:58](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L58) + +*** + +### role? + +> `optional` **role**: `string` + +#### Inherited from + +`Omit.role` + +#### Defined in + +[interfaces.ts:55](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L55) + +*** + +### url? + +> `optional` **url**: `string` + +#### Inherited from + +`Omit.url` + +#### Defined in + +[interfaces.ts:56](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L56) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPagination.md b/docs/sdk/typescript/interfaces/interfaces/IPagination.md new file mode 100644 index 0000000000..131d487a00 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IPagination.md @@ -0,0 +1,44 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IPagination + +# Interface: IPagination + +## Extended by + +- [`IEscrowsFilter`](IEscrowsFilter.md) +- [`IStatisticsFilter`](IStatisticsFilter.md) +- [`IHMTHoldersParams`](IHMTHoldersParams.md) +- [`ITransactionsFilter`](ITransactionsFilter.md) + +## Properties + +### first? + +> `optional` **first**: `number` + +#### Defined in + +[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) + +*** + +### orderDirection? + +> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) + +#### Defined in + +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) + +*** + +### skip? + +> `optional` **skip**: `number` + +#### Defined in + +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md b/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md new file mode 100644 index 0000000000..f36a3f7b4f --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md @@ -0,0 +1,47 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IPayoutFilter + +# Interface: IPayoutFilter + +## Properties + +### escrowAddress? + +> `optional` **escrowAddress**: `string` + +#### Defined in + +[interfaces.ts:106](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L106) + +*** + +### from? + +> `optional` **from**: `Date` + +#### Defined in + +[interfaces.ts:108](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L108) + +*** + +### recipient? + +> `optional` **recipient**: `string` + +#### Defined in + +[interfaces.ts:107](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L107) + +*** + +### to? + +> `optional` **to**: `Date` + +#### Defined in + +[interfaces.ts:109](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L109) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md b/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md new file mode 100644 index 0000000000..f4ea07f386 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md @@ -0,0 +1,37 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IReputationNetwork + +# Interface: IReputationNetwork + +## Properties + +### address + +> **address**: `string` + +#### Defined in + +[interfaces.ts:44](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L44) + +*** + +### id + +> **id**: `string` + +#### Defined in + +[interfaces.ts:43](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L43) + +*** + +### operators + +> **operators**: [`IOperator`](IOperator.md)[] + +#### Defined in + +[interfaces.ts:45](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L45) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md b/docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md new file mode 100644 index 0000000000..e67aa3ef0f --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md @@ -0,0 +1,49 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IReputationNetworkSubgraph + +# Interface: IReputationNetworkSubgraph + +## Extends + +- `Omit`\<[`IReputationNetwork`](IReputationNetwork.md), `"operators"`\> + +## Properties + +### address + +> **address**: `string` + +#### Inherited from + +`Omit.address` + +#### Defined in + +[interfaces.ts:44](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L44) + +*** + +### id + +> **id**: `string` + +#### Inherited from + +`Omit.id` + +#### Defined in + +[interfaces.ts:43](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L43) + +*** + +### operators + +> **operators**: [`IOperatorSubgraph`](IOperatorSubgraph.md)[] + +#### Defined in + +[interfaces.ts:50](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L50) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReward.md b/docs/sdk/typescript/interfaces/interfaces/IReward.md new file mode 100644 index 0000000000..2669959801 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IReward.md @@ -0,0 +1,27 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IReward + +# Interface: IReward + +## Properties + +### amount + +> **amount**: `bigint` + +#### Defined in + +[interfaces.ts:6](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L6) + +*** + +### escrowAddress + +> **escrowAddress**: `string` + +#### Defined in + +[interfaces.ts:5](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L5) diff --git a/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md b/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md new file mode 100644 index 0000000000..35e738be6d --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md @@ -0,0 +1,73 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IStatisticsFilter + +# Interface: IStatisticsFilter + +## Extends + +- [`IPagination`](IPagination.md) + +## Properties + +### first? + +> `optional` **first**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`first`](IPagination.md#first) + +#### Defined in + +[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) + +*** + +### from? + +> `optional` **from**: `Date` + +#### Defined in + +[interfaces.ts:97](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L97) + +*** + +### orderDirection? + +> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) + +#### Inherited from + +[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) + +#### Defined in + +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) + +*** + +### skip? + +> `optional` **skip**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) + +#### Defined in + +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) + +*** + +### to? + +> `optional` **to**: `Date` + +#### Defined in + +[interfaces.ts:98](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L98) diff --git a/docs/sdk/typescript/interfaces/interfaces/ITransaction.md b/docs/sdk/typescript/interfaces/interfaces/ITransaction.md new file mode 100644 index 0000000000..f03ce6a4e2 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/ITransaction.md @@ -0,0 +1,117 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ITransaction + +# Interface: ITransaction + +## Properties + +### block + +> **block**: `bigint` + +#### Defined in + +[interfaces.ts:128](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L128) + +*** + +### escrow? + +> `optional` **escrow**: `string` + +#### Defined in + +[interfaces.ts:136](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L136) + +*** + +### from + +> **from**: `string` + +#### Defined in + +[interfaces.ts:130](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L130) + +*** + +### internalTransactions + +> **internalTransactions**: [`InternalTransaction`](InternalTransaction.md)[] + +#### Defined in + +[interfaces.ts:138](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L138) + +*** + +### method + +> **method**: `string` + +#### Defined in + +[interfaces.ts:134](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L134) + +*** + +### receiver? + +> `optional` **receiver**: `string` + +#### Defined in + +[interfaces.ts:135](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L135) + +*** + +### timestamp + +> **timestamp**: `bigint` + +#### Defined in + +[interfaces.ts:132](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L132) + +*** + +### to + +> **to**: `string` + +#### Defined in + +[interfaces.ts:131](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L131) + +*** + +### token? + +> `optional` **token**: `string` + +#### Defined in + +[interfaces.ts:137](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L137) + +*** + +### txHash + +> **txHash**: `string` + +#### Defined in + +[interfaces.ts:129](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L129) + +*** + +### value + +> **value**: `string` + +#### Defined in + +[interfaces.ts:133](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L133) diff --git a/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md b/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md new file mode 100644 index 0000000000..31cf0b30c7 --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md @@ -0,0 +1,123 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ITransactionsFilter + +# Interface: ITransactionsFilter + +## Extends + +- [`IPagination`](IPagination.md) + +## Properties + +### chainId + +> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) + +#### Defined in + +[interfaces.ts:142](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L142) + +*** + +### endBlock? + +> `optional` **endBlock**: `number` + +#### Defined in + +[interfaces.ts:144](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L144) + +*** + +### endDate? + +> `optional` **endDate**: `Date` + +#### Defined in + +[interfaces.ts:146](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L146) + +*** + +### first? + +> `optional` **first**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`first`](IPagination.md#first) + +#### Defined in + +[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) + +*** + +### fromAddress? + +> `optional` **fromAddress**: `string` + +#### Defined in + +[interfaces.ts:147](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L147) + +*** + +### orderDirection? + +> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) + +#### Inherited from + +[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) + +#### Defined in + +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) + +*** + +### skip? + +> `optional` **skip**: `number` + +#### Inherited from + +[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) + +#### Defined in + +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) + +*** + +### startBlock? + +> `optional` **startBlock**: `number` + +#### Defined in + +[interfaces.ts:143](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L143) + +*** + +### startDate? + +> `optional` **startDate**: `Date` + +#### Defined in + +[interfaces.ts:145](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L145) + +*** + +### toAddress? + +> `optional` **toAddress**: `string` + +#### Defined in + +[interfaces.ts:148](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L148) diff --git a/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md b/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md new file mode 100644 index 0000000000..c3376cae1d --- /dev/null +++ b/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md @@ -0,0 +1,77 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / InternalTransaction + +# Interface: InternalTransaction + +## Properties + +### escrow? + +> `optional` **escrow**: `string` + +#### Defined in + +[interfaces.ts:123](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L123) + +*** + +### from + +> **from**: `string` + +#### Defined in + +[interfaces.ts:118](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L118) + +*** + +### method + +> **method**: `string` + +#### Defined in + +[interfaces.ts:121](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L121) + +*** + +### receiver? + +> `optional` **receiver**: `string` + +#### Defined in + +[interfaces.ts:122](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L122) + +*** + +### to + +> **to**: `string` + +#### Defined in + +[interfaces.ts:119](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L119) + +*** + +### token? + +> `optional` **token**: `string` + +#### Defined in + +[interfaces.ts:124](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L124) + +*** + +### value + +> **value**: `string` + +#### Defined in + +[interfaces.ts:120](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L120) diff --git a/docs/sdk/typescript/kvstore/classes/KVStoreClient.md b/docs/sdk/typescript/kvstore/classes/KVStoreClient.md index ed576deda1..512f87af1e 100644 --- a/docs/sdk/typescript/kvstore/classes/KVStoreClient.md +++ b/docs/sdk/typescript/kvstore/classes/KVStoreClient.md @@ -92,7 +92,9 @@ const kvstoreClient = await KVStoreClient.build(signer); The Runner object to interact with the Ethereum network -• **networkData**: `NetworkData` +• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) + +The network information required to connect to the KVStore contract #### Returns @@ -104,13 +106,13 @@ The Runner object to interact with the Ethereum network #### Defined in -[kvstore.ts:108](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L108) +[kvstore.ts:108](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L108) ## Properties ### networkData -> **networkData**: `NetworkData` +> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) #### Inherited from @@ -118,7 +120,7 @@ The Runner object to interact with the Ethereum network #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -132,7 +134,7 @@ The Runner object to interact with the Ethereum network #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) ## Methods @@ -182,7 +184,7 @@ await kvstoreClient.set('Role', 'RecordingOracle'); #### Defined in -[kvstore.ts:171](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L171) +[kvstore.ts:171](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L171) *** @@ -234,7 +236,7 @@ await kvstoreClient.set(keys, values); #### Defined in -[kvstore.ts:214](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L214) +[kvstore.ts:214](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L214) *** @@ -283,7 +285,7 @@ await kvstoreClient.setFileUrlAndHash('linkedin.com/example', 'linkedin_url); #### Defined in -[kvstore.ts:257](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L257) +[kvstore.ts:257](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L257) *** @@ -315,4 +317,4 @@ The Runner object to interact with the Ethereum network #### Defined in -[kvstore.ts:126](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L126) +[kvstore.ts:126](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L126) diff --git a/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md b/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md index 703967229d..092b9408d4 100644 --- a/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md +++ b/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md @@ -57,7 +57,7 @@ Gets the value of a key-value pair in the KVStore using the subgraph. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed @@ -102,7 +102,7 @@ console.log(value); #### Defined in -[kvstore.ts:389](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L389) +[kvstore.ts:389](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L389) *** @@ -114,7 +114,7 @@ Gets the URL value of the given entity, and verifies its hash. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed @@ -146,19 +146,19 @@ console.log(url); #### Defined in -[kvstore.ts:436](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L436) +[kvstore.ts:436](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L436) *** ### getKVStoreData() -> `static` **getKVStoreData**(`chainId`, `address`): `Promise`\<`IKVStore`[]\> +> `static` **getKVStoreData**(`chainId`, `address`): `Promise`\<[`IKVStore`](../../interfaces/interfaces/IKVStore.md)[]\> This function returns the KVStore data for a given address. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed @@ -168,7 +168,7 @@ Address of the KVStore #### Returns -`Promise`\<`IKVStore`[]\> +`Promise`\<[`IKVStore`](../../interfaces/interfaces/IKVStore.md)[]\> KVStore data @@ -191,7 +191,7 @@ console.log(kvStoreData); #### Defined in -[kvstore.ts:337](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L337) +[kvstore.ts:337](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L337) *** @@ -203,7 +203,7 @@ Gets the public key of the given entity, and verifies its hash. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed @@ -231,4 +231,4 @@ console.log(publicKey); #### Defined in -[kvstore.ts:496](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L496) +[kvstore.ts:496](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L496) diff --git a/docs/sdk/typescript/modules.md b/docs/sdk/typescript/modules.md index f4594be2d2..a5dd8d10ce 100644 --- a/docs/sdk/typescript/modules.md +++ b/docs/sdk/typescript/modules.md @@ -8,10 +8,14 @@ - [base](base/README.md) - [encryption](encryption/README.md) +- [enums](enums/README.md) - [escrow](escrow/README.md) +- [graphql/types](graphql/types/README.md) +- [interfaces](interfaces/README.md) - [kvstore](kvstore/README.md) - [operator](operator/README.md) - [staking](staking/README.md) - [statistics](statistics/README.md) - [storage](storage/README.md) - [transaction](transaction/README.md) +- [types](types/README.md) diff --git a/docs/sdk/typescript/operator/classes/OperatorUtils.md b/docs/sdk/typescript/operator/classes/OperatorUtils.md index 73c3e513e5..b638759b24 100644 --- a/docs/sdk/typescript/operator/classes/OperatorUtils.md +++ b/docs/sdk/typescript/operator/classes/OperatorUtils.md @@ -20,13 +20,13 @@ ### getLeader() -> `static` **getLeader**(`chainId`, `address`): `Promise`\<`ILeader`\> +> `static` **getLeader**(`chainId`, `address`): `Promise`\<[`ILeader`](../../interfaces/interfaces/ILeader.md)\> This function returns the leader data for the given address. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) • **address**: `string` @@ -34,7 +34,7 @@ Leader address. #### Returns -`Promise`\<`ILeader`\> +`Promise`\<[`ILeader`](../../interfaces/interfaces/ILeader.md)\> Returns the leader details. @@ -48,25 +48,25 @@ const leader = await OperatorUtils.getLeader(ChainId.POLYGON_AMOY, '0x62dD51230A #### Defined in -[operator.ts:44](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L44) +[operator.ts:44](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L44) *** ### getLeaders() -> `static` **getLeaders**(`filter`): `Promise`\<`ILeader`[]\> +> `static` **getLeaders**(`filter`): `Promise`\<[`ILeader`](../../interfaces/interfaces/ILeader.md)[]\> This function returns all the leader details of the protocol. #### Parameters -• **filter**: `ILeadersFilter` +• **filter**: [`ILeadersFilter`](../../interfaces/interfaces/ILeadersFilter.md) Filter for the leaders. #### Returns -`Promise`\<`ILeader`[]\> +`Promise`\<[`ILeader`](../../interfaces/interfaces/ILeader.md)[]\> Returns an array with all the leader details. @@ -83,19 +83,19 @@ const leaders = await OperatorUtils.getLeaders(filter); #### Defined in -[operator.ts:99](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L99) +[operator.ts:107](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L107) *** ### getReputationNetworkOperators() -> `static` **getReputationNetworkOperators**(`chainId`, `address`, `role`?): `Promise`\<`IOperator`[]\> +> `static` **getReputationNetworkOperators**(`chainId`, `address`, `role`?): `Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md)[]\> Retrieves the reputation network operators of the specified address. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) • **address**: `string` @@ -107,7 +107,7 @@ Address of the reputation oracle. #### Returns -`Promise`\<`IOperator`[]\> +`Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md)[]\> - Returns an array of operator details. @@ -121,19 +121,19 @@ const operators = await OperatorUtils.getReputationNetworkOperators(ChainId.POLY #### Defined in -[operator.ts:151](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L151) +[operator.ts:170](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L170) *** ### getRewards() -> `static` **getRewards**(`chainId`, `slasherAddress`): `Promise`\<`IReward`[]\> +> `static` **getRewards**(`chainId`, `slasherAddress`): `Promise`\<[`IReward`](../../interfaces/interfaces/IReward.md)[]\> This function returns information about the rewards for a given slasher address. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) • **slasherAddress**: `string` @@ -141,7 +141,7 @@ Slasher address. #### Returns -`Promise`\<`IReward`[]\> +`Promise`\<[`IReward`](../../interfaces/interfaces/IReward.md)[]\> Returns an array of Reward objects that contain the rewards earned by the user through slashing other users. @@ -155,4 +155,4 @@ const rewards = await OperatorUtils.getRewards(ChainId.POLYGON_AMOY, '0x62dD5123 #### Defined in -[operator.ts:201](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L201) +[operator.ts:220](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L220) diff --git a/docs/sdk/typescript/staking/classes/StakingClient.md b/docs/sdk/typescript/staking/classes/StakingClient.md index 1c8b30ac4a..bdf953ceff 100644 --- a/docs/sdk/typescript/staking/classes/StakingClient.md +++ b/docs/sdk/typescript/staking/classes/StakingClient.md @@ -92,7 +92,9 @@ const stakingClient = await StakingClient.build(provider); The Runner object to interact with the Ethereum network -• **networkData**: `NetworkData` +• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) + +The network information required to connect to the Staking contract #### Returns @@ -104,7 +106,7 @@ The Runner object to interact with the Ethereum network #### Defined in -[staking.ts:111](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L111) +[staking.ts:107](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L107) ## Properties @@ -114,13 +116,13 @@ The Runner object to interact with the Ethereum network #### Defined in -[staking.ts:102](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L102) +[staking.ts:99](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L99) *** ### networkData -> **networkData**: `NetworkData` +> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) #### Inherited from @@ -128,17 +130,7 @@ The Runner object to interact with the Ethereum network #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) - -*** - -### rewardPoolContract - -> **rewardPoolContract**: `RewardPool` - -#### Defined in - -[staking.ts:103](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L103) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -152,7 +144,7 @@ The Runner object to interact with the Ethereum network #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) *** @@ -162,7 +154,7 @@ The Runner object to interact with the Ethereum network #### Defined in -[staking.ts:101](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L101) +[staking.ts:98](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L98) *** @@ -172,61 +164,10 @@ The Runner object to interact with the Ethereum network #### Defined in -[staking.ts:100](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L100) +[staking.ts:97](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L97) ## Methods -### allocate() - -> **allocate**(`escrowAddress`, `amount`, `txOptions`?): `Promise`\<`void`\> - -This function allocates a portion of the staked tokens to a specific escrow. - -> Must have tokens staked - -#### Parameters - -• **escrowAddress**: `string` - -Address of the escrow contract to allocate in. - -• **amount**: `bigint` - -Amount in WEI of tokens to allocate. - -• **txOptions?**: `Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY' - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI -await stakingClient.allocate('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); -``` - -#### Defined in - -[staking.ts:458](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L458) - -*** - ### approveStake() > **approveStake**(`amount`, `txOptions`?): `Promise`\<`void`\> @@ -268,138 +209,7 @@ await stakingClient.approveStake(amount); #### Defined in -[staking.ts:203](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L203) - -*** - -### closeAllocation() - -> **closeAllocation**(`escrowAddress`, `txOptions`?): `Promise`\<`void`\> - -This function drops the allocation from a specific escrow. - -> The escrow must have allocation -> The escrow must be cancelled or completed. - -#### Parameters - -• **escrowAddress**: `string` - -Address of the escrow contract to close allocation from. - -• **txOptions?**: `Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY' - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -await stakingClient.closeAllocation('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -#### Defined in - -[staking.ts:511](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L511) - -*** - -### distributeReward() - -> **distributeReward**(`escrowAddress`, `txOptions`?): `Promise`\<`void`\> - -This function drops the allocation from a specific escrow. - -> The escrow must have rewards added - -#### Parameters - -• **escrowAddress**: `string` - -Escrow address from which rewards are distributed. - -• **txOptions?**: `Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY' - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -await stakingClient.distributeReward('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -#### Defined in - -[staking.ts:554](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L554) - -*** - -### getAllocation() - -> **getAllocation**(`escrowAddress`): `Promise`\<`IAllocation`\> - -This function returns information about the allocation of the specified escrow. - -#### Parameters - -• **escrowAddress**: `string` - -Escrow address from which we want to get allocation information. - -#### Returns - -`Promise`\<`IAllocation`\> - -Returns allocation info if exists. - -**Code example** - -```ts -import { StakingClient } from '@human-protocol/sdk'; -import { providers } from 'ethers'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const stakingClient = await StakingClient.build(provider); - -const allocationInfo = await stakingClient.getAllocation('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -#### Defined in - -[staking.ts:591](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L591) +[staking.ts:193](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L193) *** @@ -421,7 +231,7 @@ Wallet address from who is going to be slashed • **escrowAddress**: `string` -Address of the escrow which allocation will be slashed +Address of the escrow that the slash is made • **amount**: `bigint` @@ -456,7 +266,7 @@ await stakingClient.slash('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd #### Defined in -[staking.ts:387](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L387) +[staking.ts:377](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L377) *** @@ -504,7 +314,7 @@ await stakingClient.approveStake(amount); #### Defined in -[staking.ts:258](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L258) +[staking.ts:248](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L248) *** @@ -551,7 +361,7 @@ await stakingClient.unstake(amount); #### Defined in -[staking.ts:303](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L303) +[staking.ts:293](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L293) *** @@ -593,7 +403,7 @@ await stakingClient.withdraw(); #### Defined in -[staking.ts:349](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L349) +[staking.ts:339](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L339) *** @@ -625,4 +435,4 @@ The Runner object to interact with the Ethereum network #### Defined in -[staking.ts:145](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L145) +[staking.ts:135](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L135) diff --git a/docs/sdk/typescript/statistics/classes/StatisticsClient.md b/docs/sdk/typescript/statistics/classes/StatisticsClient.md index 5ac50c0f27..4b32bfffed 100644 --- a/docs/sdk/typescript/statistics/classes/StatisticsClient.md +++ b/docs/sdk/typescript/statistics/classes/StatisticsClient.md @@ -52,7 +52,7 @@ const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); #### Parameters -• **networkData**: `NetworkData` +• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) The network information required to connect to the Statistics contract @@ -62,17 +62,17 @@ The network information required to connect to the Statistics contract #### Defined in -[statistics.ts:72](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L72) +[statistics.ts:72](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L72) ## Properties ### networkData -> **networkData**: `NetworkData` +> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) #### Defined in -[statistics.ts:64](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L64) +[statistics.ts:64](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L64) *** @@ -82,13 +82,13 @@ The network information required to connect to the Statistics contract #### Defined in -[statistics.ts:65](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L65) +[statistics.ts:65](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L65) ## Methods ### getEscrowStatistics() -> **getEscrowStatistics**(`filter`): `Promise`\<`EscrowStatistics`\> +> **getEscrowStatistics**(`filter`): `Promise`\<[`EscrowStatistics`](../../graphql/types/type-aliases/EscrowStatistics.md)\> This function returns the statistical data of escrows. @@ -122,13 +122,13 @@ type EscrowStatistics = { #### Parameters -• **filter**: `IStatisticsFilter` = `{}` +• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data #### Returns -`Promise`\<`EscrowStatistics`\> +`Promise`\<[`EscrowStatistics`](../../graphql/types/type-aliases/EscrowStatistics.md)\> Escrow statistics data. @@ -148,13 +148,13 @@ const escrowStatisticsApril = await statisticsClient.getEscrowStatistics({ #### Defined in -[statistics.ts:128](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L128) +[statistics.ts:128](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L128) *** ### getHMTDailyData() -> **getHMTDailyData**(`filter`): `Promise`\<`DailyHMTData`[]\> +> **getHMTDailyData**(`filter`): `Promise`\<[`DailyHMTData`](../../graphql/types/type-aliases/DailyHMTData.md)[]\> This function returns the statistical data of HMToken day by day. @@ -182,13 +182,13 @@ type DailyHMTData = { #### Parameters -• **filter**: `IStatisticsFilter` = `{}` +• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data #### Returns -`Promise`\<`DailyHMTData`[]\> +`Promise`\<[`DailyHMTData`](../../graphql/types/type-aliases/DailyHMTData.md)[]\> Daily HMToken statistics data. @@ -213,13 +213,13 @@ console.log('HMT statistics from 5/8 - 6/8:', hmtStatisticsRange); #### Defined in -[statistics.ts:495](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L495) +[statistics.ts:495](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L495) *** ### getHMTHolders() -> **getHMTHolders**(`params`): `Promise`\<`HMTHolder`[]\> +> **getHMTHolders**(`params`): `Promise`\<[`HMTHolder`](../../graphql/types/type-aliases/HMTHolder.md)[]\> This function returns the holders of the HMToken with optional filters and ordering. @@ -227,13 +227,13 @@ This function returns the holders of the HMToken with optional filters and order #### Parameters -• **params**: `IHMTHoldersParams` = `{}` +• **params**: [`IHMTHoldersParams`](../../interfaces/interfaces/IHMTHoldersParams.md) = `{}` HMT Holders params with filters and ordering #### Returns -`Promise`\<`HMTHolder`[]\> +`Promise`\<[`HMTHolder`](../../graphql/types/type-aliases/HMTHolder.md)[]\> List of HMToken holders. @@ -256,13 +256,13 @@ console.log('HMT holders:', hmtHolders.map((h) => ({ #### Defined in -[statistics.ts:421](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L421) +[statistics.ts:421](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L421) *** ### getHMTStatistics() -> **getHMTStatistics**(): `Promise`\<`HMTStatistics`\> +> **getHMTStatistics**(): `Promise`\<[`HMTStatistics`](../../graphql/types/type-aliases/HMTStatistics.md)\> This function returns the statistical data of HMToken. @@ -292,17 +292,17 @@ console.log('HMT statistics:', { #### Returns -`Promise`\<`HMTStatistics`\> +`Promise`\<[`HMTStatistics`](../../graphql/types/type-aliases/HMTStatistics.md)\> #### Defined in -[statistics.ts:378](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L378) +[statistics.ts:378](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L378) *** ### getPaymentStatistics() -> **getPaymentStatistics**(`filter`): `Promise`\<`PaymentStatistics`\> +> **getPaymentStatistics**(`filter`): `Promise`\<[`PaymentStatistics`](../../graphql/types/type-aliases/PaymentStatistics.md)\> This function returns the statistical data of payments. @@ -333,13 +333,13 @@ type PaymentStatistics = { #### Parameters -• **filter**: `IStatisticsFilter` = `{}` +• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data #### Returns -`Promise`\<`PaymentStatistics`\> +`Promise`\<[`PaymentStatistics`](../../graphql/types/type-aliases/PaymentStatistics.md)\> Payment statistics data. @@ -380,13 +380,13 @@ console.log( #### Defined in -[statistics.ts:312](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L312) +[statistics.ts:312](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L312) *** ### getWorkerStatistics() -> **getWorkerStatistics**(`filter`): `Promise`\<`WorkerStatistics`\> +> **getWorkerStatistics**(`filter`): `Promise`\<[`WorkerStatistics`](../../graphql/types/type-aliases/WorkerStatistics.md)\> This function returns the statistical data of workers. @@ -415,13 +415,13 @@ type WorkerStatistics = { #### Parameters -• **filter**: `IStatisticsFilter` = `{}` +• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data #### Returns -`Promise`\<`WorkerStatistics`\> +`Promise`\<[`WorkerStatistics`](../../graphql/types/type-aliases/WorkerStatistics.md)\> Worker statistics data. @@ -441,4 +441,4 @@ const workerStatisticsApril = await statisticsClient.getWorkerStatistics({ #### Defined in -[statistics.ts:213](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L213) +[statistics.ts:213](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L213) diff --git a/docs/sdk/typescript/storage/classes/StorageClient.md b/docs/sdk/typescript/storage/classes/StorageClient.md index 4d546002dd..8fa93cbb59 100644 --- a/docs/sdk/typescript/storage/classes/StorageClient.md +++ b/docs/sdk/typescript/storage/classes/StorageClient.md @@ -63,11 +63,11 @@ const storageClient = new StorageClient(params, credentials); #### Parameters -• **params**: `StorageParams` +• **params**: [`StorageParams`](../../types/type-aliases/StorageParams.md) Cloud storage params -• **credentials?**: `StorageCredentials` +• **credentials?**: [`StorageCredentials`](../../types/type-aliases/StorageCredentials.md) Optional. Cloud storage access data. If credentials is not provided - use an anonymous access to the bucket @@ -77,7 +77,7 @@ Optional. Cloud storage access data. If credentials is not provided - use an ano #### Defined in -[storage.ts:73](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L73) +[storage.ts:73](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L73) ## Methods @@ -121,7 +121,7 @@ const exists = await storageClient.bucketExists('bucket-name'); #### Defined in -[storage.ts:266](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L266) +[storage.ts:266](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L266) *** @@ -167,7 +167,7 @@ const files = await storageClient.downloadFiles(keys, 'bucket-name'); #### Defined in -[storage.ts:113](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L113) +[storage.ts:113](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L113) *** @@ -211,13 +211,13 @@ const fileNames = await storageClient.listObjects('bucket-name'); #### Defined in -[storage.ts:297](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L297) +[storage.ts:297](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L297) *** ### ~~uploadFiles()~~ -> **uploadFiles**(`files`, `bucket`): `Promise`\<`UploadFile`[]\> +> **uploadFiles**(`files`, `bucket`): `Promise`\<[`UploadFile`](../../types/type-aliases/UploadFile.md)[]\> This function uploads files to a bucket. @@ -233,7 +233,7 @@ Bucket name. #### Returns -`Promise`\<`UploadFile`[]\> +`Promise`\<[`UploadFile`](../../types/type-aliases/UploadFile.md)[]\> Returns an array of json files downloaded and parsed into objects. @@ -262,7 +262,7 @@ const uploadedFiles = await storageClient.uploadFiles(files, 'bucket-name'); #### Defined in -[storage.ts:201](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L201) +[storage.ts:201](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L201) *** @@ -294,4 +294,4 @@ const file = await storageClient.downloadFileFromUrl('http://localhost/file.json #### Defined in -[storage.ts:148](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L148) +[storage.ts:148](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L148) diff --git a/docs/sdk/typescript/transaction/classes/TransactionUtils.md b/docs/sdk/typescript/transaction/classes/TransactionUtils.md index 1474a3c1d1..8adc8de4f0 100644 --- a/docs/sdk/typescript/transaction/classes/TransactionUtils.md +++ b/docs/sdk/typescript/transaction/classes/TransactionUtils.md @@ -20,13 +20,13 @@ ### getTransaction() -> `static` **getTransaction**(`chainId`, `hash`): `Promise`\<`ITransaction`\> +> `static` **getTransaction**(`chainId`, `hash`): `Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md)\> This function returns the transaction data for the given hash. #### Parameters -• **chainId**: `ChainId` +• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) The chain ID. @@ -36,7 +36,7 @@ The transaction hash. #### Returns -`Promise`\<`ITransaction`\> +`Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md)\> Returns the transaction details. @@ -50,13 +50,13 @@ const transaction = await TransactionUtils.getTransaction(ChainId.POLYGON, '0x62 #### Defined in -[transaction.ts:34](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L34) +[transaction.ts:34](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L34) *** ### getTransactions() -> `static` **getTransactions**(`filter`): `Promise`\<`ITransaction`[]\> +> `static` **getTransactions**(`filter`): `Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md)[]\> This function returns all transaction details based on the provided filter. @@ -93,13 +93,13 @@ type ITransaction = { #### Parameters -• **filter**: `ITransactionsFilter` +• **filter**: [`ITransactionsFilter`](../../interfaces/interfaces/ITransactionsFilter.md) Filter for the transactions. #### Returns -`Promise`\<`ITransaction`[]\> +`Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md)[]\> Returns an array with all the transaction details. @@ -121,4 +121,4 @@ const transactions = await TransactionUtils.getTransactions(filter); #### Defined in -[transaction.ts:109](https://github.com/humanprotocol/human-protocol/blob/95ed623c67878973c127c8529a78774329277e86/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L109) +[transaction.ts:109](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L109) diff --git a/docs/sdk/typescript/types/README.md b/docs/sdk/typescript/types/README.md new file mode 100644 index 0000000000..90690e2e95 --- /dev/null +++ b/docs/sdk/typescript/types/README.md @@ -0,0 +1,22 @@ +[**@human-protocol/sdk**](../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../modules.md) / types + +# types + +## Index + +### Enumerations + +- [EscrowStatus](enumerations/EscrowStatus.md) + +### Type Aliases + +- [EscrowCancel](type-aliases/EscrowCancel.md) +- [EscrowWithdraw](type-aliases/EscrowWithdraw.md) +- [NetworkData](type-aliases/NetworkData.md) +- [StorageCredentials](type-aliases/StorageCredentials.md) +- [StorageParams](type-aliases/StorageParams.md) +- [UploadFile](type-aliases/UploadFile.md) diff --git a/docs/sdk/typescript/types/enumerations/EscrowStatus.md b/docs/sdk/typescript/types/enumerations/EscrowStatus.md new file mode 100644 index 0000000000..0c702534fd --- /dev/null +++ b/docs/sdk/typescript/types/enumerations/EscrowStatus.md @@ -0,0 +1,81 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [types](../README.md) / EscrowStatus + +# Enumeration: EscrowStatus + +Enum for escrow statuses. + +## Enumeration Members + +### Cancelled + +> **Cancelled**: `5` + +Escrow is cancelled. + +#### Defined in + +[types.ts:30](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L30) + +*** + +### Complete + +> **Complete**: `4` + +Escrow is finished.. + +#### Defined in + +[types.ts:26](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L26) + +*** + +### Launched + +> **Launched**: `0` + +Escrow is launched. + +#### Defined in + +[types.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L10) + +*** + +### Paid + +> **Paid**: `3` + +Escrow is fully paid. + +#### Defined in + +[types.ts:22](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L22) + +*** + +### Partial + +> **Partial**: `2` + +Escrow is partially paid out. + +#### Defined in + +[types.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L18) + +*** + +### Pending + +> **Pending**: `1` + +Escrow is funded, and waiting for the results to be submitted. + +#### Defined in + +[types.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L14) diff --git a/docs/sdk/typescript/types/type-aliases/EscrowCancel.md b/docs/sdk/typescript/types/type-aliases/EscrowCancel.md new file mode 100644 index 0000000000..e47a9ae867 --- /dev/null +++ b/docs/sdk/typescript/types/type-aliases/EscrowCancel.md @@ -0,0 +1,29 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [types](../README.md) / EscrowCancel + +# Type Alias: EscrowCancel + +> **EscrowCancel**: `object` + +Represents the response data for an escrow cancellation. + +## Type declaration + +### amountRefunded + +> **amountRefunded**: `bigint` + +The amount refunded in the escrow cancellation. + +### txHash + +> **txHash**: `string` + +The hash of the transaction associated with the escrow cancellation. + +## Defined in + +[types.ts:143](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L143) diff --git a/docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md b/docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md new file mode 100644 index 0000000000..d55ae18e29 --- /dev/null +++ b/docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md @@ -0,0 +1,35 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [types](../README.md) / EscrowWithdraw + +# Type Alias: EscrowWithdraw + +> **EscrowWithdraw**: `object` + +Represents the response data for an escrow withdrawal. + +## Type declaration + +### amountWithdrawn + +> **amountWithdrawn**: `bigint` + +The amount withdrawn from the escrow. + +### tokenAddress + +> **tokenAddress**: `string` + +The address of the token used for the withdrawal. + +### txHash + +> **txHash**: `string` + +The hash of the transaction associated with the escrow withdrawal. + +## Defined in + +[types.ts:157](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L157) diff --git a/docs/sdk/typescript/types/type-aliases/NetworkData.md b/docs/sdk/typescript/types/type-aliases/NetworkData.md new file mode 100644 index 0000000000..00cc590c7b --- /dev/null +++ b/docs/sdk/typescript/types/type-aliases/NetworkData.md @@ -0,0 +1,83 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [types](../README.md) / NetworkData + +# Type Alias: NetworkData + +> **NetworkData**: `object` + +Network data + +## Type declaration + +### chainId + +> **chainId**: `number` + +Network chain id + +### factoryAddress + +> **factoryAddress**: `string` + +Escrow Factory contract address + +### hmtAddress + +> **hmtAddress**: `string` + +HMT Token contract address + +### kvstoreAddress + +> **kvstoreAddress**: `string` + +KVStore contract address + +### oldFactoryAddress + +> **oldFactoryAddress**: `string` + +Old Escrow Factory contract address + +### oldSubgraphUrl + +> **oldSubgraphUrl**: `string` + +Old subgraph URL + +### scanUrl + +> **scanUrl**: `string` + +Network scanner URL + +### stakingAddress + +> **stakingAddress**: `string` + +Staking contract address + +### subgraphUrl + +> **subgraphUrl**: `string` + +Subgraph URL + +### subgraphUrlApiKey + +> **subgraphUrlApiKey**: `string` + +Subgraph URL + +### title + +> **title**: `string` + +Network title + +## Defined in + +[types.ts:93](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L93) diff --git a/docs/sdk/typescript/types/type-aliases/StorageCredentials.md b/docs/sdk/typescript/types/type-aliases/StorageCredentials.md new file mode 100644 index 0000000000..1d5f6606e8 --- /dev/null +++ b/docs/sdk/typescript/types/type-aliases/StorageCredentials.md @@ -0,0 +1,33 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [types](../README.md) / StorageCredentials + +# Type Alias: ~~StorageCredentials~~ + +> `readonly` **StorageCredentials**: `object` + +AWS/GCP cloud storage access data + +## Type declaration + +### ~~accessKey~~ + +> **accessKey**: `string` + +Access Key + +### ~~secretKey~~ + +> **secretKey**: `string` + +Secret Key + +## Deprecated + +StorageClient is deprecated. Use Minio.Client directly. + +## Defined in + +[types.ts:38](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L38) diff --git a/docs/sdk/typescript/types/type-aliases/StorageParams.md b/docs/sdk/typescript/types/type-aliases/StorageParams.md new file mode 100644 index 0000000000..c44be0f121 --- /dev/null +++ b/docs/sdk/typescript/types/type-aliases/StorageParams.md @@ -0,0 +1,43 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [types](../README.md) / StorageParams + +# Type Alias: ~~StorageParams~~ + +> **StorageParams**: `object` + +## Type declaration + +### ~~endPoint~~ + +> **endPoint**: `string` + +Request endPoint + +### ~~port?~~ + +> `optional` **port**: `number` + +TCP/IP port number. Default value set to 80 for HTTP and 443 for HTTPs + +### ~~region?~~ + +> `optional` **region**: `string` + +Region + +### ~~useSSL~~ + +> **useSSL**: `boolean` + +Enable secure (HTTPS) access. Default value set to false + +## Deprecated + +StorageClient is deprecated. Use Minio.Client directly. + +## Defined in + +[types.ts:52](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L52) diff --git a/docs/sdk/typescript/types/type-aliases/UploadFile.md b/docs/sdk/typescript/types/type-aliases/UploadFile.md new file mode 100644 index 0000000000..3edf31e5e0 --- /dev/null +++ b/docs/sdk/typescript/types/type-aliases/UploadFile.md @@ -0,0 +1,35 @@ +[**@human-protocol/sdk**](../../README.md) • **Docs** + +*** + +[@human-protocol/sdk](../../modules.md) / [types](../README.md) / UploadFile + +# Type Alias: UploadFile + +> `readonly` **UploadFile**: `object` + +Upload file data + +## Type declaration + +### hash + +> **hash**: `string` + +Hash of uploaded object key + +### key + +> **key**: `string` + +Uploaded object key + +### url + +> **url**: `string` + +Uploaded object URL + +## Defined in + +[types.ts:75](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L75) diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index 48bad063e7..088230342a 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -92,13 +92,13 @@ export class DetailsService { skip, }); const result = transactions.map((transaction) => { - const transcationPaginationObject: TransactionPaginationDto = + const transactionPaginationObject: TransactionPaginationDto = plainToInstance( TransactionPaginationDto, { ...transaction, currentAddress: address }, { excludeExtraneousValues: true }, ); - return transcationPaginationObject; + return transactionPaginationObject; }); return result; diff --git a/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts index 0666d8fcc8..75e868ece5 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts @@ -63,6 +63,13 @@ export class LeaderDto { @Expose() public url?: string; + @ApiProperty({ example: 'https://example.test' }) + @ApiPropertyOptional() + @IsOptional() + @IsUrl() + @Expose() + public website?: string; + @ApiProperty({ example: 1 }) @IsNumber() @Expose() diff --git a/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts index 28c5f1b42f..0e5cd2711c 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts @@ -2,6 +2,12 @@ import { Expose, Transform } from 'class-transformer'; import { IsNumber, IsString } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; +export interface Transfer { + from: string; + to: string; + value: string; +} + export class TransactionPaginationDto { @ApiProperty({ example: 12345 }) @Transform(({ value }) => Number(value)) @@ -41,4 +47,11 @@ export class TransactionPaginationDto { @IsString() @Expose() public method: string; + + @ApiProperty({ + type: [Object], + description: 'List of transfers associated with the transaction', + }) + @Expose() + public transfers: Transfer[]; } diff --git a/packages/apps/dashboard/ui-2024/src/App.tsx b/packages/apps/dashboard/ui-2024/src/App.tsx index 26d75bf7be..5ed277c1f9 100644 --- a/packages/apps/dashboard/ui-2024/src/App.tsx +++ b/packages/apps/dashboard/ui-2024/src/App.tsx @@ -6,17 +6,17 @@ import SearchResults from '@pages/SearchResults'; import { LeaderBoard } from '@pages/Leaderboard'; const App: React.FC = () => { - return ( - - - } /> - } /> - } /> - } /> - Not find} /> - - - ); + return ( + + + } /> + } /> + } /> + } /> + Not find} /> + + + ); }; export default App; diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts b/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts index be216970e3..523ee4d844 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts @@ -1,61 +1,61 @@ export const colorPalette = { - white: '#F9FAFF', - whiteBackground: '#FFF', - whiteSolid: '#F6F5FC', - skyOpacity: '#DADEF0CC', - primary: { - main: '#320a8d', - light: '#320a8d', - }, - secondary: { - main: '#6309ff', - light: '#1406B280', - dark: '#14062b', - }, - info: { - main: '#eeeeee', - light: '#f5f5f5', - dark: '#bdbdbd', - }, - success: { - main: '#0AD397', - light: '#2E7D3280', - }, - warning: { - main: '#FFB300', - light: '#FFD54F', - }, - error: { - main: '#FFB300', - light: '#F20D5F', - }, - fog: { - main: '#858EC6', - light: '#CBCFE6', - dark: '#E5E7F3', - }, - overlay: { - light: '#1406B20A', - }, - sky: { - main: '#858ec6', - light: '#858ec6', - dark: '#858ec6', - contrastText: '#858ec6', - }, - ocean: { - main: '#304FFE', - light: '#8C9EFF', - dark: '#03A9F4', - }, - orange: { - main: '#ED6C02', - light: '#ED6C0280', - }, - textSecondary: { - main: '#858ec6', - light: '#858ec6', - dark: '#858ec6', - contrastText: '#858ec6', - }, + white: '#F9FAFF', + whiteBackground: '#FFF', + whiteSolid: '#F6F5FC', + skyOpacity: '#DADEF0CC', + primary: { + main: '#320a8d', + light: '#320a8d', + }, + secondary: { + main: '#6309ff', + light: '#1406B280', + dark: '#14062b', + }, + info: { + main: '#eeeeee', + light: '#f5f5f5', + dark: '#bdbdbd', + }, + success: { + main: '#0AD397', + light: '#2E7D3280', + }, + warning: { + main: '#FFB300', + light: '#FFD54F', + }, + error: { + main: '#FFB300', + light: '#F20D5F', + }, + fog: { + main: '#858EC6', + light: '#CBCFE6', + dark: '#E5E7F3', + }, + overlay: { + light: '#1406B20A', + }, + sky: { + main: '#858ec6', + light: '#858ec6', + dark: '#858ec6', + contrastText: '#858ec6', + }, + ocean: { + main: '#304FFE', + light: '#8C9EFF', + dark: '#03A9F4', + }, + orange: { + main: '#ED6C02', + light: '#ED6C0280', + }, + textSecondary: { + main: '#858ec6', + light: '#858ec6', + dark: '#858ec6', + contrastText: '#858ec6', + }, } as const; diff --git a/packages/apps/dashboard/ui-2024/src/components/Breadcrumbs/Breadcrumbs.tsx b/packages/apps/dashboard/ui-2024/src/components/Breadcrumbs/Breadcrumbs.tsx index 77a827ab9e..18bb584207 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Breadcrumbs/Breadcrumbs.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Breadcrumbs/Breadcrumbs.tsx @@ -4,26 +4,26 @@ import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; import { useNavigate } from 'react-router-dom'; const Breadcrumbs: FC<{ title?: string }> = ({ title }) => { - const navigate = useNavigate(); - return ( -
- { - navigate('/'); - }} - component="span" - fontSize={16} - sx={{ textDecoration: 'unset', cursor: 'pointer' }} - color="text.secondary" - > - Dashboard - - - - {title} - -
- ); + const navigate = useNavigate(); + return ( +
+ { + navigate('/'); + }} + component="span" + fontSize={16} + sx={{ textDecoration: 'unset', cursor: 'pointer' }} + color="text.secondary" + > + Dashboard + + + + {title} + +
+ ); }; export default Breadcrumbs; diff --git a/packages/apps/dashboard/ui-2024/src/components/Charts/AreaChart.tsx b/packages/apps/dashboard/ui-2024/src/components/Charts/AreaChart.tsx index 3204835ece..4300ff5fe8 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Charts/AreaChart.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Charts/AreaChart.tsx @@ -1,11 +1,11 @@ import { - CartesianGrid, - Tooltip, - XAxis, - YAxis, - AreaChart as AreaChartRecharts, - Area, - ResponsiveContainer, + CartesianGrid, + Tooltip, + XAxis, + YAxis, + AreaChart as AreaChartRecharts, + Area, + ResponsiveContainer, } from 'recharts'; import CustomChartTooltip from './CustomChartTooltip'; import { useEffect, useRef, useState } from 'react'; @@ -20,393 +20,393 @@ import dayjs, { Dayjs } from 'dayjs'; import ToggleCharts from '@components/Charts/ToggleCharts'; import { formatNumber } from '@helpers/formatNumber'; import { - GraphPageChartData, - useGraphPageChartData, + GraphPageChartData, + useGraphPageChartData, } from '@services/api/use-graph-page-chart-data'; import { - initialAllTime, - useGraphPageChartParams, + initialAllTime, + useGraphPageChartParams, } from '@utils/hooks/use-graph-page-chart-params'; export type GraphPageChartDataConfigObject = Partial< - Record + Record >; const CHECKED_CHARTS_DEFAULT_STATE: GraphPageChartDataConfigObject = { - totalTransactionAmount: true, - totalTransactionCount: true, - solved: true, - dailyUniqueReceivers: true, - dailyUniqueSenders: true, + totalTransactionAmount: true, + totalTransactionCount: true, + solved: true, + dailyUniqueReceivers: true, + dailyUniqueSenders: true, }; const HOVERED_CHARTS_DEFAULT_STATE: GraphPageChartDataConfigObject = { - totalTransactionAmount: false, - totalTransactionCount: false, - solved: false, - dailyUniqueReceivers: false, - dailyUniqueSenders: false, + totalTransactionAmount: false, + totalTransactionCount: false, + solved: false, + dailyUniqueReceivers: false, + dailyUniqueSenders: false, }; type SumOfNumericChartDataProperties = Record< - keyof Omit, - number + keyof Omit, + number >; const sumNumericProperties = ( - chartData: GraphPageChartData + chartData: GraphPageChartData ): SumOfNumericChartDataProperties => { - return chartData.reduce( - (acc, chartEntry) => { - acc.dailyUniqueReceivers += chartEntry.dailyUniqueReceivers; - acc.dailyUniqueSenders += chartEntry.dailyUniqueSenders; - acc.solved += chartEntry.solved; - acc.totalTransactionAmount += chartEntry.totalTransactionAmount; - acc.totalTransactionCount += chartEntry.totalTransactionCount; - return acc; - }, - { - dailyUniqueReceivers: 0, - dailyUniqueSenders: 0, - solved: 0, - totalTransactionAmount: 0, - totalTransactionCount: 0, - } - ); + return chartData.reduce( + (acc, chartEntry) => { + acc.dailyUniqueReceivers += chartEntry.dailyUniqueReceivers; + acc.dailyUniqueSenders += chartEntry.dailyUniqueSenders; + acc.solved += chartEntry.solved; + acc.totalTransactionAmount += chartEntry.totalTransactionAmount; + acc.totalTransactionCount += chartEntry.totalTransactionCount; + return acc; + }, + { + dailyUniqueReceivers: 0, + dailyUniqueSenders: 0, + solved: 0, + totalTransactionAmount: 0, + totalTransactionCount: 0, + } + ); }; export const AreaChart = ({ - changeDateOnScroll = false, + changeDateOnScroll = false, }: { - changeDateOnScroll?: boolean; + changeDateOnScroll?: boolean; }) => { - const { data } = useGraphPageChartData(); - const chartData = data || []; - const { - setFromDate, - setToDate, - clearTimePeriod, - dateRangeParams: { from, to }, - } = useGraphPageChartParams(); - const sum = sumNumericProperties(chartData); - const [checkedCharts, setCheckedCharts] = useState( - CHECKED_CHARTS_DEFAULT_STATE - ); - const chartRef = useRef(null); - const [currentHoveredChart, setCurrentHoveredChart] = useState( - HOVERED_CHARTS_DEFAULT_STATE - ); + const { data } = useGraphPageChartData(); + const chartData = data || []; + const { + setFromDate, + setToDate, + clearTimePeriod, + dateRangeParams: { from, to }, + } = useGraphPageChartParams(); + const sum = sumNumericProperties(chartData); + const [checkedCharts, setCheckedCharts] = useState( + CHECKED_CHARTS_DEFAULT_STATE + ); + const chartRef = useRef(null); + const [currentHoveredChart, setCurrentHoveredChart] = useState( + HOVERED_CHARTS_DEFAULT_STATE + ); - const toggleChart = (event: React.ChangeEvent) => { - setCheckedCharts((prevState) => ({ - ...prevState, - [event.target.name]: event.target.checked, - })); - }; + const toggleChart = (event: React.ChangeEvent) => { + setCheckedCharts((prevState) => ({ + ...prevState, + [event.target.name]: event.target.checked, + })); + }; - const onFromDateChange = (value: Dayjs | null) => { - if (value) setFromDate(value); - }; + const onFromDateChange = (value: Dayjs | null) => { + if (value) setFromDate(value); + }; - const onToDateChange = (value: Dayjs | null) => { - if (value) setToDate(value); - }; + const onToDateChange = (value: Dayjs | null) => { + if (value) setToDate(value); + }; - const onChartHover = (name: string) => { - setCurrentHoveredChart((prevState) => ({ - ...prevState, - [name]: true, - })); - }; + const onChartHover = (name: string) => { + setCurrentHoveredChart((prevState) => ({ + ...prevState, + [name]: true, + })); + }; - const onChartLeave = () => { - setCurrentHoveredChart(HOVERED_CHARTS_DEFAULT_STATE); - }; + const onChartLeave = () => { + setCurrentHoveredChart(HOVERED_CHARTS_DEFAULT_STATE); + }; - useEffect(() => { - if (!changeDateOnScroll) { - return; - } - const currentRef = chartRef.current; - if (currentRef) { - const handleScrollChangeDate = (event: WheelEvent) => { - event.preventDefault(); - clearTimePeriod(); - if (event.deltaY < 0) { - if (from.add(1, 'day').isAfter(to)) { - return; - } - setFromDate(from.add(1, 'day')); - } else if (event.deltaY > 0) { - if (from?.isSame(from)) { - return; - } - setFromDate(from.subtract(1, 'day')); - } - }; + useEffect(() => { + if (!changeDateOnScroll) { + return; + } + const currentRef = chartRef.current; + if (currentRef) { + const handleScrollChangeDate = (event: WheelEvent) => { + event.preventDefault(); + clearTimePeriod(); + if (event.deltaY < 0) { + if (from.add(1, 'day').isAfter(to)) { + return; + } + setFromDate(from.add(1, 'day')); + } else if (event.deltaY > 0) { + if (from?.isSame(from)) { + return; + } + setFromDate(from.subtract(1, 'day')); + } + }; - currentRef.addEventListener('wheel', handleScrollChangeDate); + currentRef.addEventListener('wheel', handleScrollChangeDate); - return () => { - currentRef.removeEventListener('wheel', handleScrollChangeDate); - }; - } - }, [changeDateOnScroll, clearTimePeriod, from, setFromDate, to]); + return () => { + currentRef.removeEventListener('wheel', handleScrollChangeDate); + }; + } + }, [changeDateOnScroll, clearTimePeriod, from, setFromDate, to]); - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - height={50} - stroke={colorPalette.fog.dark} - tickSize={20} - dataKey="date" - tickMargin={10} - /> - } /> - {checkedCharts.totalTransactionAmount && ( - - )} - {checkedCharts.totalTransactionCount && ( - - )} - {checkedCharts.solved && ( - - )} - {checkedCharts.dailyUniqueReceivers && ( - - )} - {checkedCharts.dailyUniqueSenders && ( - - )} - - - - - - - ); + return ( + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + height={50} + stroke={colorPalette.fog.dark} + tickSize={20} + dataKey="date" + tickMargin={10} + /> + } /> + {checkedCharts.totalTransactionAmount && ( + + )} + {checkedCharts.totalTransactionCount && ( + + )} + {checkedCharts.solved && ( + + )} + {checkedCharts.dailyUniqueReceivers && ( + + )} + {checkedCharts.dailyUniqueSenders && ( + + )} + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Charts/CustomChartTooltip.tsx b/packages/apps/dashboard/ui-2024/src/components/Charts/CustomChartTooltip.tsx index 04cde4ccf7..ccca5b6c96 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Charts/CustomChartTooltip.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Charts/CustomChartTooltip.tsx @@ -10,84 +10,84 @@ import { GraphPageChartDataConfigObject } from '@components/Charts/AreaChart'; import { NumericFormat } from 'react-number-format'; const renderTitle = (title: string) => { - const currentTitle: GraphPageChartDataConfigObject = { - totalTransactionAmount: 'Transfer Amount', - totalTransactionCount: 'Transactions Count', - solved: 'Number of Tasks', - dailyUniqueReceivers: 'Unique Receivers', - dailyUniqueSenders: 'Unique Senders', - }; - return currentTitle[title as keyof GraphPageChartDataConfigObject]; + const currentTitle: GraphPageChartDataConfigObject = { + totalTransactionAmount: 'Transfer Amount', + totalTransactionCount: 'Transactions Count', + solved: 'Number of Tasks', + dailyUniqueReceivers: 'Unique Receivers', + dailyUniqueSenders: 'Unique Senders', + }; + return currentTitle[title as keyof GraphPageChartDataConfigObject]; }; const CustomChartTooltip = ({ - payload, - label, - active, + payload, + label, + active, }: TooltipProps) => { - if (active) { - return ( - - - - {formatDate(label, 'MMMM DD, YYYY')} - - {payload?.map((elem) => ( - - - - - - {renderTitle(elem.name ?? '')} - - - - - - {' '} - {elem.name === 'totalTransactionAmount' ? 'HMT' : ''} - - - - ))} - - - ); - } - return null; + if (active) { + return ( + + + + {formatDate(label, 'MMMM DD, YYYY')} + + {payload?.map((elem) => ( + + + + + + {renderTitle(elem.name ?? '')} + + + + + + {' '} + {elem.name === 'totalTransactionAmount' ? 'HMT' : ''} + + + + ))} + + + ); + } + return null; }; export default CustomChartTooltip; diff --git a/packages/apps/dashboard/ui-2024/src/components/Charts/CustomXAxisTick.tsx b/packages/apps/dashboard/ui-2024/src/components/Charts/CustomXAxisTick.tsx index 1b365b7775..364f711fe6 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Charts/CustomXAxisTick.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Charts/CustomXAxisTick.tsx @@ -4,20 +4,20 @@ import { ContentRenderer } from 'recharts'; import { formatDate } from '@helpers/formatDate'; const CustomXAxisTick = ({ x, y, payload }: ContentRenderer) => { - return ( - - - {formatDate(payload.value, 'D MMM')} - - - ); + return ( + + + {formatDate(payload.value, 'D MMM')} + + + ); }; export default CustomXAxisTick; diff --git a/packages/apps/dashboard/ui-2024/src/components/Charts/ToggleCharts.tsx b/packages/apps/dashboard/ui-2024/src/components/Charts/ToggleCharts.tsx index 69680efa93..94dc0314d4 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Charts/ToggleCharts.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Charts/ToggleCharts.tsx @@ -5,85 +5,85 @@ import { colorPalette } from '@assets/styles/color-palette'; import { FormatNumber } from '@components/Home/FormatNumber'; interface ToggleChartsProps { - handleChange: (event: React.ChangeEvent) => void; - onMouseEnter?: (name: string) => void; - onMouseLeave?: () => void; - chartOptions: { - title: string; - isAreaChart?: boolean; - name: string; - color: string; - amount?: number | string; - }[]; + handleChange: (event: React.ChangeEvent) => void; + onMouseEnter?: (name: string) => void; + onMouseLeave?: () => void; + chartOptions: { + title: string; + isAreaChart?: boolean; + name: string; + color: string; + amount?: number | string; + }[]; } const ToggleCharts = ({ - handleChange, - chartOptions, - onMouseLeave, - onMouseEnter, + handleChange, + chartOptions, + onMouseLeave, + onMouseEnter, }: ToggleChartsProps) => { - return ( - - - {chartOptions.map((elem) => ( - - onMouseEnter ? onMouseEnter(elem.name) : undefined - } - onMouseLeave={() => (onMouseLeave ? onMouseLeave() : undefined)} - id={elem.name} - key={elem.name} - sx={{ - m: 0, - gap: 1, - }} - control={ - - } - label={ - <> - {elem.title} - - {elem.amount ? : ''} - {elem.name === 'totalTransactionAmount' && - elem.isAreaChart && ( - - HMT - - )} - - - } - /> - ))} - - - ); + return ( + + + {chartOptions.map((elem) => ( + + onMouseEnter ? onMouseEnter(elem.name) : undefined + } + onMouseLeave={() => (onMouseLeave ? onMouseLeave() : undefined)} + id={elem.name} + key={elem.name} + sx={{ + m: 0, + gap: 1, + }} + control={ + + } + label={ + <> + {elem.title} + + {elem.amount ? : ''} + {elem.name === 'totalTransactionAmount' && + elem.isAreaChart && ( + + HMT + + )} + + + } + /> + ))} + + + ); }; export default ToggleCharts; diff --git a/packages/apps/dashboard/ui-2024/src/components/Clipboard/Clipboard.tsx b/packages/apps/dashboard/ui-2024/src/components/Clipboard/Clipboard.tsx index 672b4e1854..da3bc72a74 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Clipboard/Clipboard.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Clipboard/Clipboard.tsx @@ -8,60 +8,60 @@ import CustomTooltip from '@components/CustomTooltip'; import { useState } from 'react'; interface ClipboardProps { - value: string; + value: string; } const Clipboard = ({ value }: ClipboardProps) => { - const [tooltipOpen, setTooltipOpen] = useState(false); + const [tooltipOpen, setTooltipOpen] = useState(false); - return ( - - - - {value} - + return ( + + + + {value} + - { - navigator.clipboard.writeText(value); - setTooltipOpen(true); - setTimeout(() => { - setTooltipOpen(false); - }, 1500); - }} - sx={{ - p: 0, - }} - > - - - - - - - ); + { + navigator.clipboard.writeText(value); + setTooltipOpen(true); + setTimeout(() => { + setTooltipOpen(false); + }, 1500); + }} + sx={{ + p: 0, + }} + > + + + + + + + ); }; export default Clipboard; diff --git a/packages/apps/dashboard/ui-2024/src/components/CustomTooltip/CustomTooltip.tsx b/packages/apps/dashboard/ui-2024/src/components/CustomTooltip/CustomTooltip.tsx index 77554e96f5..4002edbb51 100644 --- a/packages/apps/dashboard/ui-2024/src/components/CustomTooltip/CustomTooltip.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/CustomTooltip/CustomTooltip.tsx @@ -1,7 +1,7 @@ import { Tooltip, TooltipProps } from '@mui/material'; const CustomTooltip = (props: TooltipProps) => { - return ; + return ; }; export default CustomTooltip; diff --git a/packages/apps/dashboard/ui-2024/src/components/DataEntry/DatePicker.tsx b/packages/apps/dashboard/ui-2024/src/components/DataEntry/DatePicker.tsx index e74cb10e6b..a53e3d65f1 100644 --- a/packages/apps/dashboard/ui-2024/src/components/DataEntry/DatePicker.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/DataEntry/DatePicker.tsx @@ -1,7 +1,7 @@ import { - DatePickerProps, - LocalizationProvider, - UseDateFieldProps, + DatePickerProps, + LocalizationProvider, + UseDateFieldProps, } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { DatePicker as DatePickerMui } from '@mui/x-date-pickers/DatePicker'; @@ -9,93 +9,93 @@ import type { Dayjs } from 'dayjs'; import { Dispatch, SetStateAction, useState } from 'react'; import Typography from '@mui/material/Typography'; import { - BaseSingleInputFieldProps, - DateValidationError, - FieldSection, + BaseSingleInputFieldProps, + DateValidationError, + FieldSection, } from '@mui/x-date-pickers/models'; import { colorPalette } from '@assets/styles/color-palette'; interface CustomDateFieldProps - extends UseDateFieldProps, - BaseSingleInputFieldProps< - Dayjs | null, - Dayjs, - FieldSection, - false, - DateValidationError - > { - setOpen: Dispatch>; + extends UseDateFieldProps, + BaseSingleInputFieldProps< + Dayjs | null, + Dayjs, + FieldSection, + false, + DateValidationError + > { + setOpen: Dispatch>; } const CustomDateField = ({ - setOpen, - label, - id, - InputProps: { ref } = {}, - inputProps: { 'aria-label': ariaLabel } = {}, + setOpen, + label, + id, + InputProps: { ref } = {}, + inputProps: { 'aria-label': ariaLabel } = {}, }: CustomDateFieldProps) => { - return ( - setOpen((prevState) => !prevState)} - sx={{ - borderBottom: `1px solid ${colorPalette.primary.main}`, - lineHeight: 2.5, - '&:hover': { - cursor: 'pointer', - }, - }} - > - {label} - - ); + return ( + setOpen((prevState) => !prevState)} + sx={{ + borderBottom: `1px solid ${colorPalette.primary.main}`, + lineHeight: 2.5, + '&:hover': { + cursor: 'pointer', + }, + }} + > + {label} + + ); }; interface CustomDatePickerProps { - props: Omit, 'open' | 'onOpen' | 'onClose'>; + props: Omit, 'open' | 'onOpen' | 'onClose'>; } const CustomDaterPicker = ({ props }: CustomDatePickerProps) => { - const [open, setOpen] = useState(false); + const [open, setOpen] = useState(false); - return ( - setOpen(false)} - onOpen={() => setOpen(true)} - sx={{ - '& .StaticDatePicker-calendarContainer .DayPicker-Day': { - fontSize: 14, - }, - }} - /> - ); + return ( + setOpen(false)} + onOpen={() => setOpen(true)} + sx={{ + '& .StaticDatePicker-calendarContainer .DayPicker-Day': { + fontSize: 14, + }, + }} + /> + ); }; interface DatePickerPropsMui { - value: Dayjs; - onChange: (value: Dayjs | null) => void; - customProps?: Omit['props']; + value: Dayjs; + onChange: (value: Dayjs | null) => void; + customProps?: Omit['props']; } const DatePicker = ({ value, onChange, customProps }: DatePickerPropsMui) => { - return ( - - - - ); + return ( + + + + ); }; export default DatePicker; diff --git a/packages/apps/dashboard/ui-2024/src/components/DataEntry/ToggleButtons.tsx b/packages/apps/dashboard/ui-2024/src/components/DataEntry/ToggleButtons.tsx index 47aeccd760..808d5ec296 100644 --- a/packages/apps/dashboard/ui-2024/src/components/DataEntry/ToggleButtons.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/DataEntry/ToggleButtons.tsx @@ -4,63 +4,63 @@ import { styled } from '@mui/material'; import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; import { colorPalette } from '@assets/styles/color-palette'; import { - TIME_PERIOD_OPTIONS, - TimePeriod, - useGraphPageChartParams, + TIME_PERIOD_OPTIONS, + TimePeriod, + useGraphPageChartParams, } from '@utils/hooks/use-graph-page-chart-params'; export const StyledToggleButtonGroup = styled(ToggleButtonGroup)({ - '.MuiToggleButtonGroup-grouped': { - border: 'none', - borderRadius: 4, - width: 50, - color: colorPalette.primary.main, - }, + '.MuiToggleButtonGroup-grouped': { + border: 'none', + borderRadius: 4, + width: 50, + color: colorPalette.primary.main, + }, }); const ToggleButtons = () => { - const { setTimePeriod, selectedTimePeriod, dateRangeParams } = - useGraphPageChartParams(); + const { setTimePeriod, selectedTimePeriod, dateRangeParams } = + useGraphPageChartParams(); - const checkIfSelected = (element: TimePeriod) => { - if (element.name !== 'ALL') { - return element.value.isSame(dateRangeParams.from); - } - }; + const checkIfSelected = (element: TimePeriod) => { + if (element.name !== 'ALL') { + return element.value.isSame(dateRangeParams.from); + } + }; - return ( - - {TIME_PERIOD_OPTIONS.map((elem) => ( - { - setTimePeriod(elem); - }} - selected={checkIfSelected(elem)} - key={elem.name} - sx={{ - '.MuiTypography-root': { - wordBreak: 'normal', - }, - '&.Mui-selected': { - backgroundColor: colorPalette.primary.main, - color: colorPalette.white, - }, - '&.Mui-selected:hover': { - cursor: 'pointer', - backgroundColor: colorPalette.primary.main, - }, - }} - value={elem.name} - > - {elem.name} - - ))} - - ); + return ( + + {TIME_PERIOD_OPTIONS.map((elem) => ( + { + setTimePeriod(elem); + }} + selected={checkIfSelected(elem)} + key={elem.name} + sx={{ + '.MuiTypography-root': { + wordBreak: 'normal', + }, + '&.Mui-selected': { + backgroundColor: colorPalette.primary.main, + color: colorPalette.white, + }, + '&.Mui-selected:hover': { + cursor: 'pointer', + backgroundColor: colorPalette.primary.main, + }, + }} + value={elem.name} + > + {elem.name} + + ))} + + ); }; export default ToggleButtons; diff --git a/packages/apps/dashboard/ui-2024/src/components/Footer/Footer.tsx b/packages/apps/dashboard/ui-2024/src/components/Footer/Footer.tsx index c3a65fe6fb..f89a3f7dcd 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Footer/Footer.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Footer/Footer.tsx @@ -9,76 +9,76 @@ import { colorPalette } from '@assets/styles/color-palette'; import { env } from '@helpers/env'; const Footer: FC = () => { - const handleClick = (url: string) => { - window.open(url, '_blank'); - }; + const handleClick = (url: string) => { + window.open(url, '_blank'); + }; - return ( -
-
-
-
- handleClick(env.VITE_FOOTER_LINK_PRIVACY_POLICY)} - > - Privacy Policy - - handleClick(env.VITE_FOOTER_LINK_TERMS_OF_SERVICE)} - > - Terms of Service - - handleClick(env.VITE_FOOTER_LINK_HUMAN_PROTOCOL)} - > - HUMAN Protocol - -
- - © 2021 HPF. HUMAN Protocol® is a registered trademark - -
-
- handleClick(env.VITE_FOOTER_LINK_GITHUB)} - /> - handleClick(env.VITE_FOOTER_LINK_DISCORD)} - /> - handleClick(env.VITE_FOOTER_LINK_X)} - /> - handleClick(env.VITE_FOOTER_LINK_TELEGRAM)} - /> - handleClick(env.VITE_FOOTER_LINK_LINKEDIN)} - /> -
-
-
- ); + return ( +
+
+
+
+ handleClick(env.VITE_FOOTER_LINK_PRIVACY_POLICY)} + > + Privacy Policy + + handleClick(env.VITE_FOOTER_LINK_TERMS_OF_SERVICE)} + > + Terms of Service + + handleClick(env.VITE_FOOTER_LINK_HUMAN_PROTOCOL)} + > + HUMAN Protocol + +
+ + © 2021 HPF. HUMAN Protocol® is a registered trademark + +
+
+ handleClick(env.VITE_FOOTER_LINK_GITHUB)} + /> + handleClick(env.VITE_FOOTER_LINK_DISCORD)} + /> + handleClick(env.VITE_FOOTER_LINK_X)} + /> + handleClick(env.VITE_FOOTER_LINK_TELEGRAM)} + /> + handleClick(env.VITE_FOOTER_LINK_LINKEDIN)} + /> +
+
+
+ ); }; export default Footer; diff --git a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx index 39dca9bc9c..65258762ea 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx @@ -15,150 +15,150 @@ import { LogoBlockIconMobile } from '@components/Icons/LogoBlockIconMobile'; import TopSearchBar from '@components/Search/TopBarSearch'; const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { - const navigate = useNavigate(); - const [open, setState] = useState(false); + const navigate = useNavigate(); + const [open, setState] = useState(false); - const handleClick = (url: string) => { - window.open(url, '_blank'); - }; + const handleClick = (url: string) => { + window.open(url, '_blank'); + }; - const toggleDrawer = (open: boolean) => { - setState(open); - }; + const toggleDrawer = (open: boolean) => { + setState(open); + }; - return ( - - {displaySearchBar && ( - - )} - { - navigate('/'); - }} - underline="none" - sx={{ - ':hover': { - cursor: 'pointer', - }, - }} - > - - - - - - - + return ( + + {displaySearchBar && ( + + )} + { + navigate('/'); + }} + underline="none" + sx={{ + ':hover': { + cursor: 'pointer', + }, + }} + > + + + + + + + - {displaySearchBar && ( - - )} + {displaySearchBar && ( + + )} -
- handleClick(env.VITE_NAVBAR_LINK_GITBOOK)} - > - GitBook - - handleClick(env.VITE_NAVBAR_LINK_FAUCETS)} - > - Faucet - - handleClick(env.VITE_NAVBAR_LINK_HUMAN_WEBSITE)} - > - HUMAN Website - - - -
+
+ handleClick(env.VITE_NAVBAR_LINK_GITBOOK)} + > + GitBook + + handleClick(env.VITE_NAVBAR_LINK_FAUCETS)} + > + Faucet + + handleClick(env.VITE_NAVBAR_LINK_HUMAN_WEBSITE)} + > + HUMAN Website + + + +
- toggleDrawer(true)} - > - - + toggleDrawer(true)} + > + + - toggleDrawer(false)} - PaperProps={{ - sx: { - width: '80%', - }, - }} - > - -
-
- handleClick(env.VITE_NAVBAR_LINK_GITBOOK)} - > - GitBook - -
-
- handleClick(env.VITE_NAVBAR_LINK_FAUCETS)} - > - Faucet - -
-
- handleClick(env.VITE_NAVBAR_LINK_HUMAN_WEBSITE)} - > - HUMAN Website - -
- - -
-
-
-
- ); + toggleDrawer(false)} + PaperProps={{ + sx: { + width: '80%', + }, + }} + > + +
+
+ handleClick(env.VITE_NAVBAR_LINK_GITBOOK)} + > + GitBook + +
+
+ handleClick(env.VITE_NAVBAR_LINK_FAUCETS)} + > + Faucet + +
+
+ handleClick(env.VITE_NAVBAR_LINK_HUMAN_WEBSITE)} + > + HUMAN Website + +
+ + +
+
+
+
+ ); }; export default Header; diff --git a/packages/apps/dashboard/ui-2024/src/components/Home/FormatNumber.tsx b/packages/apps/dashboard/ui-2024/src/components/Home/FormatNumber.tsx index d280263125..c4836609fc 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Home/FormatNumber.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Home/FormatNumber.tsx @@ -1,33 +1,33 @@ import { NumericFormat } from 'react-number-format'; export const FormatNumber = ({ - value, + value, }: { - value: number | string | undefined | null; + value: number | string | undefined | null; }) => { - return ( - - ); + return ( + + ); }; export const FormatNumberWithDecimals = ({ - value, + value, }: { - value: number | string | undefined | null; + value: number | string | undefined | null; }) => { - if (value && Number(value) < 1) { - return {value}; - } - return ( - - ); + if (value && Number(value) < 1) { + return {value}; + } + return ( + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Home/GraphSwiper.tsx b/packages/apps/dashboard/ui-2024/src/components/Home/GraphSwiper.tsx index 3d230c84c6..88efa002bd 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Home/GraphSwiper.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Home/GraphSwiper.tsx @@ -8,70 +8,70 @@ import { useGraphPageChartParams } from '@utils/hooks/use-graph-page-chart-param import { useEffect } from 'react'; const GraphSwiper = () => { - const { data } = useGraphPageChartData(); - const { revertToInitialParams } = useGraphPageChartParams(); + const { data } = useGraphPageChartData(); + const { revertToInitialParams } = useGraphPageChartParams(); - useEffect(() => { - revertToInitialParams(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + useEffect(() => { + revertToInitialParams(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); - const transactionHistoryData = (data || []).map( - ({ totalTransactionCount, date }) => ({ - value: totalTransactionCount, - date, - }) - ); - const transferAmount = (data || []).map( - ({ totalTransactionAmount, date }) => ({ - value: totalTransactionAmount, - date, - }) - ); - const solvedTasks = (data || []).map(({ solved, date }) => ({ - value: solved, - date, - })); + const transactionHistoryData = (data || []).map( + ({ totalTransactionCount, date }) => ({ + value: totalTransactionCount, + date, + }) + ); + const transferAmount = (data || []).map( + ({ totalTransactionAmount, date }) => ({ + value: totalTransactionAmount, + date, + }) + ); + const solvedTasks = (data || []).map(({ solved, date }) => ({ + value: solved, + date, + })); - const uniqueSenders = (data || []).map(({ dailyUniqueSenders, date }) => ({ - value: dailyUniqueSenders, - date, - })); + const uniqueSenders = (data || []).map(({ dailyUniqueSenders, date }) => ({ + value: dailyUniqueSenders, + date, + })); - const uniqueReceivers = (data || []).map( - ({ dailyUniqueReceivers, date }) => ({ - value: dailyUniqueReceivers, - date, - }) - ); + const uniqueReceivers = (data || []).map( + ({ dailyUniqueReceivers, date }) => ({ + value: dailyUniqueReceivers, + date, + }) + ); - return ( - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + ); }; export default GraphSwiper; diff --git a/packages/apps/dashboard/ui-2024/src/components/Home/SmallGraph.tsx b/packages/apps/dashboard/ui-2024/src/components/Home/SmallGraph.tsx index cdf94e6a55..0b2327b214 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Home/SmallGraph.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Home/SmallGraph.tsx @@ -1,12 +1,12 @@ import { - AreaChart, - Area, - XAxis, - YAxis, - CartesianGrid, - Tooltip, - ResponsiveContainer, - TooltipProps, + AreaChart, + Area, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, + TooltipProps, } from 'recharts'; import Card from '@mui/material/Card'; import { colorPalette } from '@assets/styles/color-palette'; @@ -19,116 +19,116 @@ import { formatDate } from '@helpers/formatDate'; import { formatNumber } from '@helpers/formatNumber'; const CustomSmallChartTooltip = ({ - payload, - active, + payload, + active, }: TooltipProps) => { - if (active) { - return ( - - - {payload?.map((elem) => ( - - - {formatDate(elem.payload.date, 'MMMM DD, YYYY')} - - - {elem.value ? elem.value.toLocaleString('en-US') : ''} - - - ))} - - - ); - } - return null; + if (active) { + return ( + + + {payload?.map((elem) => ( + + + {formatDate(elem.payload.date, 'MMMM DD, YYYY')} + + + {elem.value ? elem.value.toLocaleString('en-US') : ''} + + + ))} + + + ); + } + return null; }; interface SmallGraphProps { - graphData: { - date: string; - value: number; - }[]; - title: string; + graphData: { + date: string; + value: number; + }[]; + title: string; } const SmallGraph = ({ title, graphData }: SmallGraphProps) => { - return ( - <> - - - - - - - - - formatDate(value, 'DD MMMM')} - tick={{ dy: 10 }} - tickSize={0} - /> - - - } /> - - - - - - {title} - - - - - ); + return ( + <> + + + + + + + + + formatDate(value, 'DD MMMM')} + tick={{ dy: 10 }} + tickSize={0} + /> + + + } /> + + + + + + {title} + + + + + ); }; export default SmallGraph; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/AvalancheIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/AvalancheIcon.tsx index b0caf42c51..2a1473418b 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/AvalancheIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/AvalancheIcon.tsx @@ -2,32 +2,32 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const AvalancheIcon: FC = (props) => { - return ( - - - - - - - ); + return ( + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/BinanceSmartChainIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/BinanceSmartChainIcon.tsx index f38a683a48..5620a6e72d 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/BinanceSmartChainIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/BinanceSmartChainIcon.tsx @@ -48,4 +48,4 @@ export const BinanceSmartChainIcon: FC = (props) => { ); }; -export default BinanceSmartChainIcon; \ No newline at end of file +export default BinanceSmartChainIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/CeloIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/CeloIcon.tsx index 06bf185222..08d77b3a59 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/CeloIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/CeloIcon.tsx @@ -2,29 +2,29 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const CeloIcon: FC = (props) => { - return ( - - - - - - ); + return ( + + + + + + ); }; export default CeloIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/DiscordIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/DiscordIcon.tsx index 5ed554f7a6..7aefd29e27 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/DiscordIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/DiscordIcon.tsx @@ -2,11 +2,11 @@ import React from 'react'; import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; const DiscordIcon: React.FC = (props) => { - return ( - - - - ); + return ( + + + + ); }; export default DiscordIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/EscrowAddressIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/EscrowAddressIcon.tsx index d3cba11e06..a8c8776d97 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/EscrowAddressIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/EscrowAddressIcon.tsx @@ -2,210 +2,210 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const EscrowAddressIcon: FC = (props) => { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/EthereumIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/EthereumIcon.tsx index d4879d20cb..381b049142 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/EthereumIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/EthereumIcon.tsx @@ -2,37 +2,37 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const EthereumIcon: FC = (props) => { - return ( - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + ); }; export default EthereumIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/ExchangeOracleIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/ExchangeOracleIcon.tsx index cd706c2919..e6b53725ee 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/ExchangeOracleIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/ExchangeOracleIcon.tsx @@ -2,33 +2,33 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const ExchangeOracleIcon: FC = (props) => { - return ( - - - - - - - ); + return ( + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/HumanIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/HumanIcon.tsx index 10446fd696..b80c2b36d0 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/HumanIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/HumanIcon.tsx @@ -14,4 +14,4 @@ export const HumanIcon: FC = (props) => { ); }; -export default HumanIcon; \ No newline at end of file +export default HumanIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/JobLauncher.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/JobLauncher.tsx index 0f973e2735..650028aa2b 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/JobLauncher.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/JobLauncher.tsx @@ -2,33 +2,33 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const JobLauncher: FC = (props) => { - return ( - - - - - - - ); + return ( + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/LeaderboardIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/LeaderboardIcon.tsx index 76b477f3a5..35f51ba3e9 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/LeaderboardIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/LeaderboardIcon.tsx @@ -2,193 +2,193 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const LeaderboardIcon: FC = (props) => { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIcon.tsx index 309d9513db..8509d09523 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIcon.tsx @@ -2,79 +2,79 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const LogoBlockIcon: FC = (props) => { - return ( - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIconMobile.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIconMobile.tsx index 15a009ad0e..51f2953567 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIconMobile.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/LogoBlockIconMobile.tsx @@ -2,32 +2,32 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const LogoBlockIconMobile: FC = (props) => { - return ( - - - - - - - ); + return ( + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbaseAlphaIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbaseAlphaIcon.tsx index 7ff0836878..7bf42a3377 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbaseAlphaIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbaseAlphaIcon.tsx @@ -68,4 +68,4 @@ export const MoonbaseAlphaIcon: FC = (props) => { ); }; -export default MoonbaseAlphaIcon; \ No newline at end of file +export default MoonbaseAlphaIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbeamIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbeamIcon.tsx index a62227b8b8..085f24f1d2 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbeamIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/MoonbeamIcon.tsx @@ -2,14 +2,14 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const MoonbeamIcon: FC = (props) => { - return ( - - - - ); + return ( + + + + ); }; export default MoonbeamIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/PolygonIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/PolygonIcon.tsx index e89d554bbd..26ef262294 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/PolygonIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/PolygonIcon.tsx @@ -2,14 +2,14 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const PolygonIcon: FC = (props) => { - return ( - - - - ); + return ( + + + + ); }; export default PolygonIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/RecordingOracle.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/RecordingOracle.tsx index 4502f8bcc6..9c02b7cfef 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/RecordingOracle.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/RecordingOracle.tsx @@ -2,53 +2,53 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const RecordingOracle: FC = (props) => { - return ( - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/ReputationOracle.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/ReputationOracle.tsx index fc169f427b..0355384782 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/ReputationOracle.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/ReputationOracle.tsx @@ -2,63 +2,63 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const ReputationOracle: FC = (props) => { - return ( - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/WalletIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/WalletIcon.tsx index 704f7fbe37..bdcb1f3b6a 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/WalletIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/WalletIcon.tsx @@ -2,180 +2,180 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const WalletIcon: FC = (props) => { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Icons/XLayerIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/Icons/XLayerIcon.tsx index 4694b5af89..b6b213e57d 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Icons/XLayerIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Icons/XLayerIcon.tsx @@ -2,77 +2,77 @@ import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; import { FC } from 'react'; export const XLayerIcon: FC = (props) => { - return ( - - - + return ( + + + - - - - - - - - - - - - - - ); + + + + + + + + + + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx b/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx index ddf29f12a2..86ecff1223 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx @@ -2,18 +2,18 @@ import CircularProgress from '@mui/material/CircularProgress'; import Box from '@mui/material/Box'; const Loader = ({ height = '100vh' }: { height?: string }) => { - return ( - - - - ); + return ( + + + + ); }; export default Loader; diff --git a/packages/apps/dashboard/ui-2024/src/components/NetworkIcon/index.tsx b/packages/apps/dashboard/ui-2024/src/components/NetworkIcon/index.tsx index 2d1bb6ae47..583bebae24 100644 --- a/packages/apps/dashboard/ui-2024/src/components/NetworkIcon/index.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/NetworkIcon/index.tsx @@ -9,37 +9,37 @@ import HumanIcon from '@components/Icons/HumanIcon'; import { AvalancheIcon } from '@components/Icons/AvalancheIcon'; export const NetworkIcon = ({ chainId }: { chainId: number }) => { - const icon = (() => { - switch (chainId) { - case 1: - case 4: - case 5: - case 11155111: - return ; - case 56: - case 97: - return ; - case 137: - case 80001: - case 80002: - return ; - case 1284: - return ; - case 1287: - return ; - case 42220: - case 44787: - return ; - case 195: - case 196: - return ; - case 43113: - case 43114: - return ; - default: - return ; - } - })(); + const icon = (() => { + switch (chainId) { + case 1: + case 4: + case 5: + case 11155111: + return ; + case 56: + case 97: + return ; + case 137: + case 80001: + case 80002: + return ; + case 1284: + return ; + case 1287: + return ; + case 42220: + case 44787: + return ; + case 195: + case 196: + return ; + case 43113: + case 43114: + return ; + default: + return ; + } + })(); - return <>{icon}; + return <>{icon}; }; diff --git a/packages/apps/dashboard/ui-2024/src/components/NothingFound/NothingFound.tsx b/packages/apps/dashboard/ui-2024/src/components/NothingFound/NothingFound.tsx index fd2775f164..aee9c6aef8 100644 --- a/packages/apps/dashboard/ui-2024/src/components/NothingFound/NothingFound.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/NothingFound/NothingFound.tsx @@ -2,19 +2,19 @@ import { FC } from 'react'; import Link from '@mui/material/Link'; const NothingFound: FC = () => { - return ( - <> -
Nothing found :(
-
- We couldn't find anything within this criteria. -
- Please search by wallet address or escrow address. -
- -
Back Home
- - - ); + return ( + <> +
Nothing found :(
+
+ We couldn't find anything within this criteria. +
+ Please search by wallet address or escrow address. +
+ +
Back Home
+ + + ); }; export default NothingFound; diff --git a/packages/apps/dashboard/ui-2024/src/components/PageWrapper/PageWrapper.tsx b/packages/apps/dashboard/ui-2024/src/components/PageWrapper/PageWrapper.tsx index 756a1c8296..7ddac5b2d4 100644 --- a/packages/apps/dashboard/ui-2024/src/components/PageWrapper/PageWrapper.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/PageWrapper/PageWrapper.tsx @@ -4,26 +4,26 @@ import Header from '@components/Header'; import Footer from '@components/Footer'; const PageWrapper: FC< - PropsWithChildren<{ - violetHeader?: boolean; - displaySearchBar?: boolean; - className?: string; - }> + PropsWithChildren<{ + violetHeader?: boolean; + displaySearchBar?: boolean; + className?: string; + }> > = ({ children, violetHeader, displaySearchBar, className }) => { - return ( -
-
-
-
{children}
-
-
-
- ); + return ( +
+
+
+
{children}
+
+
+
+ ); }; export default PageWrapper; diff --git a/packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx b/packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx index 81b4a871a5..4c740ce52f 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx @@ -5,12 +5,12 @@ import IconButton from '@mui/material/IconButton'; import SearchIcon from '@mui/icons-material/Search'; import CloseIcon from '@mui/icons-material/Close'; import { - InputAdornment, - TextField, - MenuItem, - Select as MuiSelect, - SelectChangeEvent, - Grid, + InputAdornment, + TextField, + MenuItem, + Select as MuiSelect, + SelectChangeEvent, + Grid, } from '@mui/material'; import { colorPalette } from '@assets/styles/color-palette'; import { getNetwork, networks } from '@utils/config/networks'; @@ -19,240 +19,240 @@ import { useBreakPoints } from '@utils/hooks/use-is-mobile'; import { NetworkIcon } from '@components/NetworkIcon'; const Search: FC<{ - className?: string; - displaySearchBar?: boolean; - borderColor?: string; + className?: string; + displaySearchBar?: boolean; + borderColor?: string; }> = ({ - className, - displaySearchBar, - borderColor = colorPalette.secondary.main, + className, + displaySearchBar, + borderColor = colorPalette.secondary.main, }) => { - const { mobile } = useBreakPoints(); - const { filterParams, setAddress, setChainId } = useWalletSearch(); - const [inputValue, setInputValue] = useState(''); - const [selectValue, setSelectValue] = useState(''); - const [focus, setFocus] = useState(false); - const navigate = useNavigate(); + const { mobile } = useBreakPoints(); + const { filterParams, setAddress, setChainId } = useWalletSearch(); + const [inputValue, setInputValue] = useState(''); + const [selectValue, setSelectValue] = useState(''); + const [focus, setFocus] = useState(false); + const navigate = useNavigate(); - const handleInputChange = (event: React.ChangeEvent) => { - setInputValue(event.target.value); - }; + const handleInputChange = (event: React.ChangeEvent) => { + setInputValue(event.target.value); + }; - const handleSelectChange = (event: SelectChangeEvent) => { - const chainId = Number(event.target.value); - setChainId(chainId); - const networkName = getNetwork(chainId)?.name || ''; - setSelectValue(networkName); - }; + const handleSelectChange = (event: SelectChangeEvent) => { + const chainId = Number(event.target.value); + setChainId(chainId); + const networkName = getNetwork(chainId)?.name || ''; + setSelectValue(networkName); + }; - const handleClearClick = () => { - setInputValue(''); - setAddress(''); - }; + const handleClearClick = () => { + setInputValue(''); + setAddress(''); + }; - const handleInputBlur = () => { - setFocus(false); - }; + const handleInputBlur = () => { + setFocus(false); + }; - const handleInputFocus = () => { - setFocus(true); - }; + const handleInputFocus = () => { + setFocus(true); + }; - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - setAddress(inputValue); - navigate(`/search/${filterParams.chainId || -1}/${inputValue || '0x0'}`); - }; + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setAddress(inputValue); + navigate(`/search/${filterParams.chainId || -1}/${inputValue || '0x0'}`); + }; - useEffect(() => { - const networkName = getNetwork(filterParams.chainId || -1)?.name || ''; - if (networkName) { - setSelectValue(networkName); - } - }, [filterParams.chainId]); + useEffect(() => { + const networkName = getNetwork(filterParams.chainId || -1)?.name || ''; + if (networkName) { + setSelectValue(networkName); + } + }, [filterParams.chainId]); - useEffect(() => { - setInputValue(filterParams.address); - }, [filterParams.address]); + useEffect(() => { + setInputValue(filterParams.address); + }, [filterParams.address]); - return ( -
- - ( - - Network - - ) - : () => { - return ( - - -
- {mobile.isMobile - ? null - : getNetwork(filterParams.chainId)?.name} -
-
- ); - } - } - > - {networks.map((network) => ( - - - {network.name} - - - ))} -
- - ), - endAdornment: inputValue && ( - - - - - - - - - ), - }} - /> - - ); + return ( +
+ + ( + + Network + + ) + : () => { + return ( + + +
+ {mobile.isMobile + ? null + : getNetwork(filterParams.chainId)?.name} +
+
+ ); + } + } + > + {networks.map((network) => ( + + + {network.name} + + + ))} +
+ + ), + endAdornment: inputValue && ( + + + + + + + + + ), + }} + /> + + ); }; export default Search; diff --git a/packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx b/packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx index c1718d295d..4185408e06 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx @@ -5,12 +5,12 @@ import IconButton from '@mui/material/IconButton'; import SearchIcon from '@mui/icons-material/Search'; import CloseIcon from '@mui/icons-material/Close'; import { - InputAdornment, - TextField, - MenuItem, - Select as MuiSelect, - SelectChangeEvent, - Grid, + InputAdornment, + TextField, + MenuItem, + Select as MuiSelect, + SelectChangeEvent, + Grid, } from '@mui/material'; import { colorPalette } from '@assets/styles/color-palette'; import { getNetwork, networks } from '@utils/config/networks'; @@ -19,230 +19,230 @@ import { useBreakPoints } from '@utils/hooks/use-is-mobile'; import { NetworkIcon } from '@components/NetworkIcon'; const TopSearchBar: FC<{ className?: string; displaySearchBar?: boolean }> = ({ - className, - displaySearchBar, + className, + displaySearchBar, }) => { - const { mobile } = useBreakPoints(); - const { filterParams, setAddress, setChainId } = useWalletSearch(); - const [inputValue, setInputValue] = useState(''); - const [selectValue, setSelectValue] = useState(''); - const [focus, setFocus] = useState(false); - const navigate = useNavigate(); + const { mobile } = useBreakPoints(); + const { filterParams, setAddress, setChainId } = useWalletSearch(); + const [inputValue, setInputValue] = useState(''); + const [selectValue, setSelectValue] = useState(''); + const [focus, setFocus] = useState(false); + const navigate = useNavigate(); - const handleInputChange = (event: React.ChangeEvent) => { - setAddress(event.target.value); - }; + const handleInputChange = (event: React.ChangeEvent) => { + setAddress(event.target.value); + }; - const handleSelectChange = (event: SelectChangeEvent) => { - const chainId = Number(event.target.value); - setChainId(chainId); - const networkName = getNetwork(chainId)?.name || ''; - setSelectValue(networkName); - }; + const handleSelectChange = (event: SelectChangeEvent) => { + const chainId = Number(event.target.value); + setChainId(chainId); + const networkName = getNetwork(chainId)?.name || ''; + setSelectValue(networkName); + }; - const handleClearClick = () => { - setInputValue(''); - setAddress(''); - }; + const handleClearClick = () => { + setInputValue(''); + setAddress(''); + }; - const handleInputBlur = () => { - setFocus(false); - }; + const handleInputBlur = () => { + setFocus(false); + }; - const handleInputFocus = () => { - setFocus(true); - }; + const handleInputFocus = () => { + setFocus(true); + }; - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - navigate( - `/search/${filterParams.chainId || -1}/${filterParams.address || '0x0'}` - ); - }; + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + navigate( + `/search/${filterParams.chainId || -1}/${filterParams.address || '0x0'}` + ); + }; - useEffect(() => { - const networkName = getNetwork(filterParams.chainId || -1)?.name || ''; - if (networkName) { - setSelectValue(networkName); - } - }, [filterParams.chainId]); + useEffect(() => { + const networkName = getNetwork(filterParams.chainId || -1)?.name || ''; + if (networkName) { + setSelectValue(networkName); + } + }, [filterParams.chainId]); - useEffect(() => { - setInputValue(filterParams.address); - }, [filterParams.address]); + useEffect(() => { + setInputValue(filterParams.address); + }, [filterParams.address]); - return ( -
- - ( - - Network - - ) - : () => { - return ( - - -
- {mobile.isMobile - ? null - : getNetwork(filterParams.chainId)?.name} -
-
- ); - } - } - > - {networks.map((network) => ( - - - {network.name} - - - ))} -
- - ), - endAdornment: inputValue && ( - - - - - - - - - ), - }} - /> - - ); + return ( +
+ + ( + + Network + + ) + : () => { + return ( + + +
+ {mobile.isMobile + ? null + : getNetwork(filterParams.chainId)?.name} +
+
+ ); + } + } + > + {networks.map((network) => ( + + + {network.name} + + + ))} +
+ + ), + endAdornment: inputValue && ( + + + + + + + + + ), + }} + /> + + ); }; export default TopSearchBar; diff --git a/packages/apps/dashboard/ui-2024/src/components/Search/index.ts b/packages/apps/dashboard/ui-2024/src/components/Search/index.ts index 4a4cbc8d19..85bb434b22 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Search/index.ts +++ b/packages/apps/dashboard/ui-2024/src/components/Search/index.ts @@ -1 +1 @@ -export { default } from './Search'; \ No newline at end of file +export { default } from './Search'; diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx b/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx index 998675c6d4..2a3bfa3acd 100644 --- a/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx @@ -10,56 +10,56 @@ import { useState } from 'react'; import CustomTooltip from '@components/CustomTooltip'; interface AbbreviateClipboardProps { - value: string; - link?: string; + value: string; + link?: string; } const AbbreviateClipboard = ({ value, link }: AbbreviateClipboardProps) => { - const [tooltipOpen, setTooltipOpen] = useState(false); - const navigate = useNavigate(); - return ( - - - {link ? ( - { - e.stopPropagation(); - e.preventDefault(); - navigate(link, { - preventScrollReset: false, - }); - }} - > - - {abbreviateValue(value)} - - - ) : ( - <>{abbreviateValue(value)} - )} - - { - navigator.clipboard.writeText(value); - setTooltipOpen(true); - setTimeout(() => { - setTooltipOpen(false); - }, 1500); - }} - sx={{ - p: 0, - }} - > - - - - - - ); + const [tooltipOpen, setTooltipOpen] = useState(false); + const navigate = useNavigate(); + return ( + + + {link ? ( + { + e.stopPropagation(); + e.preventDefault(); + navigate(link, { + preventScrollReset: false, + }); + }} + > + + {abbreviateValue(value)} + + + ) : ( + <>{abbreviateValue(value)} + )} + + { + navigator.clipboard.writeText(value); + setTooltipOpen(true); + setTimeout(() => { + setTooltipOpen(false); + }, 1500); + }} + sx={{ + p: 0, + }} + > + + + + + + ); }; export default AbbreviateClipboard; diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchResults/TitleSectionWrapper.tsx b/packages/apps/dashboard/ui-2024/src/components/SearchResults/TitleSectionWrapper.tsx index 0083540815..8a91684560 100644 --- a/packages/apps/dashboard/ui-2024/src/components/SearchResults/TitleSectionWrapper.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/SearchResults/TitleSectionWrapper.tsx @@ -6,53 +6,53 @@ import { colorPalette } from '@assets/styles/color-palette'; import CustomTooltip from '@components/CustomTooltip'; const TitleSectionWrapper = ({ - title, - children, - tooltip, + title, + children, + tooltip, }: { - title: string; - children: React.ReactNode; - tooltip?: { - description: string; - }; + title: string; + children: React.ReactNode; + tooltip?: { + description: string; + }; }) => { - return ( - - {tooltip ? ( - - - - - - - {title} - - ) : ( - - {title} - - )} - {children} - - ); + return ( + + {tooltip ? ( + + + + + + + {title} + + ) : ( + + {title} + + )} + {children} + + ); }; export default TitleSectionWrapper; diff --git a/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/ShadowIcon.tsx b/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/ShadowIcon.tsx index e1e401c6f7..a01fb875a4 100644 --- a/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/ShadowIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/ShadowIcon.tsx @@ -2,18 +2,18 @@ import { FC } from 'react'; import clsx from 'clsx'; const ShadowIcon: FC<{ - className?: string; - title?: string; - img: string | JSX.Element; + className?: string; + title?: string; + img: string | JSX.Element; }> = ({ className, title, img }) => { - return ( -
-
- {typeof img === 'string' ? logo : <>{img}} -
- {title} -
- ); + return ( +
+
+ {typeof img === 'string' ? logo : <>{img}} +
+ {title} +
+ ); }; export default ShadowIcon; diff --git a/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/index.ts b/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/index.ts index 7a5811caf3..fbddef1da6 100644 --- a/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/index.ts +++ b/packages/apps/dashboard/ui-2024/src/components/ShadowIcon/index.ts @@ -1 +1 @@ -export { default } from './ShadowIcon'; \ No newline at end of file +export { default } from './ShadowIcon'; diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/AddressCell.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/AddressCell.tsx index 66bee6a7a4..e1699a869a 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/AddressCell.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/AddressCell.tsx @@ -2,16 +2,16 @@ import AbbreviateClipboard from '@components/SearchResults/AbbreviateClipboard'; import { Box } from '@mui/material'; export const AddressCell = ({ - chainId, - address, + chainId, + address, }: { - chainId: string; - address: string; + chainId: string; + address: string; }) => ( - - - + + + ); diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx index a81a6a53de..a1ac7d3606 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx @@ -3,17 +3,17 @@ import { NetworkIcon } from '@components/NetworkIcon'; import { getNetwork } from '@utils/config/networks'; export const ChainCell = ({ chainId }: { chainId: number }) => ( - - - {getNetwork(chainId)?.name} - + + + {getNetwork(chainId)?.name} + ); diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/EntityIcon.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/EntityIcon.tsx index af89340afe..e2b00026cd 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/EntityIcon.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/EntityIcon.tsx @@ -5,18 +5,18 @@ import { RecordingOracle } from '@components/Icons/RecordingOracle'; import { ReputationOracle } from '@components/Icons/ReputationOracle'; export const EntityIcon: React.FC<{ role: string }> = ({ role }) => { - switch (role) { - case 'Job Launcher': - return ; - case 'Recording Oracle': - return ; - case 'Reputation Oracle': - return ; - case 'Exchange Oracle': - return ; - case 'HUMAN App': - return ; - default: - return ; - } + switch (role) { + case 'Job Launcher': + return ; + case 'Recording Oracle': + return ; + case 'Reputation Oracle': + return ; + case 'Exchange Oracle': + return ; + case 'HUMAN App': + return ; + default: + return ; + } }; diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ReputationLabel.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ReputationLabel.tsx index 293c23ec05..7ace7dc2af 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ReputationLabel.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ReputationLabel.tsx @@ -1,36 +1,36 @@ export const ReputationLabel: React.FC<{ reputation: string }> = ({ - reputation, + reputation, }) => { - switch (reputation) { - case 'High': - return ( -
- {reputation} -
- ); - case 'Medium': - return ( -
- {reputation} -
- ); - case 'Low': - return ( -
- {reputation} -
- ); - case 'Coming soon': - return ( -
- {reputation} -
- ); - default: - return ( -
- Coming soon -
- ); - } + switch (reputation) { + case 'High': + return ( +
+ {reputation} +
+ ); + case 'Medium': + return ( +
+ {reputation} +
+ ); + case 'Low': + return ( +
+ {reputation} +
+ ); + case 'Coming soon': + return ( +
+ {reputation} +
+ ); + default: + return ( +
+ Coming soon +
+ ); + } }; diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx index 3fd99601de..55c70dfc99 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx @@ -4,73 +4,73 @@ import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; import HumanIcon from '@components/Icons/HumanIcon'; import { - leaderboardSearchSelectConfig, - useLeaderboardSearch, + leaderboardSearchSelectConfig, + useLeaderboardSearch, } from '@utils/hooks/use-leaderboard-search'; import { NetworkIcon } from '@components/NetworkIcon'; import { Box } from '@mui/material'; import { useBreakPoints } from '@utils/hooks/use-is-mobile'; export const SelectNetwork = () => { - const { - setChainId, - filterParams: { chainId }, - } = useLeaderboardSearch(); + const { + setChainId, + filterParams: { chainId }, + } = useLeaderboardSearch(); - const { - mobile: { isMobile }, - } = useBreakPoints(); + const { + mobile: { isMobile }, + } = useBreakPoints(); - const handleChange = (event: SelectChangeEvent) => { - const value = event.target.value; - if (typeof value === 'number') { - setChainId(value); - } - }; + const handleChange = (event: SelectChangeEvent) => { + const value = event.target.value; + if (typeof value === 'number') { + setChainId(value); + } + }; - return ( - - By Network - - labelId="network-select-label" - id="network-select" - value={chainId} - label="By Network" - onChange={handleChange} - > - {leaderboardSearchSelectConfig.map((selectItem) => { - if ('allNetworksId' in selectItem) { - return ( - - - All Networks - - ); - } + return ( + + By Network + + labelId="network-select-label" + id="network-select" + value={chainId} + label="By Network" + onChange={handleChange} + > + {leaderboardSearchSelectConfig.map((selectItem) => { + if ('allNetworksId' in selectItem) { + return ( + + + All Networks + + ); + } - return ( - - - - + return ( + + + + - {selectItem.name} - - ); - })} - - - ); + {selectItem.name} + + ); + })} + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/TextCell.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/TextCell.tsx index 21327b55b3..0daad03b1a 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/TextCell.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/TextCell.tsx @@ -1,18 +1,18 @@ import { Typography } from '@mui/material'; interface TextCellProps { - value: string; + value: string; } export const TextCell = ({ value }: TextCellProps) => ( - - {value} - + + {value} + ); diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/index.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/index.tsx index 185361be5b..40b5a20ea5 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/index.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/index.tsx @@ -9,55 +9,55 @@ import { DataGridWrapper } from './components/DataGridWrapper'; import { Button, Typography } from '@mui/material'; export type LeaderboardCommonProps = { - data: LeaderBoardData | undefined; - status: 'success' | 'error' | 'pending'; - error: unknown; + data: LeaderBoardData | undefined; + status: 'success' | 'error' | 'pending'; + error: unknown; }; export const Leaderboard = ({ - data, - status, - error, - viewAllBanner, + data, + status, + error, + viewAllBanner, }: LeaderboardCommonProps & { - viewAllBanner?: boolean; + viewAllBanner?: boolean; }) => { - const navigate = useNavigate(); - return ( - -
- -
- - - - {viewAllBanner ? ( - - ) : null} -
- ); + const navigate = useNavigate(); + return ( + +
+ +
+ + + + {viewAllBanner ? ( + + ) : null} +
+ ); }; diff --git a/packages/apps/dashboard/ui-2024/src/helpers/abbreviateValue.ts b/packages/apps/dashboard/ui-2024/src/helpers/abbreviateValue.ts index e375685c3d..45feadaf9d 100644 --- a/packages/apps/dashboard/ui-2024/src/helpers/abbreviateValue.ts +++ b/packages/apps/dashboard/ui-2024/src/helpers/abbreviateValue.ts @@ -1,12 +1,12 @@ const abbreviateValue = (value: string | null) => { - if (value) { - const first3Letters = value.slice(0, 5); - const last5Letters = value.slice(-5); + if (value) { + const first3Letters = value.slice(0, 5); + const last5Letters = value.slice(-5); - return `${first3Letters}...${last5Letters}`; - } + return `${first3Letters}...${last5Letters}`; + } - return null; + return null; }; export default abbreviateValue; diff --git a/packages/apps/dashboard/ui-2024/src/helpers/env.ts b/packages/apps/dashboard/ui-2024/src/helpers/env.ts index 4ac40ef968..07a00a5e84 100644 --- a/packages/apps/dashboard/ui-2024/src/helpers/env.ts +++ b/packages/apps/dashboard/ui-2024/src/helpers/env.ts @@ -1,49 +1,49 @@ import { ZodError, z } from 'zod'; const envSchema = z.object({ - VITE_API_URL: z.string(), - VITE_NAVBAR_LINK_GITBOOK: z.string(), - VITE_NAVBAR_LINK_FAUCETS: z.string(), - VITE_NAVBAR_LINK_HUMAN_WEBSITE: z.string(), - VITE_NAVBAR_LINK_LAUNCH_JOBS: z.string(), - VITE_NAVBAR_LINK_WORK_AND_EARN: z.string(), - VITE_HUMANPROTOCOL_CORE_ARCHITECTURE: z.string().optional(), - VITE_FOOTER_LINK_TERMS_OF_SERVICE: z.string(), - VITE_FOOTER_LINK_PRIVACY_POLICY: z.string(), - VITE_FOOTER_LINK_HUMAN_PROTOCOL: z.string(), - VITE_FOOTER_LINK_GITHUB: z.string(), - VITE_FOOTER_LINK_DISCORD: z.string(), - VITE_FOOTER_LINK_X: z.string(), - VITE_FOOTER_LINK_TELEGRAM: z.string(), - VITE_FOOTER_LINK_LINKEDIN: z.string(), + VITE_API_URL: z.string(), + VITE_NAVBAR_LINK_GITBOOK: z.string(), + VITE_NAVBAR_LINK_FAUCETS: z.string(), + VITE_NAVBAR_LINK_HUMAN_WEBSITE: z.string(), + VITE_NAVBAR_LINK_LAUNCH_JOBS: z.string(), + VITE_NAVBAR_LINK_WORK_AND_EARN: z.string(), + VITE_HUMANPROTOCOL_CORE_ARCHITECTURE: z.string().optional(), + VITE_FOOTER_LINK_TERMS_OF_SERVICE: z.string(), + VITE_FOOTER_LINK_PRIVACY_POLICY: z.string(), + VITE_FOOTER_LINK_HUMAN_PROTOCOL: z.string(), + VITE_FOOTER_LINK_GITHUB: z.string(), + VITE_FOOTER_LINK_DISCORD: z.string(), + VITE_FOOTER_LINK_X: z.string(), + VITE_FOOTER_LINK_TELEGRAM: z.string(), + VITE_FOOTER_LINK_LINKEDIN: z.string(), }); let validEnvs; function setError() { - const root = document.getElementById('root'); - if (!root) return; + const root = document.getElementById('root'); + if (!root) return; - const errorDiv = document.createElement('div'); - errorDiv.textContent = 'Invalid .env file. Open devtools to see more details'; - root.appendChild(errorDiv); + const errorDiv = document.createElement('div'); + errorDiv.textContent = 'Invalid .env file. Open devtools to see more details'; + root.appendChild(errorDiv); } try { - validEnvs = envSchema.parse(import.meta.env); + validEnvs = envSchema.parse(import.meta.env); } catch (error) { - if (error instanceof ZodError) { - console.error('Invalid .env file'); - error.issues.forEach((issue) => { - console.error('Invalid env:', issue.path.join()); - console.error(issue); - }); - setError(); - throw new Error(); - } - setError(); - console.error(error); - throw new Error(); + if (error instanceof ZodError) { + console.error('Invalid .env file'); + error.issues.forEach((issue) => { + console.error('Invalid env:', issue.path.join()); + console.error(issue); + }); + setError(); + throw new Error(); + } + setError(); + console.error(error); + throw new Error(); } export const env = validEnvs; diff --git a/packages/apps/dashboard/ui-2024/src/helpers/formatDate.ts b/packages/apps/dashboard/ui-2024/src/helpers/formatDate.ts index e6497d747e..d2cf178433 100644 --- a/packages/apps/dashboard/ui-2024/src/helpers/formatDate.ts +++ b/packages/apps/dashboard/ui-2024/src/helpers/formatDate.ts @@ -1,5 +1,5 @@ import dayjs from 'dayjs'; export const formatDate = (date: string, dateFormat?: string) => { - return dayjs(new Date(date)).format(dateFormat ?? 'dd/MM/yyyy'); + return dayjs(new Date(date)).format(dateFormat ?? 'dd/MM/yyyy'); }; diff --git a/packages/apps/dashboard/ui-2024/src/helpers/formatHMTDecimals.ts b/packages/apps/dashboard/ui-2024/src/helpers/formatHMTDecimals.ts index 88f26f1a5b..8a6adfd05b 100644 --- a/packages/apps/dashboard/ui-2024/src/helpers/formatHMTDecimals.ts +++ b/packages/apps/dashboard/ui-2024/src/helpers/formatHMTDecimals.ts @@ -1,24 +1,24 @@ import { formatEther } from 'ethers'; export const formatHMTDecimals = (value: string) => { - const formattedValue = Number(formatEther(value)); + const formattedValue = Number(formatEther(value)); - if (Number.isInteger(formattedValue)) { - return formattedValue.toString(); - } + if (Number.isInteger(formattedValue)) { + return formattedValue.toString(); + } - if (Math.abs(formattedValue) < 1) { - if (Math.abs(formattedValue) < 0.00000001) { - return '0.00000001'; - } + if (Math.abs(formattedValue) < 1) { + if (Math.abs(formattedValue) < 0.00000001) { + return '0.00000001'; + } - return formattedValue.toFixed( - Math.min(8, formattedValue.toString().split('.')[1]?.length || 8) - ); - } + return formattedValue.toFixed( + Math.min(8, formattedValue.toString().split('.')[1]?.length || 8) + ); + } - const decimalPlaces = formattedValue.toString().split('.')[1]?.length || 0; - return decimalPlaces > 4 - ? formattedValue.toFixed(4) - : formattedValue.toString(); + const decimalPlaces = formattedValue.toString().split('.')[1]?.length || 0; + return decimalPlaces > 4 + ? formattedValue.toFixed(4) + : formattedValue.toString(); }; diff --git a/packages/apps/dashboard/ui-2024/src/helpers/formatNumber.ts b/packages/apps/dashboard/ui-2024/src/helpers/formatNumber.ts index 7ad8c999e6..029a6ae604 100644 --- a/packages/apps/dashboard/ui-2024/src/helpers/formatNumber.ts +++ b/packages/apps/dashboard/ui-2024/src/helpers/formatNumber.ts @@ -1,11 +1,11 @@ export const formatNumber = (number: number) => { - if (number >= 1000000) { - return `${(number / 1000000).toFixed()} M`; - } + if (number >= 1000000) { + return `${(number / 1000000).toFixed()} M`; + } - if (number >= 1000) { - return `${(number / 1000).toFixed()} K`; - } + if (number >= 1000) { + return `${(number / 1000).toFixed()} K`; + } - return `${number.toString()}`; + return `${number.toString()}`; }; diff --git a/packages/apps/dashboard/ui-2024/src/main.tsx b/packages/apps/dashboard/ui-2024/src/main.tsx index 72d76fdfc6..6d62a8b395 100644 --- a/packages/apps/dashboard/ui-2024/src/main.tsx +++ b/packages/apps/dashboard/ui-2024/src/main.tsx @@ -9,19 +9,19 @@ import 'simplebar-react/dist/simplebar.min.css'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; const queryClient = new QueryClient({ - defaultOptions: { - mutations: { retry: 0 }, - queries: { retry: 0 }, - }, + defaultOptions: { + mutations: { retry: 0 }, + queries: { retry: 0 }, + }, }); ReactDOM.createRoot(document.getElementById('root')!).render( - - - - - - - - + + + + + + + + ); diff --git a/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx b/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx index 4fdd2ff0ac..22e6e35593 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx @@ -12,51 +12,51 @@ import { useGraphPageChartParams } from '@utils/hooks/use-graph-page-chart-param type graphType = 'bucketed'; const Graph = () => { - const [graphType, setGraphType] = useState('bucketed'); - const handleGraphTypeChange = (_: unknown, newValue: graphType) => { - setGraphType(newValue); - }; - const { revertToInitialParams } = useGraphPageChartParams(); + const [graphType, setGraphType] = useState('bucketed'); + const handleGraphTypeChange = (_: unknown, newValue: graphType) => { + setGraphType(newValue); + }; + const { revertToInitialParams } = useGraphPageChartParams(); - useEffect(() => { - revertToInitialParams(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + useEffect(() => { + revertToInitialParams(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); - return ( - - - - - - Bucketed - - } - value="bucketed" - /> - - - - - - - ); + return ( + + + + + + Bucketed + + } + value="bucketed" + /> + + + + + + + ); }; export default Graph; diff --git a/packages/apps/dashboard/ui-2024/src/pages/Home/HMTPrice.tsx b/packages/apps/dashboard/ui-2024/src/pages/Home/HMTPrice.tsx index a7f1e2e23c..20b9474c58 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Home/HMTPrice.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Home/HMTPrice.tsx @@ -2,17 +2,17 @@ import { useHMTPrice } from '../../services/api/use-hmt-price'; import Typography from '@mui/material/Typography'; export function HMTPrice() { - const { data, status } = useHMTPrice(); - return ( -
- - HMT Price - -
- {status === 'success' && `$${data.hmtPrice}`} - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
- ); + const { data, status } = useHMTPrice(); + return ( +
+ + HMT Price + +
+ {status === 'success' && `$${data.hmtPrice}`} + {status === 'pending' && '...'} + {status === 'error' && 'No data'} +
+
+ ); } diff --git a/packages/apps/dashboard/ui-2024/src/pages/Home/Holders.tsx b/packages/apps/dashboard/ui-2024/src/pages/Home/Holders.tsx index dd5d92e504..d72698569e 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Home/Holders.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Home/Holders.tsx @@ -3,18 +3,18 @@ import Typography from '@mui/material/Typography'; import { useGeneralStats } from '@services/api/use-general-stats'; export function Holders() { - const { data, status } = useGeneralStats(); + const { data, status } = useGeneralStats(); - return ( -
- - Holders - -
- {status === 'success' && } - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
- ); + return ( +
+ + Holders + +
+ {status === 'success' && } + {status === 'pending' && '...'} + {status === 'error' && 'No data'} +
+
+ ); } diff --git a/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx b/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx index 4bbf466c8f..3203107681 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx @@ -18,115 +18,115 @@ import { colorPalette } from '@assets/styles/color-palette'; import CustomTooltip from '@components/CustomTooltip'; const Home: React.FC = () => { - const { - mobile: { isMobile }, - } = useBreakPoints(); - return ( - -
- - All HUMAN activity. In one place. - - -
-
-
-
Token
-
-
- - - -
- -
- -
-
- - - -
- -
-
-
-
- Data Overview - -
-
-
- - - -
- -
- -
-
- - - -
- -
-
-
- -
-
- } - /> - -
- ); + const { + mobile: { isMobile }, + } = useBreakPoints(); + return ( + +
+ + All HUMAN activity. In one place. + + +
+
+
+
Token
+
+
+ + + +
+ +
+ +
+
+ + + +
+ +
+
+
+
+ Data Overview + +
+
+
+ + + +
+ +
+ +
+
+ + + +
+ +
+
+
+ +
+
+ } + /> + +
+ ); }; export default Home; diff --git a/packages/apps/dashboard/ui-2024/src/pages/Home/Leaderboard.tsx b/packages/apps/dashboard/ui-2024/src/pages/Home/Leaderboard.tsx index bd430a7e6e..2b62b4f33e 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Home/Leaderboard.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Home/Leaderboard.tsx @@ -2,15 +2,15 @@ import { useLeaderboardDetails } from '@services/api/use-leaderboard-details'; import { Leaderboard as LeaderboardFeature } from '../../features/Leaderboard'; export const Leaderboard = () => { - const { data, status, error } = useLeaderboardDetails(); - const isMoreThatFiveEntries = data?.length && data.length > 5; + const { data, status, error } = useLeaderboardDetails(); + const isMoreThatFiveEntries = data?.length && data.length > 5; - return ( - - ); + return ( + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/Home/TotalNumberOfTasks.tsx b/packages/apps/dashboard/ui-2024/src/pages/Home/TotalNumberOfTasks.tsx index 3333cd49da..26a8bb850d 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Home/TotalNumberOfTasks.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Home/TotalNumberOfTasks.tsx @@ -3,18 +3,18 @@ import Typography from '@mui/material/Typography'; import { FormatNumber } from '@components/Home/FormatNumber'; export function TotalNumberOfTasks() { - const { data, status } = useHcaptchaGeneralStats(); + const { data, status } = useHcaptchaGeneralStats(); - return ( -
- - Total Number of Tasks - -
- {status === 'success' && } - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
- ); + return ( +
+ + Total Number of Tasks + +
+ {status === 'success' && } + {status === 'pending' && '...'} + {status === 'error' && 'No data'} +
+
+ ); } diff --git a/packages/apps/dashboard/ui-2024/src/pages/Home/TotalTransactions.tsx b/packages/apps/dashboard/ui-2024/src/pages/Home/TotalTransactions.tsx index c3058f5357..82bf49cab7 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Home/TotalTransactions.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Home/TotalTransactions.tsx @@ -3,20 +3,20 @@ import Typography from '@mui/material/Typography'; import { useGeneralStats } from '@services/api/use-general-stats'; export function TotalTransactions() { - const { data, status } = useGeneralStats(); + const { data, status } = useGeneralStats(); - return ( -
- - Total Transactions - -
- {status === 'success' && ( - - )} - {status === 'pending' && '...'} - {status === 'error' && 'No data'} -
-
- ); + return ( +
+ + Total Transactions + +
+ {status === 'success' && ( + + )} + {status === 'pending' && '...'} + {status === 'error' && 'No data'} +
+
+ ); } diff --git a/packages/apps/dashboard/ui-2024/src/pages/Leaderboard/index.tsx b/packages/apps/dashboard/ui-2024/src/pages/Leaderboard/index.tsx index 88d2a740ff..bbfc892e6f 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Leaderboard/index.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Leaderboard/index.tsx @@ -6,22 +6,22 @@ import { useLeaderboardAllDetails } from '@services/api/use-leaderboard-all-deta import { LeaderboardIcon } from '@components/Icons/LeaderboardIcon'; export const LeaderBoard = () => { - const { data, status, error } = useLeaderboardAllDetails(); - const isMoreThatFiveEntries = data?.length && data.length > 5; + const { data, status, error } = useLeaderboardAllDetails(); + const isMoreThatFiveEntries = data?.length && data.length > 5; - return ( - - - } - /> - - - ); + return ( + + + } + /> + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx index d37bbd9dd7..2a774f6b9c 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/EscrowAddress.tsx @@ -8,142 +8,142 @@ import { AddressDetailsEscrowSchema } from '@services/api/use-address-details'; import { HMTBalance } from '@pages/SearchResults/EscrowAddress/HMTBalance'; const EscrowAddress = ({ - data: { - token, - balance, - factoryAddress, - totalFundedAmount, - amountPaid, - status, - launcher, - exchangeOracle, - recordingOracle, - reputationOracle, - }, + data: { + token, + balance, + factoryAddress, + totalFundedAmount, + amountPaid, + status, + launcher, + exchangeOracle, + recordingOracle, + reputationOracle, + }, }: { - data: AddressDetailsEscrowSchema; + data: AddressDetailsEscrowSchema; }) => { - return ( - - - - {token} - - {balance !== undefined && balance !== null ? ( - - - - ) : null} - - {factoryAddress} - - - - {totalFundedAmount} - - HMT - - - - - - {amountPaid} - - HMT - - - + return ( + + + + {token} + + {balance !== undefined && balance !== null ? ( + + + + ) : null} + + {factoryAddress} + + + + {totalFundedAmount} + + HMT + + + + + + {amountPaid} + + HMT + + + - - - - {status} - - - + + + + {status} + + + - - - {launcher} - - + + + {launcher} + + - - {exchangeOracle} - + + {exchangeOracle} + - - {recordingOracle} - + + {recordingOracle} + - - {reputationOracle} - - - - ); + + {reputationOracle} + + + + ); }; export default EscrowAddress; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/HMTBalance.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/HMTBalance.tsx index ff2bcad48e..839e28393a 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/HMTBalance.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/EscrowAddress/HMTBalance.tsx @@ -4,30 +4,30 @@ import Typography from '@mui/material/Typography'; import { useHMTPrice } from '@services/api/use-hmt-price'; export const HMTBalance = ({ HMTBalance }: { HMTBalance: number }) => { - const { data, isError, isPending } = useHMTPrice(); + const { data, isError, isPending } = useHMTPrice(); - if (isError) { - return N/A; - } + if (isError) { + return N/A; + } - if (isPending) { - return ...; - } - const HMTBalanceInDollars = HMTBalance * data.hmtPrice; + if (isPending) { + return ...; + } + const HMTBalanceInDollars = HMTBalance * data.hmtPrice; - return ( - - {HMTBalance} - - {`HMT($${HMTBalanceInDollars.toFixed(2)})`} - - - ); + return ( + + {HMTBalance} + + {`HMT($${HMTBalanceInDollars.toFixed(2)})`} + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetails.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetails.tsx index eaa5d5fa16..5e050e1a85 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetails.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetails.tsx @@ -20,404 +20,373 @@ import { FormatNumberWithDecimals } from '@components/Home/FormatNumber'; import CustomTooltip from '@components/CustomTooltip'; interface RoleInfoProps { - title: string; - points: string[]; + title: string; + points: string[]; } const RoleInformation = ({ title, points }: RoleInfoProps) => { - return ( - - {title} -
    - {points.map((elem, idx) => ( -
  • - {elem} -
  • - ))} -
-
- ); + return ( + + {title} +
    + {points.map((elem, idx) => ( +
  • + {elem} +
  • + ))} +
+
+ ); }; const RenderRoleDetailsInfo = ({ - role, + role, }: { - role: AddressDetailsLeader['role']; + role: AddressDetailsLeader['role']; }) => { - if (!role) { - return null; - } + if (!role) { + return null; + } - const roleDetailsInfo: Partial< - Record - > = { - [Roles.reputationOracle]: { - title: 'Reputation Oracle', - points: [ - 'The Reputation Oracle is the trust engine of HUMAN Protocol.', - 'It cross-checks validated solutions from the Recording Oracle, adjusts reputation scores, and manages payments.', - "It's the final seal of quality and trust within the ecosystem.", - ], - }, - [Roles.recordingOracle]: { - title: 'Recording Oracle', - points: [ - 'The Recording Oracle is where task solutions get the green light.', - 'It is storing, and recording task solutions on the blockchain.', - "From quality checks to reputation adjustments, it's the assurance you need for dependable results.", - ], - }, - [Roles.exchangeOracle]: { - title: 'Exchange Oracle', - points: [ - "The Exchange Oracle is the HUMAN Protocol's powerhouse, directing tasks to skilled workers and ensuring smooth communication.", - 'It validates solutions, provides job updates, and handles cancellations, streamlining the job lifecycle.', - ], - }, - [Roles.jobLauncher]: { - title: 'Job Launcher', - points: [ - 'The Job Launcher is a tool that allows anybody to create and launch jobs, to be distributed as tasks through the HUMAN App.', - ], - }, - }; + const roleDetailsInfo: Partial< + Record + > = { + [Roles.reputationOracle]: { + title: 'Reputation Oracle', + points: [ + 'The Reputation Oracle is the trust engine of HUMAN Protocol.', + 'It cross-checks validated solutions from the Recording Oracle, adjusts reputation scores, and manages payments.', + "It's the final seal of quality and trust within the ecosystem.", + ], + }, + [Roles.recordingOracle]: { + title: 'Recording Oracle', + points: [ + 'The Recording Oracle is where task solutions get the green light.', + 'It is storing, and recording task solutions on the blockchain.', + "From quality checks to reputation adjustments, it's the assurance you need for dependable results.", + ], + }, + [Roles.exchangeOracle]: { + title: 'Exchange Oracle', + points: [ + "The Exchange Oracle is the HUMAN Protocol's powerhouse, directing tasks to skilled workers and ensuring smooth communication.", + 'It validates solutions, provides job updates, and handles cancellations, streamlining the job lifecycle.', + ], + }, + [Roles.jobLauncher]: { + title: 'Job Launcher', + points: [ + 'The Job Launcher is a tool that allows anybody to create and launch jobs, to be distributed as tasks through the HUMAN App.', + ], + }, + }; - const details = roleDetailsInfo[role]; + const details = roleDetailsInfo[role]; - if (!details) { - return null; - } + if (!details) { + return null; + } - return ; + return ; }; const renderReputationTitle = (reputation: Reputation) => { - const reputationAttributes: Record< - Reputation, - { title: string; colors: { title: string; border: string } } - > = { - High: { - title: 'High', - colors: { - title: colorPalette.success.main, - border: colorPalette.success.light, - }, - }, - Medium: { - title: 'Medium', - colors: { - title: colorPalette.warning.main, - border: colorPalette.warning.light, - }, - }, + const reputationAttributes: Record< + Reputation, + { title: string; colors: { title: string; border: string } } + > = { + High: { + title: 'High', + colors: { + title: colorPalette.success.main, + border: colorPalette.success.light, + }, + }, + Medium: { + title: 'Medium', + colors: { + title: colorPalette.warning.main, + border: colorPalette.warning.light, + }, + }, - Low: { - title: 'Low', - colors: { - title: colorPalette.orange.main, - border: colorPalette.orange.light, - }, - }, - Unknown: { - title: 'Coming soon', - colors: { - title: colorPalette.ocean.main, - border: colorPalette.ocean.light, - }, - }, - }; + Low: { + title: 'Low', + colors: { + title: colorPalette.orange.main, + border: colorPalette.orange.light, + }, + }, + Unknown: { + title: 'Coming soon', + colors: { + title: colorPalette.ocean.main, + border: colorPalette.ocean.light, + }, + }, + }; - const colors = reputationAttributes[reputation].colors; + const colors = reputationAttributes[reputation].colors; - return ( - - - {reputationAttributes[reputation].title} - - - ); + return ( + + + {reputationAttributes[reputation].title} + + + ); }; const renderRoleIcon = (role: AddressDetailsLeader['role']) => { - if (!role) return null; - const roleIcons = { - [Roles.reputationOracle]: , - [Roles.exchangeOracle]: , - [Roles.humanApp]: , - [Roles.jobLauncher]: , - [Roles.recordingOracle]: , - }; + if (!role) return null; + const roleIcons = { + [Roles.reputationOracle]: , + [Roles.exchangeOracle]: , + [Roles.humanApp]: , + [Roles.jobLauncher]: , + [Roles.recordingOracle]: , + }; - return roleIcons[role]; + return roleIcons[role]; }; const RoleDetails = ({ - data: { - role, - chainId, - reputation, - amountJobsProcessed, - amountStaked, - amountAllocated, - amountLocked, - }, + data: { + role, + chainId, + reputation, + amountJobsProcessed, + amountStaked, + amountLocked, + }, }: { - data: AddressDetailsLeader; + data: AddressDetailsLeader; }) => { - const { filterParams } = useWalletSearch(); + const { filterParams } = useWalletSearch(); - return ( - <> - - - - Overview - - {env.VITE_HUMANPROTOCOL_CORE_ARCHITECTURE ? ( - - - HUMAN Protocol core architecture - - - ) : null} - - - - - Role - - - {renderRoleIcon(role)} - - - - - - Network - - - {getNetwork(chainId)?.name || ''} - - - - - - - - - - Reputation Score - - {renderReputationTitle(reputation)} - - - - Jobs Launched - - {amountJobsProcessed} - - - + return ( + <> + + + + Overview + + {env.VITE_HUMANPROTOCOL_CORE_ARCHITECTURE ? ( + + + HUMAN Protocol core architecture + + + ) : null} + + + + + Role + + + {renderRoleIcon(role)} + + + + + + Network + + + {getNetwork(chainId)?.name || ''} + + + + + + + + + + Reputation Score + + {renderReputationTitle(reputation)} + + + + Jobs Launched + + {amountJobsProcessed} + + + - - - - Stake Info - - - - {amountStaked !== undefined && amountStaked !== null ? ( - - - Tokens Staked - - - - - - - HMT - - - - ) : null} - {amountAllocated !== undefined && amountAllocated !== null ? ( - - - Tokens Allocated - - - - - - - HMT - - - - ) : null} - {amountLocked !== undefined && amountLocked !== null ? ( - - - Tokens Locked - - - - - - - HMT - - - - ) : null} - - + + + + Stake Info + + + + {amountStaked !== undefined && amountStaked !== null ? ( + + + Tokens Staked + + + + + + + HMT + + + + ) : null} + {amountLocked !== undefined && amountLocked !== null ? ( + + + Tokens Locked + + + + + + + HMT + + + + ) : null} + + - {filterParams.address && filterParams.chainId ? ( - - ) : null} - - ); + {filterParams.address && filterParams.chainId ? ( + + ) : null} + + ); }; export default RoleDetails; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx index e94d3721e6..fa1421228d 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx @@ -13,97 +13,97 @@ import TableRow from '@mui/material/TableRow'; import { Stack } from '@mui/material'; export const RoleDetailsEscrowsTable = ({ - role, + role, }: { - role: AddressDetailsLeader['role']; + role: AddressDetailsLeader['role']; }) => { - const { data } = useEscrowDetails({ role }); - const { - pagination: { page, pageSize, lastPageIndex }, - setPageSize, - setNextPage, - setPrevPage, - } = useEscrowDetailsDto(); + const { data } = useEscrowDetails({ role }); + const { + pagination: { page, pageSize, lastPageIndex }, + setPageSize, + setNextPage, + setPrevPage, + } = useEscrowDetailsDto(); - return ( - - - - Escrows - - -
- - - - -
- - - {}} - page={page} - rowsPerPage={pageSize} - onRowsPerPageChange={(event) => { - setPageSize(Number(event.target.value)); - }} - rowsPerPageOptions={[5, 10]} - labelDisplayedRows={({ from, to }) => { - const effectiveTo = data?.results - ? from + data.results.length - 1 - : to; - return `${from}–${effectiveTo}`; - }} - component="div" - slotProps={{ - actions: { - nextButton: { - onClick: () => { - setNextPage(); - }, - disabled: - lastPageIndex !== undefined && - (page === lastPageIndex || lastPageIndex - 1 === page), - }, - previousButton: { - onClick: () => { - setPrevPage(); - }, - }, - }, - }} - /> - - -
- ); + return ( + + + + Escrows + + + + + + + +
+
+ + {}} + page={page} + rowsPerPage={pageSize} + onRowsPerPageChange={(event) => { + setPageSize(Number(event.target.value)); + }} + rowsPerPageOptions={[5, 10]} + labelDisplayedRows={({ from, to }) => { + const effectiveTo = data?.results + ? from + data.results.length - 1 + : to; + return `${from}–${effectiveTo}`; + }} + component="div" + slotProps={{ + actions: { + nextButton: { + onClick: () => { + setNextPage(); + }, + disabled: + lastPageIndex !== undefined && + (page === lastPageIndex || lastPageIndex - 1 === page), + }, + previousButton: { + onClick: () => { + setPrevPage(); + }, + }, + }, + }} + /> + +
+
+ ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx index 9743deb7cf..1084611602 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx @@ -12,88 +12,88 @@ import { useNavigate } from 'react-router-dom'; import { Stack, TableRow } from '@mui/material'; export const EscrowsTableBody = ({ - role, + role, }: { - role: AddressDetailsLeader['role']; + role: AddressDetailsLeader['role']; }) => { - const navigate = useNavigate(); - const { filterParams } = useWalletSearch(); - const { data, isPending, isError, error } = useEscrowDetails({ role }); - const { - setLastPageIndex, - setPrevPage, - pagination: { page }, - } = useEscrowDetailsDto(); + const navigate = useNavigate(); + const { filterParams } = useWalletSearch(); + const { data, isPending, isError, error } = useEscrowDetails({ role }); + const { + setLastPageIndex, + setPrevPage, + pagination: { page }, + } = useEscrowDetailsDto(); - useEffect(() => { - if (data?.results.length === 0) { - setLastPageIndex(page); - setPrevPage(); - } - }, [data?.results, page, setLastPageIndex, setPrevPage]); + useEffect(() => { + if (data?.results.length === 0) { + setLastPageIndex(page); + setPrevPage(); + } + }, [data?.results, page, setLastPageIndex, setPrevPage]); - useEffect(() => { - setLastPageIndex(undefined); - }, [filterParams.address, filterParams.chainId, setLastPageIndex]); + useEffect(() => { + setLastPageIndex(undefined); + }, [filterParams.address, filterParams.chainId, setLastPageIndex]); - if (isPending) { - return ( - - - - ); - } + if (isPending) { + return ( + + + + ); + } - if (isError) { - return ( - -
{handleErrorMessage(error)}
-
- ); - } + if (isError) { + return ( + +
{handleErrorMessage(error)}
+
+ ); + } - if (!data.results.length) { - return ( - -
No escrows launched yet
-
- ); - } + if (!data.results.length) { + return ( + +
No escrows launched yet
+
+ ); + } - return ( - - {data.results.map((elem, idx) => ( - - - { - e.stopPropagation(); - e.preventDefault(); - navigate(`/search/${filterParams.chainId}/${elem.address}`); - }} - > - - {elem.address} - - - - - ))} - - ); + return ( + + {data.results.map((elem, idx) => ( + + + { + e.stopPropagation(); + e.preventDefault(); + navigate(`/search/${filterParams.chainId}/${elem.address}`); + }} + > + + {elem.address} + + + + + ))} + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBodyContainer.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBodyContainer.tsx index 0396b5e791..764084e4cd 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBodyContainer.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBodyContainer.tsx @@ -2,27 +2,27 @@ import MuiTableBody from '@mui/material/TableBody'; import { Grid } from '@mui/material'; export const EscrowsTableBodyContainer = ({ - children, + children, }: { - children: JSX.Element; + children: JSX.Element; }) => { - return ( - - - {children} - - - ); + return ( + + + {children} + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx index 18ee3f8d02..9759f254ff 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx @@ -13,9 +13,9 @@ import { useWalletSearch } from '@utils/hooks/use-wallet-search'; import Loader from '@components/Loader'; import { getNetwork } from '@utils/config/networks'; import { - AddressDetails, - AddressDetailsWallet, - useAddressDetails, + AddressDetails, + AddressDetailsWallet, + useAddressDetails, } from '@services/api/use-address-details'; import { handleErrorMessage } from '@services/handle-error-message'; import RoleDetails from '@pages/SearchResults/RoleDetails/RoleDetails'; @@ -24,151 +24,151 @@ import { WalletIcon } from '@components/Icons/WalletIcon'; import { EscrowAddressIcon } from '@components/Icons/EscrowAddressIcon'; const renderCurrentResultType = ( - addressDetails: AddressDetails, - tokenId: string | undefined + addressDetails: AddressDetails, + tokenId: string | undefined ) => { - const type = Object.keys(addressDetails)[0] as - | keyof AddressDetails - | undefined; - - const renderType: Record< - keyof AddressDetails, - { title: string; icon: JSX.Element } - > = { - leader: { - title: 'Wallet Address', - icon: , - }, - escrow: { - title: 'Escrow Address', - icon: , - }, - wallet: { - title: 'Wallet Address', - icon: , - }, - }; - - if (type == null) { - return null; - } - - return ( - <> - - - - ); + const type = Object.keys(addressDetails)[0] as + | keyof AddressDetails + | undefined; + + const renderType: Record< + keyof AddressDetails, + { title: string; icon: JSX.Element } + > = { + leader: { + title: 'Wallet Address', + icon: , + }, + escrow: { + title: 'Escrow Address', + icon: , + }, + wallet: { + title: 'Wallet Address', + icon: , + }, + }; + + if (type == null) { + return null; + } + + return ( + <> + + + + ); }; const ResultError = ({ error }: { error: unknown }) => { - if (error instanceof AxiosError && error.response?.status === 400) { - return ( - - - - ); - } - return {handleErrorMessage(error)}; + if (error instanceof AxiosError && error.response?.status === 400) { + return ( + + + + ); + } + return {handleErrorMessage(error)}; }; const Results = () => { - const { data, status, error } = useAddressDetails(); - const { filterParams } = useWalletSearch(); - - if (status === 'pending' && !data) { - return ; - } - - if (status === 'error') { - return ; - } - - const selectedWalletData: AddressDetailsWallet | undefined = - data.wallet || - (data.leader && data.leader.role === null ? data.leader : undefined); - - return ( - <> - - {renderCurrentResultType(data, filterParams.address)} - - - {data.leader && data.leader.role ? ( - - ) : null} - {selectedWalletData ? : null} - {data.escrow ? : null} - - ); + const { data, status, error } = useAddressDetails(); + const { filterParams } = useWalletSearch(); + + if (status === 'pending' && !data) { + return ; + } + + if (status === 'error') { + return ; + } + + const selectedWalletData: AddressDetailsWallet | undefined = + data.wallet || + (data.leader && data.leader.role === null ? data.leader : undefined); + + return ( + <> + + {renderCurrentResultType(data, filterParams.address)} + + + {data.leader && data.leader.role ? ( + + ) : null} + {selectedWalletData ? : null} + {data.escrow ? : null} + + ); }; const SearchResults = () => { - const location = useLocation(); - const { chainId: urlChainId, address: urlAddress } = useParams(); - const { - setAddress, - setChainId, - filterParams: { chainId, address }, - } = useWalletSearch(); - const [paramsStatus, setParamsStatus] = useState< - 'loading' | 'error' | 'success' - >('loading'); - - useEffect(() => { - setParamsStatus('loading'); - }, [location]); - - useEffect(() => { - if (paramsStatus === 'success') return; - if (urlAddress) { - setAddress(urlAddress); - } else { - setParamsStatus('error'); - return; - } - const chainIdFromUrl = Number(urlChainId); - if ( - !Number.isNaN(chainIdFromUrl) && - chainIdFromUrl && - getNetwork(chainIdFromUrl) - ) { - setChainId(chainIdFromUrl); - } else { - setParamsStatus('error'); - } - }, [ - address, - chainId, - paramsStatus, - setAddress, - setChainId, - urlAddress, - urlChainId, - ]); - - useEffect(() => { - if (address && chainId && paramsStatus !== 'success') { - setParamsStatus('success'); - } - }, [address, chainId, paramsStatus]); - - return ( - - - - {paramsStatus === 'loading' && } - {paramsStatus === 'error' && ( - Something went wrong - )} - {paramsStatus === 'success' && } - - ); + const location = useLocation(); + const { chainId: urlChainId, address: urlAddress } = useParams(); + const { + setAddress, + setChainId, + filterParams: { chainId, address }, + } = useWalletSearch(); + const [paramsStatus, setParamsStatus] = useState< + 'loading' | 'error' | 'success' + >('loading'); + + useEffect(() => { + setParamsStatus('loading'); + }, [location]); + + useEffect(() => { + if (paramsStatus === 'success') return; + if (urlAddress) { + setAddress(urlAddress); + } else { + setParamsStatus('error'); + return; + } + const chainIdFromUrl = Number(urlChainId); + if ( + !Number.isNaN(chainIdFromUrl) && + chainIdFromUrl && + getNetwork(chainIdFromUrl) + ) { + setChainId(chainIdFromUrl); + } else { + setParamsStatus('error'); + } + }, [ + address, + chainId, + paramsStatus, + setAddress, + setChainId, + urlAddress, + urlChainId, + ]); + + useEffect(() => { + if (address && chainId && paramsStatus !== 'success') { + setParamsStatus('success'); + } + }, [address, chainId, paramsStatus]); + + return ( + + + + {paramsStatus === 'loading' && } + {paramsStatus === 'error' && ( + Something went wrong + )} + {paramsStatus === 'success' && } + + ); }; export default SearchResults; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddress.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddress.tsx index 4318232ece..c127024544 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddress.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddress.tsx @@ -11,92 +11,92 @@ import { NumericFormat } from 'react-number-format'; import { useBreakPoints } from '@utils/hooks/use-is-mobile'; const HmtPrice = () => { - const { - data: hmtPrice, - isError: isHmtPriceError, - isPending: isHmtPricePending, - } = useHMTPrice(); + const { + data: hmtPrice, + isError: isHmtPriceError, + isPending: isHmtPricePending, + } = useHMTPrice(); - if (isHmtPriceError) { - return N/A; - } + if (isHmtPriceError) { + return N/A; + } - if (isHmtPricePending) { - return ...; - } + if (isHmtPricePending) { + return ...; + } - return ( - - - - <>{hmtPrice.hmtPrice} - - - $ - - - - ); + return ( + + + + <>{hmtPrice.hmtPrice} + + + $ + + + + ); }; const WalletAddress = ({ - data: { balance }, + data: { balance }, }: { - data: AddressDetailsWallet; + data: AddressDetailsWallet; }) => { - const { filterParams } = useWalletSearch(); - const { mobile } = useBreakPoints(); + const { filterParams } = useWalletSearch(); + const { mobile } = useBreakPoints(); - return ( - <> - - - - - - - - - HMT - - - - - - + return ( + <> + + + + + + + + + HMT + + + + + + - {filterParams.address && filterParams.chainId ? ( - - ) : null} - - ); + {filterParams.address && filterParams.chainId ? ( + + ) : null} + + ); }; export default WalletAddress; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx index 098e47d6a3..62992706eb 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/WalletAddressTransactionsTable.tsx @@ -11,83 +11,83 @@ import { TableFooter } from '@mui/material'; import { useTransactionDetails } from '@services/api/use-transaction-details'; export const WalletAddressTransactionsTable = () => { - const { data } = useTransactionDetails(); - const { - pagination: { page, pageSize, lastPageIndex }, - setPageSize, - setNextPage, - setPrevPage, - } = useTransactionDetailsDto(); + const { data } = useTransactionDetails(); + const { + pagination: { page, pageSize, lastPageIndex }, + setPageSize, + setNextPage, + setPrevPage, + } = useTransactionDetailsDto(); - return ( - - - Transactions - - - - - - - - - {}} - page={page} - component="td" - rowsPerPage={pageSize} - onRowsPerPageChange={(event) => { - setPageSize(Number(event.target.value)); - }} - rowsPerPageOptions={[5, 10]} - labelDisplayedRows={({ from, to }) => { - const effectiveTo = data?.results - ? from + data.results.length - 1 - : to; - return `${from}–${effectiveTo}`; - }} - slotProps={{ - actions: { - nextButton: { - onClick: () => { - setNextPage(); - }, - disabled: - lastPageIndex !== undefined && - (page === lastPageIndex || - lastPageIndex - 1 === page), - }, - previousButton: { - onClick: () => { - setPrevPage(); - }, - }, - }, - }} - /> - - -
-
-
-
- ); + return ( + + + Transactions + + + + + + + + + {}} + page={page} + component="td" + rowsPerPage={pageSize} + onRowsPerPageChange={(event) => { + setPageSize(Number(event.target.value)); + }} + rowsPerPageOptions={[5, 10]} + labelDisplayedRows={({ from, to }) => { + const effectiveTo = data?.results + ? from + data.results.length - 1 + : to; + return `${from}–${effectiveTo}`; + }} + slotProps={{ + actions: { + nextButton: { + onClick: () => { + setNextPage(); + }, + disabled: + lastPageIndex !== undefined && + (page === lastPageIndex || + lastPageIndex - 1 === page), + }, + previousButton: { + onClick: () => { + setPrevPage(); + }, + }, + }, + }} + /> + + +
+
+
+
+ ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx index 712304bf13..af088b3ff5 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx @@ -4,44 +4,44 @@ import Typography from '@mui/material/Typography'; import { capitalize } from '@mui/material'; export const TransactionTableCellMethod = ({ method }: { method: string }) => { - const methodAttributes: Record< - string, - { color: { text: string; border: string } } - > = { - transfer: { - color: { - text: colorPalette.success.main, - border: colorPalette.success.light, - }, - }, - complete: { - color: { - text: colorPalette.success.main, - border: colorPalette.success.light, - }, - }, - payout: { - color: { - text: colorPalette.secondary.main, - border: colorPalette.secondary.light, - }, - }, - }; + const methodAttributes: Record< + string, + { color: { text: string; border: string } } + > = { + transfer: { + color: { + text: colorPalette.success.main, + border: colorPalette.success.light, + }, + }, + complete: { + color: { + text: colorPalette.success.main, + border: colorPalette.success.light, + }, + }, + payout: { + color: { + text: colorPalette.secondary.main, + border: colorPalette.secondary.light, + }, + }, + }; - const currentStatusColors = - methodAttributes[method]?.color || colorPalette.success.main; + const currentStatusColors = + methodAttributes[method]?.color || colorPalette.success.main; - return ( - - {capitalize(method)} - - ); + return ( + + {capitalize(method)} + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx index 3aecdf1675..6e18d806de 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue.tsx @@ -3,20 +3,20 @@ import Typography from '@mui/material/Typography'; import { useHMTPrice } from '@services/api/use-hmt-price'; export const TransactionTableCellValue = ({ value }: { value: string }) => { - const { isError, isPending } = useHMTPrice(); + const { isError, isPending } = useHMTPrice(); - if (isError) { - return N/A; - } + if (isError) { + return N/A; + } - if (isPending) { - return ...; - } + if (isPending) { + return ...; + } - return ( - - {formatHMTDecimals(value)} - HMT - - ); + return ( + + {formatHMTDecimals(value)} + HMT + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx index 9d7a8e8c38..bcffdb7470 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx @@ -13,72 +13,72 @@ import CircularProgress from '@mui/material/CircularProgress'; import { useWalletSearch } from '@utils/hooks/use-wallet-search'; export const TransactionsTableBody = () => { - const { data, isPending, isError, error } = useTransactionDetails(); - const { filterParams } = useWalletSearch(); - const { - setLastPageIndex, - setPrevPage, - pagination: { page }, - } = useTransactionDetailsDto(); + const { data, isPending, isError, error } = useTransactionDetails(); + const { filterParams } = useWalletSearch(); + const { + setLastPageIndex, + setPrevPage, + pagination: { page }, + } = useTransactionDetailsDto(); - useEffect(() => { - if (data?.results.length === 0) { - setLastPageIndex(page); - setPrevPage(); - } - }, [data?.results, page, setLastPageIndex, setPrevPage]); + useEffect(() => { + if (data?.results.length === 0) { + setLastPageIndex(page); + setPrevPage(); + } + }, [data?.results, page, setLastPageIndex, setPrevPage]); - useEffect(() => { - setLastPageIndex(undefined); - }, [filterParams.address, filterParams.chainId, setLastPageIndex]); + useEffect(() => { + setLastPageIndex(undefined); + }, [filterParams.address, filterParams.chainId, setLastPageIndex]); - if (isPending) { - return ( - - - - ); - } + if (isPending) { + return ( + + + + ); + } - if (isError) { - return ( - -
{handleErrorMessage(error)}
-
- ); - } + if (isError) { + return ( + +
{handleErrorMessage(error)}
+
+ ); + } - if (!data.results.length) { - return ( - -
No data
-
- ); - } + if (!data.results.length) { + return ( + +
No data
+
+ ); + } - return ( - - {data.results.map((elem, idx) => ( - - - - - - - - {elem.block} - - - - - - - - ))} - - ); + return ( + + {data.results.map((elem, idx) => ( + + + + + + + + {elem.block} + + + + + + + + ))} + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBodyContainer.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBodyContainer.tsx index 32e42e9d98..04d9275011 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBodyContainer.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBodyContainer.tsx @@ -2,27 +2,27 @@ import MuiTableBody from '@mui/material/TableBody'; import { Grid } from '@mui/material'; export const TransactionsTableBodyContainer = ({ - children, + children, }: { - children: JSX.Element; + children: JSX.Element; }) => { - return ( - - - {children} - - - ); + return ( + + + {children} + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx index ce995aa953..692f774955 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx @@ -9,85 +9,85 @@ import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; import CustomTooltip from '@components/CustomTooltip'; export const TransactionsTableHead = () => { - return ( - - - - - - - - - - - Transaction Hash - - - - - - - - - - - Method - - - - - - - - - - Block - - - - - - - - - - Value - - - - - Escrow Address - - - - - ); + return ( + + + + + + + + + + + Transaction Hash + + + + + + + + + + + Method + + + + + + + + + + Block + + + + + + + + + + Value + + + + + Escrow Address + + + + + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/services/api-paths.ts b/packages/apps/dashboard/ui-2024/src/services/api-paths.ts index 608ab85c2c..0e767181bb 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api-paths.ts +++ b/packages/apps/dashboard/ui-2024/src/services/api-paths.ts @@ -1,32 +1,32 @@ export const apiPaths = { - hcaptchaGeneralStats: { - path: '/stats/hcaptcha/general', - }, - generalStats: { - path: '/stats/general', - }, - statsHmtPrice: { - path: '/stats/hmt-price', - }, - hmtDailyStats: { - path: '/stats/hmt/daily', - }, - hcaptchaStatsDaily: { - path: '/stats/hcaptcha/daily', - }, - leaderboardDetails: { - path: '/details/leaders', - }, - leaderboardDetailsAll: { - path: '/details/leaders/all', - }, - addressDetails: { - path: '/details', - }, - transactionDetails: { - path: '/details/transactions', - }, - escrowDetails: { - path: '/details/escrows', - }, + hcaptchaGeneralStats: { + path: '/stats/hcaptcha/general', + }, + generalStats: { + path: '/stats/general', + }, + statsHmtPrice: { + path: '/stats/hmt-price', + }, + hmtDailyStats: { + path: '/stats/hmt/daily', + }, + hcaptchaStatsDaily: { + path: '/stats/hcaptcha/daily', + }, + leaderboardDetails: { + path: '/details/leaders', + }, + leaderboardDetailsAll: { + path: '/details/leaders/all', + }, + addressDetails: { + path: '/details', + }, + transactionDetails: { + path: '/details/transactions', + }, + escrowDetails: { + path: '/details/escrows', + }, } as const; diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-address-details.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-address-details.tsx index 997ca6d36c..b61dd32a13 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-address-details.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-address-details.tsx @@ -7,118 +7,114 @@ import { validateResponse } from '../../services/validate-response'; import { reputationSchema } from '@services/api/use-leaderboard-details'; const transformOptionalTokenAmount = ( - value: string | undefined | null, - ctx: z.RefinementCtx + value: string | undefined | null, + ctx: z.RefinementCtx ) => { - if (value === undefined || value === null) return value; + if (value === undefined || value === null) return value; - const valueAsNumber = Number(value); + const valueAsNumber = Number(value); - if (Number.isNaN(valueAsNumber)) { - ctx.addIssue({ - path: ['amountStaked'], - code: z.ZodIssueCode.custom, - }); - } + if (Number.isNaN(valueAsNumber)) { + ctx.addIssue({ + path: ['amountStaked'], + code: z.ZodIssueCode.custom, + }); + } - return valueAsNumber / 10 ** 18; + return valueAsNumber / 10 ** 18; }; const walletSchema = z.object({ - chainId: z.number(), - address: z.string(), - balance: z.string().transform(transformOptionalTokenAmount), + chainId: z.number(), + address: z.string(), + balance: z.string().transform(transformOptionalTokenAmount), }); export type AddressDetailsWallet = z.infer; const escrowSchema = z.object({ - chainId: z.number().optional().nullable(), - address: z.string().optional().nullable(), - balance: z - .string() - .optional() - .nullable() - .transform(transformOptionalTokenAmount), - token: z.string().optional().nullable(), - factoryAddress: z.string().optional().nullable(), - totalFundedAmount: z - .string() - .optional() - .nullable() - .transform(transformOptionalTokenAmount), - amountPaid: z - .string() - .optional() - .nullable() - .transform(transformOptionalTokenAmount), - status: z.string().optional().nullable(), - manifest: z.string().optional().nullable(), - launcher: z.string().optional().nullable(), - exchangeOracle: z.string().optional().nullable(), - recordingOracle: z.string().optional().nullable(), - reputationOracle: z.string().optional().nullable(), - finalResultsUrl: z.string().nullable(), + chainId: z.number().optional().nullable(), + address: z.string().optional().nullable(), + balance: z + .string() + .optional() + .nullable() + .transform(transformOptionalTokenAmount), + token: z.string().optional().nullable(), + factoryAddress: z.string().optional().nullable(), + totalFundedAmount: z + .string() + .optional() + .nullable() + .transform(transformOptionalTokenAmount), + amountPaid: z + .string() + .optional() + .nullable() + .transform(transformOptionalTokenAmount), + status: z.string().optional().nullable(), + manifest: z.string().optional().nullable(), + launcher: z.string().optional().nullable(), + exchangeOracle: z.string().optional().nullable(), + recordingOracle: z.string().optional().nullable(), + reputationOracle: z.string().optional().nullable(), + finalResultsUrl: z.string().nullable(), }); export type AddressDetailsEscrowSchema = z.infer; export enum Roles { - jobLauncher = 'Job Launcher', - exchangeOracle = 'Exchange Oracle', - humanApp = 'Human App', - recordingOracle = 'Recording Oracle', - reputationOracle = 'Reputation Oracle', + jobLauncher = 'Job Launcher', + exchangeOracle = 'Exchange Oracle', + humanApp = 'Human App', + recordingOracle = 'Recording Oracle', + reputationOracle = 'Reputation Oracle', } const leaderSchema = z.object({ - chainId: z.number(), - address: z.string(), - balance: z.string().transform(transformOptionalTokenAmount), - role: z.nativeEnum(Roles).nullable(), - amountStaked: z.string().optional().transform(transformOptionalTokenAmount), - amountAllocated: z - .string() - .optional() - .transform(transformOptionalTokenAmount), - amountLocked: z.string().optional().transform(transformOptionalTokenAmount), - lockedUntilTimestamp: z.string().optional(), - reputation: reputationSchema, - fee: z.number(), - jobTypes: z.array(z.string()).optional().nullable(), - url: z.string().optional().nullable(), - reward: z.string().optional(), - amountJobsProcessed: z.string(), + chainId: z.number(), + address: z.string(), + balance: z.string().transform(transformOptionalTokenAmount), + role: z.nativeEnum(Roles).nullable(), + amountStaked: z.string().optional().transform(transformOptionalTokenAmount), + amountLocked: z.string().optional().transform(transformOptionalTokenAmount), + lockedUntilTimestamp: z.string().optional(), + reputation: reputationSchema, + fee: z.number(), + jobTypes: z.array(z.string()).optional().nullable(), + url: z.string().optional().nullable(), + reward: z.string().optional(), + amountJobsProcessed: z.string(), }); export type AddressDetailsLeader = z.infer; const addressDetailsResponseSchema = z.object({ - wallet: z.optional(walletSchema), - escrow: z.optional(escrowSchema), - leader: z.optional(leaderSchema), + wallet: z.optional(walletSchema), + escrow: z.optional(escrowSchema), + leader: z.optional(leaderSchema), }); export type AddressDetails = z.infer; export function useAddressDetails() { - const { filterParams } = useWalletSearch(); - - return useQuery({ - queryFn: async () => { - const address = filterParams.address || '0x0'; - const { data } = await httpService.get( - `${apiPaths.addressDetails.path}/${address}`, - { params: { chainId: filterParams.chainId || -1 } } - ); - - const validResponse = validateResponse( - data, - addressDetailsResponseSchema - ); - - return validResponse; - }, - queryKey: ['useAddressDetails', filterParams.address, filterParams.chainId], - }); + const { filterParams } = useWalletSearch(); + + return useQuery({ + queryFn: async () => { + const address = filterParams.address || '0x0'; + const { data } = await httpService.get( + `${apiPaths.addressDetails.path}/${address}`, + { params: { chainId: filterParams.chainId || -1 } } + ); + + const validResponse = validateResponse( + data, + addressDetailsResponseSchema + ); + + return validResponse; + }, + queryKey: ['useAddressDetails', filterParams.address, filterParams.chainId], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-escrows-details.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-escrows-details.tsx index 662e6129a4..402e78bd72 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-escrows-details.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-escrows-details.tsx @@ -8,91 +8,91 @@ import { useEscrowDetailsDto } from '@utils/hooks/use-escrows-details-dto'; import { AddressDetailsLeader } from '@services/api/use-address-details'; const escrowDetailsSuccessResponseSchema = z.object({ - chainId: z.number(), - address: z.string(), - status: z.string(), + chainId: z.number(), + address: z.string(), + status: z.string(), }); export type TransactionDetails = z.infer< - typeof escrowDetailsSuccessResponseSchema + typeof escrowDetailsSuccessResponseSchema >; const paginatedEscrowsDetailsSuccessResponseSchema = z.object({ - address: z.string(), - chainId: z.number(), - first: z.number(), - skip: z.number(), - results: z.array(escrowDetailsSuccessResponseSchema), + address: z.string(), + chainId: z.number(), + first: z.number(), + skip: z.number(), + results: z.array(escrowDetailsSuccessResponseSchema), }); export type PaginatedEscrowDetails = z.infer< - typeof paginatedEscrowsDetailsSuccessResponseSchema + typeof paginatedEscrowsDetailsSuccessResponseSchema >; export interface PaginatedEscrowsDetailsDto { - skip: number; - first: number; - chainId: number; - role: AddressDetailsLeader['role']; + skip: number; + first: number; + chainId: number; + role: AddressDetailsLeader['role']; } export function useEscrowDetails({ - role, + role, }: { - role: AddressDetailsLeader['role']; + role: AddressDetailsLeader['role']; }) { - const { filterParams } = useWalletSearch(); - const { - setLastPageIndex, - pagination: { page, lastPageIndex }, - params, - } = useEscrowDetailsDto(); + const { filterParams } = useWalletSearch(); + const { + setLastPageIndex, + pagination: { page, lastPageIndex }, + params, + } = useEscrowDetailsDto(); - const dto: PaginatedEscrowsDetailsDto = { - chainId: filterParams.chainId, - skip: params.skip, - first: params.first, - role, - }; + const dto: PaginatedEscrowsDetailsDto = { + chainId: filterParams.chainId, + skip: params.skip, + first: params.first, + role, + }; - return useQuery({ - queryFn: async () => { - const { data } = await httpService.get( - `${apiPaths.escrowDetails.path}/${filterParams.address}`, - { - params: dto, - } - ); + return useQuery({ + queryFn: async () => { + const { data } = await httpService.get( + `${apiPaths.escrowDetails.path}/${filterParams.address}`, + { + params: dto, + } + ); - const validResponse = validateResponse( - data, - paginatedEscrowsDetailsSuccessResponseSchema - ); + const validResponse = validateResponse( + data, + paginatedEscrowsDetailsSuccessResponseSchema + ); - // check if last page - if (lastPageIndex === undefined) { - const { data: lastPageCheckData } = await httpService.get( - `${apiPaths.escrowDetails.path}/${filterParams.address}`, - { - params: { - ...dto, - skip: dto.skip + validResponse.results.length, - first: 1, - }, - } - ); - const validLastPageCheckData = validateResponse( - lastPageCheckData, - paginatedEscrowsDetailsSuccessResponseSchema - ); + // check if last page + if (lastPageIndex === undefined) { + const { data: lastPageCheckData } = await httpService.get( + `${apiPaths.escrowDetails.path}/${filterParams.address}`, + { + params: { + ...dto, + skip: dto.skip + validResponse.results.length, + first: 1, + }, + } + ); + const validLastPageCheckData = validateResponse( + lastPageCheckData, + paginatedEscrowsDetailsSuccessResponseSchema + ); - if (validLastPageCheckData.results.length === 0) { - setLastPageIndex(page + 1); - } - } + if (validLastPageCheckData.results.length === 0) { + setLastPageIndex(page + 1); + } + } - return validResponse; - }, - queryKey: ['useEscrowDetails', filterParams.address, dto], - }); + return validResponse; + }, + queryKey: ['useEscrowDetails', filterParams.address, dto], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-general-stats.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-general-stats.tsx index 3f1d5fbe00..244e21cde8 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-general-stats.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-general-stats.tsx @@ -5,24 +5,24 @@ import { apiPaths } from '../api-paths'; import { validateResponse } from '@services/validate-response'; const successGeneralStatsResponseSchema = z.object({ - totalHolders: z.number(), - totalTransactions: z.number(), + totalHolders: z.number(), + totalTransactions: z.number(), }); export type GeneralStats = z.infer; export function useGeneralStats() { - return useQuery({ - queryFn: async () => { - const { data } = await httpService.get(apiPaths.generalStats.path); + return useQuery({ + queryFn: async () => { + const { data } = await httpService.get(apiPaths.generalStats.path); - const validResponse = validateResponse( - data, - successGeneralStatsResponseSchema - ); + const validResponse = validateResponse( + data, + successGeneralStatsResponseSchema + ); - return validResponse; - }, - queryKey: ['useGeneralStats'], - }); + return validResponse; + }, + queryKey: ['useGeneralStats'], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-graph-page-chart-data.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-graph-page-chart-data.tsx index 89ae507b40..b08cd17b31 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-graph-page-chart-data.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-graph-page-chart-data.tsx @@ -9,139 +9,139 @@ import { useMemo } from 'react'; import dayjs from 'dayjs'; const hmtDailyStatSchemaResponseSchema = z.object({ - from: z.string().optional(), - to: z.string().optional(), - results: z.array( - z.object({ - totalTransactionAmount: z.string().transform((value, ctx) => { - const valueAsNumber = Number(value); - if (Number.isNaN(valueAsNumber)) { - ctx.addIssue({ - path: ['totalTransactionAmount'], - code: z.ZodIssueCode.custom, - }); - } - - return valueAsNumber / 10 ** 18; - }), - totalTransactionCount: z.number(), - dailyUniqueSenders: z.number(), - dailyUniqueReceivers: z.number(), - date: z.string(), - }) - ), + from: z.string().optional(), + to: z.string().optional(), + results: z.array( + z.object({ + totalTransactionAmount: z.string().transform((value, ctx) => { + const valueAsNumber = Number(value); + if (Number.isNaN(valueAsNumber)) { + ctx.addIssue({ + path: ['totalTransactionAmount'], + code: z.ZodIssueCode.custom, + }); + } + + return valueAsNumber / 10 ** 18; + }), + totalTransactionCount: z.number(), + dailyUniqueSenders: z.number(), + dailyUniqueReceivers: z.number(), + date: z.string(), + }) + ), }); export type HMTDailyStatsResponse = z.output< - typeof hmtDailyStatSchemaResponseSchema + typeof hmtDailyStatSchemaResponseSchema >; export type HMTDailyStat = HMTDailyStatsResponse['results'][number]; const hcaptchaDailyStatsResponseSchema = z.object({ - from: z.string().optional(), - to: z.string().optional(), - results: z.array( - z.object({ - solved: z.number(), - date: z.string(), - }) - ), + from: z.string().optional(), + to: z.string().optional(), + results: z.array( + z.object({ + solved: z.number(), + date: z.string(), + }) + ), }); export type HcaptchaDailyStatsResponse = z.infer< - typeof hcaptchaDailyStatsResponseSchema + typeof hcaptchaDailyStatsResponseSchema >; export type HcaptchaDailyStat = HcaptchaDailyStatsResponse['results'][number]; export type GraphPageChartData = (HMTDailyStat & - Omit)[]; + Omit)[]; const mergeResponses = ( - hcaptchaStatsResults: HcaptchaDailyStat[], - hmtStatsResults: HMTDailyStat[] + hcaptchaStatsResults: HcaptchaDailyStat[], + hmtStatsResults: HMTDailyStat[] ): GraphPageChartData => { - const allDates = Array.from( - new Set([ - ...hcaptchaStatsResults.map(({ date }) => date), - ...hmtStatsResults.map(({ date }) => date), - ]) - ).sort((a, b) => (dayjs(a).isBefore(dayjs(b)) ? -1 : 1)); - - const hcaptchaStatsResultsMap = new Map(); - const hmtStatsResultsMap = new Map(); - - hcaptchaStatsResults.forEach((entry) => { - hcaptchaStatsResultsMap.set(entry.date, entry); - }); - - hmtStatsResults.forEach((entry) => { - hmtStatsResultsMap.set(entry.date, entry); - }); - return allDates.map((date) => { - const hmtStatsEntry: HMTDailyStat = hmtStatsResultsMap.get(date) || { - dailyUniqueReceivers: 0, - dailyUniqueSenders: 0, - date: date, - totalTransactionAmount: 0, - totalTransactionCount: 0, - }; - - const hcaptchaStatsEntry: HcaptchaDailyStat = hcaptchaStatsResultsMap.get( - date - ) || { - date: date, - solved: 0, - }; - return { ...hmtStatsEntry, ...hcaptchaStatsEntry }; - }); + const allDates = Array.from( + new Set([ + ...hcaptchaStatsResults.map(({ date }) => date), + ...hmtStatsResults.map(({ date }) => date), + ]) + ).sort((a, b) => (dayjs(a).isBefore(dayjs(b)) ? -1 : 1)); + + const hcaptchaStatsResultsMap = new Map(); + const hmtStatsResultsMap = new Map(); + + hcaptchaStatsResults.forEach((entry) => { + hcaptchaStatsResultsMap.set(entry.date, entry); + }); + + hmtStatsResults.forEach((entry) => { + hmtStatsResultsMap.set(entry.date, entry); + }); + return allDates.map((date) => { + const hmtStatsEntry: HMTDailyStat = hmtStatsResultsMap.get(date) || { + dailyUniqueReceivers: 0, + dailyUniqueSenders: 0, + date: date, + totalTransactionAmount: 0, + totalTransactionCount: 0, + }; + + const hcaptchaStatsEntry: HcaptchaDailyStat = hcaptchaStatsResultsMap.get( + date + ) || { + date: date, + solved: 0, + }; + return { ...hmtStatsEntry, ...hcaptchaStatsEntry }; + }); }; const DEBOUNCE_MS = 300; export function useGraphPageChartData() { - const { dateRangeParams } = useGraphPageChartParams(); - const queryParams = useMemo( - () => ({ - from: dateRangeParams.from.format('YYYY-MM-DD'), - to: dateRangeParams.to.format('YYYY-MM-DD'), - }), - [dateRangeParams.from, dateRangeParams.to] - ); - - const [debouncedQueryParams] = useDebounce(queryParams, DEBOUNCE_MS); - - return useQuery({ - queryFn: async () => { - const { data: hmtDailyStats } = await httpService.get( - apiPaths.hmtDailyStats.path, - { - params: debouncedQueryParams, - } - ); - const { data: hcaptchDailyStats } = await httpService.get( - apiPaths.hcaptchaStatsDaily.path, - { - params: debouncedQueryParams, - } - ); - - const validHmtDailyStats = validateResponse( - hmtDailyStats, - hmtDailyStatSchemaResponseSchema - ); - - const validHcaptchaGeneralStats = validateResponse( - hcaptchDailyStats, - hcaptchaDailyStatsResponseSchema - ); - - return mergeResponses( - validHcaptchaGeneralStats.results, - validHmtDailyStats.results - ); - }, - staleTime: DEBOUNCE_MS, - queryKey: ['useGraphPageChartData', debouncedQueryParams], - placeholderData: keepPreviousData, - }); + const { dateRangeParams } = useGraphPageChartParams(); + const queryParams = useMemo( + () => ({ + from: dateRangeParams.from.format('YYYY-MM-DD'), + to: dateRangeParams.to.format('YYYY-MM-DD'), + }), + [dateRangeParams.from, dateRangeParams.to] + ); + + const [debouncedQueryParams] = useDebounce(queryParams, DEBOUNCE_MS); + + return useQuery({ + queryFn: async () => { + const { data: hmtDailyStats } = await httpService.get( + apiPaths.hmtDailyStats.path, + { + params: debouncedQueryParams, + } + ); + const { data: hcaptchDailyStats } = await httpService.get( + apiPaths.hcaptchaStatsDaily.path, + { + params: debouncedQueryParams, + } + ); + + const validHmtDailyStats = validateResponse( + hmtDailyStats, + hmtDailyStatSchemaResponseSchema + ); + + const validHcaptchaGeneralStats = validateResponse( + hcaptchDailyStats, + hcaptchaDailyStatsResponseSchema + ); + + return mergeResponses( + validHcaptchaGeneralStats.results, + validHmtDailyStats.results + ); + }, + staleTime: DEBOUNCE_MS, + queryKey: ['useGraphPageChartData', debouncedQueryParams], + placeholderData: keepPreviousData, + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-hcaptcha-general-stats.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-hcaptcha-general-stats.tsx index d1d66fa73d..64d9e27aeb 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-hcaptcha-general-stats.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-hcaptcha-general-stats.tsx @@ -5,27 +5,27 @@ import { apiPaths } from '../api-paths'; import { validateResponse } from '@services/validate-response'; const successHcaptchaGeneralStatsResponseSchema = z.object({ - solved: z.number(), + solved: z.number(), }); export type HcaptchaGeneralStats = z.infer< - typeof successHcaptchaGeneralStatsResponseSchema + typeof successHcaptchaGeneralStatsResponseSchema >; export function useHcaptchaGeneralStats() { - return useQuery({ - queryFn: async () => { - const { data } = await httpService.get( - apiPaths.hcaptchaGeneralStats.path - ); + return useQuery({ + queryFn: async () => { + const { data } = await httpService.get( + apiPaths.hcaptchaGeneralStats.path + ); - const validResponse = validateResponse( - data, - successHcaptchaGeneralStatsResponseSchema - ); + const validResponse = validateResponse( + data, + successHcaptchaGeneralStatsResponseSchema + ); - return validResponse; - }, - queryKey: ['useHcaptchaGeneralStats'], - }); + return validResponse; + }, + queryKey: ['useHcaptchaGeneralStats'], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-hmt-price.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-hmt-price.tsx index 974321b0eb..78232607d3 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-hmt-price.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-hmt-price.tsx @@ -5,23 +5,23 @@ import { apiPaths } from '../api-paths'; import { validateResponse } from '@services/validate-response'; const successHMTPriceResponseSchema = z.object({ - hmtPrice: z.number(), + hmtPrice: z.number(), }); export type HMTPrice = z.infer; export function useHMTPrice() { - return useQuery({ - queryFn: async () => { - const { data } = await httpService.get(apiPaths.statsHmtPrice.path); + return useQuery({ + queryFn: async () => { + const { data } = await httpService.get(apiPaths.statsHmtPrice.path); - const validResponse = validateResponse( - data, - successHMTPriceResponseSchema - ); + const validResponse = validateResponse( + data, + successHMTPriceResponseSchema + ); - return validResponse; - }, - queryKey: ['useHMTPrice'], - }); + return validResponse; + }, + queryKey: ['useHMTPrice'], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-all-details.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-all-details.tsx index fe9c417f02..ef9040d893 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-all-details.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-all-details.tsx @@ -6,26 +6,26 @@ import { useLeaderboardSearch } from '@utils/hooks/use-leaderboard-search'; import { leaderBoardSuccessResponseSchema } from '@services/api/use-leaderboard-details'; export function useLeaderboardAllDetails() { - const { - filterParams: { chainId }, - } = useLeaderboardSearch(); + const { + filterParams: { chainId }, + } = useLeaderboardSearch(); - return useQuery({ - queryFn: async () => { - const { data } = await httpService.get( - apiPaths.leaderboardDetailsAll.path, - { - params: { chainId: chainId === -1 ? undefined : chainId }, - } - ); + return useQuery({ + queryFn: async () => { + const { data } = await httpService.get( + apiPaths.leaderboardDetailsAll.path, + { + params: { chainId: chainId === -1 ? undefined : chainId }, + } + ); - const validResponse = validateResponse( - data, - leaderBoardSuccessResponseSchema - ); + const validResponse = validateResponse( + data, + leaderBoardSuccessResponseSchema + ); - return validResponse; - }, - queryKey: ['useLeaderboardAllDetails', chainId], - }); + return validResponse; + }, + queryKey: ['useLeaderboardAllDetails', chainId], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx index 145c18df36..693151ad61 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx @@ -6,39 +6,40 @@ import { validateResponse } from '@services/validate-response'; import { useLeaderboardSearch } from '@utils/hooks/use-leaderboard-search'; export const reputationSchema = z.unknown().transform((value) => { - try { - const knownReputation = z - .union([z.literal('Low'), z.literal('Medium'), z.literal('High')]) - .parse(value); + try { + const knownReputation = z + .union([z.literal('Low'), z.literal('Medium'), z.literal('High')]) + .parse(value); - return knownReputation; - } catch (error) { - return 'Unknown'; - } + return knownReputation; + } catch (error) { + return 'Unknown'; + } }); export type Reputation = z.infer; const leaderBoardEntity = z.object({ - address: z.string(), - role: z.string(), - amountStaked: z.string().transform((value, ctx) => { - const valueAsNumber = Number(value); + address: z.string(), + role: z.string(), + amountStaked: z.string().transform((value, ctx) => { + const valueAsNumber = Number(value); - if (Number.isNaN(valueAsNumber)) { - ctx.addIssue({ - path: ['amountStaked'], - code: z.ZodIssueCode.custom, - }); - } + if (Number.isNaN(valueAsNumber)) { + ctx.addIssue({ + path: ['amountStaked'], + code: z.ZodIssueCode.custom, + }); + } - return valueAsNumber / 10 ** 18; - }), - reputation: reputationSchema, - fee: z.number(), - jobTypes: z.array(z.string()), - url: z.string(), - chainId: z.number(), + return valueAsNumber / 10 ** 18; + }), + reputation: reputationSchema, + fee: z.number(), + jobTypes: z.array(z.string()), + url: z.string(), + website: z.string().optional(), + chainId: z.number(), }); export const leaderBoardSuccessResponseSchema = z.array(leaderBoardEntity); @@ -46,23 +47,23 @@ export type LeaderBoardEntity = z.infer; export type LeaderBoardData = z.infer; export function useLeaderboardDetails() { - const { - filterParams: { chainId }, - } = useLeaderboardSearch(); + const { + filterParams: { chainId }, + } = useLeaderboardSearch(); - return useQuery({ - queryFn: async () => { - const { data } = await httpService.get(apiPaths.leaderboardDetails.path, { - params: { chainId: chainId === -1 ? undefined : chainId }, - }); + return useQuery({ + queryFn: async () => { + const { data } = await httpService.get(apiPaths.leaderboardDetails.path, { + params: { chainId: chainId === -1 ? undefined : chainId }, + }); - const validResponse = validateResponse( - data, - leaderBoardSuccessResponseSchema - ); + const validResponse = validateResponse( + data, + leaderBoardSuccessResponseSchema + ); - return validResponse; - }, - queryKey: ['useLeaderboardDetails', chainId], - }); + return validResponse; + }, + queryKey: ['useLeaderboardDetails', chainId], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx index d40c57b1e0..3596cd0266 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx @@ -7,88 +7,88 @@ import { useTransactionDetailsDto } from '@utils/hooks/use-transactions-details- import { validateResponse } from '@services/validate-response'; const transactionDetailsSuccessResponseSchema = z.object({ - block: z.number(), - from: z.string(), - to: z.string(), - value: z.string(), - method: z.string(), - txHash: z.string(), + block: z.number(), + from: z.string(), + to: z.string(), + value: z.string(), + method: z.string(), + txHash: z.string(), }); export type TransactionDetails = z.infer< - typeof transactionDetailsSuccessResponseSchema + typeof transactionDetailsSuccessResponseSchema >; const paginatedTransactionDetailsSuccessResponseSchema = z.object({ - address: z.string(), - chainId: z.number(), - first: z.number(), - skip: z.number(), - results: z.array(transactionDetailsSuccessResponseSchema), + address: z.string(), + chainId: z.number(), + first: z.number(), + skip: z.number(), + results: z.array(transactionDetailsSuccessResponseSchema), }); export type PaginatedTransactionDetails = z.infer< - typeof paginatedTransactionDetailsSuccessResponseSchema + typeof paginatedTransactionDetailsSuccessResponseSchema >; export interface PaginatedTransactionDetailsDto { - skip: number; - first: number; - chainId: number; + skip: number; + first: number; + chainId: number; } export function useTransactionDetails() { - const { filterParams } = useWalletSearch(); - const { - params, - pagination: { lastPageIndex, page }, - setLastPageIndex, - } = useTransactionDetailsDto(); + const { filterParams } = useWalletSearch(); + const { + params, + pagination: { lastPageIndex, page }, + setLastPageIndex, + } = useTransactionDetailsDto(); - const dto: PaginatedTransactionDetailsDto = { - chainId: filterParams.chainId, - skip: params.skip, - first: params.first, - }; + const dto: PaginatedTransactionDetailsDto = { + chainId: filterParams.chainId, + skip: params.skip, + first: params.first, + }; - return useQuery({ - queryFn: async () => { - const { data } = await httpService.get( - `${apiPaths.transactionDetails.path}/${filterParams.address}`, - { - params: dto, - } - ); + return useQuery({ + queryFn: async () => { + const { data } = await httpService.get( + `${apiPaths.transactionDetails.path}/${filterParams.address}`, + { + params: dto, + } + ); - const validResponse = validateResponse( - data, - paginatedTransactionDetailsSuccessResponseSchema - ); + const validResponse = validateResponse( + data, + paginatedTransactionDetailsSuccessResponseSchema + ); - // check if last page - if (lastPageIndex === undefined) { - const { data: lastPageCheckData } = await httpService.get( - `${apiPaths.transactionDetails.path}/${filterParams.address}`, - { - params: { - ...dto, - skip: dto.skip + validResponse.results.length, - first: 1, - }, - } - ); - const validLastPageCheckData = validateResponse( - lastPageCheckData, - paginatedTransactionDetailsSuccessResponseSchema - ); + // check if last page + if (lastPageIndex === undefined) { + const { data: lastPageCheckData } = await httpService.get( + `${apiPaths.transactionDetails.path}/${filterParams.address}`, + { + params: { + ...dto, + skip: dto.skip + validResponse.results.length, + first: 1, + }, + } + ); + const validLastPageCheckData = validateResponse( + lastPageCheckData, + paginatedTransactionDetailsSuccessResponseSchema + ); - if (validLastPageCheckData.results.length === 0) { - setLastPageIndex(page + 1); - } - } + if (validLastPageCheckData.results.length === 0) { + setLastPageIndex(page + 1); + } + } - return validResponse; - }, - queryKey: ['useTransactionDetails', filterParams.address, dto], - }); + return validResponse; + }, + queryKey: ['useTransactionDetails', filterParams.address, dto], + }); } diff --git a/packages/apps/dashboard/ui-2024/src/services/global.type.ts b/packages/apps/dashboard/ui-2024/src/services/global.type.ts index e809ec0b60..0555a1e485 100644 --- a/packages/apps/dashboard/ui-2024/src/services/global.type.ts +++ b/packages/apps/dashboard/ui-2024/src/services/global.type.ts @@ -4,7 +4,7 @@ import type { AxiosError } from 'axios'; export type ResponseError = AxiosError | Error | ZodError | null; declare module '@tanstack/react-query' { - interface Register { - defaultError: ResponseError; - } + interface Register { + defaultError: ResponseError; + } } diff --git a/packages/apps/dashboard/ui-2024/src/services/handle-error-message.ts b/packages/apps/dashboard/ui-2024/src/services/handle-error-message.ts index d155d81e74..4e69c870ac 100644 --- a/packages/apps/dashboard/ui-2024/src/services/handle-error-message.ts +++ b/packages/apps/dashboard/ui-2024/src/services/handle-error-message.ts @@ -2,17 +2,17 @@ import { AxiosError } from 'axios'; import { ZodError } from 'zod'; export function handleErrorMessage(unknownError: unknown): string { - if (unknownError instanceof AxiosError) { - return unknownError.message; - } + if (unknownError instanceof AxiosError) { + return unknownError.message; + } - if (unknownError instanceof ZodError) { - return 'Unexpected data error'; - } + if (unknownError instanceof ZodError) { + return 'Unexpected data error'; + } - if (unknownError instanceof Error) { - return unknownError.message; - } + if (unknownError instanceof Error) { + return unknownError.message; + } - return 'Something went wrong'; + return 'Something went wrong'; } diff --git a/packages/apps/dashboard/ui-2024/src/services/http-service.ts b/packages/apps/dashboard/ui-2024/src/services/http-service.ts index 4f732f6c2c..3795426495 100644 --- a/packages/apps/dashboard/ui-2024/src/services/http-service.ts +++ b/packages/apps/dashboard/ui-2024/src/services/http-service.ts @@ -2,5 +2,5 @@ import axios from 'axios'; import { env } from '../helpers/env'; export const httpService = axios.create({ - baseURL: env.VITE_API_URL, + baseURL: env.VITE_API_URL, }); diff --git a/packages/apps/dashboard/ui-2024/src/services/validate-response.ts b/packages/apps/dashboard/ui-2024/src/services/validate-response.ts index 9cc6c04d08..a1c2b642a3 100644 --- a/packages/apps/dashboard/ui-2024/src/services/validate-response.ts +++ b/packages/apps/dashboard/ui-2024/src/services/validate-response.ts @@ -1,21 +1,21 @@ import { ZodError, type z } from 'zod'; export const validateResponse = ( - object: unknown, - zodObject: T + object: unknown, + zodObject: T ): z.infer => { - try { - const data = zodObject.parse(object); + try { + const data = zodObject.parse(object); - return data; - } catch (error) { - console.error('Unexpected response'); - if (error instanceof ZodError) { - error.issues.forEach((issue) => { - console.log(issue); - }); - } - console.error(error); - throw error; - } + return data; + } catch (error) { + console.error('Unexpected response'); + if (error instanceof ZodError) { + error.issues.forEach((issue) => { + console.log(issue); + }); + } + console.error(error); + throw error; + } }; diff --git a/packages/apps/dashboard/ui-2024/src/theme.tsx b/packages/apps/dashboard/ui-2024/src/theme.tsx index 180f495b81..4bd94edfad 100644 --- a/packages/apps/dashboard/ui-2024/src/theme.tsx +++ b/packages/apps/dashboard/ui-2024/src/theme.tsx @@ -1,278 +1,278 @@ import { createTheme } from '@mui/material/styles'; import { - PaletteColorOptions, - PaletteColor, + PaletteColorOptions, + PaletteColor, } from '@mui/material/styles/createPalette'; import { ThemeOptions } from '@mui/material'; import { colorPalette } from '@assets/styles/color-palette'; import { CSSProperties } from 'react'; declare module '@mui/material/Typography' { - interface TypographyPropsVariantOverrides { - ['Components/Button Small']: true; - ['Components/Button Large']: true; - ['Components/Chip']: true; - ['Components/Table Header']: true; - ['H6-Mobile']: true; - body3: true; - } + interface TypographyPropsVariantOverrides { + ['Components/Button Small']: true; + ['Components/Button Large']: true; + ['Components/Chip']: true; + ['Components/Table Header']: true; + ['H6-Mobile']: true; + body3: true; + } } declare module '@mui/material/styles' { - interface TypographyVariants { - ['Components/Button Small']: CSSProperties; - ['Components/Button Large']: CSSProperties; - ['Components/Chip']: CSSProperties; - ['Components/Table Header']: CSSProperties; - ['H6-Mobile']: CSSProperties; - body3: CSSProperties; - } + interface TypographyVariants { + ['Components/Button Small']: CSSProperties; + ['Components/Button Large']: CSSProperties; + ['Components/Chip']: CSSProperties; + ['Components/Table Header']: CSSProperties; + ['H6-Mobile']: CSSProperties; + body3: CSSProperties; + } - // allow configuration using `createTheme` - interface TypographyVariantsOptions { - ['Components/Button Small']?: CSSProperties; - ['Components/Button Large']?: CSSProperties; - ['Components/Chip']?: CSSProperties; - ['Components/Table Header']?: CSSProperties; - ['H6-Mobile']: CSSProperties; - body3?: CSSProperties; - } + // allow configuration using `createTheme` + interface TypographyVariantsOptions { + ['Components/Button Small']?: CSSProperties; + ['Components/Button Large']?: CSSProperties; + ['Components/Chip']?: CSSProperties; + ['Components/Table Header']?: CSSProperties; + ['H6-Mobile']: CSSProperties; + body3?: CSSProperties; + } } declare module '@mui/material/styles' { - interface Palette { - sky: PaletteColor; - white: PaletteColor; - textSecondary: PaletteColor; - } - interface PaletteOptions { - sky?: PaletteColorOptions; - white?: PaletteColorOptions; - textSecondary?: PaletteColorOptions; - } + interface Palette { + sky: PaletteColor; + white: PaletteColor; + textSecondary: PaletteColor; + } + interface PaletteOptions { + sky?: PaletteColorOptions; + white?: PaletteColorOptions; + textSecondary?: PaletteColorOptions; + } } declare module '@mui/material/Button' { - interface ButtonPropsColorOverrides { - sky: true; - white: true; - textSecondary: true; - } + interface ButtonPropsColorOverrides { + sky: true; + white: true; + textSecondary: true; + } } declare module '@mui/material/IconButton' { - interface IconButtonPropsColorOverrides { - sky: true; - white: true; - textSecondary: true; - } + interface IconButtonPropsColorOverrides { + sky: true; + white: true; + textSecondary: true; + } } declare module '@mui/material/SvgIcon' { - interface SvgIconPropsColorOverrides { - sky: true; - white: true; - textSecondary: true; - } + interface SvgIconPropsColorOverrides { + sky: true; + white: true; + textSecondary: true; + } } const theme: ThemeOptions = createTheme({ - palette: { - primary: { - main: colorPalette.primary.main, - light: colorPalette.primary.light, - }, - info: { - main: colorPalette.info.main, - light: colorPalette.info.light, - dark: colorPalette.info.dark, - }, - secondary: { - main: colorPalette.secondary.main, - light: colorPalette.secondary.light, - }, - text: { - primary: colorPalette.primary.main, - secondary: colorPalette.fog.main, - }, - sky: { - main: colorPalette.sky.main, - light: colorPalette.sky.light, - dark: colorPalette.sky.dark, - contrastText: colorPalette.sky.contrastText, - }, - white: { - main: '#fff', - light: '#fff', - dark: '#fff', - contrastText: '#fff', - }, - textSecondary: colorPalette.textSecondary, - }, - typography: { - fontFamily: 'Inter, Arial, sans-serif', - h1: { - fontSize: 32, - }, - h2: { - fontSize: 34, - fontWeight: 600, - }, - h3: { - fontSize: 24, - fontWeight: 500, - '@media (max-width:600px)': { - fontSize: 20, - }, - }, - h4: { - fontSize: 20, - fontWeight: 500, - }, - h5: { - fontSize: 18, - fontWeight: 600, - }, - h6: { - fontSize: 20, - fontWeight: 500, - }, - 'H6-Mobile': { - fontSize: '20px', - fontWeight: 500, - lineHeight: '32px', - letterSpacing: '0.15px', - textAlign: 'left', - }, - body1: { - fontSize: 16, - fontWeight: 400, - }, - body2: { - fontSize: 14, - fontWeight: 500, - }, - body3: { - fontSize: '12px', - fontWeight: 400, - lineHeight: '19.92px', - letterSpacing: '0.4px', - textAlign: 'left', - }, - 'Components/Button Small': { - fontSize: '13px', - fontWeight: 600, - lineHeight: '22px', - letterSpacing: '0.1px', - textAlign: 'left', - }, - 'Components/Button Large': { - fontSize: '15px', - fontWeight: 600, - lineHeight: '26px', - letterSpacing: '0.1px', - textAlign: 'left', - }, - 'Components/Chip': { - fontSize: '13px', - fontWeight: 400, - lineHeight: '18px', - letterSpacing: '0.16px', - textAlign: 'left', - }, - 'Components/Table Header': { - fontFamily: 'Roboto', - fontSize: '14px', - fontWeight: 500, - lineHeight: '24px', - letterSpacing: '0.17px', - textAlign: 'left', - }, - subtitle1: { - fontSize: 12, - }, - subtitle2: { - fontSize: 14, - fontWeight: 600, - lineHeight: '21.9px', - }, - caption: { - fontSize: 10, - }, - }, - components: { - MuiButton: { - styleOverrides: { - root: { - fontWeight: 600, - textTransform: 'none', - }, - }, - }, - MuiToolbar: { - styleOverrides: { - root: { - '@media (min-width:1001px)': { - paddingX: 56, - }, - }, - }, - }, - MuiTooltip: { - styleOverrides: { - tooltip: { - backgroundColor: '#320a8d', - color: '#fff', - }, - arrow: { - color: '#320a8d', - }, - }, - }, - MuiIconButton: { - styleOverrides: { - sizeMedium: { - color: colorPalette.primary.main, - }, - }, - }, - MuiSelect: { - styleOverrides: { - root: { - borderRadius: 4, - borderWidth: 2, - color: '#320a8d', - '& .MuiOutlinedInput-notchedOutline': { - borderColor: '#320a8d', - borderWidth: 2, - }, - '&:hover .MuiOutlinedInput-notchedOutline': { - borderColor: '#320a8d', - }, - '&.Mui-focused .MuiOutlinedInput-notchedOutline': { - borderColor: '#320a8d', - }, - '& .MuiSvgIcon-root': { - color: '#320a8d', - }, - }, - }, - }, - MuiTypography: { - styleOverrides: { - root: { - wordBreak: 'break-word', - }, - }, - }, - MuiOutlinedInput: { - styleOverrides: { - root: { - backgroundColor: colorPalette.white, - }, - }, - }, - }, + palette: { + primary: { + main: colorPalette.primary.main, + light: colorPalette.primary.light, + }, + info: { + main: colorPalette.info.main, + light: colorPalette.info.light, + dark: colorPalette.info.dark, + }, + secondary: { + main: colorPalette.secondary.main, + light: colorPalette.secondary.light, + }, + text: { + primary: colorPalette.primary.main, + secondary: colorPalette.fog.main, + }, + sky: { + main: colorPalette.sky.main, + light: colorPalette.sky.light, + dark: colorPalette.sky.dark, + contrastText: colorPalette.sky.contrastText, + }, + white: { + main: '#fff', + light: '#fff', + dark: '#fff', + contrastText: '#fff', + }, + textSecondary: colorPalette.textSecondary, + }, + typography: { + fontFamily: 'Inter, Arial, sans-serif', + h1: { + fontSize: 32, + }, + h2: { + fontSize: 34, + fontWeight: 600, + }, + h3: { + fontSize: 24, + fontWeight: 500, + '@media (max-width:600px)': { + fontSize: 20, + }, + }, + h4: { + fontSize: 20, + fontWeight: 500, + }, + h5: { + fontSize: 18, + fontWeight: 600, + }, + h6: { + fontSize: 20, + fontWeight: 500, + }, + 'H6-Mobile': { + fontSize: '20px', + fontWeight: 500, + lineHeight: '32px', + letterSpacing: '0.15px', + textAlign: 'left', + }, + body1: { + fontSize: 16, + fontWeight: 400, + }, + body2: { + fontSize: 14, + fontWeight: 500, + }, + body3: { + fontSize: '12px', + fontWeight: 400, + lineHeight: '19.92px', + letterSpacing: '0.4px', + textAlign: 'left', + }, + 'Components/Button Small': { + fontSize: '13px', + fontWeight: 600, + lineHeight: '22px', + letterSpacing: '0.1px', + textAlign: 'left', + }, + 'Components/Button Large': { + fontSize: '15px', + fontWeight: 600, + lineHeight: '26px', + letterSpacing: '0.1px', + textAlign: 'left', + }, + 'Components/Chip': { + fontSize: '13px', + fontWeight: 400, + lineHeight: '18px', + letterSpacing: '0.16px', + textAlign: 'left', + }, + 'Components/Table Header': { + fontFamily: 'Roboto', + fontSize: '14px', + fontWeight: 500, + lineHeight: '24px', + letterSpacing: '0.17px', + textAlign: 'left', + }, + subtitle1: { + fontSize: 12, + }, + subtitle2: { + fontSize: 14, + fontWeight: 600, + lineHeight: '21.9px', + }, + caption: { + fontSize: 10, + }, + }, + components: { + MuiButton: { + styleOverrides: { + root: { + fontWeight: 600, + textTransform: 'none', + }, + }, + }, + MuiToolbar: { + styleOverrides: { + root: { + '@media (min-width:1001px)': { + paddingX: 56, + }, + }, + }, + }, + MuiTooltip: { + styleOverrides: { + tooltip: { + backgroundColor: '#320a8d', + color: '#fff', + }, + arrow: { + color: '#320a8d', + }, + }, + }, + MuiIconButton: { + styleOverrides: { + sizeMedium: { + color: colorPalette.primary.main, + }, + }, + }, + MuiSelect: { + styleOverrides: { + root: { + borderRadius: 4, + borderWidth: 2, + color: '#320a8d', + '& .MuiOutlinedInput-notchedOutline': { + borderColor: '#320a8d', + borderWidth: 2, + }, + '&:hover .MuiOutlinedInput-notchedOutline': { + borderColor: '#320a8d', + }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { + borderColor: '#320a8d', + }, + '& .MuiSvgIcon-root': { + color: '#320a8d', + }, + }, + }, + }, + MuiTypography: { + styleOverrides: { + root: { + wordBreak: 'break-word', + }, + }, + }, + MuiOutlinedInput: { + styleOverrides: { + root: { + backgroundColor: colorPalette.white, + }, + }, + }, + }, }); export default theme; diff --git a/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts b/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts index d0be73be94..208e722704 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts +++ b/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts @@ -6,12 +6,12 @@ const chainIdsList = [1, 56, 137, 1284, 43114, 42220, 196]; const viemChains = Object.values(chains); export const getNetwork = (chainId: number): Chain | undefined => - viemChains.find((network) => { - if ('id' in network && network.id === chainId) { - return network; - } - }); + viemChains.find((network) => { + if ('id' in network && network.id === chainId) { + return network; + } + }); export const networks = chainIdsList - .map((id) => getNetwork(id)) - .filter((chain): chain is Chain => !!chain); + .map((id) => getNetwork(id)) + .filter((chain): chain is Chain => !!chain); diff --git a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-escrows-details-dto.ts b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-escrows-details-dto.ts index fdff3a041c..deabad31bf 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-escrows-details-dto.ts +++ b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-escrows-details-dto.ts @@ -1,97 +1,97 @@ import { create } from 'zustand'; export interface EscrowDetailsDto { - params: { - first: number; - skip: number; - }; - pagination: { - page: number; - pageSize: number; - lastPageIndex?: number; - }; - setNextPage: () => void; - setPrevPage: () => void; - setPageSize: (pageSize: number) => void; - setLastPageIndex: (lastPageIndex: number | undefined) => void; + params: { + first: number; + skip: number; + }; + pagination: { + page: number; + pageSize: number; + lastPageIndex?: number; + }; + setNextPage: () => void; + setPrevPage: () => void; + setPageSize: (pageSize: number) => void; + setLastPageIndex: (lastPageIndex: number | undefined) => void; } const INITIAL_PAGE_SIZE = 10; export const useEscrowDetailsDto = create((set) => ({ - params: { - first: INITIAL_PAGE_SIZE, - skip: 0, - }, - pagination: { - page: 0, - pageSize: INITIAL_PAGE_SIZE, - lastPage: false, - }, - setNextPage() { - set((state) => { - const nextPage = state.pagination.page + 1; - const newSkip = nextPage * state.params.first; + params: { + first: INITIAL_PAGE_SIZE, + skip: 0, + }, + pagination: { + page: 0, + pageSize: INITIAL_PAGE_SIZE, + lastPage: false, + }, + setNextPage() { + set((state) => { + const nextPage = state.pagination.page + 1; + const newSkip = nextPage * state.params.first; - return { - ...state, - params: { - ...state.params, - skip: newSkip, - }, - pagination: { - ...state.pagination, - page: nextPage, - }, - }; - }); - }, - setPrevPage() { - set((state) => { - const prevPage = - state.pagination.page === 0 ? 0 : state.pagination.page - 1; - const offSetPages = prevPage === 0 ? 0 : state.pagination.page - 1; - const newSkip = state.params.first * offSetPages; + return { + ...state, + params: { + ...state.params, + skip: newSkip, + }, + pagination: { + ...state.pagination, + page: nextPage, + }, + }; + }); + }, + setPrevPage() { + set((state) => { + const prevPage = + state.pagination.page === 0 ? 0 : state.pagination.page - 1; + const offSetPages = prevPage === 0 ? 0 : state.pagination.page - 1; + const newSkip = state.params.first * offSetPages; - return { - ...state, - params: { - ...state.params, - skip: newSkip, - }, - pagination: { - ...state.pagination, - page: prevPage, - }, - }; - }); - }, - setPageSize(pageSize: number) { - set((state) => { - return { - ...state, - pagination: { - lastPage: false, - page: 0, - pageSize: pageSize, - }, - params: { - ...state.params, - first: pageSize, - skip: 0, - }, - }; - }); - }, - setLastPageIndex(lastPageIndex: number | undefined) { - set((state) => { - return { - ...state, - pagination: { - ...state.pagination, - lastPageIndex, - }, - }; - }); - }, + return { + ...state, + params: { + ...state.params, + skip: newSkip, + }, + pagination: { + ...state.pagination, + page: prevPage, + }, + }; + }); + }, + setPageSize(pageSize: number) { + set((state) => { + return { + ...state, + pagination: { + lastPage: false, + page: 0, + pageSize: pageSize, + }, + params: { + ...state.params, + first: pageSize, + skip: 0, + }, + }; + }); + }, + setLastPageIndex(lastPageIndex: number | undefined) { + set((state) => { + return { + ...state, + pagination: { + ...state.pagination, + lastPageIndex, + }, + }; + }); + }, })); diff --git a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-graph-page-chart-params.tsx b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-graph-page-chart-params.tsx index 4d190501a6..abe615113f 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-graph-page-chart-params.tsx +++ b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-graph-page-chart-params.tsx @@ -6,8 +6,8 @@ const MINIMAL_DATE_FOR_DATE_PICKER = '2021-04-06'; export type GraphPageChartPeriodName = '1W' | '1M' | '6M' | '1Y' | 'ALL'; export type TimePeriod = { - value: Dayjs; - name: GraphPageChartPeriodName; + value: Dayjs; + name: GraphPageChartPeriodName; }; const oneWeekAgo = dayjs().subtract(1, 'week'); @@ -17,101 +17,101 @@ const oneYearAgo = dayjs().subtract(1, 'year'); export const initialAllTime = dayjs(MINIMAL_DATE_FOR_DATE_PICKER); export const TIME_PERIOD_OPTIONS: TimePeriod[] = [ - { - value: oneWeekAgo, - name: '1W', - }, - { - value: oneMonthAgo, - name: '1M', - }, - { - value: sixMonthsAgo, - name: '6M', - }, - { - value: oneYearAgo, - name: '1Y', - }, - { - value: initialAllTime, - name: 'ALL', - }, + { + value: oneWeekAgo, + name: '1W', + }, + { + value: oneMonthAgo, + name: '1M', + }, + { + value: sixMonthsAgo, + name: '6M', + }, + { + value: oneYearAgo, + name: '1Y', + }, + { + value: initialAllTime, + name: 'ALL', + }, ]; export interface GraphPageChartParams { - dateRangeParams: { - from: Dayjs; - to: Dayjs; - }; - selectedTimePeriod: GraphPageChartPeriodName | null; - setTimePeriod: (timePeriod: TimePeriod) => void; - clearTimePeriod: () => void; - setFromDate: (fromDate: Dayjs | null) => void; - setToDate: (toDate: Dayjs | null) => void; - setEffectiveFromAllTimeDate: (date: Dayjs) => void; - revertToInitialParams: () => void; + dateRangeParams: { + from: Dayjs; + to: Dayjs; + }; + selectedTimePeriod: GraphPageChartPeriodName | null; + setTimePeriod: (timePeriod: TimePeriod) => void; + clearTimePeriod: () => void; + setFromDate: (fromDate: Dayjs | null) => void; + setToDate: (toDate: Dayjs | null) => void; + setEffectiveFromAllTimeDate: (date: Dayjs) => void; + revertToInitialParams: () => void; } const INITIAL_RANGE_PARAMS = { - from: oneWeekAgo, - to: dayjs(), + from: oneWeekAgo, + to: dayjs(), }; export const useGraphPageChartParams = create((set) => ({ - dateRangeParams: INITIAL_RANGE_PARAMS, - selectedTimePeriod: '1W', - setFromDate: (fromDate: Dayjs | null) => { - if (!fromDate) { - return; - } - set((state) => { - return { - ...state, - dateRangeParams: { - ...state.dateRangeParams, - from: fromDate, - }, - }; - }); - }, - setToDate: (toDate: Dayjs | null) => { - if (!toDate) { - return null; - } - set((state) => ({ - ...state, - dateRangeParams: { - ...state.dateRangeParams, - to: toDate, - }, - })); - }, - setTimePeriod: (timePeriod: TimePeriod) => { - set((state) => { - return { - ...state, - selectedTimePeriod: timePeriod.name, - dateRangeParams: { - ...state.dateRangeParams, - from: timePeriod.value, - }, - }; - }); - }, - clearTimePeriod: () => { - set((state) => ({ ...state, selectedTimePeriod: null })); - }, - setEffectiveFromAllTimeDate: (date: Dayjs) => { - set((state) => ({ - ...state, - effectiveFromAllTimeDate: date, - })); - }, - revertToInitialParams: () => { - set((state) => ({ - ...state, - dateRangeParams: INITIAL_RANGE_PARAMS, - })); - }, + dateRangeParams: INITIAL_RANGE_PARAMS, + selectedTimePeriod: '1W', + setFromDate: (fromDate: Dayjs | null) => { + if (!fromDate) { + return; + } + set((state) => { + return { + ...state, + dateRangeParams: { + ...state.dateRangeParams, + from: fromDate, + }, + }; + }); + }, + setToDate: (toDate: Dayjs | null) => { + if (!toDate) { + return null; + } + set((state) => ({ + ...state, + dateRangeParams: { + ...state.dateRangeParams, + to: toDate, + }, + })); + }, + setTimePeriod: (timePeriod: TimePeriod) => { + set((state) => { + return { + ...state, + selectedTimePeriod: timePeriod.name, + dateRangeParams: { + ...state.dateRangeParams, + from: timePeriod.value, + }, + }; + }); + }, + clearTimePeriod: () => { + set((state) => ({ ...state, selectedTimePeriod: null })); + }, + setEffectiveFromAllTimeDate: (date: Dayjs) => { + set((state) => ({ + ...state, + effectiveFromAllTimeDate: date, + })); + }, + revertToInitialParams: () => { + set((state) => ({ + ...state, + dateRangeParams: INITIAL_RANGE_PARAMS, + })); + }, })); diff --git a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-is-mobile.tsx b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-is-mobile.tsx index 86c07335cc..b0c520f018 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-is-mobile.tsx +++ b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-is-mobile.tsx @@ -1,15 +1,15 @@ import useMediaQuery from '@mui/material/useMediaQuery'; const breakpoints = { - mobile: `(max-width: 1100px)`, + mobile: `(max-width: 1100px)`, }; export function useBreakPoints() { - const matchesMobile = useMediaQuery(breakpoints.mobile); - return { - mobile: { - isMobile: matchesMobile, - mediaQuery: `@media ${breakpoints.mobile}`, - }, - }; + const matchesMobile = useMediaQuery(breakpoints.mobile); + return { + mobile: { + isMobile: matchesMobile, + mediaQuery: `@media ${breakpoints.mobile}`, + }, + }; } diff --git a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-leaderboard-search.ts b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-leaderboard-search.ts index 67c7b4e00d..792c2a1c77 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-leaderboard-search.ts +++ b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-leaderboard-search.ts @@ -3,27 +3,27 @@ import { create } from 'zustand'; import type { Chain } from 'viem/chains'; export const leaderboardSearchSelectConfig: ( - | Chain - | { name: 'All Networks'; allNetworksId: -1 } + | Chain + | { name: 'All Networks'; allNetworksId: -1 } )[] = [{ name: 'All Networks', allNetworksId: -1 }, ...networks]; export interface LeaderboardSearchStore { - filterParams: { - chainId: number; - }; - setChainId: (chainId: number) => void; + filterParams: { + chainId: number; + }; + setChainId: (chainId: number) => void; } export const useLeaderboardSearch = create((set) => ({ - filterParams: { - chainId: -1, - }, - setChainId: (chainId) => { - set((state) => ({ - filterParams: { - ...state.filterParams, - chainId, - }, - })); - }, + filterParams: { + chainId: -1, + }, + setChainId: (chainId) => { + set((state) => ({ + filterParams: { + ...state.filterParams, + chainId, + }, + })); + }, })); diff --git a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-transactions-details-dto.ts b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-transactions-details-dto.ts index 95f034ba98..ce4219c922 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-transactions-details-dto.ts +++ b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-transactions-details-dto.ts @@ -1,99 +1,99 @@ import { create } from 'zustand'; export interface TransactionDetailsDto { - params: { - first: number; - skip: number; - }; - pagination: { - page: number; - pageSize: number; - lastPageIndex?: number; - }; - setNextPage: () => void; - setPrevPage: () => void; - setPageSize: (pageSize: number) => void; - setLastPageIndex: (lastPageIndex: number | undefined) => void; + params: { + first: number; + skip: number; + }; + pagination: { + page: number; + pageSize: number; + lastPageIndex?: number; + }; + setNextPage: () => void; + setPrevPage: () => void; + setPageSize: (pageSize: number) => void; + setLastPageIndex: (lastPageIndex: number | undefined) => void; } const INITIAL_PAGE_SIZE = 10; export const useTransactionDetailsDto = create( - (set) => ({ - params: { - first: INITIAL_PAGE_SIZE, - skip: 0, - }, - pagination: { - page: 0, - pageSize: INITIAL_PAGE_SIZE, - lastPage: false, - }, - setNextPage() { - set((state) => { - const nextPage = state.pagination.page + 1; - const newSkip = nextPage * state.params.first; + (set) => ({ + params: { + first: INITIAL_PAGE_SIZE, + skip: 0, + }, + pagination: { + page: 0, + pageSize: INITIAL_PAGE_SIZE, + lastPage: false, + }, + setNextPage() { + set((state) => { + const nextPage = state.pagination.page + 1; + const newSkip = nextPage * state.params.first; - return { - ...state, - params: { - ...state.params, - skip: newSkip, - }, - pagination: { - ...state.pagination, - page: nextPage, - }, - }; - }); - }, - setPrevPage() { - set((state) => { - const prevPage = - state.pagination.page === 0 ? 0 : state.pagination.page - 1; - const offSetPages = prevPage === 0 ? 0 : state.pagination.page - 1; - const newSkip = state.params.first * offSetPages; + return { + ...state, + params: { + ...state.params, + skip: newSkip, + }, + pagination: { + ...state.pagination, + page: nextPage, + }, + }; + }); + }, + setPrevPage() { + set((state) => { + const prevPage = + state.pagination.page === 0 ? 0 : state.pagination.page - 1; + const offSetPages = prevPage === 0 ? 0 : state.pagination.page - 1; + const newSkip = state.params.first * offSetPages; - return { - ...state, - params: { - ...state.params, - skip: newSkip, - }, - pagination: { - ...state.pagination, - page: prevPage, - }, - }; - }); - }, - setPageSize(pageSize: number) { - set((state) => { - return { - ...state, - pagination: { - lastPage: false, - page: 0, - pageSize: pageSize, - }, - params: { - ...state.params, - first: pageSize, - skip: 0, - }, - }; - }); - }, - setLastPageIndex(lastPageIndex: number | undefined) { - set((state) => { - return { - ...state, - pagination: { - ...state.pagination, - lastPageIndex, - }, - }; - }); - }, - }) + return { + ...state, + params: { + ...state.params, + skip: newSkip, + }, + pagination: { + ...state.pagination, + page: prevPage, + }, + }; + }); + }, + setPageSize(pageSize: number) { + set((state) => { + return { + ...state, + pagination: { + lastPage: false, + page: 0, + pageSize: pageSize, + }, + params: { + ...state.params, + first: pageSize, + skip: 0, + }, + }; + }); + }, + setLastPageIndex(lastPageIndex: number | undefined) { + set((state) => { + return { + ...state, + pagination: { + ...state.pagination, + lastPageIndex, + }, + }; + }); + }, + }) ); diff --git a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts index 747388e15c..a550725ec3 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts +++ b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts @@ -1,33 +1,33 @@ import { create } from 'zustand'; export interface WalletSearchStore { - filterParams: { - address: string; - chainId: number; - }; - setAddress: (address: string) => void; - setChainId: (chainId: number) => void; + filterParams: { + address: string; + chainId: number; + }; + setAddress: (address: string) => void; + setChainId: (chainId: number) => void; } export const useWalletSearch = create((set) => ({ - filterParams: { - address: '', - chainId: 137, - }, - setAddress: (address) => { - set((state) => ({ - filterParams: { - ...state.filterParams, - address, - }, - })); - }, - setChainId: (chainId) => { - set((state) => ({ - filterParams: { - ...state.filterParams, - chainId, - }, - })); - }, + filterParams: { + address: '', + chainId: 137, + }, + setAddress: (address) => { + set((state) => ({ + filterParams: { + ...state.filterParams, + address, + }, + })); + }, + setChainId: (chainId) => { + set((state) => ({ + filterParams: { + ...state.filterParams, + chainId, + }, + })); + }, })); diff --git a/packages/apps/dashboard/ui-2024/vite.config.ts b/packages/apps/dashboard/ui-2024/vite.config.ts index 0f4c7736c4..0041973c56 100644 --- a/packages/apps/dashboard/ui-2024/vite.config.ts +++ b/packages/apps/dashboard/ui-2024/vite.config.ts @@ -5,25 +5,25 @@ import svgr from 'vite-plugin-svgr'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [ - react(), - svgr({ - include: '**/*.svg', - exclude: 'src/assets/icons/excluded/**/*.svg', - }), - ], - resolve: { - alias: { - '@components': path.resolve(__dirname, './src/components'), - '@helpers': path.resolve(__dirname, './src/helpers'), - '@assets': path.resolve(__dirname, './src/assets'), - '@pages': path.resolve(__dirname, './src/pages'), - '@api': path.resolve(__dirname, './src/api'), - '@utils': path.resolve(__dirname, './src/utils'), - '@services': path.resolve(__dirname, './src/services'), - }, - }, - server: { - port: 3001, - }, + plugins: [ + react(), + svgr({ + include: '**/*.svg', + exclude: 'src/assets/icons/excluded/**/*.svg', + }), + ], + resolve: { + alias: { + '@components': path.resolve(__dirname, './src/components'), + '@helpers': path.resolve(__dirname, './src/helpers'), + '@assets': path.resolve(__dirname, './src/assets'), + '@pages': path.resolve(__dirname, './src/pages'), + '@api': path.resolve(__dirname, './src/api'), + '@utils': path.resolve(__dirname, './src/utils'), + '@services': path.resolve(__dirname, './src/services'), + }, + }, + server: { + port: 3001, + }, }); diff --git a/packages/apps/faucet/server/.env.example b/packages/apps/faucet/server/.env.example index 87883b5d2f..03af5931bf 100644 --- a/packages/apps/faucet/server/.env.example +++ b/packages/apps/faucet/server/.env.example @@ -2,7 +2,7 @@ NODE_ENV=development APP_PORT=8000 RPC_PORT=8545 DAILY_LIMIT=10 -PRIVATE_KEY="ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +PRIVATE_KEY="" SLACK_WEBHOOK_URL="" # Waiting time in seconds diff --git a/packages/apps/faucet/server/src/services/web3.spec.ts b/packages/apps/faucet/server/src/services/web3.spec.ts index bd5d307e3d..202ab747b1 100644 --- a/packages/apps/faucet/server/src/services/web3.spec.ts +++ b/packages/apps/faucet/server/src/services/web3.spec.ts @@ -24,7 +24,7 @@ let token: Contract; const web3 = new Web3('http://127.0.0.1:8549'); const owner = web3.eth.accounts.privateKeyToAccount( - `0x${process.env.PRIVATE_KEY}` + `0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` ); web3.eth.defaultAccount = owner.address; const externalUser = '0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f'; diff --git a/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts b/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts index 26185fbec1..2d816ad895 100644 --- a/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts +++ b/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts @@ -53,9 +53,7 @@ jest.mock('minio', () => { jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), EscrowClient: { - build: jest.fn().mockImplementation(() => ({ - createAndSetupEscrow: jest.fn().mockResolvedValue(MOCK_ADDRESS), - })), + build: jest.fn().mockImplementation(() => ({})), }, StorageClient: jest.fn().mockImplementation(() => ({ downloadFileFromUrl: jest.fn().mockResolvedValue( diff --git a/packages/apps/human-app/frontend/.eslintrc.cjs b/packages/apps/human-app/frontend/.eslintrc.cjs index 7a875d16c9..ede32c8d48 100644 --- a/packages/apps/human-app/frontend/.eslintrc.cjs +++ b/packages/apps/human-app/frontend/.eslintrc.cjs @@ -31,6 +31,7 @@ module.exports = { ], 'eslint-comments/require-description': 'off', '@typescript-eslint/explicit-function-return-type': 'off', + '@tanstack/query/exhaustive-deps': 'off', // allow imports from material react table library camelcase: ['error', { allow: ['MRT_'] }], 'react/jsx-pascal-case': ['error', { ignore: ['MRT_'] }], diff --git a/packages/apps/human-app/frontend/src/api/services/common/prepare-signature.ts b/packages/apps/human-app/frontend/src/api/services/common/prepare-signature.ts index 8890b02a4d..0aaf8102f3 100644 --- a/packages/apps/human-app/frontend/src/api/services/common/prepare-signature.ts +++ b/packages/apps/human-app/frontend/src/api/services/common/prepare-signature.ts @@ -34,7 +34,6 @@ export function usePrepareSignature(body: PrepareSignatureBody) { return useQuery({ queryFn: () => prepareSignature(body), refetchInterval: 0, - // eslint-disable-next-line @tanstack/query/exhaustive-deps -- ... queryKey: ['prepareSignature'], }); } diff --git a/packages/apps/human-app/frontend/src/api/services/operator/get-stats.ts b/packages/apps/human-app/frontend/src/api/services/operator/get-stats.ts index d9ab4c9a22..d16db88999 100644 --- a/packages/apps/human-app/frontend/src/api/services/operator/get-stats.ts +++ b/packages/apps/human-app/frontend/src/api/services/operator/get-stats.ts @@ -44,7 +44,6 @@ export function useGetOperatorStats() { }, }).catch(() => failedResponse); }, - // eslint-disable-next-line @tanstack/query/exhaustive-deps -- ... queryKey: ['getOperatorStats', keysData?.url], }); } diff --git a/packages/apps/human-app/frontend/src/smart-contracts/chains.ts b/packages/apps/human-app/frontend/src/smart-contracts/chains.ts index 5a737c7697..3d6f01b0b5 100644 --- a/packages/apps/human-app/frontend/src/smart-contracts/chains.ts +++ b/packages/apps/human-app/frontend/src/smart-contracts/chains.ts @@ -38,7 +38,7 @@ export const MainnetChains: ChainWithAddresses[] = [ { chainId: 137, name: 'Polygon', - rpcUrl: 'https://polygon-rpc.com/', + rpcUrl: 'https://polygon-rpc.com', currency: 'MATIC', explorerUrl: 'https://polygonscan.com/', addresses: MainnetContracts.Polygon, diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index 29fba4b4e6..c786dab218 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -1,7 +1,7 @@ { "name": "@human-protocol/human-app-server", "version": "0.0.1", - "description": "", + "description": "HUMAN App server", "author": "", "private": true, "license": "UNLICENSED", diff --git a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts index 42812754da..f15928a830 100644 --- a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts @@ -79,7 +79,11 @@ export class KvStoreGateway { if (!jobTypes || jobTypes === '') { return; } else { - await this.cacheManager.set(key, jobTypes, this.configService.cacheTtlJobTypes); + await this.cacheManager.set( + key, + jobTypes, + this.configService.cacheTtlJobTypes, + ); return jobTypes; } diff --git a/packages/apps/job-launcher/client/src/components/CardTextRow/index.tsx b/packages/apps/job-launcher/client/src/components/CardTextRow/index.tsx index ee22221e19..c7075f5d07 100644 --- a/packages/apps/job-launcher/client/src/components/CardTextRow/index.tsx +++ b/packages/apps/job-launcher/client/src/components/CardTextRow/index.tsx @@ -1,16 +1,19 @@ import { Stack, Typography } from '@mui/material'; import { FC } from 'react'; +import { Link } from 'react-router-dom'; type CardTextRowProps = { label?: string; value?: string | number; minWidth?: number; + url?: string; }; export const CardTextRow: FC = ({ label, value, minWidth = 130, + url, }) => { return ( @@ -22,7 +25,19 @@ export const CardTextRow: FC = ({ color="primary" sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }} > - {value} + {url ? ( + + {value} + + ) : ( + value + )} ); diff --git a/packages/apps/job-launcher/client/src/components/TokenSelect/index.tsx b/packages/apps/job-launcher/client/src/components/TokenSelect/index.tsx index 650472a2e3..111c515b56 100644 --- a/packages/apps/job-launcher/client/src/components/TokenSelect/index.tsx +++ b/packages/apps/job-launcher/client/src/components/TokenSelect/index.tsx @@ -1,4 +1,4 @@ -import { ChainId, NETWORKS } from '@human-protocol/sdk'; +import { ChainId } from '@human-protocol/sdk'; import { FormControl, InputLabel, @@ -7,15 +7,25 @@ import { Select, SelectProps, } from '@mui/material'; -import { FC } from 'react'; +import { FC, useMemo } from 'react'; import { TOKEN_ICONS } from '../../components/Icons/chains'; import { SUPPORTED_TOKEN_SYMBOLS } from '../../constants'; +import { NETWORK_TOKENS } from '../../constants/chains'; type TokenSelectProps = SelectProps & { chainId: ChainId; }; export const TokenSelect: FC = (props) => { + const availableTokens = useMemo(() => { + return SUPPORTED_TOKEN_SYMBOLS.filter( + (symbol) => + NETWORK_TOKENS[props.chainId as keyof typeof NETWORK_TOKENS]?.[ + symbol.toLowerCase() + ], + ); + }, [props.chainId]); + return ( Token @@ -35,17 +45,14 @@ export const TokenSelect: FC = (props) => { }} {...props} > - {SUPPORTED_TOKEN_SYMBOLS.map((symbol) => { + {availableTokens.map((symbol) => { const IconComponent = TOKEN_ICONS[symbol]; + const tokenAddress = + NETWORK_TOKENS[props.chainId as keyof typeof NETWORK_TOKENS]?.[ + symbol.toLowerCase() + ]; return ( - + {IconComponent && ( {IconComponent} diff --git a/packages/apps/job-launcher/client/src/constants/chains.ts b/packages/apps/job-launcher/client/src/constants/chains.ts index d1bd806ba0..1e30ac8658 100644 --- a/packages/apps/job-launcher/client/src/constants/chains.ts +++ b/packages/apps/job-launcher/client/src/constants/chains.ts @@ -1,4 +1,4 @@ -import { ChainId } from '@human-protocol/sdk'; +import { ChainId, NETWORKS } from '@human-protocol/sdk'; import { ERROR_MESSAGES } from './index'; export const IS_MAINNET = @@ -60,3 +60,45 @@ export const LOCALHOST = { }, }, }; + +export const NETWORK_TOKENS: Record< + ChainId, + { [key: string]: string | undefined } +> = { + [ChainId.POLYGON]: { + hmt: NETWORKS[ChainId.POLYGON]?.hmtAddress, + }, + [ChainId.SEPOLIA]: { + hmt: NETWORKS[ChainId.SEPOLIA]?.hmtAddress, + usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', + }, + [ChainId.POLYGON_AMOY]: { + hmt: NETWORKS[ChainId.POLYGON_AMOY]?.hmtAddress, + }, + [ChainId.ALL]: { hmt: NETWORKS[ChainId.ALL]?.hmtAddress }, + [ChainId.MAINNET]: { hmt: NETWORKS[ChainId.MAINNET]?.hmtAddress }, + [ChainId.RINKEBY]: { hmt: NETWORKS[ChainId.RINKEBY]?.hmtAddress }, + [ChainId.GOERLI]: { hmt: NETWORKS[ChainId.GOERLI]?.hmtAddress }, + [ChainId.BSC_MAINNET]: { hmt: NETWORKS[ChainId.BSC_MAINNET]?.hmtAddress }, + [ChainId.BSC_TESTNET]: { hmt: NETWORKS[ChainId.BSC_TESTNET]?.hmtAddress }, + [ChainId.POLYGON_MUMBAI]: { + hmt: NETWORKS[ChainId.POLYGON_MUMBAI]?.hmtAddress, + }, + [ChainId.MOONBEAM]: { hmt: NETWORKS[ChainId.MOONBEAM]?.hmtAddress }, + [ChainId.MOONBASE_ALPHA]: { + hmt: NETWORKS[ChainId.MOONBASE_ALPHA]?.hmtAddress, + }, + [ChainId.AVALANCHE_TESTNET]: { + hmt: NETWORKS[ChainId.AVALANCHE_TESTNET]?.hmtAddress, + }, + [ChainId.AVALANCHE]: { hmt: NETWORKS[ChainId.AVALANCHE]?.hmtAddress }, + [ChainId.CELO]: { hmt: NETWORKS[ChainId.CELO]?.hmtAddress }, + [ChainId.CELO_ALFAJORES]: { + hmt: NETWORKS[ChainId.CELO_ALFAJORES]?.hmtAddress, + }, + [ChainId.XLAYER_TESTNET]: { + hmt: NETWORKS[ChainId.XLAYER_TESTNET]?.hmtAddress, + }, + [ChainId.LOCALHOST]: { hmt: NETWORKS[ChainId.LOCALHOST]?.hmtAddress }, + [ChainId.XLAYER]: { hmt: NETWORKS[ChainId.XLAYER]?.hmtAddress }, +}; diff --git a/packages/apps/job-launcher/client/src/constants/index.tsx b/packages/apps/job-launcher/client/src/constants/index.tsx index e35f316641..84f5b877ee 100644 --- a/packages/apps/job-launcher/client/src/constants/index.tsx +++ b/packages/apps/job-launcher/client/src/constants/index.tsx @@ -1,4 +1,4 @@ -export const SUPPORTED_TOKEN_SYMBOLS = ['HMT']; +export const SUPPORTED_TOKEN_SYMBOLS = ['HMT', 'USDC']; export const ERROR_MESSAGES = { weakPassword: @@ -32,3 +32,5 @@ export const LOCAL_STORAGE_KEYS = { accessToken: 'HUMAN_JOB_LAUNCHER_ACCESS_TOKEN', refreshToken: 'HUMAN_JOB_LAUNCHER_REFRESH_TOKEN', }; + +export const DASHBOARD_URL = 'https://dashboard.humanprotocol.org/'; diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx index 544dc98057..d5f2f15fca 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx @@ -12,6 +12,7 @@ import { useJobDetails } from '../../../hooks/useJobDetails'; import { useSnackbar } from '../../../providers/SnackProvider'; import * as jobService from '../../../services/job'; import { JobStatus } from '../../../types'; +import { generateDashboardURL } from '../../../utils'; const CardContainer = styled(Card)(({ theme }) => ({ borderRadius: '16px', @@ -110,7 +111,7 @@ export default function JobDetail() { )} - + - - - - Stake details - - - - - - - - diff --git a/packages/apps/job-launcher/client/src/utils/index.ts b/packages/apps/job-launcher/client/src/utils/index.ts new file mode 100644 index 0000000000..11e48d7cbd --- /dev/null +++ b/packages/apps/job-launcher/client/src/utils/index.ts @@ -0,0 +1,7 @@ +import { DASHBOARD_URL } from '../constants'; +import { IS_MAINNET } from '../constants/chains'; + +export const generateDashboardURL = (chainId: number, address: string) => { + if (!IS_MAINNET) return; + return `${DASHBOARD_URL}/search/${chainId}/${address}`; +}; diff --git a/packages/apps/job-launcher/server/src/common/config/network-config.service.ts b/packages/apps/job-launcher/server/src/common/config/network-config.service.ts index f1d5420d1a..d03d3007b4 100644 --- a/packages/apps/job-launcher/server/src/common/config/network-config.service.ts +++ b/packages/apps/job-launcher/server/src/common/config/network-config.service.ts @@ -36,6 +36,7 @@ export class NetworkConfigService { rpcUrl: this.configService.get('RPC_URL_SEPOLIA'), tokens: { hmt: NETWORKS[ChainId.SEPOLIA]?.hmtAddress, + usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', }, }, }), diff --git a/packages/apps/job-launcher/server/src/common/constants/index.ts b/packages/apps/job-launcher/server/src/common/constants/index.ts index e7185f5864..8ccdf69672 100644 --- a/packages/apps/job-launcher/server/src/common/constants/index.ts +++ b/packages/apps/job-launcher/server/src/common/constants/index.ts @@ -45,7 +45,7 @@ export const CANCEL_JOB_STATUSES = [ JobStatus.PAID, JobStatus.FAILED, JobStatus.LAUNCHED, - JobStatus.SET_UP, + JobStatus.FUNDED, JobStatus.CREATED, JobStatus.PARTIAL, ]; diff --git a/packages/apps/job-launcher/server/src/common/enums/job.ts b/packages/apps/job-launcher/server/src/common/enums/job.ts index 461c3da6b7..3c54e8d744 100644 --- a/packages/apps/job-launcher/server/src/common/enums/job.ts +++ b/packages/apps/job-launcher/server/src/common/enums/job.ts @@ -2,7 +2,7 @@ export enum JobStatus { PENDING = 'pending', PAID = 'paid', CREATED = 'created', - SET_UP = 'set_up', + FUNDED = 'funded', LAUNCHED = 'launched', PARTIAL = 'partial', COMPLETED = 'completed', diff --git a/packages/apps/job-launcher/server/src/database/migrations/1730895674938-JobStatusFunded.ts b/packages/apps/job-launcher/server/src/database/migrations/1730895674938-JobStatusFunded.ts new file mode 100644 index 0000000000..e37782af71 --- /dev/null +++ b/packages/apps/job-launcher/server/src/database/migrations/1730895674938-JobStatusFunded.ts @@ -0,0 +1,61 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class JobStatusFunded1730895674938 implements MigrationInterface { + name = 'JobStatusFunded1730895674938'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TYPE "hmt"."jobs_status_enum" + RENAME TO "jobs_status_enum_old" + `); + await queryRunner.query(` + CREATE TYPE "hmt"."jobs_status_enum" AS ENUM( + 'pending', + 'paid', + 'created', + 'funded', + 'launched', + 'partial', + 'completed', + 'failed', + 'to_cancel', + 'canceled' + ) + `); + await queryRunner.query(` + ALTER TABLE "hmt"."jobs" + ALTER COLUMN "status" TYPE "hmt"."jobs_status_enum" USING "status"::"text"::"hmt"."jobs_status_enum" + `); + await queryRunner.query(` + DROP TYPE "hmt"."jobs_status_enum_old" + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TYPE "hmt"."jobs_status_enum_old" AS ENUM( + 'pending', + 'paid', + 'created', + 'set_up', + 'launched', + 'partial', + 'completed', + 'failed', + 'to_cancel', + 'canceled' + ) + `); + await queryRunner.query(` + ALTER TABLE "hmt"."jobs" + ALTER COLUMN "status" TYPE "hmt"."jobs_status_enum_old" USING "status"::"text"::"hmt"."jobs_status_enum_old" + `); + await queryRunner.query(` + DROP TYPE "hmt"."jobs_status_enum" + `); + await queryRunner.query(` + ALTER TYPE "hmt"."jobs_status_enum_old" + RENAME TO "jobs_status_enum" + `); + } +} diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts index eb59c06d6b..6379043c9a 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts @@ -545,7 +545,7 @@ describe('CronJobService', () => { }; jobEntityMock1 = { - status: JobStatus.SET_UP, + status: JobStatus.FUNDED, fundAmount: 100, userId: 1, id: 1, @@ -557,7 +557,7 @@ describe('CronJobService', () => { }; jobEntityMock2 = { - status: JobStatus.SET_UP, + status: JobStatus.FUNDED, fundAmount: 100, userId: 1, id: 1, @@ -641,7 +641,7 @@ describe('CronJobService', () => { expect(fundEscrowMock).toHaveBeenCalledTimes(2); expect(jobEntityMock1.status).toBe(JobStatus.FAILED); - expect(jobEntityMock2.status).toBe(JobStatus.SET_UP); + expect(jobEntityMock2.status).toBe(JobStatus.FUNDED); }); it('should complete the cron job entity on database to unlock', async () => { diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts index 5b49958b4d..3d67201deb 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts @@ -132,7 +132,7 @@ export class CronJobService { try { const jobEntities = await this.jobRepository.findByStatus( - JobStatus.CREATED, + JobStatus.FUNDED, ); for (const jobEntity of jobEntities) { @@ -173,7 +173,7 @@ export class CronJobService { try { const jobEntities = await this.jobRepository.findByStatus( - JobStatus.SET_UP, + JobStatus.CREATED, ); for (const jobEntity of jobEntities) { diff --git a/packages/apps/job-launcher/server/src/modules/job/job.dto.ts b/packages/apps/job-launcher/server/src/modules/job/job.dto.ts index 6ec0a1bd61..2f2f557091 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.dto.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.dto.ts @@ -227,22 +227,6 @@ export class JobIdDto { public id: number; } -export class StakingDetails { - @ApiProperty({ description: 'Ethereum address of the staker' }) - @IsEthereumAddress() - public staker: string; - - @ApiProperty({ description: 'Amount allocated' }) - @IsNumber() - @Min(0) - public allocated: number; - - @ApiProperty({ description: 'Amount slashed' }) - @IsNumber() - @Min(0) - public slashed: number; -} - export class ManifestDetails { @ApiProperty({ description: 'Chain ID', name: 'chain_id' }) @IsNumber() @@ -378,10 +362,6 @@ export class JobDetailsDto { @ApiProperty({ description: 'Manifest details' }) @IsNotEmpty() public manifest: ManifestDetails; - - @ApiProperty({ description: 'Staking details' }) - @IsNotEmpty() - public staking: StakingDetails; } export class FortuneManifestDto { diff --git a/packages/apps/job-launcher/server/src/modules/job/job.repository.ts b/packages/apps/job-launcher/server/src/modules/job/job.repository.ts index cd2c13d088..162445c015 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.repository.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.repository.ts @@ -110,7 +110,7 @@ export class JobRepository extends BaseRepository { JobStatus.PENDING, JobStatus.PAID, JobStatus.CREATED, - JobStatus.SET_UP, + JobStatus.FUNDED, ]; break; case JobStatusFilter.CANCELED: diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts index eb95d24d99..a292dc6662 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts @@ -4,8 +4,6 @@ import { ChainId, EscrowClient, EscrowStatus, - StakingClient, - IAllocation, EscrowUtils, Encryption, KVStoreUtils, @@ -1942,7 +1940,7 @@ describe('JobService', () => { mockJobEntity as JobEntity, ); - mockJobEntity.status = JobStatus.SET_UP; + mockJobEntity.status = JobStatus.FUNDED; expect(jobRepository.updateOne).toHaveBeenCalled(); expect(jobEntityResult).toMatchObject(mockJobEntity); }); @@ -2028,7 +2026,7 @@ describe('JobService', () => { requestType: JobRequestType.FORTUNE, fee, fundAmount, - status: JobStatus.SET_UP, + status: JobStatus.FUNDED, save: jest.fn().mockResolvedValue(true), userId: 1, }; @@ -2054,7 +2052,7 @@ describe('JobService', () => { manifestUrl: MOCK_FILE_URL, manifestHash: MOCK_FILE_HASH, requestType: JobRequestType.FORTUNE, - status: JobStatus.SET_UP, + status: JobStatus.FUNDED, userId: 1, fundAmount: 100, save: jest.fn().mockResolvedValue(true), @@ -2385,7 +2383,7 @@ describe('JobService', () => { const mockJobEntity: Partial = { id: jobId, userId, - status: JobStatus.SET_UP, + status: JobStatus.FUNDED, chainId: ChainId.LOCALHOST, fundAmount: fundAmount, save: jest.fn().mockResolvedValue(true), @@ -2429,7 +2427,7 @@ describe('JobService', () => { const mockJobEntity: Partial = { id: jobId, userId, - status: JobStatus.SET_UP, + status: JobStatus.FUNDED, chainId: ChainId.LOCALHOST, fundAmount: fundAmount, save: jest.fn().mockResolvedValue(true), @@ -3560,13 +3558,6 @@ describe('JobService', () => { describe('getDetails', () => { it('should return job details with escrow address successfully', async () => { const balance = '1'; - const allocationMock: IAllocation = { - escrowAddress: ethers.ZeroAddress, - staker: ethers.ZeroAddress, - tokens: 1n, - createdAt: 1n, - closedAt: 1n, - }; const manifestMock: FortuneManifestDto = { submissionsRequired: 10, @@ -3612,11 +3603,6 @@ describe('JobService', () => { recordingOracleAddress: expect.any(String), reputationOracleAddress: expect.any(String), }, - staking: { - staker: expect.any(String), - allocated: expect.any(Number), - slashed: 0, - }, }; const getEscrowData = { @@ -3633,9 +3619,6 @@ describe('JobService', () => { .fn() .mockResolvedValue(jobEntityMock as any); EscrowUtils.getEscrow = jest.fn().mockResolvedValue(getEscrowData); - (StakingClient.build as any).mockImplementation(() => ({ - getAllocation: jest.fn().mockResolvedValue(allocationMock), - })); storageService.downloadJsonLikeData = jest .fn() .mockResolvedValue(manifestMock); @@ -3690,11 +3673,6 @@ describe('JobService', () => { recordingOracleAddress: ethers.ZeroAddress, reputationOracleAddress: ethers.ZeroAddress, }, - staking: { - staker: expect.any(String), - allocated: 0, - slashed: 0, - }, }; jobRepository.findOneByIdAndUserId = jest diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.ts index bf026cf16a..70968b7f37 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.ts @@ -5,7 +5,6 @@ import { EscrowStatus, EscrowUtils, NETWORKS, - StakingClient, StorageParams, Encryption, KVStoreKeys, @@ -1084,7 +1083,7 @@ export class JobService { gasPrice: await this.web3Service.calculateGasPrice(jobEntity.chainId), }); - jobEntity.status = JobStatus.SET_UP; + jobEntity.status = JobStatus.LAUNCHED; await this.jobRepository.updateOne(jobEntity); return jobEntity; @@ -1103,7 +1102,7 @@ export class JobService { gasPrice: await this.web3Service.calculateGasPrice(jobEntity.chainId), }); - jobEntity.status = JobStatus.LAUNCHED; + jobEntity.status = JobStatus.FUNDED; await this.jobRepository.updateOne(jobEntity); const oracleType = this.getOracleType(jobEntity.requestType); @@ -1187,7 +1186,7 @@ export class JobService { status = JobStatus.FAILED; } break; - case JobStatus.SET_UP: + case JobStatus.FUNDED: if (await this.isCronJobRunning(CronJobType.FundEscrow)) { status = JobStatus.FAILED; } @@ -1555,13 +1554,10 @@ export class JobService { const { chainId, escrowAddress, manifestUrl, manifestHash } = jobEntity; const signer = this.web3Service.getSigner(chainId); - let escrow, allocation; + let escrow; if (escrowAddress) { - const stakingClient = await StakingClient.build(signer); - escrow = await EscrowUtils.getEscrow(chainId, escrowAddress); - allocation = await stakingClient.getAllocation(escrowAddress); } const manifestData = (await this.storageService.downloadJsonLikeData( @@ -1640,11 +1636,6 @@ export class JobService { failedReason: jobEntity.failedReason, }, manifest: manifestDetails, - staking: { - staker: ethers.ZeroAddress, - allocated: 0, - slashed: 0, - }, }; } @@ -1659,11 +1650,6 @@ export class JobService { failedReason: jobEntity.failedReason, }, manifest: manifestDetails, - staking: { - staker: allocation?.staker as string, - allocated: Number(ethers.formatEther(allocation?.tokens || 0)), - slashed: 0, // TODO: Retrieve slash tokens - }, }; } diff --git a/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts index 3c3090c91a..30983783e0 100644 --- a/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts @@ -2,11 +2,7 @@ import { Test } from '@nestjs/testing'; import { RoutingProtocolService } from './routing-protocol.service'; import { ChainId, Role } from '@human-protocol/sdk'; -import { - MOCK_ADDRESS, - MOCK_REPUTATION_ORACLE_1, - mockConfig, -} from '../../../test/constants'; +import { MOCK_REPUTATION_ORACLE_1, mockConfig } from '../../../test/constants'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { Web3Service } from '../web3/web3.service'; @@ -24,9 +20,7 @@ jest.mock('../../common/utils', () => ({ jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), EscrowClient: { - build: jest.fn().mockImplementation(() => ({ - createAndSetupEscrow: jest.fn().mockResolvedValue(MOCK_ADDRESS), - })), + build: jest.fn().mockImplementation(() => ({})), }, })); diff --git a/packages/apps/job-launcher/server/src/modules/web3/web3.service.spec.ts b/packages/apps/job-launcher/server/src/modules/web3/web3.service.spec.ts index 8e519f4dbe..844818ffa7 100644 --- a/packages/apps/job-launcher/server/src/modules/web3/web3.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/web3/web3.service.spec.ts @@ -323,6 +323,15 @@ describe('Web3Service', () => { }); it('should return matching oracle addresses based on job type', async () => { + const mockLeader = { + address: '0x0000000000000000000000000000000000000000', + reputationNetworks: [ + '0x0000000000000000000000000000000000000001', + '0x0000000000000000000000000000000000000002', + '0x0000000000000000000000000000000000000003', + ], + }; + const mockLeader1 = { address: '0x0000000000000000000000000000000000000001', jobTypes: ['Points'], @@ -337,6 +346,7 @@ describe('Web3Service', () => { }; (OperatorUtils.getLeader as jest.Mock) + .mockResolvedValueOnce(mockLeader) .mockResolvedValueOnce(mockLeader1) .mockResolvedValueOnce(mockLeader2) .mockResolvedValueOnce(mockLeader3); @@ -350,10 +360,52 @@ describe('Web3Service', () => { '0x0000000000000000000000000000000000000001', '0x0000000000000000000000000000000000000003', ]); - expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(3); + expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(4); + }); + + it('should return an empty array if reputation networks not found for chain', async () => { + const mockLeader = { + address: '0x0000000000000000000000000000000000000000', + }; + + const mockLeader1 = { + address: '0x0000000000000000000000000000000000000001', + jobTypes: ['NewJobType1'], + }; + const mockLeader2 = { + address: '0x0000000000000000000000000000000000000002', + jobTypes: ['NewJobType2'], + }; + const mockLeader3 = { + address: '0x0000000000000000000000000000000000000003', + jobTypes: ['NewJobType3'], + }; + + (OperatorUtils.getLeader as jest.Mock) + .mockResolvedValueOnce(mockLeader) + .mockResolvedValueOnce(mockLeader1) + .mockResolvedValueOnce(mockLeader2) + .mockResolvedValueOnce(mockLeader3); + + const result = await web3Service.getReputationOraclesByJobType( + ChainId.POLYGON_AMOY, + 'Points', + ); + + expect(result).toEqual([]); + expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(1); }); it('should return an empty array if no oracles match the job type', async () => { + const mockLeader = { + address: '0x0000000000000000000000000000000000000000', + reputationNetworks: [ + '0x0000000000000000000000000000000000000001', + '0x0000000000000000000000000000000000000002', + '0x0000000000000000000000000000000000000003', + ], + }; + const mockLeader1 = { address: '0x0000000000000000000000000000000000000001', jobTypes: ['NewJobType1'], @@ -368,6 +420,7 @@ describe('Web3Service', () => { }; (OperatorUtils.getLeader as jest.Mock) + .mockResolvedValueOnce(mockLeader) .mockResolvedValueOnce(mockLeader1) .mockResolvedValueOnce(mockLeader2) .mockResolvedValueOnce(mockLeader3); @@ -378,7 +431,7 @@ describe('Web3Service', () => { ); expect(result).toEqual([]); - expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(3); + expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(1); }); it('should handle errors from getLeader and return an empty array', async () => { @@ -392,7 +445,7 @@ describe('Web3Service', () => { ); expect(result).toEqual([]); - expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(3); + expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(1); }); it('should return an empty array if no reputation oracles are configured', async () => { @@ -406,7 +459,7 @@ describe('Web3Service', () => { ); expect(result).toEqual([]); - expect(OperatorUtils.getLeader).not.toHaveBeenCalled(); + expect(OperatorUtils.getLeader).toHaveBeenCalledTimes(1); }); }); }); diff --git a/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts b/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts index 8a5e784675..cb059e33aa 100644 --- a/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts +++ b/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts @@ -139,19 +139,26 @@ export class Web3Service { chainId: ChainId, jobType: string, ): Promise { - const oracleAddresses = this.web3ConfigService.reputationOracles - .split(',') - .map((address) => address.trim()) - .filter((address) => address); + const leader = await OperatorUtils.getLeader( + chainId, + this.getOperatorAddress(), + ); + + if (!leader || !leader.reputationNetworks) { + this.logger.error( + `Leader or reputation networks not found for chain ${chainId}.`, + ); + return []; + } const matchingOracles = await Promise.all( - oracleAddresses.map(async (address) => { + leader.reputationNetworks.map(async (address) => { try { - const leader = await OperatorUtils.getLeader(chainId, address); + const networkLeader = await OperatorUtils.getLeader(chainId, address); - return leader?.jobTypes && - this.matchesJobType(leader.jobTypes, jobType) - ? leader.address + return networkLeader?.jobTypes && + this.matchesJobType(networkLeader.jobTypes, jobType) + ? networkLeader.address : null; } catch (error) { this.logger.error( diff --git a/packages/apps/reputation-oracle/server/README.md b/packages/apps/reputation-oracle/server/README.md index 9dd4afdc5d..8b6523ca59 100644 --- a/packages/apps/reputation-oracle/server/README.md +++ b/packages/apps/reputation-oracle/server/README.md @@ -115,6 +115,13 @@ $ yarn migration:show For detailed information about the Exchange Oracle, please refer to the [Human Protocol Tech Docs](https://human-protocol.gitbook.io/hub/human-tech-docs/architecture/components/reputation-oracle). +### Generate env documentation + +```bash +# Generate environment variables document +$ yarn generate-env-doc +``` + ## 📝 License This project is licensed under the MIT License. See the [LICENSE](https://github.com/humanprotocol/human-protocol/blob/main/LICENSE) file for details. diff --git a/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts b/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts index d2d303cf74..aa94175724 100644 --- a/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts @@ -123,6 +123,7 @@ export class PayoutService { results.amounts, url, hash, + true, // TODO: Temporary value; it should be made dynamic in the future when the system supports batch processing. { gasPrice: await this.web3Service.calculateGasPrice(chainId), }, diff --git a/packages/core/.openzeppelin/bsc-testnet.json b/packages/core/.openzeppelin/bsc-testnet.json index 4ce6ba612d..be8b08c927 100644 --- a/packages/core/.openzeppelin/bsc-testnet.json +++ b/packages/core/.openzeppelin/bsc-testnet.json @@ -1411,6 +1411,155 @@ } } } + }, + "139dc961fe52d06c1817185c13d624ca4a96d4becdabb8b6522c4642a427b62e": { + "address": "0x2B9C5EC6220BA8Ad08CB51A60FFdbC6a6235B203", + "txHash": "0x1f94860af698900d387cf92c3f0726ecff3bfc4a0b6140e926330e11e0aacc89", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:121" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/sepolia.json b/packages/core/.openzeppelin/sepolia.json new file mode 100644 index 0000000000..2e8bece9a3 --- /dev/null +++ b/packages/core/.openzeppelin/sepolia.json @@ -0,0 +1,732 @@ +{ + "manifestVersion": "3.2", + "proxies": [ + { + "address": "0x2a7967742B90A7C4edE9dC07E7345Ce5afE356B7", + "txHash": "0x762bc0aa1b1ce66fe079b31443365d1ab215fc51bc1b0467160dd09f3abc639a", + "kind": "uups" + }, + { + "address": "0x5987A5558d961ee674efe4A8c8eB7B1b5495D3bf", + "txHash": "0x37e01ad4f1221197996086c2169d1ef1ec2e2874dde8c096dce3f91d82455b5f", + "kind": "uups" + }, + { + "address": "0xaEf023AdF6D48239E520F69080bC14eCE4fCFBdd", + "txHash": "0x6fe2bccee60cd77036ad31d957b1862ee1d9d6726967202a47e3a34facbf5913", + "kind": "uups" + } + ], + "impls": { + "d2ec2471c85bd1da9dea7e26082bfd535accbe8621b587cd0433f4363983f3ac": { + "address": "0x1d372f1771f7a87Bc2C67B79e78355940fAaE1F5", + "txHash": "0x70fc2e6a892869d087ddedfcab36df36da858dc258aa7620c889288ba5a080da", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "token", + "offset": 0, + "slot": "201", + "type": "t_address", + "contract": "Staking", + "src": "contracts/Staking.sol:26" + }, + { + "label": "rewardPool", + "offset": 0, + "slot": "202", + "type": "t_address", + "contract": "Staking", + "src": "contracts/Staking.sol:29" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "203", + "type": "t_uint256", + "contract": "Staking", + "src": "contracts/Staking.sol:32" + }, + { + "label": "lockPeriod", + "offset": 0, + "slot": "204", + "type": "t_uint32", + "contract": "Staking", + "src": "contracts/Staking.sol:35" + }, + { + "label": "stakes", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_address,t_struct(Staker)23808_storage)", + "contract": "Staking", + "src": "contracts/Staking.sol:38" + }, + { + "label": "stakers", + "offset": 0, + "slot": "206", + "type": "t_array(t_address)dyn_storage", + "contract": "Staking", + "src": "contracts/Staking.sol:41" + }, + { + "label": "allocations", + "offset": 0, + "slot": "207", + "type": "t_mapping(t_address,t_struct(Allocation)23668_storage)", + "contract": "Staking", + "src": "contracts/Staking.sol:44" + }, + { + "label": "__gap", + "offset": 0, + "slot": "208", + "type": "t_array(t_uint256)43_storage", + "contract": "Staking", + "src": "contracts/Staking.sol:592" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)43_storage": { + "label": "uint256[43]", + "numberOfBytes": "1376" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_struct(Allocation)23668_storage)": { + "label": "mapping(address => struct IStaking.Allocation)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Staker)23808_storage)": { + "label": "mapping(address => struct Stakes.Staker)", + "numberOfBytes": "32" + }, + "t_struct(Allocation)23668_storage": { + "label": "struct IStaking.Allocation", + "members": [ + { + "label": "escrowAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "staker", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "tokens", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "createdAt", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "closedAt", + "type": "t_uint256", + "offset": 0, + "slot": "4" + } + ], + "numberOfBytes": "160" + }, + "t_struct(Staker)23808_storage": { + "label": "struct Stakes.Staker", + "members": [ + { + "label": "tokensStaked", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "tokensAllocated", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "tokensLocked", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "tokensLockedUntil", + "type": "t_uint256", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "837055c9712980662789c1523a10cee7c783a7645f0e5f506718f42e1c512f4b": { + "address": "0x07D927670934d7DC612d56C1fa3b0118A17F19a9", + "txHash": "0x2c3c90dc24b49a331ce149d70282e0887c89882084e0282688b218e61bf49591", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "__gap", + "offset": 0, + "slot": "205", + "type": "t_array(t_uint256)46_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:80" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)46_storage": { + "label": "uint256[46]", + "numberOfBytes": "1472" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "5c1e0b4b2495e6a02c16b3d332f8259eb8d8335016f8d88b1dc761febc6c941a": { + "address": "0x7e03eA1d41a444f2f266C41f06EC8E84E6e8B4FF", + "txHash": "0xd4de49d978618125812dcea5b4b42ca6bb7a9442466cc5ee7518cc8138e007ac", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "token", + "offset": 0, + "slot": "201", + "type": "t_address", + "contract": "RewardPool", + "src": "contracts/RewardPool.sol:21" + }, + { + "label": "staking", + "offset": 0, + "slot": "202", + "type": "t_address", + "contract": "RewardPool", + "src": "contracts/RewardPool.sol:24" + }, + { + "label": "fees", + "offset": 0, + "slot": "203", + "type": "t_uint256", + "contract": "RewardPool", + "src": "contracts/RewardPool.sol:27" + }, + { + "label": "rewards", + "offset": 0, + "slot": "204", + "type": "t_mapping(t_address,t_array(t_struct(Reward)23611_storage)dyn_storage)", + "contract": "RewardPool", + "src": "contracts/RewardPool.sol:30" + }, + { + "label": "totalFee", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "RewardPool", + "src": "contracts/RewardPool.sol:32" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "RewardPool", + "src": "contracts/RewardPool.sol:146" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Reward)23611_storage)dyn_storage": { + "label": "struct IRewardPool.Reward[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_struct(Reward)23611_storage)dyn_storage)": { + "label": "mapping(address => struct IRewardPool.Reward[])", + "numberOfBytes": "32" + }, + "t_struct(Reward)23611_storage": { + "label": "struct IRewardPool.Reward", + "members": [ + { + "label": "escrowAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "slasher", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "tokens", + "type": "t_uint256", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "139dc961fe52d06c1817185c13d624ca4a96d4becdabb8b6522c4642a427b62e": { + "address": "0xc9729E6f4E8dceFc260AA7B3D527217Dc4C9100a", + "txHash": "0x1501b9aaea278b357af3d666b17c9722267c362553b7072f282027f458659984", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:121" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + } + } +} diff --git a/packages/core/.openzeppelin/unknown-80002.json b/packages/core/.openzeppelin/unknown-80002.json index d7474eabbe..03fae86cfc 100644 --- a/packages/core/.openzeppelin/unknown-80002.json +++ b/packages/core/.openzeppelin/unknown-80002.json @@ -578,6 +578,155 @@ }, "namespaces": {} } + }, + "139dc961fe52d06c1817185c13d624ca4a96d4becdabb8b6522c4642a427b62e": { + "address": "0xdE8BE9E3C12E9F546309A429cd88d026a25EaF8C", + "txHash": "0x6823749966d8df7957562719b61f511f00281c45960a71fb21940320c5f3ad7e", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:121" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/README.md b/packages/core/README.md index 8eb491c051..a206adfe1d 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -55,12 +55,6 @@ On the other hand, it can be cancelled anytime. > Only trusted handlers can call this function. -- `abort()` - - Cancels the escrow, and self destruct the contract instance. - - > Only trusted handlers can call this function. - - `cancel()` Cancels the escrow, and sends the remaining funds to the canceler. Escrow status is changed to `Cancelled`. diff --git a/packages/core/contracts/Escrow.sol b/packages/core/contracts/Escrow.sol index e74ea81ece..7d890dd3f7 100644 --- a/packages/core/contracts/Escrow.sol +++ b/packages/core/contracts/Escrow.sol @@ -1,17 +1,14 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +pragma solidity ^0.8.0; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '@openzeppelin/contracts/utils/ReentrancyGuard.sol'; import './interfaces/IEscrow.sol'; -import './utils/SafeMath.sol'; contract Escrow is IEscrow, ReentrancyGuard { - using SafeMath for uint256; - bytes4 private constant FUNC_SELECTOR_BALANCE_OF = bytes4(keccak256('balanceOf(address)')); @@ -23,14 +20,30 @@ contract Escrow is IEscrow, ReentrancyGuard { event TrustedHandlerAdded(address _handler); event IntermediateStorage(string _url, string _hash); event Pending(string manifest, string hash); + event PendingV2( + string manifest, + string hash, + address reputationOracle, + address recordingOracle, + address exchangeOracle + ); event BulkTransfer( uint256 indexed _txId, address[] _recipients, uint256[] _amounts, bool _isPartial ); + event BulkTransferV2( + uint256 indexed _txId, + address[] _recipients, + uint256[] _amounts, + bool _isPartial, + string finalResultsUrl + ); event Cancelled(); event Completed(); + event Fund(uint256 _amount); + event Withdraw(address _token, uint256 _amount); EscrowStatuses public override status; @@ -59,6 +72,8 @@ contract Escrow is IEscrow, ReentrancyGuard { mapping(address => bool) public areTrustedHandlers; + uint256 public remainingFunds; + constructor( address _token, address _launcher, @@ -71,7 +86,7 @@ contract Escrow is IEscrow, ReentrancyGuard { token = _token; status = EscrowStatuses.Launched; - duration = _duration.add(block.timestamp); // solhint-disable-line not-rely-on-time + duration = _duration + block.timestamp; launcher = _launcher; canceler = _canceler; escrowFactory = msg.sender; @@ -84,10 +99,14 @@ contract Escrow is IEscrow, ReentrancyGuard { (bool success, bytes memory returnData) = token.staticcall( abi.encodeWithSelector(FUNC_SELECTOR_BALANCE_OF, address(this)) ); - if (success) { - return abi.decode(returnData, (uint256)); - } - return 0; + return success ? abi.decode(returnData, (uint256)) : 0; + } + + function getTokenBalance(address _token) public view returns (uint256) { + (bool success, bytes memory returnData) = _token.staticcall( + abi.encodeWithSelector(FUNC_SELECTOR_BALANCE_OF, address(this)) + ); + return success ? abi.decode(returnData, (uint256)) : 0; } function addTrustedHandlers( @@ -129,9 +148,9 @@ contract Escrow is IEscrow, ReentrancyGuard { _exchangeOracle != address(0), 'Invalid exchange oracle address' ); - uint256 _totalFeePercentage = uint256(_reputationOracleFeePercentage) + - uint256(_recordingOracleFeePercentage) + - uint256(_exchangeOracleFeePercentage); + uint256 _totalFeePercentage = _reputationOracleFeePercentage + + _recordingOracleFeePercentage + + _exchangeOracleFeePercentage; require(_totalFeePercentage <= 100, 'Percentage out of bounds'); require( @@ -150,14 +169,18 @@ contract Escrow is IEscrow, ReentrancyGuard { manifestUrl = _url; manifestHash = _hash; status = EscrowStatuses.Pending; - emit Pending(manifestUrl, manifestHash); - } - function abort() external override trusted notComplete notPaid { - if (getBalance() != 0) { - cancel(); - } - selfdestruct(canceler); + remainingFunds = getBalance(); + require(remainingFunds > 0, 'Escrow balance is zero'); + + emit PendingV2( + manifestUrl, + manifestHash, + reputationOracle, + recordingOracle, + exchangeOracle + ); + emit Fund(remainingFunds); } function cancel() @@ -166,16 +189,36 @@ contract Escrow is IEscrow, ReentrancyGuard { trusted notBroke notComplete - notPaid nonReentrant returns (bool) { - _safeTransfer(canceler, getBalance()); + _safeTransfer(token, canceler, remainingFunds); status = EscrowStatuses.Cancelled; + remainingFunds = 0; emit Cancelled(); return true; } + function withdraw( + address _token + ) public override trusted nonReentrant returns (bool) { + uint256 _amount; + if (_token == token) { + uint256 _balance = getBalance(); + require(_balance > remainingFunds, 'No funds to withdraw'); + _amount = _balance - remainingFunds; + } else { + _amount = getTokenBalance(_token); + } + + _safeTransfer(_token, canceler, _amount); + + emit Withdraw(_token, _amount); + return true; + } + + // For backward compatibility: this function can only be called on existing escrows, + // as the "Paid" status is not set anywhere for new escrows. function complete() external override notExpired trustedOrReputationOracle { require(status == EscrowStatuses.Paid, 'Escrow not in Paid state'); status = EscrowStatuses.Complete; @@ -201,7 +244,7 @@ contract Escrow is IEscrow, ReentrancyGuard { /** * @dev Performs bulk payout to multiple workers - * Escrow needs to be complted / cancelled, so that it can be paid out. + * Escrow needs to be completed / cancelled, so that it can be paid out. * Every recipient is paid with the amount after reputation and recording oracle fees taken out. * If the amount is less than the fee, the recipient is not paid. * If the fee is zero, reputation, and recording oracle are not paid. @@ -215,20 +258,21 @@ contract Escrow is IEscrow, ReentrancyGuard { * @param _url URL storing results as transaction details * @param _hash Hash of the results * @param _txId Transaction ID + * @param forceComplete Boolean parameter indicating if remaining balance should be transferred to the escrow creator */ function bulkPayOut( address[] memory _recipients, uint256[] memory _amounts, string memory _url, string memory _hash, - uint256 _txId + uint256 _txId, + bool forceComplete ) - external + public override trustedOrReputationOracle notBroke notLaunched - notPaid notExpired nonReentrant { @@ -244,14 +288,21 @@ contract Escrow is IEscrow, ReentrancyGuard { 'Invalid status' ); - uint256 balance = getBalance(); uint256 aggregatedBulkAmount = 0; - for (uint256 i; i < _amounts.length; i++) { - require(_amounts[i] > 0, 'Amount should be greater than zero'); - aggregatedBulkAmount = aggregatedBulkAmount.add(_amounts[i]); + uint256 cachedRemainingFunds = remainingFunds; + + for (uint256 i = 0; i < _amounts.length; i++) { + uint256 amount = _amounts[i]; + require(amount > 0, 'Amount should be greater than zero'); + aggregatedBulkAmount += amount; } require(aggregatedBulkAmount < BULK_MAX_VALUE, 'Bulk value too high'); - require(aggregatedBulkAmount <= balance, 'Not enough balance'); + require( + aggregatedBulkAmount <= cachedRemainingFunds, + 'Not enough balance' + ); + + cachedRemainingFunds -= aggregatedBulkAmount; require(bytes(_url).length != 0, "URL can't be empty"); require(bytes(_hash).length != 0, "Hash can't be empty"); @@ -259,96 +310,91 @@ contract Escrow is IEscrow, ReentrancyGuard { finalResultsUrl = _url; finalResultsHash = _hash; - ( - uint256[] memory finalAmounts, - uint256 reputationOracleFee, - uint256 recordingOracleFee, - uint256 exchangeOracleFee - ) = finalizePayouts(_amounts); - - for (uint256 i = 0; i < _recipients.length; ++i) { - if (finalAmounts[i] > 0) { - _safeTransfer(_recipients[i], finalAmounts[i]); - } + uint256 totalFeePercentage = reputationOracleFeePercentage + + recordingOracleFeePercentage + + exchangeOracleFeePercentage; + + for (uint256 i = 0; i < _recipients.length; i++) { + uint256 amount = _amounts[i]; + uint256 amountFee = (totalFeePercentage * amount) / 100; + _safeTransfer(token, _recipients[i], amount - amountFee); } - if (reputationOracleFee > 0) { - _safeTransfer(reputationOracle, reputationOracleFee); + // Transfer oracle fees + if (reputationOracleFeePercentage > 0) { + _safeTransfer( + token, + reputationOracle, + (reputationOracleFeePercentage * aggregatedBulkAmount) / 100 + ); } - if (recordingOracleFee > 0) { - _safeTransfer(recordingOracle, recordingOracleFee); + if (recordingOracleFeePercentage > 0) { + _safeTransfer( + token, + recordingOracle, + (recordingOracleFeePercentage * aggregatedBulkAmount) / 100 + ); } - if (exchangeOracleFee > 0) { - _safeTransfer(exchangeOracle, exchangeOracleFee); + if (exchangeOracleFeePercentage > 0) { + _safeTransfer( + token, + exchangeOracle, + (exchangeOracleFeePercentage * aggregatedBulkAmount) / 100 + ); } - balance = getBalance(); + remainingFunds = cachedRemainingFunds; + + // Check the forceComplete flag and transfer remaining funds if true + if (forceComplete && cachedRemainingFunds > 0) { + _safeTransfer(token, launcher, cachedRemainingFunds); + cachedRemainingFunds = 0; + } - bool isPartial; - if (balance == 0) { - status = EscrowStatuses.Paid; - isPartial = false; + if (cachedRemainingFunds == 0) { + status = EscrowStatuses.Complete; + emit BulkTransferV2( + _txId, + _recipients, + _amounts, + false, + finalResultsUrl + ); + emit Completed(); } else { status = EscrowStatuses.Partial; - isPartial = true; + emit BulkTransferV2( + _txId, + _recipients, + _amounts, + true, + finalResultsUrl + ); } - - emit BulkTransfer(_txId, _recipients, finalAmounts, isPartial); } - function finalizePayouts( - uint256[] memory _amounts - ) internal view returns (uint256[] memory, uint256, uint256, uint256) { - uint256[] memory finalAmounts = new uint256[](_amounts.length); - uint256 reputationOracleFee = 0; - uint256 recordingOracleFee = 0; - uint256 exchangeOracleFee = 0; - for (uint256 j; j < _amounts.length; j++) { - uint256 amount = _amounts[j]; - uint256 amountFee = 0; - - { - uint256 singleReputationOracleFee = uint256( - reputationOracleFeePercentage - ).mul(amount).div(100); - reputationOracleFee = reputationOracleFee.add( - singleReputationOracleFee - ); - amountFee = amountFee.add(singleReputationOracleFee); - } - - { - uint256 singleRecordingOracleFee = uint256( - recordingOracleFeePercentage - ).mul(_amounts[j]).div(100); - recordingOracleFee = recordingOracleFee.add( - singleRecordingOracleFee - ); - amountFee = amountFee.add(singleRecordingOracleFee); - } - - { - uint256 singleExchangeOracleFee = uint256( - exchangeOracleFeePercentage - ).mul(_amounts[j]).div(100); - exchangeOracleFee = exchangeOracleFee.add( - singleExchangeOracleFee - ); - amountFee = amountFee.add(singleExchangeOracleFee); - } - - finalAmounts[j] = amount.sub(amountFee); - } - return ( - finalAmounts, - reputationOracleFee, - recordingOracleFee, - exchangeOracleFee - ); + /** + * @dev Overloaded function to perform bulk payout with default forceComplete set to false. + * Calls the main bulkPayout function with forceComplete as false. + * + * @param _recipients Array of recipients + * @param _amounts Array of amounts to be paid to each recipient. + * @param _url URL storing results as transaction details + * @param _hash Hash of the results + * @param _txId Transaction ID + */ + function bulkPayOut( + address[] memory _recipients, + uint256[] memory _amounts, + string memory _url, + string memory _hash, + uint256 _txId + ) external { + bulkPayOut(_recipients, _amounts, _url, _hash, _txId, false); } - function _safeTransfer(address to, uint256 value) internal { - SafeERC20.safeTransfer(IERC20(token), to, value); + function _safeTransfer(address _token, address to, uint256 value) internal { + SafeERC20.safeTransfer(IERC20(_token), to, value); } modifier trusted() { @@ -373,7 +419,7 @@ contract Escrow is IEscrow, ReentrancyGuard { } modifier notBroke() { - require(getBalance() != 0, 'Token contract out of funds'); + require(remainingFunds != 0, 'Token contract out of funds'); _; } @@ -399,7 +445,7 @@ contract Escrow is IEscrow, ReentrancyGuard { } modifier notExpired() { - require(duration > block.timestamp, 'Contract expired'); // solhint-disable-line not-rely-on-time + require(duration > block.timestamp, 'Contract expired'); _; } } diff --git a/packages/core/contracts/EscrowFactory.sol b/packages/core/contracts/EscrowFactory.sol index 0c2e31b3d6..2b0bf87fd4 100644 --- a/packages/core/contracts/EscrowFactory.sol +++ b/packages/core/contracts/EscrowFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +pragma solidity ^0.8.0; import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; @@ -17,38 +17,52 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable { mapping(address => uint256) public escrowCounters; address public lastEscrow; address public staking; + uint256 public minimumStake; - event Launched(address token, address escrow); - event LaunchedV2(address token, address escrow, string jobRequesterId); + event Launched(address indexed token, address indexed escrow); + event LaunchedV2( + address indexed token, + address indexed escrow, + string jobRequesterId + ); + event SetStakingAddress(address indexed stakingAddress); + event SetMinumumStake(uint256 indexed minimumStake); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } - function initialize(address _staking) external payable virtual initializer { + function initialize( + address _staking, + uint256 _minimumStake + ) external payable virtual initializer { __Ownable_init_unchained(); - __EscrowFactory_init_unchained(_staking); - } - - function __EscrowFactory_init_unchained( - address _staking - ) internal onlyInitializing { require(_staking != address(0), ERROR_ZERO_ADDRESS); - staking = _staking; + _setStakingAddress(_staking); + _setMinimumStake(_minimumStake); } + /** + * @dev Creates a new Escrow contract. + * + * @param token Token address to be associated with the Escrow contract. + * @param trustedHandlers Array of addresses that will serve as the trusted handlers for the Escrow. + * @param jobRequesterId String identifier for the job requester, used for tracking purposes. + * + * @return The address of the newly created Escrow contract. + */ function createEscrow( address token, address[] memory trustedHandlers, string memory jobRequesterId - ) public returns (address) { - bool hasAvailableStake = IStaking(staking).hasAvailableStake( + ) external returns (address) { + uint256 availableStake = IStaking(staking).getAvailableStake( msg.sender ); require( - hasAvailableStake == true, - 'Needs to stake HMT tokens to create an escrow.' + availableStake >= minimumStake, + 'Insufficient stake to create an escrow.' ); Escrow escrow = new Escrow( @@ -65,11 +79,38 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable { return lastEscrow; } - function hasEscrow(address _address) public view returns (bool) { + function hasEscrow(address _address) external view returns (bool) { return escrowCounters[_address] != 0; } - // solhint-disable-next-line no-empty-blocks + /** + * @dev Set the Staking address. + * @param _stakingAddress Staking address + */ + function setStakingAddress(address _stakingAddress) external onlyOwner { + _setStakingAddress(_stakingAddress); + } + + function _setStakingAddress(address _stakingAddress) private { + require(_stakingAddress != address(0), ERROR_ZERO_ADDRESS); + staking = _stakingAddress; + emit SetStakingAddress(_stakingAddress); + } + + /** + * @dev Set the minimum stake amount. + * @param _minimumStake Minimum stake + */ + function setMinimumStake(uint256 _minimumStake) external onlyOwner { + _setMinimumStake(_minimumStake); + } + + function _setMinimumStake(uint256 _minimumStake) private { + require(_minimumStake > 0, 'Must be a positive number'); + minimumStake = _minimumStake; + emit SetMinumumStake(minimumStake); + } + function _authorizeUpgrade(address) internal override onlyOwner {} /** @@ -77,5 +118,5 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable { * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[46] private __gap; + uint256[45] private __gap; } diff --git a/packages/core/contracts/RewardPool.sol b/packages/core/contracts/RewardPool.sol deleted file mode 100644 index c63f6508e2..0000000000 --- a/packages/core/contracts/RewardPool.sol +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.2; - -import '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; - -import './interfaces/IRewardPool.sol'; -import './utils/Math.sol'; - -/** - * @title Reward Pool contract - * @dev Reward Pool keeps slashed tokens, track of who slashed how much tokens, and distributes the reward after protocol fee. - */ -contract RewardPool is IRewardPool, OwnableUpgradeable, UUPSUpgradeable { - using SafeMath for uint256; - - // Token address - address public token; - - // Staking contract address - address public staking; - - // Protocol Fee - uint256 public fees; - - // Rewards per allocation - mapping(address => Reward[]) public rewards; - - uint256 public totalFee; - - /** - * @dev Emitted when a new reward record is created. - */ - event RewardAdded( - address indexed escrowAddress, - address indexed staker, - address indexed slasher, - uint256 tokens - ); - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - function initialize( - address _token, - address _staking, - uint256 _fees - ) external payable virtual initializer { - __Ownable_init_unchained(); - - __RewardPool_init_unchained(_token, _staking, _fees); - } - - function __RewardPool_init_unchained( - address _token, - address _staking, - uint256 _fees - ) internal onlyInitializing { - token = _token; - staking = _staking; - fees = _fees; - } - - /** - * @dev Add reward record - * Protocol fee is deducted for each reward - */ - function addReward( - address _escrowAddress, - address _staker, - address _slasher, - uint256 _tokens - ) external override onlyStaking { - // If the reward is smaller than protocol fee, just keep as fee - if (_tokens < fees) { - totalFee = totalFee + _tokens; - return; - } - - // Deduct protocol fee for each reward - uint256 rewardAfterFee = _tokens - fees; - totalFee = totalFee + fees; - - // Add reward record - Reward memory reward = Reward(_escrowAddress, _slasher, rewardAfterFee); - rewards[_escrowAddress].push(reward); - - emit RewardAdded(_escrowAddress, _staker, _slasher, rewardAfterFee); - } - - /** - * @dev Return rewards for allocation - */ - function getRewards( - address _escrowAddress - ) external view override returns (Reward[] memory) { - return rewards[_escrowAddress]; - } - - /** - * @dev Distribute rewards for allocation - */ - function distributeReward(address _escrowAddress) external override { - Reward[] memory rewardsForEscrow = rewards[_escrowAddress]; - - require(rewardsForEscrow.length > 0, 'No rewards for escrow'); - - // Delete rewards for allocation - delete rewards[_escrowAddress]; - - // Transfer Tokens - for (uint256 index = 0; index < rewardsForEscrow.length; index += 1) { - Reward memory reward = rewardsForEscrow[index]; - _safeTransfer(reward.slasher, reward.tokens); - } - } - - function withdraw(address to) external override onlyOwner { - uint256 amount = totalFee; - totalFee = 0; - _safeTransfer(to, amount); - } - - function _safeTransfer(address to, uint256 value) internal { - SafeERC20Upgradeable.safeTransfer(IERC20Upgradeable(token), to, value); - } - - modifier onlyStaking() { - require(staking == msg.sender, 'Caller is not staking contract'); - _; - } - - // solhint-disable-next-line no-empty-blocks - function _authorizeUpgrade(address) internal override onlyOwner {} - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - */ - uint256[45] private __gap; -} diff --git a/packages/core/contracts/Staking.sol b/packages/core/contracts/Staking.sol index e4d0005727..b4499ceddd 100644 --- a/packages/core/contracts/Staking.sol +++ b/packages/core/contracts/Staking.sol @@ -1,34 +1,28 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +pragma solidity ^0.8.0; -import '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; +import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; +import '@openzeppelin/contracts/access/Ownable.sol'; +import '@openzeppelin/contracts/utils/ReentrancyGuard.sol'; import './interfaces/HMTokenInterface.sol'; import './interfaces/IEscrow.sol'; -import './interfaces/IRewardPool.sol'; import './interfaces/IStaking.sol'; import './libs/Stakes.sol'; -import './utils/Math.sol'; /** * @title Staking contract - * @dev The Staking contract allows Operator, Exchange Oracle, Recording Oracle and Reputation Oracle to stake to Escrow. + * @dev The Staking contract allows to stake. */ -contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { - using SafeMath for uint256; +contract Staking is IStaking, Ownable, ReentrancyGuard { using Stakes for Stakes.Staker; // Token address address public token; - // Reward pool address - address public override rewardPool; - - // Minimum amount of tokens an staker needs to stake + // Minimum amount of tokens a staker needs to stake uint256 public minimumStake; // Time in blocks to unstake @@ -40,8 +34,13 @@ contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { // List of stakers address[] public stakers; - // Allocations : escrowAddress => Allocation - mapping(address => IStaking.Allocation) public allocations; + // Fee percentage + uint8 public feePercentage; + + // Accumulated fee balance in the contract + uint256 public feeBalance; + + mapping(address => bool) public slashers; /** * @dev Emitted when `staker` stake `tokens` amount. @@ -65,67 +64,25 @@ contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { address indexed staker, uint256 tokens, address indexed escrowAddress, - address slasher - ); - - /** - * @dev Emitted when `staker` allocated `tokens` amount to `escrowAddress`. - */ - event StakeAllocated( - address indexed staker, - uint256 tokens, - address indexed escrowAddress, - uint256 createdAt + address slashRequester ); /** - * @dev Emitted when `staker` close an allocation `escrowAddress`. - */ - event AllocationClosed( - address indexed staker, - uint256 tokens, - address indexed escrowAddress, - uint256 closedAt - ); - - /** - * @dev Emitted when `owner` set new value for `minimumStake`. - */ - event SetMinumumStake(uint256 indexed minimumStake); - - /** - * @dev Emitted when `owner` set new value for `lockPeriod`. + * @dev Emitted when `owner` withdraws the total `amount` of fees. */ - event SetLockPeriod(uint32 indexed lockPeriod); + event FeeWithdrawn(uint256 amount); - /** - * @dev Emitted when `owner` set new value for `rewardPool`. - */ - event SetRewardPool(address indexed rewardPool); - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - function initialize( - address _token, - uint256 _minimumStake, - uint32 _lockPeriod - ) external payable virtual initializer { - __Ownable_init_unchained(); - - __Staking_init_unchained(_token, _minimumStake, _lockPeriod); - } - - function __Staking_init_unchained( + constructor( address _token, uint256 _minimumStake, - uint32 _lockPeriod - ) internal onlyInitializing { + uint32 _lockPeriod, + uint8 _feePercentage + ) Ownable(msg.sender) { token = _token; _setMinimumStake(_minimumStake); _setLockPeriod(_lockPeriod); + _setFeePercentage(_feePercentage); + slashers[owner()] = true; } /** @@ -138,14 +95,9 @@ contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { _setMinimumStake(_minimumStake); } - /** - * @dev Set the minimum stake amount. - * @param _minimumStake Minimum stake - */ function _setMinimumStake(uint256 _minimumStake) private { require(_minimumStake > 0, 'Must be a positive number'); minimumStake = _minimumStake; - emit SetMinumumStake(minimumStake); } /** @@ -156,139 +108,33 @@ contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { _setLockPeriod(_lockPeriod); } - /** - * @dev Set the lock period for unstaking. - * @param _lockPeriod Period in blocks to wait for token withdrawals after unstaking - */ function _setLockPeriod(uint32 _lockPeriod) private { require(_lockPeriod > 0, 'Must be a positive number'); lockPeriod = _lockPeriod; - emit SetLockPeriod(lockPeriod); - } - - /** - * @dev Set the destionations of the rewards. - * @param _rewardPool Reward pool address - */ - function setRewardPool(address _rewardPool) external override onlyOwner { - _setRewardPool(_rewardPool); - } - - /** - * @dev Set the destionations of the rewards. - * @param _rewardPool Reward pool address - */ - function _setRewardPool(address _rewardPool) private { - require(_rewardPool != address(0), 'Must be a valid address'); - rewardPool = _rewardPool; - emit SetRewardPool(_rewardPool); } /** - * @dev Return if escrowAddress is use for allocation. - * @param _escrowAddress Address used as signer by the staker for an allocation - * @return True if _escrowAddress already used + * @dev Set the fee percentage for slashing. + * @param _feePercentage Fee percentage for slashing */ - function isAllocation( - address _escrowAddress - ) external view override returns (bool) { - return _getAllocationState(_escrowAddress) != AllocationState.Null; + function setFeePercentage(uint8 _feePercentage) external onlyOwner { + _setFeePercentage(_feePercentage); } - /** - * @dev Getter that returns if an staker has any stake. - * @param _staker Address of the staker - * @return True if staker has staked tokens - */ - function hasStake(address _staker) external view override returns (bool) { - return stakes[_staker].tokensStaked > 0; + function _setFeePercentage(uint8 _feePercentage) private { + require(_feePercentage <= 100, 'Fee cannot exceed 100%'); + feePercentage = _feePercentage; } /** - * @dev Getter that returns if an staker has any available stake. + * @dev Getter that returns whether a staker has any available stake. * @param _staker Address of the staker * @return True if staker has available tokens staked */ - function hasAvailableStake( + function getAvailableStake( address _staker - ) external view override returns (bool) { - return stakes[_staker].tokensAvailable() > 0; - } - - /** - * @dev Return the allocation by escrow address. - * @param _escrowAddress Address used as allocation identifier - * @return Allocation data - */ - function getAllocation( - address _escrowAddress - ) external view override returns (Allocation memory) { - return _getAllocation(_escrowAddress); - } - - /** - * @dev Return the allocation by job ID. - * @param _escrowAddress Address used as allocation identifier - * @return Allocation data - */ - function _getAllocation( - address _escrowAddress - ) private view returns (Allocation memory) { - return allocations[_escrowAddress]; - } - - /** - * @dev Return the current state of an allocation. - * @param _escrowAddress Address used as the allocation identifier - * @return AllocationState - */ - function getAllocationState( - address _escrowAddress - ) external view override returns (AllocationState) { - return _getAllocationState(_escrowAddress); - } - - /** - * @dev Return the current state of an allocation, partially depends on job status - * @param _escrowAddress Job identifier (Escrow address) - * @return AllocationState - */ - function _getAllocationState( - address _escrowAddress - ) private view returns (AllocationState) { - Allocation storage allocation = allocations[_escrowAddress]; - - if (allocation.staker == address(0)) { - return AllocationState.Null; - } - - IEscrow escrow = IEscrow(_escrowAddress); - IEscrow.EscrowStatuses escrowStatus = escrow.status(); - - if ( - allocation.createdAt != 0 && - allocation.tokens > 0 && - escrowStatus == IEscrow.EscrowStatuses.Pending - ) { - return AllocationState.Pending; - } - - if ( - allocation.closedAt == 0 && - escrowStatus == IEscrow.EscrowStatuses.Launched - ) { - return AllocationState.Active; - } - - if ( - allocation.closedAt == 0 && - (escrowStatus == IEscrow.EscrowStatuses.Complete || - escrowStatus == IEscrow.EscrowStatuses.Cancelled) - ) { - return AllocationState.Completed; - } - - return AllocationState.Closed; + ) external view override returns (uint256) { + return stakes[_staker].tokensAvailable(); } /** @@ -302,38 +148,33 @@ contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { return stakes[_staker].tokensStaked; } - /** - * @dev Get staker data by the staker address. - * @param _staker Address of the staker - * @return Staker's data - */ - function getStaker( - address _staker - ) external view override returns (Stakes.Staker memory) { - return stakes[_staker]; - } - /** * @dev Get list of stakers + * @param _startIndex Index of the first staker to return. + * @param _limit Maximum number of stakers to return. * @return List of staker's addresses, and stake data */ - function getListOfStakers() - external - view - override - returns (address[] memory, Stakes.Staker[] memory) - { - address[] memory _stakerAddresses = stakers; - uint256 _stakersCount = _stakerAddresses.length; - - if (_stakersCount == 0) { - return (new address[](0), new Stakes.Staker[](0)); - } + function getListOfStakers( + uint256 _startIndex, + uint256 _limit + ) external view returns (address[] memory, Stakes.Staker[] memory) { + uint256 _stakersCount = stakers.length; - Stakes.Staker[] memory _stakers = new Stakes.Staker[](_stakersCount); + require(_startIndex < _stakersCount, 'Start index out of bounds'); - for (uint256 _i = 0; _i < _stakersCount; _i++) { - _stakers[_i] = stakes[_stakerAddresses[_i]]; + uint256 endIndex = _startIndex + _limit > _stakersCount + ? _stakersCount + : _startIndex + _limit; + address[] memory _stakerAddresses = new address[]( + endIndex - _startIndex + ); + Stakes.Staker[] memory _stakers = new Stakes.Staker[]( + endIndex - _startIndex + ); + + for (uint256 i = _startIndex; i < endIndex; i++) { + _stakerAddresses[i - _startIndex] = stakers[i]; + _stakers[i - _startIndex] = stakes[stakers[i]]; } return (_stakerAddresses, _stakers); @@ -345,44 +186,36 @@ contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { */ function stake(uint256 _tokens) external override { require(_tokens > 0, 'Must be a positive number'); - - Stakes.Staker memory staker = stakes[msg.sender]; + Stakes.Staker storage staker = stakes[msg.sender]; require( - staker.tokensSecureStake().add(_tokens) >= minimumStake, + staker.tokensAvailable() + _tokens >= minimumStake, 'Total stake is below the minimum threshold' ); if (staker.tokensStaked == 0) { - staker = Stakes.Staker(0, 0, 0, 0); - stakes[msg.sender] = staker; stakers.push(msg.sender); } - _safeTransferFrom(msg.sender, address(this), _tokens); - - stakes[msg.sender].deposit(_tokens); + _safeTransferFrom(token, msg.sender, address(this), _tokens); + staker.deposit(_tokens); emit StakeDeposited(msg.sender, _tokens); } /** - * @dev Unstake tokens from the staker stake, lock them until lock period expires. + * @dev Unstake tokens from the staker's stake, locking them until lock period expires. * @param _tokens Amount of tokens to unstake */ - function unstake(uint256 _tokens) external override { - Stakes.Staker storage staker = stakes[msg.sender]; - + function unstake(uint256 _tokens) external override nonReentrant { require(_tokens > 0, 'Must be a positive number'); + Stakes.Staker storage staker = stakes[msg.sender]; require( - staker.tokensAvailable() >= _tokens, - 'Insufficient amount to unstake' - ); - - uint256 newStake = staker.tokensSecureStake().sub(_tokens); - require( - newStake == 0 || newStake >= minimumStake, - 'Total stake is below the minimum threshold' + staker.tokensLocked == 0 || + staker.tokensLockedUntil <= block.number, + 'Unstake in progress, complete it first' ); + uint256 stakeAvailable = staker.tokensAvailable(); + require(stakeAvailable >= _tokens, 'Insufficient amount to unstake'); uint256 tokensToWithdraw = staker.tokensWithdrawable(); if (tokensToWithdraw > 0) { @@ -399,195 +232,118 @@ contract Staking is IStaking, OwnableUpgradeable, UUPSUpgradeable { } /** - * @dev Withdraw staker tokens based on the locking period. + * @dev Withdraw staker tokens once the lock period has passed. */ - function withdraw() external override { + function withdraw() external override nonReentrant { _withdraw(msg.sender); } - /** - * @dev Withdraw staker tokens once the lock period has passed. - * @param _staker Address of staker to withdraw funds from - */ function _withdraw(address _staker) private { uint256 tokensToWithdraw = stakes[_staker].withdrawTokens(); require( tokensToWithdraw > 0, 'Stake has no available tokens for withdrawal' ); - - _safeTransfer(_staker, tokensToWithdraw); + _safeTransfer(token, _staker, tokensToWithdraw); emit StakeWithdrawn(_staker, tokensToWithdraw); } /** - * @dev Slash the staker stake allocated to the escrow. + * @dev Slash the staker's stake. * @param _staker Address of staker to slash * @param _escrowAddress Escrow address - * @param _tokens Amount of tokens to slash from the indexer stake + * @param _tokens Amount of tokens to slash from the staker's stake */ function slash( - address _slasher, + address _slashRequester, address _staker, address _escrowAddress, uint256 _tokens - ) external override onlyOwner { - require(_escrowAddress != address(0), 'Must be a valid address'); - + ) external override onlySlasher nonReentrant { + require( + _slashRequester != address(0), + 'Must be a valid slash requester address' + ); + require(_escrowAddress != address(0), 'Must be a valid escrow address'); Stakes.Staker storage staker = stakes[_staker]; - - Allocation storage allocation = allocations[_escrowAddress]; - require(_tokens > 0, 'Must be a positive number'); - require( - _tokens <= allocation.tokens, - 'Slash tokens exceed allocated ones' + _tokens <= staker.tokensStaked, + 'Slash amount exceeds staked amount' ); - staker.unallocate(_tokens); - allocation.tokens = allocation.tokens.sub(_tokens); + uint256 feeAmount = (_tokens * feePercentage) / 100; + uint256 tokensToSlash = _tokens - feeAmount; - staker.release(_tokens); + staker.release(tokensToSlash); + feeBalance += feeAmount; - _safeTransfer(rewardPool, _tokens); + _safeTransfer(token, _slashRequester, tokensToSlash); - // Keep record on Reward Pool - IRewardPool(rewardPool).addReward( - _escrowAddress, + emit StakeSlashed( _staker, - _slasher, - _tokens + tokensToSlash, + _escrowAddress, + _slashRequester ); - - emit StakeSlashed(_staker, _tokens, _escrowAddress, _slasher); } /** - * @dev Allocate available tokens to an escrow. - * @param _escrowAddress The allocationID will work to identify collected funds related to this allocation - * @param _tokens Amount of tokens to allocate + * @dev Withdraw the total amount of fees accumulated. */ - function allocate( - address _escrowAddress, - uint256 _tokens - ) external override { - _allocate(msg.sender, _escrowAddress, _tokens); - } + function withdrawFees() external override onlyOwner nonReentrant { + require(feeBalance > 0, 'No fees to withdraw'); + uint256 amount = feeBalance; + feeBalance = 0; - /** - * @dev Allocate available tokens to an escrow. - * @param _staker Staker address to allocate funds from. - * @param _escrowAddress The escrow address which collected funds related to this allocation - * @param _tokens Amount of tokens to allocate - */ - function _allocate( - address _staker, - address _escrowAddress, - uint256 _tokens - ) private { - require(_escrowAddress != address(0), 'Must be a valid address'); - require( - stakes[msg.sender].tokensAvailable() >= _tokens, - 'Insufficient amount of tokens in the stake' - ); - require(_tokens > 0, 'Must be a positive number'); - require( - _getAllocationState(_escrowAddress) == AllocationState.Null, - 'Allocation already exists' - ); - - Allocation memory allocation = Allocation( - _escrowAddress, // Escrow address - _staker, // Staker address - _tokens, // Tokens allocated - block.number, // createdAt - 0 // closedAt - ); + _safeTransfer(token, msg.sender, amount); - allocations[_escrowAddress] = allocation; - stakes[_staker].allocate(allocation.tokens); - - emit StakeAllocated( - _staker, - allocation.tokens, - _escrowAddress, - allocation.createdAt - ); + emit FeeWithdrawn(amount); } /** - * @dev Close an allocation and free the staked tokens. - * @param _escrowAddress The allocation identifier + * @dev Add a new slasher address. */ - function closeAllocation(address _escrowAddress) external override { - require(_escrowAddress != address(0), 'Must be a valid address'); - - _closeAllocation(_escrowAddress); + function addSlasher(address _slasher) external override onlyOwner { + require(_slasher != address(0), 'Invalid slasher address'); + require(!slashers[_slasher], 'Address is already a slasher'); + slashers[_slasher] = true; } /** - * @dev Close an allocation and free the staked tokens. - * @param _escrowAddress The allocation identifier + * @dev Remove an existing slasher address. */ - function _closeAllocation(address _escrowAddress) private { - Allocation storage allocation = allocations[_escrowAddress]; - require( - allocation.staker == msg.sender, - 'Only the allocator can close the allocation' - ); - - AllocationState allocationState = _getAllocationState(_escrowAddress); - require( - allocationState == AllocationState.Completed, - 'Allocation has no completed state' - ); - - allocation.closedAt = block.number; - uint256 diffInBlocks = Math.diffOrZero( - allocation.closedAt, - allocation.createdAt - ); - require(diffInBlocks > 0, 'Allocation cannot be closed so early'); - - uint256 _tokens = allocation.tokens; - - stakes[allocation.staker].unallocate(_tokens); - allocation.tokens = 0; - - emit AllocationClosed( - allocation.staker, - _tokens, - _escrowAddress, - allocation.closedAt - ); + function removeSlasher(address _slasher) external override onlyOwner { + require(slashers[_slasher], 'Address is not a slasher'); + delete slashers[_slasher]; } - function _safeTransfer(address to, uint256 value) internal { - SafeERC20Upgradeable.safeTransfer(IERC20Upgradeable(token), to, value); + modifier onlySlasher() { + require(slashers[msg.sender], 'Caller is not a slasher'); + _; } - function _safeTransferFrom( - address from, - address to, - uint256 value - ) internal { - SafeERC20Upgradeable.safeTransferFrom( - IERC20Upgradeable(token), - from, - to, - value - ); + /** + * @dev Safe transfer helper + */ + function _safeTransfer( + address _token, + address _to, + uint256 _value + ) private { + SafeERC20.safeTransfer(IERC20(_token), _to, _value); } - // solhint-disable-next-line no-empty-blocks - function _authorizeUpgrade(address) internal override onlyOwner {} - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + * @dev Safe transferFrom helper */ - uint256[43] private __gap; + function _safeTransferFrom( + address _token, + address _from, + address _to, + uint256 _value + ) private { + SafeERC20.safeTransferFrom(IERC20(_token), _from, _to, _value); + } } diff --git a/packages/core/contracts/interfaces/IEscrow.sol b/packages/core/contracts/interfaces/IEscrow.sol index c96db4b5fa..3066d9423e 100644 --- a/packages/core/contracts/interfaces/IEscrow.sol +++ b/packages/core/contracts/interfaces/IEscrow.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +pragma solidity ^0.8.0; interface IEscrow { enum EscrowStatuses { @@ -27,14 +27,23 @@ interface IEscrow { string memory _hash ) external; - function abort() external; - function cancel() external returns (bool); + function withdraw(address _token) external returns (bool); + function complete() external; function storeResults(string memory _url, string memory _hash) external; + function bulkPayOut( + address[] memory _recipients, + uint256[] memory _amounts, + string memory _url, + string memory _hash, + uint256 _txId, + bool forceComplete + ) external; + function bulkPayOut( address[] memory _recipients, uint256[] memory _amounts, diff --git a/packages/core/contracts/interfaces/IRewardPool.sol b/packages/core/contracts/interfaces/IRewardPool.sol deleted file mode 100644 index 96963e1f23..0000000000 --- a/packages/core/contracts/interfaces/IRewardPool.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.2; - -interface IRewardPool { - /** - * @dev Keep track of slashers how much they slashed per allocations - */ - struct Reward { - address escrowAddress; - address slasher; - uint256 tokens; // Tokens allocated to a escrowAddress - } - - function addReward( - address _escrowAddress, - address _staker, - address _slasher, - uint256 _tokens - ) external; - - function getRewards( - address _escrowAddress - ) external view returns (Reward[] memory); - - function distributeReward(address _escrowAddress) external; - - function withdraw(address to) external; -} diff --git a/packages/core/contracts/interfaces/IStaking.sol b/packages/core/contracts/interfaces/IStaking.sol index 07d3a0a5e9..f8d37b32fa 100644 --- a/packages/core/contracts/interfaces/IStaking.sol +++ b/packages/core/contracts/interfaces/IStaking.sol @@ -1,78 +1,18 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +pragma solidity ^0.8.0; import '../libs/Stakes.sol'; interface IStaking { - /** - * @dev Possible states an allocation can be - * States: - * - Null = Staker == address(0) - * - Pending = not Null && tokens > 0 && escrowAddress status == Pending - * - Active = Pending && escrowAddress status == Launched - * - Closed = Active && closedAt != 0 - * - Completed = Closed && closedAt && escrowAddress status == Complete - */ - enum AllocationState { - Null, - Pending, - Active, - Closed, - Completed - } - - /** - * @dev Possible sort fields - * Fields: - * - None = Do not sort - * - Stake = Sort by stake amount - */ - enum SortField { - None, - Stake - } - - /** - * @dev Allocate HMT tokens for the purpose of serving queries of a subgraph deployment - * An allocation is created in the allocate() function and consumed in claim() - */ - struct Allocation { - address escrowAddress; - address staker; - uint256 tokens; // Tokens allocated to a escrowAddress - uint256 createdAt; // Time when allocation was created - uint256 closedAt; // Time when allocation was closed - } - - function rewardPool() external view returns (address); - function setMinimumStake(uint256 _minimumStake) external; function setLockPeriod(uint32 _lockPeriod) external; - function setRewardPool(address _rewardPool) external; - - function isAllocation(address _escrowAddress) external view returns (bool); - - function hasStake(address _indexer) external view returns (bool); - - function hasAvailableStake(address _indexer) external view returns (bool); - - function getAllocation( - address _escrowAddress - ) external view returns (Allocation memory); - - function getAllocationState( - address _escrowAddress - ) external view returns (AllocationState); + function getAvailableStake(address _staker) external view returns (uint256); function getStakedTokens(address _staker) external view returns (uint256); - function getStaker( - address _staker - ) external view returns (Stakes.Staker memory); - function stake(uint256 _tokens) external; function unstake(uint256 _tokens) external; @@ -86,12 +26,14 @@ interface IStaking { uint256 _tokens ) external; - function allocate(address escrowAddress, uint256 _tokens) external; + function getListOfStakers( + uint256 _startIndex, + uint256 _limit + ) external view returns (address[] memory, Stakes.Staker[] memory); + + function withdrawFees() external; - function closeAllocation(address _escrowAddress) external; + function addSlasher(address _slasher) external; - function getListOfStakers() - external - view - returns (address[] memory, Stakes.Staker[] memory); + function removeSlasher(address _slasher) external; } diff --git a/packages/core/contracts/libs/Stakes.sol b/packages/core/contracts/libs/Stakes.sol index f3eef6b2f4..d1d323fcab 100644 --- a/packages/core/contracts/libs/Stakes.sol +++ b/packages/core/contracts/libs/Stakes.sol @@ -1,20 +1,13 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; - -import '../utils/SafeMath.sol'; -import '../utils/Math.sol'; +pragma solidity ^0.8.0; /** * @title Structures, methods and data are available to manage the staker state. */ library Stakes { - using SafeMath for uint256; - using Stakes for Stakes.Staker; - struct Staker { uint256 tokensStaked; // Tokens staked by the Staker - uint256 tokensAllocated; // Tokens allocated for jobs uint256 tokensLocked; // Tokens locked for withdrawal uint256 tokensLockedUntil; // Tokens locked until time } @@ -25,7 +18,7 @@ library Stakes { * @param _tokens Amount of tokens to deposit */ function deposit(Stakes.Staker storage stake, uint256 _tokens) internal { - stake.tokensStaked = stake.tokensStaked.add(_tokens); + stake.tokensStaked += _tokens; } /** @@ -34,25 +27,7 @@ library Stakes { * @param _tokens Amount of tokens to release */ function release(Stakes.Staker storage stake, uint256 _tokens) internal { - stake.tokensStaked = stake.tokensStaked.sub(_tokens); - } - - /** - * @dev Add tokens from the main stack to tokensAllocated. - * @param stake Staker struct - * @param _tokens Amount of tokens to allocate - */ - function allocate(Stakes.Staker storage stake, uint256 _tokens) internal { - stake.tokensAllocated = stake.tokensAllocated.add(_tokens); - } - - /** - * @dev Unallocate tokens from a escrowAddress back to the main stack. - * @param stake Staker struct - * @param _tokens Amount of tokens to unallocate - */ - function unallocate(Stakes.Staker storage stake, uint256 _tokens) internal { - stake.tokensAllocated = stake.tokensAllocated.sub(_tokens); + stake.tokensStaked -= _tokens; } /** @@ -66,34 +41,21 @@ library Stakes { uint256 _tokens, uint256 _period ) internal { - uint256 lockingPeriod = _period; - - if (stake.tokensLocked > 0) { - lockingPeriod = Math.weightedAverage( - Math.diffOrZero(stake.tokensLockedUntil, block.number), // Remaining lock period - stake.tokensLocked, - _period, - _tokens - ); - } - - stake.tokensLocked = stake.tokensLocked.add(_tokens); - stake.tokensLockedUntil = block.number.add(lockingPeriod); + stake.tokensLocked += _tokens; + stake.tokensLockedUntil = block.number + _period; } /** * @dev Unlock tokens. * @param stake Staker struct - * @param _tokens Amount of tokens to unkock + * @param _tokens Amount of tokens to unlock */ function unlockTokens( Stakes.Staker storage stake, uint256 _tokens ) internal { - stake.tokensLocked = stake.tokensLocked.sub(_tokens); - if (stake.tokensLocked == 0) { - stake.tokensLockedUntil = 0; - } + stake.tokensLocked -= _tokens; + stake.tokensLockedUntil = 0; } /** @@ -104,11 +66,11 @@ library Stakes { function withdrawTokens( Stakes.Staker storage stake ) internal returns (uint256) { - uint256 tokensToWithdraw = stake.tokensWithdrawable(); + uint256 tokensToWithdraw = tokensWithdrawable(stake); if (tokensToWithdraw > 0) { - stake.unlockTokens(tokensToWithdraw); - stake.release(tokensToWithdraw); + unlockTokens(stake, tokensToWithdraw); + release(stake, tokensToWithdraw); } return tokensToWithdraw; @@ -122,29 +84,7 @@ library Stakes { function tokensAvailable( Stakes.Staker memory stake ) internal pure returns (uint256) { - return stake.tokensStaked.sub(stake.tokensUsed()); - } - - /** - * @dev Return all tokens used in allocations and locked for withdrawal. - * @param stake Staker struct - * @return Token amount - */ - function tokensUsed( - Stakes.Staker memory stake - ) internal pure returns (uint256) { - return stake.tokensAllocated.add(stake.tokensLocked); - } - - /** - * @dev Return the amount of tokens staked which are not locked. - * @param stake Staker struct - * @return Token amount - */ - function tokensSecureStake( - Stakes.Staker memory stake - ) internal pure returns (uint256) { - return stake.tokensStaked.sub(stake.tokensLocked); + return stake.tokensStaked - stake.tokensLocked; } /** diff --git a/packages/core/contracts/test/EscrowFactoryV0.sol b/packages/core/contracts/test/EscrowFactoryV0.sol index d0828c7b37..af421729d4 100644 --- a/packages/core/contracts/test/EscrowFactoryV0.sol +++ b/packages/core/contracts/test/EscrowFactoryV0.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; +pragma solidity ^0.8.0; import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; @@ -17,33 +17,52 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable { mapping(address => uint256) public escrowCounters; address public lastEscrow; address public staking; + uint256 public minimumStake; - event Launched(address token, address escrow); - event LaunchedV2(address token, address escrow, string jobRequesterId); + event Launched(address indexed token, address indexed escrow); + event LaunchedV2( + address indexed token, + address indexed escrow, + string jobRequesterId + ); + event SetStakingAddress(address indexed stakingAddress); + event SetMinumumStake(uint256 indexed minimumStake); - function initialize(address _staking) external payable virtual initializer { - __Ownable_init_unchained(); - __EscrowFactory_init_unchained(_staking); + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); } - function __EscrowFactory_init_unchained( - address _staking - ) internal onlyInitializing { + function initialize( + address _staking, + uint256 _minimumStake + ) external payable virtual initializer { + __Ownable_init_unchained(); require(_staking != address(0), ERROR_ZERO_ADDRESS); staking = _staking; + minimumStake = _minimumStake; } + /** + * @dev Creates a new Escrow contract. + * + * @param token Token address to be associated with the Escrow contract. + * @param trustedHandlers Array of addresses that will serve as the trusted handlers for the Escrow. + * @param jobRequesterId String identifier for the job requester, used for tracking purposes. + * + * @return The address of the newly created Escrow contract. + */ function createEscrow( address token, address[] memory trustedHandlers, string memory jobRequesterId - ) public returns (address) { - bool hasAvailableStake = IStaking(staking).hasAvailableStake( + ) external returns (address) { + uint256 availableStake = IStaking(staking).getAvailableStake( msg.sender ); require( - hasAvailableStake == true, - 'Needs to stake HMT tokens to create an escrow.' + availableStake >= minimumStake, + 'Insufficient stake to create an escrow.' ); Escrow escrow = new Escrow( @@ -60,7 +79,34 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable { return lastEscrow; } - // solhint-disable-next-line no-empty-blocks + /** + * @dev Set the Staking address. + * @param _stakingAddress Staking address + */ + function setStakingAddress(address _stakingAddress) external onlyOwner { + _setStakingAddress(_stakingAddress); + } + + function _setStakingAddress(address _stakingAddress) private { + require(_stakingAddress != address(0), ERROR_ZERO_ADDRESS); + staking = _stakingAddress; + emit SetStakingAddress(_stakingAddress); + } + + /** + * @dev Set the minimum stake amount. + * @param _minimumStake Minimum stake + */ + function setMinimumStake(uint256 _minimumStake) external onlyOwner { + _setMinimumStake(_minimumStake); + } + + function _setMinimumStake(uint256 _minimumStake) private { + require(_minimumStake > 0, 'Must be a positive number'); + minimumStake = _minimumStake; + emit SetMinumumStake(minimumStake); + } + function _authorizeUpgrade(address) internal override onlyOwner {} /** @@ -68,5 +114,5 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable { * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[46] private __gap; + uint256[45] private __gap; } diff --git a/packages/core/contracts/test/USDT.sol b/packages/core/contracts/test/USDT.sol new file mode 100644 index 0000000000..b35286138e --- /dev/null +++ b/packages/core/contracts/test/USDT.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.6.2; + +import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; + +contract USDT is ERC20 { + constructor() ERC20('Tether', 'USDT') { + _mint(msg.sender, 1000000 * 10 ** 18); + } +} diff --git a/packages/core/contracts/utils/Math.sol b/packages/core/contracts/utils/Math.sol deleted file mode 100644 index 1cc658a483..0000000000 --- a/packages/core/contracts/utils/Math.sol +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.2; - -import './SafeMath.sol'; - -/** - * @title Math Library - * @notice A collection of functions to perform math operations - */ -library Math { - using SafeMath for uint256; - - enum Rounding { - Down, // Toward negative infinity - Up, // Toward infinity - Zero // Toward zero - } - - /** - * @dev Returns the largest of two numbers. - */ - function max(uint256 a, uint256 b) internal pure returns (uint256) { - return a > b ? a : b; - } - - /** - * @dev Returns the smallest of two numbers. - */ - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } - - /** - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow. - return (a & b) + (a ^ b) / 2; - } - - /** - * @dev Calculates the weighted average of two values pondering each of these - * values based on configured weights. The contribution of each value N is - * weightN/(weightA + weightB). - * @param valueA The amount for value A - * @param weightA The weight to use for value A - * @param valueB The amount for value B - * @param weightB The weight to use for value B - */ - function weightedAverage( - uint256 valueA, - uint256 weightA, - uint256 valueB, - uint256 weightB - ) internal pure returns (uint256) { - return - valueA.mul(weightA).add(valueB.mul(weightB)).div( - weightA.add(weightB) - ); - } - - /** - * @dev Returns the difference between two numbers or zero if negative. - */ - function diffOrZero(uint256 x, uint256 y) internal pure returns (uint256) { - return (x > y) ? x.sub(y) : 0; - } - - /** - * @dev Returns the ceiling of the division of two numbers. - * - * This differs from standard division with `/` in that it rounds up instead - * of rounding down. - */ - function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b - 1) / b can overflow on addition, so we distribute. - return a == 0 ? 0 : (a - 1) / b + 1; - } - - /** - * @dev Return the log in base 10, rounded down, of a positive value. - * Returns 0 if given 0. - */ - function log10(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >= 10 ** 64) { - value /= 10 ** 64; - result += 64; - } - if (value >= 10 ** 32) { - value /= 10 ** 32; - result += 32; - } - if (value >= 10 ** 16) { - value /= 10 ** 16; - result += 16; - } - if (value >= 10 ** 8) { - value /= 10 ** 8; - result += 8; - } - if (value >= 10 ** 4) { - value /= 10 ** 4; - result += 4; - } - if (value >= 10 ** 2) { - value /= 10 ** 2; - result += 2; - } - if (value >= 10 ** 1) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 10, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log10( - uint256 value, - Rounding rounding - ) internal pure returns (uint256) { - unchecked { - uint256 result = log10(value); - return - result + - (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); - } - } - - /** - * @dev Return the log in base 256, rounded down, of a positive value. - * Returns 0 if given 0. - * - * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. - */ - function log256(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >> 128 > 0) { - value >>= 128; - result += 16; - } - if (value >> 64 > 0) { - value >>= 64; - result += 8; - } - if (value >> 32 > 0) { - value >>= 32; - result += 4; - } - if (value >> 16 > 0) { - value >>= 16; - result += 2; - } - if (value >> 8 > 0) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 10, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log256( - uint256 value, - Rounding rounding - ) internal pure returns (uint256) { - unchecked { - uint256 result = log256(value); - return - result + - (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); - } - } -} diff --git a/packages/core/contracts/utils/SignedSafeMath.sol b/packages/core/contracts/utils/SignedSafeMath.sol deleted file mode 100644 index 17962082a1..0000000000 --- a/packages/core/contracts/utils/SignedSafeMath.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.0; - -/** - * @title SignedSafeMath - * @dev Signed math operations with safety checks that revert on error. - */ -library SignedSafeMath { - int256 private constant _INT256_MIN = -2 ** 255; - - /** - * @dev Returns the multiplication of two signed integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(int256 a, int256 b) internal pure returns (int256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - require( - !(a == -1 && b == _INT256_MIN), - 'SignedSafeMath: multiplication overflow' - ); - - int256 c = a * b; - require(c / a == b, 'SignedSafeMath: multiplication overflow'); - - return c; - } - - /** - * @dev Returns the integer division of two signed integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(int256 a, int256 b) internal pure returns (int256) { - require(b != 0, 'SignedSafeMath: division by zero'); - require( - !(b == -1 && a == _INT256_MIN), - 'SignedSafeMath: division overflow' - ); - - int256 c = a / b; - - return c; - } - - /** - * @dev Returns the subtraction of two signed integers, reverting on - * overflow. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(int256 a, int256 b) internal pure returns (int256) { - int256 c = a - b; - require( - (b >= 0 && c <= a) || (b < 0 && c > a), - 'SignedSafeMath: subtraction overflow' - ); - - return c; - } - - /** - * @dev Returns the addition of two signed integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(int256 a, int256 b) internal pure returns (int256) { - int256 c = a + b; - require( - (b >= 0 && c >= a) || (b < 0 && c < a), - 'SignedSafeMath: addition overflow' - ); - - return c; - } -} diff --git a/packages/core/hardhat.config.ts b/packages/core/hardhat.config.ts index edc71e0aa2..c6d98c6a9f 100644 --- a/packages/core/hardhat.config.ts +++ b/packages/core/hardhat.config.ts @@ -208,7 +208,7 @@ const config: HardhatUserConfig = { mainnet: process.env.ETHERSCAN_API_KEY || '', sepolia: process.env.ETHERSCAN_API_KEY || '', polygon: process.env.POLYGONSCAN_API_KEY || '', - polygonAmoy: process.env.AMOY_API_KEY || '', + polygonAmoy: process.env.POLYGONSCAN_API_KEY || '', bsc: process.env.BSC_API_KEY || '', bscTestnet: process.env.BSC_API_KEY || '', moonbeam: process.env.MOONSCAN_API_KEY || '', @@ -221,14 +221,6 @@ const config: HardhatUserConfig = { xlayerTestnet: process.env.OKLINK_API_KEY || '', }, customChains: [ - { - network: 'polygonAmoy', - chainId: 80002, - urls: { - apiURL: 'https://api-amoy.polygonscan.com/api', - browserURL: 'https://amoy.polygonscan.com', - }, - }, { network: 'xlayer', chainId: 196, diff --git a/packages/core/scripts/deploy-proxies.ts b/packages/core/scripts/deploy-proxies.ts index 11f195e95e..1f82d40f10 100644 --- a/packages/core/scripts/deploy-proxies.ts +++ b/packages/core/scripts/deploy-proxies.ts @@ -11,7 +11,7 @@ async function main() { const Staking = await ethers.getContractFactory('Staking'); const stakingContract = await upgrades.deployProxy( Staking, - [hmtAddress, 1, 1], + [hmtAddress, 1, 1, 1], { initializer: 'initialize', kind: 'uups' } ); await stakingContract.waitForDeployment(); @@ -47,27 +47,6 @@ async function main() { const kvStoreContract = await KVStore.deploy(); console.log('KVStore Address: ', await kvStoreContract.getAddress()); - - const RewardPool = await ethers.getContractFactory('RewardPool'); - const rewardPoolContract = await upgrades.deployProxy( - RewardPool, - [hmtAddress, await stakingContract.getAddress(), 1], - { initializer: 'initialize', kind: 'uups' } - ); - await rewardPoolContract.waitForDeployment(); - console.log( - 'Reward Pool Proxy Address: ', - await rewardPoolContract.getAddress() - ); - console.log( - 'Reward Pool Implementation Address: ', - await upgrades.erc1967.getImplementationAddress( - await rewardPoolContract.getAddress() - ) - ); - - // Configure RewardPool in Staking - await stakingContract.setRewardPool(await rewardPoolContract.getAddress()); } main().catch((error) => { diff --git a/packages/core/scripts/deploy.ts b/packages/core/scripts/deploy.ts index f664e4d72a..095e2321ba 100644 --- a/packages/core/scripts/deploy.ts +++ b/packages/core/scripts/deploy.ts @@ -14,23 +14,14 @@ async function main() { 'HMT' ); await HMTokenContract.waitForDeployment(); - console.log('HMToken Address: ', await HMTokenContract.getAddress()); + const hmtAddress = await HMTokenContract.getAddress(); + console.log('HMToken Address: ', hmtAddress); const Staking = await ethers.getContractFactory('Staking'); - const stakingContract = await upgrades.deployProxy( - Staking, - [await HMTokenContract.getAddress(), 1, 10], - { initializer: 'initialize', kind: 'uups' } - ); + const stakingContract = await Staking.deploy(hmtAddress, 1, 1000, 1); await stakingContract.waitForDeployment(); - console.log('Staking Proxy Address: ', await stakingContract.getAddress()); - console.log( - 'Staking Implementation Address: ', - await upgrades.erc1967.getImplementationAddress( - await stakingContract.getAddress() - ) - ); + console.log('Staking Address: ', await stakingContract.getAddress()); const EscrowFactory = await ethers.getContractFactory( 'contracts/EscrowFactory.sol:EscrowFactory' @@ -58,27 +49,6 @@ async function main() { console.log('KVStore Address: ', await kvStoreContract.getAddress()); - const RewardPool = await ethers.getContractFactory('RewardPool'); - const rewardPoolContract = await upgrades.deployProxy( - RewardPool, - [await HMTokenContract.getAddress(), await stakingContract.getAddress(), 1], - { initializer: 'initialize', kind: 'uups' } - ); - await rewardPoolContract.waitForDeployment(); - console.log( - 'Reward Pool Proxy Address: ', - await rewardPoolContract.getAddress() - ); - console.log( - 'Reward Pool Implementation Address: ', - await upgrades.erc1967.getImplementationAddress( - await rewardPoolContract.getAddress() - ) - ); - - // Configure RewardPool in Staking - await stakingContract.setRewardPool(await rewardPoolContract.getAddress()); - for (const account of accounts) { await (HMTokenContract as HMToken).transfer( account.address, diff --git a/packages/core/scripts/update-history-files.ts b/packages/core/scripts/update-history-files.ts index c8eb50a475..a81e2f26a0 100644 --- a/packages/core/scripts/update-history-files.ts +++ b/packages/core/scripts/update-history-files.ts @@ -3,8 +3,7 @@ import { ethers, upgrades } from 'hardhat'; async function main() { const escrowFactoryAddress = process.env.ESCROW_FACTORY_ADDRESS; const stakingAddress = process.env.STAKING_ADDRESS; - const rewardPoolAddress = process.env.REWARD_POOL_ADDRESS; - if (!(escrowFactoryAddress && stakingAddress && rewardPoolAddress)) { + if (!(escrowFactoryAddress && stakingAddress)) { console.error('Env variable missing'); return; } @@ -18,9 +17,6 @@ async function main() { const Staking = await ethers.getContractFactory('Staking'); await upgrades.forceImport(stakingAddress, Staking, { kind: 'uups' }); - - const RewardPool = await ethers.getContractFactory('RewardPool'); - await upgrades.forceImport(rewardPoolAddress, RewardPool, { kind: 'uups' }); } main().catch((error) => { diff --git a/packages/core/scripts/upgrade-proxies.ts b/packages/core/scripts/upgrade-proxies.ts index 19f14bf2ad..bd1cdbe41d 100644 --- a/packages/core/scripts/upgrade-proxies.ts +++ b/packages/core/scripts/upgrade-proxies.ts @@ -4,12 +4,8 @@ import { ethers, upgrades } from 'hardhat'; async function main() { const escrowFactoryAddress = process.env.ESCROW_FACTORY_ADDRESS; const deployEscrowFactory = process.env.DEPLOY_ESCROW_FACTORY; - const stakingAddress = process.env.STAKING_ADDRESS; - const deployStaking = process.env.DEPLOY_STAKING; - const rewardPoolAddress = process.env.REWARD_POOL_ADDRESS; - const deployRewardPool = process.env.DEPLOY_REWARD_POOL; - if (!escrowFactoryAddress && !stakingAddress && !rewardPoolAddress) { + if (!escrowFactoryAddress) { console.error('Env variable missing'); return; } @@ -23,10 +19,11 @@ async function main() { escrowFactoryAddress, EscrowFactory ); - const contract = await escrowFactoryContract.deployed(); - await ethers.provider.getTransactionReceipt( - contract.deployTransaction.hash - ); + const contract = await escrowFactoryContract.waitForDeployment(); + const hash = contract.deploymentTransaction()?.hash; + if (hash) { + await ethers.provider.getTransactionReceipt(hash); + } console.log( 'Escrow Factory Proxy Address: ', @@ -39,51 +36,6 @@ async function main() { ) ); } - - if (deployStaking == 'true' && stakingAddress) { - const Staking = await ethers.getContractFactory('Staking'); - // await upgrades.forceImport(stakingAddress, Staking, { kind: 'uups' }); //use this to get ./openzeppelin/[network].json - const stakingContract = await upgrades.upgradeProxy( - stakingAddress, - Staking - ); - const contract = await stakingContract.deployed(); - await ethers.provider.getTransactionReceipt( - contract.deployTransaction.hash - ); - - console.log('Staking Proxy Address: ', await stakingContract.getAddress()); - console.log( - 'New Staking Implementation Address: ', - await upgrades.erc1967.getImplementationAddress( - await stakingContract.getAddress() - ) - ); - } - - if (deployRewardPool == 'true' && rewardPoolAddress) { - const RewardPool = await ethers.getContractFactory('RewardPool'); - // await upgrades.forceImport(rewardPoolAddress, RewardPool, { kind: 'uups' }); //use this to get ./openzeppelin/[network].json - const rewardPoolContract = await upgrades.upgradeProxy( - rewardPoolAddress, - RewardPool - ); - const contract = await rewardPoolContract.deployed(); - await ethers.provider.getTransactionReceipt( - contract.deployTransaction.hash - ); - - console.log( - 'Reward Pool Proxy Address: ', - await rewardPoolContract.getAddress() - ); - console.log( - 'New Reward Pool Implementation Address: ', - await upgrades.erc1967.getImplementationAddress( - await rewardPoolContract.getAddress() - ) - ); - } } main().catch((error) => { diff --git a/packages/core/test/Escrow-USDT.ts b/packages/core/test/Escrow-USDT.ts new file mode 100644 index 0000000000..62853600f9 --- /dev/null +++ b/packages/core/test/Escrow-USDT.ts @@ -0,0 +1,979 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { anyValue } from '@nomicfoundation/hardhat-chai-matchers/withArgs'; +import { expect } from 'chai'; +import { ethers } from 'hardhat'; +import { EventLog, Signer } from 'ethers'; +import { USDT, Escrow, HMToken } from '../typechain-types'; + +const MOCK_URL = 'http://google.com/fake'; +const MOCK_HASH = 'kGKmnj9BRf'; +const BULK_MAX_COUNT = 100; + +enum Status { + Launched = 0, + Pending = 1, + Partial = 2, + Paid = 3, + Complete = 4, + Cancelled = 5, +} + +let owner: Signer, + launcher: Signer, + reputationOracle: Signer, + recordingOracle: Signer, + exchangeOracle: Signer, + externalAddress: Signer, + restAccounts: Signer[], + trustedHandlers: Signer[]; + +let hmtoken: HMToken, escrow: Escrow; +let usdt: USDT; + +async function deployEscrow() { + // Deploy Escrow Contract + const Escrow = await ethers.getContractFactory('contracts/Escrow.sol:Escrow'); + escrow = (await Escrow.deploy( + await usdt.getAddress(), + await launcher.getAddress(), + await owner.getAddress(), + 100, + await Promise.all( + trustedHandlers.map(async (handler) => await handler.getAddress()) + ) + )) as Escrow; +} + +async function setupEscrow() { + await escrow + .connect(owner) + .setup( + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress(), + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ); +} + +async function fundEscrow() { + const amount = 100; + await usdt.connect(owner).transfer(escrow.getAddress(), amount); +} + +describe('Escrow with USDT', function () { + this.beforeAll(async () => { + [ + owner, + launcher, + reputationOracle, + recordingOracle, + exchangeOracle, + externalAddress, + ...restAccounts + ] = await ethers.getSigners(); + + trustedHandlers = [restAccounts[0], restAccounts[1]]; + + // Deploy HMTToken Contract + const HMToken = await ethers.getContractFactory( + 'contracts/HMToken.sol:HMToken' + ); + hmtoken = (await HMToken.deploy( + 1000000000, + 'Human Token', + 18, + 'HMT' + )) as HMToken; + + // Deploy USDT Contract + const USDT = await ethers.getContractFactory( + 'contracts/test/USDT.sol:USDT' + ); + usdt = (await USDT.deploy()) as USDT; + }); + + describe('deployment', () => { + before(async () => { + await deployEscrow(); + }); + + it('Should set the right token address', async () => { + const result = await escrow.token(); + expect(result).to.equal(await usdt.getAddress()); + }); + + it('Should set the right launched status', async () => { + const result = await escrow.status(); + expect(result).to.equal(Status.Launched); + }); + + it('Should set the right escrow balance', async () => { + const result = await escrow.connect(launcher).getBalance(); + expect(result.toString()).to.equal('0'); + }); + + it('Should set the right contract creator', async () => { + const result = await escrow.launcher(); + expect(result).to.equal(await launcher.getAddress()); + }); + + it('Should set the right escrow factory contract', async () => { + const result = await escrow.escrowFactory(); + expect(result).to.equal(await owner.getAddress()); + }); + + it('Should topup and return the right escrow balance', async () => { + const amount = 1000; + await usdt.connect(owner).transfer(escrow.getAddress(), amount); + + const result = await escrow.connect(launcher).getBalance(); + expect(result).to.equal(amount.toString()); + }); + }); + + describe('addTrustedHandlers', async () => { + before(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + describe('Validations', function () { + it('Should revert with the right error if caller cannot add trusted handlers', async function () { + await expect( + escrow + .connect(externalAddress) + .addTrustedHandlers([await reputationOracle.getAddress()]) + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert when adding trusted handlers from reputation oracle', async function () { + await expect( + escrow + .connect(reputationOracle) + .addTrustedHandlers([await externalAddress.getAddress()]) + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert when adding trusted handlers from recording oracle', async function () { + await expect( + escrow + .connect(recordingOracle) + .addTrustedHandlers([await externalAddress.getAddress()]) + ).to.be.revertedWith('Address calling not trusted'); + }); + }); + + describe('Add trusted handlers', async function () { + it('Should succeed when the contract launcher address trusted handlers and a trusted handler stores results', async () => { + await escrow + .connect(owner) + .addTrustedHandlers([await restAccounts[2].getAddress()]); + + const result = await ( + await escrow + .connect(restAccounts[2]) + .storeResults(MOCK_URL, MOCK_HASH) + ).wait(); + + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_URL); + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_HASH); + }); + + it('Should succeed when add a new trusted handler from trusted handler and a trusted handler stores results', async () => { + await escrow + .connect(trustedHandlers[0]) + .addTrustedHandlers([await restAccounts[3].getAddress()]); + + const result = await ( + await escrow + .connect(restAccounts[3]) + .storeResults(MOCK_URL, MOCK_HASH) + ).wait(); + + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_URL); + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_HASH); + }); + }); + }); + + describe('storeResults', async () => { + describe('Validations', function () { + before(async () => { + await deployEscrow(); + }); + it('Should revert with the right error if address calling not trusted', async function () { + await expect( + escrow.connect(externalAddress).storeResults(MOCK_URL, MOCK_HASH) + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert with the right error if address calling is reputation oracle', async function () { + await expect( + escrow.connect(reputationOracle).storeResults(MOCK_URL, MOCK_HASH) + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert with the right error if escrow not in Pending or Partial status state', async function () { + await escrow + .connect(owner) + .addTrustedHandlers([await reputationOracle.getAddress()]); + await expect( + escrow.connect(reputationOracle).storeResults(MOCK_URL, MOCK_HASH) + ).to.be.revertedWith('Escrow not in Pending or Partial status state'); + }); + }); + + describe('Events', function () { + before(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should emit an event on intermediate storage', async function () { + await expect( + await escrow.connect(owner).storeResults(MOCK_URL, MOCK_HASH) + ) + .to.emit(escrow, 'IntermediateStorage') + .withArgs(MOCK_URL, MOCK_HASH); + }); + }); + + describe('Store results', async function () { + before(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should succeed when recording oracle stores results', async () => { + const result = await ( + await escrow + .connect(recordingOracle) + .storeResults(MOCK_URL, MOCK_HASH) + ).wait(); + + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_URL); + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_HASH); + }); + + it('Should succeed when a trusted handler stores results', async () => { + const result = await ( + await escrow + .connect(trustedHandlers[0]) + .storeResults(MOCK_URL, MOCK_HASH) + ).wait(); + + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_URL); + expect((result?.logs[0] as EventLog).args).to.contain(MOCK_HASH); + }); + }); + }); + + describe('setup', () => { + describe('Validations', function () { + before(async () => { + await deployEscrow(); + }); + + it('Should revert with the right error if address calling not trusted', async function () { + await expect( + escrow + .connect(externalAddress) + .setup( + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress(), + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ) + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert with the right error if set invalid or missing reputation oracle address', async function () { + await expect( + escrow + .connect(owner) + .setup( + ethers.ZeroAddress, + await recordingOracle.getAddress(), + await exchangeOracle.getAddress(), + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ) + ).to.be.revertedWith('Invalid reputation oracle address'); + }); + + it('Should revert with the right error if set invalid or missing recording oracle address', async function () { + await expect( + escrow + .connect(owner) + .setup( + await reputationOracle.getAddress(), + ethers.ZeroAddress, + await exchangeOracle.getAddress(), + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ) + ).to.be.revertedWith('Invalid recording oracle address'); + }); + + it('Should revert with the right error if set invalid or missing exchange oracle address', async function () { + await expect( + escrow + .connect(owner) + .setup( + await reputationOracle.getAddress(), + await reputationOracle.getAddress(), + ethers.ZeroAddress, + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ) + ).to.be.revertedWith('Invalid exchange oracle address'); + }); + + it('Should revert with the right error if fee percentage out of bounds and too high', async function () { + await expect( + escrow + .connect(owner) + .setup( + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress(), + 40, + 40, + 40, + MOCK_URL, + MOCK_HASH + ) + ).to.be.revertedWith('Percentage out of bounds'); + }); + }); + + describe('Events', function () { + before(async () => { + await deployEscrow(); + await fundEscrow(); + }); + + it('Should emit an event on pending', async function () { + await expect( + escrow + .connect(owner) + .setup( + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress(), + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ) + ) + .to.emit(escrow, 'PendingV2') + .withArgs( + MOCK_URL, + MOCK_HASH, + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress() + ) + .to.emit(escrow, 'Fund') + .withArgs(100); + }); + }); + + describe('Setup escrow', async function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + }); + + it('Should set correct escrow with params', async () => { + await escrow + .connect(owner) + .setup( + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress(), + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ); + + expect(await escrow.reputationOracle()).to.equal( + await reputationOracle.getAddress() + ); + expect(await escrow.recordingOracle()).to.equal( + await recordingOracle.getAddress() + ); + expect(await escrow.exchangeOracle()).to.equal( + await exchangeOracle.getAddress() + ); + expect(await escrow.manifestUrl()).to.equal(MOCK_URL); + expect(await escrow.manifestHash()).to.equal(MOCK_HASH); + expect(await escrow.status()).to.equal(Status.Pending); + }); + + it('Should set correct escrow with params by trusted handler', async () => { + await escrow + .connect(trustedHandlers[0]) + .setup( + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress(), + 10, + 10, + 10, + MOCK_URL, + MOCK_HASH + ); + + expect(await escrow.reputationOracle()).to.equal( + await reputationOracle.getAddress() + ); + expect(await escrow.recordingOracle()).to.equal( + await recordingOracle.getAddress() + ); + expect(await escrow.exchangeOracle()).to.equal( + await exchangeOracle.getAddress() + ); + expect(await escrow.manifestUrl()).to.equal(MOCK_URL); + expect(await escrow.manifestHash()).to.equal(MOCK_HASH); + expect(await escrow.status()).to.equal(Status.Pending); + }); + }); + }); + + describe('cancel', () => { + describe('Validations', function () { + before(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + + await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ]([await restAccounts[0].getAddress()], [100], MOCK_URL, MOCK_HASH, '000'); + }); + + it('Should revert with the right error if address calling not trusted', async function () { + await expect( + escrow.connect(externalAddress).cancel() + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert with the right error if address calling is reputation oracle', async function () { + await expect( + escrow.connect(reputationOracle).cancel() + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert with the right error if address calling is recording oracle', async function () { + await expect( + escrow.connect(recordingOracle).cancel() + ).to.be.revertedWith('Address calling not trusted'); + }); + }); + + describe('Cancel escrow', async function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should succeed when the contract was canceled', async () => { + await escrow.connect(owner).cancel(); + const ststus = await escrow.status(); + expect(ststus).to.equal(Status.Cancelled); + + expect( + await usdt.connect(owner).balanceOf(escrow.getAddress()) + ).to.equal('0', 'Escrow has not been properly canceled'); + }); + + it('Should succeed when the contract was canceled by trusted handler', async () => { + await escrow.connect(trustedHandlers[0]).cancel(); + const ststus = await escrow.status(); + expect(ststus).to.equal(Status.Cancelled); + + expect( + await usdt.connect(owner).balanceOf(escrow.getAddress()) + ).to.equal('0', 'Escrow has not been properly canceled'); + }); + }); + }); + + describe('bulkPayOut', () => { + describe('Validations', function () { + before(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should revert with the right error if address calling is not trusted', async function () { + const recepients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + + await expect( + escrow + .connect(externalAddress) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert with the right error if address calling is recording oracle', async function () { + const recepients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + + await expect( + escrow + .connect(recordingOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') + ).to.be.revertedWith('Address calling not trusted'); + }); + + it('Should revert with the right error if amount of recipients more then amount of values', async function () { + const recepients = [ + await restAccounts[0].getAddress(), + await restAccounts[1].getAddress(), + await restAccounts[2].getAddress(), + ]; + const amounts = [10, 20]; + + await expect( + escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') + ).to.be.revertedWith("Amount of recipients and values don't match"); + }); + + it('Should revert with the right error if amount of recipients less then amount of values', async function () { + const recepients = [ + await restAccounts[0].getAddress(), + await restAccounts[1].getAddress(), + ]; + const amounts = [10, 20, 30]; + + await expect( + escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') + ).to.be.revertedWith("Amount of recipients and values don't match"); + }); + + it('Should revert with the right error if too many recipients', async function () { + const recepients = Array.from( + new Array(BULK_MAX_COUNT + 1), + () => ethers.ZeroAddress + ); + const amounts = Array.from({ length: BULK_MAX_COUNT + 1 }, () => 1); + + await expect( + escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') + ).to.be.revertedWith('Too many recipients'); + }); + }); + + describe('Events', function () { + this.beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should emit bulkPayOut and Completed events for complete bulkPayOut', async function () { + const recepients = [await restAccounts[0].getAddress()]; + const amounts = [100]; + + const tx = await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + + await expect(tx) + .to.emit(escrow, 'BulkTransferV2') + .withArgs(anyValue, recepients, [100], false, MOCK_URL); + + await expect(tx).to.emit(escrow, 'Completed'); + }); + + it('Should emit only bulkPayOut event for partial bulkPayOut', async function () { + const recepients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + + const tx = await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + + await expect(tx) + .to.emit(escrow, 'BulkTransferV2') + .withArgs(anyValue, recepients, [10], true, MOCK_URL); + + await expect(tx).not.to.emit(escrow, 'Completed'); + }); + + it('Should emit bulkPayOut and Completed events for partial bulkPayOut with forceComplete option', async function () { + const recepients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + + const tx = await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000', true); + + await expect(tx) + .to.emit(escrow, 'BulkTransferV2') + .withArgs(anyValue, recepients, [10], false, MOCK_URL); + + await expect(tx).to.emit(escrow, 'Completed'); + }); + }); + + describe('Bulk payout for recipients', async function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should pays each recipient their corresponding amount', async () => { + const account1 = await restAccounts[0].getAddress(); + const account2 = await restAccounts[1].getAddress(); + const account3 = await restAccounts[2].getAddress(); + + const initialBalanceAccount1 = await usdt + .connect(owner) + .balanceOf(account1); + const initialBalanceAccount2 = await usdt + .connect(owner) + .balanceOf(account2); + const initialBalanceAccount3 = await usdt + .connect(owner) + .balanceOf(account3); + const initialBalanceRecordingOracle = await usdt + .connect(owner) + .balanceOf(await recordingOracle.getAddress()); + const initialBalanceReputationOracle = await usdt + .connect(owner) + .balanceOf(await reputationOracle.getAddress()); + const initialBalanceExchangeOracle = await usdt + .connect(owner) + .balanceOf(await exchangeOracle.getAddress()); + + const recepients = [account1, account2, account3]; + const amounts = [10, 20, 30]; + + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + + const finalBalanceAccount1 = await usdt + .connect(owner) + .balanceOf(account1); + const finalBalanceAccount2 = await usdt + .connect(owner) + .balanceOf(account2); + const finalBalanceAccount3 = await usdt + .connect(owner) + .balanceOf(account3); + const finalBalanceRecordingOracle = await usdt + .connect(owner) + .balanceOf(await recordingOracle.getAddress()); + const finalBalanceReputationOracle = await usdt + .connect(owner) + .balanceOf(await reputationOracle.getAddress()); + const finalBalanceExchangeOracle = await usdt + .connect(owner) + .balanceOf(await exchangeOracle.getAddress()); + + expect( + (finalBalanceAccount1 - initialBalanceAccount1).toString() + ).to.equal('7'); + expect( + (finalBalanceAccount2 - initialBalanceAccount2).toString() + ).to.equal('14'); + expect( + (finalBalanceAccount3 - initialBalanceAccount3).toString() + ).to.equal('21'); + expect( + ( + finalBalanceRecordingOracle - initialBalanceRecordingOracle + ).toString() + ).to.equal('6'); + expect( + ( + finalBalanceReputationOracle - initialBalanceReputationOracle + ).toString() + ).to.equal('6'); + + expect( + (finalBalanceExchangeOracle - initialBalanceExchangeOracle).toString() + ).to.equal('6'); + + expect(await escrow.remainingFunds()).to.equal('40'); + }); + + it('Should pays each recipient their corresponding amount and return the remaining to launcher with force option', async () => { + const account1 = await restAccounts[0].getAddress(); + const account2 = await restAccounts[1].getAddress(); + const account3 = await restAccounts[2].getAddress(); + + const initialBalanceAccount1 = await usdt + .connect(owner) + .balanceOf(account1); + const initialBalanceAccount2 = await usdt + .connect(owner) + .balanceOf(account2); + const initialBalanceAccount3 = await usdt + .connect(owner) + .balanceOf(account3); + const initialBalanceLauncher = await usdt + .connect(owner) + .balanceOf(await launcher.getAddress()); + const initialBalanceRecordingOracle = await usdt + .connect(owner) + .balanceOf(await recordingOracle.getAddress()); + const initialBalanceReputationOracle = await usdt + .connect(owner) + .balanceOf(await reputationOracle.getAddress()); + const initialBalanceExchangeOracle = await usdt + .connect(owner) + .balanceOf(await exchangeOracle.getAddress()); + + const recepients = [account1, account2, account3]; + const amounts = [10, 20, 30]; + + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000', true); + + const finalBalanceAccount1 = await usdt + .connect(owner) + .balanceOf(account1); + const finalBalanceAccount2 = await usdt + .connect(owner) + .balanceOf(account2); + const finalBalanceAccount3 = await usdt + .connect(owner) + .balanceOf(account3); + const finalBalanceLauncher = await usdt + .connect(owner) + .balanceOf(await launcher.getAddress()); + const finalBalanceRecordingOracle = await usdt + .connect(owner) + .balanceOf(await recordingOracle.getAddress()); + const finalBalanceReputationOracle = await usdt + .connect(owner) + .balanceOf(await reputationOracle.getAddress()); + const finalBalanceExchangeOracle = await usdt + .connect(owner) + .balanceOf(await exchangeOracle.getAddress()); + + expect( + (finalBalanceAccount1 - initialBalanceAccount1).toString() + ).to.equal('7'); + expect( + (finalBalanceAccount2 - initialBalanceAccount2).toString() + ).to.equal('14'); + expect( + (finalBalanceAccount3 - initialBalanceAccount3).toString() + ).to.equal('21'); + expect( + (finalBalanceLauncher - initialBalanceLauncher).toString() + ).to.equal('40'); + expect( + ( + finalBalanceRecordingOracle - initialBalanceRecordingOracle + ).toString() + ).to.equal('6'); + expect( + ( + finalBalanceReputationOracle - initialBalanceReputationOracle + ).toString() + ).to.equal('6'); + + expect( + (finalBalanceExchangeOracle - initialBalanceExchangeOracle).toString() + ).to.equal('6'); + + expect(await escrow.remainingFunds()).to.equal('40'); + }); + + it('Should runs from setup to bulkPayOut to complete correctly', async () => { + const recepients = [await restAccounts[3].getAddress()]; + const amounts = [100]; + + expect(await escrow.status()).to.equal(Status.Pending); + + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + expect(await escrow.status()).to.equal(Status.Complete); + }); + + it('Should runs from setup to bulkPayOut to complete correctly with multiple addresses', async () => { + const recepients = [ + await restAccounts[3].getAddress(), + await restAccounts[4].getAddress(), + await restAccounts[5].getAddress(), + ]; + const amounts = [10, 20, 70]; + + expect(await escrow.status()).to.equal(Status.Pending); + + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + expect(await escrow.status()).to.equal(Status.Complete); + }); + + it('Should runs from setup to bulkPayOut to partial correctly', async () => { + const recepients = [await restAccounts[3].getAddress()]; + const amounts = [80]; + + expect(await escrow.status()).to.equal(Status.Pending); + + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + expect(await escrow.status()).to.equal(Status.Partial); + }); + + it('Should runs from setup to bulkPayOut to partial correctly with multiple addresses', async () => { + const recepients = [ + await restAccounts[3].getAddress(), + await restAccounts[4].getAddress(), + await restAccounts[5].getAddress(), + ]; + const amounts = [10, 20, 50]; + + expect(await escrow.status()).to.equal(Status.Pending); + + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + expect(await escrow.status()).to.equal(Status.Partial); + }); + }); + }); + + describe('withdraw', () => { + describe('can fund hmtoken to escrow, and then withdraw', () => { + before(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should fund escrow with HMTokens', async () => { + const amount = 10; + await hmtoken.connect(owner).transfer(escrow.getAddress(), amount); + + const result = await hmtoken + .connect(owner) + .balanceOf(escrow.getAddress()); + expect(result.toString()).to.equal(amount.toString()); + + expect(await escrow.remainingFunds()).to.equal('100'); + }); + + it('Should withdraw HMTokens from escrow', async () => { + await escrow.connect(owner).withdraw(hmtoken.getAddress()); + + const result = await hmtoken + .connect(owner) + .balanceOf(escrow.getAddress()); + expect(result.toString()).to.equal('0'); + + expect(await escrow.remainingFunds()).to.equal('100'); + }); + + it('Should not allow USDT withdrawal from escrow', async () => { + await expect( + escrow.connect(owner).withdraw(usdt.getAddress()) + ).to.be.revertedWith('No funds to withdraw'); + }); + + it('Should allow additional USDT withdrawal from escrow', async () => { + await usdt.connect(owner).transfer(escrow.getAddress(), 100); + + await escrow.connect(owner).withdraw(usdt.getAddress()); + + const result = await usdt.connect(owner).balanceOf(escrow.getAddress()); + expect(result.toString()).to.equal('100'); + + expect(await escrow.remainingFunds()).to.equal('100'); + }); + }); + + describe('Events', function () { + const amount = 10; + before(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + + await usdt.connect(owner).transfer(escrow.getAddress(), amount); + }); + + it('Should emit an event on withdraw', async function () { + await expect(await escrow.connect(owner).withdraw(usdt.getAddress())) + .to.emit(escrow, 'Withdraw') + .withArgs(usdt.getAddress(), amount); + }); + }); + }); +}); diff --git a/packages/core/test/Escrow.ts b/packages/core/test/Escrow.ts index 4f8de1fbb2..82c4903af1 100644 --- a/packages/core/test/Escrow.ts +++ b/packages/core/test/Escrow.ts @@ -128,65 +128,10 @@ describe('Escrow', function () { }); }); - describe('abort', () => { - describe('Validations', function () { - before(async () => { - await deployEscrow(); - await setupEscrow(); - }); - - it('Should revert when aborting with not trusted address', async function () { - await expect( - escrow.connect(externalAddress).abort() - ).to.be.revertedWith('Address calling not trusted'); - }); - - it('Should revert when aborting from reputation oracle', async function () { - await expect( - escrow.connect(reputationOracle).abort() - ).to.be.revertedWith('Address calling not trusted'); - }); - - it('Should revert when aborting from recording oracle', async function () { - await expect( - escrow.connect(recordingOracle).abort() - ).to.be.revertedWith('Address calling not trusted'); - }); - }); - - describe('Calling abort', function () { - beforeEach(async () => { - await deployEscrow(); - await setupEscrow(); - }); - - it('Should transfer tokens to owner if contract funded when abort is called', async function () { - const amount = 100; - await token.connect(owner).transfer(escrow.getAddress(), amount); - - await escrow.connect(owner).abort(); - - expect( - (await token.connect(owner).balanceOf(escrow.getAddress())).toString() - ).to.equal('0', 'Escrow has not been properly aborted'); - }); - - it('Should transfer tokens to owner if contract funded when abort is called from trusted handler', async function () { - const amount = 100; - await token.connect(owner).transfer(escrow.getAddress(), amount); - - await escrow.connect(trustedHandlers[0]).abort(); - - expect( - (await token.connect(owner).balanceOf(escrow.getAddress())).toString() - ).to.equal('0', 'Escrow has not been properly aborted'); - }); - }); - }); - describe('addTrustedHandlers', async () => { before(async () => { await deployEscrow(); + await fundEscrow(); await setupEscrow(); }); @@ -199,7 +144,7 @@ describe('Escrow', function () { ).to.be.revertedWith('Address calling not trusted'); }); - it('Should revert when aborting from reputation oracle', async function () { + it('Should revert when adding trusted handlers from reputation oracle', async function () { await expect( escrow .connect(reputationOracle) @@ -207,7 +152,7 @@ describe('Escrow', function () { ).to.be.revertedWith('Address calling not trusted'); }); - it('Should revert when aborting from recording oracle', async function () { + it('Should revert when adding trusted handlers from recording oracle', async function () { await expect( escrow .connect(recordingOracle) @@ -279,6 +224,7 @@ describe('Escrow', function () { describe('Events', function () { before(async () => { await deployEscrow(); + await fundEscrow(); await setupEscrow(); }); @@ -294,6 +240,7 @@ describe('Escrow', function () { describe('Store results', async function () { before(async () => { await deployEscrow(); + await fundEscrow(); await setupEscrow(); }); @@ -416,6 +363,7 @@ describe('Escrow', function () { describe('Events', function () { before(async () => { await deployEscrow(); + await fundEscrow(); }); it('Should emit an event on pending', async function () { @@ -433,8 +381,16 @@ describe('Escrow', function () { MOCK_HASH ) ) - .to.emit(escrow, 'Pending') - .withArgs(MOCK_URL, MOCK_HASH); + .to.emit(escrow, 'PendingV2') + .withArgs( + MOCK_URL, + MOCK_HASH, + await reputationOracle.getAddress(), + await recordingOracle.getAddress(), + await exchangeOracle.getAddress() + ) + .to.emit(escrow, 'Fund') + .withArgs(100); }); }); @@ -511,13 +467,9 @@ describe('Escrow', function () { await escrow .connect(owner) - .bulkPayOut( - [await restAccounts[0].getAddress()], - [100], - MOCK_URL, - MOCK_HASH, - '000' - ); + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ]([await restAccounts[0].getAddress()], [100], MOCK_URL, MOCK_HASH, '000'); }); it('Should revert with the right error if address calling not trusted', async function () { @@ -583,7 +535,9 @@ describe('Escrow', function () { await expect( escrow .connect(externalAddress) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000') + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') ).to.be.revertedWith('Address calling not trusted'); }); @@ -594,7 +548,9 @@ describe('Escrow', function () { await expect( escrow .connect(recordingOracle) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000') + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') ).to.be.revertedWith('Address calling not trusted'); }); @@ -609,7 +565,9 @@ describe('Escrow', function () { await expect( escrow .connect(reputationOracle) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000') + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') ).to.be.revertedWith("Amount of recipients and values don't match"); }); @@ -623,7 +581,9 @@ describe('Escrow', function () { await expect( escrow .connect(reputationOracle) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000') + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') ).to.be.revertedWith("Amount of recipients and values don't match"); }); @@ -637,32 +597,71 @@ describe('Escrow', function () { await expect( escrow .connect(reputationOracle) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000') + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000') ).to.be.revertedWith('Too many recipients'); }); }); describe('Events', function () { - before(async () => { + this.beforeEach(async () => { await deployEscrow(); await fundEscrow(); await setupEscrow(); }); - it('Should emit an event on bulk transfer', async function () { + it('Should emit bulkPayOut and Completed events for complete bulkPayOut', async function () { + const recepients = [await restAccounts[0].getAddress()]; + const amounts = [100]; + + const tx = await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + + await expect(tx) + .to.emit(escrow, 'BulkTransferV2') + .withArgs(anyValue, recepients, [100], false, MOCK_URL); + + await expect(tx).to.emit(escrow, 'Completed'); + }); + + it('Should emit only bulkPayOut event for partial bulkPayOut', async function () { const recepients = [await restAccounts[0].getAddress()]; const amounts = [10]; - await expect( - escrow - .connect(owner) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000') - ) - .to.emit(escrow, 'BulkTransfer') - .withArgs(anyValue, recepients, [7], true); + const tx = await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + + await expect(tx) + .to.emit(escrow, 'BulkTransferV2') + .withArgs(anyValue, recepients, [10], true, MOCK_URL); + + await expect(tx).not.to.emit(escrow, 'Completed'); }); - }); + it('Should emit bulkPayOut and Completed events for partial bulkPayOut with forceComplete option', async function () { + const recepients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + + const tx = await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000', true); + + await expect(tx) + .to.emit(escrow, 'BulkTransferV2') + .withArgs(anyValue, recepients, [10], false, MOCK_URL); + + await expect(tx).to.emit(escrow, 'Completed'); + }); + }); describe('Bulk payout for recipients', async function () { beforeEach(async () => { await deployEscrow(); @@ -699,7 +698,9 @@ describe('Escrow', function () { await escrow .connect(reputationOracle) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); const finalBalanceAccount1 = await token .connect(owner) @@ -743,6 +744,96 @@ describe('Escrow', function () { expect( (finalBalanceExchangeOracle - initialBalanceExchangeOracle).toString() ).to.equal('6'); + + expect(await escrow.remainingFunds()).to.equal('40'); + }); + + it('Should pays each recipient their corresponding amount and return the remaining to launcher with force option', async () => { + const account1 = await restAccounts[0].getAddress(); + const account2 = await restAccounts[1].getAddress(); + const account3 = await restAccounts[2].getAddress(); + + const initialBalanceAccount1 = await token + .connect(owner) + .balanceOf(account1); + const initialBalanceAccount2 = await token + .connect(owner) + .balanceOf(account2); + const initialBalanceAccount3 = await token + .connect(owner) + .balanceOf(account3); + const initialBalanceLauncher = await token + .connect(owner) + .balanceOf(await launcher.getAddress()); + const initialBalanceRecordingOracle = await token + .connect(owner) + .balanceOf(await recordingOracle.getAddress()); + const initialBalanceReputationOracle = await token + .connect(owner) + .balanceOf(await reputationOracle.getAddress()); + const initialBalanceExchangeOracle = await token + .connect(owner) + .balanceOf(await exchangeOracle.getAddress()); + + const recepients = [account1, account2, account3]; + const amounts = [10, 20, 30]; + + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000', true); + + const finalBalanceAccount1 = await token + .connect(owner) + .balanceOf(account1); + const finalBalanceAccount2 = await token + .connect(owner) + .balanceOf(account2); + const finalBalanceAccount3 = await token + .connect(owner) + .balanceOf(account3); + const finalBalanceLauncher = await token + .connect(owner) + .balanceOf(await launcher.getAddress()); + const finalBalanceRecordingOracle = await token + .connect(owner) + .balanceOf(await recordingOracle.getAddress()); + const finalBalanceReputationOracle = await token + .connect(owner) + .balanceOf(await reputationOracle.getAddress()); + const finalBalanceExchangeOracle = await token + .connect(owner) + .balanceOf(await exchangeOracle.getAddress()); + + expect( + (finalBalanceAccount1 - initialBalanceAccount1).toString() + ).to.equal('7'); + expect( + (finalBalanceAccount2 - initialBalanceAccount2).toString() + ).to.equal('14'); + expect( + (finalBalanceAccount3 - initialBalanceAccount3).toString() + ).to.equal('21'); + expect( + (finalBalanceLauncher - initialBalanceLauncher).toString() + ).to.equal('40'); + expect( + ( + finalBalanceRecordingOracle - initialBalanceRecordingOracle + ).toString() + ).to.equal('6'); + expect( + ( + finalBalanceReputationOracle - initialBalanceReputationOracle + ).toString() + ).to.equal('6'); + + expect( + (finalBalanceExchangeOracle - initialBalanceExchangeOracle).toString() + ).to.equal('6'); + + expect(await escrow.remainingFunds()).to.equal('40'); }); it('Should runs from setup to bulkPayOut to complete correctly', async () => { @@ -753,10 +844,9 @@ describe('Escrow', function () { await escrow .connect(reputationOracle) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000'); - expect(await escrow.status()).to.equal(Status.Paid); - - await escrow.connect(reputationOracle).complete(); + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); expect(await escrow.status()).to.equal(Status.Complete); }); @@ -772,67 +862,42 @@ describe('Escrow', function () { await escrow .connect(reputationOracle) - .bulkPayOut(recepients, amounts, MOCK_URL, MOCK_HASH, '000'); - expect(await escrow.status()).to.equal(Status.Paid); - - await escrow.connect(reputationOracle).complete(); + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); expect(await escrow.status()).to.equal(Status.Complete); }); - }); - }); - describe('complete', () => { - describe('Validations', function () { - before(async () => { - await deployEscrow(); - await fundEscrow(); - await setupEscrow(); - }); + it('Should runs from setup to bulkPayOut to partial correctly', async () => { + const recepients = [await restAccounts[3].getAddress()]; + const amounts = [80]; - it('Should revert with the right error if address calling is not trusted', async function () { - await expect( - escrow.connect(externalAddress).complete() - ).to.be.revertedWith('Address calling not trusted'); - }); + expect(await escrow.status()).to.equal(Status.Pending); - it('Should revert with the right error if address calling is recording oracle', async function () { - await expect( - escrow.connect(recordingOracle).complete() - ).to.be.revertedWith('Address calling not trusted'); + await escrow + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + expect(await escrow.status()).to.equal(Status.Partial); }); - it('Should revert with the right error if escrow not in Paid status state', async function () { - await expect(escrow.connect(owner).complete()).to.be.revertedWith( - 'Escrow not in Paid state' - ); - }); - }); + it('Should runs from setup to bulkPayOut to partial correctly with multiple addresses', async () => { + const recepients = [ + await restAccounts[3].getAddress(), + await restAccounts[4].getAddress(), + await restAccounts[5].getAddress(), + ]; + const amounts = [10, 20, 50]; - describe('Complete escrow', async function () { - beforeEach(async () => { - await deployEscrow(); - await fundEscrow(); - await setupEscrow(); + expect(await escrow.status()).to.equal(Status.Pending); await escrow - .connect(owner) - .bulkPayOut( - [await restAccounts[0].getAddress()], - [100], - MOCK_URL, - MOCK_HASH, - '000' - ); - }); - - it('Should succeed when the launcher completes', async () => { - await escrow.connect(owner).complete(); - expect(await escrow.status()).to.equal(Status.Complete); - }); - - it('Should succeed when the trusted handler completes', async () => { - await escrow.connect(trustedHandlers[0]).complete(); - expect(await escrow.status()).to.equal(Status.Complete); + .connect(reputationOracle) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ](recepients, amounts, MOCK_URL, MOCK_HASH, '000'); + expect(await escrow.status()).to.equal(Status.Partial); }); }); }); diff --git a/packages/core/test/EscrowFactory.ts b/packages/core/test/EscrowFactory.ts index cae53b2637..c70531b7f6 100644 --- a/packages/core/test/EscrowFactory.ts +++ b/packages/core/test/EscrowFactory.ts @@ -14,8 +14,9 @@ describe('EscrowFactory', function () { let token: HMToken, escrowFactory: EscrowFactory, staking: Staking; const jobRequesterId = 'job-requester-id'; - const minimumStake = 2; + const minimumStake = 5; const lockPeriod = 2; + const feePercentage = 2; const stakeAmount = 10; @@ -65,13 +66,14 @@ describe('EscrowFactory', function () { }); this.beforeEach(async () => { - // Deploy Staking Conract + // Deploy Staking Contract const Staking = await ethers.getContractFactory('Staking'); - staking = (await upgrades.deployProxy( - Staking, - [await token.getAddress(), minimumStake, lockPeriod], - { kind: 'uups', initializer: 'initialize' } - )) as unknown as Staking; + staking = await Staking.deploy( + await token.getAddress(), + minimumStake, + lockPeriod, + feePercentage + ); // Approve spend HMT tokens staking contract await token.connect(operator).approve(await staking.getAddress(), 1000); @@ -83,7 +85,7 @@ describe('EscrowFactory', function () { escrowFactory = (await upgrades.deployProxy( EscrowFactory, - [await staking.getAddress()], + [await staking.getAddress(), minimumStake], { kind: 'uups', initializer: 'initialize' } )) as unknown as EscrowFactory; }); @@ -95,7 +97,7 @@ describe('EscrowFactory', function () { }); }); - it('Operator should not be able to create an escrow without staking', async () => { + it('Operator should not be able to create an escrow without meeting minimum stake', async () => { await expect( escrowFactory .connect(operator) @@ -104,10 +106,10 @@ describe('EscrowFactory', function () { [await reputationOracle.getAddress()], jobRequesterId ) - ).to.be.revertedWith('Needs to stake HMT tokens to create an escrow.'); + ).to.be.revertedWith('Insufficient stake to create an escrow.'); }); - it('Operator should be able to create an escrow after staking', async () => { + it('Operator should be able to create an escrow after meeting minimum stake', async () => { const event = await stakeAndCreateEscrow(staking); expect(event?.token).to.equal( @@ -129,6 +131,62 @@ describe('EscrowFactory', function () { .withArgs(await token.getAddress(), anyValue, jobRequesterId); }); + it('Owner should be able to set minimumStake', async () => { + await escrowFactory.connect(owner).setMinimumStake(15); + const minimumStake = await escrowFactory.minimumStake(); + expect(minimumStake).to.equal(15, 'Minimum stake updated correctly'); + }); + + it('Owner should be able to modify staking address', async () => { + const Staking = await ethers.getContractFactory('Staking'); + const newStaking = await Staking.deploy( + await token.getAddress(), + minimumStake, + lockPeriod, + feePercentage + ); + await escrowFactory + .connect(owner) + .setStakingAddress(await newStaking.getAddress()); + const newStakingAddress = await escrowFactory.staking(); + expect(newStakingAddress).to.equal( + await newStaking.getAddress(), + 'Staking address updated correctly' + ); + expect(newStakingAddress).not.to.equal( + await staking.getAddress(), + 'Staking address is different to the previous one' + ); + }); + + it('Operator should not create escrow if new minimumStake is not met', async () => { + await escrowFactory.connect(owner).setMinimumStake(15); + await staking.connect(operator).stake(stakeAmount); + + await expect( + escrowFactory + .connect(operator) + .createEscrow( + await token.getAddress(), + [await reputationOracle.getAddress()], + jobRequesterId + ) + ).to.be.revertedWith('Insufficient stake to create an escrow.'); + }); + + it('Operator should be able to create escrow after staking more to meet new minimum', async () => { + await escrowFactory.connect(owner).setMinimumStake(15); + await staking.connect(operator).stake(20); + + const event = await createEscrow(); + + expect(event?.token).to.equal( + await token.getAddress(), + 'token address is correct' + ); + expect(event?.escrow).to.not.be.null; + }); + it('Should find the newly created escrow from deployed escrow', async () => { await stakeAndCreateEscrow(staking); const escrowAddress = await escrowFactory.lastEscrow(); @@ -139,13 +197,10 @@ describe('EscrowFactory', function () { expect(result).to.equal(true); }); - it('Operator should be able to create another escrow after allocating some of the stakes', async () => { - const result = await stakeAndCreateEscrow(staking); - const escrowAddress = result?.escrow; + it('Operator should be able to create another escrow after unstaking some of the stakes', async () => { + await stakeAndCreateEscrow(staking); - staking - .connect(operator) - .allocate(escrowAddress.toString(), stakeAmount / 2); + staking.connect(operator).unstake(2); const event = await createEscrow(); @@ -156,11 +211,10 @@ describe('EscrowFactory', function () { expect(event?.escrow).to.not.be.null; }); - it('Operator should not be able to create an escrow after allocating all of the stakes', async () => { - const result = await stakeAndCreateEscrow(staking); - const escrowAddress = result?.escrow; + it('Operator should not be able to create an escrow after unstaking all of the stakes', async () => { + await stakeAndCreateEscrow(staking); - staking.connect(operator).allocate(escrowAddress.toString(), stakeAmount); + staking.connect(operator).unstake(stakeAmount); await expect( escrowFactory @@ -170,22 +224,17 @@ describe('EscrowFactory', function () { [await reputationOracle.getAddress()], jobRequesterId ) - ).to.be.revertedWith('Needs to stake HMT tokens to create an escrow.'); + ).to.be.revertedWith('Insufficient stake to create an escrow.'); }); - it('Operator should be able to create an escrow after staking more tokens', async () => { - const result = await stakeAndCreateEscrow(staking); - const escrowAddress = result?.escrow; - - staking.connect(operator).allocate(escrowAddress.toString(), stakeAmount); - - const event = await stakeAndCreateEscrow(staking); + it('Should find the newly created escrow from deployed escrow', async () => { + await stakeAndCreateEscrow(staking); + const escrowAddress = await escrowFactory.lastEscrow(); - expect(event?.token).to.equal( - await token.getAddress(), - 'token address is correct' - ); - expect(event?.escrow).to.not.be.null; + const result = await escrowFactory + .connect(operator) + .hasEscrow(escrowAddress); + expect(result).to.equal(true); }); describe('proxy implementation', function () { diff --git a/packages/core/test/MetaHumanGovernor.ts b/packages/core/test/MetaHumanGovernor.ts index 30fa23ab47..edafb96a59 100644 --- a/packages/core/test/MetaHumanGovernor.ts +++ b/packages/core/test/MetaHumanGovernor.ts @@ -21,7 +21,7 @@ import { SECONDS_PER_BLOCK, } from './GovernanceUtils'; -describe.only('MetaHumanGovernor', function () { +describe('MetaHumanGovernor', function () { let owner: Signer; let user1: Signer; let wormholeMockForGovernor: WormholeMock; diff --git a/packages/core/test/RewardPool.ts b/packages/core/test/RewardPool.ts deleted file mode 100644 index eedcfd09c7..0000000000 --- a/packages/core/test/RewardPool.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { ethers, upgrades } from 'hardhat'; -import { EventLog, Signer } from 'ethers'; -import { - EscrowFactory, - HMToken, - RewardPool, - Staking, -} from '../typechain-types'; -import { expect } from 'chai'; - -describe('RewardPool', function () { - let token: HMToken, - escrowFactory: EscrowFactory, - staking: Staking, - rewardPool: RewardPool; - let owner: Signer, - validator: Signer, - validator2: Signer, - operator: Signer, - exchangeOracle: Signer, - reputationOracle: Signer, - recordingOracle: Signer, - externalAccount: Signer; - - const minimumStake = 2; - const lockPeriod = 2; - const rewardFee = 2; - const jobRequesterId = 'job-requester-id'; - - this.beforeAll(async () => { - [ - owner, - validator, - validator2, - operator, - exchangeOracle, - reputationOracle, - recordingOracle, - externalAccount, - ] = await ethers.getSigners(); - - // Deploy HMTToken Contract - const HMToken = await ethers.getContractFactory( - 'contracts/HMToken.sol:HMToken' - ); - token = (await HMToken.deploy( - 1000000000, - 'Human Token', - 18, - 'HMT' - )) as HMToken; - - // Deploy Staking Conract - const Staking = await ethers.getContractFactory('Staking'); - staking = (await upgrades.deployProxy( - Staking, - [await token.getAddress(), minimumStake, lockPeriod], - { kind: 'uups', initializer: 'initialize' } - )) as unknown as Staking; - - // Deploy Escrow Factory Contract - const EscrowFactory = await ethers.getContractFactory( - 'contracts/EscrowFactory.sol:EscrowFactory' - ); - - escrowFactory = (await upgrades.deployProxy( - EscrowFactory, - [await staking.getAddress()], - { kind: 'uups', initializer: 'initialize' } - )) as unknown as EscrowFactory; - }); - - this.beforeEach(async () => { - // Send HMT tokens to contract participants - [ - validator, - validator2, - operator, - exchangeOracle, - reputationOracle, - recordingOracle, - externalAccount, - ].forEach(async (account) => { - await token.connect(owner).approve(await account.getAddress(), 1000); - await token - .connect(account) - .transferFrom( - await owner.getAddress(), - await account.getAddress(), - 1000 - ); - }); - - // Deploy Reward Pool Conract - const RewardPool = await ethers.getContractFactory('RewardPool'); - rewardPool = (await upgrades.deployProxy( - RewardPool, - [await token.getAddress(), await staking.getAddress(), rewardFee], - { kind: 'uups', initializer: 'initialize' } - )) as unknown as RewardPool; - - // Configure RewardPool in Staking - await staking.setRewardPool(await rewardPool.getAddress()); - - // Approve spend HMT tokens staking contract - [ - validator, - validator2, - operator, - exchangeOracle, - reputationOracle, - recordingOracle, - externalAccount, - ].map(async (account) => { - await token.connect(account).approve(await staking.getAddress(), 1000); - }); - }); - - it('Should set token address given to constructor', async () => { - expect(await rewardPool.token()).to.equal(await token.getAddress()); - }); - - it('Should set fee given to constructor', async () => { - expect(await rewardPool.fees()).to.equal(rewardFee); - }); - - describe('Add Reward', () => { - let escrowAddress: string; - const stakedTokens = 10; - const allocatedTokens = 5; - - beforeEach(async () => { - await staking.connect(validator).stake(stakedTokens); - - await staking.connect(operator).stake(stakedTokens); - - const result = await ( - await escrowFactory - .connect(operator) - .createEscrow( - await token.getAddress(), - [await validator.getAddress()], - jobRequesterId - ) - ).wait(); - const event = ( - result?.logs?.find(({ topics }) => - topics.includes(ethers.id('LaunchedV2(address,address,string)')) - ) as EventLog - )?.args; - - expect(event?.token).to.equal( - await token.getAddress(), - 'token address is correct' - ); - expect(event?.escrow).to.not.be.null; - - escrowAddress = event?.escrow; - - await staking.connect(operator).allocate(escrowAddress, allocatedTokens); - }); - - it('Only staking can add reward', async () => { - await expect( - rewardPool - .connect(operator) - .addReward( - ethers.ZeroAddress, - ethers.ZeroAddress, - ethers.ZeroAddress, - 1 - ) - ).to.be.revertedWith('Caller is not staking contract'); - }); - - it('When slashed is lower than fee, reward record is not created', async () => { - const slashedTokens = 1; - - await staking - .connect(owner) - .slash( - await validator.getAddress(), - await operator.getAddress(), - escrowAddress, - slashedTokens - ); - - expect(await token.balanceOf(await rewardPool.getAddress())).to.equal( - slashedTokens - ); - - const rewards = await rewardPool.getRewards(escrowAddress); - expect(rewards.length).to.equal(0); - }); - - it('When slashed is higher than fee, reward record is created', async () => { - const slashedTokens = 3; - await expect( - await staking - .connect(owner) - .slash( - await validator.getAddress(), - await operator.getAddress(), - escrowAddress, - slashedTokens - ) - ) - .to.emit(rewardPool, 'RewardAdded') - .withArgs( - escrowAddress, - await operator.getAddress(), - await validator.getAddress(), - slashedTokens - rewardFee - ); - - expect(await token.balanceOf(await rewardPool.getAddress())).to.equal( - slashedTokens - ); - - const rewards = await rewardPool.getRewards(escrowAddress); - expect(rewards.length).to.equal(1); - expect(rewards[0].escrowAddress).to.equal(escrowAddress); - expect(rewards[0].slasher).to.equal(await validator.getAddress()); - expect(rewards[0].tokens).to.equal(slashedTokens - rewardFee); - }); - }); - - describe('Distribute & Withdraw Reward', () => { - let escrowAddress: string; - const stakedTokens = 10; - const allocatedTokens = 8; - - beforeEach(async () => { - await staking.connect(validator).stake(stakedTokens); - - await staking.connect(validator2).stake(stakedTokens); - - await staking.connect(operator).stake(stakedTokens); - - const result = await ( - await escrowFactory - .connect(operator) - .createEscrow( - await token.getAddress(), - [await validator.getAddress()], - jobRequesterId - ) - ).wait(); - const event = ( - result?.logs?.find(({ topics }) => - topics.includes(ethers.id('LaunchedV2(address,address,string)')) - ) as EventLog - )?.args; - - expect(event?.token).to.equal( - await token.getAddress(), - 'token address is correct' - ); - expect(event?.escrow).to.not.be.null; - - escrowAddress = event?.escrow; - - await staking.connect(operator).allocate(escrowAddress, allocatedTokens); - }); - - it('Should revert if there is no reward', async () => { - await expect( - rewardPool.distributeReward(escrowAddress) - ).to.be.revertedWith('No rewards for escrow'); - }); - - it('Should distribute the reward.', async () => { - const vSlashAmount = 2; - const v2SlashAmount = 3; - await staking - .connect(owner) - .slash( - await validator.getAddress(), - await operator.getAddress(), - escrowAddress, - vSlashAmount - ); - await staking - .connect(owner) - .slash( - await validator2.getAddress(), - await operator.getAddress(), - escrowAddress, - v2SlashAmount - ); - - const vBalanceBefore = await token.balanceOf( - await validator.getAddress() - ); - const v2BalanceBefore = await token.balanceOf( - await validator2.getAddress() - ); - - await rewardPool.distributeReward(escrowAddress); - - expect(await token.balanceOf(await validator.getAddress())).to.equal( - vBalanceBefore + BigInt(vSlashAmount - rewardFee) - ); - - expect(await token.balanceOf(await validator2.getAddress())).to.equal( - v2BalanceBefore + BigInt(v2SlashAmount - rewardFee) - ); - - expect(await token.balanceOf(await rewardPool.getAddress())).to.equal( - rewardFee * 2 - ); - }); - - it('Should withdraw the reward', async () => { - const vSlashAmount = 2; - const v2SlashAmount = 3; - await staking - .connect(owner) - .slash( - await validator.getAddress(), - await operator.getAddress(), - escrowAddress, - vSlashAmount - ); - await staking - .connect(owner) - .slash( - await validator2.getAddress(), - await operator.getAddress(), - escrowAddress, - v2SlashAmount - ); - - const oBalanceBefore = await token.balanceOf(await owner.getAddress()); - - await rewardPool.withdraw(await owner.getAddress()); - - expect(await token.balanceOf(await owner.getAddress())).to.equal( - oBalanceBefore + BigInt(rewardFee * 2) - ); - }); - }); -}); diff --git a/packages/core/test/Staking.ts b/packages/core/test/Staking.ts index 16a5a86fde..1ffc77ab27 100644 --- a/packages/core/test/Staking.ts +++ b/packages/core/test/Staking.ts @@ -2,16 +2,7 @@ import { anyValue } from '@nomicfoundation/hardhat-chai-matchers/withArgs'; import { expect } from 'chai'; import { ethers, upgrades } from 'hardhat'; import { EventLog, Signer } from 'ethers'; -import { - Escrow, - EscrowFactory, - HMToken, - Staking, - RewardPool, -} from '../typechain-types'; - -const MOCK_URL = 'http://google.com/fake'; -const MOCK_HASH = 'kGKmnj9BRf'; +import { EscrowFactory, HMToken, Staking } from '../typechain-types'; const mineNBlocks = async (n: number) => { await Promise.all( @@ -26,7 +17,7 @@ const mineNBlocks = async (n: number) => { describe('Staking', function () { const minimumStake = 2; const lockPeriod = 2; - const rewardFee = 1; + const feePercentage = 10; const jobRequesterId = 'job-requester-id'; let owner: Signer, @@ -38,10 +29,7 @@ describe('Staking', function () { reputationOracle: Signer, recordingOracle: Signer; - let token: HMToken, - escrowFactory: EscrowFactory, - staking: Staking, - rewardPool: RewardPool; + let token: HMToken, escrowFactory: EscrowFactory, staking: Staking; this.beforeAll(async () => { [ @@ -90,13 +78,14 @@ describe('Staking', function () { }); this.beforeEach(async () => { - // Deploy Staking Conract + // Deploy Staking Contract const Staking = await ethers.getContractFactory('Staking'); - staking = (await upgrades.deployProxy( - Staking, - [await token.getAddress(), minimumStake, lockPeriod], - { kind: 'uups', initializer: 'initialize' } - )) as unknown as Staking; + staking = await Staking.deploy( + await token.getAddress(), + minimumStake, + lockPeriod, + feePercentage + ); // Deploy Escrow Factory Contract const EscrowFactory = await ethers.getContractFactory( @@ -105,18 +94,10 @@ describe('Staking', function () { escrowFactory = (await upgrades.deployProxy( EscrowFactory, - [await staking.getAddress()], + [await staking.getAddress(), minimumStake], { kind: 'uups', initializer: 'initialize' } )) as unknown as EscrowFactory; - // Deploy Reward Pool Conract - const RewardPool = await ethers.getContractFactory('RewardPool'); - rewardPool = (await upgrades.deployProxy( - RewardPool, - [await token.getAddress(), await staking.getAddress(), rewardFee], - { kind: 'uups', initializer: 'initialize' } - )) as unknown as RewardPool; - // Topup staking address await token.connect(owner).transfer(await staking.getAddress(), 1000); @@ -151,6 +132,11 @@ describe('Staking', function () { const result = await staking.lockPeriod(); expect(result.toString()).to.equal(lockPeriod.toString()); }); + + it('Should set the right fee percentage', async () => { + const result = await staking.feePercentage(); + expect(result.toString()).to.equal(feePercentage.toString()); + }); }); describe('stake', function () { @@ -182,8 +168,10 @@ describe('Staking', function () { it('Should stake token and increase staker stake', async function () { await staking.connect(operator).stake(2); await expect( - await staking.connect(operator).hasStake(await operator.getAddress()) - ).to.equal(true); + await staking + .connect(operator) + .getStakedTokens(await operator.getAddress()) + ).to.above(0); }); }); }); @@ -211,12 +199,13 @@ describe('Staking', function () { ).to.be.revertedWith('Insufficient amount to unstake'); }); - it('Should revert with the right error if total stake is below the minimum threshold', async function () { - const amount = 9; + it('Should revert with the right error if there is a pending unstake', async function () { + const amount = 1; + await staking.connect(operator).unstake(amount); await expect( staking.connect(operator).unstake(amount) - ).to.be.revertedWith('Total stake is below the minimum threshold'); + ).to.be.revertedWith('Unstake in progress, complete it first'); }); }); @@ -237,120 +226,13 @@ describe('Staking', function () { await staking.connect(operator).unstake(amount); const staker = await staking .connect(operator) - .getStaker(await operator.getAddress()); + .stakes(await operator.getAddress()); await expect(staker.tokensLocked).to.equal(amount.toString()); await expect(staker.tokensLockedUntil).to.not.equal('0'); }); }); }); - describe('allocate', function () { - let escrowAddress: string; - - this.beforeEach(async () => { - const amount = 10; - - await staking.connect(operator).stake(amount); - - const result = await ( - await escrowFactory - .connect(operator) - .createEscrow( - await token.getAddress(), - [await validator.getAddress()], - jobRequesterId - ) - ).wait(); - const event = ( - result?.logs?.find(({ topics }) => - topics.includes(ethers.id('LaunchedV2(address,address,string)')) - ) as EventLog - )?.args; - - expect(event?.token).to.equal( - await token.getAddress(), - 'token address is correct' - ); - expect(event?.escrow).to.not.be.null; - - escrowAddress = event?.escrow; - }); - - describe('Validations', function () { - it('Should revert with the right error if not a valid address', async function () { - const amount = 5; - - await expect( - staking.connect(operator).allocate(ethers.ZeroAddress, amount) - ).to.be.revertedWith('Must be a valid address'); - }); - - it('Should revert with the right error if not an insufficient amount of tokens in the stake', async function () { - const amount = 20; - await expect( - staking.connect(operator).allocate(escrowAddress.toString(), amount) - ).to.be.revertedWith('Insufficient amount of tokens in the stake'); - }); - - it('Should revert with the right error if not a positive number', async function () { - const amount = 0; - - await expect( - staking.connect(operator).allocate(escrowAddress.toString(), amount) - ).to.be.revertedWith('Must be a positive number'); - }); - - it('Should revert with the right error if allocation already exists', async function () { - const amount = 3; - - await staking - .connect(operator) - .allocate(escrowAddress.toString(), amount); - - await expect( - staking.connect(operator).allocate(escrowAddress.toString(), amount) - ).to.be.revertedWith('Allocation already exists'); - }); - }); - - describe('Events', function () { - it('Should emit an event on stake allocated', async function () { - const amount = 5; - - await expect( - await staking - .connect(operator) - .allocate(escrowAddress.toString(), amount) - ) - .to.emit(staking, 'StakeAllocated') - .withArgs( - await operator.getAddress(), - amount, - escrowAddress.toString(), - anyValue - ); - }); - }); - - describe('Allocate tokens', function () { - it('Should allocate tokens to allocation', async function () { - const amount = 5; - - await staking - .connect(operator) - .allocate(escrowAddress.toString(), amount); - const allocation = await staking - .connect(operator) - .getAllocation(escrowAddress.toString()); - - await expect(allocation.escrowAddress).to.equal( - escrowAddress.toString() - ); - await expect(allocation.tokens).to.equal(amount.toString()); - }); - }); - }); - describe('withdraw', function () { this.beforeEach(async () => { const stakeTokens = 10; @@ -379,7 +261,7 @@ describe('Staking', function () { expect(event?.escrow).to.not.be.null; }); - describe('Withdrawal without allocation', function () { + describe('Withdrawal without tokens available', function () { describe('Validations', function () { it('Should revert with the right error if has no available tokens for withdrawal', async function () { await expect(staking.connect(operator).withdraw()).to.be.revertedWith( @@ -411,7 +293,7 @@ describe('Staking', function () { const staker = await staking .connect(operator) - .getStaker(await operator.getAddress()); + .stakes(await operator.getAddress()); let latestBlockNumber = await ethers.provider.getBlockNumber(); expect(latestBlockNumber).to.be.lessThan(staker.tokensLockedUntil); @@ -427,7 +309,7 @@ describe('Staking', function () { await staking.connect(operator).withdraw(); const stakerAfterWithdrawn = await staking .connect(operator) - .getStaker(await operator.getAddress()); + .stakes(await operator.getAddress()); await expect(stakerAfterWithdrawn.tokensStaked).to.equal( restTokensStaked.toString() @@ -444,9 +326,9 @@ describe('Staking', function () { it('Should revert with the right error if caller is not an owner', async function () { const minumumStake = 0; - await expect( - staking.connect(operator).setMinimumStake(minumumStake) - ).to.be.revertedWith('Ownable: caller is not the owner'); + await expect(staking.connect(operator).setMinimumStake(minumumStake)) + .to.be.revertedWithCustomError(staking, 'OwnableUnauthorizedAccount') + .withArgs(await operator.getAddress()); }); it('Should revert with the right error if not a positive number', async function () { @@ -458,16 +340,6 @@ describe('Staking', function () { }); }); - describe('Events', function () { - it('Should emit an event on stake locked', async function () { - const minumumStake = 5; - - await expect(await staking.connect(owner).setMinimumStake(minumumStake)) - .to.emit(staking, 'SetMinumumStake') - .withArgs(minumumStake); - }); - }); - describe('Set minimum stake', function () { it('Should assign a value to minimum stake variable', async function () { const minumumStake = 5; @@ -483,9 +355,9 @@ describe('Staking', function () { it('Should revert with the right error if caller is not an owner', async function () { const lockPeriod = 0; - await expect( - staking.connect(operator).setLockPeriod(lockPeriod) - ).to.be.revertedWith('Ownable: caller is not the owner'); + await expect(staking.connect(operator).setLockPeriod(lockPeriod)) + .to.be.revertedWithCustomError(staking, 'OwnableUnauthorizedAccount') + .withArgs(await operator.getAddress()); }); it('Should revert with the right error if not a positive number', async function () { @@ -497,18 +369,8 @@ describe('Staking', function () { }); }); - describe('Events', function () { - it('Should emit an event on stake locked', async function () { - const lockPeriod = 5; - - await expect(await staking.connect(owner).setLockPeriod(lockPeriod)) - .to.emit(staking, 'SetLockPeriod') - .withArgs(lockPeriod); - }); - }); - - describe('Set minimum stake', function () { - it('Should assign a value to minimum stake variable', async function () { + describe('Set lock period', function () { + it('Should assign a value to lock period variable', async function () { const lockPeriod = 5; await staking.connect(owner).setLockPeriod(lockPeriod); @@ -517,186 +379,41 @@ describe('Staking', function () { }); }); - describe('setRewardPool', function () { + describe('setFeePercentage', function () { describe('Validations', function () { it('Should revert with the right error if caller is not an owner', async function () { - await expect( - staking.connect(operator).setRewardPool(await rewardPool.getAddress()) - ).to.be.revertedWith('Ownable: caller is not the owner'); - }); - - it('Should revert with the right error if not a positive number', async function () { - await expect( - staking.connect(owner).setRewardPool(ethers.ZeroAddress) - ).to.be.revertedWith('Must be a valid address'); - }); - }); - - describe('Events', function () { - it('Should emit an event on set reward pool', async function () { - await expect( - await staking - .connect(owner) - .setRewardPool(await rewardPool.getAddress()) - ) - .to.emit(staking, 'SetRewardPool') - .withArgs(await rewardPool.getAddress()); - }); - }); - - describe('Set minimum stake', function () { - it('Should assign a value to minimum stake variable', async function () { - await staking - .connect(owner) - .setRewardPool(await rewardPool.getAddress()); - await expect(await staking.rewardPool()).to.equal( - await rewardPool.getAddress() - ); - }); - }); - }); + const feePercentage = 0; - describe('isAllocation', function () { - describe('Is escrow address has allocation', function () { - let escrowAddress: string; - - this.beforeEach(async () => { - const stakedTokens = 10; - await staking.connect(operator).stake(stakedTokens); - - const result = await ( - await escrowFactory - .connect(operator) - .createEscrow( - await token.getAddress(), - [await validator.getAddress()], - jobRequesterId - ) - ).wait(); - const event = ( - result?.logs?.find(({ topics }) => - topics.includes(ethers.id('LaunchedV2(address,address,string)')) - ) as EventLog - )?.args; - - expect(event?.token).to.equal( - await token.getAddress(), - 'token address is correct' - ); - expect(event?.escrow).to.not.be.null; - - escrowAddress = event?.escrow; + await expect(staking.connect(operator).setFeePercentage(feePercentage)) + .to.be.revertedWithCustomError(staking, 'OwnableUnauthorizedAccount') + .withArgs(await operator.getAddress()); }); - it('Should return an escrow address has not allocation', async function () { - expect( - await staking.connect(owner).isAllocation(escrowAddress) - ).to.equal(false); - }); + it('Should revert with the right error if exceed the maximum value', async function () { + const feePercentage = 120; - it('Should return an escrow address has allocation', async function () { - const allocatedTokens = 5; - await staking - .connect(operator) - .allocate(escrowAddress, allocatedTokens); - - expect( - await staking.connect(owner).isAllocation(escrowAddress) - ).to.equal(true); - }); - }); - }); - - describe('hasStake', function () { - describe('Is stakes has stake', function () { - it('Should return an escrow address has not allocation', async function () { - expect( - await staking.connect(owner).hasStake(await operator.getAddress()) - ).to.equal(false); - }); - - it('Should return an escrow address has allocation', async function () { - const stakedTokens = 10; - await staking.connect(operator).stake(stakedTokens); - - expect( - await staking.connect(owner).hasStake(await operator.getAddress()) - ).to.equal(true); + await expect( + staking.connect(owner).setFeePercentage(feePercentage) + ).to.be.revertedWith('Fee cannot exceed 100%'); }); }); - }); - - describe('getAllocation', function () { - describe('Return allocation by escrow address', function () { - let escrowAddress: string; - const allocatedTokens = 5; - - this.beforeEach(async () => { - const stakedTokens = 10; - await staking.connect(operator).stake(stakedTokens); + describe('Set fee percentage', function () { + it('Should assign a value to fee percentage variable', async function () { + const feePercentage = 5; - const result = await ( - await escrowFactory - .connect(operator) - .createEscrow( - await token.getAddress(), - [await validator.getAddress()], - jobRequesterId - ) - ).wait(); - const event = ( - result?.logs?.find(({ topics }) => - topics.includes(ethers.id('LaunchedV2(address,address,string)')) - ) as EventLog - )?.args; - - expect(event?.token).to.equal( - await token.getAddress(), - 'token address is correct' - ); - expect(event?.escrow).to.not.be.null; - - escrowAddress = event?.escrow; - - await staking - .connect(operator) - .allocate(escrowAddress, allocatedTokens); - }); - - it('Should return a null allocation by escrow address', async function () { - const allocation = await staking - .connect(operator) - .getAllocation(ethers.ZeroAddress); - - expect(allocation.escrowAddress).to.equal(ethers.ZeroAddress); - expect(allocation.staker).to.equal(ethers.ZeroAddress); - expect(allocation.tokens).to.equal(0); // Tokens allocated to a escrowAddress - expect(allocation.createdAt).to.equal(0); // Time when allocation was created - expect(allocation.closedAt).to.equal(0); // Time when allocation was closed - }); - - it('Should return an allocation by escrow address', async function () { - const allocation = await staking - .connect(operator) - .getAllocation(escrowAddress); - - expect(allocation.escrowAddress).to.equal(escrowAddress); - expect(allocation.staker).to.equal(await operator.getAddress()); - expect(allocation.tokens).to.equal(allocatedTokens); // Tokens allocated to a escrowAddress + await staking.connect(owner).setFeePercentage(feePercentage); + await expect(await staking.feePercentage()).to.equal(feePercentage); }); }); }); describe('slash', function () { let escrowAddress: string; - const stakedTokens = 10; - const allocatedTokens = 5; - const slashedTokens = 2; + const stakedTokens = 100; + const slashedTokens = 100; this.beforeEach(async () => { - await staking.connect(owner).setRewardPool(await rewardPool.getAddress()); - await staking.connect(validator).stake(stakedTokens); await staking.connect(operator).stake(stakedTokens); @@ -723,12 +440,10 @@ describe('Staking', function () { expect(event?.escrow).to.not.be.null; escrowAddress = event?.escrow; - - await staking.connect(operator).allocate(escrowAddress, allocatedTokens); }); describe('Validations', function () { - it('Should revert with the right error if caller is not the owner', async function () { + it('Should revert with the right error if caller is not an allowed slasher', async function () { await expect( staking .connect(operator) @@ -738,7 +453,7 @@ describe('Staking', function () { escrowAddress, slashedTokens ) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWith(`Caller is not a slasher`); }); it('Should revert with the right error if invalid address', async function () { @@ -751,10 +466,10 @@ describe('Staking', function () { ethers.ZeroAddress, slashedTokens ) - ).to.be.revertedWith('Must be a valid address'); + ).to.be.revertedWith('Must be a valid escrow address'); }); - it('Should revert if slash amount exceeds allocation', async function () { + it('Should revert if slash amount exceeds staking', async function () { await staking .connect(owner) .slash( @@ -771,9 +486,9 @@ describe('Staking', function () { await validator.getAddress(), await operator.getAddress(), escrowAddress, - allocatedTokens + stakedTokens ) - ).to.be.revertedWith('Slash tokens exceed allocated ones'); + ).to.be.revertedWith('Slash amount exceeds staked amount'); }); it('Should revert if slash amount is 0', async function () { @@ -792,6 +507,7 @@ describe('Staking', function () { describe('Events', function () { it('Should emit an event on stake slashed', async function () { + const feeAmount = (slashedTokens * feePercentage) / 100; await expect( await staking .connect(owner) @@ -805,46 +521,32 @@ describe('Staking', function () { .to.emit(staking, 'StakeSlashed') .withArgs( await operator.getAddress(), - slashedTokens, + slashedTokens - feeAmount, escrowAddress, await validator.getAddress() ); }); }); - describe('Return allocation by escrow address', function () { - it('Should slash tokens from stake and transfer to the reward pool', async function () { - const slashedTokens = 2; - - await staking - .connect(owner) - .slash( - await validator.getAddress(), - await operator.getAddress(), - escrowAddress, - slashedTokens - ); - - // await staking.connect(operator).withdraw(); - - const allocation = await staking - .connect(operator) - .getAllocation(escrowAddress); - await expect(allocation.tokens).to.equal( - allocatedTokens - slashedTokens - ); - - const stakerAfterSlash = await staking - .connect(operator) - .getStaker(await operator.getAddress()); - await expect(stakerAfterSlash.tokensStaked).to.equal( - stakedTokens - slashedTokens + it('Should transfer the slashed amount to the slasher', async function () { + const initialBalance = await token.connect(owner).balanceOf(validator); + const initialStake = (await staking.connect(owner).stakes(operator)) + .tokensStaked; + await staking + .connect(owner) + .slash( + await validator.getAddress(), + await operator.getAddress(), + escrowAddress, + slashedTokens ); - - await expect( - await token.balanceOf(await rewardPool.getAddress()) - ).to.equal(slashedTokens); - }); + const feeAmount = (slashedTokens * feePercentage) / 100; + const finalBalance = await token.connect(owner).balanceOf(validator); + const finalStake = (await staking.connect(owner).stakes(operator)) + .tokensStaked; + expect(finalBalance - initialBalance).to.equal(slashedTokens - feeAmount); + expect(initialStake - finalStake).to.equal(slashedTokens - feeAmount); + expect(await staking.connect(owner).feeBalance()).to.equal(feeAmount); }); }); @@ -870,7 +572,7 @@ describe('Staking', function () { }); it('Should return list of stakers', async () => { - const [stakers, stakes] = await staking.getListOfStakers(); + const [stakers, stakes] = await staking.getListOfStakers(0, 10); expect(stakers.length).to.equal(6); expect(stakes.length).to.equal(6); @@ -884,26 +586,22 @@ describe('Staking', function () { }); }); - describe('closeAllocation', function () { + describe('withdrawFees', function () { let escrowAddress: string; - let escrow: Escrow; + const stakedTokens = 100; + const slashedTokens = 100; this.beforeEach(async () => { - const amount = 10; - const allocationAmount = 5; + await staking.connect(validator).stake(stakedTokens); - await staking.connect(operator).stake(amount); + await staking.connect(operator).stake(stakedTokens); const result = await ( await escrowFactory .connect(operator) .createEscrow( await token.getAddress(), - [ - await validator.getAddress(), - await reputationOracle.getAddress(), - await recordingOracle.getAddress(), - ], + [await validator.getAddress()], jobRequesterId ) ).wait(); @@ -918,99 +616,111 @@ describe('Staking', function () { 'token address is correct' ); expect(event?.escrow).to.not.be.null; - escrowAddress = event?.escrow; + }); - // Fund escrow - await token.connect(owner).transfer(escrowAddress, 100); + describe('Valitions', function () { + it('Should revert with the right error if caller is not an owner', async function () { + await expect(staking.connect(operator).withdrawFees()) + .to.be.revertedWithCustomError(staking, 'OwnableUnauthorizedAccount') + .withArgs(await operator.getAddress()); + }); - const EscrowFactory = await ethers.getContractFactory( - 'contracts/Escrow.sol:Escrow' - ); - escrow = (await EscrowFactory.attach(escrowAddress)) as Escrow; - - // Setup escrow - await escrow - .connect(operator) - .setup( - await reputationOracle.getAddress(), - await recordingOracle.getAddress(), - await exchangeOracle.getAddress(), - 10, - 10, - 10, - MOCK_URL, - MOCK_HASH + it('Should revert with the right error if there are no fees to withdraw', async function () { + await expect(staking.connect(owner).withdrawFees()).to.be.revertedWith( + 'No fees to withdraw' ); - - await staking - .connect(operator) - .allocate(escrowAddress.toString(), allocationAmount); + }); }); - describe('Validations', function () { - it('Should revert with the right error if not a valid address', async function () { - await expect( - staking.connect(operator).closeAllocation(ethers.ZeroAddress) - ).to.be.revertedWith('Must be a valid address'); - }); + describe('Withdraw fees', function () { + let feeAmount: number; + this.beforeEach(async () => { + await staking + .connect(owner) + .slash( + await validator.getAddress(), + await operator.getAddress(), + escrowAddress, + slashedTokens + ); - it('Should revert with the right error if the caller is not the allocator', async function () { - await expect( - staking.connect(validator).closeAllocation(escrowAddress.toString()) - ).to.be.revertedWith('Only the allocator can close the allocation'); + feeAmount = (slashedTokens * feePercentage) / 100; + expect(await staking.connect(owner).feeBalance()).to.equal(feeAmount); }); - it('Should revert with the right error if escrow is not completed nor cancelled', async function () { - await expect( - staking.connect(operator).closeAllocation(escrowAddress.toString()) - ).to.be.revertedWith('Allocation has no completed state'); + it('Should withdraw the correct amount of fees', async function () { + const initialBalance = await token.connect(owner).balanceOf(owner); + const initialFees = await staking.connect(owner).feeBalance(); + expect(initialFees).to.equal(feeAmount.toString()); + + await staking.connect(owner).withdrawFees(); + + const finalBalance = await token.connect(owner).balanceOf(owner); + const finalFees = await staking.connect(owner).feeBalance(); + expect(finalFees).to.equal('0'); + expect(finalBalance - initialBalance).to.equal(feeAmount); }); }); + }); - describe('Close allocation on completed/cancelled escrows', function () { - it('Should close allocation on completed escrows', async function () { - // Bulk payout & Complete Escrow - await escrow - .connect(operator) - .bulkPayOut( - [await operator2.getAddress()], - [100], - MOCK_URL, - MOCK_HASH, - '000' - ); + describe('addSlasher', function () { + let newSlasher: string; - await escrow.connect(operator).complete(); + this.beforeEach(async () => { + newSlasher = await operator2.getAddress(); + }); - // Close allocation - await staking - .connect(operator) - .closeAllocation(escrowAddress.toString()); + describe('Validaciones', function () { + it('Should revert with the right error if caller is not the owner', async function () { + await expect(staking.connect(operator).addSlasher(newSlasher)) + .to.be.revertedWithCustomError(staking, 'OwnableUnauthorizedAccount') + .withArgs(await operator.getAddress()); + }); - const allocation = await staking - .connect(operator) - .getAllocation(escrowAddress.toString()); + it('Should revert with the right error if the address is already a slasher', async function () { + await staking.connect(owner).addSlasher(newSlasher); + await expect( + staking.connect(owner).addSlasher(newSlasher) + ).to.be.revertedWith('Address is already a slasher'); + }); + }); - expect(allocation.closedAt).not.to.be.null; - expect(allocation.tokens.toString()).to.equal('0'); + describe('Add slasher', function () { + it('Should add a new slasher', async function () { + await staking.connect(owner).addSlasher(newSlasher); + expect(await staking.slashers(newSlasher)).to.equal(true); }); + }); + }); - it('Should close allocation on cancelled escrows', async function () { - // Close escrow - await escrow.connect(operator).cancel(); + describe('removeSlasher', function () { + let newSlasher: string; - // Close allocation - await staking - .connect(operator) - .closeAllocation(escrowAddress.toString()); + this.beforeEach(async () => { + newSlasher = await operator2.getAddress(); + await staking.connect(owner).addSlasher(newSlasher); + }); - const allocation = await staking - .connect(operator) - .getAllocation(escrowAddress.toString()); + describe('Validaciones', function () { + it('Should revert with the right error if caller is not the owner', async function () { + await expect(staking.connect(operator).removeSlasher(newSlasher)) + .to.be.revertedWithCustomError(staking, 'OwnableUnauthorizedAccount') + .withArgs(await operator.getAddress()); + }); + + it('Should revert with the right error if the address is not a slasher', async function () { + const nonSlasher = await operator3.getAddress(); + await expect( + staking.connect(owner).removeSlasher(nonSlasher) + ).to.be.revertedWith('Address is not a slasher'); + }); + }); - expect(allocation.closedAt).not.to.be.null; - expect(allocation.tokens.toString()).to.equal('0'); + describe('Remove slasher', function () { + it('Should remove the slasher', async function () { + await staking.connect(owner).removeSlasher(newSlasher); + expect(await staking.slashers(newSlasher)).to.equal(false); }); }); }); diff --git a/packages/examples/cvat/recording-oracle/tests/integration/chain/test_escrow.py b/packages/examples/cvat/recording-oracle/tests/integration/chain/test_escrow.py index 2bcb156c87..9420567794 100644 --- a/packages/examples/cvat/recording-oracle/tests/integration/chain/test_escrow.py +++ b/packages/examples/cvat/recording-oracle/tests/integration/chain/test_escrow.py @@ -33,6 +33,7 @@ create_escrow, fund_escrow, get_intermediate_results_url, + setup_escrow, ) @@ -51,6 +52,7 @@ def setUp(self): self.escrow_address = create_escrow(self.w3) fund_escrow(self.w3, self.escrow_address) + setup_escrow(self.w3, self.escrow_address) def escrow(self, status: str = "Pending", balance: float = amount): mock_escrow = MagicMock() @@ -79,6 +81,7 @@ def test_validate_escrow_without_funds(self): def test_validate_escrow_invalid_status(self): escrow_address = create_escrow(self.w3) fund_escrow(self.w3, escrow_address) + setup_escrow(self.w3, escrow_address) bulk_payout( self.w3, escrow_address, @@ -132,6 +135,8 @@ def test_get_encrypted_escrow_manifest(self): def test_store_results(self): escrow_address = create_escrow(self.w3) + fund_escrow(self.w3, escrow_address) + setup_escrow(self.w3, escrow_address) with patch("src.chain.escrow.get_web3") as mock_function: mock_function.return_value = self.w3 results = store_results( @@ -143,6 +148,8 @@ def test_store_results(self): def test_store_results_invalid_url(self): escrow_address = create_escrow(self.w3) + fund_escrow(self.w3, escrow_address) + setup_escrow(self.w3, escrow_address) with patch("src.chain.escrow.get_web3") as mock_function: mock_function.return_value = self.w3 with pytest.raises(EscrowClientError, match="Invalid URL: invalid_url"): @@ -150,6 +157,8 @@ def test_store_results_invalid_url(self): def test_store_results_invalid_hash(self): escrow_address = create_escrow(self.w3) + fund_escrow(self.w3, escrow_address) + setup_escrow(self.w3, escrow_address) with patch("src.chain.escrow.get_web3") as mock_function: mock_function.return_value = self.w3 with pytest.raises(EscrowClientError, match="Invalid empty hash"): diff --git a/packages/examples/cvat/recording-oracle/tests/integration/cron/test_process_exchange_oracle_webhooks.py b/packages/examples/cvat/recording-oracle/tests/integration/cron/test_process_exchange_oracle_webhooks.py index dddf27a923..ce69214180 100644 --- a/packages/examples/cvat/recording-oracle/tests/integration/cron/test_process_exchange_oracle_webhooks.py +++ b/packages/examples/cvat/recording-oracle/tests/integration/cron/test_process_exchange_oracle_webhooks.py @@ -23,7 +23,7 @@ from src.services.webhook import OracleWebhookDirectionTags from tests.utils.constants import DEFAULT_GAS_PAYER_PRIV, SIGNATURE -from tests.utils.setup_escrow import create_escrow, fund_escrow +from tests.utils.setup_escrow import create_escrow, fund_escrow, setup_escrow class ServiceIntegrationTest(unittest.TestCase): @@ -57,6 +57,7 @@ def make_webhook(self, escrow_address, event_type=ExchangeOracleEventTypes.job_f def test_process_exchange_oracle_webhook(self): escrow_address = create_escrow(self.w3) fund_escrow(self.w3, escrow_address) + setup_escrow(self.w3, escrow_address) webhook = self.make_webhook(escrow_address) self.session.add(webhook) @@ -144,6 +145,7 @@ def test_process_job_launcher_webhooks_invalid_manifest_url(self, mock_manifest_ mock_manifest_url.return_value = "invalid_url" escrow_address = create_escrow(self.w3) fund_escrow(self.w3, escrow_address) + setup_escrow(self.w3, escrow_address) webhook = self.make_webhook(escrow_address) diff --git a/packages/examples/cvat/recording-oracle/tests/utils/setup_escrow.py b/packages/examples/cvat/recording-oracle/tests/utils/setup_escrow.py index b840fbc44b..9910375dc1 100644 --- a/packages/examples/cvat/recording-oracle/tests/utils/setup_escrow.py +++ b/packages/examples/cvat/recording-oracle/tests/utils/setup_escrow.py @@ -25,10 +25,17 @@ def create_escrow(web3: Web3): escrow_client = EscrowClient(web3) staking_client.approve_stake(amount) staking_client.stake(amount) - return escrow_client.create_and_setup_escrow( + return escrow_client.create_escrow( token_address=NETWORKS[ChainId.LOCALHOST]["hmt_address"], trusted_handlers=[web3.eth.default_account], job_requester_id=JOB_REQUESTER_ID, + ) + + +def setup_escrow(web3: Web3, escrow_address: str): + escrow_client = EscrowClient(web3) + escrow_client.setup( + escrow_address=escrow_address, escrow_config=EscrowConfig( exchange_oracle_address=EXCHANGE_ORACLE_ADDRESS, exchange_oracle_fee=EXCHANGE_ORACLE_FEE, diff --git a/packages/sdk/python/human-protocol-sdk/README.md b/packages/sdk/python/human-protocol-sdk/README.md index f5698192a4..ecd654d90d 100644 --- a/packages/sdk/python/human-protocol-sdk/README.md +++ b/packages/sdk/python/human-protocol-sdk/README.md @@ -137,16 +137,17 @@ escrow_config = EscrowConfig( ) ``` -Calling `create_and_setup_escrow`, the escrow can be created and set up as follows: +Calling `create`, the escrow can be created: ```python from human_protocol_sdk import EscrowClient escrow_client = EscrowClient(w3) -escrow_address = escrow_client.create_and_setup_escrow( +job_requester_id = 'job-requester' +escrow_address = escrow_client.create( token_address = "0x5FbDB2315678afecb367f032d93F642f64180aa3", trusted_handlers = ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"], - escrow_config = escrow_config + job_requester_id = job_requester_id ) ``` @@ -159,10 +160,21 @@ escrow_client.fund( ) ``` -While no payouts have been performed, aborting and canceling a job is still possible. +Calling `setup`, the escrow can be setup: + +```python +from human_protocol_sdk import EscrowClient + +escrow_client = EscrowClient(w3) +escrow_client.setup( + escrow_address = escrow_address, + escrow_config = escrow_config +) +``` + +While no payouts have been performed, canceling a job is still possible. ```python -escrow_client.abort(escrow_address = escrow_address) escrow_client.cancel(escrow_address = escrow_address) ``` diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst index 41f1c65865..19b2b74847 100644 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst +++ b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst @@ -13,3 +13,4 @@ Submodules :maxdepth: 4 human_protocol_sdk.kvstore.kvstore_client + human_protocol_sdk.kvstore.kvstore_utils diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py index 06e0e87c09..51cf738311 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py @@ -45,7 +45,6 @@ class OrderDirection(Enum): "hmt_address": "0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867", "factory_address": "0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a", "staking_address": "0x05398211bA2046E296fBc9a9D3EB49e3F15C3123", - "reward_pool_address": "0x4A5963Dd6792692e9147EdC7659936b96251917a", "kvstore_address": "0xB6d36B1CDaD50302BCB3DB43bAb0D349458e1b8D", "old_subgraph_url": "", "old_factory_address": "", @@ -60,7 +59,6 @@ class OrderDirection(Enum): "hmt_address": "0xd3A31D57FDD790725d0F6B78095F62E8CD4ab317", "factory_address": "0x87469B4f2Fcf37cBd34E54244c0BD4Fa0603664c", "staking_address": "0xf46B45Df3d956369726d8Bd93Ba33963Ab692920", - "reward_pool_address": "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4", "kvstore_address": "0x19Fc3e859C1813ac9427a7a78BeB9ae102CE96d3", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/goerli" @@ -74,12 +72,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/sepolia/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmadNQBBzcfJHTmzLezZGbwvLux7HmnmfByBHubS2cmLUr" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmYycE8kMaMcKmGizepi8pcFkRfyRmqBt2qwiNbkd6oCQt" ), "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", - "factory_address": "0xD6D347ba6987519B4e42EcED43dF98eFf5465a23", - "staking_address": "0x2B9C5EC6220BA8Ad08CB51A60FFdbC6a6235B203", - "reward_pool_address": "0xAFf5a986A530ff839d49325A5dF69F96627E8D29", + "factory_address": "0x5987A5558d961ee674efe4A8c8eB7B1b5495D3bf", + "staking_address": "0x2163e3A40032Af1C359ac731deaB48258b317890", "kvstore_address": "0xCc0AF0635aa19fE799B6aFDBe28fcFAeA7f00a60", "old_subgraph_url": (""), "old_factory_address": "0x98108c28B7767a52BE38B4860832dd4e11A7ecad", @@ -96,7 +93,6 @@ class OrderDirection(Enum): "hmt_address": "0x711Fd6ab6d65A98904522d4e3586F492B989c527", "factory_address": "0x92FD968AcBd521c232f5fB8c33b342923cC72714", "staking_address": "0xdFbB79dC35a3A53741be54a2C9b587d6BafAbd1C", - "reward_pool_address": "0xf376443BCc6d4d4D63eeC086bc4A9E4a83878e0e", "kvstore_address": "0x21A0C4CED7aE447fCf87D9FE3A29FA9B3AB20Ff1", "old_subgraph_url": "https://api.thegraph.com/subgraphs/name/humanprotocol/bsc", "old_factory_address": "0xc88bC422cAAb2ac8812de03176402dbcA09533f4", @@ -108,12 +104,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/bsc-testnet/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/Qmdq449rn4WKDf7NLvRZgt7CedZRrvpDzPqcvSmhvuu16D" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmZ5fFGPrDSQBfvZHAVQbkaPAgymcCmbhTVk7iuqHXY72P" ), "hmt_address": "0xE3D74BBFa45B4bCa69FF28891fBE392f4B4d4e4d", "factory_address": "0x2bfA592DBDaF434DDcbb893B1916120d181DAD18", - "staking_address": "0x5517fE916Fe9F8dB15B0DDc76ebDf0BdDCd4ed18", - "reward_pool_address": "0xB0A0500103eCEc431b73F6BAd923F0a2774E6e29", + "staking_address": "0xD6D347ba6987519B4e42EcED43dF98eFf5465a23", "kvstore_address": "0x32e27177BA6Ea91cf28dfd91a0Da9822A4b74EcF", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/bsctest" @@ -132,7 +127,6 @@ class OrderDirection(Enum): "hmt_address": "0xc748B2A084F8eFc47E086ccdDD9b7e67aEb571BF", "factory_address": "0xBDBfD2cC708199C5640C6ECdf3B0F4A4C67AdfcB", "staking_address": "0xcbAd56bE3f504E98bd70875823d3CC0242B7bB29", - "reward_pool_address": "0xa8e32d777a3839440cc7c24D591A64B9481753B3", "kvstore_address": "0xbcB28672F826a50B03EE91B28145EAbddA73B2eD", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/polygon" @@ -149,7 +143,6 @@ class OrderDirection(Enum): "hmt_address": "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4", "factory_address": "0xA8D927C4DA17A6b71675d2D49dFda4E9eBE58f2d", "staking_address": "0x7Fd3dF914E7b6Bd96B4c744Df32183b51368Bfac", - "reward_pool_address": "0xf0145eD99AC3c4f877aDa7dA4D1E059ec9116BAE", "kvstore_address": "0xD96158c7267Ea658a4688F4aEf1c85659851625d", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/mumbai" @@ -163,12 +156,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/amoy/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/Qmbwio5UnvDn5GQRJ5kLJfK27fqHK9nkEh4YXXYKWCc9rH" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmTZ33SRoH4o4HE9JMrH9kPTYS11z3T1N7evePrNZrEvBh" ), "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", "factory_address": "0xAFf5a986A530ff839d49325A5dF69F96627E8D29", - "staking_address": "0xCc0AF0635aa19fE799B6aFDBe28fcFAeA7f00a60", - "reward_pool_address": "0xd866bCEFf6D0F77E1c3EAE28230AE6C79b03fDa7", + "staking_address": "0xffE496683F842a923110415b7278ded3F265f2C5", "kvstore_address": "0x724AeFC243EdacCA27EAB86D3ec5a76Af4436Fc7", "old_subgraph_url": "", "old_factory_address": "", @@ -185,7 +177,6 @@ class OrderDirection(Enum): "hmt_address": "0x3b25BC1dC591D24d60560d0135D6750A561D4764", "factory_address": "0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a", "staking_address": "0x05398211bA2046E296fBc9a9D3EB49e3F15C3123", - "reward_pool_address": "0x4A5963Dd6792692e9147EdC7659936b96251917a", "kvstore_address": "0x2B95bEcb6EBC4589f64CB000dFCF716b4aeF8aA6", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/moonbeam" @@ -204,7 +195,6 @@ class OrderDirection(Enum): "hmt_address": "0x2dd72db2bBA65cE663e476bA8b84A1aAF802A8e3", "factory_address": "0x5e622FF522D81aa426f082bDD95210BC25fCA7Ed", "staking_address": "0xBFC7009F3371F93F3B54DdC8caCd02914a37495c", - "reward_pool_address": "0xf46B45Df3d956369726d8Bd93Ba33963Ab692920", "kvstore_address": "0xcC561f4482f4Ff051D2Dcc65c2cE1A0f291bbA46", "old_subgraph_url": "", "old_factory_address": "", @@ -221,7 +211,6 @@ class OrderDirection(Enum): "hmt_address": "0x12365293cb6477d4fc2686e46BB97E3Fb64f1550", "factory_address": "0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a", "staking_address": "0x05398211bA2046E296fBc9a9D3EB49e3F15C3123", - "reward_pool_address": "0x4A5963Dd6792692e9147EdC7659936b96251917a", "kvstore_address": "0x9Bc7bff35B2Be2413708d48c3B0aEF5c43646728", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/avalanche" @@ -240,7 +229,6 @@ class OrderDirection(Enum): "hmt_address": "0x9406d5c635AD22b0d76c75E52De57A2177919ca3", "factory_address": "0x56C2ba540726ED4f46E7a134b6b9Ee9C867FcF92", "staking_address": "0x9890473B0b93E24d6D1a8Dfb739D577C6f25FFd3", - "reward_pool_address": "0x5517fE916Fe9F8dB15B0DDc76ebDf0BdDCd4ed18", "kvstore_address": "0x3aD4B091E054f192a822D1406f4535eAd38580e4", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/fuji" @@ -259,7 +247,6 @@ class OrderDirection(Enum): "hmt_address": "0x19Ead835951493A763c96910255d5eeF147E914F", "factory_address": "0xc90B43a5d576D9d8026c48904dfbaED50C15Fa08", "staking_address": "0x34cD3Bd6B16c559f321799b516dE61E12017fFd1", - "reward_pool_address": "0xb9344bAD98E3d26a4d83900922baf395a2Ec154c", "kvstore_address": "0x86Af9f6Cd34B69Db1B202223C6d6D109f2491569", "old_subgraph_url": "", "old_factory_address": "", @@ -276,7 +263,6 @@ class OrderDirection(Enum): "hmt_address": "0x2736B33455A872dC478E1E004106D04c35472468", "factory_address": "0x86Af9f6Cd34B69Db1B202223C6d6D109f2491569", "staking_address": "0x003548Df34be8836cF0F9673403a1E40ba449a0F", - "reward_pool_address": "0xA9545C2530BD5bdb464d5E274F59ACceAa73eD86", "kvstore_address": "0x938335006ea6F9Eb0e8020969cFF94404425e298", "old_subgraph_url": "", "old_factory_address": "", @@ -293,7 +279,6 @@ class OrderDirection(Enum): "hmt_address": "0x10acbe3b9e6a2ff7f341e5cbf4b6617741ff44aa", "factory_address": "0x4949C9DFFD83F0D5Ab0AB24C57C4D403D5c20C15", "staking_address": "0x01D115E9E8bF0C58318793624CC662a030D07F1D", - "reward_pool_address": "0x7ABa5F75b2b530cB0c8927C86591c21dF44f06b6", "kvstore_address": "0x6512d894cc3d3FE93Da9d0420430136fA889FaB9", "old_subgraph_url": "", "old_factory_address": "", @@ -310,7 +295,6 @@ class OrderDirection(Enum): "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", "factory_address": "0x6Cd3ecAD36ee88E9ef3665CF381D9dAE0FE0a32e", "staking_address": "0x187edb5651464427b312De2AD40F4C679cf6e02D", - "reward_pool_address": "0x6daccd1f3a68945f8a7ac6d20260953f7a97fae4", "kvstore_address": "0xdE8BE9E3C12E9F546309A429cd88d026a25EaF8C", "old_subgraph_url": "", "old_factory_address": "", @@ -323,7 +307,6 @@ class OrderDirection(Enum): "hmt_address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", "factory_address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", "staking_address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", - "reward_pool_address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", "kvstore_address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707", "old_subgraph_url": "", "old_factory_address": "", diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py index b810be3762..dd043deaad 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py @@ -85,6 +85,20 @@ def __init__(self, tx_hash: str, amount_refunded: any): self.amountRefunded = amount_refunded +class EscrowWithdraw: + def __init__(self, tx_hash: str, token_address: str, amount_withdrawn: any): + """ + Represents the result of an escrow cancellation transaction. + + :param tx_hash: The hash of the transaction associated with the escrow withdrawal. + :param token_address: The address of the token used for the withdrawal. + :param amount_withdrawn: The amount withdrawn from the escrow. + """ + self.txHash = tx_hash + self.tokenAddress = token_address + self.amountWithdrawn = amount_withdrawn + + class EscrowClientError(Exception): """ Raises when some error happens when interacting with escrow. @@ -342,79 +356,6 @@ def get_w3_with_priv_key(priv_key: str): tx_options, ) - def create_and_setup_escrow( - self, - token_address: str, - trusted_handlers: List[str], - job_requester_id: str, - escrow_config: EscrowConfig, - ) -> str: - """ - Creates and sets up an escrow. - - :param token_address: Token to use for pay outs - :param trusted_handlers: Array of addresses that can perform actions on the contract - :param job_requester_id: The id of the job requester - :param escrow_config: Object containing all the necessary information to setup an escrow - - :return: The address of the escrow created - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - token_address = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4' - trusted_handlers = [ - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' - ] - job_requester_id = 'job-requester' - escrow_config = EscrowConfig( - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - 10, - 10, - 10, - "htttp://localhost/manifest.json", - "b5dad76bf6772c0f07fd5e048f6e75a5f86ee079", - ) - escrow_address = escrow_client.create_and_setup_escrow( - token_address, - trusted_handlers, - job_requester_id, - escrow_config - ) - """ - - escrow_address = self.create_escrow( - token_address, trusted_handlers, job_requester_id - ) - self.setup(escrow_address, escrow_config) - - return escrow_address - def fund( self, escrow_address: str, @@ -599,6 +540,7 @@ def bulk_payout( final_results_url: str, final_results_hash: str, txId: Decimal, + force_complete: Optional[bool] = False, tx_options: Optional[TxParams] = None, ) -> None: """Pays out the amounts specified to the workers and sets the URL of the final results file. @@ -609,6 +551,7 @@ def bulk_payout( :param final_results_url: Final results file url :param final_results_hash: Final results file hash :param txId: Serial number of the bulks + :param force_complete: (Optional) Indicates if remaining balance should be transferred to the escrow creator :param tx_options: (Optional) Additional transaction parameters :return: None @@ -683,15 +626,31 @@ def get_w3_with_priv_key(priv_key: str): if not final_results_hash: raise EscrowClientError("Invalid empty final results hash") - handle_transaction( - self.w3, - "Bulk Payout", - self._get_escrow_contract(escrow_address).functions.bulkPayOut( - recipients, amounts, final_results_url, final_results_hash, txId - ), - EscrowClientError, - tx_options, - ) + if force_complete: + handle_transaction( + self.w3, + "Bulk Payout", + self._get_escrow_contract(escrow_address).functions.bulkPayOut( + recipients, + amounts, + final_results_url, + final_results_hash, + txId, + force_complete, + ), + EscrowClientError, + tx_options, + ) + else: + handle_transaction( + self.w3, + "Bulk Payout", + self._get_escrow_contract(escrow_address).functions.bulkPayOut( + recipients, amounts, final_results_url, final_results_hash, txId + ), + EscrowClientError, + tx_options, + ) def cancel( self, escrow_address: str, tx_options: Optional[TxParams] = None @@ -776,11 +735,16 @@ def get_w3_with_priv_key(priv_key: str): return escrow_cancel_data - def abort(self, escrow_address: str, tx_options: Optional[TxParams] = None) -> None: - """Cancels the specified escrow, - sends the balance to the canceler and selfdestructs the escrow contract. + def add_trusted_handlers( + self, + escrow_address: str, + handlers: List[str], + tx_options: Optional[TxParams] = None, + ) -> None: + """Adds an array of addresses to the trusted handlers list. - :param escrow_address: Address of the escrow to abort + :param escrow_address: Address of the escrow + :param handlers: Array of trusted handler addresses :param tx_options: (Optional) Additional transaction parameters :return: None @@ -810,35 +774,51 @@ def get_w3_with_priv_key(priv_key: str): (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') escrow_client = EscrowClient(w3) - escrow_client.abort("0x62dD51230A30401C455c8398d06F85e4EaB6309f") + trusted_handlers = [ + '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', + '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' + ] + escrow_client.add_trusted_handlers( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + trusted_handlers + ) """ - if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") + for handler in handlers: + if not Web3.is_address(handler): + raise EscrowClientError(f"Invalid handler address: {handler}") handle_transaction( self.w3, - "Abort", - self._get_escrow_contract(escrow_address).functions.abort(), + "Add Trusted Handlers", + self._get_escrow_contract(escrow_address).functions.addTrustedHandlers( + handlers + ), EscrowClientError, tx_options, ) - def add_trusted_handlers( + def withdraw( self, escrow_address: str, - handlers: List[str], + token_address: str, tx_options: Optional[TxParams] = None, - ) -> None: - """Adds an array of addresses to the trusted handlers list. + ) -> EscrowWithdraw: + """Withdraws additional tokens in the escrow to the canceler. - :param escrow_address: Address of the escrow - :param handlers: Array of trusted handler addresses + :param escrow_address: Address of the escrow to withdraw + :param token_address: Address of the token to withdraw :param tx_options: (Optional) Additional transaction parameters - :return: None + :return: EscrowWithdraw: + An instance of the EscrowWithdraw class containing details of the withdrawal transaction, + including the transaction hash and the token address and amount withdrawn. :raise EscrowClientError: If an error occurs while checking the parameters + :raise EscrowClientError: If the transfer event associated with the withdrawal + is not found in the transaction logs + :example: .. code-block:: python @@ -863,31 +843,53 @@ def get_w3_with_priv_key(priv_key: str): (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') escrow_client = EscrowClient(w3) - trusted_handlers = [ - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' - ] - escrow_client.add_trusted_handlers( + escrow_cancel_data = escrow_client.withdraw( "0x62dD51230A30401C455c8398d06F85e4EaB6309f", - trusted_handlers + "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4" ) """ + if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") - for handler in handlers: - if not Web3.is_address(handler): - raise EscrowClientError(f"Invalid handler address: {handler}") - handle_transaction( + if not Web3.is_address(token_address): + raise EscrowClientError(f"Invalid token address: {token_address}") + + transaction_receipt = handle_transaction( self.w3, - "Add Trusted Handlers", - self._get_escrow_contract(escrow_address).functions.addTrustedHandlers( - handlers - ), + "Withdraw", + self._get_escrow_contract(escrow_address).functions.withdraw(token_address), EscrowClientError, tx_options, ) + amount_transferred = None + + erc20_interface = get_erc20_interface() + token_contract = self.w3.eth.contract(token_address, abi=erc20_interface["abi"]) + + for log in transaction_receipt["logs"]: + if log["address"] == token_address: + processed_log = token_contract.events.Transfer().process_log(log) + + if ( + processed_log["event"] == "Transfer" + and processed_log["args"]["from"] == escrow_address + ): + amount_transferred = processed_log["args"]["value"] + break + + if amount_transferred is None: + raise EscrowClientError("Transfer Event Not Found in Transaction Logs") + + escrow_withdraw_data = EscrowWithdraw( + tx_hash=transaction_receipt["transactionHash"].hex(), + token_address=token_address, + amount_withdrawn=amount_transferred, + ) + + return escrow_withdraw_data + def get_balance(self, escrow_address: str) -> Decimal: """Gets the balance for a specified escrow address. @@ -917,6 +919,16 @@ def get_balance(self, escrow_address: str) -> Decimal: if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") + try: + return ( + self._get_escrow_contract(escrow_address) + .functions.remainingFunds() + .call() + ) + except: + # Use getBalance for older contracts + pass + return self._get_escrow_contract(escrow_address).functions.getBalance().call() def get_manifest_hash(self, escrow_address: str) -> str: diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/operator.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/operator.py index 809c500bc0..7ebe9c2ea4 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/operator.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/operator.py @@ -7,12 +7,10 @@ id address amountStaked - amountAllocated amountLocked lockedUntilTimestamp amountWithdrawn amountSlashed - reputation reward amountJobsProcessed role @@ -23,6 +21,9 @@ jobTypes registrationNeeded registrationInstructions + reputationNetworks { + address + } } """ diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/statistics.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/statistics.py index 6b48cbd7f4..48a6c88a1f 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/statistics.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/statistics.py @@ -14,7 +14,6 @@ escrow_statistics_fragment = """ fragment EscrowStatisticsFields on EscrowStatistics { fundEventCount - setupEventCount storeResultsEventCount bulkPayoutEventCount pendingStatusEventCount @@ -31,7 +30,6 @@ fragment EventDayDataFields on EventDayData { timestamp dailyFundEventCount - dailySetupEventCount dailyStoreResultsEventCount dailyBulkPayoutEventCount dailyPendingStatusEventCount diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py index 57c3a79cf1..2e301f444b 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py @@ -9,6 +9,19 @@ timestamp value method + receiver + escrow + token + internalTransactions { + from + id + to + value + receiver + escrow + token + method + } } """ @@ -20,17 +33,17 @@ def get_transactions_query(filter: TransactionFilter) -> str: if from_address == to_address: address_condition = f""" {f'{{ from: $fromAddress }}' if from_address else ''} - {f'{{ to: $toAddress }}' if to_address else ''} + {f'{{ or: [{{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }}, {{ internalTransactions_: {{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }} }}] }}' if to_address else ''} """ else: address_condition = f""" {f'from: $fromAddress' if from_address else ''} - {f'to: $toAddress' if to_address else ''} + {f'or: [{{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }}, {{ internalTransactions_: {{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }} }}]' if to_address else ''} """ where_clause = f""" where: {{ - {"or: [" + address_condition + "]," if from_address == to_address else address_condition} + {"or: [" + address_condition + "]," if from_address and from_address == to_address else address_condition} {f'timestamp_gte: $startDate,' if filter.start_date else ''} {f'timestamp_lte: $endDate,' if filter.end_date else ''} {f'block_gte: $startBlock,' if filter.start_block else ''} diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py index 4a959d9423..9d227662d8 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py @@ -66,22 +66,22 @@ def __init__( id: str, address: str, amount_staked: int, - amount_allocated: int, amount_locked: int, locked_until_timestamp: int, amount_withdrawn: int, amount_slashed: int, - reputation: int, reward: int, amount_jobs_processed: int, role: Optional[str] = None, fee: Optional[int] = None, public_key: Optional[str] = None, webhook_url: Optional[str] = None, + website: Optional[str] = None, url: Optional[str] = None, job_types: Optional[List[str]] = None, registration_needed: Optional[bool] = None, registration_instructions: Optional[str] = None, + reputation_networks: Optional[List[str]] = None, ): """ Initializes an LeaderData instance. @@ -90,44 +90,44 @@ def __init__( :param id: Identifier :param address: Address :param amount_staked: Amount staked - :param amount_allocated: Amount allocated :param amount_locked: Amount locked :param locked_until_timestamp: Locked until timestamp :param amount_withdrawn: Amount withdrawn :param amount_slashed: Amount slashed - :param reputation: Reputation :param reward: Reward :param amount_jobs_processed: Amount of jobs launched :param role: Role :param fee: Fee :param public_key: Public key :param webhook_url: Webhook url + :param website: Website url :param url: Url :param job_types: Job types - :param registration_needed: True, - :param registration_instructions: Instructions url, + :param registration_needed: True + :param registration_instructions: Instructions url + :param reputation_networks: List of reputation networks """ self.chain_id = chain_id self.id = id self.address = address self.amount_staked = amount_staked - self.amount_allocated = amount_allocated self.amount_locked = amount_locked self.locked_until_timestamp = locked_until_timestamp self.amount_withdrawn = amount_withdrawn self.amount_slashed = amount_slashed - self.reputation = reputation self.reward = reward self.amount_jobs_processed = amount_jobs_processed self.role = role self.fee = fee self.public_key = public_key self.webhook_url = webhook_url + self.website = website self.url = url self.job_types = job_types self.registration_needed = registration_needed self.registration_instructions = registration_instructions + self.reputation_networks = reputation_networks class RewardData: @@ -223,31 +223,39 @@ def get_leaders(filter: LeaderFilter) -> List[LeaderData]: leaders_raw = leaders_data["data"]["leaders"] - job_types = [] - if isinstance(job_types, str): - job_types = job_types.split(",") - elif isinstance(job_types, list): - job_types = job_types + for leader in leaders_raw: + job_types = [] + reputation_networks = [] + + if isinstance(leader.get("jobTypes"), str): + job_types = leader["jobTypes"].split(",") + elif isinstance(leader.get("jobTypes"), list): + job_types = leader["jobTypes"] - leaders.extend( - [ + if leader.get("reputationNetworks") and isinstance( + leader.get("reputationNetworks"), list + ): + reputation_networks = [ + network["address"] for network in leader["reputationNetworks"] + ] + + leaders.append( LeaderData( chain_id=filter.chain_id, id=leader.get("id", ""), address=leader.get("address", ""), amount_staked=int(leader.get("amountStaked", 0)), - amount_allocated=int(leader.get("amountAllocated", 0)), amount_locked=int(leader.get("amountLocked", 0)), locked_until_timestamp=int(leader.get("lockedUntilTimestamp", 0)), amount_withdrawn=int(leader.get("amountWithdrawn", 0)), amount_slashed=int(leader.get("amountSlashed", 0)), - reputation=int(leader.get("reputation", 0)), reward=int(leader.get("reward", 0)), amount_jobs_processed=int(leader.get("amountJobsProcessed", 0)), role=leader.get("role", None), fee=int(leader.get("fee")) if leader.get("fee", None) else None, public_key=leader.get("publicKey", None), webhook_url=leader.get("webhookUrl", None), + website=leader.get("website", None), url=leader.get("url", None), job_types=( leader.get("jobTypes").split(",") @@ -262,10 +270,9 @@ def get_leaders(filter: LeaderFilter) -> List[LeaderData]: registration_instructions=leader.get( "registrationInstructions", None ), + reputation_networks=reputation_networks, ) - for leader in leaders_raw - ] - ) + ) return leaders @@ -319,23 +326,37 @@ def get_leader( leader = leader_data["data"]["leader"] + job_types = [] + reputation_networks = [] + + if isinstance(leader.get("jobTypes"), str): + job_types = leader["jobTypes"].split(",") + elif isinstance(leader.get("jobTypes"), list): + job_types = leader["jobTypes"] + + if leader.get("reputationNetworks") and isinstance( + leader.get("reputationNetworks"), list + ): + reputation_networks = [ + network["address"] for network in leader["reputationNetworks"] + ] + return LeaderData( chain_id=chain_id, id=leader.get("id", ""), address=leader.get("address", ""), amount_staked=int(leader.get("amountStaked", 0)), - amount_allocated=int(leader.get("amountAllocated", 0)), amount_locked=int(leader.get("amountLocked", 0)), locked_until_timestamp=int(leader.get("lockedUntilTimestamp", 0)), amount_withdrawn=int(leader.get("amountWithdrawn", 0)), amount_slashed=int(leader.get("amountSlashed", 0)), - reputation=int(leader.get("reputation", 0)), reward=int(leader.get("reward", 0)), amount_jobs_processed=int(leader.get("amountJobsProcessed", 0)), role=leader.get("role", None), fee=int(leader.get("fee")) if leader.get("fee", None) else None, public_key=leader.get("publicKey", None), webhook_url=leader.get("webhookUrl", None), + website=leader.get("website", None), url=leader.get("url", None), job_types=( leader.get("jobTypes").split(",") @@ -348,6 +369,7 @@ def get_leader( ), registration_needed=leader.get("registrationNeeded", None), registration_instructions=leader.get("registrationInstructions", None), + reputation_networks=reputation_networks, ) @staticmethod diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/__init__.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/__init__.py index 93f6278118..32cfe61efb 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/__init__.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/__init__.py @@ -3,4 +3,4 @@ obtain staking information from both the contracts and subgraph. """ -from .staking_client import AllocationData, StakingClient, StakingClientError +from .staking_client import StakingClient, StakingClientError diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py index be399fbb38..f6619cc6e9 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py @@ -66,7 +66,6 @@ def get_w3_with_priv_key(priv_key: str): get_erc20_interface, get_factory_interface, get_staking_interface, - get_reward_pool_interface, handle_transaction, ) @@ -81,35 +80,9 @@ class StakingClientError(Exception): pass -class AllocationData: - def __init__( - self, - escrow_address: str, - staker: str, - tokens: str, - created_at: str, - closed_at: str, - ): - """ - Initializes an AllocationData instance. - - :param escrow_address: Escrow address - :param staker: Staker address - :param tokens: Amount allocated - :param created_at: Creation date - :param closed_at: Closing date - """ - - self.escrow_address = escrow_address - self.staker = staker - self.tokens = tokens - self.created_at = created_at - self.closed_at = closed_at - - class StakingClient: """ - A class used to manage staking, and allocation on the HUMAN network. + A class used to manage staking on the HUMAN network. """ def __init__(self, w3: Web3): @@ -154,12 +127,6 @@ def __init__(self, w3: Web3): address=self.network["staking_address"], abi=staking_interface["abi"] ) - reward_pool_interface = get_reward_pool_interface() - self.reward_pool_contract = self.w3.eth.contract( - address=self.network["reward_pool_address"], - abi=reward_pool_interface["abi"], - ) - def approve_stake( self, amount: Decimal, tx_options: Optional[TxParams] = None ) -> None: @@ -267,117 +234,6 @@ def get_w3_with_priv_key(priv_key: str): tx_options, ) - def allocate( - self, - escrow_address: str, - amount: Decimal, - tx_options: Optional[TxParams] = None, - ) -> None: - """Allocates HMT token to the escrow. - - :param escrow_address: Address of the escrow - :param amount: Amount to allocate - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :validate: - - Amount must be greater than 0 - - Escrow address must be valid - - Amount must be less than or equal to the staked amount (on-chain) - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - staking_client.allocate('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount) - """ - - if amount <= 0: - raise StakingClientError("Amount to allocate must be greater than 0") - - if not self._is_valid_escrow(escrow_address): - raise StakingClientError(f"Invalid escrow address: {escrow_address}") - - handle_transaction( - self.w3, - "Allocate HMT", - self.staking_contract.functions.allocate(escrow_address, amount), - StakingClientError, - tx_options, - ) - - def close_allocation( - self, escrow_address: str, tx_options: Optional[TxParams] = None - ) -> None: - """Closes allocated HMT token from the escrow. - - :param escrow_address: Address of the escrow - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :validate: - - Escrow address must be valid - - Escrow should be cancelled / completed (on-chain) - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - staking_client.close_allocation('0x62dD51230A30401C455c8398d06F85e4EaB6309f') - """ - - if not self._is_valid_escrow(escrow_address): - raise StakingClientError(f"Invalid escrow address: {escrow_address}") - - handle_transaction( - self.w3, - "Close allocation", - self.staking_contract.functions.closeAllocation(escrow_address), - StakingClientError, - tx_options, - ) - def unstake(self, amount: Decimal, tx_options: Optional[TxParams] = None) -> None: """Unstakes HMT token. @@ -543,99 +399,6 @@ def get_w3_with_priv_key(priv_key: str): tx_options, ) - def distribute_reward( - self, escrow_address: str, tx_options: Optional[TxParams] = None - ) -> None: - """Pays out rewards to the slashers for the specified escrow address. - - :param escrow_address: Address of the escrow - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :validate: - - Escrow address must be valid - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import construct_sign_and_send_raw_middleware - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.add( - construct_sign_and_send_raw_middleware(gas_payer), - "construct_sign_and_send_raw_middleware", - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - staking_client.distribute_reward('0x62dD51230A30401C455c8398d06F85e4EaB6309f') - """ - - if not self._is_valid_escrow(escrow_address): - raise StakingClientError(f"Invalid escrow address: {escrow_address}") - - handle_transaction( - self.w3, - "Distribute reward", - self.reward_pool_contract.functions.distributeReward(escrow_address), - StakingClientError, - tx_options, - ) - - def get_allocation(self, escrow_address: str) -> Optional[AllocationData]: - """Gets the allocation info for the specified escrow. - - :param escrow_address: Address of the escrow - - :return: Allocation info if escrow exists, otherwise None - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - staking_client = StakingClient(w3) - - allocation = staking_client.get_allocation( - '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - ) - """ - - [ - escrow_address, - staker, - tokens, - created_at, - closed_at, - ] = self.staking_contract.functions.getAllocation(escrow_address).call() - - if escrow_address == web3.constants.ADDRESS_ZERO: - return None - - return AllocationData( - escrow_address=escrow_address, - staker=staker, - tokens=tokens, - created_at=created_at, - closed_at=closed_at, - ) - def _is_valid_escrow(self, escrow_address: str) -> bool: """Checks if the escrow address is valid. diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py index 223f7e5210..4be621822d 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py @@ -33,6 +33,26 @@ from human_protocol_sdk.utils import get_data_from_subgraph +class InternalTransaction: + def __init__( + self, + from_address: str, + to_address: str, + value: str, + method: str, + receiver: str, + escrow: str, + token: str, + ): + self.from_address = from_address + self.to_address = to_address + self.value = value + self.method = method + self.receiver = receiver + self.escrow = escrow + self.token = token + + class TransactionData: def __init__( self, @@ -44,6 +64,10 @@ def __init__( timestamp: int, value: str, method: str, + receiver: str, + escrow: str, + token: str, + internal_transactions: list[InternalTransaction], ): self.chain_id = chain_id self.block = block @@ -53,6 +77,10 @@ def __init__( self.timestamp = timestamp self.value = value self.method = method + self.receiver = receiver + self.escrow = escrow + self.token = token + self.internal_transactions = internal_transactions class TransactionUtilsError(Exception): @@ -120,6 +148,10 @@ def get_transaction(chain_id: ChainId, hash: str) -> Optional[TransactionData]: timestamp=transaction.get("timestamp", 0), value=transaction.get("value", ""), method=transaction.get("method", ""), + receiver=transaction.get("receiver", ""), + escrow=transaction.get("escrow", ""), + token=transaction.get("token", ""), + internal_transactions=transaction.get("internalTransactions", []), ) @staticmethod @@ -197,6 +229,10 @@ def get_transactions(filter: TransactionFilter) -> List[TransactionData]: timestamp=transaction.get("timestamp", 0), value=transaction.get("value", ""), method=transaction.get("method", ""), + receiver=transaction.get("receiver", ""), + escrow=transaction.get("escrow", ""), + token=transaction.get("token", ""), + internal_transactions=transaction.get("internalTransactions", []), ) for transaction in transactions_raw ] diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py index 5ff42741e5..4a00fc4184 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py @@ -155,18 +155,6 @@ def get_staking_interface(): ) -def get_reward_pool_interface(): - """Retrieve the RewardPool interface. - - :return: The RewardPool interface of smart contract. - - """ - - return get_contract_interface( - "{}/contracts/RewardPool.sol/RewardPool.json".format(ARTIFACTS_FOLDER) - ) - - def get_escrow_interface(): """Retrieve the RewardPool interface. diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_client.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_client.py index 12e4f9fdde..458b56e891 100644 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_client.py +++ b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_client.py @@ -622,138 +622,6 @@ def test_setup_with_tx_options(self): tx_options, ) - def test_create_and_setup_escrow(self): - mock_function_create = MagicMock() - self.escrow.factory_contract.functions.createEscrow = mock_function_create - mock_contract = MagicMock() - mock_contract.functions.setup = MagicMock() - self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) - escrow_address = "0x1234567890123456789012345678901234567890" - token_address = "0x1234567890123456789012345678901234567890" - trusted_handlers = [self.w3.eth.default_account] - job_requester_id = "job-requester" - escrow_config = EscrowConfig( - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - 10, - 10, - 10, - "https://www.example.com/result", - "test", - ) - with patch( - "human_protocol_sdk.escrow.escrow_client.handle_transaction" - ) as mock_function: - with patch( - "human_protocol_sdk.escrow.escrow_client.next" - ) as mock_function_next: - mock_function_next.return_value = SimpleNamespace( - args=SimpleNamespace(escrow=escrow_address) - ) - response = self.escrow.create_and_setup_escrow( - token_address, trusted_handlers, job_requester_id, escrow_config - ) - - self.assertEqual(response, escrow_address) - mock_function_create.assert_called_once_with( - token_address, trusted_handlers, job_requester_id - ) - mock_function_next.assert_called_once() - - mock_function.assert_any_call( - self.w3, - "Create Escrow", - mock_function_create.return_value, - EscrowClientError, - None, - ) - mock_function.assert_called_with( - self.w3, - "Setup", - mock_contract.functions.setup.return_value, - EscrowClientError, - None, - ) - - def test_create_and_setup_escrow_invalid_token(self): - self.escrow.setup = MagicMock() - token_address = "invalid_address" - trusted_handlers = [self.w3.eth.default_account] - job_requester_id = "job-requester" - escrow_config = EscrowConfig( - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - 10, - 10, - 10, - "https://www.example.com/result", - "test", - ) - - with self.assertRaises(EscrowClientError) as cm: - self.escrow.create_and_setup_escrow( - token_address, trusted_handlers, job_requester_id, escrow_config - ) - self.assertEqual(f"Invalid token address: {token_address}", str(cm.exception)) - self.escrow.setup.assert_not_called() - - def test_create_and_setup_escrow_invalid_handler(self): - self.escrow.setup = MagicMock() - token_address = "0x1234567890123456789012345678901234567890" - trusted_handlers = ["invalid_address"] - job_requester_id = "job-requester" - escrow_config = EscrowConfig( - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - 10, - 10, - 10, - "https://www.example.com/result", - "test", - ) - - with self.assertRaises(EscrowClientError) as cm: - self.escrow.create_and_setup_escrow( - token_address, trusted_handlers, job_requester_id, escrow_config - ) - self.assertEqual( - f"Invalid handler address: {trusted_handlers[0]}", str(cm.exception) - ) - self.escrow.setup.assert_not_called() - - def test_create_and_setup_escrow_without_account(self): - mock_provider = MagicMock(spec=HTTPProvider) - w3 = Web3(mock_provider) - mock_chain_id = ChainId.LOCALHOST.value - type(w3.eth).chain_id = PropertyMock(return_value=mock_chain_id) - - escrowClient = EscrowClient(w3) - - escrowClient.setup = MagicMock() - token_address = "0x1234567890123456789012345678901234567890" - trusted_handlers = ["0x1234567890123456789012345678901234567890"] - job_requester_id = "job-requester" - escrow_config = EscrowConfig( - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - "0x1234567890123456789012345678901234567890", - 10, - 10, - 10, - "https://www.example.com/result", - "test", - ) - - with self.assertRaises(EscrowClientError) as cm: - escrowClient.create_and_setup_escrow( - token_address, trusted_handlers, job_requester_id, escrow_config - ) - self.assertEqual("You must add an account to Web3 instance", str(cm.exception)) - escrowClient.setup.assert_not_called() - def test_fund(self): escrow_address = token_address = "0x1234567890123456789012345678901234567890" amount = 100 @@ -998,6 +866,43 @@ def test_bulk_payout(self): None, ) + def test_bulk_payout_with_force_complete(self): + mock_contract = MagicMock() + mock_contract.functions.bulkPayOut = MagicMock() + self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) + self.escrow.get_balance = MagicMock(return_value=100) + escrow_address = "0x1234567890123456789012345678901234567890" + recipients = ["0x1234567890123456789012345678901234567890"] + amounts = [100] + final_results_url = "https://www.example.com/result" + final_results_hash = "test" + txId = 1 + + with patch( + "human_protocol_sdk.escrow.escrow_client.handle_transaction" + ) as mock_function: + self.escrow.bulk_payout( + escrow_address, + recipients, + amounts, + final_results_url, + final_results_hash, + txId, + True, + ) + + self.escrow._get_escrow_contract.assert_called_once_with(escrow_address) + mock_contract.functions.bulkPayOut.assert_called_once_with( + recipients, amounts, final_results_url, final_results_hash, txId, True + ) + mock_function.assert_called_once_with( + self.w3, + "Bulk Payout", + mock_contract.functions.bulkPayOut.return_value, + EscrowClientError, + None, + ) + def test_bulk_payout_invalid_address(self): escrow_address = "0x1234567890123456789012345678901234567890" recipients = ["0x1234567890123456789012345678901234567890"] @@ -1355,6 +1260,7 @@ def test_bulk_payout_with_tx_options(self): final_results_url, final_results_hash, txId, + False, tx_options, ) @@ -1660,35 +1566,50 @@ def test_cancel_with_tx_options(self): self.assertEqual(escrow_cancel_data.txHash, tx_hash.hex()) self.assertEqual(escrow_cancel_data.amountRefunded, amount_refunded) - def test_abort(self): + def test_add_trusted_handlers(self): mock_contract = MagicMock() - mock_contract.functions.abort = MagicMock() + mock_contract.functions.addTrustedHandlers = MagicMock() self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) escrow_address = "0x1234567890123456789012345678901234567890" + handlers = [ + "0x1234567890123456789012345678901234567891", + "0x1234567890123456789012345678901234567892", + ] with patch( "human_protocol_sdk.escrow.escrow_client.handle_transaction" ) as mock_function: - self.escrow.abort(escrow_address) + self.escrow.add_trusted_handlers(escrow_address, handlers) self.escrow._get_escrow_contract.assert_called_once_with(escrow_address) - mock_contract.functions.abort.assert_called_once_with() + mock_contract.functions.addTrustedHandlers.assert_called_once_with(handlers) mock_function.assert_called_once_with( self.w3, - "Abort", - mock_contract.functions.abort.return_value, + "Add Trusted Handlers", + mock_contract.functions.addTrustedHandlers.return_value, EscrowClientError, None, ) - def test_abort_invalid_address(self): - escrow_address = "invalid_address" + def test_add_trusted_handlers_invalid_address(self): + escrow_address = "0x1234567890123456789012345678901234567890" + handlers = [ + "0x1234567890123456789012345678901234567891", + "0x1234567890123456789012345678901234567892", + ] with self.assertRaises(EscrowClientError) as cm: - self.escrow.abort(escrow_address) - self.assertEqual(f"Invalid escrow address: {escrow_address}", str(cm.exception)) + self.escrow.add_trusted_handlers("invalid_address", handlers) + self.assertEqual(f"Invalid escrow address: invalid_address", str(cm.exception)) - def test_abort_without_account(self): + with self.assertRaises(EscrowClientError) as cm: + self.escrow.add_trusted_handlers( + escrow_address, + ["invalid_address", "0x1234567890123456789012345678901234567892"], + ) + self.assertEqual(f"Invalid handler address: invalid_address", str(cm.exception)) + + def test_add_trusted_handlers_without_account(self): mock_provider = MagicMock(spec=HTTPProvider) w3 = Web3(mock_provider) mock_chain_id = ChainId.LOCALHOST.value @@ -1697,117 +1618,152 @@ def test_abort_without_account(self): escrowClient = EscrowClient(w3) escrow_address = "0x1234567890123456789012345678901234567890" + handlers = [ + "0x1234567890123456789012345678901234567891", + "0x1234567890123456789012345678901234567892", + ] with self.assertRaises(EscrowClientError) as cm: - escrowClient.abort(escrow_address) + escrowClient.add_trusted_handlers(escrow_address, handlers) self.assertEqual("You must add an account to Web3 instance", str(cm.exception)) - def test_abort_invalid_status(self): - mock_contract = MagicMock() - mock_contract.functions.abort = MagicMock() - mock_contract.functions.abort.return_value.transact.side_effect = Exception( - "Error: VM Exception while processing transaction: reverted with reason string 'Escrow in Paid status state'." - ) - self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) - escrow_address = "0x1234567890123456789012345678901234567890" - - with self.assertRaises(EscrowClientError) as cm: - self.escrow.abort(escrow_address) - self.assertEqual( - "Abort transaction failed: Escrow in Paid status state", str(cm.exception) - ) - - def test_abort_invalid_caller(self): + def test_add_trusted_handlers_invalid_caller(self): mock_contract = MagicMock() - mock_contract.functions.abort = MagicMock() - mock_contract.functions.abort.return_value.transact.side_effect = Exception( + mock_contract.functions.addTrustedHandlers = MagicMock() + mock_contract.functions.addTrustedHandlers.return_value.transact.side_effect = Exception( "Error: VM Exception while processing transaction: reverted with reason string 'Address calling not trusted'." ) self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) escrow_address = "0x1234567890123456789012345678901234567890" + handlers = [ + "0x1234567890123456789012345678901234567891", + "0x1234567890123456789012345678901234567892", + ] with self.assertRaises(EscrowClientError) as cm: - self.escrow.abort(escrow_address) + self.escrow.add_trusted_handlers(escrow_address, handlers) self.assertEqual( - "Abort transaction failed: Address calling not trusted", str(cm.exception) + "Add Trusted Handlers transaction failed: Address calling not trusted", + str(cm.exception), ) - def test_abort_invalid_escrow(self): + def test_add_trusted_handlers_invalid_escrow(self): self.escrow.factory_contract.functions.hasEscrow = MagicMock(return_value=False) escrow_address = "0x1234567890123456789012345678901234567890" + handlers = [ + "0x1234567890123456789012345678901234567891", + "0x1234567890123456789012345678901234567892", + ] with self.assertRaises(EscrowClientError) as cm: - self.escrow.abort(escrow_address) + self.escrow.add_trusted_handlers(escrow_address, handlers) self.assertEqual( "Escrow address is not provided by the factory", str(cm.exception) ) - def test_abort_with_tx_options(self): + def test_add_trusted_handlers_with_tx_options(self): mock_contract = MagicMock() - mock_contract.functions.abort = MagicMock() + mock_contract.functions.addTrustedHandlers = MagicMock() self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) escrow_address = "0x1234567890123456789012345678901234567890" + handlers = [ + "0x1234567890123456789012345678901234567891", + "0x1234567890123456789012345678901234567892", + ] tx_options = {"gas": 50000} with patch( "human_protocol_sdk.escrow.escrow_client.handle_transaction" ) as mock_function: - self.escrow.abort(escrow_address, tx_options) + self.escrow.add_trusted_handlers(escrow_address, handlers, tx_options) self.escrow._get_escrow_contract.assert_called_once_with(escrow_address) - mock_contract.functions.abort.assert_called_once_with() + mock_contract.functions.addTrustedHandlers.assert_called_once_with(handlers) mock_function.assert_called_once_with( self.w3, - "Abort", - mock_contract.functions.abort.return_value, + "Add Trusted Handlers", + mock_contract.functions.addTrustedHandlers.return_value, EscrowClientError, tx_options, ) - def test_add_trusted_handlers(self): + def test_withdraw(self): mock_contract = MagicMock() - mock_contract.functions.addTrustedHandlers = MagicMock() + mock_contract.functions.withdraw = MagicMock() self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) - escrow_address = "0x1234567890123456789012345678901234567890" - handlers = [ - "0x1234567890123456789012345678901234567891", - "0x1234567890123456789012345678901234567892", - ] + escrow_address = "0xa76507AbFE3B67cB25F16DbC75a883D4190B7e46" + token_address = "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4" with patch( "human_protocol_sdk.escrow.escrow_client.handle_transaction" ) as mock_function: - self.escrow.add_trusted_handlers(escrow_address, handlers) + tx_hash = bytes.fromhex( + "01682095d5abb0270d11a31139b9a1f410b363c84add467004e728ec831bd529" + ) + amount_withdrawn = 187744067287473730 + mock_function.return_value = { + "transactionHash": tx_hash, + "logs": [ + { + "logIndex": 0, + "transactionIndex": 0, + "transactionHash": tx_hash, + "blockHash": bytes.fromhex( + "92abf9325a3959a911a2581e9ea36cba3060d8b293b50e5738ff959feb95258a" + ), + "blockNumber": 5, + "address": token_address, + "data": bytes.fromhex( + "000000000000000000000000000000000000000000000000029b003c075b5e42" + ), + "topics": [ + bytes.fromhex( + "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + ), + bytes.fromhex( + "000000000000000000000000a76507abfe3b67cb25f16dbc75a883d4190b7e46" + ), + bytes.fromhex( + "0000000000000000000000005607acf0828e238099aa1784541a5abd7f975c76" + ), + ], + } + ], + } + + escrow_withdraw_data = self.escrow.withdraw(escrow_address, token_address) self.escrow._get_escrow_contract.assert_called_once_with(escrow_address) - mock_contract.functions.addTrustedHandlers.assert_called_once_with(handlers) + mock_contract.functions.withdraw.assert_called_once_with(token_address) mock_function.assert_called_once_with( self.w3, - "Add Trusted Handlers", - mock_contract.functions.addTrustedHandlers.return_value, + "Withdraw", + mock_contract.functions.withdraw.return_value, EscrowClientError, None, ) - def test_add_trusted_handlers_invalid_address(self): - escrow_address = "0x1234567890123456789012345678901234567890" - handlers = [ - "0x1234567890123456789012345678901234567891", - "0x1234567890123456789012345678901234567892", - ] + self.assertEqual(escrow_withdraw_data.txHash, tx_hash.hex()) + self.assertEqual(escrow_withdraw_data.tokenAddress, token_address) + self.assertEqual(escrow_withdraw_data.amountWithdrawn, amount_withdrawn) + + def test_withdraw_invalid_escrow_address(self): + escrow_address = "invalid_address" + token_address = "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4" with self.assertRaises(EscrowClientError) as cm: - self.escrow.add_trusted_handlers("invalid_address", handlers) - self.assertEqual(f"Invalid escrow address: invalid_address", str(cm.exception)) + self.escrow.withdraw(escrow_address, token_address) + self.assertEqual(f"Invalid escrow address: {escrow_address}", str(cm.exception)) + + def test_withdraw_invalid_token_address(self): + escrow_address = "0xa76507AbFE3B67cB25F16DbC75a883D4190B7e46" + token_address = "invalid_address" with self.assertRaises(EscrowClientError) as cm: - self.escrow.add_trusted_handlers( - escrow_address, - ["invalid_address", "0x1234567890123456789012345678901234567892"], - ) - self.assertEqual(f"Invalid handler address: invalid_address", str(cm.exception)) + self.escrow.withdraw(escrow_address, token_address) + self.assertEqual(f"Invalid token address: {token_address}", str(cm.exception)) - def test_add_trusted_handlers_without_account(self): + def test_withdraw_without_account(self): mock_provider = MagicMock(spec=HTTPProvider) w3 = Web3(mock_provider) mock_chain_id = ChainId.LOCALHOST.value @@ -1816,85 +1772,134 @@ def test_add_trusted_handlers_without_account(self): escrowClient = EscrowClient(w3) escrow_address = "0x1234567890123456789012345678901234567890" - handlers = [ - "0x1234567890123456789012345678901234567891", - "0x1234567890123456789012345678901234567892", - ] + token_address = "0x1234567890123456789012345678901234567890" with self.assertRaises(EscrowClientError) as cm: - escrowClient.add_trusted_handlers(escrow_address, handlers) + escrowClient.withdraw(escrow_address, token_address) self.assertEqual("You must add an account to Web3 instance", str(cm.exception)) - def test_add_trusted_handlers_invalid_caller(self): + def test_withdraw_invalid_status(self): mock_contract = MagicMock() - mock_contract.functions.addTrustedHandlers = MagicMock() - mock_contract.functions.addTrustedHandlers.return_value.transact.side_effect = Exception( + mock_contract.functions.withdraw = MagicMock() + mock_contract.functions.withdraw.return_value.transact.side_effect = Exception( + "Error: VM Exception while processing transaction: reverted with reason string 'Escrow in Paid status state'." + ) + self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) + escrow_address = "0x1234567890123456789012345678901234567890" + token_address = "0x1234567890123456789012345678901234567890" + + with self.assertRaises(EscrowClientError) as cm: + self.escrow.withdraw(escrow_address, token_address) + self.assertEqual( + "Withdraw transaction failed: Escrow in Paid status state", + str(cm.exception), + ) + + def test_withdraw_invalid_caller(self): + mock_contract = MagicMock() + mock_contract.functions.withdraw = MagicMock() + mock_contract.functions.withdraw.return_value.transact.side_effect = Exception( "Error: VM Exception while processing transaction: reverted with reason string 'Address calling not trusted'." ) self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) escrow_address = "0x1234567890123456789012345678901234567890" - handlers = [ - "0x1234567890123456789012345678901234567891", - "0x1234567890123456789012345678901234567892", - ] + token_address = "0x1234567890123456789012345678901234567890" with self.assertRaises(EscrowClientError) as cm: - self.escrow.add_trusted_handlers(escrow_address, handlers) + self.escrow.withdraw(escrow_address, token_address) self.assertEqual( - "Add Trusted Handlers transaction failed: Address calling not trusted", + "Withdraw transaction failed: Address calling not trusted", str(cm.exception), ) - def test_add_trusted_handlers_invalid_escrow(self): + def test_withdraw_invalid_escrow(self): self.escrow.factory_contract.functions.hasEscrow = MagicMock(return_value=False) escrow_address = "0x1234567890123456789012345678901234567890" - handlers = [ - "0x1234567890123456789012345678901234567891", - "0x1234567890123456789012345678901234567892", - ] + token_address = "0x1234567890123456789012345678901234567890" with self.assertRaises(EscrowClientError) as cm: - self.escrow.add_trusted_handlers(escrow_address, handlers) + self.escrow.withdraw(escrow_address, token_address) self.assertEqual( "Escrow address is not provided by the factory", str(cm.exception) ) - def test_add_trusted_handlers_with_tx_options(self): + def test_withdraw_with_tx_options(self): mock_contract = MagicMock() - mock_contract.functions.addTrustedHandlers = MagicMock() + mock_contract.functions.withdraw = MagicMock() self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) - escrow_address = "0x1234567890123456789012345678901234567890" - handlers = [ - "0x1234567890123456789012345678901234567891", - "0x1234567890123456789012345678901234567892", - ] tx_options = {"gas": 50000} + escrow_address = "0xa76507AbFE3B67cB25F16DbC75a883D4190B7e46" + token_address = "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4" + with patch( "human_protocol_sdk.escrow.escrow_client.handle_transaction" ) as mock_function: - self.escrow.add_trusted_handlers(escrow_address, handlers, tx_options) + tx_hash = bytes.fromhex( + "01682095d5abb0270d11a31139b9a1f410b363c84add467004e728ec831bd529" + ) + amount_withdrawn = 187744067287473730 + mock_function.return_value = { + "transactionHash": tx_hash, + "logs": [ + { + "logIndex": 0, + "transactionIndex": 0, + "transactionHash": tx_hash, + "blockHash": bytes.fromhex( + "92abf9325a3959a911a2581e9ea36cba3060d8b293b50e5738ff959feb95258a" + ), + "blockNumber": 5, + "address": token_address, + "data": bytes.fromhex( + "000000000000000000000000000000000000000000000000029b003c075b5e42" + ), + "topics": [ + bytes.fromhex( + "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + ), + bytes.fromhex( + "000000000000000000000000a76507abfe3b67cb25f16dbc75a883d4190b7e46" + ), + bytes.fromhex( + "0000000000000000000000005607acf0828e238099aa1784541a5abd7f975c76" + ), + ], + } + ], + } + + escrow_withdraw_data = self.escrow.withdraw( + escrow_address, token_address, tx_options + ) self.escrow._get_escrow_contract.assert_called_once_with(escrow_address) - mock_contract.functions.addTrustedHandlers.assert_called_once_with(handlers) + mock_contract.functions.withdraw.assert_called_once_with(token_address) mock_function.assert_called_once_with( self.w3, - "Add Trusted Handlers", - mock_contract.functions.addTrustedHandlers.return_value, + "Withdraw", + mock_contract.functions.withdraw.return_value, EscrowClientError, tx_options, ) + self.assertEqual(escrow_withdraw_data.txHash, tx_hash.hex()) + self.assertEqual(escrow_withdraw_data.tokenAddress, token_address) + self.assertEqual(escrow_withdraw_data.amountWithdrawn, amount_withdrawn) + def test_get_balance(self): mock_contract = MagicMock() mock_contract.functions.getBalance = MagicMock() + mock_remaining_funds = MagicMock() + mock_remaining_funds.side_effect = Exception("Test") + mock_contract.functions.remainingFunds = mock_remaining_funds mock_contract.functions.getBalance.return_value.call.return_value = 100 self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) escrow_address = "0x1234567890123456789012345678901234567890" result = self.escrow.get_balance(escrow_address) - self.escrow._get_escrow_contract.assert_called_once_with(escrow_address) + self.escrow._get_escrow_contract.assert_called_with(escrow_address) mock_contract.functions.getBalance.assert_called_once_with() self.assertEqual(result, 100) @@ -1911,6 +1916,9 @@ def test_get_balance_without_account(self): escrowClient = EscrowClient(w3) mock_contract = MagicMock() + mock_remaining_funds = MagicMock() + mock_remaining_funds.side_effect = Exception("Test") + mock_contract.functions.remainingFunds = mock_remaining_funds mock_contract.functions.getBalance = MagicMock() mock_contract.functions.getBalance.return_value.call.return_value = 100 escrowClient._get_escrow_contract = MagicMock(return_value=mock_contract) @@ -1918,7 +1926,7 @@ def test_get_balance_without_account(self): result = escrowClient.get_balance(escrow_address) - escrowClient._get_escrow_contract.assert_called_once_with(escrow_address) + escrowClient._get_escrow_contract.assert_called_with(escrow_address) mock_contract.functions.getBalance.assert_called_once_with() self.assertEqual(result, 100) @@ -1930,6 +1938,19 @@ def test_get_balance_invalid_escrow(self): "Escrow address is not provided by the factory", str(cm.exception) ) + def test_get_balance_new_escrow(self): + mock_contract = MagicMock() + mock_contract.functions.remainingFunds = MagicMock() + mock_contract.functions.remainingFunds.return_value.call.return_value = 100 + self.escrow._get_escrow_contract = MagicMock(return_value=mock_contract) + escrow_address = "0x1234567890123456789012345678901234567890" + + result = self.escrow.get_balance(escrow_address) + + self.escrow._get_escrow_contract.assert_called_once_with(escrow_address) + mock_contract.functions.remainingFunds.assert_called_once_with() + self.assertEqual(result, 100) + def test_get_manifest_hash(self): mock_contract = MagicMock() mock_contract.functions.manifestHash = MagicMock() diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/operator/test_operator_utils.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/operator/test_operator_utils.py index 735348b6fd..10c40a7139 100644 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/operator/test_operator_utils.py +++ b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/operator/test_operator_utils.py @@ -28,22 +28,22 @@ def test_get_leaders(self): "id": DEFAULT_GAS_PAYER, "address": DEFAULT_GAS_PAYER, "amountStaked": "100", - "amountAllocated": "50", "amountLocked": "25", "lockedUntilTimestamp": "0", "amountWithdrawn": "25", "amountSlashed": "25", - "reputation": "25", "reward": "25", "amountJobsProcessed": "25", "role": "role", "fee": None, "publicKey": None, "webhookUrl": None, + "website": None, "url": None, "jobTypes": "type1,type2", "registrationNeeded": True, "registrationInstructions": "www.google.com", + "reputationNetworks": [{"address": "0x01"}], } ], } @@ -62,22 +62,22 @@ def test_get_leaders(self): self.assertEqual(leaders[0].id, DEFAULT_GAS_PAYER) self.assertEqual(leaders[0].address, DEFAULT_GAS_PAYER) self.assertEqual(leaders[0].amount_staked, 100) - self.assertEqual(leaders[0].amount_allocated, 50) self.assertEqual(leaders[0].amount_locked, 25) self.assertEqual(leaders[0].locked_until_timestamp, 0) self.assertEqual(leaders[0].amount_withdrawn, 25) self.assertEqual(leaders[0].amount_slashed, 25) - self.assertEqual(leaders[0].reputation, 25) self.assertEqual(leaders[0].reward, 25) self.assertEqual(leaders[0].amount_jobs_processed, 25) self.assertEqual(leaders[0].role, "role") self.assertEqual(leaders[0].fee, None) self.assertEqual(leaders[0].public_key, None) self.assertEqual(leaders[0].webhook_url, None) + self.assertEqual(leaders[0].website, None) self.assertEqual(leaders[0].url, None) self.assertEqual(leaders[0].job_types, ["type1", "type2"]) self.assertEqual(leaders[0].registration_needed, True) self.assertEqual(leaders[0].registration_instructions, "www.google.com") + self.assertEqual(leaders[0].reputation_networks, ["0x01"]) def test_get_leaders_when_job_types_is_none(self): filter = LeaderFilter(chain_id=ChainId.POLYGON, role="role") @@ -94,20 +94,20 @@ def test_get_leaders_when_job_types_is_none(self): "id": DEFAULT_GAS_PAYER, "address": DEFAULT_GAS_PAYER, "amountStaked": "100", - "amountAllocated": "50", "amountLocked": "25", "lockedUntilTimestamp": "0", "amountWithdrawn": "25", "amountSlashed": "25", - "reputation": "25", "reward": "25", "amountJobsProcessed": "25", "role": "role", "fee": None, "publicKey": None, "webhookUrl": None, + "website": None, "url": None, "jobTypes": None, + "reputationNetworks": [{"address": "0x01"}], } ], } @@ -126,23 +126,22 @@ def test_get_leaders_when_job_types_is_none(self): self.assertEqual(leaders[0].id, DEFAULT_GAS_PAYER) self.assertEqual(leaders[0].address, DEFAULT_GAS_PAYER) self.assertEqual(leaders[0].amount_staked, 100) - self.assertEqual(leaders[0].amount_allocated, 50) self.assertEqual(leaders[0].amount_locked, 25) self.assertEqual(leaders[0].locked_until_timestamp, 0) self.assertEqual(leaders[0].amount_withdrawn, 25) self.assertEqual(leaders[0].amount_slashed, 25) - self.assertEqual(leaders[0].reputation, 25) self.assertEqual(leaders[0].reward, 25) self.assertEqual(leaders[0].amount_jobs_processed, 25) self.assertEqual(leaders[0].role, "role") self.assertEqual(leaders[0].fee, None) self.assertEqual(leaders[0].public_key, None) self.assertEqual(leaders[0].webhook_url, None) + self.assertEqual(leaders[0].website, None) self.assertEqual(leaders[0].url, None) self.assertEqual(leaders[0].registration_needed, None) self.assertEqual(leaders[0].registration_instructions, None) - # Should rerutn empty array self.assertEqual(leaders[0].job_types, []) + self.assertEqual(leaders[0].reputation_networks, ["0x01"]) def test_get_leaders_when_job_types_is_array(self): filter = LeaderFilter(chain_id=ChainId.POLYGON, role="role") @@ -159,20 +158,20 @@ def test_get_leaders_when_job_types_is_array(self): "id": DEFAULT_GAS_PAYER, "address": DEFAULT_GAS_PAYER, "amountStaked": "100", - "amountAllocated": "50", "amountLocked": "25", "lockedUntilTimestamp": "0", "amountWithdrawn": "25", "amountSlashed": "25", - "reputation": "25", "reward": "25", "amountJobsProcessed": "25", "role": "role", "fee": None, "publicKey": None, "webhookUrl": None, + "website": None, "url": None, "jobTypes": ["type1", "type2", "type3"], + "reputationNetworks": [{"address": "0x01"}], } ], } @@ -191,22 +190,22 @@ def test_get_leaders_when_job_types_is_array(self): self.assertEqual(leaders[0].id, DEFAULT_GAS_PAYER) self.assertEqual(leaders[0].address, DEFAULT_GAS_PAYER) self.assertEqual(leaders[0].amount_staked, 100) - self.assertEqual(leaders[0].amount_allocated, 50) self.assertEqual(leaders[0].amount_locked, 25) self.assertEqual(leaders[0].locked_until_timestamp, 0) self.assertEqual(leaders[0].amount_withdrawn, 25) self.assertEqual(leaders[0].amount_slashed, 25) - self.assertEqual(leaders[0].reputation, 25) self.assertEqual(leaders[0].reward, 25) self.assertEqual(leaders[0].amount_jobs_processed, 25) self.assertEqual(leaders[0].role, "role") self.assertEqual(leaders[0].fee, None) self.assertEqual(leaders[0].public_key, None) self.assertEqual(leaders[0].webhook_url, None) + self.assertEqual(leaders[0].website, None) self.assertEqual(leaders[0].url, None) self.assertEqual( leaders[0].job_types, ["type1", "type2", "type3"] ) # Should the same array + self.assertEqual(leaders[0].reputation_networks, ["0x01"]) def test_get_leaders_empty_data(self): filter = LeaderFilter(chain_id=ChainId.POLYGON, role="role") @@ -248,22 +247,22 @@ def test_get_leader(self): "id": staker_address, "address": staker_address, "amountStaked": "100", - "amountAllocated": "50", "amountLocked": "25", "lockedUntilTimestamp": "0", "amountWithdrawn": "25", "amountSlashed": "25", - "reputation": "25", "reward": "25", "amountJobsProcessed": "25", "role": "role", "fee": None, "publicKey": None, "webhookUrl": None, + "website": None, "url": None, "jobTypes": "type1,type2", "registrationNeeded": True, "registrationInstructions": "www.google.com", + "reputationNetworks": [{"address": "0x01"}], } } } @@ -281,22 +280,22 @@ def test_get_leader(self): self.assertEqual(leader.id, staker_address) self.assertEqual(leader.address, staker_address) self.assertEqual(leader.amount_staked, 100) - self.assertEqual(leader.amount_allocated, 50) self.assertEqual(leader.amount_locked, 25) self.assertEqual(leader.locked_until_timestamp, 0) self.assertEqual(leader.amount_withdrawn, 25) self.assertEqual(leader.amount_slashed, 25) - self.assertEqual(leader.reputation, 25) self.assertEqual(leader.reward, 25) self.assertEqual(leader.amount_jobs_processed, 25) self.assertEqual(leader.role, "role") self.assertEqual(leader.fee, None) self.assertEqual(leader.public_key, None) self.assertEqual(leader.webhook_url, None) + self.assertEqual(leader.website, None) self.assertEqual(leader.url, None) self.assertEqual(leader.job_types, ["type1", "type2"]) self.assertEqual(leader.registration_needed, True) self.assertEqual(leader.registration_instructions, "www.google.com") + self.assertEqual(leader.reputation_networks, ["0x01"]) def test_get_leader_when_job_types_is_none(self): staker_address = "0x1234567890123456789012345678901234567891" @@ -313,20 +312,20 @@ def test_get_leader_when_job_types_is_none(self): "id": staker_address, "address": staker_address, "amountStaked": "100", - "amountAllocated": "50", "amountLocked": "25", "lockedUntilTimestamp": "0", "amountWithdrawn": "25", "amountSlashed": "25", - "reputation": "25", "reward": "25", "amountJobsProcessed": "25", "role": "role", "fee": None, "publicKey": None, "webhookUrl": None, + "website": None, "url": None, "jobTypes": None, + "reputationNetworks": [{"address": "0x01"}], } } } @@ -344,22 +343,22 @@ def test_get_leader_when_job_types_is_none(self): self.assertEqual(leader.id, staker_address) self.assertEqual(leader.address, staker_address) self.assertEqual(leader.amount_staked, 100) - self.assertEqual(leader.amount_allocated, 50) self.assertEqual(leader.amount_locked, 25) self.assertEqual(leader.locked_until_timestamp, 0) self.assertEqual(leader.amount_withdrawn, 25) self.assertEqual(leader.amount_slashed, 25) - self.assertEqual(leader.reputation, 25) self.assertEqual(leader.reward, 25) self.assertEqual(leader.amount_jobs_processed, 25) self.assertEqual(leader.role, "role") self.assertEqual(leader.fee, None) self.assertEqual(leader.public_key, None) self.assertEqual(leader.webhook_url, None) + self.assertEqual(leader.website, None) self.assertEqual(leader.url, None) self.assertEqual(leader.job_types, []) self.assertEqual(leader.registration_needed, None) self.assertEqual(leader.registration_instructions, None) + self.assertEqual(leader.reputation_networks, ["0x01"]) def test_get_leader_when_job_types_is_array(self): staker_address = "0x1234567890123456789012345678901234567891" @@ -376,20 +375,20 @@ def test_get_leader_when_job_types_is_array(self): "id": staker_address, "address": staker_address, "amountStaked": "100", - "amountAllocated": "50", "amountLocked": "25", "lockedUntilTimestamp": "0", "amountWithdrawn": "25", "amountSlashed": "25", - "reputation": "25", "reward": "25", "amountJobsProcessed": "25", "role": "role", "fee": None, "publicKey": None, "webhookUrl": None, + "website": None, "url": None, "jobTypes": ["type1", "type2", "type3"], + "reputationNetworks": [{"address": "0x01"}], } } } @@ -407,20 +406,20 @@ def test_get_leader_when_job_types_is_array(self): self.assertEqual(leader.id, staker_address) self.assertEqual(leader.address, staker_address) self.assertEqual(leader.amount_staked, 100) - self.assertEqual(leader.amount_allocated, 50) self.assertEqual(leader.amount_locked, 25) self.assertEqual(leader.locked_until_timestamp, 0) self.assertEqual(leader.amount_withdrawn, 25) self.assertEqual(leader.amount_slashed, 25) - self.assertEqual(leader.reputation, 25) self.assertEqual(leader.reward, 25) self.assertEqual(leader.amount_jobs_processed, 25) self.assertEqual(leader.role, "role") self.assertEqual(leader.fee, None) self.assertEqual(leader.public_key, None) self.assertEqual(leader.webhook_url, None) + self.assertEqual(leader.website, None) self.assertEqual(leader.url, None) self.assertEqual(leader.job_types, ["type1", "type2", "type3"]) + self.assertEqual(leader.reputation_networks, ["0x01"]) def test_get_leader_empty_data(self): staker_address = "0x1234567890123456789012345678901234567891" diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/staking/test_staking_client.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/staking/test_staking_client.py index 190f4b3a96..2dece9c08b 100644 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/staking/test_staking_client.py +++ b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/staking/test_staking_client.py @@ -49,7 +49,6 @@ def test_init_with_valid_inputs(self): self.assertIsNotNone(staking_client.hmtoken_contract) self.assertIsNotNone(staking_client.factory_contract) self.assertIsNotNone(staking_client.staking_contract) - self.assertIsNotNone(staking_client.reward_pool_contract) def test_init_with_invalid_chain_id(self): mock_provider = MagicMock(spec=HTTPProvider) @@ -161,118 +160,6 @@ def test_stake_with_tx_options(self): ) mock_function.assert_called_once_with(100) - def test_allocate(self): - escrow_address = "escrow1" - self.staking_client._is_valid_escrow = MagicMock(return_value=True) - - mock_function = MagicMock() - self.staking_client.staking_contract.functions.allocate = mock_function - - with patch( - "human_protocol_sdk.staking.staking_client.handle_transaction" - ) as mock_handle_transaction: - self.staking_client.allocate(escrow_address, 10) - - mock_handle_transaction.assert_called_once_with( - self.w3, - "Allocate HMT", - mock_function.return_value, - StakingClientError, - None, - ) - mock_function.assert_called_once_with(escrow_address, 10) - - def test_allocate_invalid_amount(self): - escrow_address = "escrow1" - self.staking_client._is_valid_escrow = MagicMock(return_value=True) - - with self.assertRaises(StakingClientError) as cm: - self.staking_client.allocate(escrow_address, -1) - self.assertEqual("Amount to allocate must be greater than 0", str(cm.exception)) - - def test_allocate_invalid_escrow(self): - escrow_address = "invalid_escrow" - self.staking_client._is_valid_escrow = MagicMock(return_value=False) - - with self.assertRaises(StakingClientError) as cm: - self.staking_client.allocate(escrow_address, 10) - self.assertEqual("Invalid escrow address: invalid_escrow", str(cm.exception)) - - def test_allocate_with_tx_options(self): - escrow_address = "escrow1" - self.staking_client._is_valid_escrow = MagicMock(return_value=True) - - mock_function = MagicMock() - self.staking_client.staking_contract.functions.allocate = mock_function - - tx_options = {"gas": 50000} - - with patch( - "human_protocol_sdk.staking.staking_client.handle_transaction" - ) as mock_handle_transaction: - self.staking_client.allocate(escrow_address, 10, tx_options) - - mock_handle_transaction.assert_called_once_with( - self.w3, - "Allocate HMT", - mock_function.return_value, - StakingClientError, - tx_options, - ) - mock_function.assert_called_once_with(escrow_address, 10) - - def test_close_allocation(self): - escrow_address = "escrow1" - self.staking_client._is_valid_escrow = MagicMock(return_value=True) - - mock_function = MagicMock() - self.staking_client.staking_contract.functions.closeAllocation = mock_function - - with patch( - "human_protocol_sdk.staking.staking_client.handle_transaction" - ) as mock_handle_transaction: - self.staking_client.close_allocation(escrow_address) - - mock_handle_transaction.assert_called_once_with( - self.w3, - "Close allocation", - mock_function.return_value, - StakingClientError, - None, - ) - mock_function.assert_called_once_with(escrow_address) - - def test_close_allocation_invalid_escrow(self): - escrow_address = "invalid_escrow" - self.staking_client._is_valid_escrow = MagicMock(return_value=False) - - with self.assertRaises(StakingClientError) as cm: - self.staking_client.close_allocation(escrow_address) - self.assertEqual("Invalid escrow address: invalid_escrow", str(cm.exception)) - - def test_close_allocation_with_tx_options(self): - escrow_address = "escrow1" - self.staking_client._is_valid_escrow = MagicMock(return_value=True) - - mock_function = MagicMock() - self.staking_client.staking_contract.functions.closeAllocation = mock_function - - tx_options = {"gas": 50000} - - with patch( - "human_protocol_sdk.staking.staking_client.handle_transaction" - ) as mock_handle_transaction: - self.staking_client.close_allocation(escrow_address, tx_options) - - mock_handle_transaction.assert_called_once_with( - self.w3, - "Close allocation", - mock_function.return_value, - StakingClientError, - tx_options, - ) - mock_function.assert_called_once_with(escrow_address) - def test_unstake(self): mock_function = MagicMock() self.staking_client.staking_contract.functions.unstake = mock_function @@ -434,103 +321,6 @@ def test_slash_with_tx_options(self): ) mock_function.assert_called_once_with(slasher, staker, escrow_address, 50) - def test_distribute_reward(self): - escrow_address = "escrow1" - self.staking_client._is_valid_escrow = MagicMock(return_value=True) - - mock_function = MagicMock() - self.staking_client.reward_pool_contract.functions.distributeReward = ( - mock_function - ) - - with patch( - "human_protocol_sdk.staking.staking_client.handle_transaction" - ) as mock_handle_transaction: - self.staking_client.distribute_reward(escrow_address) - - mock_handle_transaction.assert_called_once_with( - self.w3, - "Distribute reward", - mock_function.return_value, - StakingClientError, - None, - ) - mock_function.assert_called_once_with(escrow_address) - - def test_distribute_rewards_invalid(self): - escrow_address = "invalid_escrow" - self.staking_client._is_valid_escrow = MagicMock(return_value=False) - - with self.assertRaises(StakingClientError) as cm: - self.staking_client.distribute_reward(escrow_address) - self.assertEqual("Invalid escrow address: invalid_escrow", str(cm.exception)) - - def test_distribute_reward_with_tx_options(self): - escrow_address = "escrow1" - self.staking_client._is_valid_escrow = MagicMock(return_value=True) - tx_options = {"gas": 50000} - - mock_function = MagicMock() - self.staking_client.reward_pool_contract.functions.distributeReward = ( - mock_function - ) - - with patch( - "human_protocol_sdk.staking.staking_client.handle_transaction" - ) as mock_handle_transaction: - self.staking_client.distribute_reward(escrow_address, tx_options) - - mock_handle_transaction.assert_called_once_with( - self.w3, - "Distribute reward", - mock_function.return_value, - StakingClientError, - tx_options, - ) - mock_function.assert_called_once_with(escrow_address) - - def test_get_allocation(self): - escrow_address = "0x1234567890123456789012345678901234567891" - - mock_function = MagicMock() - mock_function.return_value.call.return_value = [ - escrow_address, - "staker", - 10, - 10, - 0, - ] - self.staking_client.staking_contract.functions.getAllocation = mock_function - - allocation = self.staking_client.get_allocation(escrow_address) - - mock_function.assert_called_once_with(escrow_address) - - self.assertEqual(allocation.escrow_address, escrow_address) - self.assertEqual(allocation.staker, "staker") - self.assertEqual(allocation.tokens, 10) - self.assertNotEqual(allocation.created_at, 0) - self.assertEqual(allocation.closed_at, 0) - - def test_get_allocation_invalid_address(self): - escrow_address = "0x1234567890123456789012345678901234567891" - - mock_function = MagicMock() - mock_function.return_value.call.return_value = [ - web3.constants.ADDRESS_ZERO, - "staker", - 10, - 0, - 0, - ] - self.staking_client.staking_contract.functions.getAllocation = mock_function - - allocation = self.staking_client.get_allocation(escrow_address) - - mock_function.assert_called_once_with(escrow_address) - - self.assertIsNone(allocation) - if __name__ == "__main__": unittest.main(exit=True) diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/transaction/test_transaction_utils.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/transaction/test_transaction_utils.py index 5b69d5b463..a2e4c3ca19 100644 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/transaction/test_transaction_utils.py +++ b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/transaction/test_transaction_utils.py @@ -26,6 +26,14 @@ def test_get_transactions(self): "timestamp": 1622700000, "value": "1000000000000000000", "method": "transfer", + "internalTransactions": [ + { + "from": "0x1234567890123456789012345678901234567890", + "to": "0x9876543210987654321098765432109876543211", + "value": "1000000000000000000", + "method": "transfer", + } + ], } mock_transaction_2 = { "block": 456, @@ -35,6 +43,14 @@ def test_get_transactions(self): "timestamp": 1622800000, "value": "2000000000000000000", "method": "transfer", + "internalTransactions": [ + { + "from": "0x9876543210987654321098765432109876543210", + "to": "0x9876543210987654321098765432109876543211", + "value": "1000000000000000000", + "method": "transfer", + } + ], } mock_function.return_value = { @@ -136,6 +152,14 @@ def test_get_transaction(self): "timestamp": 1622700000, "value": "1000000000000000000", "method": "transfer", + "internalTransactions": [ + { + "from": "0x1234567890123456789012345678901234567890", + "to": "0x9876543210987654321098765432109876543211", + "value": "1000000000000000000", + "method": "transfer", + } + ], } mock_function.return_value = {"data": {"transaction": mock_transaction}} diff --git a/packages/sdk/typescript/human-protocol-sdk/package.json b/packages/sdk/typescript/human-protocol-sdk/package.json index 69adf34445..96fa91425d 100644 --- a/packages/sdk/typescript/human-protocol-sdk/package.json +++ b/packages/sdk/typescript/human-protocol-sdk/package.json @@ -63,7 +63,11 @@ "./src/staking.ts", "./src/storage.ts", "./src/statistics.ts", - "./src/transaction.ts" + "./src/transaction.ts", + "./src/enums.ts", + "./src/graphql/types.ts", + "./src/interfaces.ts", + "./src/types.ts" ] } } diff --git a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts index 90bb1e3ea9..753b30774f 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts @@ -1,39 +1,18 @@ import { ChainId } from './enums'; import { NetworkData } from './types'; -/** - * @constant Default public bucket name - */ export const DEFAULT_PUBLIC_BUCKET = 'escrow-public-results'; -/** - * @constant Default storage endpoint - */ export const DEFAULT_ENDPOINT = 'localhost'; -/** - * @constant Default storage region - */ export const DEFAULT_REGION = 'eu'; -/** - * @constant Default storage port - */ export const DEFAULT_PORT = 9000; -/** - * @constant Default storage port - */ export const DEFAULT_USE_SSL = false; -/** - * @constant Default tx Id - */ export const DEFAULT_TX_ID = 1; -/** - * @constant Default Enum for escrow statuses. - */ export enum HttpStatus { OK = 200, CREATED = 201, @@ -45,9 +24,6 @@ export enum HttpStatus { INTERNAL_SERVER_ERROR = 500, } -/** - * @constant Default network parameters - */ export const NETWORKS: { [chainId in ChainId]?: NetworkData; } = { @@ -58,7 +34,6 @@ export const NETWORKS: { factoryAddress: '0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a', hmtAddress: '0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867', stakingAddress: '0x05398211bA2046E296fBc9a9D3EB49e3F15C3123', - rewardPoolAddress: '0x4A5963Dd6792692e9147EdC7659936b96251917a', kvstoreAddress: '0xB6d36B1CDaD50302BCB3DB43bAb0D349458e1b8D', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/ethereum/version/latest', @@ -74,7 +49,6 @@ export const NETWORKS: { factoryAddress: '0x925B24444511c86F4d4E63141D8Be0A025E2dca4', hmtAddress: '0x4dCf5ac4509888714dd43A5cCc46d7ab389D9c23', stakingAddress: '', - rewardPoolAddress: '', kvstoreAddress: '', subgraphUrl: '', subgraphUrlApiKey: '', @@ -88,7 +62,6 @@ export const NETWORKS: { factoryAddress: '0x87469B4f2Fcf37cBd34E54244c0BD4Fa0603664c', hmtAddress: '0xd3A31D57FDD790725d0F6B78095F62E8CD4ab317', stakingAddress: '0xf46B45Df3d956369726d8Bd93Ba33963Ab692920', - rewardPoolAddress: '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4', kvstoreAddress: '0x19Fc3e859C1813ac9427a7a78BeB9ae102CE96d3', subgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/goerli-v2', @@ -101,15 +74,14 @@ export const NETWORKS: { chainId: ChainId.SEPOLIA, title: 'Ethereum Sepolia', scanUrl: 'https://sepolia.etherscan.io/', - factoryAddress: '0xD6D347ba6987519B4e42EcED43dF98eFf5465a23', + factoryAddress: '0x5987A5558d961ee674efe4A8c8eB7B1b5495D3bf', hmtAddress: '0x792abbcC99c01dbDec49c9fa9A828a186Da45C33', - stakingAddress: '0x2B9C5EC6220BA8Ad08CB51A60FFdbC6a6235B203', - rewardPoolAddress: '0xAFf5a986A530ff839d49325A5dF69F96627E8D29', + stakingAddress: '0x2163e3A40032Af1C359ac731deaB48258b317890', kvstoreAddress: '0xCc0AF0635aa19fE799B6aFDBe28fcFAeA7f00a60', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/sepolia/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmadNQBBzcfJHTmzLezZGbwvLux7HmnmfByBHubS2cmLUr', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmYycE8kMaMcKmGizepi8pcFkRfyRmqBt2qwiNbkd6oCQt', oldSubgraphUrl: '', oldFactoryAddress: '', }, @@ -120,7 +92,6 @@ export const NETWORKS: { factoryAddress: '0x92FD968AcBd521c232f5fB8c33b342923cC72714', hmtAddress: '0x711Fd6ab6d65A98904522d4e3586F492B989c527', stakingAddress: '0xdFbB79dC35a3A53741be54a2C9b587d6BafAbd1C', - rewardPoolAddress: '0xf376443BCc6d4d4D63eeC086bc4A9E4a83878e0e', kvstoreAddress: '0x21A0C4CED7aE447fCf87D9FE3A29FA9B3AB20Ff1', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/bsc/version/latest', @@ -135,13 +106,12 @@ export const NETWORKS: { scanUrl: 'https://testnet.bscscan.com', factoryAddress: '0x2bfA592DBDaF434DDcbb893B1916120d181DAD18', hmtAddress: '0xE3D74BBFa45B4bCa69FF28891fBE392f4B4d4e4d', - stakingAddress: '0x5517fE916Fe9F8dB15B0DDc76ebDf0BdDCd4ed18', - rewardPoolAddress: '0xB0A0500103eCEc431b73F6BAd923F0a2774E6e29', + stakingAddress: '0xD6D347ba6987519B4e42EcED43dF98eFf5465a23', kvstoreAddress: '0x32e27177BA6Ea91cf28dfd91a0Da9822A4b74EcF', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/bsc-testnet/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/Qmdq449rn4WKDf7NLvRZgt7CedZRrvpDzPqcvSmhvuu16D', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmZ5fFGPrDSQBfvZHAVQbkaPAgymcCmbhTVk7iuqHXY72P', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/bsctest', oldFactoryAddress: '0xaae6a2646c1f88763e62e0cd08ad050ea66ac46f', @@ -153,7 +123,6 @@ export const NETWORKS: { factoryAddress: '0xBDBfD2cC708199C5640C6ECdf3B0F4A4C67AdfcB', hmtAddress: '0xc748B2A084F8eFc47E086ccdDD9b7e67aEb571BF', stakingAddress: '0xcbAd56bE3f504E98bd70875823d3CC0242B7bB29', - rewardPoolAddress: '0xa8e32d777a3839440cc7c24D591A64B9481753B3', kvstoreAddress: '0xbcB28672F826a50B03EE91B28145EAbddA73B2eD', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/polygon/version/latest', @@ -170,7 +139,6 @@ export const NETWORKS: { factoryAddress: '0xA8D927C4DA17A6b71675d2D49dFda4E9eBE58f2d', hmtAddress: '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4', stakingAddress: '0x7Fd3dF914E7b6Bd96B4c744Df32183b51368Bfac', - rewardPoolAddress: '0xf0145eD99AC3c4f877aDa7dA4D1E059ec9116BAE', kvstoreAddress: '0xD96158c7267Ea658a4688F4aEf1c85659851625d', subgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/mumbai-v2', @@ -185,13 +153,12 @@ export const NETWORKS: { scanUrl: 'https://amoy.polygonscan.com/', factoryAddress: '0xAFf5a986A530ff839d49325A5dF69F96627E8D29', hmtAddress: '0x792abbcC99c01dbDec49c9fa9A828a186Da45C33', - stakingAddress: '0xCc0AF0635aa19fE799B6aFDBe28fcFAeA7f00a60', - rewardPoolAddress: '0xd866bCEFf6D0F77E1c3EAE28230AE6C79b03fDa7', + stakingAddress: '0xffE496683F842a923110415b7278ded3F265f2C5', kvstoreAddress: '0x724AeFC243EdacCA27EAB86D3ec5a76Af4436Fc7', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/amoy/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/Qmbwio5UnvDn5GQRJ5kLJfK27fqHK9nkEh4YXXYKWCc9rH', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmTZ33SRoH4o4HE9JMrH9kPTYS11z3T1N7evePrNZrEvBh', oldSubgraphUrl: '', oldFactoryAddress: '', }, @@ -202,7 +169,6 @@ export const NETWORKS: { factoryAddress: '0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a', hmtAddress: '0x3b25BC1dC591D24d60560d0135D6750A561D4764', stakingAddress: '0x05398211bA2046E296fBc9a9D3EB49e3F15C3123', - rewardPoolAddress: '0x4A5963Dd6792692e9147EdC7659936b96251917a', kvstoreAddress: '0x2B95bEcb6EBC4589f64CB000dFCF716b4aeF8aA6', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/moonbeam/version/latest', @@ -219,7 +185,6 @@ export const NETWORKS: { factoryAddress: '0x5e622FF522D81aa426f082bDD95210BC25fCA7Ed', hmtAddress: '0x2dd72db2bBA65cE663e476bA8b84A1aAF802A8e3', stakingAddress: '0xBFC7009F3371F93F3B54DdC8caCd02914a37495c', - rewardPoolAddress: '0xf46B45Df3d956369726d8Bd93Ba33963Ab692920', kvstoreAddress: '0xcC561f4482f4Ff051D2Dcc65c2cE1A0f291bbA46', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/moonbase-alpha/version/latest', @@ -235,7 +200,6 @@ export const NETWORKS: { factoryAddress: '0x56C2ba540726ED4f46E7a134b6b9Ee9C867FcF92', hmtAddress: '0x9406d5c635AD22b0d76c75E52De57A2177919ca3', stakingAddress: '0x9890473B0b93E24d6D1a8Dfb739D577C6f25FFd3', - rewardPoolAddress: '0x5517fE916Fe9F8dB15B0DDc76ebDf0BdDCd4ed18', kvstoreAddress: '0x3aD4B091E054f192a822D1406f4535eAd38580e4', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/fuji/version/latest', @@ -252,7 +216,6 @@ export const NETWORKS: { factoryAddress: '0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a', hmtAddress: '0x12365293cb6477d4fc2686e46BB97E3Fb64f1550', stakingAddress: '0x05398211bA2046E296fBc9a9D3EB49e3F15C3123', - rewardPoolAddress: '0x4A5963Dd6792692e9147EdC7659936b96251917a', kvstoreAddress: '0x9Bc7bff35B2Be2413708d48c3B0aEF5c43646728', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/avalanche/version/latest', @@ -269,7 +232,6 @@ export const NETWORKS: { factoryAddress: '0x86Af9f6Cd34B69Db1B202223C6d6D109f2491569', hmtAddress: '0x2736B33455A872dC478E1E004106D04c35472468', stakingAddress: '0x003548Df34be8836cF0F9673403a1E40ba449a0F', - rewardPoolAddress: '0xA9545C2530BD5bdb464d5E274F59ACceAa73eD86', kvstoreAddress: '0x938335006ea6F9Eb0e8020969cFF94404425e298', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/celo-alfajores/version/latest', @@ -285,7 +247,6 @@ export const NETWORKS: { factoryAddress: '0xc90B43a5d576D9d8026c48904dfbaED50C15Fa08', hmtAddress: '0x19Ead835951493A763c96910255d5eeF147E914F', stakingAddress: '0x34cD3Bd6B16c559f321799b516dE61E12017fFd1', - rewardPoolAddress: '0xb9344bAD98E3d26a4d83900922baf395a2Ec154c', kvstoreAddress: '0x86Af9f6Cd34B69Db1B202223C6d6D109f2491569', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/celo/version/latest', @@ -301,7 +262,6 @@ export const NETWORKS: { factoryAddress: '0x4949C9DFFD83F0D5Ab0AB24C57C4D403D5c20C15', hmtAddress: '0x10acbe3b9e6a2ff7f341e5cbf4b6617741ff44aa', stakingAddress: '0x01D115E9E8bF0C58318793624CC662a030D07F1D', - rewardPoolAddress: '0x7ABa5F75b2b530cB0c8927C86591c21dF44f06b6', kvstoreAddress: '0x6512d894cc3d3FE93Da9d0420430136fA889FaB9', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/xlayer/version/latest', @@ -317,7 +277,6 @@ export const NETWORKS: { factoryAddress: '0x6Cd3ecAD36ee88E9ef3665CF381D9dAE0FE0a32e', hmtAddress: '0x792abbcC99c01dbDec49c9fa9A828a186Da45C33', stakingAddress: '0x819069fEd50581587fAB9E583b5488fc2D33B7ea', - rewardPoolAddress: '0x6daccd1f3a68945f8a7ac6d20260953f7a97fae4', kvstoreAddress: '0xdE8BE9E3C12E9F546309A429cd88d026a25EaF8C', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/xlayer-testnet/version/latest', @@ -333,7 +292,6 @@ export const NETWORKS: { factoryAddress: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9', hmtAddress: '0x5FbDB2315678afecb367f032d93F642f64180aa3', stakingAddress: '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0', - rewardPoolAddress: '0xa513E6E4b8f2a923D98304ec87F64353C4D5C853', kvstoreAddress: '0x5FC8d32690cc91D4c39d9d3abcBD16989F875707', subgraphUrl: 'http://localhost:8000/subgraphs/name/humanprotocol/localhost', subgraphUrlApiKey: '', @@ -347,6 +305,7 @@ export const KVStoreKeys = { fee: 'fee', publicKey: 'public_key', webhookUrl: 'webhook_url', + website: 'website', url: 'url', jobTypes: 'job_types', registrationNeeded: 'registration_needed', diff --git a/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts b/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts index 072b4b2dad..5bcf2bd213 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts @@ -413,7 +413,7 @@ export class EncryptionUtils { * This function encrypts a message using the specified public keys. * * @param {string} message Message to encrypt. - * @param {string} publicKey Array of public keys to use for encryption. + * @param {string} publicKeys Array of public keys to use for encryption. * @returns {Promise} Message encrypted. * * **Code example** diff --git a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts index 1addb2d8bf..4d6c631db4 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { + ERC20, + ERC20__factory, Escrow, EscrowFactory, EscrowFactory__factory, @@ -45,7 +47,12 @@ import { StatusEvent, } from './graphql'; import { IEscrowConfig, IEscrowsFilter } from './interfaces'; -import { EscrowCancel, EscrowStatus, NetworkData } from './types'; +import { + EscrowCancel, + EscrowStatus, + EscrowWithdraw, + NetworkData, +} from './types'; import { getSubgraphUrl, isValidUrl, throwError } from './utils'; /** @@ -124,7 +131,7 @@ export class EscrowClient extends BaseEthersClient { * **EscrowClient constructor** * * @param {ContractRunner} runner The Runner object to interact with the Ethereum network - * @param {NetworkData} network The network information required to connect to the Escrow contract + * @param {NetworkData} networkData The network information required to connect to the Escrow contract */ constructor(runner: ContractRunner, networkData: NetworkData) { super(runner, networkData); @@ -370,69 +377,6 @@ export class EscrowClient extends BaseEthersClient { } } - /** - * This function creates and sets up an escrow. - * - * @param {string} tokenAddress Token address to use for pay outs. - * @param {string[]} trustedHandlers Array of addresses that can perform actions on the contract. - * @param {string} jobRequesterId Job Requester Id - * @param {IEscrowConfig} escrowConfig Configuration object with escrow settings. - * @returns {Promise} Returns the address of the escrow created. - * - * - * **Code example** - * - * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY' - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * - * const tokenAddress = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4'; - * const trustedHandlers = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; - * const jobRequesterId = "job-requester-id"; - * - * const escrowConfig = { - * recordingOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - * reputationOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - * exchangeOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - * recordingOracleFee: bigint.from('10'), - * reputationOracleFee: bigint.from('10'), - * exchangeOracleFee: bigint.from('10'), - * manifestUrl: 'htttp://localhost/manifest.json', - * manifestHash: 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079', - * }; - * - * const escrowAddress = await escrowClient.createAndSetupEscrow(tokenAddress, trustedHandlers, jobRequesterId, escrowConfig); - * ``` - */ - @requiresSigner - async createAndSetupEscrow( - tokenAddress: string, - trustedHandlers: string[], - jobRequesterId: string, - escrowConfig: IEscrowConfig - ): Promise { - try { - const escrowAddress = await this.createEscrow( - tokenAddress, - trustedHandlers, - jobRequesterId - ); - - await this.setup(escrowAddress, escrowConfig); - - return escrowAddress; - } catch (e) { - return throwError(e); - } - } - /** * This function adds funds of the chosen token to the escrow. * @@ -619,6 +563,7 @@ export class EscrowClient extends BaseEthersClient { * @param {bigint[]} amounts Array of amounts the recipients will receive. * @param {string} finalResultsUrl Final results file url. * @param {string} finalResultsHash Final results file hash. + * @param {string} forceComplete Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). * @returns Returns void if successful. Throws error if any. * @@ -653,6 +598,7 @@ export class EscrowClient extends BaseEthersClient { amounts: bigint[], finalResultsUrl: string, finalResultsHash: string, + forceComplete = false, txOptions: Overrides = {} ): Promise { if (!ethers.isAddress(escrowAddress)) { @@ -706,17 +652,34 @@ export class EscrowClient extends BaseEthersClient { try { const escrowContract = this.getEscrowContract(escrowAddress); - - await ( - await escrowContract.bulkPayOut( - recipients, - amounts, - finalResultsUrl, - finalResultsHash, - DEFAULT_TX_ID, - txOptions - ) - ).wait(); + if (forceComplete) { + await ( + await escrowContract[ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ]( + recipients, + amounts, + finalResultsUrl, + finalResultsHash, + DEFAULT_TX_ID, + forceComplete, + txOptions + ) + ).wait(); + } else { + await ( + await escrowContract[ + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ]( + recipients, + amounts, + finalResultsUrl, + finalResultsHash, + DEFAULT_TX_ID, + txOptions + ) + ).wait(); + } return; } catch (e) { return throwError(e); @@ -808,9 +771,10 @@ export class EscrowClient extends BaseEthersClient { } /** - * This function cancels the specified escrow, sends the balance to the canceler and selfdestructs the escrow contract. + * This function adds an array of addresses to the trusted handlers list. * * @param {string} escrowAddress Address of the escrow. + * @param {string[]} trustedHandlers Array of addresses of trusted handlers to add. * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). * @returns Returns void if successful. Throws error if any. * @@ -830,15 +794,30 @@ export class EscrowClient extends BaseEthersClient { * const signer = new Wallet(privateKey, provider); * const escrowClient = await EscrowClient.build(signer); * - * await escrowClient.abort('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * const trustedHandlers = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'] + * await escrowClient.addTrustedHandlers('0x62dD51230A30401C455c8398d06F85e4EaB6309f', trustedHandlers); * ``` */ @requiresSigner - async abort(escrowAddress: string, txOptions: Overrides = {}): Promise { + async addTrustedHandlers( + escrowAddress: string, + trustedHandlers: string[], + txOptions: Overrides = {} + ): Promise { if (!ethers.isAddress(escrowAddress)) { throw ErrorInvalidEscrowAddressProvided; } + if (trustedHandlers.length === 0) { + throw ErrorListOfHandlersCannotBeEmpty; + } + + trustedHandlers.forEach((trustedHandler) => { + if (!ethers.isAddress(trustedHandler)) { + throw new InvalidEthereumAddressError(trustedHandler); + } + }); + if (!(await this.escrowFactoryContract.hasEscrow(escrowAddress))) { throw ErrorEscrowAddressIsNotProvidedByFactory; } @@ -846,7 +825,9 @@ export class EscrowClient extends BaseEthersClient { try { const escrowContract = this.getEscrowContract(escrowAddress); - await (await escrowContract.abort(txOptions)).wait(); + await ( + await escrowContract.addTrustedHandlers(trustedHandlers, txOptions) + ).wait(); return; } catch (e) { return throwError(e); @@ -854,20 +835,20 @@ export class EscrowClient extends BaseEthersClient { } /** - * This function sets the status of an escrow to completed. + * This function withdraws additional tokens in the escrow to the canceler. * - * @param {string} escrowAddress Address of the escrow. - * @param {string[]} trustedHandlers Array of addresses of trusted handlers to add. + * @param {string} escrowAddress Address of the escrow to withdraw. + * @param {string} tokenAddress Address of the token to withdraw. * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. + * @returns {EscrowWithdraw} Returns the escrow withdrawal data including transaction hash and withdrawal amount. Throws error if any. * * * **Code example** * - * > Only Job Launcher or trusted handler can call it. + * > Only Job Launcher or a trusted handler can call it. * * ```ts - * import { Wallet, providers } from 'ethers'; + * import { ethers, Wallet, providers } from 'ethers'; * import { EscrowClient } from '@human-protocol/sdk'; * * const rpcUrl = 'YOUR_RPC_URL'; @@ -877,30 +858,26 @@ export class EscrowClient extends BaseEthersClient { * const signer = new Wallet(privateKey, provider); * const escrowClient = await EscrowClient.build(signer); * - * const trustedHandlers = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'] - * await escrowClient.addTrustedHandlers('0x62dD51230A30401C455c8398d06F85e4EaB6309f', trustedHandlers); + * await escrowClient.withdraw( + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + * '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4' + * ); * ``` */ @requiresSigner - async addTrustedHandlers( + async withdraw( escrowAddress: string, - trustedHandlers: string[], + tokenAddress: string, txOptions: Overrides = {} - ): Promise { + ): Promise { if (!ethers.isAddress(escrowAddress)) { throw ErrorInvalidEscrowAddressProvided; } - if (trustedHandlers.length === 0) { - throw ErrorListOfHandlersCannotBeEmpty; + if (!ethers.isAddress(tokenAddress)) { + throw ErrorInvalidTokenAddress; } - trustedHandlers.forEach((trustedHandler) => { - if (!ethers.isAddress(trustedHandler)) { - throw new InvalidEthereumAddressError(trustedHandler); - } - }); - if (!(await this.escrowFactoryContract.hasEscrow(escrowAddress))) { throw ErrorEscrowAddressIsNotProvidedByFactory; } @@ -908,10 +885,43 @@ export class EscrowClient extends BaseEthersClient { try { const escrowContract = this.getEscrowContract(escrowAddress); - await ( - await escrowContract.addTrustedHandlers(trustedHandlers, txOptions) + const transactionReceipt = await ( + await escrowContract.withdraw(tokenAddress, txOptions) ).wait(); - return; + + let amountTransferred: bigint | undefined = undefined; + + const tokenContract: ERC20 = ERC20__factory.connect( + tokenAddress, + this.runner + ); + if (transactionReceipt) + for (const log of transactionReceipt.logs) { + if (log.address === tokenAddress) { + const parsedLog = tokenContract.interface.parseLog({ + topics: log.topics as string[], + data: log.data, + }); + + const from = parsedLog?.args[0]; + if (parsedLog?.name === 'Transfer' && from === escrowAddress) { + amountTransferred = parsedLog?.args[2]; + break; + } + } + } + + if (amountTransferred === undefined) { + throw ErrorTransferEventNotFoundInTransactionLogs; + } + + const escrowWithdrawData: EscrowWithdraw = { + txHash: transactionReceipt?.hash || '', + tokenAddress, + amountWithdrawn: amountTransferred, + }; + + return escrowWithdrawData; } catch (e) { return throwError(e); } @@ -949,7 +959,13 @@ export class EscrowClient extends BaseEthersClient { try { const escrowContract = this.getEscrowContract(escrowAddress); - return escrowContract.getBalance(); + try { + return await escrowContract.remainingFunds(); + } catch { + // Use getBalance() method below if remainingFunds() is not available + } + + return await escrowContract.getBalance(); } catch (e) { return throwError(e); } diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts index fe9f7411a0..6e0e34dc09 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts @@ -6,22 +6,22 @@ const LEADER_FRAGMENT = gql` id address amountStaked - amountAllocated amountLocked lockedUntilTimestamp amountWithdrawn amountSlashed - reputation reward amountJobsProcessed role fee publicKey webhookUrl + website url jobTypes registrationNeeded registrationInstructions + reputationNetworks } `; diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/statistics.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/statistics.ts index d7848afa05..6c73f4eb4b 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/statistics.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/statistics.ts @@ -15,7 +15,6 @@ const HMTOKEN_STATISTICS_FRAGMENT = gql` const ESCROW_STATISTICS_FRAGMENT = gql` fragment EscrowStatisticsFields on EscrowStatistics { fundEventCount - setupEventCount storeResultsEventCount bulkPayoutEventCount pendingStatusEventCount @@ -32,7 +31,6 @@ const EVENT_DAY_DATA_FRAGMENT = gql` fragment EventDayDataFields on EventDayData { timestamp dailyFundEventCount - dailySetupEventCount dailyStoreResultsEventCount dailyBulkPayoutEventCount dailyPendingStatusEventCount diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts index e108571888..04d0edeecc 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts @@ -10,6 +10,19 @@ const TRANSACTION_FRAGMENT = gql` timestamp value method + receiver + escrow + token + internalTransactions { + from + id + to + value + receiver + escrow + token + method + } } `; @@ -21,20 +34,16 @@ export const GET_TRANSACTIONS_QUERY = (filter: ITransactionsFilter) => { fromAddress === toAddress ? ` ${fromAddress ? `{ from: $fromAddress }` : ''} - ${toAddress ? `{ to: $toAddress }` : ''} + ${toAddress ? `{ or: [{ or: [{ to: $toAddress }, { receiver: $toAddress }] }, {internalTransactions_: { or: [{ to: $toAddress }, { receiver: $toAddress }] } ]}` : ''} ` : ` ${fromAddress ? `from: $fromAddress` : ''} - ${toAddress ? `to: $toAddress` : ''} + ${toAddress ? `or: [{ or: [{ to: $toAddress }, { receiver: $toAddress }] }, { internalTransactions_: { or: [{ to: $toAddress }, { receiver: $toAddress }] } }]` : ''} `; const WHERE_CLAUSE = ` where: { - ${ - fromAddress === toAddress - ? `or: [ ${addressCondition} ],` - : addressCondition - } + ${fromAddress && fromAddress === toAddress ? `or: [ ${addressCondition} ],` : addressCondition} ${startDate ? `timestamp_gte: $startDate,` : ''} ${endDate ? `timestamp_lte: $endDate,` : ''} ${startBlock ? `block_gte: $startBlock,` : ''} diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts index 90cbfff524..ebbd7cdf98 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts @@ -41,7 +41,6 @@ export type HMTStatisticsData = { export type EscrowStatisticsData = { fundEventCount: string; - setupEventCount: string; storeResultsEventCount: string; bulkPayoutEventCount: string; pendingStatusEventCount: string; @@ -56,7 +55,6 @@ export type EscrowStatisticsData = { export type EventDayData = { timestamp: string; dailyFundEventCount: string; - dailySetupEventCount: string; dailyStoreResultsEventCount: string; dailyBulkPayoutEventCount: string; dailyPendingStatusEventCount: string; diff --git a/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts b/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts index cfef0dae25..005b9fdc58 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts @@ -1,14 +1,6 @@ import { EscrowStatus } from './types'; import { ChainId, OrderDirection } from './enums'; -export interface IAllocation { - escrowAddress: string; - staker: string; - tokens: bigint; - createdAt: bigint; - closedAt: bigint; -} - export interface IReward { escrowAddress: string; amount: bigint; @@ -19,26 +11,28 @@ export interface ILeader { chainId: ChainId; address: string; amountStaked: bigint; - amountAllocated: bigint; amountLocked: bigint; lockedUntilTimestamp: bigint; amountWithdrawn: bigint; amountSlashed: bigint; - reputation: bigint; reward: bigint; amountJobsProcessed: bigint; role?: string; fee?: bigint; publicKey?: string; webhookUrl?: string; + website?: string; url?: string; jobTypes?: string[]; registrationNeeded?: boolean; registrationInstructions?: string; + reputationNetworks?: string[]; } -export interface ILeaderSubgraph extends Omit { +export interface ILeaderSubgraph + extends Omit { jobTypes?: string; + reputationNetworks?: { address: string }[]; } export interface ILeadersFilter { @@ -121,6 +115,16 @@ export interface IKVStore { value: string; } +export interface InternalTransaction { + from: string; + to: string; + value: string; + method: string; + receiver?: string; + escrow?: string; + token?: string; +} + export interface ITransaction { block: bigint; txHash: string; @@ -129,6 +133,10 @@ export interface ITransaction { timestamp: bigint; value: string; method: string; + receiver?: string; + escrow?: string; + token?: string; + internalTransactions: InternalTransaction[]; } export interface ITransactionsFilter extends IPagination { diff --git a/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts b/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts index e1262c29c8..f0409f1ab5 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts @@ -103,7 +103,7 @@ export class KVStoreClient extends BaseEthersClient { * **KVStoreClient constructor** * * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network - * @param {NetworkData} network - The network information required to connect to the KVStore contract + * @param {NetworkData} networkData - The network information required to connect to the KVStore contract */ constructor(runner: ContractRunner, networkData: NetworkData) { super(runner, networkData); diff --git a/packages/sdk/typescript/human-protocol-sdk/src/operator.ts b/packages/sdk/typescript/human-protocol-sdk/src/operator.ts index bd03a522af..f62ba07001 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/operator.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/operator.ts @@ -65,6 +65,7 @@ export class OperatorUtils { } let jobTypes: string[] = []; + let reputationNetworks: string[] = []; if (typeof leader.jobTypes === 'string') { jobTypes = leader.jobTypes.split(','); @@ -72,9 +73,16 @@ export class OperatorUtils { jobTypes = leader.jobTypes; } + if (leader.reputationNetworks && Array.isArray(leader.reputationNetworks)) { + reputationNetworks = leader.reputationNetworks.map( + (network) => network.address + ); + } + return { ...leader, jobTypes, + reputationNetworks, }; } @@ -118,6 +126,7 @@ export class OperatorUtils { leaders_data = leaders_data.concat( leaders.map((leader) => { let jobTypes: string[] = []; + let reputationNetworks: string[] = []; if (typeof leader.jobTypes === 'string') { jobTypes = leader.jobTypes.split(','); @@ -125,9 +134,19 @@ export class OperatorUtils { jobTypes = leader.jobTypes; } + if ( + leader.reputationNetworks && + Array.isArray(leader.reputationNetworks) + ) { + reputationNetworks = leader.reputationNetworks.map( + (network) => network.address + ); + } + return { ...leader, jobTypes, + reputationNetworks, }; }) ); diff --git a/packages/sdk/typescript/human-protocol-sdk/src/staking.ts b/packages/sdk/typescript/human-protocol-sdk/src/staking.ts index 6001e93768..de9a1cebd5 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/staking.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/staking.ts @@ -3,8 +3,6 @@ import { EscrowFactory__factory, HMToken, HMToken__factory, - RewardPool, - RewardPool__factory, Staking, Staking__factory, } from '@human-protocol/core/typechain-types'; @@ -23,7 +21,6 @@ import { ErrorProviderDoesNotExist, ErrorUnsupportedChainID, } from './error'; -import { IAllocation } from './interfaces'; import { NetworkData } from './types'; import { throwError } from './utils'; @@ -100,13 +97,12 @@ export class StakingClient extends BaseEthersClient { public tokenContract: HMToken; public stakingContract: Staking; public escrowFactoryContract: EscrowFactory; - public rewardPoolContract: RewardPool; /** * **StakingClient constructor** * * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network - * @param {NetworkData} network - The network information required to connect to the Staking contract + * @param {NetworkData} networkData - The network information required to connect to the Staking contract */ constructor(runner: ContractRunner, networkData: NetworkData) { super(runner, networkData); @@ -125,18 +121,12 @@ export class StakingClient extends BaseEthersClient { networkData.hmtAddress, runner ); - - this.rewardPoolContract = RewardPool__factory.connect( - networkData.rewardPoolAddress, - this.runner - ); } /** * Creates an instance of StakingClient from a Runner. * * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network - * @param {number | undefined} gasPriceMultiplier - The multiplier to apply to the gas price * * @returns {Promise} - An instance of StakingClient * @throws {ErrorProviderDoesNotExist} - Thrown if the provider does not exist for the provided Signer @@ -360,7 +350,7 @@ export class StakingClient extends BaseEthersClient { * * @param {string} slasher Wallet address from who requested the slash * @param {string} staker Wallet address from who is going to be slashed - * @param {string} escrowAddress Address of the escrow which allocation will be slashed + * @param {string} escrowAddress Address of the escrow that the slash is made * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). * @param {bigint} amount Amount in WEI of tokens to unstake. * @returns Returns void if successful. Throws error if any. @@ -425,177 +415,4 @@ export class StakingClient extends BaseEthersClient { return throwError(e); } } - - /** - * This function allocates a portion of the staked tokens to a specific escrow. - * - * > Must have tokens staked - * - * @param {string} escrowAddress Address of the escrow contract to allocate in. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @param {bigint} amount Amount in WEI of tokens to allocate. - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY' - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); - * - * const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI - * await stakingClient.allocate('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); - * ``` - */ - @requiresSigner - public async allocate( - escrowAddress: string, - amount: bigint, - txOptions: Overrides = {} - ): Promise { - if (typeof amount !== 'bigint') { - throw ErrorInvalidStakingValueType; - } - - if (amount < 0n) { - throw ErrorInvalidStakingValueSign; - } - - await this.checkValidEscrow(escrowAddress); - - try { - await ( - await this.stakingContract.allocate(escrowAddress, amount, txOptions) - ).wait(); - return; - } catch (e) { - return throwError(e); - } - } - - /** - * This function drops the allocation from a specific escrow. - * - * > The escrow must have allocation - * > The escrow must be cancelled or completed. - * - * @param {string} escrowAddress Address of the escrow contract to close allocation from. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * ```ts - * import { Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY' - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); - * - * await stakingClient.closeAllocation('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); - * ``` - */ - @requiresSigner - public async closeAllocation( - escrowAddress: string, - txOptions: Overrides = {} - ): Promise { - await this.checkValidEscrow(escrowAddress); - - try { - await ( - await this.stakingContract.closeAllocation(escrowAddress, txOptions) - ).wait(); - return; - } catch (e) { - return throwError(e); - } - } - - /** - * This function drops the allocation from a specific escrow. - * - * > The escrow must have rewards added - * - * @param {string} escrowAddress Escrow address from which rewards are distributed. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * ```ts - * import { Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY' - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); - * - * await stakingClient.distributeReward('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); - * ``` - */ - @requiresSigner - public async distributeReward( - escrowAddress: string, - txOptions: Overrides = {} - ): Promise { - await this.checkValidEscrow(escrowAddress); - - try { - ( - await this.rewardPoolContract.distributeReward(escrowAddress, txOptions) - ).wait(); - return; - } catch (e) { - return throwError(e); - } - } - - /** - * This function returns information about the allocation of the specified escrow. - * - * @param {string} escrowAddress Escrow address from which we want to get allocation information. - * @returns {IAllocation} Returns allocation info if exists. - * - * - * **Code example** - * - * ```ts - * import { StakingClient } from '@human-protocol/sdk'; - * import { providers } from 'ethers'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const stakingClient = await StakingClient.build(provider); - * - * const allocationInfo = await stakingClient.getAllocation('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); - * ``` - */ - public async getAllocation(escrowAddress: string): Promise { - await this.checkValidEscrow(escrowAddress); - - try { - const result = await this.stakingContract.getAllocation(escrowAddress); - return result; - } catch (e) { - return throwError(e); - } - } } diff --git a/packages/sdk/typescript/human-protocol-sdk/src/types.ts b/packages/sdk/typescript/human-protocol-sdk/src/types.ts index b47a5a27c1..ad029935b9 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/types.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/types.ts @@ -115,10 +115,6 @@ export type NetworkData = { * Staking contract address */ stakingAddress: string; - /** - * RewardPool contract address - */ - rewardPoolAddress: string; /** * KVStore contract address */ @@ -154,3 +150,21 @@ export type EscrowCancel = { */ amountRefunded: bigint; }; + +/** + * Represents the response data for an escrow withdrawal. + */ +export type EscrowWithdraw = { + /** + * The hash of the transaction associated with the escrow withdrawal. + */ + txHash: string; + /** + * The address of the token used for the withdrawal. + */ + tokenAddress: string; + /** + * The amount withdrawn from the escrow. + */ + amountWithdrawn: bigint; +}; diff --git a/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts index 7a7ab931a1..25139998de 100644 --- a/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts +++ b/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { + ERC20__factory, EscrowFactory__factory, Escrow__factory, HMToken__factory, @@ -71,15 +72,16 @@ describe('EscrowClient', () => { mockEscrowContract = { createEscrow: vi.fn(), setup: vi.fn(), - createAndSetupEscrow: vi.fn(), fund: vi.fn(), storeResults: vi.fn(), complete: vi.fn(), - bulkPayOut: vi.fn(), + 'bulkPayOut(address[],uint256[],string,string,uint256)': vi.fn(), + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)': vi.fn(), cancel: vi.fn(), - abort: vi.fn(), + withdraw: vi.fn(), addTrustedHandlers: vi.fn(), getBalance: vi.fn(), + remainingFunds: vi.fn(), manifestHash: vi.fn(), manifestUrl: vi.fn(), finalResultsUrl: vi.fn(), @@ -603,90 +605,6 @@ describe('EscrowClient', () => { }); }); - describe('createAndSetupEscrow', () => { - test('should successfully create and setup escrow', async () => { - const escrowAddress = ethers.ZeroAddress; - const tokenAddress = ethers.ZeroAddress; - const trustedHandlers = [ethers.ZeroAddress]; - const jobRequesterId = 'job-requester'; - - const escrowConfig = { - recordingOracle: ethers.ZeroAddress, - reputationOracle: ethers.ZeroAddress, - exchangeOracle: ethers.ZeroAddress, - recordingOracleFee: 10n, - reputationOracleFee: 10n, - exchangeOracleFee: 10n, - manifestUrl: VALID_URL, - manifestHash: FAKE_HASH, - }; - - escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); - escrowClient.createEscrow = vi.fn().mockReturnValue(escrowAddress); - const setupSpy = vi - .spyOn(escrowClient.escrowContract, 'setup') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - - await escrowClient.createAndSetupEscrow( - tokenAddress, - trustedHandlers, - jobRequesterId, - escrowConfig - ); - - expect(escrowClient.createEscrow).toHaveBeenCalledWith( - tokenAddress, - trustedHandlers, - jobRequesterId - ); - expect(setupSpy).toHaveBeenCalledWith( - ethers.ZeroAddress, - ethers.ZeroAddress, - ethers.ZeroAddress, - 10n, - 10n, - 10n, - VALID_URL, - FAKE_HASH, - {} - ); - }); - - test('should throw an error if setup escrow fails', async () => { - const escrowConfig = { - recordingOracle: ethers.ZeroAddress, - reputationOracle: ethers.ZeroAddress, - exchangeOracle: ethers.ZeroAddress, - recordingOracleFee: 10n, - reputationOracleFee: 10n, - exchangeOracleFee: 10n, - manifestUrl: VALID_URL, - manifestHash: FAKE_HASH, - }; - - escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); - escrowClient.escrowContract.setup.mockRejectedValueOnce(new Error()); - - await expect( - escrowClient.setup(ethers.ZeroAddress, escrowConfig) - ).rejects.toThrow(); - - expect(escrowClient.escrowContract.setup).toHaveBeenCalledWith( - ethers.ZeroAddress, - ethers.ZeroAddress, - ethers.ZeroAddress, - 10n, - 10n, - 10n, - VALID_URL, - FAKE_HASH, - {} - ); - }); - }); - describe('fund', () => { test('should throw an error if escrowAddress is an invalid address', async () => { const invalidAddress = FAKE_ADDRESS; @@ -1165,10 +1083,12 @@ describe('EscrowClient', () => { const finalResultsHash = FAKE_HASH; escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); - escrowClient.getBalance = vi.fn().mockReturnValue(100n); const bulkPayOutSpy = vi - .spyOn(escrowClient.escrowContract, 'bulkPayOut') + .spyOn( + escrowClient.escrowContract, + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ) .mockImplementation(() => ({ wait: vi.fn().mockResolvedValue(true), })); @@ -1191,15 +1111,42 @@ describe('EscrowClient', () => { ); }); - test('should throw an error if bulkPayOut fails', async () => { + test('should successfully bulkPayOut escrow with forceComplete option', async () => { const escrowAddress = ethers.ZeroAddress; + const recipients = [ethers.ZeroAddress, ethers.ZeroAddress]; + const amounts = [10n, 10n]; + const finalResultsUrl = VALID_URL; + const finalResultsHash = FAKE_HASH; escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); - escrowClient.escrowContract.abort.mockRejectedValueOnce(new Error()); - await expect(escrowClient.abort(escrowAddress)).rejects.toThrow(); + const bulkPayOutSpy = vi + .spyOn( + escrowClient.escrowContract, + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ) + .mockImplementation(() => ({ + wait: vi.fn().mockResolvedValue(true), + })); + + await escrowClient.bulkPayOut( + escrowAddress, + recipients, + amounts, + finalResultsUrl, + finalResultsHash, + true + ); - expect(escrowClient.escrowContract.abort).toHaveBeenCalledWith({}); + expect(bulkPayOutSpy).toHaveBeenCalledWith( + recipients, + amounts, + finalResultsUrl, + finalResultsHash, + DEFAULT_TX_ID, + true, + {} + ); }); test('should successfully bulkPayOut escrow with transaction options', async () => { @@ -1213,7 +1160,10 @@ describe('EscrowClient', () => { escrowClient.getBalance = vi.fn().mockReturnValue(100n); const bulkPayOutSpy = vi - .spyOn(escrowClient.escrowContract, 'bulkPayOut') + .spyOn( + escrowClient.escrowContract, + 'bulkPayOut(address[],uint256[],string,string,uint256)' + ) .mockImplementation(() => ({ wait: vi.fn().mockResolvedValue(true), })); @@ -1225,6 +1175,7 @@ describe('EscrowClient', () => { amounts, finalResultsUrl, finalResultsHash, + false, txOptions ); @@ -1394,68 +1345,6 @@ describe('EscrowClient', () => { }); }); - describe('abort', () => { - test('should throw an error if escrowAddress is an invalid address', async () => { - const invalidAddress = FAKE_ADDRESS; - - await expect(escrowClient.abort(invalidAddress)).rejects.toThrow( - ErrorInvalidEscrowAddressProvided - ); - }); - - test('should throw an error if hasEscrow returns false', async () => { - const escrowAddress = ethers.ZeroAddress; - - escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(false); - - await expect(escrowClient.abort(escrowAddress)).rejects.toThrow( - ErrorEscrowAddressIsNotProvidedByFactory - ); - }); - - test('should successfully abort escrow', async () => { - const escrowAddress = ethers.ZeroAddress; - - escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); - const abortSpy = vi - .spyOn(escrowClient.escrowContract, 'abort') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - - await escrowClient.abort(escrowAddress); - - expect(abortSpy).toHaveBeenCalledWith({}); - }); - - test('should throw an error if abort fails', async () => { - const escrowAddress = ethers.ZeroAddress; - - escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); - escrowClient.escrowContract.abort.mockRejectedValueOnce(new Error()); - - await expect(escrowClient.abort(escrowAddress)).rejects.toThrow(); - - expect(escrowClient.escrowContract.abort).toHaveBeenCalledWith({}); - }); - - test('should successfully abort escrow with transaction options', async () => { - const escrowAddress = ethers.ZeroAddress; - - escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); - const abortSpy = vi - .spyOn(escrowClient.escrowContract, 'abort') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - const txOptions: Overrides = { gasLimit: 45000 }; - - await escrowClient.abort(escrowAddress, txOptions); - - expect(abortSpy).toHaveBeenCalledWith(txOptions); - }); - }); - describe('addTrustedHandlers', () => { test('should throw an error if escrowAddress is an invalid address', async () => { const escrowAddress = FAKE_ADDRESS; @@ -1558,6 +1447,183 @@ describe('EscrowClient', () => { }); }); + describe('withdraw', () => { + const escrowAddress = ethers.ZeroAddress; + const tokenAddress = ethers.ZeroAddress; + + test('should throw an error if escrowAddress is an invalid address', async () => { + const invalidEscrowAddress = FAKE_ADDRESS; + + await expect( + escrowClient.withdraw(invalidEscrowAddress, tokenAddress) + ).rejects.toThrow(ErrorInvalidEscrowAddressProvided); + }); + + test('should throw an error if tokenAddress is an invalid address', async () => { + const invalidTokenAddress = FAKE_ADDRESS; + + await expect( + escrowClient.withdraw(escrowAddress, invalidTokenAddress) + ).rejects.toThrow(ErrorInvalidTokenAddress); + }); + + test('should throw an error if hasEscrow returns false', async () => { + escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(false); + + await expect( + escrowClient.withdraw(escrowAddress, tokenAddress) + ).rejects.toThrow(ErrorEscrowAddressIsNotProvidedByFactory); + }); + + test('should successfully withdraw from escrow', async () => { + const amountWithdrawn = 1n; + + const log = { + address: ethers.ZeroAddress, + name: 'Transfer', + args: [ethers.ZeroAddress, ethers.ZeroAddress, amountWithdrawn], + }; + mockTx.wait.mockResolvedValueOnce({ + hash: FAKE_HASH, + logs: [log], + }); + + const mockERC20FactoryContract = { + interface: { + parseLog: vi.fn().mockReturnValueOnce(log), + }, + }; + + vi.spyOn(ERC20__factory, 'connect').mockReturnValue( + mockERC20FactoryContract as any + ); + + escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.withdraw.mockResolvedValueOnce(mockTx); + + const result = await escrowClient.withdraw(escrowAddress, tokenAddress); + + expect(result).toStrictEqual({ + amountWithdrawn, + tokenAddress, + txHash: FAKE_HASH, + }); + expect(escrowClient.escrowContract.withdraw).toHaveBeenCalledWith( + tokenAddress, + {} + ); + }); + + test('should throw an error if the withdraw fails', async () => { + escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.withdraw.mockRejectedValueOnce(new Error()); + + await expect( + escrowClient.withdraw(escrowAddress, tokenAddress) + ).rejects.toThrow(); + + expect(escrowClient.escrowContract.withdraw).toHaveBeenCalledWith( + tokenAddress, + {} + ); + }); + + test('should throw an error if the wait fails', async () => { + mockTx.wait.mockRejectedValueOnce(new Error()); + escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.withdraw.mockResolvedValueOnce(mockTx); + + await expect( + escrowClient.withdraw(escrowAddress, tokenAddress) + ).rejects.toThrow(); + + expect(escrowClient.escrowContract.withdraw).toHaveBeenCalledWith( + tokenAddress, + {} + ); + }); + + test('should throw an error if transfer event not found in transaction logs', async () => { + const escrowAddress = ethers.ZeroAddress; + mockTx.wait.mockResolvedValueOnce({ + transactionHash: FAKE_HASH, + logs: [ + { + address: ethers.ZeroAddress, + name: 'NotTransfer', + args: [ethers.ZeroAddress, ethers.ZeroAddress, undefined], + }, + ], + }); + escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.withdraw.mockResolvedValueOnce(mockTx); + + const mockERC20FactoryContract = { + interface: { + parseLog: vi.fn(), + }, + }; + + vi.spyOn(ERC20__factory, 'connect').mockReturnValue( + mockERC20FactoryContract as any + ); + + await expect( + escrowClient.withdraw(escrowAddress, tokenAddress) + ).rejects.toThrow(); + + expect(escrowClient.escrowContract.withdraw).toHaveBeenCalledWith( + tokenAddress, + {} + ); + }); + + test('should successfully withdraw from escrow with transaction options', async () => { + const escrowAddress = ethers.ZeroAddress; + const amountWithdrawn = 1n; + + const log = { + address: ethers.ZeroAddress, + name: 'Transfer', + args: [ethers.ZeroAddress, ethers.ZeroAddress, amountWithdrawn], + }; + mockTx.wait.mockResolvedValueOnce({ + hash: FAKE_HASH, + logs: [log], + }); + + const mockERC20FactoryContract = { + interface: { + parseLog: vi.fn().mockReturnValueOnce(log), + }, + }; + + vi.spyOn(ERC20__factory, 'connect').mockReturnValue( + mockERC20FactoryContract as any + ); + + escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.withdraw.mockResolvedValueOnce(mockTx); + const txOptions: Overrides = { gasLimit: 45000 }; + + const result = await escrowClient.withdraw( + escrowAddress, + tokenAddress, + txOptions + ); + + expect(result).toStrictEqual({ + amountWithdrawn, + tokenAddress, + txHash: FAKE_HASH, + }); + expect(escrowClient.escrowContract.withdraw).toHaveBeenCalledWith( + tokenAddress, + txOptions + ); + }); + }); + describe('getBalance', () => { test('should throw an error if escrowAddress is an invalid address', async () => { const escrowAddress = FAKE_ADDRESS; @@ -1582,6 +1648,9 @@ describe('EscrowClient', () => { const amount = 100n; escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.remainingFunds.mockRejectedValueOnce( + new Error() + ); escrowClient.escrowContract.getBalance.mockReturnValue(amount); const balance = await escrowClient.getBalance(escrowAddress); @@ -1594,12 +1663,28 @@ describe('EscrowClient', () => { const escrowAddress = ethers.ZeroAddress; escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.remainingFunds.mockRejectedValueOnce( + new Error() + ); escrowClient.escrowContract.getBalance.mockRejectedValueOnce(new Error()); await expect(escrowClient.getBalance(escrowAddress)).rejects.toThrow(); expect(escrowClient.escrowContract.getBalance).toHaveBeenCalledWith(); }); + + test('should successfully get balance of new escrow contracts', async () => { + const escrowAddress = ethers.ZeroAddress; + const amount = 100n; + + escrowClient.escrowFactoryContract.hasEscrow.mockReturnValue(true); + escrowClient.escrowContract.remainingFunds.mockResolvedValueOnce(amount); + + const balance = await escrowClient.getBalance(escrowAddress); + + expect(balance).toEqual(amount); + expect(escrowClient.escrowContract.remainingFunds).toHaveBeenCalledWith(); + }); }); describe('getManifestHash', () => { diff --git a/packages/sdk/typescript/human-protocol-sdk/test/kvstore.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/kvstore.test.ts index 04e47d4e2c..397855e826 100644 --- a/packages/sdk/typescript/human-protocol-sdk/test/kvstore.test.ts +++ b/packages/sdk/typescript/human-protocol-sdk/test/kvstore.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Overrides, ethers } from 'ethers'; -import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NETWORKS } from '../src/constants'; import { ChainId } from '../src/enums'; import { diff --git a/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts index e66d1b1072..d4be89f1a4 100644 --- a/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts +++ b/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts @@ -39,22 +39,27 @@ describe('OperatorUtils', () => { chainId: ChainId.LOCALHOST, address: stakerAddress, amountStaked: ethers.parseEther('100'), - amountAllocated: ethers.parseEther('50'), amountLocked: ethers.parseEther('25'), lockedUntilTimestamp: ethers.toBigInt(0), amountWithdrawn: ethers.parseEther('25'), amountSlashed: ethers.parseEther('25'), - reputation: ethers.parseEther('25'), reward: ethers.parseEther('25'), amountJobsProcessed: ethers.parseEther('25'), jobTypes: 'type1,type2', registrationNeeded: true, registrationInstructions: 'www.google.com', + website: 'www.google.com', + reputationNetworks: [ + { + address: '0x01', + }, + ], }; const mockLeader: ILeader = { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2'], + reputationNetworks: ['0x01'], }; test('should return staker information', async () => { @@ -82,6 +87,7 @@ describe('OperatorUtils', () => { const mockLeader: ILeader = { ...mockLeaderSubgraph, jobTypes: [], + reputationNetworks: ['0x01'], }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ @@ -108,6 +114,7 @@ describe('OperatorUtils', () => { const mockLeader: ILeader = { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2', 'type3'], + reputationNetworks: ['0x01'], }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ @@ -175,22 +182,27 @@ describe('OperatorUtils', () => { chainId: ChainId.LOCALHOST, address: stakerAddress, amountStaked: ethers.parseEther('100'), - amountAllocated: ethers.parseEther('50'), amountLocked: ethers.parseEther('25'), lockedUntilTimestamp: ethers.toBigInt(0), amountWithdrawn: ethers.parseEther('25'), amountSlashed: ethers.parseEther('25'), - reputation: ethers.parseEther('25'), reward: ethers.parseEther('25'), amountJobsProcessed: ethers.parseEther('25'), jobTypes: 'type1,type2', registrationNeeded: true, registrationInstructions: 'www.google.com', + website: 'www.google.com', + reputationNetworks: [ + { + address: '0x01', + }, + ], }; const mockLeader: ILeader = { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2'], + reputationNetworks: ['0x01'], }; test('should return an array of stakers', async () => { @@ -216,6 +228,7 @@ describe('OperatorUtils', () => { const mockLeader: ILeader = { ...mockLeaderSubgraph, jobTypes: [], + reputationNetworks: ['0x01'], }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ @@ -240,6 +253,7 @@ describe('OperatorUtils', () => { const mockLeader: ILeader = { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2', 'type3'], + reputationNetworks: ['0x01'], }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ diff --git a/packages/sdk/typescript/human-protocol-sdk/test/staking.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/staking.test.ts index 7bd6ca591d..2b1be0e2df 100644 --- a/packages/sdk/typescript/human-protocol-sdk/test/staking.test.ts +++ b/packages/sdk/typescript/human-protocol-sdk/test/staking.test.ts @@ -11,7 +11,6 @@ import { ErrorProviderDoesNotExist, ErrorUnsupportedChainID, } from '../src/error'; -import { IAllocation } from '../src/interfaces'; import { StakingClient } from '../src/staking'; import { DEFAULT_GAS_PAYER_PRIVKEY, @@ -25,8 +24,7 @@ describe('StakingClient', () => { mockSigner: any, mockStakingContract: any, mockEscrowFactoryContract: any, - mockTokenContract: any, - mockRewardPoolContract: any; + mockTokenContract: any; beforeEach(async () => { mockProvider = { @@ -44,13 +42,8 @@ describe('StakingClient', () => { unstake: vi.fn(), withdraw: vi.fn(), slash: vi.fn(), - allocate: vi.fn(), - closeAllocation: vi.fn(), - distributeReward: vi.fn(), - getRewards: vi.fn(), getStaker: vi.fn(), getListOfStakers: vi.fn(), - getAllocation: vi.fn(), getAddress: vi.fn().mockResolvedValue(ethers.ZeroAddress), }; @@ -63,15 +56,10 @@ describe('StakingClient', () => { approve: vi.fn(), }; - mockRewardPoolContract = { - distributeReward: vi.fn(), - }; - stakingClient = await StakingClient.build(mockSigner); stakingClient.stakingContract = mockStakingContract; stakingClient.tokenContract = mockTokenContract; stakingClient.escrowFactoryContract = mockEscrowFactoryContract; - stakingClient.rewardPoolContract = mockRewardPoolContract; }); afterEach(() => { @@ -484,256 +472,4 @@ describe('StakingClient', () => { expect(slashSpy).toHaveBeenCalledTimes(1); }); }); - - describe('allocate', () => { - const amount = ethers.toBigInt(FAKE_AMOUNT); - const negativeAmount = ethers.toBigInt(FAKE_NEGATIVE_AMOUNT); - const invalidAddress = 'InvalidAddress'; - - test('throws an error if escrow address is invalid', async () => { - await expect( - stakingClient.allocate(invalidAddress, amount) - ).rejects.toThrow(ErrorInvalidEscrowAddressProvided); - expect(mockStakingContract.allocate).toHaveBeenCalledTimes(0); - }); - - test('throws an error if amount is not a bigint', async () => { - await expect( - stakingClient.allocate(ethers.ZeroAddress, 'foo') - ).rejects.toThrow(ErrorInvalidStakingValueType); - expect(mockStakingContract.allocate).toHaveBeenCalledTimes(0); - }); - - test('throws an error if amount is negative', async () => { - await expect( - stakingClient.allocate(ethers.ZeroAddress, negativeAmount) - ).rejects.toThrow(ErrorInvalidStakingValueSign); - expect(mockStakingContract.allocate).toHaveBeenCalledTimes(0); - }); - - test('throws an error if escrow address is not provided by the factory', async () => { - mockEscrowFactoryContract.hasEscrow.mockRejectedValueOnce(new Error()); - - await expect( - stakingClient.allocate(ethers.ZeroAddress, amount) - ).rejects.toThrow(); - expect(mockStakingContract.allocate).toHaveBeenCalledTimes(0); - }); - - test('should call the allocate method with the correct parameters', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - const allocateSpy = vi - .spyOn(mockStakingContract, 'allocate') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - await stakingClient.allocate(ethers.ZeroAddress, amount); - - expect(allocateSpy).toHaveBeenCalledWith(ethers.ZeroAddress, amount, {}); - expect(allocateSpy).toHaveBeenCalledTimes(1); - }); - - test('should call the allocate method with with transaction options', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - const allocateSpy = vi - .spyOn(mockStakingContract, 'allocate') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - - const txOptions: Overrides = { gasLimit: 45000 }; - - await stakingClient.allocate(ethers.ZeroAddress, amount, txOptions); - - expect(allocateSpy).toHaveBeenCalledWith( - ethers.ZeroAddress, - amount, - txOptions - ); - expect(allocateSpy).toHaveBeenCalledTimes(1); - }); - - test('should throw an error if the allocate method fails', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - mockStakingContract.allocate.mockRejectedValueOnce(new Error()); - - await expect( - stakingClient.allocate(ethers.ZeroAddress, amount) - ).rejects.toThrow(); - expect(mockStakingContract.allocate).toHaveBeenCalledWith( - ethers.ZeroAddress, - amount, - {} - ); - expect(mockStakingContract.allocate).toHaveBeenCalledTimes(1); - }); - }); - - describe('closeAllocation', () => { - const invalidAddress = 'InvalidAddress'; - - test('should throws an error if escrow address is invalid', async () => { - await expect( - stakingClient.closeAllocation(invalidAddress) - ).rejects.toThrow(ErrorInvalidEscrowAddressProvided); - expect(mockStakingContract.closeAllocation).toHaveBeenCalledTimes(0); - }); - - test('throws an error if escrow address is not provided by the factory', async () => { - mockEscrowFactoryContract.hasEscrow.mockRejectedValueOnce(new Error()); - - await expect( - stakingClient.closeAllocation(ethers.ZeroAddress) - ).rejects.toThrow(); - expect(mockStakingContract.closeAllocation).toHaveBeenCalledTimes(0); - }); - - test('should throw an error when stakingContract.closeAllocation throws an error', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - mockStakingContract.closeAllocation.mockRejectedValueOnce(new Error()); - - await expect( - stakingClient.closeAllocation(ethers.ZeroAddress) - ).rejects.toThrow(); - - expect(mockStakingContract.closeAllocation).toHaveBeenCalledWith( - ethers.ZeroAddress, - {} - ); - expect(mockStakingContract.closeAllocation).toHaveBeenCalledTimes(1); - }); - - test('should call the closeAllocation method with the correct parameters', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - const closeAllocationSpy = vi - .spyOn(mockStakingContract, 'closeAllocation') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - - await stakingClient.closeAllocation(ethers.ZeroAddress); - - expect(closeAllocationSpy).toHaveBeenCalledWith(ethers.ZeroAddress, {}); - expect(closeAllocationSpy).toHaveBeenCalledTimes(1); - }); - - test('should call the closeAllocation method with transaction options', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - const closeAllocationSpy = vi - .spyOn(mockStakingContract, 'closeAllocation') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - - const txOptions: Overrides = { gasLimit: 45000 }; - - await stakingClient.closeAllocation(ethers.ZeroAddress, txOptions); - - expect(closeAllocationSpy).toHaveBeenCalledWith( - ethers.ZeroAddress, - txOptions - ); - expect(closeAllocationSpy).toHaveBeenCalledTimes(1); - }); - }); - - describe('distributeReward', () => { - const invalidAddress = 'InvalidAddress'; - - test('should throw an error if an invalid escrow address is provided', async () => { - await expect( - stakingClient.distributeReward(invalidAddress) - ).rejects.toThrow(ErrorInvalidEscrowAddressProvided); - expect(mockRewardPoolContract.distributeReward).toHaveBeenCalledTimes(0); - }); - - test('throws an error if escrow address is not provided by the factory', async () => { - mockEscrowFactoryContract.hasEscrow.mockRejectedValueOnce(new Error()); - - await expect( - stakingClient.distributeReward(ethers.ZeroAddress) - ).rejects.toThrow(); - expect(mockRewardPoolContract.distributeReward).toHaveBeenCalledTimes(0); - }); - - test('should call distributeReward on the reward pool contract', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - const distributeRewardSpy = vi - .spyOn(mockRewardPoolContract, 'distributeReward') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - - await stakingClient.distributeReward(ethers.ZeroAddress); - - expect(distributeRewardSpy).toHaveBeenCalledWith(ethers.ZeroAddress, {}); - expect(distributeRewardSpy).toHaveBeenCalledTimes(1); - }); - - test('should call distributeReward on the reward pool contract with transaction options', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - const distributeRewardSpy = vi - .spyOn(mockRewardPoolContract, 'distributeReward') - .mockImplementation(() => ({ - wait: vi.fn().mockResolvedValue(true), - })); - - const txOptions: Overrides = { gasLimit: 45000 }; - - await stakingClient.distributeReward(ethers.ZeroAddress, txOptions); - - expect(distributeRewardSpy).toHaveBeenCalledWith( - ethers.ZeroAddress, - txOptions - ); - expect(distributeRewardSpy).toHaveBeenCalledTimes(1); - }); - }); - - describe('getAllocation', () => { - const invalidAddress = 'InvalidAddress'; - - test('should throw an error for invalid escrow address', async () => { - await expect(stakingClient.getAllocation(invalidAddress)).rejects.toThrow( - ErrorInvalidEscrowAddressProvided - ); - expect(mockStakingContract.getAllocation).toHaveBeenCalledTimes(0); - }); - - test('throws an error if escrow address is not provided by the factory', async () => { - mockEscrowFactoryContract.hasEscrow.mockRejectedValueOnce(new Error()); - - await expect( - stakingClient.getAllocation(ethers.ZeroAddress) - ).rejects.toThrow(); - expect(mockStakingContract.getAllocation).toHaveBeenCalledTimes(0); - }); - - test('should return allocation information', async () => { - const mockAllocation: IAllocation = { - escrowAddress: ethers.ZeroAddress, - staker: ethers.ZeroAddress, - tokens: ethers.parseEther('100'), - createdAt: ethers.parseEther('100'), - closedAt: ethers.parseEther('100'), - }; - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - mockStakingContract.getAllocation.mockResolvedValueOnce(mockAllocation); - - const result = await stakingClient.getAllocation(ethers.ZeroAddress); - expect(result).toEqual(mockAllocation); - expect(mockStakingContract.getAllocation).toHaveBeenCalledWith( - ethers.ZeroAddress - ); - expect(mockStakingContract.getAllocation).toHaveBeenCalledTimes(1); - }); - - test('should throw an error if the allocation data cannot be retrieved', async () => { - mockEscrowFactoryContract.hasEscrow.mockResolvedValueOnce(true); - mockStakingContract.getAllocation.mockRejectedValue(new Error()); - await expect( - stakingClient.getAllocation(ethers.ZeroAddress) - ).rejects.toThrow(); - }); - }); }); diff --git a/packages/sdk/typescript/human-protocol-sdk/test/transaction.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/transaction.test.ts index 0e40c517fc..3f32f81200 100644 --- a/packages/sdk/typescript/human-protocol-sdk/test/transaction.test.ts +++ b/packages/sdk/typescript/human-protocol-sdk/test/transaction.test.ts @@ -31,6 +31,14 @@ describe('TransactionUtils', () => { timestamp: 1625247600n, value: '1000000000000000000', method: 'transfer', + internalTransactions: [ + { + from: '0x1234567890123456789012345678901234567890', + to: '0x1234567890123456789012345678901234567891', + value: '1000000000000000000', + method: 'transfer', + }, + ], }; test('should return transaction information', async () => { @@ -74,12 +82,20 @@ describe('TransactionUtils', () => { describe('getTransactions', () => { const mockTransaction: ITransaction = { block: 12345n, - hash: '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + txHash: '0x62dD51230A30401C455c8398d06F85e4EaB6309f', from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', timestamp: 1625247600n, value: '1000000000000000000', method: 'transfer', + internalTransactions: [ + { + from: '0x1234567890123456789012345678901234567890', + to: '0x1234567890123456789012345678901234567891', + value: '1000000000000000000', + method: 'transfer', + }, + ], }; test('should return an array of transactions', async () => { diff --git a/packages/sdk/typescript/subgraph/.gitignore b/packages/sdk/typescript/subgraph/.gitignore index 2b1deccc97..88babc7c01 100644 --- a/packages/sdk/typescript/subgraph/.gitignore +++ b/packages/sdk/typescript/subgraph/.gitignore @@ -11,4 +11,6 @@ subgraph.yaml tests/.bin tests/.latest.json -src/mapping/HMToken.ts \ No newline at end of file +src/mapping/HMToken.ts +src/mapping/Staking.ts +src/mapping/Escrow.ts \ No newline at end of file diff --git a/packages/sdk/typescript/subgraph/config/amoy.json b/packages/sdk/typescript/subgraph/config/amoy.json index d8b4763b87..7023315ca3 100644 --- a/packages/sdk/typescript/subgraph/config/amoy.json +++ b/packages/sdk/typescript/subgraph/config/amoy.json @@ -22,8 +22,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/KVStore.json" }, "Staking": { - "address": "0xCc0AF0635aa19fE799B6aFDBe28fcFAeA7f00a60", - "startBlock": 5772993, + "address": "0xffE496683F842a923110415b7278ded3F265f2C5", + "startBlock": 14983952, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "RewardPool": { diff --git a/packages/sdk/typescript/subgraph/config/bsc-testnet.json b/packages/sdk/typescript/subgraph/config/bsc-testnet.json index 20fa6d9f9e..dd113230df 100644 --- a/packages/sdk/typescript/subgraph/config/bsc-testnet.json +++ b/packages/sdk/typescript/subgraph/config/bsc-testnet.json @@ -17,8 +17,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/Escrow.json" }, "Staking": { - "address": "0x5517fE916Fe9F8dB15B0DDc76ebDf0BdDCd4ed18", - "startBlock": 26716357, + "address": "0xD6D347ba6987519B4e42EcED43dF98eFf5465a23", + "startBlock": 45938762, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "KVStore": { diff --git a/packages/sdk/typescript/subgraph/config/sepolia.json b/packages/sdk/typescript/subgraph/config/sepolia.json index 1facf4293f..77edb312d6 100644 --- a/packages/sdk/typescript/subgraph/config/sepolia.json +++ b/packages/sdk/typescript/subgraph/config/sepolia.json @@ -2,8 +2,8 @@ "network": "sepolia", "description": "HUMAN subgraph on Sepolia Ethereum Testnet", "EscrowFactory": { - "address": "0xD6D347ba6987519B4e42EcED43dF98eFf5465a23", - "startBlock": 5716237, + "address": "0x5987A5558d961ee674efe4A8c8eB7B1b5495D3bf", + "startBlock": 7067993, "abi": "../../../../node_modules/@human-protocol/core/abis/EscrowFactory.json" }, "HMToken": { @@ -22,8 +22,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/KVStore.json" }, "Staking": { - "address": "0x2B9C5EC6220BA8Ad08CB51A60FFdbC6a6235B203", - "startBlock": 5716235, + "address": "0x2163e3A40032Af1C359ac731deaB48258b317890", + "startBlock": 7062708, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "RewardPool": { diff --git a/packages/sdk/typescript/subgraph/package.json b/packages/sdk/typescript/subgraph/package.json index 59ca899a8c..74d5aaf44e 100644 --- a/packages/sdk/typescript/subgraph/package.json +++ b/packages/sdk/typescript/subgraph/package.json @@ -6,8 +6,10 @@ "generated" ], "scripts": { - "generate": "mustache ./config/$NETWORK.json template.yaml > subgraph.yaml && yarn generate-hmt && graph codegen", + "generate": "mustache ./config/$NETWORK.json template.yaml > subgraph.yaml && yarn generate-escrow && yarn generate-hmt && yarn generate-staking && graph codegen", + "generate-escrow": "mustache ./config/$NETWORK.json src/mapping/EscrowTemplate.ts > src/mapping/Escrow.ts", "generate-hmt": "mustache ./config/$NETWORK.json src/mapping/HMTokenTemplate.ts > src/mapping/HMToken.ts", + "generate-staking": "mustache ./config/$NETWORK.json src/mapping/StakingTemplate.ts > src/mapping/Staking.ts", "codegen": "graph codegen", "build": "graph build", "pretest": "NETWORK=polygon yarn generate", diff --git a/packages/sdk/typescript/subgraph/schema.graphql b/packages/sdk/typescript/subgraph/schema.graphql index 4198c463f9..06f6b3773e 100644 --- a/packages/sdk/typescript/subgraph/schema.graphql +++ b/packages/sdk/typescript/subgraph/schema.graphql @@ -33,12 +33,10 @@ type Leader @entity { id: Bytes! address: Bytes! amountStaked: BigInt! - amountAllocated: BigInt! amountLocked: BigInt! lockedUntilTimestamp: BigInt! amountWithdrawn: BigInt! amountSlashed: BigInt! - reputation: BigInt! reward: BigInt! amountJobsProcessed: BigInt! @@ -46,10 +44,11 @@ type Leader @entity { fee: BigInt publicKey: String webhookUrl: String + website: String jobTypes: [String!] url: String urls: [LeaderURL!]! @derivedFrom(field: "leader") - reputationNetwork: ReputationNetwork + reputationNetworks: [ReputationNetwork!] registrationNeeded: Boolean registrationInstructions: String } @@ -64,7 +63,7 @@ type LeaderURL @entity { type ReputationNetwork @entity { id: Bytes! address: Bytes! - operators: [Leader!]! @derivedFrom(field: "reputationNetwork") + operators: [Leader!]! @derivedFrom(field: "reputationNetworks") } type Escrow @entity { @@ -73,6 +72,7 @@ type Escrow @entity { token: Bytes! # address factoryAddress: Bytes! # address launcher: Bytes! # address + canceler: Bytes! # address count: BigInt! balance: BigInt! totalFundedAmount: BigInt! @@ -163,7 +163,7 @@ type FundEvent @entity(immutable: true) { amount: BigInt! } -type SetupEvent @entity(immutable: true) { +type PendingEvent @entity(immutable: true) { id: Bytes! block: BigInt! timestamp: BigInt! @@ -208,6 +208,19 @@ type EscrowStatusEvent @entity(immutable: true) { status: String! } +type WithdrawEvent @entity(immutable: true) { + id: Bytes! + block: BigInt! + timestamp: BigInt! + txHash: Bytes! + + escrowAddress: Bytes! # address + sender: Bytes! # address + receiver: Bytes! # address + token: Bytes! # address + amount: BigInt! +} + # KVStore type KVStoreSetEvent @entity(immutable: true) { id: Bytes! @@ -269,42 +282,7 @@ type StakeSlashedEvent @entity(immutable: true) { escrowAddress: Bytes! # address staker: Bytes! # address - slasher: Bytes! # address - amount: BigInt! -} - -type StakeAllocatedEvent @entity(immutable: true) { - id: Bytes! - block: BigInt! - timestamp: BigInt! - txHash: Bytes! - - escrowAddress: Bytes! # address - staker: Bytes! # address - amount: BigInt! -} - -type AllocationClosedEvent @entity(immutable: true) { - id: Bytes! - block: BigInt! - timestamp: BigInt! - txHash: Bytes! - - escrowAddress: Bytes! # address - staker: Bytes! # address - amount: BigInt! -} - -# RewardPool -type RewardAddedEvent @entity(immutable: true) { - id: Bytes! - block: BigInt! - timestamp: BigInt! - txHash: Bytes! - - escrowAddress: Bytes! # address - staker: Bytes! # address - slasher: Bytes # address + slashRequester: Bytes! # address amount: BigInt! } @@ -325,7 +303,6 @@ type HMTokenStatistics @entity { type EscrowStatistics @entity { id: Bytes! fundEventCount: BigInt! - setupEventCount: BigInt! storeResultsEventCount: BigInt! bulkPayoutEventCount: BigInt! pendingStatusEventCount: BigInt! @@ -341,7 +318,6 @@ type EventDayData @entity { id: Bytes! timestamp: Int! dailyFundEventCount: BigInt! - dailySetupEventCount: BigInt! dailyStoreResultsEventCount: BigInt! dailyBulkPayoutEventCount: BigInt! dailyPendingStatusEventCount: BigInt! @@ -365,13 +341,30 @@ type LeaderStatistics @entity { leaders: BigInt! } -type Transaction @entity(immutable: true) { +type Transaction @entity { id: Bytes! block: BigInt! timestamp: BigInt! txHash: Bytes! from: Bytes! - to: Bytes - value: BigInt + to: Bytes! + receiver: Bytes + escrow: Bytes + value: BigInt! + method: String! + token: Bytes + internalTransactions: [InternalTransaction!] + @derivedFrom(field: "transaction") +} + +type InternalTransaction @entity { + id: Bytes! + from: Bytes! + to: Bytes! + receiver: Bytes + escrow: Bytes + value: BigInt! + token: Bytes method: String! + transaction: Transaction! } diff --git a/packages/sdk/typescript/subgraph/src/mapping/Escrow.ts b/packages/sdk/typescript/subgraph/src/mapping/Escrow.ts deleted file mode 100644 index 0030b23c47..0000000000 --- a/packages/sdk/typescript/subgraph/src/mapping/Escrow.ts +++ /dev/null @@ -1,355 +0,0 @@ -import { - BulkTransfer, - Cancelled, - Completed, - Escrow as EscrowContract, - IntermediateStorage, - Pending, -} from '../../generated/templates/Escrow/Escrow'; -import { - BulkPayoutEvent, - Escrow, - EscrowStatistics, - EscrowStatusEvent, - SetupEvent, - StoreResultsEvent, - Worker, -} from '../../generated/schema'; -import { Address, BigInt, dataSource } from '@graphprotocol/graph-ts'; -import { ZERO_BI, ONE_BI } from './utils/number'; -import { toEventId } from './utils/event'; -import { getEventDayData } from './utils/dayUpdates'; -import { createTransaction } from './utils/transaction'; -import { toBytes } from './utils/string'; -import { createOrLoadLeader } from './Staking'; - -export const STATISTICS_ENTITY_ID = toBytes('escrow-statistics-id'); - -function constructStatsEntity(): EscrowStatistics { - const entity = new EscrowStatistics(STATISTICS_ENTITY_ID); - - entity.fundEventCount = ZERO_BI; - entity.setupEventCount = ZERO_BI; - entity.storeResultsEventCount = ZERO_BI; - entity.bulkPayoutEventCount = ZERO_BI; - entity.pendingStatusEventCount = ZERO_BI; - entity.cancelledStatusEventCount = ZERO_BI; - entity.partialStatusEventCount = ZERO_BI; - entity.paidStatusEventCount = ZERO_BI; - entity.completedStatusEventCount = ZERO_BI; - entity.totalEventCount = ZERO_BI; - entity.totalEscrowCount = ZERO_BI; - - return entity; -} - -export function createOrLoadEscrowStatistics(): EscrowStatistics { - let statsEntity = EscrowStatistics.load(STATISTICS_ENTITY_ID); - - if (!statsEntity) { - statsEntity = constructStatsEntity(); - } - - return statsEntity; -} - -export function createOrLoadWorker(address: Address): Worker { - let worker = Worker.load(address); - - if (!worker) { - worker = new Worker(address); - worker.address = address; - worker.totalAmountReceived = ZERO_BI; - worker.payoutCount = ZERO_BI; - } - - return worker; -} - -export function handlePending(event: Pending): void { - createTransaction(event, 'setup'); - // Create SetupEvent entity - const setupEventEntity = new SetupEvent(toEventId(event)); - setupEventEntity.block = event.block.number; - setupEventEntity.timestamp = event.block.timestamp; - setupEventEntity.txHash = event.transaction.hash; - setupEventEntity.escrowAddress = event.address; - setupEventEntity.sender = event.transaction.from; - setupEventEntity.save(); - - // Create EscrowStatusEvent entity - const statusEventEntity = new EscrowStatusEvent(toEventId(event)); - statusEventEntity.block = event.block.number; - statusEventEntity.timestamp = event.block.timestamp; - statusEventEntity.txHash = event.transaction.hash; - statusEventEntity.escrowAddress = event.address; - statusEventEntity.sender = event.transaction.from; - statusEventEntity.status = 'Pending'; - - // Updates escrow statistics - const statsEntity = createOrLoadEscrowStatistics(); - statsEntity.setupEventCount = statsEntity.setupEventCount.plus(ONE_BI); - statsEntity.pendingStatusEventCount = - statsEntity.pendingStatusEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus( - ONE_BI.plus(ONE_BI) - ); - statsEntity.save(); - - // Update event day data - const eventDayData = getEventDayData(event); - eventDayData.dailySetupEventCount = - eventDayData.dailySetupEventCount.plus(ONE_BI); - eventDayData.dailyPendingStatusEventCount = - eventDayData.dailyPendingStatusEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = eventDayData.dailyTotalEventCount.plus( - ONE_BI.plus(ONE_BI) - ); - - // Update escrow entity - const escrowEntity = Escrow.load(dataSource.address()); - if (escrowEntity) { - escrowEntity.manifestUrl = event.params.manifest; - escrowEntity.manifestHash = event.params.hash; - escrowEntity.status = 'Pending'; - - // Read data on-chain - const escrowContract = EscrowContract.bind(event.address); - - const reputationOracle = escrowContract.try_reputationOracle(); - if (!reputationOracle.reverted) { - escrowEntity.reputationOracle = reputationOracle.value; - } - - const recordingOracle = escrowContract.try_recordingOracle(); - if (!recordingOracle.reverted) { - escrowEntity.recordingOracle = recordingOracle.value; - } - - const exchangeOracle = escrowContract.try_exchangeOracle(); - if (!exchangeOracle.reverted) { - escrowEntity.exchangeOracle = exchangeOracle.value; - } - - escrowEntity.save(); - statusEventEntity.launcher = escrowEntity.launcher; - } - statusEventEntity.save(); - - // Increase amount of jobs processed by leader - if (escrowEntity) { - if (escrowEntity.reputationOracle) { - const reputationOracleLeader = createOrLoadLeader( - Address.fromBytes(escrowEntity.reputationOracle!) - ); - reputationOracleLeader.amountJobsProcessed = - reputationOracleLeader.amountJobsProcessed.plus(ONE_BI); - reputationOracleLeader.save(); - } - - if (escrowEntity.recordingOracle) { - const recordingOracleLeader = createOrLoadLeader( - Address.fromBytes(escrowEntity.recordingOracle!) - ); - recordingOracleLeader.amountJobsProcessed = - recordingOracleLeader.amountJobsProcessed.plus(ONE_BI); - recordingOracleLeader.save(); - } - - if (escrowEntity.exchangeOracle) { - const exchangeOracleLeader = createOrLoadLeader( - Address.fromBytes(escrowEntity.exchangeOracle!) - ); - exchangeOracleLeader.amountJobsProcessed = - exchangeOracleLeader.amountJobsProcessed.plus(ONE_BI); - exchangeOracleLeader.save(); - } - } -} - -export function handleIntermediateStorage(event: IntermediateStorage): void { - createTransaction(event, 'storeResults'); - // Create StoreResultsEvent entity - const eventEntity = new StoreResultsEvent(toEventId(event)); - eventEntity.block = event.block.number; - eventEntity.timestamp = event.block.timestamp; - eventEntity.txHash = event.transaction.hash; - eventEntity.escrowAddress = event.address; - eventEntity.sender = event.transaction.from; - eventEntity.intermediateResultsUrl = event.params._url; - eventEntity.save(); - - // Updates escrow statistics - const statsEntity = createOrLoadEscrowStatistics(); - statsEntity.storeResultsEventCount = - statsEntity.storeResultsEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); - statsEntity.save(); - - // Update event day data - const eventDayData = getEventDayData(event); - eventDayData.dailyStoreResultsEventCount = - eventDayData.dailyStoreResultsEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = - eventDayData.dailyTotalEventCount.plus(ONE_BI); - eventDayData.save(); - - // Update escrow entity - const escrowEntity = Escrow.load(dataSource.address()); - if (escrowEntity) { - escrowEntity.intermediateResultsUrl = event.params._url; - escrowEntity.save(); - } -} - -export function handleBulkTransfer(event: BulkTransfer): void { - createTransaction(event, 'bulkTransfer'); - // Create BulkPayoutEvent entity - const eventEntity = new BulkPayoutEvent(toEventId(event)); - eventEntity.block = event.block.number; - eventEntity.timestamp = event.block.timestamp; - eventEntity.txHash = event.transaction.hash; - eventEntity.escrowAddress = event.address; - eventEntity.sender = event.transaction.from; - eventEntity.bulkPayoutTxId = event.params._txId; - eventEntity.bulkCount = BigInt.fromI32(event.params._recipients.length); - eventEntity.save(); - - // Update escrow statistics - const statsEntity = createOrLoadEscrowStatistics(); - statsEntity.bulkPayoutEventCount = - statsEntity.bulkPayoutEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); - - // Update event day data - const eventDayData = getEventDayData(event); - eventDayData.dailyBulkPayoutEventCount = - eventDayData.dailyBulkPayoutEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = - eventDayData.dailyTotalEventCount.plus(ONE_BI); - - // Create EscrowStatusEvent entity - const statusEventEntity = new EscrowStatusEvent(toEventId(event)); - statusEventEntity.block = event.block.number; - statusEventEntity.timestamp = event.block.timestamp; - statusEventEntity.txHash = event.transaction.hash; - statusEventEntity.escrowAddress = event.address; - statusEventEntity.sender = event.transaction.from; - - // Update escrow entity - const escrowEntity = Escrow.load(dataSource.address()); - if (escrowEntity) { - escrowEntity.status = event.params._isPartial ? 'Partial' : 'Paid'; - - // Read data on-chain - const escrowContract = EscrowContract.bind(event.address); - const finalResultsUrl = escrowContract.try_finalResultsUrl(); - if (!finalResultsUrl.reverted) { - escrowEntity.finalResultsUrl = finalResultsUrl.value; - } - - escrowEntity.save(); - statusEventEntity.launcher = escrowEntity.launcher; - } - - if (event.params._isPartial) { - statusEventEntity.status = 'Partial'; - - statsEntity.partialStatusEventCount = - statsEntity.partialStatusEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); - - eventDayData.dailyPartialStatusEventCount = - eventDayData.dailyPartialStatusEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = - eventDayData.dailyTotalEventCount.plus(ONE_BI); - } else { - statusEventEntity.status = 'Paid'; - - statsEntity.paidStatusEventCount = - statsEntity.paidStatusEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); - - eventDayData.dailyPaidStatusEventCount = - eventDayData.dailyPaidStatusEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = - eventDayData.dailyTotalEventCount.plus(ONE_BI); - } - - // Save statistics, and event day data - statsEntity.save(); - eventDayData.save(); - statusEventEntity.save(); -} - -export function handleCancelled(event: Cancelled): void { - createTransaction(event, 'cancel'); - // Create EscrowStatusEvent entity - const eventEntity = new EscrowStatusEvent(toEventId(event)); - eventEntity.block = event.block.number; - eventEntity.timestamp = event.block.timestamp; - eventEntity.txHash = event.transaction.hash; - eventEntity.escrowAddress = event.address; - eventEntity.sender = event.transaction.from; - eventEntity.status = 'Cancelled'; - - // Update statistics - const statsEntity = createOrLoadEscrowStatistics(); - statsEntity.cancelledStatusEventCount = - statsEntity.cancelledStatusEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); - statsEntity.save(); - - // Update event day data - const eventDayData = getEventDayData(event); - eventDayData.dailyCancelledStatusEventCount = - eventDayData.dailyCancelledStatusEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = - eventDayData.dailyTotalEventCount.plus(ONE_BI); - eventDayData.save(); - - // Update escrow entity - const escrowEntity = Escrow.load(dataSource.address()); - if (escrowEntity) { - escrowEntity.status = 'Cancelled'; - escrowEntity.save(); - eventEntity.launcher = escrowEntity.launcher; - } - eventEntity.save(); -} - -export function handleCompleted(event: Completed): void { - createTransaction(event, 'complete'); - // Create EscrowStatusEvent entity - const eventEntity = new EscrowStatusEvent(toEventId(event)); - eventEntity.block = event.block.number; - eventEntity.timestamp = event.block.timestamp; - eventEntity.txHash = event.transaction.hash; - eventEntity.escrowAddress = event.address; - eventEntity.sender = event.transaction.from; - eventEntity.status = 'Complete'; - - // Update statistics - const statsEntity = createOrLoadEscrowStatistics(); - statsEntity.completedStatusEventCount = - statsEntity.completedStatusEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); - statsEntity.save(); - - // Update event day data - const eventDayData = getEventDayData(event); - eventDayData.dailyCompletedStatusEventCount = - eventDayData.dailyCompletedStatusEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = - eventDayData.dailyTotalEventCount.plus(ONE_BI); - eventDayData.save(); - - // Update escrow entity - const escrowEntity = Escrow.load(dataSource.address()); - if (escrowEntity) { - escrowEntity.status = 'Complete'; - escrowEntity.save(); - eventEntity.launcher = escrowEntity.launcher; - } - eventEntity.save(); -} diff --git a/packages/sdk/typescript/subgraph/src/mapping/EscrowFactory.ts b/packages/sdk/typescript/subgraph/src/mapping/EscrowFactory.ts index 29481090d9..4e17b7fabc 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/EscrowFactory.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/EscrowFactory.ts @@ -10,9 +10,17 @@ import { createTransaction } from './utils/transaction'; import { getEventDayData } from './utils/dayUpdates'; import { toEventId } from './utils/event'; import { ONE_BI, ZERO_BI } from './utils/number'; +import { dataSource } from '@graphprotocol/graph-ts'; export function handleLaunched(event: Launched): void { - createTransaction(event, 'createEscrow'); + createTransaction( + event, + 'createEscrow', + event.transaction.from, + dataSource.address(), + null, + event.params.escrow + ); // Create LaunchedStatusEvent entity const statusEventEntity = new EscrowStatusEvent(toEventId(event)); statusEventEntity.block = event.block.number; @@ -32,6 +40,7 @@ export function handleLaunched(event: Launched): void { entity.token = event.params.token; entity.factoryAddress = event.address; entity.launcher = event.transaction.from; + entity.canceler = event.transaction.from; entity.balance = ZERO_BI; entity.amountPaid = ZERO_BI; @@ -62,7 +71,14 @@ export function handleLaunched(event: Launched): void { } export function handleLaunchedV2(event: LaunchedV2): void { - createTransaction(event, 'createEscrow'); + createTransaction( + event, + 'createEscrow', + event.transaction.from, + dataSource.address(), + null, + event.params.escrow + ); // Create Escrow entity const entity = new Escrow(event.params.escrow); @@ -72,6 +88,7 @@ export function handleLaunchedV2(event: LaunchedV2): void { entity.jobRequesterId = event.params.jobRequesterId; entity.factoryAddress = event.address; entity.launcher = event.transaction.from; + entity.canceler = event.transaction.from; entity.balance = ZERO_BI; entity.amountPaid = ZERO_BI; diff --git a/packages/sdk/typescript/subgraph/src/mapping/EscrowTemplate.ts b/packages/sdk/typescript/subgraph/src/mapping/EscrowTemplate.ts new file mode 100644 index 0000000000..96401c0237 --- /dev/null +++ b/packages/sdk/typescript/subgraph/src/mapping/EscrowTemplate.ts @@ -0,0 +1,735 @@ +import { + BulkTransfer, + BulkTransferV2, + Cancelled, + Completed, + Escrow as EscrowContract, + IntermediateStorage, + Pending, + Fund, + PendingV2, + Withdraw, +} from '../../generated/templates/Escrow/Escrow'; +import { + BulkPayoutEvent, + Escrow, + EscrowStatistics, + EscrowStatusEvent, + FundEvent, + PendingEvent, + StoreResultsEvent, + Worker, + Payout, + DailyWorker, + InternalTransaction, + WithdrawEvent, +} from '../../generated/schema'; +import { + Address, + BigInt, + Bytes, + dataSource, + ethereum, +} from '@graphprotocol/graph-ts'; +import { ZERO_BI, ONE_BI } from './utils/number'; +import { toEventDayId, toEventId } from './utils/event'; +import { getEventDayData } from './utils/dayUpdates'; +import { createTransaction } from './utils/transaction'; +import { toBytes } from './utils/string'; +import { createOrLoadLeader } from './Staking'; + +export const HMT_ADDRESS = Address.fromString('{{ HMToken.address }}'); +export const STATISTICS_ENTITY_ID = toBytes('escrow-statistics-id'); + +function constructStatsEntity(): EscrowStatistics { + const entity = new EscrowStatistics(STATISTICS_ENTITY_ID); + + entity.fundEventCount = ZERO_BI; + entity.storeResultsEventCount = ZERO_BI; + entity.bulkPayoutEventCount = ZERO_BI; + entity.pendingStatusEventCount = ZERO_BI; + entity.cancelledStatusEventCount = ZERO_BI; + entity.partialStatusEventCount = ZERO_BI; + entity.paidStatusEventCount = ZERO_BI; + entity.completedStatusEventCount = ZERO_BI; + entity.totalEventCount = ZERO_BI; + entity.totalEscrowCount = ZERO_BI; + + return entity; +} + +export function createOrLoadEscrowStatistics(): EscrowStatistics { + let statsEntity = EscrowStatistics.load(STATISTICS_ENTITY_ID); + + if (!statsEntity) { + statsEntity = constructStatsEntity(); + } + + return statsEntity; +} + +export function createOrLoadWorker(address: Address): Worker { + let worker = Worker.load(address); + + if (!worker) { + worker = new Worker(address); + worker.address = address; + worker.totalAmountReceived = ZERO_BI; + worker.payoutCount = ZERO_BI; + } + + return worker; +} + +// Update statistics +function updateStatisticsForPending(): void { + const statsEntity = createOrLoadEscrowStatistics(); + statsEntity.pendingStatusEventCount = + statsEntity.pendingStatusEventCount.plus(ONE_BI); + statsEntity.totalEventCount = statsEntity.totalEventCount.plus( + ONE_BI.plus(ONE_BI) + ); + statsEntity.save(); +} + +// Update event day data +function updateEventDayDataForPending(event: ethereum.Event): void { + const eventDayData = getEventDayData(event); + eventDayData.dailyPendingStatusEventCount = + eventDayData.dailyPendingStatusEventCount.plus(ONE_BI); + eventDayData.dailyTotalEventCount = eventDayData.dailyTotalEventCount.plus( + ONE_BI.plus(ONE_BI) + ); + eventDayData.save(); +} + +// Create common event entities +function createCommonEntitiesForPending( + event: ethereum.Event, + status: string +): EscrowStatusEvent { + // Create pendingEvent entity + const pendingEventEntity = new PendingEvent(toEventId(event)); + pendingEventEntity.block = event.block.number; + pendingEventEntity.timestamp = event.block.timestamp; + pendingEventEntity.txHash = event.transaction.hash; + pendingEventEntity.escrowAddress = event.address; + pendingEventEntity.sender = event.transaction.from; + pendingEventEntity.save(); + + // Create EscrowStatusEvent entity + const statusEventEntity = new EscrowStatusEvent(toEventId(event)); + statusEventEntity.block = event.block.number; + statusEventEntity.timestamp = event.block.timestamp; + statusEventEntity.txHash = event.transaction.hash; + statusEventEntity.escrowAddress = event.address; + statusEventEntity.sender = event.transaction.from; + statusEventEntity.status = status; + statusEventEntity.save(); + + return statusEventEntity; +} + +// Update escrow entity +function updateEscrowEntityForPending( + escrowEntity: Escrow, + escrowStatusEvent: EscrowStatusEvent, + manifestUrl: string, + manifestHash: string, + reputationOracle: Address | null = null, + recordingOracle: Address | null = null, + exchangeOracle: Address | null = null +): void { + escrowEntity.manifestUrl = manifestUrl; + escrowEntity.manifestHash = manifestHash; + escrowEntity.status = 'Pending'; + + // Update oracles if provided + if (reputationOracle) { + escrowEntity.reputationOracle = reputationOracle; + } + + if (recordingOracle) { + escrowEntity.recordingOracle = recordingOracle; + } + + if (exchangeOracle) { + escrowEntity.exchangeOracle = exchangeOracle; + } + + escrowEntity.save(); + + // Increase amount of jobs processed by leader + if (escrowEntity.reputationOracle) { + const reputationOracleLeader = createOrLoadLeader( + Address.fromBytes(escrowEntity.reputationOracle!) + ); + reputationOracleLeader.amountJobsProcessed = + reputationOracleLeader.amountJobsProcessed.plus(ONE_BI); + reputationOracleLeader.save(); + } + + if (escrowEntity.recordingOracle) { + const recordingOracleLeader = createOrLoadLeader( + Address.fromBytes(escrowEntity.recordingOracle!) + ); + recordingOracleLeader.amountJobsProcessed = + recordingOracleLeader.amountJobsProcessed.plus(ONE_BI); + recordingOracleLeader.save(); + } + + if (escrowEntity.exchangeOracle) { + const exchangeOracleLeader = createOrLoadLeader( + Address.fromBytes(escrowEntity.exchangeOracle!) + ); + exchangeOracleLeader.amountJobsProcessed = + exchangeOracleLeader.amountJobsProcessed.plus(ONE_BI); + exchangeOracleLeader.save(); + } + escrowStatusEvent.launcher = escrowEntity.launcher; + escrowStatusEvent.save(); +} + +export function handlePending(event: Pending): void { + // Create common entities for setup and status + const escrowStatusEvent = createCommonEntitiesForPending(event, 'Pending'); + + // Update statistics + updateStatisticsForPending(); + + // Update event day data + updateEventDayDataForPending(event); + + // Update escrow entity + const escrowEntity = Escrow.load(dataSource.address()); + if (escrowEntity) { + // Read data on-chain + const escrowContract = EscrowContract.bind(event.address); + + const reputationOracle = escrowContract.try_reputationOracle(); + const recordingOracle = escrowContract.try_recordingOracle(); + const exchangeOracle = escrowContract.try_exchangeOracle(); + + updateEscrowEntityForPending( + escrowEntity, + escrowStatusEvent, + event.params.manifest, + event.params.hash, + !reputationOracle.reverted ? reputationOracle.value : null, + !recordingOracle.reverted ? recordingOracle.value : null, + !exchangeOracle.reverted ? exchangeOracle.value : null + ); + + createTransaction( + event, + 'setup', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); + } +} + +export function handlePendingV2(event: PendingV2): void { + // Create common entities for setup and status + const escrowStatusEvent = createCommonEntitiesForPending(event, 'Pending'); + + // Update statistics + updateStatisticsForPending(); + + // Update event day data + updateEventDayDataForPending(event); + + // Update escrow entity + const escrowEntity = Escrow.load(dataSource.address()); + if (escrowEntity) { + updateEscrowEntityForPending( + escrowEntity, + escrowStatusEvent, + event.params.manifest, + event.params.hash, + event.params.reputationOracle, + event.params.recordingOracle, + event.params.exchangeOracle + ); + + createTransaction( + event, + 'setup', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); + } +} + +export function handleIntermediateStorage(event: IntermediateStorage): void { + // Create StoreResultsEvent entity + const eventEntity = new StoreResultsEvent(toEventId(event)); + eventEntity.block = event.block.number; + eventEntity.timestamp = event.block.timestamp; + eventEntity.txHash = event.transaction.hash; + eventEntity.escrowAddress = event.address; + eventEntity.sender = event.transaction.from; + eventEntity.intermediateResultsUrl = event.params._url; + eventEntity.save(); + + // Updates escrow statistics + const statsEntity = createOrLoadEscrowStatistics(); + statsEntity.storeResultsEventCount = + statsEntity.storeResultsEventCount.plus(ONE_BI); + statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); + statsEntity.save(); + + // Update event day data + const eventDayData = getEventDayData(event); + eventDayData.dailyStoreResultsEventCount = + eventDayData.dailyStoreResultsEventCount.plus(ONE_BI); + eventDayData.dailyTotalEventCount = + eventDayData.dailyTotalEventCount.plus(ONE_BI); + eventDayData.save(); + + // Update escrow entity + const escrowEntity = Escrow.load(dataSource.address()); + if (escrowEntity) { + escrowEntity.intermediateResultsUrl = event.params._url; + escrowEntity.save(); + createTransaction( + event, + 'storeResults', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); + } +} + +// Create BulkPayoutEvent entity +function createBulkPayoutEvent( + event: ethereum.Event, + txId: BigInt, + recipientsLength: number +): void { + const eventEntity = new BulkPayoutEvent(toEventId(event)); + eventEntity.block = event.block.number; + eventEntity.timestamp = event.block.timestamp; + eventEntity.txHash = event.transaction.hash; + eventEntity.escrowAddress = event.address; + eventEntity.sender = event.transaction.from; + eventEntity.bulkPayoutTxId = txId; + eventEntity.bulkCount = BigInt.fromI32(recipientsLength); + eventEntity.save(); +} + +// Update escrow statistics +function updateEscrowStatisticsForBulkTransfer(isPartial: boolean): void { + const statsEntity = createOrLoadEscrowStatistics(); + statsEntity.bulkPayoutEventCount = + statsEntity.bulkPayoutEventCount.plus(ONE_BI); + statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); + + if (isPartial) { + statsEntity.partialStatusEventCount = + statsEntity.partialStatusEventCount.plus(ONE_BI); + } else { + statsEntity.paidStatusEventCount = + statsEntity.paidStatusEventCount.plus(ONE_BI); + } + + statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); + statsEntity.save(); +} + +// Update event day data +function updateEventDayDataForBulkTransfer( + event: ethereum.Event, + isPartial: boolean +): void { + const eventDayData = getEventDayData(event); + eventDayData.dailyBulkPayoutEventCount = + eventDayData.dailyBulkPayoutEventCount.plus(ONE_BI); + eventDayData.dailyTotalEventCount = + eventDayData.dailyTotalEventCount.plus(ONE_BI); + + if (isPartial) { + eventDayData.dailyPartialStatusEventCount = + eventDayData.dailyPartialStatusEventCount.plus(ONE_BI); + } else { + eventDayData.dailyPaidStatusEventCount = + eventDayData.dailyPaidStatusEventCount.plus(ONE_BI); + } + + eventDayData.dailyTotalEventCount = + eventDayData.dailyTotalEventCount.plus(ONE_BI); + eventDayData.save(); +} + +// Create and save EscrowStatusEvent entity +function createAndSaveStatusEventForBulkTransfer( + event: ethereum.Event, + status: string, + escrowEntity: Escrow | null +): void { + const statusEventEntity = new EscrowStatusEvent(toEventId(event)); + statusEventEntity.block = event.block.number; + statusEventEntity.timestamp = event.block.timestamp; + statusEventEntity.txHash = event.transaction.hash; + statusEventEntity.escrowAddress = event.address; + statusEventEntity.sender = event.transaction.from; + statusEventEntity.status = status; + + if (escrowEntity) { + statusEventEntity.launcher = escrowEntity.launcher; + } + + statusEventEntity.save(); +} + +// Update escrow entity +function updateEscrowEntityForBulkTransfer( + escrowEntity: Escrow, + isPartial: boolean, + finalResultsUrl: string | null +): void { + escrowEntity.status = isPartial ? 'Partial' : 'Paid'; + + if (finalResultsUrl) { + escrowEntity.finalResultsUrl = finalResultsUrl; + } + + escrowEntity.save(); +} + +export function handleBulkTransfer(event: BulkTransfer): void { + // Create BulkPayoutEvent entity + createBulkPayoutEvent( + event, + event.params._txId, + event.params._recipients.length + ); + + // Update escrow statistics + updateEscrowStatisticsForBulkTransfer(event.params._isPartial); + + // Update event day data + updateEventDayDataForBulkTransfer(event, event.params._isPartial); + + // Update escrow entity + const escrowEntity = Escrow.load(dataSource.address()); + if (escrowEntity) { + // Read data on-chain + const escrowContract = EscrowContract.bind(event.address); + const finalResultsUrl = escrowContract.try_finalResultsUrl(); + + updateEscrowEntityForBulkTransfer( + escrowEntity, + event.params._isPartial, + !finalResultsUrl.reverted ? finalResultsUrl.value : null + ); + + // Create and save EscrowStatusEvent entity + createAndSaveStatusEventForBulkTransfer( + event, + escrowEntity.status, + escrowEntity + ); + + createTransaction( + event, + 'bulkTransfer', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); + } +} + +export function handleBulkTransferV2(event: BulkTransferV2): void { + // Create BulkPayoutEvent entity + createBulkPayoutEvent( + event, + event.params._txId, + event.params._recipients.length + ); + + // Update escrow statistics + updateEscrowStatisticsForBulkTransfer(event.params._isPartial); + + // Update event day data + updateEventDayDataForBulkTransfer(event, event.params._isPartial); + + // Update escrow entity + const escrowEntity = Escrow.load(dataSource.address()); + if (escrowEntity !== null) { + // If the escrow is non-HMT, track the balance data + if (Address.fromBytes(escrowEntity.token) != HMT_ADDRESS) { + for (let i = 0; i < event.params._recipients.length; i++) { + const recipient = event.params._recipients[i]; + const amount = event.params._amounts[i]; + + escrowEntity.amountPaid = escrowEntity.amountPaid.plus(amount); + escrowEntity.balance = escrowEntity.balance.minus(amount); + + // Update worker, and create payout object + const worker = createOrLoadWorker(recipient); + worker.totalAmountReceived = worker.totalAmountReceived.plus(amount); + worker.payoutCount = worker.payoutCount.plus(ONE_BI); + worker.save(); + + const payoutId = event.transaction.hash.concat(recipient); + const payment = new Payout(payoutId); + payment.escrowAddress = event.address; + payment.recipient = recipient; + payment.amount = amount; + payment.createdAt = event.block.timestamp; + payment.save(); + + // Update event day data and daily worker + const eventDayData = getEventDayData(event); + eventDayData.dailyPayoutCount = + eventDayData.dailyPayoutCount.plus(ONE_BI); + eventDayData.dailyPayoutAmount = + eventDayData.dailyPayoutAmount.plus(amount); + + const eventDayId = toEventDayId(event); + const dailyWorkerId = Bytes.fromI32(eventDayId.toI32()).concat( + recipient + ); + + let dailyWorker = DailyWorker.load(dailyWorkerId); + if (!dailyWorker) { + dailyWorker = new DailyWorker(dailyWorkerId); + dailyWorker.timestamp = eventDayId; + dailyWorker.address = recipient; + dailyWorker.escrowAddress = event.address; + dailyWorker.save(); + + eventDayData.dailyWorkerCount = + eventDayData.dailyWorkerCount.plus(ONE_BI); + } + + const transaction = createTransaction( + event, + 'bulkTransfer', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.token) + ); + + // Create a transfer per recipient and amount + for (let i = 0; i < event.params._recipients.length; i++) { + const recipient = event.params._recipients[i]; + const amount = event.params._amounts[i]; + const internalTransaction = new InternalTransaction( + event.transaction.hash + .concatI32(i) + .concatI32(event.block.timestamp.toI32()) + ); + internalTransaction.from = Address.fromBytes(escrowEntity.address); + internalTransaction.to = recipient; + internalTransaction.value = amount; + internalTransaction.transaction = transaction.id; + internalTransaction.method = 'transfer'; + internalTransaction.escrow = Address.fromBytes(escrowEntity.address); + internalTransaction.save(); + } + + eventDayData.save(); + } + } + + // Assign finalResultsUrl directly from the event + updateEscrowEntityForBulkTransfer( + escrowEntity, + event.params._isPartial, + event.params.finalResultsUrl + ); + + // Create and save EscrowStatusEvent entity + createAndSaveStatusEventForBulkTransfer( + event, + escrowEntity.status, + escrowEntity + ); + } +} + +export function handleCancelled(event: Cancelled): void { + // Create EscrowStatusEvent entity + const eventEntity = new EscrowStatusEvent(toEventId(event)); + eventEntity.block = event.block.number; + eventEntity.timestamp = event.block.timestamp; + eventEntity.txHash = event.transaction.hash; + eventEntity.escrowAddress = event.address; + eventEntity.sender = event.transaction.from; + eventEntity.status = 'Cancelled'; + + // Update statistics + const statsEntity = createOrLoadEscrowStatistics(); + statsEntity.cancelledStatusEventCount = + statsEntity.cancelledStatusEventCount.plus(ONE_BI); + statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); + statsEntity.save(); + + // Update event day data + const eventDayData = getEventDayData(event); + eventDayData.dailyCancelledStatusEventCount = + eventDayData.dailyCancelledStatusEventCount.plus(ONE_BI); + eventDayData.dailyTotalEventCount = + eventDayData.dailyTotalEventCount.plus(ONE_BI); + eventDayData.save(); + + // Update escrow entity + const escrowEntity = Escrow.load(dataSource.address()); + + if (escrowEntity) { + const transaction = createTransaction( + event, + 'cancel', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); + if (Address.fromBytes(escrowEntity.token) != HMT_ADDRESS) { + // If escrow is funded with HMT, balance is already tracked by HMT transfer + const internalTransaction = new InternalTransaction(toEventId(event)); + internalTransaction.from = escrowEntity.address; + internalTransaction.to = Address.fromBytes(escrowEntity.token); + internalTransaction.receiver = escrowEntity.canceler; + internalTransaction.value = escrowEntity.balance; + internalTransaction.transaction = transaction.id; + internalTransaction.method = 'transfer'; + internalTransaction.token = Address.fromBytes(escrowEntity.token); + internalTransaction.save(); + escrowEntity.balance = ZERO_BI; + } + escrowEntity.status = 'Cancelled'; + escrowEntity.save(); + eventEntity.launcher = escrowEntity.launcher; + } + eventEntity.save(); +} + +export function handleCompleted(event: Completed): void { + // Create EscrowStatusEvent entity + const eventEntity = new EscrowStatusEvent(toEventId(event)); + eventEntity.block = event.block.number; + eventEntity.timestamp = event.block.timestamp; + eventEntity.txHash = event.transaction.hash; + eventEntity.escrowAddress = event.address; + eventEntity.sender = event.transaction.from; + eventEntity.status = 'Complete'; + + // Update statistics + const statsEntity = createOrLoadEscrowStatistics(); + statsEntity.completedStatusEventCount = + statsEntity.completedStatusEventCount.plus(ONE_BI); + statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); + statsEntity.save(); + + // Update event day data + const eventDayData = getEventDayData(event); + eventDayData.dailyCompletedStatusEventCount = + eventDayData.dailyCompletedStatusEventCount.plus(ONE_BI); + eventDayData.dailyTotalEventCount = + eventDayData.dailyTotalEventCount.plus(ONE_BI); + eventDayData.save(); + + // Update escrow entity + const escrowEntity = Escrow.load(dataSource.address()); + if (escrowEntity) { + escrowEntity.status = 'Complete'; + escrowEntity.save(); + eventEntity.launcher = escrowEntity.launcher; + + createTransaction( + event, + 'complete', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); + } + eventEntity.save(); +} + +export function handleFund(event: Fund): void { + const escrowEntity = Escrow.load(dataSource.address()); + + if (!escrowEntity) { + return; + } + + // Create FundEvent entity + const fundEventEntity = new FundEvent(toEventId(event)); + fundEventEntity.block = event.block.number; + fundEventEntity.timestamp = event.block.timestamp; + fundEventEntity.txHash = event.transaction.hash; + fundEventEntity.escrowAddress = event.address; + fundEventEntity.sender = event.transaction.from; + fundEventEntity.amount = event.params._amount; + fundEventEntity.save(); + + // Update escrow statistics + const statsEntity = createOrLoadEscrowStatistics(); + statsEntity.fundEventCount = statsEntity.fundEventCount.plus(ONE_BI); + statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); + statsEntity.save(); + + // Update event day data + const eventDayData = getEventDayData(event); + eventDayData.dailyFundEventCount = + eventDayData.dailyFundEventCount.plus(ONE_BI); + eventDayData.dailyTotalEventCount = + eventDayData.dailyTotalEventCount.plus(ONE_BI); + eventDayData.save(); + + // Update escrow entity + escrowEntity.totalFundedAmount = event.params._amount; + + if (escrowEntity.token != HMT_ADDRESS) { + escrowEntity.balance = event.params._amount; + } + + escrowEntity.save(); +} + +export function handleWithdraw(event: Withdraw): void { + const escrowEntity = Escrow.load(dataSource.address()); + + if (!escrowEntity) { + return; + } + + createTransaction( + event, + 'withdraw', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + event.transaction.from, + Address.fromBytes(escrowEntity.address), + event.params._amount, + event.params._token + ); + + // Crear entidad WithdrawEvent similar a FundEvent + const withdrawEventEntity = new WithdrawEvent(toEventId(event)); + withdrawEventEntity.block = event.block.number; + withdrawEventEntity.timestamp = event.block.timestamp; + withdrawEventEntity.txHash = event.transaction.hash; + withdrawEventEntity.escrowAddress = event.address; + withdrawEventEntity.sender = event.transaction.from; + withdrawEventEntity.receiver = escrowEntity.canceler; + withdrawEventEntity.amount = event.params._amount; + withdrawEventEntity.token = event.params._token; + withdrawEventEntity.save(); +} diff --git a/packages/sdk/typescript/subgraph/src/mapping/HMTokenTemplate.ts b/packages/sdk/typescript/subgraph/src/mapping/HMTokenTemplate.ts index aa44cae521..d1cc7b519b 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/HMTokenTemplate.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/HMTokenTemplate.ts @@ -1,4 +1,4 @@ -import { Address, BigInt, Bytes } from '@graphprotocol/graph-ts'; +import { Address, BigInt, Bytes, dataSource } from '@graphprotocol/graph-ts'; import { Approval, @@ -9,7 +9,6 @@ import { import { DailyWorker, Escrow, - FundEvent, HMTApprovalEvent, HMTBulkApprovalEvent, HMTBulkTransferEvent, @@ -22,7 +21,7 @@ import { } from '../../generated/schema'; import { toEventDayId, toEventId } from './utils/event'; import { ONE_BI, ONE_DAY, ZERO_BI } from './utils/number'; -import { createOrLoadEscrowStatistics, createOrLoadWorker } from './Escrow'; +import { createOrLoadWorker } from './Escrow'; import { getEventDayData } from './utils/dayUpdates'; import { createTransaction } from './utils/transaction'; import { toBytes } from './utils/string'; @@ -152,38 +151,34 @@ export function handleTransfer(event: Transfer): void { const eventDayData = getEventDayData(event); const escrow = Escrow.load(event.params._to); if (escrow) { - // Create FundEvent entity - const fundEventEntity = new FundEvent(toEventId(event)); - fundEventEntity.block = event.block.number; - fundEventEntity.timestamp = event.block.timestamp; - fundEventEntity.txHash = event.transaction.hash; - fundEventEntity.escrowAddress = escrow.address; - fundEventEntity.sender = event.params._from; - fundEventEntity.amount = event.params._value; - fundEventEntity.save(); - - // Update escrow statistics - const statsEntity = createOrLoadEscrowStatistics(); - statsEntity.fundEventCount = statsEntity.fundEventCount.plus(ONE_BI); - statsEntity.totalEventCount = statsEntity.totalEventCount.plus(ONE_BI); - statsEntity.save(); - - // Update event day data - eventDayData.dailyFundEventCount = - eventDayData.dailyFundEventCount.plus(ONE_BI); - eventDayData.dailyTotalEventCount = - eventDayData.dailyTotalEventCount.plus(ONE_BI); - - // Update escrow balance, and totalFundedAmount + // Update escrow balance escrow.balance = escrow.balance.plus(event.params._value); escrow.totalFundedAmount = escrow.totalFundedAmount.plus( event.params._value ); escrow.save(); - createTransaction(event, 'fund', event.params._to, event.params._value); + createTransaction( + event, + 'fund', + event.params._from, + dataSource.address(), + event.params._to, + event.params._to, + event.params._value, + dataSource.address() + ); } else { - createTransaction(event, 'transfer', event.params._to, event.params._value); + createTransaction( + event, + 'transfer', + event.params._from, + dataSource.address(), + event.params._to, + null, + event.params._value, + dataSource.address() + ); } // Update holders @@ -286,7 +281,16 @@ export function handleTransfer(event: Transfer): void { } export function handleBulkTransfer(event: BulkTransfer): void { - createTransaction(event, 'transferBulk'); + createTransaction( + event, + 'transferBulk', + event.transaction.from, + dataSource.address(), + null, + null, + null, + dataSource.address() + ); // Create HMTBulkTransferEvent entity const eventEntity = new HMTBulkTransferEvent(toEventId(event)); eventEntity.block = event.block.number; @@ -307,8 +311,12 @@ export function handleApproval(event: Approval): void { createTransaction( event, 'approve', + event.params._owner, + dataSource.address(), event.params._spender, - event.params._value + null, + event.params._value, + dataSource.address() ); // Create HMTApprovalEvent entity const eventEntity = new HMTApprovalEvent(toEventId(event)); @@ -328,7 +336,16 @@ export function handleApproval(event: Approval): void { } export function handleBulkApproval(event: BulkApproval): void { - createTransaction(event, 'increaseApprovalBulk'); + createTransaction( + event, + 'increaseApprovalBulk', + event.transaction.from, + dataSource.address(), + null, + null, + null, + dataSource.address() + ); // Create HMTBulkApprovalEvent entity const eventEntity = new HMTBulkApprovalEvent(toEventId(event)); eventEntity.block = event.block.number; diff --git a/packages/sdk/typescript/subgraph/src/mapping/KVStore.ts b/packages/sdk/typescript/subgraph/src/mapping/KVStore.ts index dc11703909..929ca3b506 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/KVStore.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/KVStore.ts @@ -9,7 +9,7 @@ import { DataSaved } from '../../generated/KVStore/KVStore'; import { createOrLoadLeader } from './Staking'; import { toEventId } from './utils/event'; import { isValidEthAddress } from './utils/ethAdrress'; -import { Address, BigInt } from '@graphprotocol/graph-ts'; +import { Address, BigInt, Bytes, dataSource } from '@graphprotocol/graph-ts'; import { createTransaction } from './utils/transaction'; import { toBytes } from './utils/string'; @@ -58,7 +58,7 @@ export function createOrUpdateKVStore(event: DataSaved): void { } export function handleDataSaved(event: DataSaved): void { - createTransaction(event, 'set'); + createTransaction(event, 'set', event.transaction.from, dataSource.address()); // Create KVStoreSetEvent entity const eventEntity = new KVStoreSetEvent(toEventId(event)); eventEntity.block = event.block.number; @@ -84,6 +84,8 @@ export function handleDataSaved(event: DataSaved): void { leader.publicKey = event.params.value; } else if (key == 'webhookurl' || key == 'webhook_url') { leader.webhookUrl = event.params.value; + } else if (key == 'website') { + leader.website = event.params.value; } else if (key == 'url') { leader.url = event.params.value; } else if (key == 'jobtypes' || key == 'job_types') { @@ -102,11 +104,25 @@ export function handleDataSaved(event: DataSaved): void { const operator = createOrLoadLeader(ethAddress); + let reputationNetworks = operator.reputationNetworks; + if (reputationNetworks === null) { + reputationNetworks = []; + } + if (event.params.value.toLowerCase() == 'active') { - operator.reputationNetwork = reputationNetwork.id; + reputationNetworks.push(reputationNetwork.id); } else if (event.params.value.toLowerCase() == 'inactive') { - operator.reputationNetwork = null; + const filteredNetworks: Bytes[] = []; + for (let i = 0; i < reputationNetworks.length; i++) { + if (reputationNetworks[i] != reputationNetwork.id) { + filteredNetworks.push(reputationNetworks[i]); + } + } + reputationNetworks = filteredNetworks; } + + operator.reputationNetworks = reputationNetworks; + operator.save(); } else if (key == 'registration_needed') { leader.registrationNeeded = event.params.value.toLowerCase() == 'true'; diff --git a/packages/sdk/typescript/subgraph/src/mapping/RewardPool.ts b/packages/sdk/typescript/subgraph/src/mapping/RewardPool.ts deleted file mode 100644 index ce5bae0fcc..0000000000 --- a/packages/sdk/typescript/subgraph/src/mapping/RewardPool.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { RewardAddedEvent } from '../../generated/schema'; -import { RewardAdded } from '../../generated/RewardPool/RewardPool'; -import { createOrLoadLeader } from './Staking'; -import { toEventId } from './utils/event'; -import { createTransaction } from './utils/transaction'; - -export function handleRewardAdded(event: RewardAdded): void { - createTransaction(event, 'addReward'); - // Create RewardAddedEvent entity - const eventEntity = new RewardAddedEvent(toEventId(event)); - eventEntity.block = event.block.number; - eventEntity.timestamp = event.block.timestamp; - eventEntity.txHash = event.transaction.hash; - eventEntity.escrowAddress = event.params.escrowAddress; - eventEntity.staker = event.params.staker; - eventEntity.slasher = event.params.slasher; - eventEntity.amount = event.params.tokens; - eventEntity.save(); - - // Update leader - const leader = createOrLoadLeader(event.params.slasher); - leader.reward = leader.reward.plus(eventEntity.amount); - leader.save(); -} diff --git a/packages/sdk/typescript/subgraph/src/mapping/Staking.ts b/packages/sdk/typescript/subgraph/src/mapping/StakingTemplate.ts similarity index 70% rename from packages/sdk/typescript/subgraph/src/mapping/Staking.ts rename to packages/sdk/typescript/subgraph/src/mapping/StakingTemplate.ts index 63507d03d7..b2f8598c7d 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/Staking.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/StakingTemplate.ts @@ -1,28 +1,26 @@ import { - AllocationClosed, - StakeAllocated, + FeeWithdrawn, StakeDeposited, StakeLocked, StakeSlashed, StakeWithdrawn, } from '../../generated/Staking/Staking'; import { - AllocationClosedEvent, Leader, LeaderStatistics, - StakeAllocatedEvent, StakeDepositedEvent, StakeLockedEvent, StakeSlashedEvent, StakeWithdrawnEvent, } from '../../generated/schema'; -import { Address } from '@graphprotocol/graph-ts'; +import { Address, dataSource } from '@graphprotocol/graph-ts'; import { ONE_BI, ZERO_BI } from './utils/number'; import { toEventId } from './utils/event'; import { createTransaction } from './utils/transaction'; import { toBytes } from './utils/string'; export const STATISTICS_ENTITY_ID = toBytes('leader-statistics-id'); +export const TOKEN_ADDRESS = Address.fromString('{{ HMToken.address }}'); function constructStatsEntity(): LeaderStatistics { const entity = new LeaderStatistics(STATISTICS_ENTITY_ID); @@ -50,13 +48,11 @@ export function createOrLoadLeader(address: Address): Leader { leader.address = address; leader.amountStaked = ZERO_BI; - leader.amountAllocated = ZERO_BI; leader.amountLocked = ZERO_BI; leader.lockedUntilTimestamp = ZERO_BI; leader.amountSlashed = ZERO_BI; leader.amountWithdrawn = ZERO_BI; leader.reward = ZERO_BI; - leader.reputation = ZERO_BI; leader.amountJobsProcessed = ZERO_BI; } @@ -64,7 +60,16 @@ export function createOrLoadLeader(address: Address): Leader { } export function handleStakeDeposited(event: StakeDeposited): void { - createTransaction(event, 'stake', event.transaction.to, event.params.tokens); + createTransaction( + event, + 'stake', + event.params.staker, + dataSource.address(), + null, + null, + event.params.tokens, + TOKEN_ADDRESS + ); // Create StakeDepostiedEvent entity const eventEntity = new StakeDepositedEvent(toEventId(event)); eventEntity.block = event.block.number; @@ -97,8 +102,12 @@ export function handleStakeLocked(event: StakeLocked): void { createTransaction( event, 'unstake', - event.transaction.to, - event.params.tokens + event.params.staker, + dataSource.address(), + null, + null, + event.params.tokens, + TOKEN_ADDRESS ); // Create StakeLockedEvent entity const eventEntity = new StakeLockedEvent(toEventId(event)); @@ -120,9 +129,13 @@ export function handleStakeLocked(event: StakeLocked): void { export function handleStakeWithdrawn(event: StakeWithdrawn): void { createTransaction( event, - 'withdraw', - event.transaction.to, - event.params.tokens + 'stakeWithdrawn', + event.params.staker, + dataSource.address(), + null, + null, + event.params.tokens, + TOKEN_ADDRESS ); // Create StakeWithdrawnEvent entity const eventEntity = new StakeWithdrawnEvent(toEventId(event)); @@ -144,69 +157,44 @@ export function handleStakeWithdrawn(event: StakeWithdrawn): void { leader.save(); } -export function handleStakeAllocated(event: StakeAllocated): void { +export function handleStakeSlashed(event: StakeSlashed): void { createTransaction( event, - 'allocate', + 'slash', + event.params.staker, + dataSource.address(), + null, event.params.escrowAddress, - event.params.tokens + event.params.tokens, + TOKEN_ADDRESS ); - // Create StakeAllocatedEvent entity - const eventEntity = new StakeAllocatedEvent(toEventId(event)); + // Create StakeSlashedEvent entity + const eventEntity = new StakeSlashedEvent(toEventId(event)); eventEntity.block = event.block.number; eventEntity.timestamp = event.block.timestamp; eventEntity.txHash = event.transaction.hash; eventEntity.staker = event.params.staker; eventEntity.amount = event.params.tokens; eventEntity.escrowAddress = event.params.escrowAddress; + eventEntity.slashRequester = event.params.slashRequester; eventEntity.save(); // Update leader const leader = createOrLoadLeader(event.params.staker); - leader.amountAllocated = leader.amountAllocated.plus(eventEntity.amount); + leader.amountSlashed = leader.amountSlashed.plus(eventEntity.amount); + leader.amountStaked = leader.amountStaked.minus(eventEntity.amount); leader.save(); } -export function handleAllocationClosed(event: AllocationClosed): void { +export function handleFeeWithdrawn(event: FeeWithdrawn): void { createTransaction( event, - 'closeAllocation', - event.params.escrowAddress, - event.params.tokens + 'withdrawFees', + event.transaction.from, + dataSource.address(), + null, + null, + event.params.amount, + TOKEN_ADDRESS ); - // Create AllocationClosedEvent entity - const eventEntity = new AllocationClosedEvent(toEventId(event)); - eventEntity.block = event.block.number; - eventEntity.timestamp = event.block.timestamp; - eventEntity.txHash = event.transaction.hash; - eventEntity.staker = event.params.staker; - eventEntity.amount = event.params.tokens; - eventEntity.escrowAddress = event.params.escrowAddress; - eventEntity.save(); - - // Update leader - const leader = createOrLoadLeader(event.params.staker); - leader.amountAllocated = leader.amountAllocated.minus(eventEntity.amount); - leader.save(); -} - -export function handleStakeSlashed(event: StakeSlashed): void { - createTransaction(event, 'slash', event.params.slasher, event.params.tokens); - // Create StakeSlashedEvent entity - const eventEntity = new StakeSlashedEvent(toEventId(event)); - eventEntity.block = event.block.number; - eventEntity.timestamp = event.block.timestamp; - eventEntity.txHash = event.transaction.hash; - eventEntity.staker = event.params.staker; - eventEntity.amount = event.params.tokens; - eventEntity.escrowAddress = event.params.escrowAddress; - eventEntity.slasher = event.params.slasher; - eventEntity.save(); - - // Update leader - const leader = createOrLoadLeader(event.params.staker); - leader.amountSlashed = leader.amountSlashed.plus(eventEntity.amount); - leader.amountAllocated = leader.amountAllocated.minus(eventEntity.amount); - leader.amountStaked = leader.amountStaked.minus(eventEntity.amount); - leader.save(); } diff --git a/packages/sdk/typescript/subgraph/src/mapping/legacy/Escrow.ts b/packages/sdk/typescript/subgraph/src/mapping/legacy/Escrow.ts index 98beb1019e..570b5496ef 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/legacy/Escrow.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/legacy/Escrow.ts @@ -1,4 +1,4 @@ -import { dataSource } from '@graphprotocol/graph-ts'; +import { Address, dataSource } from '@graphprotocol/graph-ts'; import { BulkTransfer, @@ -9,7 +9,7 @@ import { import { BulkPayoutEvent, Escrow, - SetupEvent, + PendingEvent, StoreResultsEvent, } from '../../../generated/schema'; import { createOrLoadEscrowStatistics } from '../Escrow'; @@ -28,19 +28,17 @@ enum EscrowStatuses { } export function handlePending(event: Pending): void { - createTransaction(event, 'setup'); - // Create SetupEvent entity - const setupEventEntity = new SetupEvent(toEventId(event)); - setupEventEntity.block = event.block.number; - setupEventEntity.timestamp = event.block.timestamp; - setupEventEntity.txHash = event.transaction.hash; - setupEventEntity.escrowAddress = event.address; - setupEventEntity.sender = event.transaction.from; - setupEventEntity.save(); + // Create PendingEvent entity + const pendingEventEntity = new PendingEvent(toEventId(event)); + pendingEventEntity.block = event.block.number; + pendingEventEntity.timestamp = event.block.timestamp; + pendingEventEntity.txHash = event.transaction.hash; + pendingEventEntity.escrowAddress = dataSource.address(); + pendingEventEntity.sender = event.transaction.from; + pendingEventEntity.save(); // Updates escrow statistics const statsEntity = createOrLoadEscrowStatistics(); - statsEntity.setupEventCount = statsEntity.setupEventCount.plus(ONE_BI); statsEntity.pendingStatusEventCount = statsEntity.pendingStatusEventCount.plus(ONE_BI); statsEntity.totalEventCount = statsEntity.totalEventCount.plus( @@ -50,8 +48,6 @@ export function handlePending(event: Pending): void { // Update event day data const eventDayData = getEventDayData(event); - eventDayData.dailySetupEventCount = - eventDayData.dailySetupEventCount.plus(ONE_BI); eventDayData.dailyPendingStatusEventCount = eventDayData.dailyPendingStatusEventCount.plus(ONE_BI); eventDayData.dailyTotalEventCount = eventDayData.dailyTotalEventCount.plus( @@ -79,11 +75,19 @@ export function handlePending(event: Pending): void { } escrowEntity.save(); + + createTransaction( + event, + 'setup', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); } } export function handleIntermediateStorage(event: IntermediateStorage): void { - createTransaction(event, 'storeResults'); // Create StoreResultsEvent entity const eventEntity = new StoreResultsEvent(toEventId(event)); eventEntity.block = event.block.number; @@ -114,11 +118,19 @@ export function handleIntermediateStorage(event: IntermediateStorage): void { if (escrowEntity) { escrowEntity.intermediateResultsUrl = event.params._url; escrowEntity.save(); + + createTransaction( + event, + 'storeResults', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); } } export function handleBulkTransfer(event: BulkTransfer): void { - createTransaction(event, 'bulkTransfer'); // Create BulkPayoutEvent entity const eventEntity = new BulkPayoutEvent(toEventId(event)); eventEntity.block = event.block.number; @@ -184,6 +196,15 @@ export function handleBulkTransfer(event: BulkTransfer): void { escrowEntity.finalResultsUrl = finalResultsUrl.value; } escrowEntity.save(); + + createTransaction( + event, + 'bulkTransfer', + event.transaction.from, + Address.fromBytes(escrowEntity.address), + null, + Address.fromBytes(escrowEntity.address) + ); } // Save statistics, and event day data diff --git a/packages/sdk/typescript/subgraph/src/mapping/legacy/EscrowFactory.ts b/packages/sdk/typescript/subgraph/src/mapping/legacy/EscrowFactory.ts index 05b9432787..5eb374b630 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/legacy/EscrowFactory.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/legacy/EscrowFactory.ts @@ -6,9 +6,17 @@ import { getEventDayData } from '../utils/dayUpdates'; import { createOrLoadEscrowStatistics } from '../Escrow'; import { createOrLoadLeader } from '../Staking'; import { createTransaction } from '../utils/transaction'; +import { dataSource } from '@graphprotocol/graph-ts'; export function handleLaunched(event: Launched): void { - createTransaction(event, 'createEscrow'); + createTransaction( + event, + 'createEscrow', + event.transaction.from, + dataSource.address(), + null, + event.params.escrow + ); // Create Escrow entity const entity = new Escrow(event.params.escrow); @@ -18,6 +26,7 @@ export function handleLaunched(event: Launched): void { entity.token = event.params.eip20; entity.factoryAddress = event.address; entity.launcher = event.transaction.from; + entity.canceler = event.transaction.from; entity.balance = ZERO_BI; entity.amountPaid = ZERO_BI; diff --git a/packages/sdk/typescript/subgraph/src/mapping/utils/dayUpdates.ts b/packages/sdk/typescript/subgraph/src/mapping/utils/dayUpdates.ts index bb1abb511e..15be03ae4b 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/utils/dayUpdates.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/utils/dayUpdates.ts @@ -14,7 +14,6 @@ export function getEventDayData(event: ethereum.Event): EventDayData { eventDayData = new EventDayData(eventDayDataID); eventDayData.timestamp = dayStartTimestamp; eventDayData.dailyFundEventCount = ZERO_BI; - eventDayData.dailySetupEventCount = ZERO_BI; eventDayData.dailyStoreResultsEventCount = ZERO_BI; eventDayData.dailyBulkPayoutEventCount = ZERO_BI; eventDayData.dailyPendingStatusEventCount = ZERO_BI; diff --git a/packages/sdk/typescript/subgraph/src/mapping/utils/event.ts b/packages/sdk/typescript/subgraph/src/mapping/utils/event.ts index 670aac7fa1..e33f662619 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/utils/event.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/utils/event.ts @@ -7,6 +7,12 @@ export function toEventId(event: ethereum.Event): Bytes { .concatI32(event.block.timestamp.toI32()); } +export function toPreviousEventId(event: ethereum.Event): Bytes { + return event.transaction.hash + .concatI32(event.logIndex.toI32() - 1) + .concatI32(event.block.timestamp.toI32()); +} + export function toEventDayId(event: ethereum.Event): BigInt { const timestamp = event.block.timestamp.toI32(); const dayID = timestamp / ONE_DAY; diff --git a/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts b/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts index c7830c2a75..ecf759d749 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts @@ -1,21 +1,114 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'; -import { Transaction } from '../../../generated/schema'; +import { Transaction, InternalTransaction } from '../../../generated/schema'; +import { toEventId, toPreviousEventId } from './event'; + +const mainMethods: string[] = [ + 'createEscrow', + 'setup', + 'fund', + 'bulkTransfer', + 'storeResults', + 'withdraw', + 'cancel', + 'stake', + 'unstake', + 'slash', + 'stakeWithdrawn', + 'withdrawFees', + 'approve', +]; export function createTransaction( event: ethereum.Event, method: string, - to: Address | null = null, - value: BigInt | null = null -): void { - const transaction = new Transaction(event.transaction.hash); + from: Address, + to: Address, + receiver: Address | null = null, + escrow: Address | null = null, + value: BigInt | null = null, + token: Address | null = null +): Transaction { + let transaction = Transaction.load(event.transaction.hash); + if (transaction == null) { + transaction = new Transaction(event.transaction.hash); + transaction.txHash = event.transaction.hash; + transaction.block = event.block.number; + transaction.timestamp = event.block.timestamp; + transaction.from = from; + transaction.to = event.transaction.to!; + + if ( + Address.fromBytes(transaction.to) != to && + (escrow === null || Address.fromBytes(transaction.to) != escrow) && + (token === null || Address.fromBytes(transaction.to) != token) + ) { + transaction.method = 'multimethod'; + transaction.value = BigInt.fromI32(0); + transaction.token = null; + transaction.escrow = null; + + const internalTransaction = new InternalTransaction(toEventId(event)); + internalTransaction.method = method; + internalTransaction.from = from; + internalTransaction.to = to; + internalTransaction.value = value !== null ? value : BigInt.fromI32(0); + internalTransaction.transaction = transaction.txHash; + internalTransaction.token = token; + internalTransaction.escrow = escrow; + internalTransaction.receiver = receiver; + internalTransaction.save(); + } else { + transaction.to = to; + transaction.method = method; + transaction.value = value !== null ? value : BigInt.fromI32(0); + transaction.token = token; + transaction.escrow = escrow; + transaction.receiver = receiver; + } + transaction.save(); + } else if ( + mainMethods.includes(method) && + Address.fromBytes(transaction.to) == to + ) { + transaction.method = method; + transaction.value = value !== null ? value : BigInt.fromI32(0); + transaction.token = token; + transaction.escrow = escrow; + transaction.receiver = receiver; + transaction.save(); + } else { + if ( + transaction.method == 'set' && + method == 'set' && + transaction.to == to + ) { + const internalTransaction = new InternalTransaction( + toPreviousEventId(event) + ); + internalTransaction.method = transaction.method; + internalTransaction.from = transaction.from; + internalTransaction.to = transaction.to; + internalTransaction.value = transaction.value; + internalTransaction.transaction = transaction.txHash; + internalTransaction.save(); + + transaction.method = 'setBulk'; + transaction.save(); + } - transaction.from = event.transaction.from; - transaction.to = to !== null ? to : event.transaction.to; - transaction.txHash = event.transaction.hash; - transaction.block = event.block.number; - transaction.timestamp = event.block.timestamp; - transaction.value = value !== null ? value : event.transaction.value; - transaction.method = method; + const internalTransaction = new InternalTransaction(toEventId(event)); + internalTransaction.method = method; + internalTransaction.from = from; + internalTransaction.to = to; + internalTransaction.value = + value !== null ? value : event.transaction.value; + internalTransaction.transaction = transaction.txHash; + internalTransaction.token = token; + internalTransaction.escrow = escrow; + internalTransaction.receiver = receiver; + internalTransaction.save(); + } - transaction.save(); + return transaction; } diff --git a/packages/sdk/typescript/subgraph/template.yaml b/packages/sdk/typescript/subgraph/template.yaml index 475c12ebe0..5b38f4ebe6 100644 --- a/packages/sdk/typescript/subgraph/template.yaml +++ b/packages/sdk/typescript/subgraph/template.yaml @@ -21,9 +21,9 @@ dataSources: - name: EscrowFactory file: '{{{ EscrowFactory.abi }}}' eventHandlers: - - event: Launched(address,address) + - event: Launched(indexed address,indexed address) handler: handleLaunched - - event: LaunchedV2(address,address,string) + - event: LaunchedV2(indexed address,indexed address,string) handler: handleLaunchedV2 - kind: ethereum name: HMToken @@ -90,8 +90,6 @@ dataSources: - StakeLocked - StakeWithdrawn - StakeSlashed - - StakeAllocated - - AllocationClosed abis: - name: Staking file: '{{{ Staking.abi }}}' @@ -104,31 +102,9 @@ dataSources: handler: handleStakeWithdrawn - event: StakeSlashed(indexed address,uint256,indexed address,address) handler: handleStakeSlashed - - event: StakeAllocated(indexed address,uint256,indexed address,uint256) - handler: handleStakeAllocated - - event: AllocationClosed(indexed address,uint256,indexed address,uint256) - handler: handleAllocationClosed + - event: FeeWithdrawn(uint256) + handler: handleFeeWithdrawn file: ./src/mapping/Staking.ts - - kind: ethereum - name: RewardPool - network: '{{ network }}' - source: - abi: RewardPool - address: '{{ RewardPool.address }}' - startBlock: {{ RewardPool.startBlock }} - mapping: - kind: ethereum/events - apiVersion: 0.0.7 - language: wasm/assemblyscript - entities: - - RewardAdded - abis: - - name: RewardPool - file: '{{{ RewardPool.abi }}}' - eventHandlers: - - event: RewardAdded(indexed address,indexed address,indexed address,uint256) - handler: handleRewardAdded - file: ./src/mapping/RewardPool.ts {{ #LegacyEscrowFactory }} - kind: ethereum name: LegacyEscrowFactory @@ -175,12 +151,20 @@ templates: handler: handleIntermediateStorage - event: Pending(string,string) handler: handlePending + - event: PendingV2(string,string,address,address,address) + handler: handlePendingV2 - event: BulkTransfer(indexed uint256,address[],uint256[],bool) handler: handleBulkTransfer + - event: BulkTransferV2(indexed uint256,address[],uint256[],bool,string) + handler: handleBulkTransfer - event: Cancelled() handler: handleCancelled - event: Completed() handler: handleCompleted + - event: Fund(uint256) + handler: handleFund + - event: Withdraw(address,uint256) + handler: handleWithdraw - name: LegacyEscrow kind: ethereum/contract network: '{{ network }}' diff --git a/packages/sdk/typescript/subgraph/tests/escrow-factory/escrow-factory.test.ts b/packages/sdk/typescript/subgraph/tests/escrow-factory/escrow-factory.test.ts index 47fb2693b2..2249062dcd 100644 --- a/packages/sdk/typescript/subgraph/tests/escrow-factory/escrow-factory.test.ts +++ b/packages/sdk/typescript/subgraph/tests/escrow-factory/escrow-factory.test.ts @@ -1,10 +1,12 @@ -import { Address, BigInt } from '@graphprotocol/graph-ts'; +import { Address, BigInt, DataSourceContext } from '@graphprotocol/graph-ts'; import { describe, test, assert, clearStore, afterAll, + dataSourceMock, + beforeAll, } from 'matchstick-as/assembly'; import { STATISTICS_ENTITY_ID } from '../../src/mapping/Escrow'; @@ -18,12 +20,19 @@ const launcherAddressString = '0x92a2eef7ff696bcef98957a0189872680600a959'; const launcherAddress = Address.fromString(launcherAddressString); const tokenAddressString = '0xd979105297fb0eee83f7433fc09279cb5b94ffc4'; const tokenAddress = Address.fromString(tokenAddressString); -const escrow1AddressString = '0xd979105297fb0eee83f7433fc09279cb5b94ffc6'; +const escrow1AddressString = '0xd979105297fb0eee83f7475fc09279cb5b94ffc6'; const escrow1Address = Address.fromString(escrow1AddressString); const escrow2AddressString = '0xd979105297fb0eee83f7433fc09279cb5b94ffc7'; const escrow2Address = Address.fromString(escrow2AddressString); describe('EscrowFactory', () => { + beforeAll(() => { + dataSourceMock.setReturnValues( + factoryAddressString, + 'rinkeby', + new DataSourceContext() + ); + }); afterAll(() => { clearStore(); }); @@ -226,5 +235,11 @@ describe('EscrowFactory', () => { 'from', data2.transaction.from.toHex() ); + assert.fieldEquals( + 'Transaction', + data2.transaction.hash.toHex(), + 'to', + factoryAddressString + ); }); }); diff --git a/packages/sdk/typescript/subgraph/tests/escrow-factory/fixtures.ts b/packages/sdk/typescript/subgraph/tests/escrow-factory/fixtures.ts index 30d6b42f2d..4673d3412f 100644 --- a/packages/sdk/typescript/subgraph/tests/escrow-factory/fixtures.ts +++ b/packages/sdk/typescript/subgraph/tests/escrow-factory/fixtures.ts @@ -1,7 +1,8 @@ import { newMockEvent } from 'matchstick-as/assembly/index'; -import { ethereum, BigInt, Address } from '@graphprotocol/graph-ts'; +import { ethereum, BigInt, Address, dataSource } from '@graphprotocol/graph-ts'; import { Launched } from '../../generated/EscrowFactory/EscrowFactory'; +import { generateUniqueHash } from '../../tests/utils'; export function createLaunchedEvent( factory: Address, @@ -11,9 +12,17 @@ export function createLaunchedEvent( timestamp: BigInt ): Launched { const newLaunchedEvent = changetype(newMockEvent()); + newLaunchedEvent.transaction.hash = generateUniqueHash( + escrow.toString(), + timestamp, + newLaunchedEvent.transaction.nonce + ); newLaunchedEvent.block.timestamp = timestamp; newLaunchedEvent.transaction.from = launcher; + newLaunchedEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); newLaunchedEvent.address = factory; newLaunchedEvent.parameters = []; diff --git a/packages/sdk/typescript/subgraph/tests/escrow/escrow.test.ts b/packages/sdk/typescript/subgraph/tests/escrow/escrow.test.ts index b2976d5f25..ec6c1e8324 100644 --- a/packages/sdk/typescript/subgraph/tests/escrow/escrow.test.ts +++ b/packages/sdk/typescript/subgraph/tests/escrow/escrow.test.ts @@ -24,6 +24,10 @@ import { handleBulkTransfer, handleCancelled, handleCompleted, + handleFund, + handlePendingV2, + handleBulkTransferV2, + handleWithdraw, } from '../../src/mapping/Escrow'; import { toEventId } from '../../src/mapping/utils/event'; import { ZERO_BI } from '../../src/mapping/utils/number'; @@ -33,6 +37,10 @@ import { createBulkTransferEvent, createCancelledEvent, createCompletedEvent, + createFundEvent, + createPendingV2Event, + createBulkTransferV2Event, + createWithdrawEvent, } from './fixtures'; const escrowAddressString = '0xa16081f360e3847006db660bae1c6d1b2e17ec2a'; @@ -56,6 +64,8 @@ const exchangeOracleAddressString = const exchangeOracleAddress = Address.fromString(exchangeOracleAddressString); const launcherAddressString = '0x15d34aaf54267db7d7c367839aaf71a00a2c6a65'; const launcherAddress = Address.fromString(launcherAddressString); +const tokenAddressString = '0x15d34aaf54267db7d7c367839aaf71a00a2c6a62'; +const tokenAddress = Address.fromString(tokenAddressString); describe('Escrow', () => { beforeAll(() => { @@ -86,12 +96,13 @@ describe('Escrow', () => { escrow.token = Address.zero(); escrow.factoryAddress = Address.zero(); escrow.launcher = launcherAddress; + escrow.canceler = launcherAddress; escrow.count = ZERO_BI; - escrow.balance = BigInt.fromI32(100); - escrow.totalFundedAmount = BigInt.fromI32(100); + escrow.balance = ZERO_BI; + escrow.totalFundedAmount = ZERO_BI; escrow.amountPaid = ZERO_BI; escrow.status = 'Launched'; - escrow.createdAt = BigInt.fromI32(0); + escrow.createdAt = ZERO_BI; escrow.save(); }); @@ -116,27 +127,32 @@ describe('Escrow', () => { const id = toEventId(newPending1).toHex(); - // SetupEvent + // PendingEvent assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'block', newPending1.block.number.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'timestamp', newPending1.block.timestamp.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'txHash', newPending1.transaction.hash.toHex() ); - assert.fieldEquals('SetupEvent', id, 'escrowAddress', escrowAddressString); - assert.fieldEquals('SetupEvent', id, 'sender', operatorAddressString); + assert.fieldEquals( + 'PendingEvent', + id, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('PendingEvent', id, 'sender', operatorAddressString); // EscrowStatusEvent assert.fieldEquals( @@ -225,7 +241,7 @@ describe('Escrow', () => { ); }); - test('Should properly handle Pending event for new contract, without exchange oracle', () => { + test('Should properly handle Pending event for old event, without exchange oracle', () => { const URL = 'test.com'; const HASH = 'is_hash_1'; @@ -241,27 +257,32 @@ describe('Escrow', () => { const id = toEventId(newPending1).toHex(); - // SetupEvent + // PendingEvent assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'block', newPending1.block.number.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'timestamp', newPending1.block.timestamp.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'txHash', newPending1.transaction.hash.toHex() ); - assert.fieldEquals('SetupEvent', id, 'escrowAddress', escrowAddressString); - assert.fieldEquals('SetupEvent', id, 'sender', operatorAddressString); + assert.fieldEquals( + 'PendingEvent', + id, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('PendingEvent', id, 'sender', operatorAddressString); // EscrowStatusEvent assert.fieldEquals( @@ -367,7 +388,7 @@ describe('Escrow', () => { ); }); - test('Should properly handle Pending event for new contract, with exchange oracle', () => { + test('Should properly handle Pending event for old event, with exchange oracle', () => { const URL = 'test.com'; const HASH = 'is_hash_1'; @@ -383,27 +404,32 @@ describe('Escrow', () => { const id = toEventId(newPending1).toHex(); - // SetupEvent + // PendingEvent assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'block', newPending1.block.number.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'timestamp', newPending1.block.timestamp.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'txHash', newPending1.transaction.hash.toHex() ); - assert.fieldEquals('SetupEvent', id, 'escrowAddress', escrowAddressString); - assert.fieldEquals('SetupEvent', id, 'sender', operatorAddressString); + assert.fieldEquals( + 'PendingEvent', + id, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('PendingEvent', id, 'sender', operatorAddressString); // EscrowStatusEvent assert.fieldEquals( @@ -520,6 +546,211 @@ describe('Escrow', () => { ); }); + test('Should properly handle Fund event', () => { + const fund = createFundEvent(operatorAddress, 100, BigInt.fromI32(10)); + + handleFund(fund); + + const id = toEventId(fund).toHex(); + + // FundEvent + assert.fieldEquals('FundEvent', id, 'block', fund.block.number.toString()); + assert.fieldEquals( + 'FundEvent', + id, + 'timestamp', + fund.block.timestamp.toString() + ); + assert.fieldEquals( + 'FundEvent', + id, + 'txHash', + fund.transaction.hash.toHex() + ); + assert.fieldEquals('FundEvent', id, 'escrowAddress', escrowAddressString); + assert.fieldEquals('FundEvent', id, 'sender', operatorAddressString); + assert.fieldEquals('FundEvent', id, 'amount', '100'); + + // Escrow + assert.fieldEquals('Escrow', escrowAddressString, 'balance', '100'); + assert.fieldEquals( + 'Escrow', + escrowAddressString, + 'totalFundedAmount', + '100' + ); + }); + + test('Should skip Fund event if balance is greater than 0', () => { + const fund = createFundEvent(operatorAddress, 100, BigInt.fromI32(10)); + + handleFund(fund); + + // Escrow + assert.fieldEquals('Escrow', escrowAddressString, 'balance', '100'); + assert.fieldEquals( + 'Escrow', + escrowAddressString, + 'totalFundedAmount', + '100' + ); + }); + + test('Should properly handle Pending event for new event', () => { + const URL = 'test.com'; + const HASH = 'is_hash_1'; + + const newPending1 = createPendingV2Event( + operatorAddress, + URL, + HASH, + reputationOracleAddress, + recordingOracleAddress, + exchangeOracleAddress + ); + + handlePendingV2(newPending1); + + const id = toEventId(newPending1).toHex(); + + // PendingEvent + assert.fieldEquals( + 'PendingEvent', + id, + 'block', + newPending1.block.number.toString() + ); + assert.fieldEquals( + 'PendingEvent', + id, + 'timestamp', + newPending1.block.timestamp.toString() + ); + assert.fieldEquals( + 'PendingEvent', + id, + 'txHash', + newPending1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'PendingEvent', + id, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('PendingEvent', id, 'sender', operatorAddressString); + + // EscrowStatusEvent + assert.fieldEquals( + 'EscrowStatusEvent', + id, + 'block', + newPending1.block.number.toString() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id, + 'timestamp', + newPending1.block.timestamp.toString() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id, + 'txHash', + newPending1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id, + 'sender', + operatorAddressString + ); + assert.fieldEquals('EscrowStatusEvent', id, 'status', 'Pending'); + assert.fieldEquals( + 'EscrowStatusEvent', + id, + 'launcher', + launcherAddressString + ); + + // Escrow + assert.fieldEquals('Escrow', escrowAddress.toHex(), 'status', 'Pending'); + assert.fieldEquals('Escrow', escrowAddress.toHex(), 'manifestUrl', URL); + assert.fieldEquals('Escrow', escrowAddress.toHex(), 'manifestHash', HASH); + assert.fieldEquals( + 'Escrow', + escrowAddress.toHex(), + 'reputationOracle', + reputationOracleAddressString + ); + + assert.fieldEquals( + 'Escrow', + escrowAddress.toHex(), + 'recordingOracle', + recordingOracleAddressString + ); + + assert.fieldEquals( + 'Transaction', + newPending1.transaction.hash.toHex(), + 'txHash', + newPending1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'Transaction', + newPending1.transaction.hash.toHex(), + 'method', + 'setup' + ); + assert.fieldEquals( + 'Transaction', + newPending1.transaction.hash.toHex(), + 'block', + newPending1.block.number.toString() + ); + assert.fieldEquals( + 'Transaction', + newPending1.transaction.hash.toHex(), + 'from', + newPending1.transaction.from.toHex() + ); + assert.fieldEquals( + 'Transaction', + newPending1.transaction.hash.toHex(), + 'to', + escrowAddressString + ); + + // Leader + assert.fieldEquals( + 'Leader', + reputationOracleAddressString, + 'amountJobsProcessed', + '4' + ); + + assert.fieldEquals( + 'Leader', + recordingOracleAddressString, + 'amountJobsProcessed', + '4' + ); + + assert.fieldEquals( + 'Leader', + exchangeOracleAddressString, + 'amountJobsProcessed', + '2' + ); + }); + test('should properly handle IntermediateStorage event', () => { const URL = 'test.com'; const newIS = createISEvent(workerAddress, URL, 'is_hash_1'); @@ -601,7 +832,7 @@ describe('Escrow', () => { const id1 = toEventId(bulk1).toHex(); - // BulkPayoutEvent + // BulkPayoutEvent; assert.fieldEquals( 'BulkPayoutEvent', id1, @@ -761,6 +992,219 @@ describe('Escrow', () => { 'finalResultsUrl', 'test.com' ); + + assert.fieldEquals( + 'Transaction', + bulk1.transaction.hash.toHex(), + 'txHash', + bulk1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'Transaction', + bulk1.transaction.hash.toHex(), + 'method', + 'bulkTransfer' + ); + assert.fieldEquals( + 'Transaction', + bulk1.transaction.hash.toHex(), + 'block', + bulk1.block.number.toString() + ); + assert.fieldEquals( + 'Transaction', + bulk1.transaction.hash.toHex(), + 'from', + bulk1.transaction.from.toHex() + ); + assert.fieldEquals( + 'Transaction', + bulk1.transaction.hash.toHex(), + 'to', + escrowAddressString + ); + }); + + test('Should properly handle BulkTransferV2 events', () => { + // Bulk 1 + const bulk1 = createBulkTransferV2Event( + operatorAddress, + 1, + [workerAddress, workerAddress], + [1, 1], + true, + 'test.com', + BigInt.fromI32(10) + ); + + handleBulkTransferV2(bulk1); + + const id1 = toEventId(bulk1).toHex(); + + // BulkPayoutEvent + assert.fieldEquals( + 'BulkPayoutEvent', + id1, + 'block', + bulk1.block.number.toString() + ); + assert.fieldEquals( + 'BulkPayoutEvent', + id1, + 'timestamp', + bulk1.block.timestamp.toString() + ); + assert.fieldEquals( + 'BulkPayoutEvent', + id1, + 'txHash', + bulk1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'BulkPayoutEvent', + id1, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('BulkPayoutEvent', id1, 'sender', operatorAddressString); + assert.fieldEquals('BulkPayoutEvent', id1, 'bulkPayoutTxId', '1'); + assert.fieldEquals('BulkPayoutEvent', id1, 'bulkCount', '2'); + + // EscrowStatusEvent + assert.fieldEquals( + 'EscrowStatusEvent', + id1, + 'block', + bulk1.block.number.toString() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id1, + 'timestamp', + bulk1.block.timestamp.toString() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id1, + 'txHash', + bulk1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id1, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id1, + 'sender', + operatorAddressString + ); + assert.fieldEquals('EscrowStatusEvent', id1, 'status', 'Partial'); + assert.fieldEquals( + 'EscrowStatusEvent', + id1, + 'launcher', + launcherAddressString + ); + + // Escrow + assert.fieldEquals('Escrow', escrowAddress.toHex(), 'status', 'Partial'); + assert.fieldEquals('Escrow', escrowAddress.toHex(), 'balance', '98'); + + // Bulk 2 + const bulk2 = createBulkTransferV2Event( + operatorAddress, + 3, + [workerAddress, workerAddress, workerAddress, worker2Address], + [1, 1, 1, 95], + false, + 'test.com', + BigInt.fromI32(11) + ); + + handleBulkTransferV2(bulk2); + + const id2 = toEventId(bulk2).toHex(); + + assert.fieldEquals( + 'BulkPayoutEvent', + id2, + 'block', + bulk2.block.number.toString() + ); + assert.fieldEquals( + 'BulkPayoutEvent', + id2, + 'timestamp', + bulk2.block.timestamp.toString() + ); + assert.fieldEquals( + 'BulkPayoutEvent', + id2, + 'txHash', + bulk2.transaction.hash.toHex() + ); + assert.fieldEquals( + 'BulkPayoutEvent', + id2, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('BulkPayoutEvent', id2, 'sender', operatorAddressString); + assert.fieldEquals('BulkPayoutEvent', id2, 'bulkPayoutTxId', '3'); + assert.fieldEquals('BulkPayoutEvent', id2, 'bulkCount', '4'); + + // EscrowStatusEvent + assert.fieldEquals( + 'EscrowStatusEvent', + id2, + 'block', + bulk2.block.number.toString() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id2, + 'timestamp', + bulk2.block.timestamp.toString() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id2, + 'txHash', + bulk2.transaction.hash.toHex() + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id2, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals( + 'EscrowStatusEvent', + id2, + 'sender', + operatorAddressString + ); + assert.fieldEquals('EscrowStatusEvent', id2, 'status', 'Paid'); + assert.fieldEquals( + 'EscrowStatusEvent', + id2, + 'launcher', + launcherAddressString + ); + + // Escrow + assert.fieldEquals('Escrow', escrowAddress.toHex(), 'status', 'Paid'); + assert.fieldEquals( + 'Escrow', + escrowAddress.toHex(), + 'finalResultsUrl', + 'test.com' + ); + assert.fieldEquals('Escrow', escrowAddress.toHex(), 'balance', '0'); + assert.fieldEquals( 'Transaction', bulk1.transaction.hash.toHex(), @@ -953,32 +1397,106 @@ describe('Escrow', () => { ); }); + test('Should properly handle Withdraw event', () => { + const withdraw = createWithdrawEvent( + operatorAddress, + tokenAddress, + 100, + BigInt.fromI32(10) + ); + + handleWithdraw(withdraw); + + const id = toEventId(withdraw).toHex(); + + // WithdrawEvent + assert.fieldEquals( + 'WithdrawEvent', + id, + 'block', + withdraw.block.number.toString() + ); + assert.fieldEquals( + 'WithdrawEvent', + id, + 'timestamp', + withdraw.block.timestamp.toString() + ); + assert.fieldEquals( + 'WithdrawEvent', + id, + 'txHash', + withdraw.transaction.hash.toHex() + ); + assert.fieldEquals( + 'WithdrawEvent', + id, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('WithdrawEvent', id, 'sender', operatorAddressString); + assert.fieldEquals('WithdrawEvent', id, 'receiver', launcherAddressString); + assert.fieldEquals('WithdrawEvent', id, 'amount', '100'); + assert.fieldEquals('WithdrawEvent', id, 'token', tokenAddressString); + + assert.fieldEquals( + 'Transaction', + withdraw.transaction.hash.toHex(), + 'txHash', + withdraw.transaction.hash.toHex() + ); + assert.fieldEquals( + 'Transaction', + withdraw.transaction.hash.toHex(), + 'method', + 'withdraw' + ); + assert.fieldEquals( + 'Transaction', + withdraw.transaction.hash.toHex(), + 'block', + withdraw.block.number.toString() + ); + assert.fieldEquals( + 'Transaction', + withdraw.transaction.hash.toHex(), + 'from', + operatorAddressString + ); + assert.fieldEquals( + 'Transaction', + withdraw.transaction.hash.toHex(), + 'value', + '100' + ); + }); + describe('Statistics', () => { beforeEach(() => { clearStore(); }); test('Should properly calculate setup & pending in statistics', () => { - const newPending1 = createPendingEvent( + const newPending1 = createPendingV2Event( operatorAddress, 'test.com', - 'is_hash_1' + 'is_hash_1', + reputationOracleAddress, + recordingOracleAddress, + exchangeOracleAddress ); - const newPending2 = createPendingEvent( + const newPending2 = createPendingV2Event( operatorAddress, 'test.com', - 'is_hash_1' + 'is_hash_1', + reputationOracleAddress, + recordingOracleAddress, + exchangeOracleAddress ); - handlePending(newPending1); - handlePending(newPending2); + handlePendingV2(newPending1); + handlePendingV2(newPending2); - assert.fieldEquals( - 'EscrowStatistics', - STATISTICS_ENTITY_ID.toHex(), - 'setupEventCount', - '2' - ); assert.fieldEquals( 'EscrowStatistics', STATISTICS_ENTITY_ID.toHex(), @@ -1027,7 +1545,6 @@ describe('Escrow', () => { [ 'fundEventCount', - 'setupEventCount', 'bulkPayoutEventCount', 'pendingStatusEventCount', 'cancelledStatusEventCount', @@ -1052,8 +1569,8 @@ describe('Escrow', () => { }); test('Should properly calculate bulkPayout, partialStatus, paidStatus event in statistics', () => { - handleBulkTransfer( - createBulkTransferEvent( + handleBulkTransferV2( + createBulkTransferV2Event( operatorAddress, 1, [ @@ -1065,16 +1582,18 @@ describe('Escrow', () => { ], [1, 1, 1, 1, 1], true, + 'test.com', BigInt.fromI32(11) ) ); - handleBulkTransfer( - createBulkTransferEvent( + handleBulkTransferV2( + createBulkTransferV2Event( operatorAddress, 2, [workerAddress, workerAddress, workerAddress, workerAddress], [1, 1, 1, 1], false, + 'test.com', BigInt.fromI32(11) ) ); @@ -1100,7 +1619,6 @@ describe('Escrow', () => { [ 'fundEventCount', - 'setupEventCount', 'storeResultsEventCount', 'pendingStatusEventCount', 'cancelledStatusEventCount', @@ -1138,7 +1656,6 @@ describe('Escrow', () => { [ 'fundEventCount', - 'setupEventCount', 'storeResultsEventCount', 'bulkPayoutEventCount', 'pendingStatusEventCount', @@ -1178,7 +1695,6 @@ describe('Escrow', () => { [ 'fundEventCount', - 'setupEventCount', 'storeResultsEventCount', 'bulkPayoutEventCount', 'pendingStatusEventCount', @@ -1201,5 +1717,79 @@ describe('Escrow', () => { '2' ); }); + + test('Should properly calculate fund event in statstics', () => { + dataSourceMock.setReturnValues( + escrowAddressString, + 'rinkeby', + new DataSourceContext() + ); + + createMockedFunction( + escrowAddress, + 'reputationOracle', + 'reputationOracle():(address)' + ).returns([ethereum.Value.fromAddress(reputationOracleAddress)]); + createMockedFunction( + escrowAddress, + 'recordingOracle', + 'recordingOracle():(address)' + ).returns([ethereum.Value.fromAddress(recordingOracleAddress)]); + createMockedFunction( + escrowAddress, + 'finalResultsUrl', + 'finalResultsUrl():(string)' + ).returns([ethereum.Value.fromString('test.com')]); + + const escrow = new Escrow(escrowAddress); + escrow.address = escrowAddress; + escrow.token = Address.zero(); + escrow.factoryAddress = Address.zero(); + escrow.launcher = launcherAddress; + escrow.canceler = launcherAddress; + escrow.count = ZERO_BI; + escrow.balance = ZERO_BI; + escrow.totalFundedAmount = ZERO_BI; + escrow.amountPaid = ZERO_BI; + escrow.status = 'Launched'; + escrow.createdAt = ZERO_BI; + + escrow.save(); + + const newFund1 = createFundEvent(operatorAddress, 1, BigInt.fromI32(10)); + + handleFund(newFund1); + + assert.fieldEquals( + 'EscrowStatistics', + STATISTICS_ENTITY_ID.toHex(), + 'fundEventCount', + '1' + ); + + [ + 'storeResultsEventCount', + 'bulkPayoutEventCount', + 'pendingStatusEventCount', + 'cancelledStatusEventCount', + 'partialStatusEventCount', + 'paidStatusEventCount', + 'completedStatusEventCount', + ].forEach((field) => { + assert.fieldEquals( + 'EscrowStatistics', + STATISTICS_ENTITY_ID.toHex(), + field, + '0' + ); + }); + + assert.fieldEquals( + 'EscrowStatistics', + STATISTICS_ENTITY_ID.toHex(), + 'totalEventCount', + '1' + ); + }); }); }); diff --git a/packages/sdk/typescript/subgraph/tests/escrow/fixtures.ts b/packages/sdk/typescript/subgraph/tests/escrow/fixtures.ts index 5ab3ff0dcd..7546898636 100644 --- a/packages/sdk/typescript/subgraph/tests/escrow/fixtures.ts +++ b/packages/sdk/typescript/subgraph/tests/escrow/fixtures.ts @@ -7,7 +7,12 @@ import { BulkTransfer, Cancelled, Completed, + Fund, + PendingV2, + BulkTransferV2, + Withdraw, } from '../../generated/templates/Escrow/Escrow'; +import { generateUniqueHash } from '../../tests/utils'; export function createPendingEvent( sender: Address, @@ -15,6 +20,45 @@ export function createPendingEvent( hash: string ): Pending { const newPendingEvent = changetype(newMockEvent()); + newPendingEvent.transaction.hash = generateUniqueHash( + sender.toString(), + newPendingEvent.transaction.nonce, + newPendingEvent.transaction.nonce + ); + + newPendingEvent.transaction.from = sender; + + newPendingEvent.parameters = []; + + const manifestParam = new ethereum.EventParam( + 'manifest', + ethereum.Value.fromString(manifest) + ); + const hashParam = new ethereum.EventParam( + 'hash', + ethereum.Value.fromString(hash) + ); + + newPendingEvent.parameters.push(manifestParam); + newPendingEvent.parameters.push(hashParam); + + return newPendingEvent; +} + +export function createPendingV2Event( + sender: Address, + manifest: string, + hash: string, + reputationOracleAddress: Address, + recordingOracleAddress: Address, + exchangeOracleAddress: Address +): PendingV2 { + const newPendingEvent = changetype(newMockEvent()); + newPendingEvent.transaction.hash = generateUniqueHash( + sender.toString(), + newPendingEvent.transaction.nonce, + newPendingEvent.transaction.nonce + ); newPendingEvent.transaction.from = sender; @@ -28,9 +72,24 @@ export function createPendingEvent( 'hash', ethereum.Value.fromString(hash) ); + const reputationOracleAddressParam = new ethereum.EventParam( + 'reputationOracleAddress', + ethereum.Value.fromAddress(reputationOracleAddress) + ); + const recordingOracleAddressParam = new ethereum.EventParam( + 'recordingOracleAddress', + ethereum.Value.fromAddress(recordingOracleAddress) + ); + const exchangeOracleAddressParam = new ethereum.EventParam( + 'exchangeOracleAddress', + ethereum.Value.fromAddress(exchangeOracleAddress) + ); newPendingEvent.parameters.push(manifestParam); newPendingEvent.parameters.push(hashParam); + newPendingEvent.parameters.push(reputationOracleAddressParam); + newPendingEvent.parameters.push(recordingOracleAddressParam); + newPendingEvent.parameters.push(exchangeOracleAddressParam); return newPendingEvent; } @@ -42,6 +101,11 @@ export function createISEvent( ): IntermediateStorage { const newIntermediateStorageEvent = changetype(newMockEvent()); + newIntermediateStorageEvent.transaction.hash = generateUniqueHash( + sender.toString(), + newIntermediateStorageEvent.transaction.nonce, + newIntermediateStorageEvent.transaction.nonce + ); newIntermediateStorageEvent.transaction.from = sender; @@ -71,6 +135,11 @@ export function createBulkTransferEvent( timestamp: BigInt ): BulkTransfer { const newBTEvent = changetype(newMockEvent()); + newBTEvent.transaction.hash = generateUniqueHash( + sender.toString(), + timestamp, + newBTEvent.transaction.nonce + ); newBTEvent.block.timestamp = timestamp; newBTEvent.transaction.from = sender; @@ -102,8 +171,64 @@ export function createBulkTransferEvent( return newBTEvent; } +export function createBulkTransferV2Event( + sender: Address, + txId: i32, + recipients: Address[], + amounts: i32[], + isPartial: boolean, + finalResultsUrl: string, + timestamp: BigInt +): BulkTransferV2 { + const newBTEvent = changetype(newMockEvent()); + newBTEvent.transaction.hash = generateUniqueHash( + sender.toString(), + timestamp, + newBTEvent.transaction.nonce + ); + + newBTEvent.block.timestamp = timestamp; + newBTEvent.transaction.from = sender; + + newBTEvent.parameters = []; + + const txIdParam = new ethereum.EventParam( + '_txId', + ethereum.Value.fromI32(txId) + ); + const recipientsParam = new ethereum.EventParam( + '_recipients', + ethereum.Value.fromAddressArray(recipients) + ); + const amountsParam = new ethereum.EventParam( + '_amounts', + ethereum.Value.fromI32Array(amounts) + ); + const isPartialParam = new ethereum.EventParam( + '_isPartial', + ethereum.Value.fromBoolean(isPartial) + ); + const finalResultsUrlParam = new ethereum.EventParam( + '_finalResultsUrl', + ethereum.Value.fromString(finalResultsUrl) + ); + + newBTEvent.parameters.push(txIdParam); + newBTEvent.parameters.push(recipientsParam); + newBTEvent.parameters.push(amountsParam); + newBTEvent.parameters.push(isPartialParam); + newBTEvent.parameters.push(finalResultsUrlParam); + + return newBTEvent; +} + export function createCancelledEvent(sender: Address): Cancelled { const newCancelledEvent = changetype(newMockEvent()); + newCancelledEvent.transaction.hash = generateUniqueHash( + sender.toString(), + newCancelledEvent.transaction.nonce, + newCancelledEvent.transaction.nonce + ); newCancelledEvent.transaction.from = sender; @@ -121,3 +246,66 @@ export function createCompletedEvent(sender: Address): Completed { return newCompletedEvent; } + +export function createFundEvent( + sender: Address, + amount: i32, + timestamp: BigInt +): Fund { + const newFundEvent = changetype(newMockEvent()); + newFundEvent.transaction.hash = generateUniqueHash( + sender.toString(), + timestamp, + newFundEvent.transaction.nonce + ); + + newFundEvent.block.timestamp = timestamp; + + newFundEvent.transaction.from = sender; + + newFundEvent.parameters = []; + + const amountParam = new ethereum.EventParam( + '_amount', + ethereum.Value.fromI32(amount) + ); + + newFundEvent.parameters.push(amountParam); + + return newFundEvent; +} + +export function createWithdrawEvent( + sender: Address, + token: Address, + amount: i32, + timestamp: BigInt +): Withdraw { + const newWithdrawEvent = changetype(newMockEvent()); + newWithdrawEvent.transaction.hash = generateUniqueHash( + sender.toString() + token.toString(), + timestamp, + newWithdrawEvent.transaction.nonce + ); + + newWithdrawEvent.block.timestamp = timestamp; + + newWithdrawEvent.transaction.from = sender; + + newWithdrawEvent.parameters = []; + + const tokenParam = new ethereum.EventParam( + '_token', + ethereum.Value.fromAddress(token) + ); + + const amountParam = new ethereum.EventParam( + '_amount', + ethereum.Value.fromI32(amount) + ); + + newWithdrawEvent.parameters.push(tokenParam); + newWithdrawEvent.parameters.push(amountParam); + + return newWithdrawEvent; +} diff --git a/packages/sdk/typescript/subgraph/tests/hmt/fixtures.ts b/packages/sdk/typescript/subgraph/tests/hmt/fixtures.ts index 53514f991a..259a0ac3da 100644 --- a/packages/sdk/typescript/subgraph/tests/hmt/fixtures.ts +++ b/packages/sdk/typescript/subgraph/tests/hmt/fixtures.ts @@ -1,5 +1,5 @@ import { newMockEvent } from 'matchstick-as/assembly/index'; -import { Address, ethereum, BigInt } from '@graphprotocol/graph-ts'; +import { Address, ethereum, BigInt, dataSource } from '@graphprotocol/graph-ts'; import { Transfer, @@ -7,6 +7,7 @@ import { BulkTransfer, BulkApproval, } from '../../generated/HMToken/HMToken'; +import { generateUniqueHash } from '../../tests/utils'; export function createTransferEvent( from: string, @@ -15,7 +16,17 @@ export function createTransferEvent( timestamp: BigInt ): Transfer { const transferEvent = changetype(newMockEvent()); + transferEvent.transaction.hash = generateUniqueHash( + to, + timestamp, + transferEvent.transaction.nonce + ); + transferEvent.parameters = []; + transferEvent.transaction.from = Address.fromString(from); + transferEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); transferEvent.block.timestamp = timestamp; const fromParam = new ethereum.EventParam( '_from', @@ -44,6 +55,16 @@ export function createApprovalEvent( timestamp: BigInt ): Approval { const approvalEvent = changetype(newMockEvent()); + approvalEvent.transaction.hash = generateUniqueHash( + owner, + timestamp, + approvalEvent.transaction.nonce + ); + + approvalEvent.transaction.from = Address.fromString(spender); + approvalEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); approvalEvent.parameters = []; approvalEvent.block.timestamp = timestamp; const ownerParam = new ethereum.EventParam( @@ -72,6 +93,15 @@ export function createBulkTransferEvent( timestamp: BigInt ): BulkTransfer { const bulkTransferEvent = changetype(newMockEvent()); + bulkTransferEvent.transaction.hash = generateUniqueHash( + bulkCount.toString(), + timestamp, + bulkTransferEvent.transaction.nonce + ); + bulkTransferEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); + bulkTransferEvent.parameters = []; bulkTransferEvent.block.timestamp = timestamp; const txIdParam = new ethereum.EventParam( @@ -95,6 +125,16 @@ export function createBulkApprovalEvent( timestamp: BigInt ): BulkApproval { const bulkApprovalEvent = changetype(newMockEvent()); + bulkApprovalEvent.transaction.hash = generateUniqueHash( + bulkCount.toString(), + timestamp, + bulkApprovalEvent.transaction.nonce + ); + + bulkApprovalEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); + bulkApprovalEvent.parameters = []; bulkApprovalEvent.block.timestamp = timestamp; const txIdParam = new ethereum.EventParam( diff --git a/packages/sdk/typescript/subgraph/tests/hmt/hmt.test.ts b/packages/sdk/typescript/subgraph/tests/hmt/hmt.test.ts index 235b1bbe8e..81b667fdff 100644 --- a/packages/sdk/typescript/subgraph/tests/hmt/hmt.test.ts +++ b/packages/sdk/typescript/subgraph/tests/hmt/hmt.test.ts @@ -11,7 +11,6 @@ import { } from 'matchstick-as/assembly'; import { Escrow } from '../../generated/schema'; -import { STATISTICS_ENTITY_ID } from '../../src/mapping/Escrow'; import { HMT_STATISTICS_ENTITY_ID, handleTransfer, @@ -28,6 +27,7 @@ import { createBulkApprovalEvent, } from './fixtures'; +const tokenAddressString = '0xa16081f360e3847006db660bae1c6d1b2e17ffaa'; const escrowAddressString = '0xa16081f360e3847006db660bae1c6d1b2e17ec2a'; const escrowAddress = Address.fromString(escrowAddressString); const operatorAddressString = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'; @@ -40,7 +40,7 @@ const holder1Address = Address.fromString(holder1AddressString); describe('HMToken', () => { beforeAll(() => { dataSourceMock.setReturnValues( - escrowAddressString, + tokenAddressString, 'rinkeby', new DataSourceContext() ); @@ -50,6 +50,7 @@ describe('HMToken', () => { escrow.token = Address.zero(); escrow.factoryAddress = Address.zero(); escrow.launcher = Address.zero(); + escrow.canceler = Address.zero(); escrow.count = ZERO_BI; escrow.balance = BigInt.fromI32(100); escrow.totalFundedAmount = BigInt.fromI32(100); @@ -100,29 +101,6 @@ describe('HMToken', () => { assert.fieldEquals('HMTTransferEvent', id, 'to', escrowAddressString); assert.fieldEquals('HMTTransferEvent', id, 'amount', '1'); - // FundEvent - assert.fieldEquals( - 'FundEvent', - id, - 'block', - transfer.block.number.toString() - ); - assert.fieldEquals( - 'FundEvent', - id, - 'timestamp', - transfer.block.timestamp.toString() - ); - assert.fieldEquals( - 'FundEvent', - id, - 'txHash', - transfer.transaction.hash.toHex() - ); - assert.fieldEquals('FundEvent', id, 'escrowAddress', escrowAddressString); - assert.fieldEquals('FundEvent', id, 'sender', operatorAddressString); - assert.fieldEquals('FundEvent', id, 'amount', '1'); - // Escrow assert.fieldEquals('Escrow', escrowAddressString, 'balance', '101'); assert.fieldEquals( @@ -153,14 +131,32 @@ describe('HMToken', () => { 'Transaction', transfer.transaction.hash.toHex(), 'from', - transfer.transaction.from.toHex() + operatorAddressString ); assert.fieldEquals( 'Transaction', transfer.transaction.hash.toHex(), 'to', + tokenAddressString + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'receiver', + escrowAddressString + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'escrow', escrowAddressString ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'token', + tokenAddressString + ); assert.fieldEquals( 'Transaction', transfer.transaction.hash.toHex(), @@ -204,9 +200,6 @@ describe('HMToken', () => { assert.fieldEquals('HMTTransferEvent', id, 'to', holderAddressString); assert.fieldEquals('HMTTransferEvent', id, 'amount', '1'); - // No FundEvent - assert.notInStore('FundEvent', id); - // Holder assert.fieldEquals( 'Holder', @@ -215,6 +208,54 @@ describe('HMToken', () => { holderAddressString ); assert.fieldEquals('Holder', holderAddressString, 'balance', '1'); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'txHash', + transfer.transaction.hash.toHex() + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'method', + 'transfer' + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'block', + transfer.block.number.toString() + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'from', + operatorAddressString + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'to', + tokenAddressString + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'receiver', + holderAddressString + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'token', + tokenAddressString + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'value', + '1' + ); }); test('Should properly handle Transfer event from Escrow', () => { @@ -306,14 +347,26 @@ describe('HMToken', () => { 'Transaction', transfer.transaction.hash.toHex(), 'from', - transfer.transaction.from.toHex() + escrowAddressString ); assert.fieldEquals( 'Transaction', transfer.transaction.hash.toHex(), 'to', + tokenAddressString + ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'receiver', operatorAddressString ); + assert.fieldEquals( + 'Transaction', + transfer.transaction.hash.toHex(), + 'token', + tokenAddressString + ); assert.fieldEquals( 'Transaction', transfer.transaction.hash.toHex(), @@ -382,7 +435,7 @@ describe('HMToken', () => { holderAddressString, operatorAddressString, 1, - BigInt.fromI32(10) + BigInt.fromI32(100) ); handleApproval(approval); @@ -440,12 +493,6 @@ describe('HMToken', () => { 'from', approval.transaction.from.toHex() ); - assert.fieldEquals( - 'Transaction', - approval.transaction.hash.toHex(), - 'to', - operatorAddressString - ); assert.fieldEquals( 'Transaction', approval.transaction.hash.toHex(), @@ -455,7 +502,7 @@ describe('HMToken', () => { }); test('Should properly handle BulkApproval event', () => { - const bulkApproval = createBulkApprovalEvent(1, 3, BigInt.fromI32(10)); + const bulkApproval = createBulkApprovalEvent(1, 3, BigInt.fromI32(200)); handleBulkApproval(bulkApproval); @@ -664,71 +711,5 @@ describe('HMToken', () => { '2' ); }); - - test('Should properly calculate FundEvent in statistics, when sending to escrow', () => { - const escrow = new Escrow(escrowAddress); - escrow.address = escrowAddress; - escrow.token = Address.zero(); - escrow.factoryAddress = Address.zero(); - escrow.launcher = Address.zero(); - escrow.count = ZERO_BI; - escrow.balance = BigInt.fromI32(100); - escrow.totalFundedAmount = BigInt.fromI32(100); - escrow.amountPaid = ZERO_BI; - escrow.createdAt = BigInt.fromI32(0); - escrow.status = 'Launched'; - - escrow.save(); - - const transfer1 = createTransferEvent( - operatorAddressString, - escrowAddressString, - 1, - BigInt.fromI32(10) - ); - - handleTransfer(transfer1); - - const transfer2 = createTransferEvent( - operatorAddressString, - escrowAddressString, - 1, - BigInt.fromI32(20) - ); - - handleTransfer(transfer2); - - assert.fieldEquals( - 'EscrowStatistics', - STATISTICS_ENTITY_ID.toHex(), - 'fundEventCount', - '2' - ); - - [ - 'setupEventCount', - 'storeResultsEventCount', - 'bulkPayoutEventCount', - 'pendingStatusEventCount', - 'cancelledStatusEventCount', - 'partialStatusEventCount', - 'paidStatusEventCount', - 'completedStatusEventCount', - ].forEach((field) => { - assert.fieldEquals( - 'EscrowStatistics', - STATISTICS_ENTITY_ID.toHex(), - field, - '0' - ); - }); - - assert.fieldEquals( - 'EscrowStatistics', - STATISTICS_ENTITY_ID.toHex(), - 'totalEventCount', - '2' - ); - }); }); }); diff --git a/packages/sdk/typescript/subgraph/tests/kvstore/fixtures.ts b/packages/sdk/typescript/subgraph/tests/kvstore/fixtures.ts index 63d175d4b5..cb36b5bfa2 100644 --- a/packages/sdk/typescript/subgraph/tests/kvstore/fixtures.ts +++ b/packages/sdk/typescript/subgraph/tests/kvstore/fixtures.ts @@ -1,6 +1,7 @@ import { DataSaved } from '../../generated/KVStore/KVStore'; import { newMockEvent } from 'matchstick-as/assembly/index'; -import { ethereum, Address, BigInt } from '@graphprotocol/graph-ts'; +import { ethereum, Address, BigInt, dataSource } from '@graphprotocol/graph-ts'; +import { generateUniqueHash } from '../../tests/utils'; export function createDataSavedEvent( sender: string, @@ -9,8 +10,17 @@ export function createDataSavedEvent( timestamp: BigInt ): DataSaved { const newDataSavedEvent = changetype(newMockEvent()); + newDataSavedEvent.transaction.hash = generateUniqueHash( + sender.toString(), + timestamp, + newDataSavedEvent.transaction.nonce + ); + newDataSavedEvent.transaction.value = BigInt.fromI32(0); newDataSavedEvent.block.timestamp = timestamp; + newDataSavedEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); newDataSavedEvent.parameters = []; newDataSavedEvent.parameters.push( diff --git a/packages/sdk/typescript/subgraph/tests/kvstore/kvstore.test.ts b/packages/sdk/typescript/subgraph/tests/kvstore/kvstore.test.ts index bb604896ca..6129d239af 100644 --- a/packages/sdk/typescript/subgraph/tests/kvstore/kvstore.test.ts +++ b/packages/sdk/typescript/subgraph/tests/kvstore/kvstore.test.ts @@ -1,10 +1,12 @@ -import { BigInt } from '@graphprotocol/graph-ts'; +import { BigInt, DataSourceContext } from '@graphprotocol/graph-ts'; import { describe, test, assert, clearStore, afterEach, + dataSourceMock, + beforeAll, } from 'matchstick-as/assembly'; import { handleDataSaved } from '../../src/mapping/KVStore'; @@ -12,7 +14,16 @@ import { toEventId } from '../../src/mapping/utils/event'; import { toBytes } from '../../src/mapping/utils/string'; import { createDataSavedEvent } from './fixtures'; +const kvStoreAddressString = '0x15d34aaf54267db7d7c367839aaf71a00a2c6a65'; + describe('KVStore', () => { + beforeAll(() => { + dataSourceMock.setReturnValues( + kvStoreAddressString, + 'rinkeby', + new DataSourceContext() + ); + }); afterEach(() => { clearStore(); }); @@ -94,7 +105,7 @@ describe('KVStore', () => { assert.fieldEquals('KVStoreSetEvent', id2, 'value', 'Validator'); }); - test('Should properly create a transaction', () => { + test('Should properly create a transaction with set method', () => { const data1 = createDataSavedEvent( '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', 'role', @@ -159,6 +170,99 @@ describe('KVStore', () => { 'from', data2.transaction.from.toHex() ); + assert.fieldEquals( + 'Transaction', + data1.transaction.hash.toHex(), + 'to', + kvStoreAddressString + ); + assert.fieldEquals( + 'Transaction', + data2.transaction.hash.toHex(), + 'to', + kvStoreAddressString + ); + }); + + test('Should properly create a transaction with setBulk method', () => { + const data1 = createDataSavedEvent( + '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', + 'role', + 'Operator', + BigInt.fromI32(10) + ); + const data2 = createDataSavedEvent( + '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', + 'webhook_url', + 'https://operator.example.com', + BigInt.fromI32(10) + ); + + handleDataSaved(data1); + handleDataSaved(data2); + + assert.fieldEquals( + 'Transaction', + data1.transaction.hash.toHex(), + 'txHash', + data1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'Transaction', + data1.transaction.hash.toHex(), + 'method', + 'setBulk' + ); + assert.fieldEquals( + 'Transaction', + data1.transaction.hash.toHex(), + 'block', + data1.block.number.toString() + ); + assert.fieldEquals( + 'Transaction', + data1.transaction.hash.toHex(), + 'from', + data1.transaction.from.toHex() + ); + assert.fieldEquals( + 'Transaction', + data1.transaction.hash.toHex(), + 'to', + kvStoreAddressString + ); + + const internalTransactionId = toEventId(data1).toHex(); + assert.fieldEquals( + 'InternalTransaction', + internalTransactionId, + 'transaction', + data1.transaction.hash.toHex() + ); + assert.fieldEquals( + 'InternalTransaction', + internalTransactionId, + 'from', + data1.transaction.from.toHex() + ); + assert.fieldEquals( + 'InternalTransaction', + internalTransactionId, + 'to', + kvStoreAddressString + ); + assert.fieldEquals( + 'InternalTransaction', + internalTransactionId, + 'value', + '0' + ); + assert.fieldEquals( + 'InternalTransaction', + internalTransactionId, + 'method', + 'set' + ); }); test('Should properly update leader role', () => { @@ -320,6 +424,38 @@ describe('KVStore', () => { ); }); + test("Should properly update leader's website", () => { + const data1 = createDataSavedEvent( + '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', + 'website', + 'https://operator.example.com', + BigInt.fromI32(10) + ); + const data2 = createDataSavedEvent( + '0x92a2eEF7Ff696BCef98957a0189872680600a959', + 'website', + 'https://validator.example.com', + BigInt.fromI32(11) + ); + + handleDataSaved(data1); + handleDataSaved(data2); + + assert.fieldEquals( + 'Leader', + data1.params.sender.toHex(), + 'website', + 'https://operator.example.com' + ); + + assert.fieldEquals( + 'Leader', + data2.params.sender.toHex(), + 'website', + 'https://validator.example.com' + ); + }); + test("Should properly update leader's url", () => { const data1 = createDataSavedEvent( '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', @@ -411,11 +547,12 @@ describe('KVStore', () => { 'role', 'Job Launcher' ); + assert.fieldEquals( 'Leader', data2.params.sender.toHex(), - 'reputationNetwork', - data1.params.sender.toHex() + 'reputationNetworks', + `[${data1.params.sender.toHex()}]` ); }); diff --git a/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/escrow-factory.test.ts b/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/escrow-factory.test.ts index c35fe7e035..22365d426b 100644 --- a/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/escrow-factory.test.ts +++ b/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/escrow-factory.test.ts @@ -1,10 +1,12 @@ -import { Address, BigInt } from '@graphprotocol/graph-ts'; +import { Address, BigInt, DataSourceContext } from '@graphprotocol/graph-ts'; import { describe, test, assert, clearStore, afterAll, + beforeAll, + dataSourceMock, } from 'matchstick-as/assembly'; import { createLaunchedEvent } from './fixtures'; @@ -23,6 +25,14 @@ const escrow2AddressString = '0xd979105297fb0eee83f7433fc09279cb5b94ffc7'; const escrow2Address = Address.fromString(escrow2AddressString); describe('EscrowFactory', () => { + beforeAll(() => { + dataSourceMock.setReturnValues( + factoryAddressString, + 'rinkeby', + new DataSourceContext() + ); + }); + afterAll(() => { clearStore(); }); diff --git a/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/fixtures.ts b/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/fixtures.ts index 43049a1021..4bd35a6135 100644 --- a/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/fixtures.ts +++ b/packages/sdk/typescript/subgraph/tests/legacy/escrow-factory/fixtures.ts @@ -1,7 +1,8 @@ import { newMockEvent } from 'matchstick-as/assembly/index'; -import { ethereum, BigInt, Address } from '@graphprotocol/graph-ts'; +import { ethereum, BigInt, Address, dataSource } from '@graphprotocol/graph-ts'; import { Launched } from '../../../generated/LegacyEscrowFactory/EscrowFactory'; +import { generateUniqueHash } from '../../../tests/utils'; export function createLaunchedEvent( factory: Address, @@ -11,9 +12,17 @@ export function createLaunchedEvent( timestamp: BigInt ): Launched { const newLaunchedEvent = changetype(newMockEvent()); + newLaunchedEvent.transaction.hash = generateUniqueHash( + escrow.toString(), + timestamp, + newLaunchedEvent.transaction.nonce + ); newLaunchedEvent.block.timestamp = timestamp; newLaunchedEvent.transaction.from = launcher; + newLaunchedEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); newLaunchedEvent.address = factory; newLaunchedEvent.parameters = []; diff --git a/packages/sdk/typescript/subgraph/tests/legacy/escrow/escrow.test.ts b/packages/sdk/typescript/subgraph/tests/legacy/escrow/escrow.test.ts index b8c339394e..43fb67e5a8 100644 --- a/packages/sdk/typescript/subgraph/tests/legacy/escrow/escrow.test.ts +++ b/packages/sdk/typescript/subgraph/tests/legacy/escrow/escrow.test.ts @@ -89,6 +89,7 @@ describe('Escrow', () => { escrow.token = Address.zero(); escrow.factoryAddress = Address.zero(); escrow.launcher = launcherAddress; + escrow.canceler = launcherAddress; escrow.count = ZERO_BI; escrow.balance = BigInt.fromI32(100); escrow.totalFundedAmount = BigInt.fromI32(100); @@ -113,27 +114,32 @@ describe('Escrow', () => { const id = toEventId(newPending1).toHex(); - // SetupEvent + // PendingEvent assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'block', newPending1.block.number.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'timestamp', newPending1.block.timestamp.toString() ); assert.fieldEquals( - 'SetupEvent', + 'PendingEvent', id, 'txHash', newPending1.transaction.hash.toHex() ); - assert.fieldEquals('SetupEvent', id, 'escrowAddress', escrowAddressString); - assert.fieldEquals('SetupEvent', id, 'sender', operatorAddressString); + assert.fieldEquals( + 'PendingEvent', + id, + 'escrowAddress', + escrowAddressString + ); + assert.fieldEquals('PendingEvent', id, 'sender', operatorAddressString); // Escrow assert.fieldEquals('Escrow', escrowAddress.toHex(), 'status', 'Pending'); @@ -434,12 +440,6 @@ describe('Escrow', () => { handlePending(newPending1); handlePending(newPending2); - assert.fieldEquals( - 'EscrowStatistics', - STATISTICS_ENTITY_ID.toHex(), - 'setupEventCount', - '2' - ); assert.fieldEquals( 'EscrowStatistics', STATISTICS_ENTITY_ID.toHex(), @@ -488,7 +488,6 @@ describe('Escrow', () => { [ 'fundEventCount', - 'setupEventCount', 'bulkPayoutEventCount', 'pendingStatusEventCount', 'cancelledStatusEventCount', @@ -524,6 +523,7 @@ describe('Escrow', () => { escrow.token = Address.zero(); escrow.factoryAddress = Address.zero(); escrow.launcher = Address.zero(); + escrow.canceler = Address.zero(); escrow.count = ZERO_BI; escrow.balance = BigInt.fromI32(100); escrow.totalFundedAmount = BigInt.fromI32(100); @@ -570,7 +570,6 @@ describe('Escrow', () => { [ 'fundEventCount', - 'setupEventCount', 'storeResultsEventCount', 'pendingStatusEventCount', 'cancelledStatusEventCount', diff --git a/packages/sdk/typescript/subgraph/tests/legacy/escrow/fixtures.ts b/packages/sdk/typescript/subgraph/tests/legacy/escrow/fixtures.ts index 3c2070d48c..90fac742a5 100644 --- a/packages/sdk/typescript/subgraph/tests/legacy/escrow/fixtures.ts +++ b/packages/sdk/typescript/subgraph/tests/legacy/escrow/fixtures.ts @@ -6,6 +6,7 @@ import { Pending, BulkTransfer, } from '../../../generated/templates/LegacyEscrow/Escrow'; +import { generateUniqueHash } from '../../../tests/utils'; export function createPendingEvent( sender: Address, @@ -13,6 +14,11 @@ export function createPendingEvent( hash: string ): Pending { const newPendingEvent = changetype(newMockEvent()); + newPendingEvent.transaction.hash = generateUniqueHash( + sender.toString(), + newPendingEvent.transaction.nonce, + newPendingEvent.transaction.nonce + ); newPendingEvent.transaction.from = sender; @@ -40,6 +46,11 @@ export function createISEvent( ): IntermediateStorage { const newIntermediateStorageEvent = changetype(newMockEvent()); + newIntermediateStorageEvent.transaction.hash = generateUniqueHash( + sender.toString(), + newIntermediateStorageEvent.transaction.nonce, + newIntermediateStorageEvent.transaction.nonce + ); newIntermediateStorageEvent.transaction.from = sender; @@ -67,6 +78,11 @@ export function createBulkTransferEvent( timestamp: BigInt ): BulkTransfer { const newBTEvent = changetype(newMockEvent()); + newBTEvent.transaction.hash = generateUniqueHash( + sender.toString(), + timestamp, + newBTEvent.transaction.nonce + ); newBTEvent.block.timestamp = timestamp; newBTEvent.transaction.from = sender; diff --git a/packages/sdk/typescript/subgraph/tests/reward-pool/fixtures.ts b/packages/sdk/typescript/subgraph/tests/reward-pool/fixtures.ts deleted file mode 100644 index 74e1713f89..0000000000 --- a/packages/sdk/typescript/subgraph/tests/reward-pool/fixtures.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { RewardAdded } from '../../generated/RewardPool/RewardPool'; -import { newMockEvent } from 'matchstick-as/assembly/index'; -import { ethereum, Address, BigInt } from '@graphprotocol/graph-ts'; - -export function createRewardAddedEvent( - escrowAddress: string, - staker: string, - slasher: string, - tokens: i32, - timestamp: BigInt -): RewardAdded { - const newRewardAddedEvent = changetype(newMockEvent()); - - newRewardAddedEvent.block.timestamp = timestamp; - - newRewardAddedEvent.parameters = []; - newRewardAddedEvent.parameters.push( - new ethereum.EventParam( - 'escrowAddress', - ethereum.Value.fromAddress(Address.fromString(escrowAddress)) - ) - ); - newRewardAddedEvent.parameters.push( - new ethereum.EventParam( - 'staker', - ethereum.Value.fromAddress(Address.fromString(staker)) - ) - ); - newRewardAddedEvent.parameters.push( - new ethereum.EventParam( - 'slasher', - ethereum.Value.fromAddress(Address.fromString(slasher)) - ) - ); - newRewardAddedEvent.parameters.push( - new ethereum.EventParam('tokens', ethereum.Value.fromI32(tokens)) - ); - - return newRewardAddedEvent; -} diff --git a/packages/sdk/typescript/subgraph/tests/reward-pool/reward-pool.test.ts b/packages/sdk/typescript/subgraph/tests/reward-pool/reward-pool.test.ts deleted file mode 100644 index fcfa5d4f48..0000000000 --- a/packages/sdk/typescript/subgraph/tests/reward-pool/reward-pool.test.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { BigInt } from '@graphprotocol/graph-ts'; -import { - describe, - test, - assert, - clearStore, - afterAll, -} from 'matchstick-as/assembly'; - -import { handleRewardAdded } from '../../src/mapping/RewardPool'; -import { toEventId } from '../../src/mapping/utils/event'; -import { createRewardAddedEvent } from './fixtures'; - -describe('RewardPool', () => { - afterAll(() => { - clearStore(); - }); - - test('Should properly index RewardAddedEvent events', () => { - const data1 = createRewardAddedEvent( - '0xD979105297fB0eee83F7433fC09279cb5B94fFC7', - '0xD979105297fB0eee83F7433fC09279cb5B94fFC5', - '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', - 30, - BigInt.fromI32(50) - ); - const data2 = createRewardAddedEvent( - '0x92a2eEF7Ff696BCef98957a0189872680600a95A', - '0x92a2eEF7Ff696BCef98957a0189872680600a958', - '0x92a2eEF7Ff696BCef98957a0189872680600a959', - 50, - BigInt.fromI32(51) - ); - - handleRewardAdded(data1); - handleRewardAdded(data2); - - const id1 = toEventId(data1).toHex(); - const id2 = toEventId(data2).toHex(); - - // Data 1 - assert.fieldEquals( - 'RewardAddedEvent', - id1, - 'block', - data1.block.number.toString() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id1, - 'timestamp', - data1.block.timestamp.toString() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id1, - 'txHash', - data1.transaction.hash.toHex() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id1, - 'escrowAddress', - data1.params.escrowAddress.toHex() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id1, - 'staker', - data1.params.staker.toHex() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id1, - 'slasher', - data1.params.slasher.toHex() - ); - assert.fieldEquals('RewardAddedEvent', id1, 'amount', '30'); - - // Data 2 - assert.fieldEquals( - 'RewardAddedEvent', - id2, - 'block', - data2.block.number.toString() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id2, - 'timestamp', - data2.block.timestamp.toString() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id2, - 'txHash', - data2.transaction.hash.toHex() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id2, - 'escrowAddress', - data2.params.escrowAddress.toHex() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id2, - 'staker', - data2.params.staker.toHex() - ); - assert.fieldEquals( - 'RewardAddedEvent', - id2, - 'slasher', - data2.params.slasher.toHex() - ); - assert.fieldEquals('RewardAddedEvent', id2, 'amount', '50'); - - // Leader - assert.fieldEquals('Leader', data1.params.slasher.toHex(), 'reward', '30'); - - assert.fieldEquals('Leader', data2.params.slasher.toHex(), 'reward', '50'); - assert.fieldEquals( - 'Transaction', - data1.transaction.hash.toHex(), - 'txHash', - data1.transaction.hash.toHex() - ); - assert.fieldEquals( - 'Transaction', - data1.transaction.hash.toHex(), - 'method', - 'addReward' - ); - assert.fieldEquals( - 'Transaction', - data1.transaction.hash.toHex(), - 'block', - data1.block.number.toString() - ); - assert.fieldEquals( - 'Transaction', - data1.transaction.hash.toHex(), - 'from', - data1.transaction.from.toHex() - ); - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'txHash', - data2.transaction.hash.toHex() - ); - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'method', - 'addReward' - ); - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'block', - data2.block.number.toString() - ); - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'from', - data2.transaction.from.toHex() - ); - }); -}); diff --git a/packages/sdk/typescript/subgraph/tests/staking/fixtures.ts b/packages/sdk/typescript/subgraph/tests/staking/fixtures.ts index 71897b13c6..cc77767183 100644 --- a/packages/sdk/typescript/subgraph/tests/staking/fixtures.ts +++ b/packages/sdk/typescript/subgraph/tests/staking/fixtures.ts @@ -1,13 +1,13 @@ +import { Address, BigInt, dataSource, ethereum } from '@graphprotocol/graph-ts'; +import { newMockEvent } from 'matchstick-as/assembly/index'; import { - AllocationClosed, - StakeAllocated, + FeeWithdrawn, StakeDeposited, StakeLocked, StakeSlashed, StakeWithdrawn, } from '../../generated/Staking/Staking'; -import { newMockEvent } from 'matchstick-as/assembly/index'; -import { ethereum, Address, BigInt } from '@graphprotocol/graph-ts'; +import { generateUniqueHash } from '../../tests/utils'; export function createStakeDepositedEvent( staker: string, @@ -15,8 +15,16 @@ export function createStakeDepositedEvent( timestamp: BigInt ): StakeDeposited { const newStakeDepositedEvent = changetype(newMockEvent()); - + newStakeDepositedEvent.transaction.hash = generateUniqueHash( + staker, + timestamp, + newStakeDepositedEvent.transaction.nonce + ); newStakeDepositedEvent.block.timestamp = timestamp; + newStakeDepositedEvent.transaction.from = Address.fromString(staker); + newStakeDepositedEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); newStakeDepositedEvent.parameters = []; newStakeDepositedEvent.parameters.push( @@ -39,7 +47,15 @@ export function createStakeLockedEvent( timestamp: BigInt ): StakeLocked { const newStakeLockedEvent = changetype(newMockEvent()); - + newStakeLockedEvent.transaction.hash = generateUniqueHash( + staker, + timestamp, + newStakeLockedEvent.transaction.nonce + ); + newStakeLockedEvent.transaction.from = Address.fromString(staker); + newStakeLockedEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); newStakeLockedEvent.block.timestamp = timestamp; newStakeLockedEvent.parameters = []; @@ -65,7 +81,16 @@ export function createStakeWithdrawnEvent( timestamp: BigInt ): StakeWithdrawn { const newStakeWithdrawnEvent = changetype(newMockEvent()); + newStakeWithdrawnEvent.transaction.hash = generateUniqueHash( + staker, + timestamp, + newStakeWithdrawnEvent.transaction.nonce + ); + newStakeWithdrawnEvent.transaction.from = Address.fromString(staker); + newStakeWithdrawnEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); newStakeWithdrawnEvent.block.timestamp = timestamp; newStakeWithdrawnEvent.parameters = []; @@ -86,11 +111,20 @@ export function createStakeSlashedEvent( staker: string, tokens: i32, escrowAddress: string, - slasher: string, + slashRequester: string, timestamp: BigInt ): StakeSlashed { const newStakeSlashedEvent = changetype(newMockEvent()); + newStakeSlashedEvent.transaction.hash = generateUniqueHash( + staker, + timestamp, + newStakeSlashedEvent.transaction.nonce + ); + newStakeSlashedEvent.transaction.from = Address.fromString(staker); + newStakeSlashedEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() + ); newStakeSlashedEvent.block.timestamp = timestamp; newStakeSlashedEvent.parameters = []; @@ -111,78 +145,34 @@ export function createStakeSlashedEvent( ); newStakeSlashedEvent.parameters.push( new ethereum.EventParam( - 'slasher', - ethereum.Value.fromAddress(Address.fromString(slasher)) + 'slashRequester', + ethereum.Value.fromAddress(Address.fromString(slashRequester)) ) ); return newStakeSlashedEvent; } -export function createStakeAllocatedEvent( - staker: string, - tokens: i32, - escrowAddress: string, - createdAt: i32, +export function createFeeWithdrawnEvent( + amount: i32, timestamp: BigInt -): StakeAllocated { - const newStakeAllocatedEvent = changetype(newMockEvent()); - - newStakeAllocatedEvent.block.timestamp = timestamp; - - newStakeAllocatedEvent.parameters = []; - newStakeAllocatedEvent.parameters.push( - new ethereum.EventParam( - 'staker', - ethereum.Value.fromAddress(Address.fromString(staker)) - ) - ); - newStakeAllocatedEvent.parameters.push( - new ethereum.EventParam('tokens', ethereum.Value.fromI32(tokens)) +): FeeWithdrawn { + const newFeeWithdrawnEvent = changetype(newMockEvent()); + newFeeWithdrawnEvent.transaction.hash = generateUniqueHash( + amount.toString(), + timestamp, + newFeeWithdrawnEvent.transaction.nonce ); - newStakeAllocatedEvent.parameters.push( - new ethereum.EventParam( - 'escrowAddress', - ethereum.Value.fromAddress(Address.fromString(escrowAddress)) - ) - ); - newStakeAllocatedEvent.parameters.push( - new ethereum.EventParam('createdAt', ethereum.Value.fromI32(createdAt)) - ); - - return newStakeAllocatedEvent; -} - -export function createAllocationClosedEvent( - staker: string, - tokens: i32, - escrowAddress: string, - closedAt: i32, - timestamp: BigInt -): AllocationClosed { - const newAllocationClosedEvent = changetype(newMockEvent()); - - newAllocationClosedEvent.block.timestamp = timestamp; - newAllocationClosedEvent.parameters = []; - newAllocationClosedEvent.parameters.push( - new ethereum.EventParam( - 'staker', - ethereum.Value.fromAddress(Address.fromString(staker)) - ) - ); - newAllocationClosedEvent.parameters.push( - new ethereum.EventParam('tokens', ethereum.Value.fromI32(tokens)) + newFeeWithdrawnEvent.transaction.to = Address.fromString( + dataSource.address().toHexString() ); - newAllocationClosedEvent.parameters.push( - new ethereum.EventParam( - 'escrowAddress', - ethereum.Value.fromAddress(Address.fromString(escrowAddress)) - ) - ); - newAllocationClosedEvent.parameters.push( - new ethereum.EventParam('closedAt', ethereum.Value.fromI32(closedAt)) + newFeeWithdrawnEvent.block.timestamp = timestamp; + + newFeeWithdrawnEvent.parameters = []; + newFeeWithdrawnEvent.parameters.push( + new ethereum.EventParam('amount', ethereum.Value.fromI32(amount)) ); - return newAllocationClosedEvent; + return newFeeWithdrawnEvent; } diff --git a/packages/sdk/typescript/subgraph/tests/staking/staking.test.ts b/packages/sdk/typescript/subgraph/tests/staking/staking.test.ts index c5864da246..ef67637128 100644 --- a/packages/sdk/typescript/subgraph/tests/staking/staking.test.ts +++ b/packages/sdk/typescript/subgraph/tests/staking/staking.test.ts @@ -1,4 +1,4 @@ -import { Address, BigInt } from '@graphprotocol/graph-ts'; +import { Address, BigInt, DataSourceContext } from '@graphprotocol/graph-ts'; import { describe, test, @@ -6,29 +6,30 @@ import { clearStore, beforeAll, afterAll, + dataSourceMock, } from 'matchstick-as/assembly'; import { Escrow } from '../../generated/schema'; import { - handleAllocationClosed, - handleStakeAllocated, handleStakeDeposited, handleStakeLocked, handleStakeSlashed, handleStakeWithdrawn, + handleFeeWithdrawn, STATISTICS_ENTITY_ID, + TOKEN_ADDRESS, } from '../../src/mapping/Staking'; import { toEventId } from '../../src/mapping/utils/event'; import { ZERO_BI } from '../../src/mapping/utils/number'; import { - createAllocationClosedEvent, - createStakeAllocatedEvent, + createFeeWithdrawnEvent, createStakeDepositedEvent, createStakeLockedEvent, createStakeSlashedEvent, createStakeWithdrawnEvent, } from './fixtures'; +const stakingAddressString = '0xa16081f360e3847006db660bae1c6d1b2e17ffaa'; const escrow1AddressString = '0xD979105297fB0eee83F7433fC09279cb5B94fFC7'; const escrow1Address = Address.fromString(escrow1AddressString); const escrow2AddressString = '0x92a2eEF7Ff696BCef98957a0189872680600a95A'; @@ -36,11 +37,17 @@ const escrow2Address = Address.fromString(escrow2AddressString); describe('Staking', () => { beforeAll(() => { + dataSourceMock.setReturnValues( + stakingAddressString, + 'rinkeby', + new DataSourceContext() + ); const escrow1 = new Escrow(escrow1Address); escrow1.address = escrow1Address; escrow1.token = Address.zero(); escrow1.factoryAddress = Address.zero(); escrow1.launcher = Address.zero(); + escrow1.canceler = Address.zero(); escrow1.count = ZERO_BI; escrow1.balance = ZERO_BI; escrow1.totalFundedAmount = ZERO_BI; @@ -54,6 +61,7 @@ describe('Staking', () => { escrow2.token = Address.zero(); escrow2.factoryAddress = Address.zero(); escrow2.launcher = Address.zero(); + escrow2.canceler = Address.zero(); escrow2.count = ZERO_BI; escrow2.balance = ZERO_BI; escrow2.totalFundedAmount = ZERO_BI; @@ -192,6 +200,12 @@ describe('Staking', () => { 'value', '200' ); + assert.fieldEquals( + 'Transaction', + data2.transaction.hash.toHex(), + 'token', + TOKEN_ADDRESS.toHexString() + ); }); test('Should properly index StakeLocked events', () => { @@ -348,6 +362,12 @@ describe('Staking', () => { 'value', '100' ); + assert.fieldEquals( + 'Transaction', + data2.transaction.hash.toHex(), + 'token', + TOKEN_ADDRESS.toHexString() + ); }); test('Should properly index StakeWithdrawn events', () => { @@ -492,7 +512,7 @@ describe('Staking', () => { 'Transaction', data2.transaction.hash.toHex(), 'method', - 'withdraw' + 'stakeWithdrawn' ); assert.fieldEquals( 'Transaction', @@ -512,197 +532,11 @@ describe('Staking', () => { 'value', '100' ); - }); - - test('Should properly index StakeAllocated events', () => { - const data1 = createStakeAllocatedEvent( - '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', - 30, - '0xD979105297fB0eee83F7433fC09279cb5B94fFC7', - 50, - BigInt.fromI32(50) - ); - const data2 = createStakeAllocatedEvent( - '0x92a2eEF7Ff696BCef98957a0189872680600a959', - 50, - '0x92a2eEF7Ff696BCef98957a0189872680600a95A', - 51, - BigInt.fromI32(51) - ); - - handleStakeAllocated(data1); - handleStakeAllocated(data2); - - const id1 = toEventId(data1).toHex(); - const id2 = toEventId(data2).toHex(); - - // Data 1 - assert.fieldEquals( - 'StakeAllocatedEvent', - id1, - 'block', - data1.block.number.toString() - ); - assert.fieldEquals( - 'StakeAllocatedEvent', - id1, - 'timestamp', - data1.block.timestamp.toString() - ); - assert.fieldEquals( - 'StakeAllocatedEvent', - id1, - 'txHash', - data1.transaction.hash.toHex() - ); - assert.fieldEquals( - 'StakeAllocatedEvent', - id1, - 'staker', - data1.params.staker.toHex() - ); - assert.fieldEquals('StakeAllocatedEvent', id1, 'amount', '30'); - assert.fieldEquals( - 'StakeAllocatedEvent', - id1, - 'escrowAddress', - data1.params.escrowAddress.toHex() - ); - - // Data 2 - assert.fieldEquals( - 'StakeAllocatedEvent', - id2, - 'block', - data2.block.number.toString() - ); - assert.fieldEquals( - 'StakeAllocatedEvent', - id2, - 'timestamp', - data2.block.timestamp.toString() - ); - assert.fieldEquals( - 'StakeAllocatedEvent', - id2, - 'txHash', - data2.transaction.hash.toHex() - ); - assert.fieldEquals( - 'StakeAllocatedEvent', - id2, - 'staker', - data2.params.staker.toHex() - ); - assert.fieldEquals('StakeAllocatedEvent', id2, 'amount', '50'); - assert.fieldEquals( - 'StakeAllocatedEvent', - id2, - 'escrowAddress', - data2.params.escrowAddress.toHex() - ); - - // Leader statistics - assert.fieldEquals( - 'LeaderStatistics', - STATISTICS_ENTITY_ID.toHex(), - 'leaders', - '2' - ); - - // Leader - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountStaked', - '70' - ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountLocked', - '20' - ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'lockedUntilTimestamp', - '30' - ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountWithdrawn', - '30' - ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountAllocated', - '30' - ); - - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountStaked', - '100' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountLocked', - '0' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'lockedUntilTimestamp', - '0' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountWithdrawn', - '100' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountAllocated', - '50' - ); - - // Transaction - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'txHash', - data2.transaction.hash.toHex() - ); assert.fieldEquals( 'Transaction', data2.transaction.hash.toHex(), - 'method', - 'allocate' - ); - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'block', - data2.block.number.toString() - ); - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'from', - data2.transaction.from.toHex() - ); - assert.fieldEquals( - 'Transaction', - data2.transaction.hash.toHex(), - 'value', - '50' + 'token', + TOKEN_ADDRESS.toHexString() ); }); @@ -710,14 +544,14 @@ describe('Staking', () => { const data1 = createStakeSlashedEvent( '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', 10, - '0xD979105297fB0eee83F7433fC09279cb5B94fFC7', + escrow1AddressString, '0xD979105297fB0eee83F7433fC09279cb5B94fFC8', BigInt.fromI32(60) ); const data2 = createStakeSlashedEvent( '0x92a2eEF7Ff696BCef98957a0189872680600a959', 10, - '0x92a2eEF7Ff696BCef98957a0189872680600a95A', + escrow2AddressString, '0x92a2eEF7Ff696BCef98957a0189872680600a95B', BigInt.fromI32(61) ); @@ -763,8 +597,8 @@ describe('Staking', () => { assert.fieldEquals( 'StakeSlashedEvent', id1, - 'slasher', - data1.params.slasher.toHex() + 'slashRequester', + data1.params.slashRequester.toHex() ); // Data 2 @@ -802,8 +636,8 @@ describe('Staking', () => { assert.fieldEquals( 'StakeSlashedEvent', id2, - 'slasher', - data2.params.slasher.toHex() + 'slashRequester', + data2.params.slashRequester.toHex() ); // Leader statistics @@ -839,12 +673,6 @@ describe('Staking', () => { 'amountWithdrawn', '30' ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountAllocated', - '20' - ); assert.fieldEquals( 'Leader', data1.params.staker.toHex(), @@ -876,12 +704,6 @@ describe('Staking', () => { 'amountWithdrawn', '100' ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountAllocated', - '40' - ); assert.fieldEquals( 'Leader', data2.params.staker.toHex(), @@ -920,210 +742,61 @@ describe('Staking', () => { 'value', '10' ); - }); - - test('Should properly index AllocationClosed events', () => { - const data1 = createAllocationClosedEvent( - '0xD979105297fB0eee83F7433fC09279cb5B94fFC6', - 20, - '0xD979105297fB0eee83F7433fC09279cb5B94fFC7', - 70, - BigInt.fromI32(70) - ); - const data2 = createAllocationClosedEvent( - '0x92a2eEF7Ff696BCef98957a0189872680600a959', - 40, - '0x92a2eEF7Ff696BCef98957a0189872680600a95A', - 71, - BigInt.fromI32(71) - ); - - handleAllocationClosed(data1); - handleAllocationClosed(data2); - - const id1 = toEventId(data1).toHex(); - const id2 = toEventId(data2).toHex(); - - // Data 1 - assert.fieldEquals( - 'AllocationClosedEvent', - id1, - 'block', - data1.block.number.toString() - ); - assert.fieldEquals( - 'AllocationClosedEvent', - id1, - 'timestamp', - data1.block.timestamp.toString() - ); - assert.fieldEquals( - 'AllocationClosedEvent', - id1, - 'txHash', - data1.transaction.hash.toHex() - ); - assert.fieldEquals( - 'AllocationClosedEvent', - id1, - 'staker', - data1.params.staker.toHex() - ); - assert.fieldEquals('AllocationClosedEvent', id1, 'amount', '20'); - assert.fieldEquals( - 'AllocationClosedEvent', - id1, - 'escrowAddress', - data1.params.escrowAddress.toHex() - ); - - // Data 2 - assert.fieldEquals( - 'AllocationClosedEvent', - id2, - 'block', - data2.block.number.toString() - ); - assert.fieldEquals( - 'AllocationClosedEvent', - id2, - 'timestamp', - data2.block.timestamp.toString() - ); - assert.fieldEquals( - 'AllocationClosedEvent', - id2, - 'txHash', - data2.transaction.hash.toHex() - ); - assert.fieldEquals( - 'AllocationClosedEvent', - id2, - 'staker', - data2.params.staker.toHex() - ); - assert.fieldEquals('AllocationClosedEvent', id2, 'amount', '40'); - assert.fieldEquals( - 'AllocationClosedEvent', - id2, - 'escrowAddress', - data2.params.escrowAddress.toHex() - ); - - // Leader statistics - assert.fieldEquals( - 'LeaderStatistics', - STATISTICS_ENTITY_ID.toHex(), - 'leaders', - '2' - ); - - // Leader assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountStaked', - '60' - ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountLocked', - '20' - ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'lockedUntilTimestamp', - '30' - ); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountWithdrawn', - '30' + 'Transaction', + data2.transaction.hash.toHex(), + 'token', + TOKEN_ADDRESS.toHexString() ); assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountAllocated', - '0' + 'Transaction', + data2.transaction.hash.toHex(), + 'escrow', + escrow2Address.toHexString() ); + }); - assert.fieldEquals( - 'Leader', - data1.params.staker.toHex(), - 'amountSlashed', - '10' - ); + test('Should properly create transactions for FeeWithdrawn events', () => { + const data = createFeeWithdrawnEvent(10, BigInt.fromI32(60)); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountStaked', - '90' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountLocked', - '0' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'lockedUntilTimestamp', - '0' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountWithdrawn', - '100' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountAllocated', - '0' - ); - assert.fieldEquals( - 'Leader', - data2.params.staker.toHex(), - 'amountSlashed', - '10' - ); + handleFeeWithdrawn(data); // Transaction assert.fieldEquals( 'Transaction', - data2.transaction.hash.toHex(), + data.transaction.hash.toHex(), 'txHash', - data2.transaction.hash.toHex() + data.transaction.hash.toHex() ); assert.fieldEquals( 'Transaction', - data2.transaction.hash.toHex(), + data.transaction.hash.toHex(), 'method', - 'closeAllocation' + 'withdrawFees' ); assert.fieldEquals( 'Transaction', - data2.transaction.hash.toHex(), + data.transaction.hash.toHex(), 'block', - data2.block.number.toString() + data.block.number.toString() ); assert.fieldEquals( 'Transaction', - data2.transaction.hash.toHex(), - 'from', - data2.transaction.from.toHex() + data.transaction.hash.toHex(), + 'to', + stakingAddressString ); assert.fieldEquals( 'Transaction', - data2.transaction.hash.toHex(), + data.transaction.hash.toHex(), 'value', - '40' + '10' + ); + assert.fieldEquals( + 'Transaction', + data.transaction.hash.toHex(), + 'token', + TOKEN_ADDRESS.toHexString() ); }); }); diff --git a/packages/sdk/typescript/subgraph/tests/utils.ts b/packages/sdk/typescript/subgraph/tests/utils.ts new file mode 100644 index 0000000000..bbbbb7981b --- /dev/null +++ b/packages/sdk/typescript/subgraph/tests/utils.ts @@ -0,0 +1,11 @@ +import { Bytes, BigInt } from '@graphprotocol/graph-ts'; + +export function generateUniqueHash( + address: string, + timestamp: BigInt, + nonce: BigInt +): Bytes { + const uniqueString = + address + '-' + timestamp.toString() + '-' + nonce.toString(); + return Bytes.fromUTF8(uniqueString); +} diff --git a/scripts/fortune/docker-compose.yml b/scripts/fortune/docker-compose.yml index ed98924e45..a53d8b0157 100644 --- a/scripts/fortune/docker-compose.yml +++ b/scripts/fortune/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3.8' services: postgres: container_name: postgres @@ -87,4 +86,4 @@ services: hostname: ipfs image: ipfs/kubo:v0.14.0 ports: - - 5010:5001 \ No newline at end of file + - 5010:5001 diff --git a/yarn.lock b/yarn.lock index 8dfefd7490..d35095c2ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,9 @@ "@adobe/css-tools@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63" - integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ== + version "4.4.1" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.1.tgz#2447a230bfe072c1659e6815129c03cf170710e3" + integrity sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ== "@adraffy/ens-normalize@1.10.0": version "1.10.0" @@ -66,9 +66,9 @@ rxjs "7.8.1" "@apollo/client@^3.11.1": - version "3.11.8" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.11.8.tgz#f6bacdc7e1b243807c1387113e1d445a53471a9c" - integrity sha512-CgG1wbtMjsV2pRGe/eYITmV5B8lXUCYljB2gB/6jWTFQcrvirUVvKg7qtFdjYkQSFbIffU1IDyxgeaN81eTjbA== + version "3.11.10" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.11.10.tgz#e16ae82ea9b16536ffd109847d24f9293fab5c4d" + integrity sha512-IfGc+X4il0rDqVQBBWdxIKM+ciDCiDzBq9+Bg9z4tJMi87uF6po4v+ddiac1wP0ARgVPsFwEIGxK7jhN4pW8jg== dependencies: "@graphql-typed-document-node/core" "^3.1.1" "@wry/caches" "^1.0.0" @@ -126,11 +126,11 @@ tslib "^1.11.1" "@aws-sdk/types@^3.1.0": - version "3.679.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.679.0.tgz#3737bb0f190add9e788b838a24cd5d8106dbed4f" - integrity sha512-NwVq8YvInxQdJ47+zz4fH3BRRLC6lL+WLkvr242PVBbUOLRyK/lkwHlfiKUoeVIMyK5NF+up6TRg71t/8Bny6Q== + version "3.696.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.696.0.tgz#559c3df74dc389b6f40ba6ec6daffeab155330cd" + integrity sha512-9rTvUJIAj5d3//U5FDPWGJ1nFJLuWb30vugGOrWk7aNZ6y9tuA3PI7Cc9dP8WEXKVyK1vuuk8rSFP2iqXnlgrw== dependencies: - "@smithy/types" "^3.5.0" + "@smithy/types" "^3.7.1" tslib "^2.6.2" "@aws-sdk/util-utf8-browser@^3.0.0": @@ -154,7 +154,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.2.tgz#278b6b13664557de95b8f35b90d96785850bb56e" integrity sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.23.5", "@babel/core@^7.23.9", "@babel/core@^7.24.0", "@babel/core@^7.25.2": +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.23.5", "@babel/core@^7.23.9", "@babel/core@^7.24.0", "@babel/core@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== @@ -243,10 +243,10 @@ regexpu-core "^6.1.1" semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" - integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== +"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" + integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== dependencies: "@babel/helper-compilation-targets" "^7.22.6" "@babel/helper-plugin-utils" "^7.22.5" @@ -927,14 +927,14 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.25.9" -"@babel/plugin-transform-react-jsx-self@^7.24.7": +"@babel/plugin-transform-react-jsx-self@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-jsx-source@^7.24.7": +"@babel/plugin-transform-react-jsx-source@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== @@ -1230,15 +1230,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@coinbase/wallet-sdk@4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.1.0.tgz#3224a102b724dcb1a63005f371d596ae2999953b" - integrity sha512-SkJJ72X/AA3+aS21sPs/4o4t6RVeDSA7HuBW4zauySX3eBiPU0zmVw95tXH/eNSX50agKz9WzeN8P5F+HcwLOw== - dependencies: - "@noble/hashes" "^1.4.0" - clsx "^1.2.1" - eventemitter3 "^5.0.1" - preact "^10.16.0" +"@bytecodealliance/preview2-shim@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@bytecodealliance/preview2-shim/-/preview2-shim-0.17.0.tgz#9bc1cadbb9f86c446c6f579d3431c08a06a6672e" + integrity sha512-JorcEwe4ud0x5BS/Ar2aQWOQoFzjq/7jcnxYXCvSMh0oRm0dQXzOA+hqLDBnOMks1LLBA7dmiLLsEBl09Yd6iQ== "@coinbase/wallet-sdk@4.2.1": version "4.2.1" @@ -1251,6 +1246,16 @@ preact "^10.24.2" vitest "^2.1.2" +"@coinbase/wallet-sdk@4.2.3": + version "4.2.3" + resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.2.3.tgz#a30fa0605b24bc42c37f52a62d2442bcbb7734af" + integrity sha512-BcyHZ/Ec84z0emORzqdXDv4P0oV+tV3a0OirfA8Ko1JGBIAVvB+hzLvZzCDvnuZx7MTK+Dd8Y9Tjlo446BpCIg== + dependencies: + "@noble/hashes" "^1.4.0" + clsx "^1.2.1" + eventemitter3 "^5.0.1" + preact "^10.24.2" + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -1295,16 +1300,16 @@ dependencies: "@edge-runtime/primitives" "4.1.0" -"@emotion/babel-plugin@^11.12.0": - version "11.12.0" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2" - integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw== +"@emotion/babel-plugin@^11.13.5": + version "11.13.5" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz#eab8d65dbded74e0ecfd28dc218e75607c4e7bc0" + integrity sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ== dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/runtime" "^7.18.3" "@emotion/hash" "^0.9.2" "@emotion/memoize" "^0.9.0" - "@emotion/serialize" "^1.2.0" + "@emotion/serialize" "^1.3.3" babel-plugin-macros "^3.1.0" convert-source-map "^1.5.0" escape-string-regexp "^4.0.0" @@ -1312,14 +1317,14 @@ source-map "^0.5.7" stylis "4.2.0" -"@emotion/cache@^11.11.0", "@emotion/cache@^11.13.0": - version "11.13.1" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7" - integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw== +"@emotion/cache@^11.11.0", "@emotion/cache@^11.13.5": + version "11.13.5" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.5.tgz#e78dad0489e1ed7572507ba8ed9d2130529e4266" + integrity sha512-Z3xbtJ+UcK76eWkagZ1onvn/wAVb1GOMuR15s30Fm2wrMgC7jzpnO2JZXr4eujTTqoQFUrZIw/rT0c6Zzjca1g== dependencies: "@emotion/memoize" "^0.9.0" "@emotion/sheet" "^1.4.0" - "@emotion/utils" "^1.4.0" + "@emotion/utils" "^1.4.2" "@emotion/weak-memoize" "^0.4.0" stylis "4.2.0" @@ -1353,28 +1358,28 @@ integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== "@emotion/react@^11.10.5", "@emotion/react@^11.11.3", "@emotion/react@^11.11.4": - version "11.13.3" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.3.tgz#a69d0de2a23f5b48e0acf210416638010e4bd2e4" - integrity sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg== + version "11.13.5" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.5.tgz#fc818ff5b13424f86501ba4d0740f343ae20b8d9" + integrity sha512-6zeCUxUH+EPF1s+YF/2hPVODeV/7V07YU5x+2tfuRL8MdW6rv5vb2+CBEGTGwBdux0OIERcOS+RzxeK80k2DsQ== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.12.0" - "@emotion/cache" "^11.13.0" - "@emotion/serialize" "^1.3.1" + "@emotion/babel-plugin" "^11.13.5" + "@emotion/cache" "^11.13.5" + "@emotion/serialize" "^1.3.3" "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0" - "@emotion/utils" "^1.4.0" + "@emotion/utils" "^1.4.2" "@emotion/weak-memoize" "^0.4.0" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0", "@emotion/serialize@^1.3.1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.2.tgz#e1c1a2e90708d5d85d81ccaee2dfeb3cc0cccf7a" - integrity sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA== +"@emotion/serialize@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.3.tgz#d291531005f17d704d0463a032fe679f376509e8" + integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA== dependencies: "@emotion/hash" "^0.9.2" "@emotion/memoize" "^0.9.0" "@emotion/unitless" "^0.10.0" - "@emotion/utils" "^1.4.1" + "@emotion/utils" "^1.4.2" csstype "^3.0.2" "@emotion/sheet@^1.4.0": @@ -1383,16 +1388,16 @@ integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== "@emotion/styled@^11.10.5", "@emotion/styled@^11.11.0", "@emotion/styled@^11.11.5": - version "11.13.0" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.13.0.tgz#633fd700db701472c7a5dbef54d6f9834e9fb190" - integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA== + version "11.13.5" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.13.5.tgz#0fa6602227414c5e42cf267506e3c35bae655df9" + integrity sha512-gnOQ+nGLPvDXgIx119JqGalys64lhMdnNQA9TMxhDA4K0Hq5+++OE20Zs5GxiCV9r814xQ2K5WmtofSpHVW6BQ== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.12.0" + "@emotion/babel-plugin" "^11.13.5" "@emotion/is-prop-valid" "^1.3.0" - "@emotion/serialize" "^1.3.0" + "@emotion/serialize" "^1.3.3" "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0" - "@emotion/utils" "^1.4.0" + "@emotion/utils" "^1.4.2" "@emotion/unitless@0.8.1": version "0.8.1" @@ -1409,10 +1414,10 @@ resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf" integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw== -"@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.1.tgz#b3adbb43de12ee2149541c4f1337d2eb7774f0ad" - integrity sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA== +"@emotion/utils@^1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.2.tgz#6df6c45881fcb1c412d6688a311a98b7f59c1b52" + integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA== "@emotion/weak-memoize@^0.4.0": version "0.4.0" @@ -1424,116 +1429,236 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== +"@esbuild/aix-ppc64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c" + integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw== + "@esbuild/android-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== +"@esbuild/android-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0" + integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w== + "@esbuild/android-arm@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== +"@esbuild/android-arm@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810" + integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew== + "@esbuild/android-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== +"@esbuild/android-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705" + integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ== + "@esbuild/darwin-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== +"@esbuild/darwin-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz#2d0d9414f2acbffd2d86e98253914fca603a53dd" + integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw== + "@esbuild/darwin-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== +"@esbuild/darwin-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107" + integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA== + "@esbuild/freebsd-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== +"@esbuild/freebsd-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7" + integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA== + "@esbuild/freebsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== +"@esbuild/freebsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93" + integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ== + "@esbuild/linux-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== +"@esbuild/linux-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75" + integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g== + "@esbuild/linux-arm@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== +"@esbuild/linux-arm@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d" + integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw== + "@esbuild/linux-ia32@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== +"@esbuild/linux-ia32@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb" + integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA== + "@esbuild/linux-loong64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== +"@esbuild/linux-loong64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c" + integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g== + "@esbuild/linux-mips64el@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== +"@esbuild/linux-mips64el@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3" + integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA== + "@esbuild/linux-ppc64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== +"@esbuild/linux-ppc64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e" + integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ== + "@esbuild/linux-riscv64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== +"@esbuild/linux-riscv64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25" + integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw== + "@esbuild/linux-s390x@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== +"@esbuild/linux-s390x@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319" + integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g== + "@esbuild/linux-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== +"@esbuild/linux-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef" + integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA== + "@esbuild/netbsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== +"@esbuild/netbsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c" + integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg== + +"@esbuild/openbsd-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2" + integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg== + "@esbuild/openbsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== +"@esbuild/openbsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf" + integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q== + "@esbuild/sunos-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== +"@esbuild/sunos-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4" + integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA== + "@esbuild/win32-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== +"@esbuild/win32-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b" + integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA== + "@esbuild/win32-ia32@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== +"@esbuild/win32-ia32@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103" + integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw== + "@esbuild/win32-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== +"@esbuild/win32-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244" + integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" @@ -2814,6 +2939,17 @@ utf-8-validate "^5.0.2" uuid "^8.3.2" +"@metamask/sdk-communication-layer@0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.31.0.tgz#0acc063b62aa09d044c7aab65801712d760e53b2" + integrity sha512-V9CxdzabDPjQVgmKGHsyU3SYt4Af27g+4DbGCx0fLoHqN/i1RBDZqs/LYbJX3ykJCANzE+llz/MolMCMrzM2RA== + dependencies: + bufferutil "^4.0.8" + date-fns "^2.29.3" + debug "^4.3.4" + utf-8-validate "^5.0.2" + uuid "^8.3.2" + "@metamask/sdk-install-modal-web@0.30.0": version "0.30.0" resolved "https://registry.yarnpkg.com/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.30.0.tgz#9ec634201b1b47bb30064f42ae0efba7f204bb0a" @@ -2821,6 +2957,13 @@ dependencies: qr-code-styling "^1.6.0-rc.1" +"@metamask/sdk-install-modal-web@0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.31.0.tgz#2d1e297d8c1bae93cb458061d86dfaf777e8bdfa" + integrity sha512-nr8AZ+ccEfC3BmzTkT2wH16wOARqVrkhAFqsxYsnaozn+BAb+Hwo/GRhaIGzYgYFj/tTD3SM0UtXd6x2gzMDQw== + dependencies: + "@paulmillr/qr" "^0.2.1" + "@metamask/sdk@0.30.1": version "0.30.1" resolved "https://registry.yarnpkg.com/@metamask/sdk/-/sdk-0.30.1.tgz#63126ad769566098000cc3c2cd513d18808471f3" @@ -2847,6 +2990,31 @@ util "^0.12.4" uuid "^8.3.2" +"@metamask/sdk@0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@metamask/sdk/-/sdk-0.31.0.tgz#6b539f05f4a1a7b26136c5eda361d954ee6b3937" + integrity sha512-L1TKg7NkgCJbjkJsDTC6ZEpjGdroxsFksm17eGWPmNqdPf561ujJkU3xWCUPxEvU0hI+Wz3y2GegJsNej9/jWw== + dependencies: + "@babel/runtime" "^7.26.0" + "@metamask/onboarding" "^1.0.1" + "@metamask/providers" "16.1.0" + "@metamask/sdk-communication-layer" "0.31.0" + "@metamask/sdk-install-modal-web" "0.31.0" + "@paulmillr/qr" "^0.2.1" + bowser "^2.9.0" + cross-fetch "^4.0.0" + debug "^4.3.4" + eciesjs "^0.4.11" + eth-rpc-errors "^4.0.3" + eventemitter2 "^6.4.9" + obj-multiplex "^1.0.0" + pump "^3.0.0" + readable-stream "^3.6.2" + socket.io-client "^4.5.1" + tslib "^2.6.0" + util "^0.12.4" + uuid "^8.3.2" + "@metamask/superstruct@^3.0.0", "@metamask/superstruct@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@metamask/superstruct/-/superstruct-3.1.0.tgz#148f786a674fba3ac885c1093ab718515bf7f648" @@ -2909,9 +3077,9 @@ integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== "@microsoft/tsdoc@^0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz#f29a55df17cb6e87cfbabce33ff6a14a9f85076d" - integrity sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA== + version "0.15.1" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz#d4f6937353bc4568292654efb0a0e0532adbcba2" + integrity sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw== "@motionone/animation@^10.15.1", "@motionone/animation@^10.18.0": version "10.18.0" @@ -2995,41 +3163,41 @@ clsx "^2.1.0" prop-types "^15.8.1" -"@mui/core-downloads-tracker@^5.16.7": - version "5.16.7" - resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz#182a325a520f7ebd75de051fceabfc0314cfd004" - integrity sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ== +"@mui/core-downloads-tracker@^5.16.8": + version "5.16.8" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.8.tgz#b83316d14dad08fac7cd0574f2643b01959b4464" + integrity sha512-DARxShbBsWz6azwkTmv05rR7rJfcd9cXFsQtbcr24A+5esQBSnK2N3cbg/izlvuMGxonfWaysz/ae+6Ij9RAHQ== "@mui/icons-material@^6.1.1", "@mui/icons-material@^6.1.5": - version "6.1.6" - resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-6.1.6.tgz#bfaf32874a9f9ec88c07d1ca132d1a0671e9ed7c" - integrity sha512-5r9urIL2lxXb/sPN3LFfFYEibsXJUb986HhhIeu1gOcte460pwdSiEhBSxkAuyT8Dj7jvu9MjqSBmSumQELo8A== + version "6.1.9" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-6.1.9.tgz#68b1003d3e29db4f5d5e5f46a4333f34762aeeeb" + integrity sha512-AzlhIT51rdjkZ/EcUV2dbhNkNSUHIqCnNoUxodpiTw8buyAUBd+qnxg5OBSuPpun/ZEdSSB8Q7Uyh6zqjiMsEQ== dependencies: "@babel/runtime" "^7.26.0" "@mui/lab@^5.0.0-alpha.141": - version "5.0.0-alpha.173" - resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.173.tgz#a0f9696d93a765b48d69a7da5aaca0affa510ae8" - integrity sha512-Gt5zopIWwxDgGy/MXcp6GueD84xFFugFai4hYiXY0zowJpTVnIrTQCQXV004Q7rejJ7aaCntX9hpPJqCrioshA== + version "5.0.0-alpha.174" + resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.174.tgz#ca31049b7140a6717392b3b990264628c89fcf99" + integrity sha512-6jw+vcjfnDr/V4qzqwOPFwoqzxejGfm9F0k9E92QLmtFv5F0pH73OjmQDzALL7zrcwR4iV4D94iJZ1xFawiREA== dependencies: "@babel/runtime" "^7.23.9" "@mui/base" "5.0.0-beta.40" - "@mui/system" "^5.16.5" + "@mui/system" "^5.16.8" "@mui/types" "^7.2.15" - "@mui/utils" "^5.16.5" + "@mui/utils" "^5.16.8" clsx "^2.1.0" prop-types "^15.8.1" "@mui/material@^5.15.18", "@mui/material@^5.16.7": - version "5.16.7" - resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.7.tgz#6e814e2eefdaf065a769cecf549c3569e107a50b" - integrity sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg== + version "5.16.8" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.8.tgz#cf6a3784910fae05cbcd0a871eaca2821639d867" + integrity sha512-amnDx385shdQasC7wAk/oQjfti8N4wm0fLEcD7n5KXDZxn9Y+0VKEC+ieVseOUGuY5B2FqzdNfeVwUPTmUBszQ== dependencies: "@babel/runtime" "^7.23.9" - "@mui/core-downloads-tracker" "^5.16.7" - "@mui/system" "^5.16.7" + "@mui/core-downloads-tracker" "^5.16.8" + "@mui/system" "^5.16.8" "@mui/types" "^7.2.15" - "@mui/utils" "^5.16.6" + "@mui/utils" "^5.16.8" "@popperjs/core" "^2.11.8" "@types/react-transition-group" "^4.4.10" clsx "^2.1.0" @@ -3038,13 +3206,13 @@ react-is "^18.3.1" react-transition-group "^4.4.5" -"@mui/private-theming@^5.16.6": - version "5.16.6" - resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.6.tgz#547671e7ae3f86b68d1289a0b90af04dfcc1c8c9" - integrity sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw== +"@mui/private-theming@^5.16.8": + version "5.16.8" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.8.tgz#7914996caaf6eedc59914aeab83dcd2d4e4da1ec" + integrity sha512-3Vl9yFVLU6T3CFtxRMQTcJ60Ijv7wxQi4yjH92+9YXcsqvVspeIYoocqNoIV/1bXGYfyWu5zrCmwQVHaGY7bug== dependencies: "@babel/runtime" "^7.23.9" - "@mui/utils" "^5.16.6" + "@mui/utils" "^5.16.8" prop-types "^15.8.1" "@mui/styled-engine-sc@6.1.3": @@ -3057,26 +3225,26 @@ hoist-non-react-statics "^3.3.2" prop-types "^15.8.1" -"@mui/styled-engine@^5.16.6": - version "5.16.6" - resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.6.tgz#60110c106dd482dfdb7e2aa94fd6490a0a3f8852" - integrity sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g== +"@mui/styled-engine@^5.16.8": + version "5.16.8" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.8.tgz#b8ca35f93f503a51d0759a05475bfd28e10757ea" + integrity sha512-OFdgFf8JczSRs0kvWGdSn0ZeXxWrY0LITDPJ/nAtLEvUUTyrlFaO4il3SECX8ruzvf1VnAxHx4M/4mX9oOn9yA== dependencies: "@babel/runtime" "^7.23.9" "@emotion/cache" "^11.11.0" csstype "^3.1.3" prop-types "^15.8.1" -"@mui/system@^5.16.5", "@mui/system@^5.16.7": - version "5.16.7" - resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.7.tgz#4583ca5bf3b38942e02c15a1e622ba869ac51393" - integrity sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA== +"@mui/system@^5.16.8": + version "5.16.8" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.8.tgz#e5010d76cd2fdcc403ad3f98abfba99d330055ad" + integrity sha512-L32TaFDFpGIi1g6ysRtmhc9zDgrlxDXu3NlrGE8gAsQw/ziHrPdr0PNr20O0POUshA1q14W4dNZ/z0Nx2F9lhA== dependencies: "@babel/runtime" "^7.23.9" - "@mui/private-theming" "^5.16.6" - "@mui/styled-engine" "^5.16.6" + "@mui/private-theming" "^5.16.8" + "@mui/styled-engine" "^5.16.8" "@mui/types" "^7.2.15" - "@mui/utils" "^5.16.6" + "@mui/utils" "^5.16.8" clsx "^2.1.0" csstype "^3.1.3" prop-types "^15.8.1" @@ -3086,10 +3254,10 @@ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.19.tgz#c941954dd24393fdce5f07830d44440cf4ab6c80" integrity sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA== -"@mui/utils@^5.15.14", "@mui/utils@^5.16.5", "@mui/utils@^5.16.6": - version "5.16.6" - resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.6.tgz#905875bbc58d3dcc24531c3314a6807aba22a711" - integrity sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA== +"@mui/utils@^5.15.14", "@mui/utils@^5.16.8": + version "5.16.8" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.8.tgz#e44acf38d446d361347c46b3e81ae366f615f37b" + integrity sha512-P/yb7BSWallQUeiNGxb+TM8epHteIUC8gzNTdPV2VfKhVY/EnGliHgt5np0GPkjQ7EzwDi/+gBevrAJtf+K94A== dependencies: "@babel/runtime" "^7.23.9" "@mui/types" "^7.2.15" @@ -3099,9 +3267,9 @@ react-is "^18.3.1" "@mui/utils@^5.16.6 || ^6.0.0": - version "6.1.6" - resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-6.1.6.tgz#4b9fd34da3a1dd4700fe506a20ca7da3933ba48e" - integrity sha512-sBS6D9mJECtELASLM+18WUcXF6RH3zNxBRFeyCRg8wad6NbyNrdxLuwK+Ikvc38sTZwBzAz691HmSofLqHd9sQ== + version "6.1.9" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-6.1.9.tgz#821612300f66684054fd6e36336cfea91f050fbe" + integrity sha512-N7uzBp7p2or+xanXn3aH2OTINC6F/Ru/U8h6amhRZEev8bJhKN86rIDIoxZZ902tj+09LXtH83iLxFMjMHyqNA== dependencies: "@babel/runtime" "^7.26.0" "@mui/types" "^7.2.19" @@ -3111,9 +3279,9 @@ react-is "^18.3.1" "@mui/x-data-grid@^7.22.2": - version "7.22.2" - resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-7.22.2.tgz#2c7fce281b25785cde1af07698c4e555028d46d9" - integrity sha512-yfy2s5A6tbajQZiEdsba49T4FYb9F0WPrzbbG30dl1+sIiX4ZRX7ma44UIDGPZrsZv8xkkE+p8qeJxZ7OaMteA== + version "7.22.3" + resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-7.22.3.tgz#22c4c23212434c6256ed5d11f7ba12a8310f9c4b" + integrity sha512-O6kBf6yt/GkOcWjHca5xWN10qBQ/MkITvJmBuIOtX+LH7YtOAriMgD2zkhNbXxHChi7QdEud3bNC3jw5RLRVCA== dependencies: "@babel/runtime" "^7.25.7" "@mui/utils" "^5.16.6 || ^6.0.0" @@ -3123,9 +3291,9 @@ reselect "^5.1.1" "@mui/x-date-pickers@^7.5.0": - version "7.22.1" - resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-7.22.1.tgz#3abe7ad0b5816051fdcef4ffbe5343965e7dfc8e" - integrity sha512-VBgicE+7PvJrdHSL6HyieHT6a/0dENH8RaMIM2VwUFrGoZzvik50WNwY5U+Hip1BwZLIEvlqtNRQIIj6kgBR6Q== + version "7.22.3" + resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-7.22.3.tgz#bd1cf8f18aff58c7ff964c3b552a757947dc8c87" + integrity sha512-shNp92IrST5BiVy2f4jbrmRaD32QhyUthjh1Oexvpcn0v6INyuWgxfodoTi5ZCnE5Ue5UVFSs4R9Xre0UbJ5DQ== dependencies: "@babel/runtime" "^7.25.7" "@mui/utils" "^5.16.6 || ^6.0.0" @@ -3154,9 +3322,9 @@ integrity sha512-pxeBp9w/s99HaW2+pezM1P3fLiWmUEnTUoUMLa9UYViCtjj0E0A19W/vaT5JFACCzFIeNrwH4/16jkpAhQ25Vw== "@nestjs/cli@^10.3.2": - version "10.4.7" - resolved "https://registry.yarnpkg.com/@nestjs/cli/-/cli-10.4.7.tgz#c4170713e268eb0780f174fd07c605b01c43e273" - integrity sha512-4wJTtBJsbvjLIzXl+Qj6DYHv4J7abotuXyk7bes5erL79y+KBT61LulL56SqilzmNnHOAVbXcSXOn9S2aWUn6A== + version "10.4.8" + resolved "https://registry.yarnpkg.com/@nestjs/cli/-/cli-10.4.8.tgz#e6dec4eeda8a125918cbf1c0d10773ac6bb6d40e" + integrity sha512-BQ/MIXcO2TjLVR9ZCN1MRQqijgCI7taueLdxowLS9UmAHbN7iZcQt307NTC6SFt8uVJg2CrLanD60M/Pr0ZMoQ== dependencies: "@angular-devkit/core" "17.3.11" "@angular-devkit/schematics" "17.3.11" @@ -3167,21 +3335,21 @@ cli-table3 "0.6.5" commander "4.1.1" fork-ts-checker-webpack-plugin "9.0.2" - glob "10.4.2" + glob "10.4.5" inquirer "8.2.6" node-emoji "1.11.0" ora "5.4.1" tree-kill "1.2.2" tsconfig-paths "4.2.0" - tsconfig-paths-webpack-plugin "4.1.0" + tsconfig-paths-webpack-plugin "4.2.0" typescript "5.6.3" webpack "5.96.1" webpack-node-externals "3.0.0" "@nestjs/common@^10.2.7": - version "10.4.7" - resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.4.7.tgz#076cb77c06149805cb1e193d8cdc69bbe8446c75" - integrity sha512-gIOpjD3Mx8gfYGxYm/RHPcJzqdknNNFCyY+AxzBT3gc5Xvvik1Dn5OxaMGw5EbVfhZgJKVP0n83giUOAlZQe7w== + version "10.4.11" + resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.4.11.tgz#7cd1021561a1591e278c254daa06b2e1e7872c98" + integrity sha512-7MnKYckMsT/LGlwC0PCY8XZFWD84bxVwsPsn9H2RrLSbCCwUvcRb39ZkQt4uR+zKj2fq4TsV80+5DfjMwFvVdg== dependencies: uid "2.0.2" iterare "1.2.1" @@ -3197,9 +3365,9 @@ lodash "4.17.21" "@nestjs/core@^10.2.8", "@nestjs/core@^10.3.10": - version "10.4.7" - resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-10.4.7.tgz#adb27067a8c40b79f0713b417457fdfc6cf3406a" - integrity sha512-AIpQzW/vGGqSLkKvll1R7uaSNv99AxZI2EFyVJPNGDgFsfXaohfV1Ukl6f+s75Km+6Fj/7aNl80EqzNWQCS8Ig== + version "10.4.11" + resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-10.4.11.tgz#d71f57b62e8862ed1b9352baf75d7f39429bd007" + integrity sha512-S8wbxl08SZ2dgLRrIJNpesxI8ppn3y50XW3hH3HvKfUSjMEmCNIcGvge3WxJULiYkOUnmZ3ZqJAmKr2EjAGliA== dependencies: uid "2.0.2" "@nuxtjs/opencollective" "0.3.2" @@ -3216,7 +3384,12 @@ "@types/jsonwebtoken" "9.0.5" jsonwebtoken "9.0.2" -"@nestjs/mapped-types@*", "@nestjs/mapped-types@2.0.5": +"@nestjs/mapped-types@*": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.6.tgz#d2d8523709fd5d872a9b9e0c38162746e2a7f44e" + integrity sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ== + +"@nestjs/mapped-types@2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz#485d6b44e19779c98d04e52bd1d2bcc7001df0ea" integrity sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg== @@ -3227,9 +3400,9 @@ integrity sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ== "@nestjs/platform-express@^10.3.10": - version "10.4.7" - resolved "https://registry.yarnpkg.com/@nestjs/platform-express/-/platform-express-10.4.7.tgz#e0000464734af9e16e7de435cb63596b3d3982bc" - integrity sha512-q6XDOxZPTZ9cxALcVuKUlRBk+cVEv6dW2S8p2yVre22kpEQxq53/OI8EseDvzObGb6hepZ8+yBY04qoYqSlXNQ== + version "10.4.11" + resolved "https://registry.yarnpkg.com/@nestjs/platform-express/-/platform-express-10.4.11.tgz#5c80ae93dda45c3bac146bc560e0307747661b9a" + integrity sha512-YjhoIOdCbpxy3p5Em2pqYsUY+5cpyocguCzMI91qh41/jTAUzBD25K+hAiMyENZXEkDyscoF8OajyZvWm1ihdQ== dependencies: body-parser "1.20.3" cors "2.8.5" @@ -3284,9 +3457,9 @@ check-disk-space "3.4.0" "@nestjs/testing@^10.4.6": - version "10.4.7" - resolved "https://registry.yarnpkg.com/@nestjs/testing/-/testing-10.4.7.tgz#c8ef5c222f19e8069fda236b4e7a8504dd6a2dc0" - integrity sha512-aS3sQ0v4g8cyHDzW3xJv1+8MiFAkxUNXmnau588IFFI/nBIo/kevLNHNPr85keYekkJ/lwNDW72h8UGg8BYd9w== + version "10.4.11" + resolved "https://registry.yarnpkg.com/@nestjs/testing/-/testing-10.4.11.tgz#30505132bf49869f44321b759a5f4b3b2ee4811f" + integrity sha512-jpZwVrPfOvjZxdYMHasHko38XD+yuGAGJBM3qFQlZRQkZ+mEa6AuXUcMXihXWehHw7DXTeYi7u2hA+HN/wBBbw== dependencies: tslib "2.7.0" @@ -3305,9 +3478,9 @@ eslint-scope "5.1.1" "@noble/ciphers@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.0.0.tgz#34758a1cbfcd4126880f83e6b1cdeb88785b7970" - integrity sha512-wH5EHOmLi0rEazphPbecAzmjd12I6/Yv/SiHdkA9LSycsQk7RuuTp7am5/o62qYr0RScE7Pc9icXGBbsr6cesA== + version "1.1.2" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.1.2.tgz#d9f543a13896004d3dca49f6eb38933da117bb7a" + integrity sha512-7eTr/DCRCW+V9QaVGsfujw0mk7UOeRARbEz+fRzESRBfiBR3wsBzxOrYWNvqKTQjUfBFeSxJsVSfl6NJhZuYwg== "@noble/curves@1.2.0", "@noble/curves@~1.2.0": version "1.2.0" @@ -3323,13 +3496,20 @@ dependencies: "@noble/hashes" "1.4.0" -"@noble/curves@1.6.0", "@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.6.0": +"@noble/curves@1.6.0", "@noble/curves@~1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b" integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ== dependencies: "@noble/hashes" "1.5.0" +"@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== + dependencies: + "@noble/hashes" "1.6.0" + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -3345,11 +3525,21 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== -"@noble/hashes@1.5.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.5.0": +"@noble/hashes@1.5.0", "@noble/hashes@~1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== + +"@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== + "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" @@ -3386,53 +3576,53 @@ resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== -"@nomicfoundation/edr-darwin-arm64@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.4.tgz#6eaa64a6ea5201e4c92b121f2b7fd197b26e450a" - integrity sha512-QNQErISLgssV9+qia8sIjRANqtbW8snSDvjspixT/kSQ5ZSGxxctTg7x72wPSrcu8+EBEveIe5uqENIp5GH8HQ== +"@nomicfoundation/edr-darwin-arm64@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.5.tgz#37a31565d7ef42bed9028ac44aed82144de30bd1" + integrity sha512-A9zCCbbNxBpLgjS1kEJSpqxIvGGAX4cYbpDYCU2f3jVqOwaZ/NU761y1SvuCRVpOwhoCXqByN9b7HPpHi0L4hw== -"@nomicfoundation/edr-darwin-x64@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.4.tgz#d15ca89e9deef7d0a710cf90e79f3cc270a5a999" - integrity sha512-cjVmREiwByyc9+oGfvAh49IAw+oVJHF9WWYRD+Tm/ZlSpnEVWxrGNBak2bd/JSYjn+mZE7gmWS4SMRi4nKaLUg== +"@nomicfoundation/edr-darwin-x64@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.5.tgz#3252f6e86397af460b7a480bfe1b889464d75b89" + integrity sha512-x3zBY/v3R0modR5CzlL6qMfFMdgwd6oHrWpTkuuXnPFOX8SU31qq87/230f4szM+ukGK8Hi+mNq7Ro2VF4Fj+w== -"@nomicfoundation/edr-linux-arm64-gnu@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.4.tgz#e73c41ca015dfddb5f4cb6cd3d9b2cbe5cc28989" - integrity sha512-96o9kRIVD6W5VkgKvUOGpWyUGInVQ5BRlME2Fa36YoNsRQMaKtmYJEU0ACosYES6ZTpYC8U5sjMulvPtVoEfOA== +"@nomicfoundation/edr-linux-arm64-gnu@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.5.tgz#e7dc2934920b6cfabeb5ee7a5e26c8fb0d4964ac" + integrity sha512-HGpB8f1h8ogqPHTyUpyPRKZxUk2lu061g97dOQ/W4CxevI0s/qiw5DB3U3smLvSnBHKOzYS1jkxlMeGN01ky7A== -"@nomicfoundation/edr-linux-arm64-musl@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.4.tgz#90906f733e4ad26657baeb22d28855d934ab7541" - integrity sha512-+JVEW9e5plHrUfQlSgkEj/UONrIU6rADTEk+Yp9pbe+mzNkJdfJYhs5JYiLQRP4OjxH4QOrXI97bKU6FcEbt5Q== +"@nomicfoundation/edr-linux-arm64-musl@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.5.tgz#00459cd53e9fb7bd5b7e32128b508a6e89079d89" + integrity sha512-ESvJM5Y9XC03fZg9KaQg3Hl+mbx7dsSkTIAndoJS7X2SyakpL9KZpOSYrDk135o8s9P9lYJdPOyiq+Sh+XoCbQ== -"@nomicfoundation/edr-linux-x64-gnu@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.4.tgz#11b8bd73df145a192e5a08199e5e81995fcde502" - integrity sha512-nzYWW+fO3EZItOeP4CrdMgDXfaGBIBkKg0Y/7ySpUxLqzut40O4Mb0/+quqLAFkacUSWMlFp8nsmypJfOH5zoA== +"@nomicfoundation/edr-linux-x64-gnu@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.5.tgz#5c9e4e2655caba48e0196977cba395bbde6fe97d" + integrity sha512-HCM1usyAR1Ew6RYf5AkMYGvHBy64cPA5NMbaeY72r0mpKaH3txiMyydcHibByOGdQ8iFLWpyUdpl1egotw+Tgg== -"@nomicfoundation/edr-linux-x64-musl@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.4.tgz#a34b9a2c9e34853207824dc81622668a069ca642" - integrity sha512-QFRoE9qSQ2boRrVeQ1HdzU+XN7NUgwZ1SIy5DQt4d7jCP+5qTNsq8LBNcqhRBOATgO63nsweNUhxX/Suj5r1Sw== +"@nomicfoundation/edr-linux-x64-musl@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.5.tgz#9c220751b66452dc43a365f380e1e236a0a8c5a9" + integrity sha512-nB2uFRyczhAvWUH7NjCsIO6rHnQrof3xcCe6Mpmnzfl2PYcGyxN7iO4ZMmRcQS7R1Y670VH6+8ZBiRn8k43m7A== -"@nomicfoundation/edr-win32-x64-msvc@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.4.tgz#ca035c6f66ae9f88fa3ef123a1f3a2099cce7a5a" - integrity sha512-2yopjelNkkCvIjUgBGhrn153IBPLwnsDeNiq6oA0WkeM8tGmQi4td+PGi9jAriUDAkc59Yoi2q9hYA6efiY7Zw== +"@nomicfoundation/edr-win32-x64-msvc@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.5.tgz#90d3ac2a6a8a687522bda5ff2e92dd97e68126ea" + integrity sha512-B9QD/4DSSCFtWicO8A3BrsnitO1FPv7axB62wq5Q+qeJ50yJlTmyeGY3cw62gWItdvy2mh3fRM6L1LpnHiB77A== "@nomicfoundation/edr@^0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.6.4.tgz#1cd336c46a60f5af774e6cf0f1943f49f63dded6" - integrity sha512-YgrSuT3yo5ZQkbvBGqQ7hG+RDvz3YygSkddg4tb1Z0Y6pLXFzwrcEwWaJCFAVeeZxdxGfCgGMUYgRVneK+WXkw== + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.6.5.tgz#b3b1ebcdd0148cfe67cca128e7ebe8092e200359" + integrity sha512-tAqMslLP+/2b2sZP4qe9AuGxG3OkQ5gGgHE4isUuq6dUVjwCRPFhAOhpdFl+OjY5P3yEv3hmq9HjUGRa2VNjng== dependencies: - "@nomicfoundation/edr-darwin-arm64" "0.6.4" - "@nomicfoundation/edr-darwin-x64" "0.6.4" - "@nomicfoundation/edr-linux-arm64-gnu" "0.6.4" - "@nomicfoundation/edr-linux-arm64-musl" "0.6.4" - "@nomicfoundation/edr-linux-x64-gnu" "0.6.4" - "@nomicfoundation/edr-linux-x64-musl" "0.6.4" - "@nomicfoundation/edr-win32-x64-msvc" "0.6.4" + "@nomicfoundation/edr-darwin-arm64" "0.6.5" + "@nomicfoundation/edr-darwin-x64" "0.6.5" + "@nomicfoundation/edr-linux-arm64-gnu" "0.6.5" + "@nomicfoundation/edr-linux-arm64-musl" "0.6.5" + "@nomicfoundation/edr-linux-x64-gnu" "0.6.5" + "@nomicfoundation/edr-linux-x64-musl" "0.6.5" + "@nomicfoundation/edr-win32-x64-msvc" "0.6.5" "@nomicfoundation/ethereumjs-common@4.0.4": version "4.0.4" @@ -3483,12 +3673,12 @@ lodash.isequal "^4.5.0" "@nomicfoundation/hardhat-ignition@^0.15.5": - version "0.15.7" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.7.tgz#7e7c159c7da4773e3b23ca5fa8df88439e51952d" - integrity sha512-RFhGazR0/JqHxuuIxjjMmM+nWFqEvA7wcVqcX7vUqqmAIGuok4HhnWQH8aOvBaVguiXvvlFDJL0PIlxmkFgIUg== + version "0.15.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.8.tgz#d1a6bb508740959986ad256a4403570aec3d40d0" + integrity sha512-TN8TFQokcd7VyqGfbXO+KS8Q4K/gmsOFlv8dPnt/N596AncgV2Igxh5C3O+KVez11PDHNqoj1JzcDzzNVHrIRw== dependencies: - "@nomicfoundation/ignition-core" "^0.15.7" - "@nomicfoundation/ignition-ui" "^0.15.7" + "@nomicfoundation/ignition-core" "^0.15.8" + "@nomicfoundation/ignition-ui" "^0.15.8" chalk "^4.0.0" debug "^4.3.2" fs-extra "^10.0.0" @@ -3508,24 +3698,24 @@ integrity sha512-jhcWHp0aHaL0aDYj8IJl80v4SZXWMS1A2XxXa1CA6pBiFfJKuZinCkO6wb+POAt0LIfXB3gA3AgdcOccrcwBwA== "@nomicfoundation/hardhat-verify@^2.0.11", "@nomicfoundation/hardhat-verify@^2.0.8": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.11.tgz#4ce12b592e01ee93a81933924609c233ed00d951" - integrity sha512-lGIo4dNjVQFdsiEgZp3KP6ntLiF7xJEJsbNHfSyIiFCyI0Yv0518ElsFtMC5uCuHEChiBBMrib9jWQvHHT+X3Q== + version "2.0.12" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.12.tgz#480819a245a2db0b127e473c62079f7b4f16daa8" + integrity sha512-Lg3Nu7DCXASQRVI/YysjuAX2z8jwOCbS0w5tz2HalWGSTZThqA0v9N0v0psHbKNqzPJa8bNOeapIVSziyJTnAg== dependencies: "@ethersproject/abi" "^5.1.2" "@ethersproject/address" "^5.0.2" cbor "^8.1.0" - chalk "^2.4.2" debug "^4.1.1" lodash.clonedeep "^4.5.0" + picocolors "^1.1.0" semver "^6.3.0" table "^6.8.0" undici "^5.14.0" -"@nomicfoundation/ignition-core@^0.15.7": - version "0.15.7" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-core/-/ignition-core-0.15.7.tgz#ce205990f347737537b6a6c744ff1a245a2a3dc7" - integrity sha512-C4/0V/q2gNxKDt88cMr+Oxlf4NINQ7QgmJyciQ1/6UdCRUg+/Pgdgpd3vgGXQVTotq50Q/BU4ofNUAD/8HRqtg== +"@nomicfoundation/ignition-core@^0.15.8": + version "0.15.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-core/-/ignition-core-0.15.8.tgz#a5bf84f52d029d0305b5a34a289e6bb64bdcb5e6" + integrity sha512-U+CmTjKU9uwvh7qIabqboy/K/sDoClDgpsFRHoFvAj87DPDkXYb/mZBSkXPTU1wxTxrW6GTFE4lG3e7LAyF+kw== dependencies: "@ethersproject/address" "5.6.1" "@nomicfoundation/solidity-analyzer" "^0.1.1" @@ -3537,70 +3727,17 @@ lodash "4.17.21" ndjson "2.0.0" -"@nomicfoundation/ignition-ui@^0.15.7": - version "0.15.7" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.7.tgz#586371dd25d10360337a7363683dfb229b8c8622" - integrity sha512-pj2LmXylgbHOTNrkFqFrre/FAOjcwYl4VKIKVH/QMMBH/DatbiT8aC5n9o2fbLD8uwlPEesD+uXZuKCE71KFBg== - -"@nomicfoundation/slang-darwin-arm64@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-darwin-arm64/-/slang-darwin-arm64-0.17.0.tgz#8cded3c24322624e3b6618760caba8e840bd1c1d" - integrity sha512-O0q94EUtoWy9A5kOTOa9/khtxXDYnLqmuda9pQELurSiwbQEVCPQL8kb34VbOW+ifdre66JM/05Xw9JWhIZ9sA== - -"@nomicfoundation/slang-darwin-x64@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-darwin-x64/-/slang-darwin-x64-0.17.0.tgz#6ebeb33a2ced89fc6023f6cda4af96403486038a" - integrity sha512-IaDbHzvT08sBK2HyGzonWhq1uu8IxdjmTqAWHr25Oh/PYnamdi8u4qchZXXYKz/DHLoYN3vIpBXoqLQIomhD/g== - -"@nomicfoundation/slang-linux-arm64-gnu@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-arm64-gnu/-/slang-linux-arm64-gnu-0.17.0.tgz#41c7e57a9b1a3aee6911f0cab22e683c149fb470" - integrity sha512-Lj4anvOsQZxs1SycG8VyT2Rl2oqIhyLSUCgGepTt3CiJ/bM+8r8bLJIgh8vKkki4BWz49YsYIgaJB2IPv8FFTw== - -"@nomicfoundation/slang-linux-arm64-musl@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-arm64-musl/-/slang-linux-arm64-musl-0.17.0.tgz#9c4b51689274ae75c2c8a4cddd2e1cc0a79c191d" - integrity sha512-/xkTCa9d5SIWUBQE3BmLqDFfJRr4yUBwbl4ynPiGUpRXrD69cs6pWKkwjwz/FdBpXqVo36I+zY95qzoTj/YhOA== - -"@nomicfoundation/slang-linux-x64-gnu@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-x64-gnu/-/slang-linux-x64-gnu-0.17.0.tgz#c3a3b6a7b775fc617832958d10e6664bf86d39d0" - integrity sha512-oe5IO5vntOqYvTd67deCHPIWuSuWm6aYtT2/0Kqz2/VLtGz4ClEulBSRwfnNzBVtw2nksWipE1w8BzhImI7Syg== - -"@nomicfoundation/slang-linux-x64-musl@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-x64-musl/-/slang-linux-x64-musl-0.17.0.tgz#725118ff99a7217b9f1d1bd84411d9442084077d" - integrity sha512-PpYCI5K/kgLAMXaPY0V4VST5gCDprEOh7z/47tbI8kJQumI5odjsj/Cs8MpTo7/uRH6flKYbVNgUzcocWVYrAQ== - -"@nomicfoundation/slang-win32-arm64-msvc@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-arm64-msvc/-/slang-win32-arm64-msvc-0.17.0.tgz#9c8bc4ccf21eaaac0cfcb6d3954ede4e2dea4c02" - integrity sha512-u/Mkf7OjokdBilP7QOJj6QYJU4/mjkbKnTX21wLyCIzeVWS7yafRPYpBycKIBj2pRRZ6ceAY5EqRpb0aiCq+0Q== - -"@nomicfoundation/slang-win32-ia32-msvc@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-ia32-msvc/-/slang-win32-ia32-msvc-0.17.0.tgz#3fc5d00a3f8c1d85a5e94146af78a5526a4f3d27" - integrity sha512-XJBVQfNnZQUv0tP2JSJ573S+pmgrLWgqSZOGaMllnB/TL1gRci4Z7dYRJUF2s82GlRJE+FHSI2Ro6JISKmlXCg== - -"@nomicfoundation/slang-win32-x64-msvc@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-x64-msvc/-/slang-win32-x64-msvc-0.17.0.tgz#f6a5e3250fa07cbda49151edeb80f09090e5b71a" - integrity sha512-zPGsAeiTfqfPNYHD8BfrahQmYzA78ZraoHKTGraq/1xwJwzBK4bu/NtvVA4pJjBV+B4L6DCxVhSbpn40q26JQA== +"@nomicfoundation/ignition-ui@^0.15.8": + version "0.15.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.8.tgz#8c0dacec4809d8b90724a1901866656222beeda9" + integrity sha512-VUD5MsWrrv7E2P0AJO01pV8w8m66Du0uwBKXM0oUV5DRIzqm6eYHt9eCDb1KBINDpiFxOQiuyWQMdeKxgPp3qw== -"@nomicfoundation/slang@^0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang/-/slang-0.17.0.tgz#d9c25cd711ebf3490c9d0c99e9b4ca2481341a6b" - integrity sha512-1GlkGRcGpVnjFw9Z1vvDKOKo2mzparFt7qrl2pDxWp+jrVtlvej98yCMX52pVyrYE7ZeOSZFnx/DtsSgoukStQ== - dependencies: - "@nomicfoundation/slang-darwin-arm64" "0.17.0" - "@nomicfoundation/slang-darwin-x64" "0.17.0" - "@nomicfoundation/slang-linux-arm64-gnu" "0.17.0" - "@nomicfoundation/slang-linux-arm64-musl" "0.17.0" - "@nomicfoundation/slang-linux-x64-gnu" "0.17.0" - "@nomicfoundation/slang-linux-x64-musl" "0.17.0" - "@nomicfoundation/slang-win32-arm64-msvc" "0.17.0" - "@nomicfoundation/slang-win32-ia32-msvc" "0.17.0" - "@nomicfoundation/slang-win32-x64-msvc" "0.17.0" +"@nomicfoundation/slang@^0.18.3": + version "0.18.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang/-/slang-0.18.3.tgz#976b6c3820081cebf050afbea434038aac9313cc" + integrity sha512-YqAWgckqbHM0/CZxi9Nlf4hjk9wUNLC9ngWCWBiqMxPIZmzsVKYuChdlrfeBPQyvQQBoOhbx+7C1005kLVQDZQ== + dependencies: + "@bytecodealliance/preview2-shim" "0.17.0" "@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": version "0.1.2" @@ -3811,53 +3948,53 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.2.tgz#b1d03075e49290d06570b2fd42154d76c2a5d210" integrity sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA== -"@openzeppelin/defender-sdk-base-client@^1.14.4", "@openzeppelin/defender-sdk-base-client@^1.15.1": - version "1.15.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.15.1.tgz#4ff72f25af903d24283dbe5bdd59af28829567dd" - integrity sha512-z3ZoDDRgRAlkaOFrY1SoHK/hn6LWlnfuFvs7WAA+nahlltS9UN7ro4v6P2aUq4ZQH2kZg5JeNfHCkpkRFaGa5Q== +"@openzeppelin/defender-sdk-base-client@^1.14.4", "@openzeppelin/defender-sdk-base-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.15.2.tgz#aae7ec001365968b81ccce087f39a6eb52fa13f9" + integrity sha512-N3ZTeH8TXyklL7yNPMLUv0dxQwT78DTkOEDhzMS2/QE2FxbXrclSseoeeXxl6UYI61RBtZKn+okbSsbwiB5QWQ== dependencies: amazon-cognito-identity-js "^6.3.6" async-retry "^1.3.3" "@openzeppelin/defender-sdk-deploy-client@^1.14.4": - version "1.15.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.15.1.tgz#da56912495a913642080af9f5d8e825769cec148" - integrity sha512-seJajiWFCM+dbMIv3290TOEsygeWyGa9DQxPESpFwXvlLxfPcKN/o8g+4bs98BmC9v6d0q5ckoWA8iEuzEBLpA== + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.15.2.tgz#3b1d953aa66b6cdee13e7e672a488af2e2acf974" + integrity sha512-zspzMqh+OC8arXAkgBqTUDVO+NfCkt54UrsmQHbA3UAjr5TiDXKycBKU5ORb01hE+2gAmoPwEpDW9uS2VLg33A== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.15.1" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" lodash "^4.17.21" "@openzeppelin/defender-sdk-network-client@^1.14.4": - version "1.15.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.15.1.tgz#37f1a1cd3b58bbc03cb60c336cbbdf49f68b341b" - integrity sha512-X09to21R7UjWMstDTmY+F8B6N+4c0B/hNio++fRsCs8kgO/ZcBLAQ3HDFgCBRVmhRI8+Qpa2uqc673aU6hW10A== + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.15.2.tgz#7178836d9861272ad509d93dea8739a5c4bf86c1" + integrity sha512-9r9pegc1aR7xzP9fmj1zvkk0OXMRJE10JabxxiJzAQQgmNXDeTGI6W5bFgrNJfxzcImNGqddJ3K4weKdLyL21A== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.15.1" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" lodash "^4.17.21" "@openzeppelin/hardhat-upgrades@^3.3.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.5.0.tgz#90ed0508fed8415b7fa9ee1c04ade8ec57091d46" - integrity sha512-Ju/JnT7NRiOMi5m5Y0dGiz37d8wnjVBep1v5Vr7+6+MFNuQa1yddUEVWhWhoEw4udI3/mYwyw4Sfz3sq7vhicQ== + version "3.6.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.6.0.tgz#8a252d6015b21ade1f5151816b6bc7b12348df53" + integrity sha512-RuVuCciCfFOqCyKSJ2D4Zffp3hxhvXTn16JzTlD9cx3A7V/2d3JA75tpRHD7RVPic+dcSFIf+BZRWOHuhc2ayg== dependencies: "@openzeppelin/defender-sdk-base-client" "^1.14.4" "@openzeppelin/defender-sdk-deploy-client" "^1.14.4" "@openzeppelin/defender-sdk-network-client" "^1.14.4" - "@openzeppelin/upgrades-core" "^1.40.0" + "@openzeppelin/upgrades-core" "^1.41.0" chalk "^4.1.0" debug "^4.1.1" ethereumjs-util "^7.1.5" proper-lockfile "^4.1.1" undici "^6.11.1" -"@openzeppelin/upgrades-core@^1.32.2", "@openzeppelin/upgrades-core@^1.40.0": - version "1.40.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.40.0.tgz#f01647afb99b46356b3e7b98e3b2c7f864d85add" - integrity sha512-4bPSXdEqHsNRL5T1ybPLneWGYjzGl6XWGWkv7aUoFFgz8mOdarstRBX1Wi4XJFw6IeHPUI7mMSQr2jdz8Y2ypQ== +"@openzeppelin/upgrades-core@^1.32.2", "@openzeppelin/upgrades-core@^1.41.0": + version "1.41.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.41.0.tgz#3a5e044cf53acd50c392f3297e7c37e4ff8f8355" + integrity sha512-+oryinqZnxkiZvg7bWqWX4Ki/CNwVUZEqC6Elpi5PQoahpL3/6Sq9xjIozD5AiI2O61h8JHQ+A//5NtczyavJw== dependencies: - "@nomicfoundation/slang" "^0.17.0" + "@nomicfoundation/slang" "^0.18.3" cbor "^9.0.0" chalk "^4.1.0" compare-versions "^6.0.0" @@ -3966,6 +4103,11 @@ "@parcel/watcher-win32-ia32" "2.5.0" "@parcel/watcher-win32-x64" "2.5.0" +"@paulmillr/qr@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@paulmillr/qr/-/qr-0.2.1.tgz#76ade7080be4ac4824f638146fd8b6db1805eeca" + integrity sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ== + "@peculiar/asn1-schema@^2.3.13", "@peculiar/asn1-schema@^2.3.8": version "2.3.13" resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.13.tgz#ec8509cdcbc0da3abe73fd7e690556b57a61b8f4" @@ -4110,10 +4252,10 @@ redux-thunk "^3.1.0" reselect "^5.1.0" -"@remix-run/router@1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.20.0.tgz#03554155b45d8b529adf635b2f6ad1165d70d8b4" - integrity sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg== +"@remix-run/router@1.21.0": + version "1.21.0" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.21.0.tgz#c65ae4262bdcfe415dbd4f64ec87676e4a56e2b5" + integrity sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA== "@reown/appkit-adapter-wagmi@1.3.2": version "1.3.2" @@ -4280,95 +4422,95 @@ estree-walker "^2.0.2" picomatch "^4.0.2" -"@rollup/rollup-android-arm-eabi@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz#c460b54c50d42f27f8254c435a4f3b3e01910bc8" - integrity sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw== - -"@rollup/rollup-android-arm64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz#96e01f3a04675d8d5973ab8d3fd6bc3be21fa5e1" - integrity sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA== - -"@rollup/rollup-darwin-arm64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz#9b2ec23b17b47cbb2f771b81f86ede3ac6730bce" - integrity sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ== - -"@rollup/rollup-darwin-x64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz#f30e4ee6929e048190cf10e0daa8e8ae035b6e46" - integrity sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg== - -"@rollup/rollup-freebsd-arm64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz#c54b2373ec5bcf71f08c4519c7ae80a0b6c8e03b" - integrity sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw== - -"@rollup/rollup-freebsd-x64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz#3bc53aa29d5a34c28ba8e00def76aa612368458e" - integrity sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g== - -"@rollup/rollup-linux-arm-gnueabihf@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz#c85aedd1710c9e267ee86b6d1ce355ecf7d9e8d9" - integrity sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA== - -"@rollup/rollup-linux-arm-musleabihf@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz#e77313408bf13995aecde281aec0cceb08747e42" - integrity sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw== - -"@rollup/rollup-linux-arm64-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz#633f632397b3662108cfaa1abca2a80b85f51102" - integrity sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg== - -"@rollup/rollup-linux-arm64-musl@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz#63edd72b29c4cced93e16113a68e1be9fef88907" - integrity sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA== - -"@rollup/rollup-linux-powerpc64le-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz#a9418a4173df80848c0d47df0426a0bf183c4e75" - integrity sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA== - -"@rollup/rollup-linux-riscv64-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz#bc9c195db036a27e5e3339b02f51526b4ce1e988" - integrity sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw== - -"@rollup/rollup-linux-s390x-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz#1651fdf8144ae89326c01da5d52c60be63e71a82" - integrity sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ== - -"@rollup/rollup-linux-x64-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz#e473de5e4acb95fcf930a35cbb7d3e8080e57a6f" - integrity sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA== - -"@rollup/rollup-linux-x64-musl@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz#0af12dd2578c29af4037f0c834b4321429dd5b01" - integrity sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q== - -"@rollup/rollup-win32-arm64-msvc@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz#e48e78cdd45313b977c1390f4bfde7ab79be8871" - integrity sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA== - -"@rollup/rollup-win32-ia32-msvc@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz#a3fc8536d243fe161c796acb93eba43c250f311c" - integrity sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg== - -"@rollup/rollup-win32-x64-msvc@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz#e2a9d1fd56524103a6cc8a54404d9d3ebc73c454" - integrity sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg== +"@rollup/rollup-android-arm-eabi@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz#e3c9cc13f144ba033df4d2c3130a214dc8e3473e" + integrity sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw== + +"@rollup/rollup-android-arm64@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz#0474250fcb5871aca952e249a0c3270fc4310b55" + integrity sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA== + +"@rollup/rollup-darwin-arm64@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz#77c29b4f9c430c1624f1a6835f2a7e82be3d16f2" + integrity sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q== + +"@rollup/rollup-darwin-x64@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz#7d87711f641a458868758cbf110fb32eabd6a25a" + integrity sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ== + +"@rollup/rollup-freebsd-arm64@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz#662f808d2780e4e91021ac9ee7ed800862bb9a57" + integrity sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw== + +"@rollup/rollup-freebsd-x64@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz#71e5a7bcfcbe51d8b65d158675acec1307edea79" + integrity sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA== + +"@rollup/rollup-linux-arm-gnueabihf@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz#08f67fcec61ee18f8b33b3f403a834ab8f3aa75d" + integrity sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w== + +"@rollup/rollup-linux-arm-musleabihf@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz#2e1ad4607f86475b1731556359c6070eb8f4b109" + integrity sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A== + +"@rollup/rollup-linux-arm64-gnu@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz#c65d559dcb0d3dabea500cf7b8215959ae6cccf8" + integrity sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg== + +"@rollup/rollup-linux-arm64-musl@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz#6739f7eb33e20466bb88748519c98ce8dee23922" + integrity sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA== + +"@rollup/rollup-linux-powerpc64le-gnu@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz#8d9fe9471c256e55278cb1f7b1c977cd8fe6df20" + integrity sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ== + +"@rollup/rollup-linux-riscv64-gnu@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz#9a467f7ad5b61c9d66b24e79a3c57cb755d02c35" + integrity sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw== + +"@rollup/rollup-linux-s390x-gnu@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz#efaddf22df27b87a267a731fbeb9539e92cd4527" + integrity sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg== + +"@rollup/rollup-linux-x64-gnu@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz#a959eccb04b07fd1591d7ff745a6865faa7042cd" + integrity sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q== + +"@rollup/rollup-linux-x64-musl@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz#927764f1da1f2dd50943716dec93796d10cb6e99" + integrity sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw== + +"@rollup/rollup-win32-arm64-msvc@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz#030b6cc607d845da23dced624e47fb45de105840" + integrity sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A== + +"@rollup/rollup-win32-ia32-msvc@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz#3457a3f44a84f51d8097c3606429e01f0d2d0ec2" + integrity sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ== + +"@rollup/rollup-win32-x64-msvc@4.27.4": + version "4.27.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz#67d516613c9f2fe42e2d8b78e252d0003179d92c" + integrity sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug== "@rtsao/scc@^1.1.0": version "1.1.0" @@ -4388,6 +4530,14 @@ "@safe-global/safe-apps-sdk" "^9.1.0" events "^3.3.0" +"@safe-global/safe-apps-provider@0.18.4": + version "0.18.4" + resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.4.tgz#53df912aa20d933f6b14c5bcb0737a8cd47def57" + integrity sha512-SWYeG3gyTO6wGHMSokfHakZ9isByn2mHsM0VohIorYFFEyGGmJ89btnTm+DqDUSoQtvWAatZB7XNy6CaYMvqtg== + dependencies: + "@safe-global/safe-apps-sdk" "^9.1.0" + events "^3.3.0" + "@safe-global/safe-apps-sdk@9.1.0", "@safe-global/safe-apps-sdk@^9.1.0": version "9.1.0" resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz#0e65913e0f202e529ed3c846e0f5a98c2d35aa98" @@ -4397,11 +4547,16 @@ viem "^2.1.1" "@safe-global/safe-gateway-typescript-sdk@^3.5.3": - version "3.22.2" - resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.2.tgz#d4ff9972e58f9344fc95f8d41b2ec6517baa8e79" - integrity sha512-Y0yAxRaB98LFp2Dm+ACZqBSdAmI3FlpH/LjxOZ94g/ouuDJecSq0iR26XZ5QDuEL8Rf+L4jBJaoDC08CD0KkJw== + version "3.22.4" + resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.4.tgz#9109a538df40f778666a3e6776e7a08c757e893d" + integrity sha512-Z7Z8w3GEJdJ/paF+NK23VN4AwqWPadq0AeRYjYLjIBiPWpRB2UO/FKq7ONABEq0YFgNPklazIV4IExQU1gavXA== + +"@scure/base@^1.1.3", "@scure/base@~1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" + integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== -"@scure/base@^1.1.3", "@scure/base@~1.1.0", "@scure/base@~1.1.2", "@scure/base@~1.1.6", "@scure/base@~1.1.7", "@scure/base@~1.1.8": +"@scure/base@~1.1.0", "@scure/base@~1.1.2", "@scure/base@~1.1.6", "@scure/base@~1.1.7", "@scure/base@~1.1.8": version "1.1.9" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== @@ -4433,7 +4588,7 @@ "@noble/hashes" "~1.4.0" "@scure/base" "~1.1.6" -"@scure/bip32@1.5.0", "@scure/bip32@^1.5.0": +"@scure/bip32@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.5.0.tgz#dd4a2e1b8a9da60e012e776d954c4186db6328e6" integrity sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw== @@ -4442,6 +4597,15 @@ "@noble/hashes" "~1.5.0" "@scure/base" "~1.1.7" +"@scure/bip32@^1.5.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891" + integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA== + dependencies: + "@noble/curves" "~1.7.0" + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -4466,7 +4630,7 @@ "@noble/hashes" "~1.4.0" "@scure/base" "~1.1.6" -"@scure/bip39@1.4.0", "@scure/bip39@^1.4.0": +"@scure/bip39@1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.4.0.tgz#664d4f851564e2e1d4bffa0339f9546ea55960a6" integrity sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw== @@ -4474,6 +4638,14 @@ "@noble/hashes" "~1.5.0" "@scure/base" "~1.1.8" +"@scure/bip39@^1.4.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be" + integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A== + dependencies: + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + "@sendgrid/client@^8.1.4": version "8.1.4" resolved "https://registry.yarnpkg.com/@sendgrid/client/-/client-8.1.4.tgz#4db39e49d8ed732169d73b5d5c94d2b11907970d" @@ -4565,39 +4737,39 @@ "@sentry/types" "5.30.0" tslib "^1.9.3" -"@shikijs/core@1.22.2": - version "1.22.2" - resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.22.2.tgz#9c22bd4cc8a4d6c062461cfd35e1faa6c617ca25" - integrity sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg== +"@shikijs/core@1.24.0": + version "1.24.0" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.24.0.tgz#5a90301df89f3a60d5ed9610d6537631fcd1c506" + integrity sha512-6pvdH0KoahMzr6689yh0QJ3rCgF4j1XsXRHNEeEN6M4xJTfQ6QPWrmHzIddotg+xPJUPEPzYzYCKzpYyhTI6Gw== dependencies: - "@shikijs/engine-javascript" "1.22.2" - "@shikijs/engine-oniguruma" "1.22.2" - "@shikijs/types" "1.22.2" + "@shikijs/engine-javascript" "1.24.0" + "@shikijs/engine-oniguruma" "1.24.0" + "@shikijs/types" "1.24.0" "@shikijs/vscode-textmate" "^9.3.0" "@types/hast" "^3.0.4" hast-util-to-html "^9.0.3" -"@shikijs/engine-javascript@1.22.2": - version "1.22.2" - resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz#62e90dbd2ed1d78b972ad7d0a1f8ffaaf5e43279" - integrity sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw== +"@shikijs/engine-javascript@1.24.0": + version "1.24.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.24.0.tgz#7f7f7afd3210601ba9c7d966f00c7a167f9f6453" + integrity sha512-ZA6sCeSsF3Mnlxxr+4wGEJ9Tto4RHmfIS7ox8KIAbH0MTVUkw3roHPHZN+LlJMOHJJOVupe6tvuAzRpN8qK1vA== dependencies: - "@shikijs/types" "1.22.2" + "@shikijs/types" "1.24.0" "@shikijs/vscode-textmate" "^9.3.0" - oniguruma-to-js "0.4.3" + oniguruma-to-es "0.7.0" -"@shikijs/engine-oniguruma@1.22.2": - version "1.22.2" - resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz#b12a44e3faf486e19fbcf8952f4b56b9b9b8d9b8" - integrity sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA== +"@shikijs/engine-oniguruma@1.24.0": + version "1.24.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.0.tgz#4e6f49413fbc96dabfa30cb232ca1acf5ca1a446" + integrity sha512-Eua0qNOL73Y82lGA4GF5P+G2+VXX9XnuUxkiUuwcxQPH4wom+tE39kZpBFXfUuwNYxHSkrSxpB1p4kyRW0moSg== dependencies: - "@shikijs/types" "1.22.2" + "@shikijs/types" "1.24.0" "@shikijs/vscode-textmate" "^9.3.0" -"@shikijs/types@1.22.2": - version "1.22.2" - resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.22.2.tgz#695a283f19963fe0638fc2646862ba5cfc4623a8" - integrity sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg== +"@shikijs/types@1.24.0": + version "1.24.0" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.24.0.tgz#a1755b125cb8fb1780a876a0a57242939eafd79f" + integrity sha512-aptbEuq1Pk88DMlCe+FzXNnBZ17LCiLIGWAeCWhoFDzia5Q5Krx3DgnULLiouSdd6+LUM39XwXGppqYE0Ghtug== dependencies: "@shikijs/vscode-textmate" "^9.3.0" "@types/hast" "^3.0.4" @@ -4643,10 +4815,10 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@smithy/types@^3.5.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.6.0.tgz#03a52bfd62ee4b7b2a1842c8ae3ada7a0a5ff3a4" - integrity sha512-8VXK/KzOHefoC65yRgCn5vG1cysPJjHnOVt9d0ybFQSmJgQj152vMn4EkYhGuaOmnnZvCPav/KnYyE6/KsNZ2w== +"@smithy/types@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.1.tgz#4af54c4e28351e9101996785a33f2fdbf93debe7" + integrity sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA== dependencies: tslib "^2.6.2" @@ -4660,6 +4832,11 @@ resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.18.0.tgz#8e77a02a09ecce957255a2f48c9a7178ec191908" integrity sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA== +"@solidity-parser/parser@^0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.19.0.tgz#37a8983b2725af9b14ff8c4a475fa0e98d773c3f" + integrity sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA== + "@sqltools/formatter@^1.2.5": version "1.2.5" resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12" @@ -4800,16 +4977,16 @@ "@stablelib/wipe" "^1.0.1" "@stripe/react-stripe-js@^2.4.0": - version "2.8.1" - resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-2.8.1.tgz#63d9a666749f818b1bf4eb788eb1bc57eb496f3d" - integrity sha512-C410jVKOATinXLalWotab6E6jlWAlbqUDWL9q1km0p5UHrvnihjjYzA8imYXc4xc4Euf9GeKDQc4n35HKZvgwg== + version "2.9.0" + resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-2.9.0.tgz#1f1a9a3d5eab8ca144e060df1e9fd855a7658aca" + integrity sha512-+/j2g6qKAKuWSurhgRMfdlIdKM+nVVJCy/wl0US2Ccodlqx0WqfIIBhUkeONkCG+V/b+bZzcj4QVa3E/rXtT4Q== dependencies: prop-types "^15.7.2" "@stripe/stripe-js@^4.2.0": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-4.9.0.tgz#95dc000b2f90aeb4db2f2bab82a2fc574f26d1fd" - integrity sha512-tMPZQZZXGWyNX7hbgenq+1xEj2oigJ54XddbtSX36VedoKsPBq7dxwRXu4Xd5FdpT3JDyyDtnmvYkaSnH1yHTQ== + version "4.10.0" + resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-4.10.0.tgz#5c785f9a5a500113d69d98c16061e0addd1c0305" + integrity sha512-KrMOL+sH69htCIXCaZ4JluJ35bchuCCznyPyrbN8JXSGQfwBI1SuIEMZNwvy8L8ykj29t6sa5BAAiL7fNoLZ8A== "@svgr/babel-plugin-add-jsx-attribute@8.0.0": version "8.0.0" @@ -4900,11 +5077,11 @@ integrity sha512-Oa3vVDq8Um2lJ2L1nG/vCPdOzTF6ccgbizrtaLPf/37VjbiLr4CGb1fVqMhzsMFs0niK4qL97NZni7DR/8nDmg== "@tanstack/eslint-plugin-query@^5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.60.1.tgz#ce4d1307d5801834949607d8f60b2ff835ccf1fe" - integrity sha512-oCaWtFKa6WwX14fm/Sp486eTFXXgadiDzEYxhM/tiAlM+xzvPwp6ZHgR6sndmvYK+s/jbksDCTLIPS0PCH8L2g== + version "5.61.6" + resolved "https://registry.yarnpkg.com/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.61.6.tgz#4fa72360532ecdf2dc0198b2be722a8c2e0b6c4e" + integrity sha512-39DEve67KRcUOv4WI3svSyKzFGEhPTH4gzy99UBh2PmrDOUvAjfG59zSheNJFLHHokpSOQYJhFRNuMlC00CBMw== dependencies: - "@typescript-eslint/utils" "^8.3.0" + "@typescript-eslint/utils" "^8.15.0" "@tanstack/match-sorter-utils@8.19.4": version "8.19.4" @@ -4913,75 +5090,51 @@ dependencies: remove-accents "0.5.0" -"@tanstack/query-core@5.59.17": - version "5.59.17" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.59.17.tgz#bda3bb678be48e2f6ee692abd1cfc2db3d455e4b" - integrity sha512-jWdDiif8kaqnRGHNXAa9CnudtxY5v9DUxXhodgqX2Rwzj+1UwStDHEbBd9IA5C7VYAaJ2s+BxFR6PUBs8ERorA== +"@tanstack/query-core@5.61.5": + version "5.61.5" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.61.5.tgz#3ba80527f6474b5edbf348c1b0a6254b3cdfe160" + integrity sha512-iG5vqurEOEbv+paP6kW3zPENa99kSIrd1THISJMaTwVlJ+N5yjVDNOUwp9McK2DWqWCXM3v13ubBbAyhxT78UQ== -"@tanstack/query-core@5.60.5": - version "5.60.5" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.60.5.tgz#37b7c5ab7e6894cea9ef341299a7a3febc2ea361" - integrity sha512-jiS1aC3XI3BJp83ZiTuDLerTmn9P3U95r6p+6/SNauLJaYxfIC4dMuWygwnBHIZxjn2zJqEpj3nysmPieoxfPQ== +"@tanstack/query-devtools@5.61.4": + version "5.61.4" + resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.61.4.tgz#86a3be0ffb97d810525600e3787b5b69808cf9db" + integrity sha512-21Tw+u8E3IJJj4A/Bct4H0uBaDTEu7zBrR79FeSyY+mS2gx5/m316oDtJiKkILc819VSTYt+sFzODoJNcpPqZQ== -"@tanstack/query-core@5.60.6": - version "5.60.6" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.60.6.tgz#0dd33fe231b0d18bf66d0c615b29899738300658" - integrity sha512-tI+k0KyCo1EBJ54vxK1kY24LWj673ujTydCZmzEZKAew4NqZzTaVQJEuaG1qKj2M03kUHN46rchLRd+TxVq/zQ== - -"@tanstack/query-devtools@5.59.19": - version "5.59.19" - resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.59.19.tgz#ef82f09a88b585450168640578eb43824da75037" - integrity sha512-Gw+3zsADpqiYgx/6MMr9bP1+x2LR8vOuGjo5Un/89qwwP3z7WAHPWFagLFDYkLq68NX7ekUpW/EOYlUMugMXGA== - -"@tanstack/query-persist-client-core@5.59.17": - version "5.59.17" - resolved "https://registry.yarnpkg.com/@tanstack/query-persist-client-core/-/query-persist-client-core-5.59.17.tgz#7aa14614cf64e5d0d4262caf0cb65e8efddcb1ef" - integrity sha512-2buT5Un3fxsdYmfdRvNS62i7z0oDkTsaydAcDhmekl3jeiU/hK+X4OhV8i+jnvjEb9u+0i3aUWm9kvzlh77TXQ== +"@tanstack/query-persist-client-core@5.61.5": + version "5.61.5" + resolved "https://registry.yarnpkg.com/@tanstack/query-persist-client-core/-/query-persist-client-core-5.61.5.tgz#12b99e5b05233c96bf953f40c2e2cb0985431488" + integrity sha512-YqJ4aN96brRTSzZN/WEcoid3pUK0h+6wvIhx4Qb6+BEDDHAUj/2jaD4eHqnn8H6YlfnFT6LXfqYv4Z4dwgfLZA== dependencies: - "@tanstack/query-core" "5.59.17" + "@tanstack/query-core" "5.61.5" "@tanstack/query-sync-storage-persister@^5.59.0": - version "5.59.17" - resolved "https://registry.yarnpkg.com/@tanstack/query-sync-storage-persister/-/query-sync-storage-persister-5.59.17.tgz#0bf54c5b46a0dda6fcf3cf11ef1d40500de4d3c4" - integrity sha512-JWCj1/Vl7mA/uzO6yXzcZCUg9XHU0O/6DjkCOwM00eJDn18epCYeOlvPWvTapvUDKVFsv4kcAWtyxeSyuPlvtA== + version "5.61.5" + resolved "https://registry.yarnpkg.com/@tanstack/query-sync-storage-persister/-/query-sync-storage-persister-5.61.5.tgz#6d1ad4a1995351c3396a179853e8cbd7ff53e900" + integrity sha512-X3MtyV9yvQy1lWL0nieTSCS9vNedn0RD2EDNtW1BYxt2hRuxx3qMldx8LogZHn5xtyJ9B7oDdVfhIqWBvQFPTw== dependencies: - "@tanstack/query-core" "5.59.17" - "@tanstack/query-persist-client-core" "5.59.17" + "@tanstack/query-core" "5.61.5" + "@tanstack/query-persist-client-core" "5.61.5" "@tanstack/react-query-devtools@^5.59.16": - version "5.59.19" - resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.59.19.tgz#446bc0e0aa83321a5635f82368ba2580aa6deb29" - integrity sha512-mYFWTHLtJr2HdyYPZPzzvQ2ksCsSL6L04fCtusPFD3waskXrtmvWvyuDIGeEGdVAYS0Urwxw/0sYvcTVQZH+zQ== + version "5.61.5" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.61.5.tgz#0c89cd3d7e883f603c22a2f8b061b23c7dab3ab6" + integrity sha512-P2DwlKyoGar6FX2XL324gM7AX8fuXm6DecLvfUoGpWbxtbuAtfzglRiCDLKkc5tJ7pekuaZsFFas/cyfTymoCQ== dependencies: - "@tanstack/query-devtools" "5.59.19" + "@tanstack/query-devtools" "5.61.4" "@tanstack/react-query-persist-client@^5.51.11": - version "5.59.19" - resolved "https://registry.yarnpkg.com/@tanstack/react-query-persist-client/-/react-query-persist-client-5.59.19.tgz#a3b107e51a9280b27ca88cd1ffedc9c46e872bb6" - integrity sha512-rUq/ITDyW5tulkfczfBaB562+tk0Cfz8VS6GQWTLBBvk6P8Fdg/+R+27YeMnnYVYId99NPI14SCbnsFS9YOnDQ== - dependencies: - "@tanstack/query-persist-client-core" "5.59.17" - -"@tanstack/react-query@^5.48.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.61.0.tgz#73473feb37aa28ceb410e297ee060e18f06f88e0" - integrity sha512-SBzV27XAeCRBOQ8QcC94w2H1Md0+LI0gTWwc3qRJoaGuewKn5FNW4LSqwPFJZVEItfhMfGT7RpZuSFXjTi12pQ== + version "5.61.5" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-persist-client/-/react-query-persist-client-5.61.5.tgz#6fc006288c0e8f9405fac1e6d49d5221f30d2233" + integrity sha512-Ot0goy9omtjRy2I6KX0j/NKqNlWIMVWlNoc4P8sXF/xXQD8Ks+6eStqzADspm5Wmp7F3JnQgPGuzlSYqseSUtA== dependencies: - "@tanstack/query-core" "5.60.6" + "@tanstack/query-persist-client-core" "5.61.5" -"@tanstack/react-query@^5.60.5": - version "5.60.5" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.60.5.tgz#3194c390f7eff20542b321c3042880dc3f1a81e2" - integrity sha512-M77bOsPwj1wYE56gk7iJvxGAr4IC12NWdIDhT+Eo8ldkWRHMvIR8I/rufIvT1OXoV/bl7EECwuRuMlxxWtvW2Q== +"@tanstack/react-query@^5.48.0", "@tanstack/react-query@^5.60.5", "@tanstack/react-query@^5.61.0": + version "5.61.5" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.61.5.tgz#abe26e5f2d7c9c6c0643579abfd9119ac22a88c8" + integrity sha512-rjy8aqPgBBEz/rjJnpnuhi8TVkVTorMUsJlM3lMvrRb5wK6yzfk34Er0fnJ7w/4qyF01SnXsLB/QsTBsLF5PaQ== dependencies: - "@tanstack/query-core" "5.60.5" - -"@tanstack/react-query@^5.61.0": - version "5.61.0" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.61.0.tgz#73473feb37aa28ceb410e297ee060e18f06f88e0" - integrity sha512-SBzV27XAeCRBOQ8QcC94w2H1Md0+LI0gTWwc3qRJoaGuewKn5FNW4LSqwPFJZVEItfhMfGT7RpZuSFXjTi12pQ== - dependencies: - "@tanstack/query-core" "5.60.6" + "@tanstack/query-core" "5.61.5" "@tanstack/react-table@8.20.5": version "8.20.5" @@ -5007,10 +5160,10 @@ resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.10.6.tgz#babe3989b2344a5f12fc64129f9bbed5d3402999" integrity sha512-1giLc4dzgEKLMx5pgKjL6HlG5fjZMgCjzlKAlpr7yoUtetVPELgER1NtephAI910nMwfPTHNyWKSFmJdHkz2Cw== -"@tenderly/api-client@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tenderly/api-client/-/api-client-1.0.1.tgz#0238bf5cc48e9a87a8f4b4c4a13743aab8721ea8" - integrity sha512-u/982299rccyvkuGuyM93AxnGXFHpIs8ZozD+E8gXHIRxLPyz/rZW/mjrcOGW9EBJwCvimVpLKcdDTKQ+DJTlQ== +"@tenderly/api-client@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@tenderly/api-client/-/api-client-1.1.0.tgz#fa06adf17ecc1ef83c5fb8536b71b542e7023228" + integrity sha512-kyye7TQ+RbDbJ7bSUjNf/O9fTtRYNUDIEUZQSrmNonowMw5/EpNi664eWaOoC00NEzxgttVrtme/GHvIOu7rNg== dependencies: axios "^0.27.2" cli-table3 "^0.6.2" @@ -5021,12 +5174,12 @@ prompts "^2.4.2" tslog "^4.4.0" -"@tenderly/hardhat-integration@^1.0.0": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tenderly/hardhat-integration/-/hardhat-integration-1.0.2.tgz#639519ad1d47bf11bf68d34a30355a50ed85130f" - integrity sha512-ZcmorNYGEdmNJ2SVZx90bpOcK43Ay6fOAJem+qbL3o8iRlxfcDvr72kTBq7Ed/CPyfvLWBVwcyGxQIsQWNMruQ== +"@tenderly/hardhat-integration@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@tenderly/hardhat-integration/-/hardhat-integration-1.1.0.tgz#028abf38950d72d0bd59efe57e76ec365762f1a7" + integrity sha512-JGeEneTnI/OuQ0SGJVAgt5o67hMVWw34RSNeaKokAGelzaAkJ5SA3gWZcUgPXRytdEmOIQusPVOFlE0dyiG4Yw== dependencies: - "@tenderly/api-client" "^1.0.0" + "@tenderly/api-client" "^1.1.0" axios "^1.6.7" dotenv "^16.4.5" fs-extra "^10.1.0" @@ -5038,9 +5191,9 @@ typescript "^5.5.4" "@tenderly/hardhat-tenderly@^2.0.1": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-2.4.0.tgz#c1a7e5fc4a88323169253f24a9c0d7acc61bf1b9" - integrity sha512-WbKdjJ03JK2lTjtkNorOQiN6QRqzBkCUbkPcxfYAJHEaQSfIEZrP9Ui7mFl1quP9L5mFfu8PFZtXcxzzHGIBWA== + version "2.5.1" + resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-2.5.1.tgz#b15544a2690d71e4a76e008f820e9afa921834d2" + integrity sha512-RdDl4gY5W2ZYistPkIIdHZRe3vHqs6JOgqQjqmI2OaE9y5FRlPeVUHRLAqoroVU+PkQhFPrgjBv5er/pJSonLA== dependencies: "@ethersproject/bignumber" "^5.7.0" "@nomicfoundation/hardhat-ethers" "^3.0.0" @@ -5048,7 +5201,7 @@ "@nomicfoundation/hardhat-verify" "^2.0.8" "@openzeppelin/hardhat-upgrades" "^3.3.0" "@openzeppelin/upgrades-core" "^1.32.2" - "@tenderly/hardhat-integration" "^1.0.0" + "@tenderly/hardhat-integration" "^1.1.0" dotenv "^16.4.5" ethers "^6.8.1" @@ -5321,9 +5474,9 @@ "@types/d3-path" "*" "@types/d3-time@*", "@types/d3-time@^3.0.0": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" - integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== "@types/d3-timer@^3.0.0": version "3.0.2" @@ -5374,9 +5527,9 @@ "@types/send" "*" "@types/express-serve-static-core@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz#3c9997ae9d00bc236e45c6374e84f2596458d9db" - integrity sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA== + version "5.0.2" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz#812d2871e5eea17fb0bd5214dda7a7b748c0e12a" + integrity sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg== dependencies: "@types/node" "*" "@types/qs" "*" @@ -5596,9 +5749,9 @@ integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/mocha@^10.0.8": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.9.tgz#101e9da88d2c02e5ac8952982c23b224524d662a" - integrity sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q== + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== "@types/ms@*": version "0.7.34" @@ -5613,11 +5766,11 @@ "@types/react" "*" "@types/node@*", "@types/node@>=13.7.0", "@types/node@>=8.1.0", "@types/node@^22.5.4": - version "22.9.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.0.tgz#b7f16e5c3384788542c72dc3d561a7ceae2c0365" - integrity sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ== + version "22.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.1.tgz#41ffeee127b8975a05f8c4f83fb89bcb2987d766" + integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ== dependencies: - undici-types "~6.19.8" + undici-types "~6.20.0" "@types/node@16.18.11": version "16.18.11" @@ -6032,13 +6185,13 @@ "@typescript-eslint/types" "7.18.0" "@typescript-eslint/visitor-keys" "7.18.0" -"@typescript-eslint/scope-manager@8.13.0": - version "8.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz#2f4aed0b87d72360e64e4ea194b1fde14a59082e" - integrity sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA== +"@typescript-eslint/scope-manager@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz#ebc9a3b399a69a6052f3d88174456dd399ef5905" + integrity sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg== dependencies: - "@typescript-eslint/types" "8.13.0" - "@typescript-eslint/visitor-keys" "8.13.0" + "@typescript-eslint/types" "8.16.0" + "@typescript-eslint/visitor-keys" "8.16.0" "@typescript-eslint/type-utils@5.62.0": version "5.62.0" @@ -6085,10 +6238,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9" integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ== -"@typescript-eslint/types@8.13.0": - version "8.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.13.0.tgz#3f35dead2b2491a04339370dcbcd17bbdfc204d8" - integrity sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng== +"@typescript-eslint/types@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.16.0.tgz#49c92ae1b57942458ab83d9ec7ccab3005e64737" + integrity sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -6131,13 +6284,13 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/typescript-estree@8.13.0": - version "8.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz#db8c93dd5437ca3ce417a255fb35ddc3c12c3e95" - integrity sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g== +"@typescript-eslint/typescript-estree@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz#9d741e56e5b13469b5190e763432ce5551a9300c" + integrity sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw== dependencies: - "@typescript-eslint/types" "8.13.0" - "@typescript-eslint/visitor-keys" "8.13.0" + "@typescript-eslint/types" "8.16.0" + "@typescript-eslint/visitor-keys" "8.16.0" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" @@ -6182,15 +6335,15 @@ "@typescript-eslint/types" "7.18.0" "@typescript-eslint/typescript-estree" "7.18.0" -"@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/utils@^8.3.0", "@typescript-eslint/utils@^8.4.0": - version "8.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.13.0.tgz#f6d40e8b5053dcaeabbd2e26463857abf27d62c0" - integrity sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ== +"@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/utils@^8.15.0", "@typescript-eslint/utils@^8.4.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.16.0.tgz#c71264c437157feaa97842809836254a6fc833c3" + integrity sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "8.13.0" - "@typescript-eslint/types" "8.13.0" - "@typescript-eslint/typescript-estree" "8.13.0" + "@typescript-eslint/scope-manager" "8.16.0" + "@typescript-eslint/types" "8.16.0" + "@typescript-eslint/typescript-estree" "8.16.0" "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" @@ -6216,28 +6369,28 @@ "@typescript-eslint/types" "7.18.0" eslint-visitor-keys "^3.4.3" -"@typescript-eslint/visitor-keys@8.13.0": - version "8.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz#e97b0d92b266ef38a1faf40a74da289b66683a5b" - integrity sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw== +"@typescript-eslint/visitor-keys@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz#d5086afc060b01ff7a4ecab8d49d13d5a7b07705" + integrity sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ== dependencies: - "@typescript-eslint/types" "8.13.0" - eslint-visitor-keys "^3.4.3" + "@typescript-eslint/types" "8.16.0" + eslint-visitor-keys "^4.2.0" "@ungap/structured-clone@^1.0.0", "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@vercel/build-utils@8.4.12": - version "8.4.12" - resolved "https://registry.yarnpkg.com/@vercel/build-utils/-/build-utils-8.4.12.tgz#8c5dcd4269bc2347b89424805d28e2661a3aa302" - integrity sha512-pIH0b965wJhd1otROVPndfZenPKFVoYSaRjtSKVOT/oNBT13ifq86UVjb5ZjoVfqUI2TtSTP+68kBqLPeoq30g== +"@vercel/build-utils@8.6.0": + version "8.6.0" + resolved "https://registry.yarnpkg.com/@vercel/build-utils/-/build-utils-8.6.0.tgz#c58d3551d6917795038bbcf1921aa678379cda7b" + integrity sha512-shST7/8zY0Oi2uxgwt9S/fjat96Ohpt0bXB+4/TeekdDmIIIL8t+mg9ASEg1WGF8JjWqWx+tYQfXlvv7d/D+dg== -"@vercel/error-utils@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@vercel/error-utils/-/error-utils-2.0.2.tgz#d75ccce100dbdfc9cb85700767b59d4257a91113" - integrity sha512-Sj0LFafGpYr6pfCqrQ82X6ukRl5qpmVrHM/191kNYFqkkB9YkjlMAj6QcEsvCG259x4QZ7Tya++0AB85NDPbKQ== +"@vercel/error-utils@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@vercel/error-utils/-/error-utils-2.0.3.tgz#72575bf3a3ff3e67f474364e24e753d113c5b79a" + integrity sha512-CqC01WZxbLUxoiVdh9B/poPbNpY9U+tO1N9oWHwTl5YAZxcqXmmWJ8KNMFItJCUUWdY3J3xv8LvAuQv2KZ5YdQ== "@vercel/nft@0.27.3": version "0.27.3" @@ -6258,16 +6411,16 @@ resolve-from "^5.0.0" "@vercel/node@^3.0.26": - version "3.2.24" - resolved "https://registry.yarnpkg.com/@vercel/node/-/node-3.2.24.tgz#1c52a264e1355ee39f9bf87575f3b2442106b1ef" - integrity sha512-KEm50YBmcfRNOw5NfdcqMI4BkP4+5TD9kRwAByHHlIZXLj1NTTknvMF+69sHBYzwpK/SUZIkeo7jTrtcl4g+RQ== + version "3.2.27" + resolved "https://registry.yarnpkg.com/@vercel/node/-/node-3.2.27.tgz#7ec19723b142bcb6fa809bfca7928420a8375b5c" + integrity sha512-vvTBD8Rz2jgbnm9/mTe+wB1rh/uISr7HRkyECUt92IlI4tYxOf/vS7ARgR86TGzb9WDwTrnRVxCl92q//f7hHA== dependencies: "@edge-runtime/node-utils" "2.3.0" "@edge-runtime/primitives" "4.1.0" "@edge-runtime/vm" "3.2.0" "@types/node" "16.18.11" - "@vercel/build-utils" "8.4.12" - "@vercel/error-utils" "2.0.2" + "@vercel/build-utils" "8.6.0" + "@vercel/error-utils" "2.0.3" "@vercel/nft" "0.27.3" "@vercel/static-config" "3.0.0" async-listen "3.0.0" @@ -6319,13 +6472,13 @@ prettier-plugin-packagejson "^2.4.12" "@vitejs/plugin-react@^4.2.1", "@vitejs/plugin-react@^4.3.1": - version "4.3.3" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz#28301ac6d7aaf20b73a418ee5c65b05519b4836c" - integrity sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA== + version "4.3.4" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz#c64be10b54c4640135a5b28a2432330e88ad7c20" + integrity sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug== dependencies: - "@babel/core" "^7.25.2" - "@babel/plugin-transform-react-jsx-self" "^7.24.7" - "@babel/plugin-transform-react-jsx-source" "^7.24.7" + "@babel/core" "^7.26.0" + "@babel/plugin-transform-react-jsx-self" "^7.25.9" + "@babel/plugin-transform-react-jsx-source" "^7.25.9" "@types/babel__core" "^7.20.5" react-refresh "^0.14.2" @@ -6338,36 +6491,29 @@ "@vitest/utils" "1.6.0" chai "^4.3.10" -"@vitest/expect@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.5.tgz#5a6afa6314cae7a61847927bb5bc038212ca7381" - integrity sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q== +"@vitest/expect@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.6.tgz#5a334eb9ee9287292fbe961955cafb06f7af7da6" + integrity sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg== dependencies: - "@vitest/spy" "2.1.5" - "@vitest/utils" "2.1.5" + "@vitest/spy" "2.1.6" + "@vitest/utils" "2.1.6" chai "^5.1.2" tinyrainbow "^1.2.0" -"@vitest/mocker@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.5.tgz#54ee50648bc0bb606dfc58e13edfacb8b9208324" - integrity sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ== +"@vitest/mocker@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.6.tgz#d13c5a7bd0abf432e1030f68acb43f51c4b3692e" + integrity sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A== dependencies: - "@vitest/spy" "2.1.5" + "@vitest/spy" "2.1.6" estree-walker "^3.0.3" magic-string "^0.30.12" -"@vitest/pretty-format@2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.4.tgz#fc31993bdc1ef5a6c1a4aa6844e7ba55658a4f9f" - integrity sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww== - dependencies: - tinyrainbow "^1.2.0" - -"@vitest/pretty-format@2.1.5", "@vitest/pretty-format@^2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.5.tgz#bc79b8826d4a63dc04f2a75d2944694039fa50aa" - integrity sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw== +"@vitest/pretty-format@2.1.6", "@vitest/pretty-format@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.6.tgz#9bc642047a3efc637b41492b1f222c43be3822e4" + integrity sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA== dependencies: tinyrainbow "^1.2.0" @@ -6380,12 +6526,12 @@ p-limit "^5.0.0" pathe "^1.1.1" -"@vitest/runner@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.5.tgz#4d5e2ba2dfc0af74e4b0f9f3f8be020559b26ea9" - integrity sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g== +"@vitest/runner@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.6.tgz#948cad2cccfe2e56be5b3f9979cf9a417ca59737" + integrity sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA== dependencies: - "@vitest/utils" "2.1.5" + "@vitest/utils" "2.1.6" pathe "^1.1.2" "@vitest/snapshot@1.6.0": @@ -6397,12 +6543,12 @@ pathe "^1.1.1" pretty-format "^29.7.0" -"@vitest/snapshot@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.5.tgz#a09a8712547452a84e08b3ec97b270d9cc156b4f" - integrity sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg== +"@vitest/snapshot@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.6.tgz#21740449221e37f80c4a8fb3e15f100f30e7934d" + integrity sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw== dependencies: - "@vitest/pretty-format" "2.1.5" + "@vitest/pretty-format" "2.1.6" magic-string "^0.30.12" pathe "^1.1.2" @@ -6413,24 +6559,24 @@ dependencies: tinyspy "^2.2.0" -"@vitest/spy@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.5.tgz#f790d1394a5030644217ce73562e92465e83147e" - integrity sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw== +"@vitest/spy@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.6.tgz#229f9d48b90b8bdd6573723bdec0699915598080" + integrity sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ== dependencies: tinyspy "^3.0.2" "@vitest/ui@^2.1.1": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-2.1.4.tgz#fcd0928c1d24301e4e5c2d3783150a0c391966ff" - integrity sha512-Zd9e5oU063c+j9N9XzGJagCLNvG71x/2tOme3Js4JEZKX55zsgxhJwUgLI8hkN6NjMLpdJO8d7nVUUuPGAA58Q== + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-2.1.6.tgz#50555594138df76d16324d17356df83f92bb62ff" + integrity sha512-SrpLAM0/xpOjXBDv3mayFh5TDEYM59fmEmJXgp1AqtpUWHVw4Tonp6Z9dVBhChU/Q+BY57m74nrQZK8vxKDrMQ== dependencies: - "@vitest/utils" "2.1.4" + "@vitest/utils" "2.1.6" fflate "^0.8.2" flatted "^3.3.1" pathe "^1.1.2" sirv "^3.0.0" - tinyglobby "^0.2.9" + tinyglobby "^0.2.10" tinyrainbow "^1.2.0" "@vitest/utils@1.6.0": @@ -6443,36 +6589,15 @@ loupe "^2.3.7" pretty-format "^29.7.0" -"@vitest/utils@2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.4.tgz#6d67ac966647a21ce8bc497472ce230de3b64537" - integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg== - dependencies: - "@vitest/pretty-format" "2.1.4" - loupe "^3.1.2" - tinyrainbow "^1.2.0" - -"@vitest/utils@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.5.tgz#0e19ce677c870830a1573d33ee86b0d6109e9546" - integrity sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg== +"@vitest/utils@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.6.tgz#2af6a82c5c45da35ecd322d0568247a6e9c95c5f" + integrity sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ== dependencies: - "@vitest/pretty-format" "2.1.5" + "@vitest/pretty-format" "2.1.6" loupe "^3.1.2" tinyrainbow "^1.2.0" -"@wagmi/connectors@5.3.4": - version "5.3.4" - resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-5.3.4.tgz#a39218fbd11f0f93cb9af697b1d982e74b647adb" - integrity sha512-z37wFxKyZwfNWfS8rS6nZ+TbqLAp68HLFEW4FsamHzddJeAy1CddEmwF7jIQ07aZbupRhJTclVWqys/mG4T2HA== - dependencies: - "@coinbase/wallet-sdk" "4.1.0" - "@metamask/sdk" "0.30.1" - "@safe-global/safe-apps-provider" "0.18.3" - "@safe-global/safe-apps-sdk" "9.1.0" - "@walletconnect/ethereum-provider" "2.17.0" - cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3" - "@wagmi/connectors@5.3.7": version "5.3.7" resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-5.3.7.tgz#6a7fc28cfe773e770aa8f8d385241d153361525c" @@ -6485,14 +6610,17 @@ "@walletconnect/ethereum-provider" "2.17.0" cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3" -"@wagmi/core@2.14.2": - version "2.14.2" - resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-2.14.2.tgz#0697e13ac1dbf3bbec3f79d0bdffa4e7ee290dcf" - integrity sha512-FugfZ2/4E4unj1VODvDznfK0iff8krZ1CpBv4Ckf/XK7t54Had71tokTgqvhsYDIcxPhVBfeGHMWFxugmhzAmA== +"@wagmi/connectors@5.5.2": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-5.5.2.tgz#88c5dc72e82da1d4d7c0290be0c131b4e4b63178" + integrity sha512-QYXDGu7ELr88R2ijkNMhVN402Vt9EXGrtHSMLq7u9pSu/N4mODZvXbvE9RWQ8PNrtCKGYLrHxI/oUGjCf1zxzQ== dependencies: - eventemitter3 "5.0.1" - mipd "0.0.7" - zustand "5.0.0" + "@coinbase/wallet-sdk" "4.2.3" + "@metamask/sdk" "0.31.0" + "@safe-global/safe-apps-provider" "0.18.4" + "@safe-global/safe-apps-sdk" "9.1.0" + "@walletconnect/ethereum-provider" "2.17.0" + cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3" "@wagmi/core@2.14.4": version "2.14.4" @@ -6503,6 +6631,15 @@ mipd "0.0.7" zustand "5.0.0" +"@wagmi/core@2.15.1": + version "2.15.1" + resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-2.15.1.tgz#1e38facf8cdc1c3e3eafc7f32ebdf0c2fd8b9743" + integrity sha512-xeSdA9FOZs+H1NG51GekfgDQ5aG8KGYUphuh+aYhsvMYtaEy6DVKmpgS13nvAzxe4rjtw0cm6RR0SA4G+paVdg== + dependencies: + eventemitter3 "5.0.1" + mipd "0.0.7" + zustand "5.0.0" + "@walletconnect/core@2.17.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.17.0.tgz#bf490e85a4702eff0f7cf81ba0d3c1016dffff33" @@ -6765,125 +6902,125 @@ "@walletconnect/window-getters" "^1.0.1" tslib "1.14.1" -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-numbers" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== +"@webassemblyjs/floating-point-hex-parser@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== +"@webassemblyjs/helper-api-error@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== +"@webassemblyjs/helper-buffer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== +"@webassemblyjs/helper-numbers@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/floating-point-hex-parser" "1.13.2" + "@webassemblyjs/helper-api-error" "1.13.2" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== +"@webassemblyjs/helper-wasm-bytecode@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== +"@webassemblyjs/helper-wasm-section@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/wasm-gen" "1.14.1" -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== +"@webassemblyjs/ieee754@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== +"@webassemblyjs/leb128@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== +"@webassemblyjs/utf8@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== "@webassemblyjs/wasm-edit@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" - -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== - dependencies: - "@webassemblyjs/ast" "1.12.1" + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/helper-wasm-section" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-opt" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + "@webassemblyjs/wast-printer" "1.14.1" + +"@webassemblyjs/wasm-gen@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wasm-opt@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-api-error" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wast-printer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw== + dependencies: + "@webassemblyjs/ast" "1.14.1" "@xtuc/long" "4.2.2" "@whatwg-node/events@^0.0.3": @@ -6934,13 +7071,6 @@ dependencies: tslib "^2.3.0" -"@wry/trie@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.4.3.tgz#077d52c22365871bf3ffcbab8e95cb8bc5689af4" - integrity sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w== - dependencies: - tslib "^2.3.0" - "@wry/trie@^0.5.0": version "0.5.0" resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.5.0.tgz#11e783f3a53f6e4cd1d42d2d1323f5bc3fa99c94" @@ -7054,7 +7184,7 @@ acorn-walk@^8.0.2, acorn-walk@^8.1.1, acorn-walk@^8.3.2: dependencies: acorn "^8.11.0" -acorn@^8.1.0, acorn@^8.11.0, acorn@^8.12.1, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.6.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.1.0, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.6.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -7643,9 +7773,9 @@ axios@^0.27.2: form-data "^4.0.0" axios@^1.1.3, axios@^1.3.4, axios@^1.4.0, axios@^1.6.7, axios@^1.7.2, axios@^1.7.4: - version "1.7.7" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" - integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== + version "1.7.8" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.8.tgz#1997b1496b394c21953e68c14aaa51b7b5de3d6e" + integrity sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -7700,12 +7830,12 @@ babel-plugin-macros@^3.1.0: resolve "^1.19.0" babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.11" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" - integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + version "0.4.12" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" + integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og== dependencies: "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.2" + "@babel/helper-define-polyfill-provider" "^0.6.3" semver "^6.3.1" babel-plugin-polyfill-corejs3@^0.10.6: @@ -7717,11 +7847,11 @@ babel-plugin-polyfill-corejs3@^0.10.6: core-js-compat "^3.38.0" babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" - integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + version "0.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" + integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q== dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.2" + "@babel/helper-define-polyfill-provider" "^0.6.3" babel-plugin-transform-react-remove-prop-types@^0.4.24: version "0.4.24" @@ -7892,9 +8022,9 @@ bn.js@4.11.6: integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.8, 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== + version "4.12.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" + integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" @@ -8359,9 +8489,9 @@ camelize@^1.0.0: integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== caniuse-lite@^1.0.30001669: - version "1.0.30001677" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz#27c2e2c637e007cfa864a16f7dfe7cde66b38b5f" - integrity sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog== + version "1.0.30001684" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz#0eca437bab7d5f03452ff0ef9de8299be6b08e16" + integrity sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ== cardinal@^2.1.1: version "2.1.1" @@ -8593,17 +8723,17 @@ ci-info@^3.2.0: integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== ci-info@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2" - integrity sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.1.0.tgz#92319d2fa29d2620180ea5afed31f589bc98cf83" + integrity sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + version "1.0.6" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.6.tgz#8fe672437d01cd6c4561af5334e0cc50ff1955f7" + integrity sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" citty@^0.1.5, citty@^0.1.6: version "0.1.6" @@ -9244,7 +9374,7 @@ cross-fetch@^4.0.0: dependencies: node-fetch "^2.6.12" -cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -9253,6 +9383,15 @@ cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + "crossws@>=0.2.0 <0.4.0": version "0.3.1" resolved "https://registry.yarnpkg.com/crossws/-/crossws-0.3.1.tgz#7980e0b6688fe23286661c3ab8deeccbaa05ca86" @@ -9829,10 +9968,10 @@ dom-helpers@^5.0.1: "@babel/runtime" "^7.8.7" csstype "^3.0.2" -domain-browser@^4.22.0: - version "4.23.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.23.0.tgz#427ebb91efcb070f05cffdfb8a4e9a6c25f8c94b" - integrity sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA== +domain-browser@4.22.0: + version "4.22.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.22.0.tgz#6ddd34220ec281f9a65d3386d267ddd35c491f9f" + integrity sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw== domexception@^4.0.0: version "4.0.0" @@ -9886,10 +10025,10 @@ ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: dependencies: safe-buffer "^5.0.1" -eciesjs@^0.4.8: - version "0.4.11" - resolved "https://registry.yarnpkg.com/eciesjs/-/eciesjs-0.4.11.tgz#cdd3b988df9c7be99049c765f5ff895efa16060d" - integrity sha512-SmUG449n1w1YGvJD9R30tBGvpxTxA0cnn0rfvpFIBvmezfIhagLjsH2JG8HBHOLS8slXsPh48II7IDUTH/J3Mg== +eciesjs@^0.4.11, eciesjs@^0.4.8: + version "0.4.12" + resolved "https://registry.yarnpkg.com/eciesjs/-/eciesjs-0.4.12.tgz#0ce482454953592e07b79b4824751f3b5c508b56" + integrity sha512-DGejvMCihsRAmKRFQiL6KZDE34vWVd0gvXlykFq1aEzJy/rD65AVyAIUZKZOvgvaP9ATQRcHGEZV5DfgrgjA4w== dependencies: "@ecies/ciphers" "^0.2.1" "@noble/ciphers" "^1.0.0" @@ -9931,9 +10070,9 @@ electron-fetch@^1.7.2: encoding "^0.1.13" electron-to-chromium@^1.5.41: - version "1.5.52" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.52.tgz#2bed832c95a56a195504f918150e548474687da8" - integrity sha512-xtoijJTZ+qeucLBDNztDOuQBE1ksqjvNjvqFoST3nGC7fSpqJ+X6BdTBaY5BHG+IhWWmpc6b/KfpeuEDupEPOQ== + version "1.5.66" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.66.tgz#1e9b4bc7638ac02d3551eea1dbaeb0101ec5823f" + integrity sha512-pI2QF6+i+zjPbqRzJwkMvtvkdI7MjVbSh2g8dlMguDJIXEPw+kwasS1Jl+YGPEBfGVxsVgGUratAKymPdPo2vQ== elliptic@6.5.4: version "6.5.4" @@ -9949,9 +10088,9 @@ elliptic@6.5.4: minimalistic-crypto-utils "^1.0.1" elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.5, elliptic@^6.5.7: - version "6.6.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" - integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -9966,6 +10105,11 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== +emoji-regex-xs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz#e8af22e5d9dbd7f7f22d280af3d19d2aab5b0724" + integrity sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg== + emoji-regex@^10.3.0: version "10.4.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" @@ -10081,10 +10225,10 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5: + version "1.23.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.5.tgz#f4599a4946d57ed467515ed10e4f157289cd52fb" + integrity sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ== dependencies: array-buffer-byte-length "^1.0.1" arraybuffer.prototype.slice "^1.0.3" @@ -10101,7 +10245,7 @@ es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23 function.prototype.name "^1.1.6" get-intrinsic "^1.2.4" get-symbol-description "^1.0.2" - globalthis "^1.0.3" + globalthis "^1.0.4" gopd "^1.0.1" has-property-descriptors "^1.0.2" has-proto "^1.0.3" @@ -10117,10 +10261,10 @@ es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23 is-string "^1.0.7" is-typed-array "^1.1.13" is-weakref "^1.0.2" - object-inspect "^1.13.1" + object-inspect "^1.13.3" object-keys "^1.1.1" object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" + regexp.prototype.flags "^1.5.3" safe-array-concat "^1.1.2" safe-regex-test "^1.0.3" string.prototype.trim "^1.2.9" @@ -10200,13 +10344,13 @@ es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: hasown "^2.0.0" es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" es6-promise@^4.0.3: version "4.2.8" @@ -10375,6 +10519,36 @@ esbuild@^0.21.3: "@esbuild/win32-ia32" "0.21.5" "@esbuild/win32-x64" "0.21.5" +esbuild@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.0.tgz#f2d470596885fcb2e91c21eb3da3b3c89c0b55e7" + integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ== + optionalDependencies: + "@esbuild/aix-ppc64" "0.24.0" + "@esbuild/android-arm" "0.24.0" + "@esbuild/android-arm64" "0.24.0" + "@esbuild/android-x64" "0.24.0" + "@esbuild/darwin-arm64" "0.24.0" + "@esbuild/darwin-x64" "0.24.0" + "@esbuild/freebsd-arm64" "0.24.0" + "@esbuild/freebsd-x64" "0.24.0" + "@esbuild/linux-arm" "0.24.0" + "@esbuild/linux-arm64" "0.24.0" + "@esbuild/linux-ia32" "0.24.0" + "@esbuild/linux-loong64" "0.24.0" + "@esbuild/linux-mips64el" "0.24.0" + "@esbuild/linux-ppc64" "0.24.0" + "@esbuild/linux-riscv64" "0.24.0" + "@esbuild/linux-s390x" "0.24.0" + "@esbuild/linux-x64" "0.24.0" + "@esbuild/netbsd-x64" "0.24.0" + "@esbuild/openbsd-arm64" "0.24.0" + "@esbuild/openbsd-x64" "0.24.0" + "@esbuild/sunos-x64" "0.24.0" + "@esbuild/win32-arm64" "0.24.0" + "@esbuild/win32-ia32" "0.24.0" + "@esbuild/win32-x64" "0.24.0" + escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" @@ -10623,9 +10797,9 @@ eslint-plugin-testing-library@^5.0.1: "@typescript-eslint/utils" "^5.58.0" eslint-plugin-testing-library@^6.2.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.4.0.tgz#1ba8a7422e3e31cc315a73ff17c34908f56f9838" - integrity sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA== + version "6.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.5.0.tgz#02532698270f525be8ceeb4740f66eef0f6f4729" + integrity sha512-Ls5TUfLm5/snocMAOlofSOJxNN0aKqwTlco7CrNtMjkTdQlkpSMaeTCDHCuXfzrI97xcx2rSCNeKeJjtpkNC1w== dependencies: "@typescript-eslint/utils" "^5.62.0" @@ -10692,6 +10866,11 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + eslint@^8.0.1, eslint@^8.55.0, eslint@^8.57.0: version "8.57.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" @@ -10993,7 +11172,7 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -eventemitter2@^6.4.7: +eventemitter2@^6.4.7, eventemitter2@^6.4.9: version "6.4.9" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.9.tgz#41f2750781b4230ed58827bc119d293471ecb125" integrity sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg== @@ -11176,7 +11355,7 @@ fast-fifo@^1.0.0: resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.7, fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.2: +fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.7, fast-glob@^3.2.9, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -11342,13 +11521,6 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -11380,9 +11552,9 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.2.9, flatted@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + version "3.3.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" + integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== fmix@^0.1.0: version "0.1.0" @@ -11769,10 +11941,10 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@10.4.2: - version "10.4.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.2.tgz#bed6b95dade5c1f80b4434daced233aee76160e5" - integrity sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w== +glob@10.4.5, glob@^10.2.2, glob@^10.3.10: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: foreground-child "^3.1.0" jackspeak "^3.1.2" @@ -11793,18 +11965,6 @@ glob@7.1.7, glob@~7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@9.3.5: version "9.3.5" resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" @@ -11815,18 +11975,6 @@ glob@9.3.5: minipass "^4.2.4" path-scurry "^1.6.1" -glob@^10.2.2, glob@^10.3.10: - version "10.4.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" - integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" - glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -11889,7 +12037,7 @@ globals@^13.19.0, globals@^13.23.0: dependencies: type-fest "^0.20.2" -globalthis@^1.0.3, globalthis@^1.0.4: +globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== @@ -11923,17 +12071,6 @@ globby@^11.0.3, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^13.1.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" - integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.3.0" - ignore "^5.2.4" - merge2 "^1.4.1" - slash "^4.0.0" - globule@^1.0.0: version "1.3.4" resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.4.tgz#7c11c43056055a75a6e68294453c17f2796170fb" @@ -12191,14 +12328,14 @@ hardhat-deploy@^0.11.43: zksync-web3 "^0.14.3" hardhat-gas-reporter@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-2.2.1.tgz#ce0b5437fdcaf919479d7a51cf45d8d72cbcd16b" - integrity sha512-3AfPDGBn6VPmRKU65W28qVvG5x+qYL2gH9PAivd31oGj/ZHpZTutqXh6wq46993Vz35rnPDnrGo028U4/NP/Vw== + version "2.2.2" + resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-2.2.2.tgz#b1530b1938b994d67dffda207314504b7946af09" + integrity sha512-xlg3d00wrgUvP2S5tw3Zf6nO7OyS5crK3P6/ZP69i24pz4grM+6oFHGW/eJPSGqiDWBYX+gKp9XoqP4rwRXrdQ== dependencies: "@ethersproject/abi" "^5.7.0" "@ethersproject/bytes" "^5.7.0" "@ethersproject/units" "^5.7.0" - "@solidity-parser/parser" "^0.18.0" + "@solidity-parser/parser" "^0.19.0" axios "^1.6.7" brotli-wasm "^2.0.1" chalk "4.1.2" @@ -12212,9 +12349,9 @@ hardhat-gas-reporter@^2.0.2: viem "2.7.14" hardhat@^2.22.10: - version "2.22.15" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.15.tgz#319b4948f875968fde3f0d09a7edfe74e16b1365" - integrity sha512-BpTGa9PE/sKAaHi4s/S1e9WGv63DR1m7Lzfd60C8gSEchDPfAJssVRSq0MZ2v2k76ig9m0kHAwVLf5teYwu/Mw== + version "2.22.16" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.16.tgz#6cf3413f63b14770f863f35452da891ac2bd50cb" + integrity sha512-d52yQZ09u0roL6GlgJSvtknsBtIuj9JrJ/U8VMzr/wue+gO5v2tQayvOX6llerlR57Zw2EOTQjLAt6RpHvjwHA== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" @@ -12230,7 +12367,6 @@ hardhat@^2.22.10: aggregate-error "^3.0.0" ansi-escapes "^4.3.0" boxen "^5.1.2" - chalk "^2.4.2" chokidar "^4.0.0" ci-info "^2.0.0" debug "^4.1.1" @@ -12238,10 +12374,9 @@ hardhat@^2.22.10: env-paths "^2.2.0" ethereum-cryptography "^1.0.3" ethereumjs-abi "^0.6.8" - find-up "^2.1.0" + find-up "^5.0.0" fp-ts "1.19.3" fs-extra "^7.0.1" - glob "7.2.0" immutable "^4.0.0-rc.12" io-ts "1.10.4" json-stream-stringify "^3.1.4" @@ -12250,12 +12385,14 @@ hardhat@^2.22.10: mnemonist "^0.38.0" mocha "^10.0.0" p-map "^4.0.0" + picocolors "^1.1.0" raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" solc "0.8.26" source-map-support "^0.5.13" stacktrace-parser "^0.1.10" + tinyglobby "^0.2.6" tsort "0.0.1" undici "^5.14.0" uuid "^8.3.2" @@ -12330,12 +12467,12 @@ hash-base@^3.0.0: safe-buffer "^5.2.0" hash-base@~3.0, hash-base@~3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow== + version "3.0.5" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" + integrity sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" @@ -12580,9 +12717,9 @@ humanize-ms@^1.2.1: ms "^2.0.0" husky@^9.1.6: - version "9.1.6" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.6.tgz#e23aa996b6203ab33534bdc82306b0cf2cb07d6c" - integrity sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A== + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== hyperlinker@^1.0.0: version "1.0.0" @@ -12604,9 +12741,9 @@ i18next@23.11.5: "@babel/runtime" "^7.23.2" i18next@^23.8.2: - version "23.16.4" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.4.tgz#79c07544f6d6fa803fe8427108d547542c1d6cf4" - integrity sha512-9NIYBVy9cs4wIqzurf7nLXPyf3R78xYbxExVqHLK9od3038rjpyOEzW+XB130kZ1N4PZ9inTtJ471CRJ4Ituyg== + version "23.16.8" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.8.tgz#3ae1373d344c2393f465556f394aba5a9233b93a" + integrity sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg== dependencies: "@babel/runtime" "^7.23.2" @@ -12668,11 +12805,16 @@ immutable@4.2.1: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.1.tgz#8a4025691018c560a40c67e43d698f816edc44d4" integrity sha512-7WYV7Q5BTs0nlQm7tl92rDYYoyELLKHoDMBKhrxEoiV4mrfVdRz8hzPiYOzH7yWjzoVEamxRuAqhxL2PLRwZYQ== -immutable@^4.0.0, immutable@^4.0.0-rc.12: +immutable@^4.0.0-rc.12: version "4.3.7" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== +immutable@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.0.3.tgz#aa037e2313ea7b5d400cd9298fa14e404c933db1" + integrity sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw== + import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -12992,13 +13134,13 @@ is-builtin-module@^3.2.1: builtin-modules "^3.3.0" is-bun-module@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-1.2.1.tgz#495e706f42e29f086fd5fe1ac3c51f106062b9fc" - integrity sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q== + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-1.3.0.tgz#ea4d24fdebfcecc98e81bcbcb506827fee288760" + integrity sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA== dependencies: semver "^7.6.3" -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.1.3, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== @@ -13017,7 +13159,7 @@ is-data-view@^1.0.1: dependencies: is-typed-array "^1.1.13" -is-date-object@^1.0.1, is-date-object@^1.0.5: +is-date-object@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== @@ -13044,12 +13186,12 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== +is-finalizationregistry@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz#d74a7d0c5f3578e34a20729e69202e578d495dc2" + integrity sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -13213,7 +13355,7 @@ is-string@^1.0.5, is-string@^1.0.7: dependencies: has-tostringtag "^1.0.0" -is-symbol@^1.0.2, is-symbol@^1.0.3: +is-symbol@^1.0.3, is-symbol@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== @@ -13924,10 +14066,10 @@ js-sha3@0.8.0, js-sha3@^0.8.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.0.tgz#0f893996d6f3ed46df7f0a3b12a03f5fd84223c1" - integrity sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ== +js-tokens@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" + integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== js-yaml@3.14.1, js-yaml@3.x, js-yaml@^3.13.1, js-yaml@^3.14.1: version "3.14.1" @@ -14279,9 +14421,9 @@ levn@~0.3.0: type-check "~0.3.2" libphonenumber-js@^1.10.53: - version "1.11.12" - resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.11.12.tgz#e108a4632048255f30b872bb1abbb3356f290fbb" - integrity sha512-QkJn9/D7zZ1ucvT++TQSvZuSA2xAWeUytU+DiEQwbPKLyrDpvbul2AFs1CGbRAPpSCCk47aRAb5DX5mmcayp4g== + version "1.11.15" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.11.15.tgz#0947ba02208cf6c44fdf3b07e097a98b3ec945f4" + integrity sha512-M7+rtYi9l5RvMmHyjyoF3BHHUpXTYdJ0PezZGHNs0GyW1lO+K7jxlXpbdIb7a56h0nqLYdjIw+E+z0ciGaJP7g== lilconfig@~3.1.2: version "3.1.2" @@ -14408,20 +14550,12 @@ loader-runner@^4.2.0: integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== local-pkg@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c" - integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg== - dependencies: - mlly "^1.4.2" - pkg-types "^1.0.3" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + version "0.5.1" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.1.tgz#69658638d2a95287534d4c2fff757980100dbb6d" + integrity sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ== dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" + mlly "^1.7.3" + pkg-types "^1.2.1" locate-path@^5.0.0: version "5.0.0" @@ -14700,17 +14834,10 @@ magic-string@0.30.8: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magic-string@^0.30.12: - version "0.30.13" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.13.tgz#92438e3ff4946cf54f18247c981e5c161c46683c" - integrity sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" - -magic-string@^0.30.3, magic-string@^0.30.5: - version "0.30.12" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60" - integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw== +magic-string@^0.30.12, magic-string@^0.30.3, magic-string@^0.30.5: + version "0.30.14" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.14.tgz#e9bb29870b81cfc1ec3cc656552f5a7fcbf19077" + integrity sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw== dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" @@ -14955,36 +15082,36 @@ micro-ftch@^0.3.1: integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== micromark-util-character@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" - integrity sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz#2f987831a40d4c510ac261e89852c4e9703ccda6" + integrity sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q== dependencies: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" micromark-util-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1" - integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz#0d51d1c095551cfaac368326963cf55f15f540b8" + integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw== micromark-util-sanitize-uri@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de" - integrity sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz#ab89789b818a58752b73d6b55238621b7faa8fd7" + integrity sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ== dependencies: micromark-util-character "^2.0.0" micromark-util-encode "^2.0.0" micromark-util-symbol "^2.0.0" micromark-util-symbol@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044" - integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz#e5da494e8eb2b071a0d08fb34f6cefec6c0a19b8" + integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q== micromark-util-types@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e" - integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.1.tgz#a3edfda3022c6c6b55bfb049ef5b75d70af50709" + integrity sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ== micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@~4.0.8: version "4.0.8" @@ -15299,14 +15426,14 @@ mkdirp@^2.1.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== -mlly@^1.4.2, mlly@^1.7.1, mlly@^1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.2.tgz#21c0d04543207495b8d867eff0ac29fac9a023c0" - integrity sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA== +mlly@^1.7.1, mlly@^1.7.2, mlly@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.3.tgz#d86c0fcd8ad8e16395eb764a5f4b831590cee48c" + integrity sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A== dependencies: - acorn "^8.12.1" + acorn "^8.14.0" pathe "^1.1.2" - pkg-types "^1.2.0" + pkg-types "^1.2.1" ufo "^1.5.4" mnemonist@^0.38.0: @@ -15460,9 +15587,9 @@ nan@^2.17.0: integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== nanoid@^3.0.2, nanoid@^3.1.20, nanoid@^3.1.23, nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== napi-wasm@^1.1.0: version "1.1.3" @@ -15538,9 +15665,9 @@ no-case@^3.0.4: tslib "^2.0.3" nock@^13.5.1: - version "13.5.5" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.5.tgz#cd1caaca281d42be17d51946367a3d53a6af3e78" - integrity sha512-XKYnqUrCwXC8DGG1xX4YH5yNIrlh9c065uaMZZHUoeUUINTOyt+x/G+ezYk0Ft6ExSREVIs+qBJDK503viTfFA== + version "13.5.6" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.6.tgz#5e693ec2300bbf603b61dae6df0225673e6c4997" + integrity sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ== dependencies: debug "^4.1.0" json-stringify-safe "^5.0.1" @@ -15598,9 +15725,9 @@ node-forge@^1.0.0, node-forge@^1.3.1: integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-gyp-build@^4.2.0, node-gyp-build@^4.2.2, node-gyp-build@^4.3.0: - version "4.8.2" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" - integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + version "4.8.4" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" + integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== node-gyp@^8.4.1: version "8.4.1" @@ -15649,9 +15776,9 @@ node-sass@^9.0.0: "true-case-path" "^2.2.1" node-stdlib-browser@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/node-stdlib-browser/-/node-stdlib-browser-1.2.1.tgz#888fa104914af94143ca4d8a8980fe0ed242d2d1" - integrity sha512-dZezG3D88Lg22DwyjsDuUs7cCT/XGr8WwJgg/S3ZnkcWuPet2Tt/W1d2Eytb1Z73JpZv+XVCDI5TWv6UMRq0Gg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/node-stdlib-browser/-/node-stdlib-browser-1.3.0.tgz#6e04d149f9abfc345a2271b2820a75df0f9cd7de" + integrity sha512-g/koYzOr9Fb1Jc+tHUHlFd5gODjGn48tHexUK8q6iqOVriEgSnd3/1T7myBYc+0KBVze/7F7n65ec9rW6OD7xw== dependencies: assert "^2.0.0" browser-resolve "^2.0.0" @@ -15661,7 +15788,7 @@ node-stdlib-browser@^1.2.0: constants-browserify "^1.0.0" create-require "^1.1.1" crypto-browserify "^3.11.0" - domain-browser "^4.22.0" + domain-browser "4.22.0" events "^3.0.0" https-browserify "^1.0.0" isomorphic-timers-promises "^1.0.1" @@ -15822,10 +15949,10 @@ object-hash@^3.0.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== +object-inspect@^1.13.1, object-inspect@^1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== object-is@^1.1.5: version "1.1.6" @@ -15961,12 +16088,14 @@ onetime@^7.0.0: dependencies: mimic-function "^5.0.0" -oniguruma-to-js@0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz#8d899714c21f5c7d59a3c0008ca50e848086d740" - integrity sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ== +oniguruma-to-es@0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-0.7.0.tgz#999fe7df1e6acae4507e2d77afc6de4fc8533116" + integrity sha512-HRaRh09cE0gRS3+wi2zxekB+I5L8C/gN60S+vb11eADHUaB/q4u8wGGOX3GvwvitG8ixaeycZfeoyruKQzUgNg== dependencies: - regex "^4.3.2" + emoji-regex-xs "^1.0.0" + regex "^5.0.2" + regex-recursion "^4.3.0" open@^8.4.0: version "8.4.2" @@ -15985,13 +16114,13 @@ openpgp@5.11.2, openpgp@^5.11.2: asn1.js "^5.0.0" optimism@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.0.tgz#e7bb38b24715f3fdad8a9a7fc18e999144bbfa63" - integrity sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ== + version "0.18.1" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.1.tgz#5cf16847921413dbb0ac809907370388b9c6335f" + integrity sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ== dependencies: "@wry/caches" "^1.0.0" "@wry/context" "^0.7.0" - "@wry/trie" "^0.4.3" + "@wry/trie" "^0.5.0" tslib "^2.3.0" optionator@^0.8.1: @@ -16094,13 +16223,6 @@ p-limit@3.1.0, p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -16115,13 +16237,6 @@ p-limit@^5.0.0: dependencies: yocto-queue "^1.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== - dependencies: - p-limit "^1.1.0" - p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -16143,11 +16258,6 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -16271,11 +16381,6 @@ path-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -16467,7 +16572,7 @@ picocolors@1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picocolors@^1.0.0, picocolors@^1.1.0: +picocolors@^1.0.0, picocolors@^1.1.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -16556,7 +16661,7 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" -pkg-types@^1.0.3, pkg-types@^1.2.0: +pkg-types@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.2.1.tgz#6ac4e455a5bb4b9a6185c1c79abd544c901db2e5" integrity sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw== @@ -16599,13 +16704,13 @@ postcss@8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" -postcss@^8.4.43: - version "8.4.47" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" - integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== +postcss@^8.4.43, postcss@^8.4.49: + version "8.4.49" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" + integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== dependencies: nanoid "^3.3.7" - picocolors "^1.1.0" + picocolors "^1.1.1" source-map-js "^1.2.1" postgres-array@~2.0.0: @@ -16658,9 +16763,9 @@ postgres-range@^1.1.1: integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== preact@^10.16.0, preact@^10.24.2: - version "10.24.3" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.24.3.tgz#086386bd47071e3b45410ef20844c21e23828f64" - integrity sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA== + version "10.25.0" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.25.0.tgz#22a1c93ce97336c5d01d74f363433ab0cd5cde64" + integrity sha512-6bYnzlLxXV3OSpUxLdaxBmE7PMOu0aR3pG6lryK/0jmvcDFPlcXGQAt5DpK3RITWiDrfYZRI0druyaK/S9kYLg== prelude-ls@^1.2.1: version "1.2.1" @@ -16680,11 +16785,11 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier-plugin-packagejson@^2.4.12: - version "2.5.3" - resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.3.tgz#a3f9eb02ece197db6b7696be5df43ddc2397ad81" - integrity sha512-ATMEEXr+ywls1kgrZEWl4SBPEm0uDdyDAjyNzUC0/Z8WZTD3RqbJcQDR+Dau+wYkW9KHK6zqQIsFyfn+9aduWg== + version "2.5.6" + resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.6.tgz#cd3cca60e1aa87ee3ce3b4032c1c999798d9f714" + integrity sha512-TY7KiLtyt6Tlf53BEbXUWkN0+TRdHKgIMmtXtDCyHH6yWnZ50Lwq6Vb6lyjapZrhDTXooC4EtlY5iLe1sCgi5w== dependencies: - sort-package-json "2.10.1" + sort-package-json "2.12.0" synckit "0.9.2" prettier-plugin-solidity@^1.3.1: @@ -16711,9 +16816,9 @@ prettier@^2.3.1, prettier@^2.3.2: integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== prettier@^3.1.1, prettier@^3.2.5: - version "3.3.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" - integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + version "3.4.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.1.tgz#e211d451d6452db0a291672ca9154bc8c2579f7b" + integrity sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg== pretty-format@^27.0.2: version "27.5.1" @@ -16889,9 +16994,11 @@ proxy-from-env@^1.1.0: integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== psl@^1.1.33: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + version "1.13.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.13.0.tgz#8b2357f13ef3cf546af3f52de00543a94da86cfa" + integrity sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw== + dependencies: + punycode "^2.3.1" public-encrypt@^4.0.3: version "4.0.3" @@ -16942,11 +17049,11 @@ pure-rand@^6.0.0: integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== pvtsutils@^1.3.2, pvtsutils@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.5.tgz#b8705b437b7b134cd7fd858f025a23456f1ce910" - integrity sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA== + version "1.3.6" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.6.tgz#ec46e34db7422b9e4fdc5490578c1883657d6001" + integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== dependencies: - tslib "^2.6.1" + tslib "^2.8.1" pvutils@^1.1.3: version "1.1.3" @@ -16979,13 +17086,20 @@ qrcode@1.5.3, qrcode@^1.5.0: pngjs "^5.0.0" yargs "^15.3.1" -qs@6.13.0, qs@^6.11.0, qs@^6.12.3, qs@^6.4.0, qs@^6.9.4: +qs@6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: side-channel "^1.0.6" +qs@^6.11.0, qs@^6.12.3, qs@^6.4.0, qs@^6.9.4: + version "6.13.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.1.tgz#3ce5fc72bd3a8171b85c99b93c65dd20b7d1b16e" + integrity sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg== + dependencies: + side-channel "^1.0.6" + query-string@7.1.3, query-string@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" @@ -17099,9 +17213,9 @@ react-hook-form@^7.53.2: integrity sha512-YVel6fW5sOeedd1524pltpHX+jgU2u3DSDtXEaBORNdqiNrsX/nUI/iGXONegttg0mJVnfrIkiV0cmTU6Oo2xw== react-i18next@^15.1.0: - version "15.1.0" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.0.tgz#9494e4add2389f04c205dd7628c1aa75747b98a3" - integrity sha512-zj3nJynMnZsy2gPZiOTC7XctCY5eQGqT3tcKMmfJWC9FMvgd+960w/adq61j8iPzpwmsXejqID9qC3Mqu1Xu2Q== + version "15.1.2" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.2.tgz#e7ea4ef952736eca9e3e1ff0229f2dcd61b8332a" + integrity sha512-tl7AfbWyz9a4BefFXnVooc+gvQBVlavUkVTphGUcvhsNmbRf5UixJVdHeSFkE4gUyQkmFPYHVwTuxIdHjfQgiA== dependencies: "@babel/runtime" "^7.25.0" html-parse-stringify "^3.0.1" @@ -17168,19 +17282,19 @@ react-refresh@^0.14.2: integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== react-router-dom@^6.14.1, react-router-dom@^6.22.0, react-router-dom@^6.23.1, react-router-dom@^6.24.1, react-router-dom@^6.4.3: - version "6.27.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.27.0.tgz#8d7972a425fd75f91c1e1ff67e47240c5752dc3f" - integrity sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g== + version "6.28.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.28.0.tgz#f73ebb3490e59ac9f299377062ad1d10a9f579e6" + integrity sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg== dependencies: - "@remix-run/router" "1.20.0" - react-router "6.27.0" + "@remix-run/router" "1.21.0" + react-router "6.28.0" -react-router@6.27.0: - version "6.27.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.27.0.tgz#db292474926c814c996c0ff3ef0162d1f9f60ed4" - integrity sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw== +react-router@6.28.0: + version "6.28.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.28.0.tgz#29247c86d7ba901d7e5a13aa79a96723c3e59d0d" + integrity sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg== dependencies: - "@remix-run/router" "1.20.0" + "@remix-run/router" "1.21.0" react-smooth@^4.0.0: version "4.0.1" @@ -17381,18 +17495,18 @@ reflect-metadata@^0.2.1, reflect-metadata@^0.2.2: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== -reflect.getprototypeof@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" - integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== +reflect.getprototypeof@^1.0.4, reflect.getprototypeof@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz#04311b33a1b713ca5eb7b5aed9950a86481858e5" + integrity sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g== dependencies: call-bind "^1.0.7" define-properties "^1.2.1" - es-abstract "^1.23.1" + es-abstract "^1.23.5" es-errors "^1.3.0" get-intrinsic "^1.2.4" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" + gopd "^1.0.1" + which-builtin-type "^1.1.4" regenerate-unicode-properties@^10.2.0: version "10.2.0" @@ -17418,17 +17532,31 @@ regenerator-transform@^0.15.2: dependencies: "@babel/runtime" "^7.8.4" -regex@^4.3.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/regex/-/regex-4.4.0.tgz#cb731e2819f230fad69089e1bd854fef7569e90a" - integrity sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ== +regex-recursion@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/regex-recursion/-/regex-recursion-4.3.0.tgz#32c3a42a57d78bf2d0c83875074c2f7ebaf2a4f6" + integrity sha512-5LcLnizwjcQ2ALfOj95MjcatxyqF5RPySx9yT+PaXu3Gox2vyAtLDjHB8NTJLtMGkvyau6nI3CfpwFCjPUIs/A== + dependencies: + regex-utilities "^2.3.0" + +regex-utilities@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/regex-utilities/-/regex-utilities-2.3.0.tgz#87163512a15dce2908cf079c8960d5158ff43280" + integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng== + +regex@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/regex/-/regex-5.0.2.tgz#291d960467e6499a79ceec022d20a4e0df67c54f" + integrity sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ== + dependencies: + regex-utilities "^2.3.0" regexp-tree@^0.1.27: version "0.1.27" resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== -regexp.prototype.flags@^1.5.2: +regexp.prototype.flags@^1.5.2, regexp.prototype.flags@^1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== @@ -17439,14 +17567,14 @@ regexp.prototype.flags@^1.5.2: set-function-name "^2.0.2" regexpu-core@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.1.1.tgz#b469b245594cb2d088ceebc6369dceb8c00becac" - integrity sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw== + version "6.2.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826" + integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA== dependencies: regenerate "^1.4.2" regenerate-unicode-properties "^10.2.0" regjsgen "^0.8.0" - regjsparser "^0.11.0" + regjsparser "^0.12.0" unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" @@ -17477,10 +17605,10 @@ regjsparser@^0.10.0: dependencies: jsesc "~0.5.0" -regjsparser@^0.11.0: - version "0.11.2" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.11.2.tgz#7404ad42be00226d72bcf1f003f1f441861913d8" - integrity sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA== +regjsparser@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc" + integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ== dependencies: jsesc "~3.0.2" @@ -17683,31 +17811,31 @@ rlp@^2.2.3, rlp@^2.2.4: dependencies: bn.js "^5.2.0" -rollup@^4.20.0: - version "4.24.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.24.4.tgz#fdc76918de02213c95447c9ffff5e35dddb1d058" - integrity sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA== +rollup@^4.20.0, rollup@^4.23.0: + version "4.27.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.27.4.tgz#b23e4ef4fe4d0d87f5237dacf63f95a499503897" + integrity sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw== dependencies: "@types/estree" "1.0.6" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.24.4" - "@rollup/rollup-android-arm64" "4.24.4" - "@rollup/rollup-darwin-arm64" "4.24.4" - "@rollup/rollup-darwin-x64" "4.24.4" - "@rollup/rollup-freebsd-arm64" "4.24.4" - "@rollup/rollup-freebsd-x64" "4.24.4" - "@rollup/rollup-linux-arm-gnueabihf" "4.24.4" - "@rollup/rollup-linux-arm-musleabihf" "4.24.4" - "@rollup/rollup-linux-arm64-gnu" "4.24.4" - "@rollup/rollup-linux-arm64-musl" "4.24.4" - "@rollup/rollup-linux-powerpc64le-gnu" "4.24.4" - "@rollup/rollup-linux-riscv64-gnu" "4.24.4" - "@rollup/rollup-linux-s390x-gnu" "4.24.4" - "@rollup/rollup-linux-x64-gnu" "4.24.4" - "@rollup/rollup-linux-x64-musl" "4.24.4" - "@rollup/rollup-win32-arm64-msvc" "4.24.4" - "@rollup/rollup-win32-ia32-msvc" "4.24.4" - "@rollup/rollup-win32-x64-msvc" "4.24.4" + "@rollup/rollup-android-arm-eabi" "4.27.4" + "@rollup/rollup-android-arm64" "4.27.4" + "@rollup/rollup-darwin-arm64" "4.27.4" + "@rollup/rollup-darwin-x64" "4.27.4" + "@rollup/rollup-freebsd-arm64" "4.27.4" + "@rollup/rollup-freebsd-x64" "4.27.4" + "@rollup/rollup-linux-arm-gnueabihf" "4.27.4" + "@rollup/rollup-linux-arm-musleabihf" "4.27.4" + "@rollup/rollup-linux-arm64-gnu" "4.27.4" + "@rollup/rollup-linux-arm64-musl" "4.27.4" + "@rollup/rollup-linux-powerpc64le-gnu" "4.27.4" + "@rollup/rollup-linux-riscv64-gnu" "4.27.4" + "@rollup/rollup-linux-s390x-gnu" "4.27.4" + "@rollup/rollup-linux-x64-gnu" "4.27.4" + "@rollup/rollup-linux-x64-musl" "4.27.4" + "@rollup/rollup-win32-arm64-msvc" "4.27.4" + "@rollup/rollup-win32-ia32-msvc" "4.27.4" + "@rollup/rollup-win32-x64-msvc" "4.27.4" fsevents "~2.3.2" rrweb-cssom@^0.7.1: @@ -17789,12 +17917,12 @@ sass-graph@^4.0.1: yargs "^17.2.1" sass@^1.78.0: - version "1.80.6" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.80.6.tgz#5d0aa55763984effe41e40019c9571ab73e6851f" - integrity sha512-ccZgdHNiBF1NHBsWvacvT5rju3y1d/Eu+8Ex6c21nHp2lZGLBEtuwc415QfiI1PJa1TpCo3iXwwSRjRpn2Ckjg== + version "1.81.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.81.0.tgz#a9010c0599867909dfdbad057e4a6fbdd5eec941" + integrity sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA== dependencies: chokidar "^4.0.0" - immutable "^4.0.0" + immutable "^5.0.2" source-map-js ">=0.6.2 <2.0.0" optionalDependencies: "@parcel/watcher" "^2.4.1" @@ -18011,9 +18139,9 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" - integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + version "1.8.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a" + integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA== shelljs@^0.8.3: version "0.8.5" @@ -18025,14 +18153,14 @@ shelljs@^0.8.3: rechoir "^0.6.2" shiki@^1.16.2: - version "1.22.2" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.22.2.tgz#ed109a3d0850504ad5a1edf8496470a2121c5b7b" - integrity sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA== - dependencies: - "@shikijs/core" "1.22.2" - "@shikijs/engine-javascript" "1.22.2" - "@shikijs/engine-oniguruma" "1.22.2" - "@shikijs/types" "1.22.2" + version "1.24.0" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.24.0.tgz#ea374523cbf32df0141ad3e5f79d16aea901ab69" + integrity sha512-qIneep7QRwxRd5oiHb8jaRzH15V/S8F3saCXOdjwRLgozZJr5x2yeBhQtqkO3FSzQDwYEFAYuifg4oHjpDghrg== + dependencies: + "@shikijs/core" "1.24.0" + "@shikijs/engine-javascript" "1.24.0" + "@shikijs/engine-oniguruma" "1.24.0" + "@shikijs/types" "1.24.0" "@shikijs/vscode-textmate" "^9.3.0" "@types/hast" "^3.0.4" @@ -18101,11 +18229,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -18216,12 +18339,12 @@ solidity-ast@^0.4.51: integrity sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g== solidity-coverage@^0.8.2: - version "0.8.13" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.13.tgz#8eeada2e82ae19d25568368aa782a2baad0e0ce7" - integrity sha512-RiBoI+kF94V3Rv0+iwOj3HQVSqNzA9qm/qDP1ZDXK5IX0Cvho1qiz8hAXTsAo6KOIUeP73jfscq0KlLqVxzGWA== + version "0.8.14" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.14.tgz#db9bfcc10e3bc369fc074b35b267d665bcc6ae2e" + integrity sha512-ItAAObe5GaEOp20kXC2BZRnph+9P7Rtoqg2mQc2SXGEHgSDF2wWd1Wxz3ntzQWXkbCtIIGdJT918HG00cObwbA== dependencies: "@ethersproject/abi" "^5.0.9" - "@solidity-parser/parser" "^0.18.0" + "@solidity-parser/parser" "^0.19.0" chalk "^2.4.2" death "^1.1.0" difflib "^0.2.4" @@ -18252,19 +18375,19 @@ sort-object-keys@^1.1.3: resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== -sort-package-json@2.10.1: - version "2.10.1" - resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.10.1.tgz#18e7fa0172233cb2d4d926f7c99e6bfcf4d1d25c" - integrity sha512-d76wfhgUuGypKqY72Unm5LFnMpACbdxXsLPcL27pOsSrmVqH3PztFp1uq+Z22suk15h7vXmTesuh2aEjdCqb5w== +sort-package-json@2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.12.0.tgz#4196a1ba82ba63c4a512add1d00ab39026bf8ab7" + integrity sha512-/HrPQAeeLaa+vbAH/znjuhwUluuiM/zL5XX9kop8UpDgjtyWKt43hGDk2vd/TBdDpzIyzIHVUgmYofzYrAQjew== dependencies: detect-indent "^7.0.1" detect-newline "^4.0.0" get-stdin "^9.0.0" git-hooks-list "^3.0.0" - globby "^13.1.2" is-plain-obj "^4.1.0" semver "^7.6.0" sort-object-keys "^1.1.3" + tinyglobby "^0.2.9" "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0, source-map-js@^1.2.1: version "1.2.1" @@ -18427,12 +18550,7 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -std-env@^3.5.0, std-env@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" - integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== - -std-env@^3.8.0: +std-env@^3.5.0, std-env@^3.7.0, std-env@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== @@ -18475,9 +18593,9 @@ stream-http@^3.2.0: xtend "^4.0.2" stream-json@^1.8.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.0.tgz#caae36fd9fff99662f504dce859bc855d5668282" - integrity sha512-TqnfW7hRTKje7UobBzXZJ2qOEDJvdcSVgVIK/fopC03xINFuFqQs8RVjyDT4ry7TmOo2ueAXwpXXXG4tNgtvoQ== + version "1.9.1" + resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.1.tgz#e3fec03e984a503718946c170db7d74556c2a187" + integrity sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw== dependencies: stream-chain "^2.2.5" @@ -18714,11 +18832,11 @@ strip-json-comments@~2.0.1: integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== strip-literal@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.0.tgz#6d82ade5e2e74f5c7e8739b6c84692bd65f0bd2a" - integrity sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw== + version "2.1.1" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.1.tgz#26906e65f606d49f748454a08084e94190c2e5ad" + integrity sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q== dependencies: - js-tokens "^9.0.0" + js-tokens "^9.0.1" stripe@^17.4.0: version "17.4.0" @@ -18850,9 +18968,9 @@ swagger-ui-dist@5.17.14: integrity sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw== swiper@^11.1.3: - version "11.1.14" - resolved "https://registry.yarnpkg.com/swiper/-/swiper-11.1.14.tgz#7901b4955c46dd0ad76fac1e9de2a69f04f34abb" - integrity sha512-VbQLQXC04io6AoAjIUWuZwW4MSYozkcP9KjLdrsG/00Q/yiwvhz9RQyt0nHXV10hi9NVnDNy1/wv7Dzq1lkOCQ== + version "11.1.15" + resolved "https://registry.yarnpkg.com/swiper/-/swiper-11.1.15.tgz#e2258c8d38282e2f115ca463d6e8c5b84cdcf1ca" + integrity sha512-IzWeU34WwC7gbhjKsjkImTuCRf+lRbO6cnxMGs88iVNKDwV+xQpBCJxZ4bNH6gSrIbbyVJ1kuGzo3JTtz//CBw== swr@^2.2.4: version "2.2.5" @@ -19119,7 +19237,7 @@ tinyexec@^0.3.1: resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98" integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ== -tinyglobby@^0.2.9: +tinyglobby@^0.2.10, tinyglobby@^0.2.6, tinyglobby@^0.2.9: version "0.2.10" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.10.tgz#e712cf2dc9b95a1f5c5bbd159720e15833977a0f" integrity sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew== @@ -19152,17 +19270,17 @@ tinyspy@^3.0.2: resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== -tldts-core@^6.1.58: - version "6.1.58" - resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.58.tgz#f0b5c1fcb2e214f558c7cb380fb1e6f4b2459d8b" - integrity sha512-dR936xmhBm7AeqHIhCWwK765gZ7dFyL+IqLSFAjJbFlUXGMLCb8i2PzlzaOuWBuplBTaBYseSb565nk/ZEM0Bg== +tldts-core@^6.1.64: + version "6.1.64" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.64.tgz#0b017a7fefb92d8542b1078c793c00cc28ad9eac" + integrity sha512-uqnl8vGV16KsyflHOzqrYjjArjfXaU6rMPXYy2/ZWoRKCkXtghgB4VwTDXUG+t0OTGeSewNAG31/x1gCTfLt+Q== tldts@^6.1.32: - version "6.1.58" - resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.58.tgz#63d211f46f2c17d69d4cedf0c4c19423a608874f" - integrity sha512-MQJrJhjHOYGYb8DobR6Y4AdDbd4TYkyQ+KBDVc5ODzs1cbrvPpfN1IemYi9jfipJ/vR1YWvrDli0hg1y19VRoA== + version "6.1.64" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.64.tgz#bfeaa17f881944c943f1f6647494af418901d73f" + integrity sha512-ph4AE5BXWIOsSy9stpoeo7bYe/Cy7VfpciIH4RhVZUPItCJmhqWCN0EVzxd8BOHiyNb42vuJc6NWTjJkg91Tuw== dependencies: - tldts-core "^6.1.58" + tldts-core "^6.1.64" tmp-promise@3.0.3: version "3.0.3" @@ -19277,9 +19395,9 @@ trim-newlines@^3.0.0: integrity sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q== ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.0.tgz#709c6f2076e511a81557f3d07a0cbd566ae8195c" - integrity sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ== + version "1.4.2" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.2.tgz#a6a6dff26117ac7965624fc118525971edc6a82a" + integrity sha512-ZF5gQIQa/UmzfvxbHZI3JXN0/Jt+vnAfAviNRAMc491laiK6YCLpCW9ft8oaCRFOTxCZtUTE6XB0ZQAe3olntw== ts-command-line-args@^2.2.0: version "2.5.1" @@ -19395,13 +19513,14 @@ ts-toolbelt@^6.15.5: resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz#cb3b43ed725cb63644782c64fbcad7d8f28c0a83" integrity sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A== -tsconfig-paths-webpack-plugin@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz#3c6892c5e7319c146eee1e7302ed9e6f2be4f763" - integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA== +tsconfig-paths-webpack-plugin@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz#f7459a8ed1dd4cf66ad787aefc3d37fff3cf07fc" + integrity sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA== dependencies: chalk "^4.1.0" enhanced-resolve "^5.7.0" + tapable "^2.2.1" tsconfig-paths "^4.1.2" tsconfig-paths@4.2.0, tsconfig-paths@^4.1.2: @@ -19438,7 +19557,7 @@ tslib@2.7.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== -tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0, tslib@^2.6.1, tslib@^2.6.2, tslib@^2.7.0: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0, tslib@^2.6.0, tslib@^2.6.2, tslib@^2.7.0, tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -19579,9 +19698,9 @@ typed-array-byte-length@^1.0.1: is-typed-array "^1.1.13" typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz#3fa9f22567700cc86aaf86a1e7176f74b59600f2" + integrity sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw== dependencies: available-typed-arrays "^1.0.7" call-bind "^1.0.7" @@ -19589,18 +19708,19 @@ typed-array-byte-offset@^1.0.2: gopd "^1.0.1" has-proto "^1.0.3" is-typed-array "^1.1.13" + reflect.getprototypeof "^1.0.6" typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== dependencies: call-bind "^1.0.7" for-each "^0.3.3" gopd "^1.0.1" - has-proto "^1.0.3" is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" typedarray@^0.0.6: version "0.0.6" @@ -19608,9 +19728,9 @@ typedarray@^0.0.6: integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typedoc-plugin-markdown@^4.2.3: - version "4.2.10" - resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.10.tgz#cd386e9f2dec122cae79e487983811d92ac37161" - integrity sha512-PLX3pc1/7z13UJm4TDE9vo9jWGcClFUErXXtd5LdnoLjV6mynPpqZLU992DwMGFSRqJFZeKbVyqlNNeNHnk2tQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.3.0.tgz#d4ee289ea8e04b03801dc476eb3090142983bfe5" + integrity sha512-yAR7+JGSwHWNzQhS8AFlGX6GmbWnK7/Q2Y8hHy5pkL/WB9ooJqhsI6B1abldhM3lOQCWqCdkzu9yFMPuvl2HUw== typedoc@^0.26.5: version "0.26.11" @@ -19654,11 +19774,16 @@ typescript@4.9.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -typescript@5.6.3, typescript@^5.2.2, typescript@^5.5.4, typescript@^5.6.3: +typescript@5.6.3: version "5.6.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== +typescript@^5.2.2, typescript@^5.5.4, typescript@^5.6.3: + version "5.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" + integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== + typical@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" @@ -19720,15 +19845,20 @@ uncrypto@^0.1.3: resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== -undici-types@~6.19.2, undici-types@~6.19.8: +undici-types@~6.19.2: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + undici@5.28.4, undici@^5.14.0, undici@^6.11.1: - version "6.20.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.20.1.tgz#fbb87b1e2b69d963ff2d5410a40ffb4c9e81b621" - integrity sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA== + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.0.tgz#4b3d3afaef984e07b48e7620c34ed8a285ed4cd4" + integrity sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw== unenv@^1.10.0: version "1.10.0" @@ -20118,25 +20248,10 @@ viem@2.7.14: isows "1.0.3" ws "8.13.0" -viem@2.x, viem@^2.1.1: - version "2.21.44" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.44.tgz#793600a6afa8c0c1d62b4b819d036f833f623195" - integrity sha512-oyLTCt7OQUetQN2m9KPNgSA//MzpnQLABAyglPKh+fAypU8cTT/hC5UyLQvaYt4WPg6dkbKOxfsahV4739pu9w== - dependencies: - "@noble/curves" "1.6.0" - "@noble/hashes" "1.5.0" - "@scure/bip32" "1.5.0" - "@scure/bip39" "1.4.0" - abitype "1.0.6" - isows "1.0.6" - ox "0.1.2" - webauthn-p256 "0.0.10" - ws "8.18.0" - -viem@^2.21.44: - version "2.21.50" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.50.tgz#a645a7fb4a017c644712b905e03ab533b7e24ea7" - integrity sha512-WHB8NmkaForODuSALb0Ai3E296aEigzYSE+pzB9Y0cTNJeiZT8rpkdxxUFYfjwFMnPkz2tivqrSpuw3hO5TH6w== +viem@2.x, viem@^2.1.1, viem@^2.21.44: + version "2.21.52" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.52.tgz#a020f83c1e4df9dde78db3570f4c8c3a22ffb8ab" + integrity sha512-O53JhgVhp9CB0T3afy79O5ixNr8XXRGYQtlGYerzttnP56Oh2NBx4+Otz8IFd9N5DVPywf6tmYxHP1RVA99xJA== dependencies: "@noble/curves" "1.6.0" "@noble/hashes" "1.5.0" @@ -20159,16 +20274,16 @@ vite-node@1.6.0: picocolors "^1.0.0" vite "^5.0.0" -vite-node@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.5.tgz#cf28c637b2ebe65921f3118a165b7cf00a1cdf19" - integrity sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w== +vite-node@2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.6.tgz#d7b79c5cde56c749f619dead049944918726b91e" + integrity sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A== dependencies: cac "^6.7.14" debug "^4.3.7" es-module-lexer "^1.5.4" pathe "^1.1.2" - vite "^5.0.0" + vite "^5.0.0 || ^6.0.0" vite-plugin-node-polyfills@^0.22.0: version "0.22.0" @@ -20188,9 +20303,9 @@ vite-plugin-svgr@^4.2.0: "@svgr/plugin-jsx" "^8.1.0" vite@^5.0.0, vite@^5.4.7: - version "5.4.10" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.10.tgz#d358a7bd8beda6cf0f3b7a450a8c7693a4f80c18" - integrity sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ== + version "5.4.11" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.11.tgz#3b415cd4aed781a356c1de5a9ebafb837715f6e5" + integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q== dependencies: esbuild "^0.21.3" postcss "^8.4.43" @@ -20198,6 +20313,17 @@ vite@^5.0.0, vite@^5.4.7: optionalDependencies: fsevents "~2.3.3" +"vite@^5.0.0 || ^6.0.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.0.1.tgz#24c9caf24998f0598de37bed67e50ec5b9dfeaf0" + integrity sha512-Ldn6gorLGr4mCdFnmeAOLweJxZ34HjKnDm4HGo6P66IEqTxQb36VEdFJQENKxWjupNfoIjvRUnswjn1hpYEpjQ== + dependencies: + esbuild "^0.24.0" + postcss "^8.4.49" + rollup "^4.23.0" + optionalDependencies: + fsevents "~2.3.3" + vitest@^1.2.2, vitest@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.6.0.tgz#9d5ad4752a3c451be919e412c597126cffb9892f" @@ -20225,17 +20351,17 @@ vitest@^1.2.2, vitest@^1.6.0: why-is-node-running "^2.2.2" vitest@^2.1.2: - version "2.1.5" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.5.tgz#a93b7b84a84650130727baae441354e6df118148" - integrity sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A== - dependencies: - "@vitest/expect" "2.1.5" - "@vitest/mocker" "2.1.5" - "@vitest/pretty-format" "^2.1.5" - "@vitest/runner" "2.1.5" - "@vitest/snapshot" "2.1.5" - "@vitest/spy" "2.1.5" - "@vitest/utils" "2.1.5" + version "2.1.6" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.6.tgz#44d661c6b3f3a3a0c597143f78d27215ee4666cc" + integrity sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ== + dependencies: + "@vitest/expect" "2.1.6" + "@vitest/mocker" "2.1.6" + "@vitest/pretty-format" "^2.1.6" + "@vitest/runner" "2.1.6" + "@vitest/snapshot" "2.1.6" + "@vitest/spy" "2.1.6" + "@vitest/utils" "2.1.6" chai "^5.1.2" debug "^4.3.7" expect-type "^1.1.0" @@ -20246,8 +20372,8 @@ vitest@^2.1.2: tinyexec "^0.3.1" tinypool "^1.0.1" tinyrainbow "^1.2.0" - vite "^5.0.0" - vite-node "2.1.5" + vite "^5.0.0 || ^6.0.0" + vite-node "2.1.6" why-is-node-running "^2.3.0" vm-browserify@^1.0.1: @@ -20289,12 +20415,12 @@ wagmi@2.12.29: use-sync-external-store "1.2.0" wagmi@^2.12.8: - version "2.12.26" - resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-2.12.26.tgz#dc8f04d6733fb0c452dac67d93ceddd0b4d2fedc" - integrity sha512-TY4X/yquiNpFiao4tIcuy1p7vOFfrXhD4EP8k2vAJzhXAS9Po4KBTpsQBuNQuRjMDtTF/+vfn9rKG1bdG7DlAg== + version "2.13.2" + resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-2.13.2.tgz#a9e0d54efbff1927d32cebbc19bc426720da9feb" + integrity sha512-xm9vRcmDko/XYZDjYAqlx8TCa1MYMdVSM6NswQEv/E1Bg+9rfC/EK/5CyWLRkPUpEKn17kKfH/W9gAqmbQmRAw== dependencies: - "@wagmi/connectors" "5.3.4" - "@wagmi/core" "2.14.2" + "@wagmi/connectors" "5.5.2" + "@wagmi/core" "2.15.1" use-sync-external-store "1.2.0" walker@^1.0.8: @@ -20338,7 +20464,7 @@ web-vitals@^4.2.2: resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== -web3-core@^4.4.0, web3-core@^4.5.0, web3-core@^4.5.1, web3-core@^4.6.0, web3-core@^4.7.0: +web3-core@^4.4.0, web3-core@^4.5.0, web3-core@^4.6.0, web3-core@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-4.7.0.tgz#a109ed079e5f98a968487f4bb18c7aaf845f768a" integrity sha512-skP4P56fhlrE+rIuS4WY9fTdja1DPml2xrrDmv+vQhPtmSFBs7CqesycIRLQh4dK1D4de/a23tkX6DLYdUt3nA== @@ -20369,42 +20495,42 @@ web3-eth-abi@1.7.0: "@ethersproject/abi" "5.0.7" web3-utils "1.7.0" -web3-eth-abi@^4.2.3, web3-eth-abi@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.3.0.tgz#9036541206418b9db6f1db295ad87a6f0fa0ed7d" - integrity sha512-OqZPGGxHmfKJt33BfpclEMmWvnnLJ/B+jVTnVagd2OIU1kIv09xf/E60ei0eGeG612uFy/pPq31u4RidF/gf6g== +web3-eth-abi@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.4.0.tgz#30ded71d585b41d2f0f1f5d7c74faa2a4e70d240" + integrity sha512-RQzt9W93OgFBwOdNGcc9ulCyYt4zmRAMkKGbEdp3wcN4vmwTlRhh21+akj2ND4bg3C3RUiP4yprYgDEyN0/Fmg== dependencies: abitype "0.7.1" web3-errors "^1.3.0" - web3-types "^1.8.1" + web3-types "^1.9.0" web3-utils "^4.3.2" web3-validator "^2.0.6" -web3-eth-accounts@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-4.2.1.tgz#db27399137e1a26f9d467b9500019a70771f5724" - integrity sha512-aOlEZFzqAgKprKs7+DGArU4r9b+ILBjThpeq42aY7LAQcP+mSpsWcQgbIRK3r/n3OwTYZ3aLPk0Ih70O/LwnYA== +web3-eth-accounts@^4.2.1, web3-eth-accounts@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-4.3.0.tgz#b103e827ff1d07252181776b1b665d6a19a73980" + integrity sha512-7UX3rJiNgHYoqrO1WRPks/9J5Mh2x5N9HAd9QsOM8zfKY2rwSyCIIQM03OFXDEQRZ/ztycKTHgeLStmhlUUKIQ== dependencies: "@ethereumjs/rlp" "^4.0.1" crc-32 "^1.2.2" ethereum-cryptography "^2.0.0" web3-errors "^1.3.0" - web3-types "^1.7.0" - web3-utils "^4.3.1" + web3-types "^1.9.0" + web3-utils "^4.3.2" web3-validator "^2.0.6" -web3-eth-contract@^4.5.0, web3-eth-contract@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-4.7.0.tgz#119a744e8a35f60fd7bc3e4f8637f0380a3d0e85" - integrity sha512-fdStoBOjFyMHwlyJmSUt/BTDL1ATwKGmG3zDXQ/zTKlkkW/F/074ut0Vry4GuwSBg9acMHc0ycOiZx9ZKjNHsw== +web3-eth-contract@^4.5.0, web3-eth-contract@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-4.7.1.tgz#8d447b96323203a2a2744efdf87a1f0dffe4bcc1" + integrity sha512-D9nHCclq4lj2CX1sOrGga1UFA9CNBWZV6NGwNr6WjbBGIFl9ui2mivE9c3vNGEfSMnvKEq/zE83N+eGOwcWZlg== dependencies: "@ethereumjs/rlp" "^5.0.2" - web3-core "^4.5.1" + web3-core "^4.7.0" web3-errors "^1.3.0" - web3-eth "^4.8.2" - web3-eth-abi "^4.2.3" - web3-types "^1.7.0" - web3-utils "^4.3.1" + web3-eth "^4.11.0" + web3-eth-abi "^4.4.0" + web3-types "^1.9.0" + web3-utils "^4.3.2" web3-validator "^2.0.6" web3-eth-ens@^4.4.0: @@ -20444,20 +20570,20 @@ web3-eth-personal@^4.1.0: web3-utils "^4.3.1" web3-validator "^2.0.6" -web3-eth@^4.10.0, web3-eth@^4.8.0, web3-eth@^4.8.2, web3-eth@^4.9.0: - version "4.10.0" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-4.10.0.tgz#a62017908e543fe1bae398e2384bd29d1ebbbacd" - integrity sha512-8d7epCOm1hv/xGnOW8pWNkO5Ze9b+LKl81Pa1VUdRi2xZKtBaQsk+4qg6EnqeDF6SPpL502wNmX6TAB69vGBWw== +web3-eth@^4.11.0, web3-eth@^4.8.0, web3-eth@^4.9.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-4.11.0.tgz#ea24b9c3db175438ea46738a20e28dbde7c8fe54" + integrity sha512-nZIJ/8FOOj5aEXoS8p9puuX5jLyzewZv3nXqoKNtu531/vA/yIiU/EtPnAV62RvVMcbDSiF/BLVFdBZCsVMJbg== dependencies: setimmediate "^1.0.5" web3-core "^4.7.0" web3-errors "^1.3.0" - web3-eth-abi "^4.3.0" - web3-eth-accounts "^4.2.1" + web3-eth-abi "^4.4.0" + web3-eth-accounts "^4.3.0" web3-net "^4.1.0" web3-providers-ws "^4.0.8" web3-rpc-methods "^1.3.0" - web3-types "^1.8.1" + web3-types "^1.9.0" web3-utils "^4.3.2" web3-validator "^2.0.6" @@ -20511,22 +20637,22 @@ web3-rpc-methods@^1.3.0: web3-types "^1.6.0" web3-validator "^2.0.6" -web3-rpc-providers@^1.0.0-rc.2: - version "1.0.0-rc.2" - resolved "https://registry.yarnpkg.com/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.2.tgz#2f3bf62415708ce09ffd5c77d197046e7d5fefb1" - integrity sha512-ocFIEXcBx/DYQ90HhVepTBUVnL9pGsZw8wyPb1ZINSenwYus9SvcFkjU1Hfvd/fXjuhAv2bUVch9vxvMx1mXAQ== +web3-rpc-providers@^1.0.0-rc.3: + version "1.0.0-rc.3" + resolved "https://registry.yarnpkg.com/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.3.tgz#be14c679cea1e7ee742b60e68bcdfe760a90e3e7" + integrity sha512-aeFPYgvHjsf2yQi3CSQA9Ie4xnmO7VmNkY098rA7AWvhgyjVgIWlrVgZjUn55FXtthbiiTRm/CLriv99UeOfGQ== dependencies: web3-errors "^1.3.0" web3-providers-http "^4.2.0" web3-providers-ws "^4.0.8" - web3-types "^1.7.0" - web3-utils "^4.3.1" + web3-types "^1.9.0" + web3-utils "^4.3.2" web3-validator "^2.0.6" -web3-types@^1.3.0, web3-types@^1.6.0, web3-types@^1.7.0, web3-types@^1.8.0, web3-types@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.8.1.tgz#6379aca0f99330eb0f8f6ca80a3de93129b58339" - integrity sha512-isspsvQbBJFUkJYz2Badb7dz/BrLLLpOop/WmnL5InyYMr7kYYc8038NYO7Vkp1M7Bupa/wg+yALvBm7EGbyoQ== +web3-types@^1.3.0, web3-types@^1.6.0, web3-types@^1.7.0, web3-types@^1.8.0, web3-types@^1.8.1, web3-types@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.9.0.tgz#4cfd17d5d3485797df1d72de8f2f8d03b0d1ac61" + integrity sha512-I520KBPoXqEaM/ybj6xHD1E3gRb8/WdudLQaRBvJNQSSfHuPW9P2sD59mbhm6dsKtnje+T90dIxSyzVVFlEdlg== web3-utils@1.7.0: version "1.7.0" @@ -20578,16 +20704,16 @@ web3-validator@^2.0.3, web3-validator@^2.0.6: zod "^3.21.4" web3@^4.12.1: - version "4.14.0" - resolved "https://registry.yarnpkg.com/web3/-/web3-4.14.0.tgz#9d69e3a8a64da9377fbec416dfe4d260ddfa2711" - integrity sha512-LohqxtSXXl4uA3abPK0bB91dziA5GygOLtO83p8bQzY+CYxp1fgGfiD8ahDRcu+WBttUhRFZmCsOhmrmP7HtTA== + version "4.15.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-4.15.0.tgz#925a7881d56da1ef808be12bbc8a38ccb872cc6f" + integrity sha512-0QWDWE4gDWldXb4KWq++K8m/A9zsR0LpJLtVT39/b4OjfdW0d4mE0qAUd3UocxuKTh1eG5pOCfumbGS5l6p1qg== dependencies: web3-core "^4.7.0" web3-errors "^1.3.0" - web3-eth "^4.10.0" - web3-eth-abi "^4.3.0" - web3-eth-accounts "^4.2.1" - web3-eth-contract "^4.7.0" + web3-eth "^4.11.0" + web3-eth-abi "^4.4.0" + web3-eth-accounts "^4.3.0" + web3-eth-contract "^4.7.1" web3-eth-ens "^4.4.0" web3-eth-iban "^4.0.7" web3-eth-personal "^4.1.0" @@ -20595,8 +20721,8 @@ web3@^4.12.1: web3-providers-http "^4.2.0" web3-providers-ws "^4.0.8" web3-rpc-methods "^1.3.0" - web3-rpc-providers "^1.0.0-rc.2" - web3-types "^1.8.1" + web3-rpc-providers "^1.0.0-rc.3" + web3-types "^1.9.0" web3-utils "^4.3.2" web3-validator "^2.0.6" @@ -20737,16 +20863,17 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-builtin-type@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.4.tgz#592796260602fc3514a1b5ee7fa29319b72380c3" - integrity sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w== +which-builtin-type@^1.1.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.0.tgz#58042ac9602d78a6d117c7e811349df1268ba63c" + integrity sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA== dependencies: + call-bind "^1.0.7" function.prototype.name "^1.1.6" has-tostringtag "^1.0.2" is-async-function "^2.0.0" is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" + is-finalizationregistry "^1.1.0" is-generator-function "^1.0.10" is-regex "^1.1.4" is-weakref "^1.0.2" @@ -20771,9 +20898,9 @@ which-module@^2.0.0: integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + version "1.1.16" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.16.tgz#db4db429c4706feca2f01677a144278e4a8c216b" + integrity sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ== dependencies: available-typed-arrays "^1.0.7" call-bind "^1.0.7" @@ -20983,9 +21110,9 @@ yaml@1.10.2, yaml@^1.10.0, yaml@^1.10.2: integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yaml@^2.5.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3" - integrity sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ== + version "2.6.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.1.tgz#42f2b1ba89203f374609572d5349fb8686500773" + integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== yaml@~2.5.0: version "2.5.1" From 9e3c26aa5f0c0b0119a6010e4e20282c122a26ef Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Fri, 29 Nov 2024 14:17:27 +0100 Subject: [PATCH 27/92] [Human App] fix: adjust network names and filters (#2856) --- .../human-app/frontend/src/api/api-paths.ts | 3 + .../src/api/services/worker/get-ui-config.ts | 28 ++ .../src/hooks/use-get-all-networks.ts | 15 + .../desktop/available-jobs-network-filter.tsx | 14 +- .../desktop/available-jobs-table.tsx | 22 +- .../mobile/available-jobs-drawer-mobile.tsx | 4 +- .../available-jobs-network-filter-mobile.tsx | 14 +- .../mobile/available-jobs-table-mobile.tsx | 2 +- .../worker/jobs/components/drawer-mobile.tsx | 275 ------------------ .../desktop/my-jobs-network-filter.tsx | 14 +- .../my-jobs/desktop/my-jobs-table.tsx | 17 +- .../my-jobs/mobile/my-jobs-drawer-mobile.tsx | 4 +- .../mobile/my-jobs-network-filter-mobile.tsx | 14 +- .../my-jobs/mobile/my-jobs-table-mobile.tsx | 2 +- .../src/pages/worker/jobs/jobs.page.tsx | 32 +- .../frontend/src/smart-contracts/chains.ts | 100 ++++++- .../src/smart-contracts/get-network-name.ts | 8 +- 17 files changed, 232 insertions(+), 336 deletions(-) create mode 100644 packages/apps/human-app/frontend/src/api/services/worker/get-ui-config.ts create mode 100644 packages/apps/human-app/frontend/src/hooks/use-get-all-networks.ts delete mode 100644 packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx diff --git a/packages/apps/human-app/frontend/src/api/api-paths.ts b/packages/apps/human-app/frontend/src/api/api-paths.ts index 03c0116814..d925116678 100644 --- a/packages/apps/human-app/frontend/src/api/api-paths.ts +++ b/packages/apps/human-app/frontend/src/api/api-paths.ts @@ -71,6 +71,9 @@ export const apiPaths = { registrationInExchangeOracle: { path: '/exchange-oracle-registration', }, + uiConfig: { + path: '/ui-config', + }, }, operator: { web3Auth: { diff --git a/packages/apps/human-app/frontend/src/api/services/worker/get-ui-config.ts b/packages/apps/human-app/frontend/src/api/services/worker/get-ui-config.ts new file mode 100644 index 0000000000..29c628ded6 --- /dev/null +++ b/packages/apps/human-app/frontend/src/api/services/worker/get-ui-config.ts @@ -0,0 +1,28 @@ +import { useQuery } from '@tanstack/react-query'; +import { z } from 'zod'; +import { apiClient } from '@/api/api-client'; +import { apiPaths } from '@/api/api-paths'; + +const uiConfigSchema = z.object({ + chainIdsEnabled: z.array(z.number()), +}); + +export type UiConfig = z.infer; + +const getUiConfig = async (): Promise => { + const response = await apiClient(apiPaths.worker.uiConfig.path, { + successSchema: uiConfigSchema, + options: { + method: 'GET', + }, + }); + return response; +}; + +export function useGetUiConfig() { + return useQuery({ + queryKey: ['ui-config'], + queryFn: getUiConfig, + staleTime: Infinity, + }); +} diff --git a/packages/apps/human-app/frontend/src/hooks/use-get-all-networks.ts b/packages/apps/human-app/frontend/src/hooks/use-get-all-networks.ts new file mode 100644 index 0000000000..f2a68c4cf7 --- /dev/null +++ b/packages/apps/human-app/frontend/src/hooks/use-get-all-networks.ts @@ -0,0 +1,15 @@ +import { useMemo } from 'react'; +import { getEnabledChainsByUiConfig } from '@/smart-contracts/chains'; + +export const useGetAllNetworks = (chainIdsEnabled: number[]) => { + const allNetworks = useMemo(() => { + const chains = getEnabledChainsByUiConfig(chainIdsEnabled); + + return chains.map(({ chainId, name }) => ({ + option: chainId, + name, + })); + }, [chainIdsEnabled]); + + return { allNetworks }; +}; diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-network-filter.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-network-filter.tsx index 00a6e1851a..371a26ab66 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-network-filter.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/desktop/available-jobs-network-filter.tsx @@ -1,15 +1,17 @@ /* eslint-disable camelcase --- ... */ -import { chains } from '@/smart-contracts/chains'; +import { useGetAllNetworks } from '@/hooks/use-get-all-networks'; import { Filtering } from '@/components/ui/table/table-header-menu.tsx/filtering'; import { useJobsFilterStore } from '@/hooks/use-jobs-filter-store'; -const allNetworks = chains.map(({ chainId, name }) => ({ - option: chainId, - name, -})); +interface AvailableJobsNetworkFilterProps { + chainIdsEnabled: number[]; +} -export function AvailableJobsNetworkFilter() { +export function AvailableJobsNetworkFilter({ + chainIdsEnabled, +}: AvailableJobsNetworkFilterProps) { const { setFilterParams, filterParams } = useJobsFilterStore(); + const { allNetworks } = useGetAllNetworks(chainIdsEnabled); return ( [] = [ +const getColumns = ( + chainIdsEnabled: number[] +): MRT_ColumnDef[] => [ { accessorKey: 'job_description', header: t('worker.jobs.jobDescription'), @@ -56,8 +62,8 @@ const columns: MRT_ColumnDef[] = [ header: t('worker.jobs.network'), size: 100, enableSorting: false, - Cell: () => { - return getNetworkName(); + Cell: (props) => { + return getNetworkName(props.row.original.chain_id); }, muiTableHeadCellProps: () => ({ component: (props) => { @@ -66,7 +72,9 @@ const columns: MRT_ColumnDef[] = [ {...props} headerText={t('worker.jobs.network')} iconType="filter" - popoverContent={} + popoverContent={ + + } /> ); }, @@ -156,7 +164,9 @@ const columns: MRT_ColumnDef[] = [ }, ]; -export function AvailableJobsTable() { +export function AvailableJobsTable({ + chainIdsEnabled, +}: AvailableJobsTableProps) { const { colorPalette, isDarkMode } = useColorMode(); const { setSearchEscrowAddress, @@ -194,6 +204,8 @@ export function AvailableJobsTable() { }; }, [resetFilterParams]); + const columns: MRT_ColumnDef[] = getColumns(chainIdsEnabled); + const table = useMaterialReactTable({ columns, data: memoizedTableDataResults, diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx index bf967dbf02..2b6f29f2ab 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx @@ -15,9 +15,11 @@ import { useColorMode } from '@/hooks/use-color-mode'; interface DrawerMobileProps { setIsMobileFilterDrawerOpen: Dispatch>; + chainIdsEnabled: number[]; } export function AvailableJobsDrawerMobile({ setIsMobileFilterDrawerOpen, + chainIdsEnabled, }: DrawerMobileProps) { const handleMainNavIconClick = useHandleMainNavIconClick(); const { colorPalette } = useColorMode(); @@ -109,7 +111,7 @@ export function AvailableJobsDrawerMobile({ flexDirection="row" key={crypto.randomUUID()} > - + ({ - option: chainId, - name, -})); +interface AvailableJobsNetworkFilterProps { + chainIdsEnabled: number[]; +} -export function AvailableJobsNetworkFilterMobile() { +export function AvailableJobsNetworkFilterMobile({ + chainIdsEnabled, +}: AvailableJobsNetworkFilterProps) { const { setFilterParams, filterParams } = useJobsFilterStore(); + const { allNetworks } = useGetAllNetworks(chainIdsEnabled); return ( - {getNetworkName()} + {getNetworkName(d.chain_id)}
diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx deleted file mode 100644 index 9e4e88ce71..0000000000 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/drawer-mobile.tsx +++ /dev/null @@ -1,275 +0,0 @@ -/* eslint-disable camelcase --- response from api */ -import Box from '@mui/material/Box'; -import Drawer from '@mui/material/Drawer'; -import CssBaseline from '@mui/material/CssBaseline'; -import { - Checkbox, - Divider, - IconButton, - Stack, - Typography, -} from '@mui/material'; -import { useTranslation } from 'react-i18next'; -import CloseIcon from '@mui/icons-material/Close'; -import type { Dispatch, SetStateAction } from 'react'; -import { Button } from '@/components/ui/button'; -import { HumanLogoIcon, SortArrow } from '@/components/ui/icons'; -import type { JobsFilterStoreProps } from '@/hooks/use-jobs-filter-store'; -import { useJobsFilterStore } from '@/hooks/use-jobs-filter-store'; -import { AvailableJobsNetworkFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-network-filter-mobile'; -import { AvailableJobsStatusFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile'; -import { AvailableJobsJobTypeFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-job-type-filter-mobile'; -import { useColorMode } from '@/hooks/use-color-mode'; -import { MyJobStatus } from '@/api/services/worker/my-jobs-data'; - -interface DrawerMobileProps { - selectedTab: string; - setIsMobileFilterDrawerOpen: Dispatch>; -} -export function DrawerMobile({ - selectedTab, - setIsMobileFilterDrawerOpen, -}: DrawerMobileProps) { - const { colorPalette } = useColorMode(); - const { t } = useTranslation(); - const { setFilterParams, filterParams } = useJobsFilterStore(); - - const handleCheckboxClick = ( - paramName: keyof JobsFilterStoreProps['filterParams'], - paramValue: string - ) => { - if (filterParams[paramName] === paramValue) { - setFilterParams({ - ...filterParams, - [paramName]: undefined, - }); - } else { - setFilterParams({ - ...filterParams, - [paramName]: paramValue, - }); - } - }; - - return ( - - - - - - - { - setIsMobileFilterDrawerOpen(false); - }} - sx={{ - zIndex: '99999999', - marginRight: '15px', - backgroundColor: colorPalette.white, - }} - > - - - - - {t('worker.jobs.mobileFilterDrawer.filters')} - - - - {t('worker.jobs.mobileFilterDrawer.sortBy')} - - - {t('worker.jobs.rewardAmount')} - - - - - {t('worker.jobs.mobileFilterDrawer.filters')} - - - - {t('worker.jobs.network')} - - - - - - - - {t('worker.jobs.jobType')} - - - - - - - {t('worker.jobs.status')} - - <> - - {selectedTab === 'myJobs' && ( - <> - - { - handleCheckboxClick('status', 'validation'); - }} - /> - - {t('worker.jobs.mobileFilterDrawer.jobsStatus.validation')} - - - - { - handleCheckboxClick('status', 'expired'); - }} - /> - - {t('worker.jobs.mobileFilterDrawer.jobsStatus.expired')} - - - - { - handleCheckboxClick('status', 'rejected'); - }} - /> - - {t('worker.jobs.mobileFilterDrawer.jobsStatus.rejected')} - - - - )} - - - - ); -} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-network-filter.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-network-filter.tsx index b7942d49f8..03bcd86cda 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-network-filter.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/desktop/my-jobs-network-filter.tsx @@ -1,15 +1,17 @@ /* eslint-disable camelcase --- ... */ import { useMyJobsFilterStore } from '@/hooks/use-my-jobs-filter-store'; -import { chains } from '@/smart-contracts/chains'; +import { useGetAllNetworks } from '@/hooks/use-get-all-networks'; import { Filtering } from '@/components/ui/table/table-header-menu.tsx/filtering'; -const allNetworks = chains.map(({ chainId, name }) => ({ - option: chainId, - name, -})); +interface MyJobsNetworkFilterProps { + chainIdsEnabled: number[]; +} -export function MyJobsNetworkFilter() { +export function MyJobsNetworkFilter({ + chainIdsEnabled, +}: MyJobsNetworkFilterProps) { const { setFilterParams, filterParams } = useMyJobsFilterStore(); + const { allNetworks } = useGetAllNetworks(chainIdsEnabled); return ( void; isRefreshTasksPending: boolean; + chainIdsEnabled: number[]; }): MRT_ColumnDef[] => [ { accessorKey: 'escrow_address', @@ -54,8 +60,8 @@ const getColumnsDefinition = ({ accessorKey: 'network', header: t('worker.jobs.network'), size: 100, - Cell: () => { - return getNetworkName(); + Cell: (props) => { + return getNetworkName(props.row.original.chain_id); }, muiTableHeadCellProps: () => ({ component: (props) => { @@ -64,7 +70,9 @@ const getColumnsDefinition = ({ {...props} headerText={t('worker.jobs.network')} iconType="filter" - popoverContent={} + popoverContent={ + + } /> ); }, @@ -205,7 +213,7 @@ const getColumnsDefinition = ({ }, ]; -export function MyJobsTable() { +export function MyJobsTable({ chainIdsEnabled }: MyJobsTableProps) { const { colorPalette, isDarkMode } = useColorMode(); const { setSearchEscrowAddress, @@ -257,6 +265,7 @@ export function MyJobsTable() { columns: getColumnsDefinition({ refreshData: refreshTasks(oracle_address ?? ''), isRefreshTasksPending, + chainIdsEnabled, }), data: memoizedTableDataResults, state: { diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-drawer-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-drawer-mobile.tsx index 6fc2d5b52d..4309e49a39 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-drawer-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs/mobile/my-jobs-drawer-mobile.tsx @@ -16,9 +16,11 @@ import { MyJobsStatusFilterMobile } from './my-jobs-status-filter-mobile'; interface DrawerMobileProps { setIsMobileFilterDrawerOpen: Dispatch>; + chainIdsEnabled: number[]; } export function MyJobsDrawerMobile({ setIsMobileFilterDrawerOpen, + chainIdsEnabled, }: DrawerMobileProps) { const handleMainNavIconClick = useHandleMainNavIconClick(); const { colorPalette } = useColorMode(); @@ -111,7 +113,7 @@ export function MyJobsDrawerMobile({ flexDirection="row" key={crypto.randomUUID()} > - + ({ - option: chainId, - name, -})); +interface MyJobsNetworkFilterMobileProps { + chainIdsEnabled: number[]; +} -export function MyJobsNetworkFilterMobile() { +export function MyJobsNetworkFilterMobile({ + chainIdsEnabled, +}: MyJobsNetworkFilterMobileProps) { const { setFilterParams, filterParams } = useMyJobsFilterStore(); + const { allNetworks } = useGetAllNetworks(chainIdsEnabled); return ( - {getNetworkName()} + {getNetworkName(d.chain_id)} diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/jobs.page.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/jobs.page.tsx index 05bc12ac2f..5d470fdc4b 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/jobs.page.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/jobs.page.tsx @@ -11,6 +11,7 @@ import { AvailableJobsTable } from '@/pages/worker/jobs/components/available-job import { MyJobsDrawerMobile } from '@/pages/worker/jobs/components/my-jobs/mobile/my-jobs-drawer-mobile'; import { AvailableJobsDrawerMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile'; import { useGetOracles } from '@/api/services/worker/oracles'; +import { useGetUiConfig } from '@/api/services/worker/get-ui-config'; import { PageCardLoader } from '@/components/ui/page-card'; import { useColorMode } from '@/hooks/use-color-mode'; import { useGetOraclesNotifications } from '@/hooks/use-get-oracles-notifications'; @@ -28,7 +29,17 @@ function generateTabA11yProps(index: number) { export function JobsPage() { const { isDarkMode } = useColorMode(); - const { data, isError, isPending, error } = useGetOracles(); + const { + data, + isError: isErrorGetOracles, + isPending: isPendingGetOracles, + error, + } = useGetOracles(); + const { + data: uiConfigData, + isPending: isPendingUiConfig, + isError: isErrorUiConfig, + } = useGetUiConfig(); const { address: oracle_address } = useParams<{ address: string }>(); const { t } = useTranslation(); const [activeTab, setActiveTab] = useState(0); @@ -36,6 +47,10 @@ export function JobsPage() { const [selectedTab, setSelectedTab] = useState<'availableJobs' | 'myJobs'>( 'availableJobs' ); + + const isError = isErrorGetOracles || isErrorUiConfig; + const isPending = isPendingGetOracles || isPendingUiConfig; + const [isMobileFilterDrawerOpen, setIsMobileFilterDrawerOpen] = useState(false); const { onError } = useGetOraclesNotifications(); @@ -68,12 +83,15 @@ export function JobsPage() { return ( <> - {selectedTab === 'availableJobs' ? ( + {selectedTab === 'availableJobs' && uiConfigData && ( - ) : ( + )} + {selectedTab === 'myJobs' && uiConfigData && ( )} @@ -142,7 +160,9 @@ export function JobsPage() { } /> ) : ( - + )} )} @@ -159,7 +179,9 @@ export function JobsPage() { } /> ) : ( - + )} )} diff --git a/packages/apps/human-app/frontend/src/smart-contracts/chains.ts b/packages/apps/human-app/frontend/src/smart-contracts/chains.ts index 3d6f01b0b5..b71cdf9888 100644 --- a/packages/apps/human-app/frontend/src/smart-contracts/chains.ts +++ b/packages/apps/human-app/frontend/src/smart-contracts/chains.ts @@ -3,33 +3,60 @@ // For particular chains we define set of smart contract addresses. // Thanks to that we can get addresses for selected chain with getContractAddress // function - +import { ChainId } from '@human-protocol/sdk/src/enums'; +import { NETWORKS } from '@human-protocol/sdk/src/constants'; +import { env } from '@/shared/env'; import { MainnetContracts, TestnetContracts, type ContractsAddresses, } from '@/smart-contracts/contracts'; -import { env } from '@/shared/env'; export interface Chain { - rpcUrl: string; explorerUrl: string; - currency: string; name: string; chainId: number; + rpcUrl?: string; } export type ChainWithAddresses = Chain & { addresses: ContractsAddresses; }; +export const TestnetChainsIds = [ + ChainId.POLYGON_AMOY, + ChainId.SEPOLIA, + ChainId.RINKEBY, + ChainId.GOERLI, + ChainId.BSC_TESTNET, + ChainId.POLYGON_MUMBAI, + ChainId.MOONBASE_ALPHA, + ChainId.AVALANCHE_TESTNET, + ChainId.CELO_ALFAJORES, + ChainId.XLAYER_TESTNET, + ChainId.LOCALHOST, +] as const; + +export const MainnetChainsIds = [ + ChainId.POLYGON, + ChainId.MAINNET, + ChainId.BSC_MAINNET, + ChainId.MOONBEAM, + ChainId.AVALANCHE, + ChainId.CELO, + ChainId.XLAYER, + ChainId.ALL, +] as const; + +export type TestnetNarrow = Exclude; +export type MainnetNarrow = Exclude; + export const TestnetChains: ChainWithAddresses[] = [ { chainId: 80002, name: 'Amoy', - rpcUrl: 'https://rpc-amoy.polygon.technology', - currency: 'MATIC', explorerUrl: 'https://amoy.polygonscan.com/', + rpcUrl: 'https://rpc-amoy.polygon.technology', addresses: TestnetContracts.Amoy, }, ]; @@ -38,18 +65,61 @@ export const MainnetChains: ChainWithAddresses[] = [ { chainId: 137, name: 'Polygon', - rpcUrl: 'https://polygon-rpc.com', - currency: 'MATIC', explorerUrl: 'https://polygonscan.com/', + rpcUrl: 'https://polygon-rpc.com/', addresses: MainnetContracts.Polygon, }, ]; -// chains for getContractAddress function -export const chainsWithSCAddresses: ChainWithAddresses[] = - env.VITE_NETWORK === 'mainnet' ? MainnetChains : TestnetChains; +export const AllTestnetsChains: ChainWithAddresses[] = + getChainConfigsForChainIds([...TestnetChainsIds]); + +export const AllMainnetChains: ChainWithAddresses[] = + getChainConfigsForChainIds([...MainnetChainsIds]); + +function getChainConfigsForChainIds( + chainsArr: T[] +): ChainWithAddresses[] { + const result: ChainWithAddresses[] = []; + + for (const currentValue of chainsArr) { + if (currentValue in NETWORKS) { + result.push({ + chainId: currentValue, + name: NETWORKS[currentValue]?.title ?? '', + explorerUrl: NETWORKS[currentValue]?.scanUrl ?? '', + addresses: { + Staking: NETWORKS[currentValue]?.stakingAddress ?? '', + HMToken: NETWORKS[currentValue]?.hmtAddress ?? '', + EthKVStore: NETWORKS[currentValue]?.kvstoreAddress ?? '', + }, + }); + } + } + return result; +} + +const handleFilterChains = ( + chainsArr: ChainWithAddresses[], + chainIdsEnabled: number[] +) => { + return chainsArr.filter((chain) => + chainIdsEnabled.some((el) => el === chain.chainId) + ); +}; + +export const getTestnetChainsEnabled = (chainIdsEnabled: number[]) => { + return handleFilterChains(AllTestnetsChains, chainIdsEnabled); +}; + +export const getMainnetChainsEnabled = (chainIdsEnabled: number[]) => { + return handleFilterChains(AllMainnetChains, chainIdsEnabled); +}; -// chains for wallet-connect modal -export const chains: Chain[] = ( - env.VITE_NETWORK === 'mainnet' ? MainnetChains : TestnetChains -).map(({ addresses: _, ...chainData }) => chainData); +export const getEnabledChainsByUiConfig = ( + chainIdsEnabled: number[] +): Chain[] => + (env.VITE_NETWORK === 'mainnet' + ? getMainnetChainsEnabled(chainIdsEnabled) + : getTestnetChainsEnabled(chainIdsEnabled) + ).map(({ addresses: _, ...chainData }) => chainData); diff --git a/packages/apps/human-app/frontend/src/smart-contracts/get-network-name.ts b/packages/apps/human-app/frontend/src/smart-contracts/get-network-name.ts index 22717f2b5a..9905705b8d 100644 --- a/packages/apps/human-app/frontend/src/smart-contracts/get-network-name.ts +++ b/packages/apps/human-app/frontend/src/smart-contracts/get-network-name.ts @@ -1,9 +1,9 @@ -import { MainnetChains, TestnetChains } from '@/smart-contracts/chains'; +import { AllTestnetsChains, AllMainnetChains } from '@/smart-contracts/chains'; import { env } from '@/shared/env'; -export const getNetworkName = (): string => { +export const getNetworkName = (chainId: number): string => { if (env.VITE_NETWORK === 'testnet') { - return TestnetChains[0]?.name; + return AllTestnetsChains.find((el) => el.chainId === chainId)?.name ?? ''; } - return MainnetChains[0]?.name; + return AllMainnetChains.find((el) => el.chainId === chainId)?.name ?? ''; }; From d8227f868c088956be2e517f4327ff84a6d0ed77 Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Fri, 29 Nov 2024 16:17:47 +0300 Subject: [PATCH 28/92] [Human App] fix: base url for refreshToken fn (#2864) --- packages/apps/human-app/frontend/src/api/fetcher.ts | 5 +++-- .../frontend/src/shared/helpers/normalize-base-url.ts | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 packages/apps/human-app/frontend/src/shared/helpers/normalize-base-url.ts diff --git a/packages/apps/human-app/frontend/src/api/fetcher.ts b/packages/apps/human-app/frontend/src/api/fetcher.ts index 8a1c19ce8b..73bb6d41bb 100644 --- a/packages/apps/human-app/frontend/src/api/fetcher.ts +++ b/packages/apps/human-app/frontend/src/api/fetcher.ts @@ -4,6 +4,7 @@ import type { ResponseError } from '@/shared/types/global.type'; import { browserAuthProvider } from '@/shared/helpers/browser-auth-provider'; import { env } from '@/shared/env'; import { type SignInSuccessResponse } from '@/api/services/worker/sign-in/types'; +import { normalizeBaseUrl } from '@/shared/helpers/normalize-base-url'; import { fetchTokenRefresh } from './fetch-refresh-token'; const appendHeader = ( @@ -72,7 +73,7 @@ export async function refreshToken(): Promise<{ refresh_token: string; } | null> { if (!refreshPromise) { - refreshPromise = fetchTokenRefresh(env.VITE_API_URL); + refreshPromise = fetchTokenRefresh(normalizeBaseUrl(env.VITE_API_URL)); } const result = await refreshPromise; @@ -159,7 +160,7 @@ export function createFetcher(defaultFetcherConfig?: { const urlAsString = fetchUrlToString(baseUrl); if (!urlAsString) return url; const normalizedUrl = fetchUrlToString(url).replace(/\//, ''); - const normalizedBaseUrl = urlAsString.replace(/\/$/, ''); + const normalizedBaseUrl = normalizeBaseUrl(urlAsString); return `${normalizedBaseUrl}/${normalizedUrl}`; })(); diff --git a/packages/apps/human-app/frontend/src/shared/helpers/normalize-base-url.ts b/packages/apps/human-app/frontend/src/shared/helpers/normalize-base-url.ts new file mode 100644 index 0000000000..10c493ddb7 --- /dev/null +++ b/packages/apps/human-app/frontend/src/shared/helpers/normalize-base-url.ts @@ -0,0 +1,3 @@ +export function normalizeBaseUrl(baseUrl: string): string { + return baseUrl.replace(/\/$/, ''); +} From 1b66b1f351b998764a7e822573d386cd886338ac Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Fri, 29 Nov 2024 15:10:55 +0100 Subject: [PATCH 29/92] [Human App] fix: remove status filter for available jobs on mobile (#2843) --- .../src/assets/icons-dark-mode/refresh.svg | 2 +- .../frontend/src/assets/icons/refresh.svg | 2 +- .../mobile/available-jobs-drawer-mobile.tsx | 11 ------- .../available-jobs-status-filter-mobile.tsx | 33 ------------------- 4 files changed, 2 insertions(+), 46 deletions(-) delete mode 100644 packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx diff --git a/packages/apps/human-app/frontend/src/assets/icons-dark-mode/refresh.svg b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/refresh.svg index f01c9a38e6..c74526a1bf 100644 --- a/packages/apps/human-app/frontend/src/assets/icons-dark-mode/refresh.svg +++ b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/refresh.svg @@ -1,3 +1,3 @@ - + diff --git a/packages/apps/human-app/frontend/src/assets/icons/refresh.svg b/packages/apps/human-app/frontend/src/assets/icons/refresh.svg index 7590498e9c..35b4dec21e 100644 --- a/packages/apps/human-app/frontend/src/assets/icons/refresh.svg +++ b/packages/apps/human-app/frontend/src/assets/icons/refresh.svg @@ -1,3 +1,3 @@ - + diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx index 2b6f29f2ab..822d06cce8 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-drawer-mobile.tsx @@ -7,7 +7,6 @@ import CloseIcon from '@mui/icons-material/Close'; import type { Dispatch, SetStateAction } from 'react'; import { HumanLogoIcon } from '@/components/ui/icons'; import { AvailableJobsNetworkFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-network-filter-mobile'; -import { AvailableJobsStatusFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile'; import { useHandleMainNavIconClick } from '@/hooks/use-handle-main-nav-icon-click'; import { AvailableJobsJobTypeFilterMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-job-type-filter-mobile'; import { AvailableJobsRewardAmountSortMobile } from '@/pages/worker/jobs/components/available-jobs/mobile/available-jobs-reward-amount-sort-mobile'; @@ -130,16 +129,6 @@ export function AvailableJobsDrawerMobile({ > - - - {t('worker.jobs.status')} - - ); diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx deleted file mode 100644 index af413edd7b..0000000000 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/available-jobs/mobile/available-jobs-status-filter-mobile.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import capitalize from 'lodash/capitalize'; -import { Filtering } from '@/components/ui/table/table-header-menu.tsx/filtering'; -import { useJobsFilterStore } from '@/hooks/use-jobs-filter-store'; -import { MyJobStatus } from '@/api/services/worker/my-jobs-data'; - -export function AvailableJobsStatusFilterMobile() { - const { setFilterParams, filterParams } = useJobsFilterStore(); - - return ( - { - setFilterParams({ - ...filterParams, - status: undefined, - page: 0, - }); - }} - filteringOptions={Object.values(MyJobStatus).map((status) => ({ - name: capitalize(status), - option: status, - }))} - isChecked={(status) => status === filterParams.status} - isMobile={false} - setFiltering={(status) => { - setFilterParams({ - ...filterParams, - status, - page: 0, - }); - }} - /> - ); -} From f8d85a1dc7d312c79d20bf8701c74536b7b47d66 Mon Sep 17 00:00:00 2001 From: mpblocky <185767042+mpblocky@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:35:26 +0100 Subject: [PATCH 30/92] [Human App] fix: type assertion in web3 provider hook (#2865) --- .../human-app/frontend/src/components/data-entry/input.tsx | 4 ++-- .../apps/human-app/frontend/src/hooks/use-web3-provider.tsx | 6 ++++-- .../src/pages/worker/profile/wallet-connect-done.tsx | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/apps/human-app/frontend/src/components/data-entry/input.tsx b/packages/apps/human-app/frontend/src/components/data-entry/input.tsx index 51094fe7c2..cac35a5093 100644 --- a/packages/apps/human-app/frontend/src/components/data-entry/input.tsx +++ b/packages/apps/human-app/frontend/src/components/data-entry/input.tsx @@ -57,8 +57,8 @@ export function Input({ sx={{ input: { '&:-webkit-autofill': { - '-webkit-box-shadow': `0 0 0 30px transparent inset !important`, - '-webkit-text-fill-color': `${colorPalette.text.primary} !important`, + WebkitBoxShadow: `0 0 0 30px transparent inset !important`, + WebkitTextFillColor: `${colorPalette.text.primary} !important`, transition: 'background-color 5000s ease-in-out 0s, color 5000s ease-in-out 0s', }, diff --git a/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx b/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx index 3f4dc7bba9..2a2c191f89 100644 --- a/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx +++ b/packages/apps/human-app/frontend/src/hooks/use-web3-provider.tsx @@ -19,14 +19,16 @@ const getSignerAndProvider = async (walletProvider: Eip1193Provider) => { export function useWeb3Provider() { const { chainId } = useAppKitNetwork(); - const { walletProvider } = useAppKitProvider('eip155'); + const { walletProvider } = useAppKitProvider( + 'eip155' + ); const useSignerAndProviderMutation = useMutation({ mutationFn: getSignerAndProvider, }); useEffect(() => { - useSignerAndProviderMutation.mutate(walletProvider); + if (walletProvider) useSignerAndProviderMutation.mutate(walletProvider); // eslint-disable-next-line react-hooks/exhaustive-deps -- not nesseccary }, [walletProvider, chainId]); diff --git a/packages/apps/human-app/frontend/src/pages/worker/profile/wallet-connect-done.tsx b/packages/apps/human-app/frontend/src/pages/worker/profile/wallet-connect-done.tsx index 65f21c6cba..fe98e38c58 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/profile/wallet-connect-done.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/profile/wallet-connect-done.tsx @@ -16,13 +16,13 @@ import { const CustomTextField = styled(TextField)(() => ({ '& .Mui-disabled': { color: colorPalette.text.disabledSecondary, - '-webkit-text-fill-color': colorPalette.text.disabledSecondary, + WebkitTextFillColor: colorPalette.text.disabledSecondary, }, })); const CustomTextFieldDark = styled(TextField)(() => ({ '& .Mui-disabled': { color: darkColorPalette.text.disabledSecondary, - '-webkit-text-fill-color': darkColorPalette.text.disabledSecondary, + WebkitTextFillColor: darkColorPalette.text.disabledSecondary, }, '& .MuiOutlinedInput-root': { '& fieldset': { From b29d498cae03941b20f8197c108c951e90f8bb47 Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:57:11 +0300 Subject: [PATCH 31/92] [Fortune Exchange Oracle] Implemented rewardToken (#2869) * Implemented rewardToken * Updated create assignment method * Removed token * Removed lower case --- .../1733127731356-AddRewardTokenToJobTable.ts | 30 +++++++++++++++++++ .../assignment/assignment.controller.spec.ts | 4 +-- .../assignment/assignment.controller.ts | 1 + .../src/modules/assignment/assignment.dto.ts | 3 ++ .../assignment/assignment.service.spec.ts | 4 +-- .../modules/assignment/assignment.service.ts | 3 +- .../server/src/modules/job/job.entity.ts | 3 ++ .../src/modules/job/job.service.spec.ts | 20 ++++++++++++- .../server/src/modules/job/job.service.ts | 14 +++++++-- 9 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts diff --git a/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts new file mode 100644 index 0000000000..119a4e39e2 --- /dev/null +++ b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts @@ -0,0 +1,30 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddRewardTokenToJobTable1733127731356 + implements MigrationInterface +{ + name = 'AddRewardTokenToJobTable1733127731356'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "hmt"."jobs" + ADD "reward_token" character varying NOT NULL DEFAULT 'HMT' + `); + + await queryRunner.query(` + UPDATE "hmt"."jobs" + SET "reward_token" = 'HMT' + `); + + await queryRunner.query(` + ALTER TABLE "hmt"."jobs" + ALTER COLUMN "reward_token" DROP DEFAULT + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "hmt"."jobs" DROP COLUMN "reward_token" + `); + } +} diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.spec.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.spec.ts index e0706a49dc..9f0caafdad 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.spec.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.spec.ts @@ -9,7 +9,7 @@ import { ResignDto, } from './assignment.dto'; import { AssignmentStatus, JobType } from '../../common/enums/job'; -import { MOCK_EXCHANGE_ORACLE } from '../../../test/constants'; +import { MOCK_ADDRESS, MOCK_EXCHANGE_ORACLE } from '../../../test/constants'; jest.mock('../../common/utils/signature'); @@ -78,7 +78,7 @@ describe('assignmentController', () => { }; jest .spyOn(assignmentService, 'createAssignment') - .mockResolvedValue({ id: 1 } as any); + .mockResolvedValue({ id: 1, workerAddress: MOCK_ADDRESS, job: { rewardToken: 'HMT' } } as any); await assignmentController.createAssignment(body, { user: { address: userAddress }, } as RequestWithUser); diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.ts index 4f72d67ec6..4e67bec4e9 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.controller.ts @@ -68,6 +68,7 @@ export class AssignmentController { escrowAddress: body.escrowAddress, chainId: body.chainId, workerAddress: assignment.workerAddress, + rewardToken: assignment.job.rewardToken }; return response; } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.dto.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.dto.ts index 64ad9b2bc5..509a13d96e 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.dto.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.dto.ts @@ -150,4 +150,7 @@ export class AssignJobResponseDto { @ApiProperty({ name: 'worker_address' }) workerAddress: string; + + @ApiProperty({ name: 'reward_token' }) + rewardToken: string; } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.spec.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.spec.ts index ab530ff178..051466ba82 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.spec.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.spec.ts @@ -6,7 +6,6 @@ import { MOCK_MANIFEST_URL, MOCK_PRIVATE_KEY, } from '../../../test/constants'; -import { TOKEN } from '../../common/constant'; import { AssignmentStatus, JobType } from '../../common/enums/job'; import { AssignmentRepository } from '../assignment/assignment.repository'; import { AssignmentService } from '../assignment/assignment.service'; @@ -321,6 +320,7 @@ describe('AssignmentService', () => { chainId: 1, escrowAddress, manifestUrl: MOCK_MANIFEST_URL, + rewardToken: 'HMT', }, status: AssignmentStatus.ACTIVE, createdAt: new Date(), @@ -370,7 +370,7 @@ describe('AssignmentService', () => { escrowAddress: escrowAddress, jobType: JobType.FORTUNE, status: AssignmentStatus.ACTIVE, - rewardToken: TOKEN, + rewardToken: 'HMT', rewardAmount: 20, url: expect.any(String), createdAt: expect.any(String), diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts index 2d4f95847f..922a5e8dcd 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts @@ -10,7 +10,6 @@ import { import { AssignmentEntity } from './assignment.entity'; import { AssignmentRepository } from './assignment.repository'; import { PageDto } from '../../common/pagination/pagination.dto'; -import { TOKEN } from '../../common/constant'; import { JobService } from '../job/job.service'; import { Escrow__factory } from '@human-protocol/core/typechain-types'; import { Web3Service } from '../web3/web3.service'; @@ -138,7 +137,7 @@ export class AssignmentService { JobType.FORTUNE, entity.status, entity.rewardAmount, - TOKEN, + entity.job.rewardToken, entity.createdAt.toISOString(), entity.expiresAt.toISOString(), entity.updatedAt.toISOString(), diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.entity.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.entity.ts index b3d9d89049..55e873148b 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.entity.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.entity.ts @@ -17,6 +17,9 @@ export class JobEntity extends BaseEntity { @Column({ type: 'varchar', nullable: true }) public manifestUrl: string; + @Column({ type: 'varchar' }) + public rewardToken: string; + @Column({ type: 'enum', enum: JobStatus, diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts index 2f6425233c..558f6d9152 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts @@ -9,7 +9,11 @@ import { HttpService } from '@nestjs/axios'; import { ConfigService } from '@nestjs/config'; import { Test } from '@nestjs/testing'; import { of } from 'rxjs'; -import { MOCK_MANIFEST_URL, mockConfig } from '../../../test/constants'; +import { + MOCK_ADDRESS, + MOCK_MANIFEST_URL, + mockConfig, +} from '../../../test/constants'; import { AssignmentStatus, JobFieldName, @@ -31,6 +35,7 @@ import { PGPConfigService } from '../../common/config/pgp-config.service'; import { S3ConfigService } from '../../common/config/s3-config.service'; import { ErrorJob, ErrorAssignment } from '../../common/constant/errors'; import { BadRequestException, NotFoundException } from '@nestjs/common'; +import { HMToken__factory } from '@human-protocol/core/typechain-types'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), @@ -146,7 +151,19 @@ describe('JobService', () => { getReputationOracleAddress: jest .fn() .mockResolvedValue(reputationNetwork), + getTokenAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), })); + + const mockTokenContract: any = { + symbol: jest.fn(), + interface: { + parseLog: jest.fn().mockReturnValue({ args: { _to: MOCK_ADDRESS } }), + }, + }; + jest + .spyOn(HMToken__factory, 'connect') + .mockReturnValue(mockTokenContract); + jest.spyOn(mockTokenContract, 'symbol').mockReturnValue('HMT'); }); const webhook: WebhookDto = { chainId, @@ -166,6 +183,7 @@ describe('JobService', () => { escrowAddress: escrowAddress, manifestUrl: MOCK_MANIFEST_URL, reputationNetwork: reputationNetwork, + rewardToken: 'HMT', status: JobStatus.ACTIVE, }); }); diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts index 464cc45fab..2d77b9abcf 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts @@ -5,6 +5,10 @@ import { EscrowClient, StorageClient, } from '@human-protocol/sdk'; +import { + HMToken, + HMToken__factory, +} from '@human-protocol/core/typechain-types'; import { BadRequestException, Inject, @@ -12,7 +16,6 @@ import { Logger, NotFoundException, } from '@nestjs/common'; -import { TOKEN } from '../../common/constant'; import { AssignmentStatus, JobFieldName, @@ -69,10 +72,17 @@ export class JobService { const reputationOracleAddress = await escrowClient.getReputationOracleAddress(escrowAddress); + const tokenAddress = await escrowClient.getTokenAddress(escrowAddress); + const tokenContract: HMToken = HMToken__factory.connect( + tokenAddress, + signer, + ); + const newJobEntity = new JobEntity(); newJobEntity.escrowAddress = escrowAddress; newJobEntity.manifestUrl = await escrowClient.getManifestUrl(escrowAddress); newJobEntity.chainId = chainId; + newJobEntity.rewardToken = await tokenContract.symbol(); newJobEntity.status = JobStatus.ACTIVE; newJobEntity.reputationNetwork = reputationOracleAddress; await this.jobRepository.createUnique(newJobEntity); @@ -180,7 +190,7 @@ export class JobService { ).toString(); } if (data.fields?.includes(JobFieldName.RewardToken)) { - job.rewardToken = TOKEN; + job.rewardToken = entity.rewardToken; } if (data.fields?.includes(JobFieldName.Qualifications)) { job.qualifications = manifest.qualifications; From 1050b627978301a4f0948f9c8220cd8b96eeed1e Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Mon, 2 Dec 2024 13:46:09 +0100 Subject: [PATCH 32/92] [Subgraph] Events indexing issue (#2870) * fix events indexing issue and redeploy contracts and subgraph * fix core tests --- packages/core/.openzeppelin/bsc-testnet.json | 149 ++++++++++++++++++ packages/core/.openzeppelin/sepolia.json | 149 ++++++++++++++++++ .../core/.openzeppelin/unknown-80002.json | 149 ++++++++++++++++++ packages/core/contracts/EscrowFactory.sol | 8 +- .../core/contracts/test/EscrowFactoryV0.sol | 8 +- .../human_protocol_sdk/constants.py | 6 +- .../human-protocol-sdk/src/constants.ts | 6 +- .../sdk/typescript/subgraph/template.yaml | 4 +- 8 files changed, 459 insertions(+), 20 deletions(-) diff --git a/packages/core/.openzeppelin/bsc-testnet.json b/packages/core/.openzeppelin/bsc-testnet.json index be8b08c927..dd0690a620 100644 --- a/packages/core/.openzeppelin/bsc-testnet.json +++ b/packages/core/.openzeppelin/bsc-testnet.json @@ -1560,6 +1560,155 @@ }, "namespaces": {} } + }, + "d8e7c667c3c32b70d946e17a08d17aae9f2e8940b3ea8209c7275e6769c902a9": { + "address": "0x85dEc6b23fAa98bd1a75ef915076680bbeafD962", + "txHash": "0xd1a1840de66a71180b4303d5a31b2c7deee8f3926e2c0841ce7322285f810c18", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:121" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/sepolia.json b/packages/core/.openzeppelin/sepolia.json index 2e8bece9a3..b91768abe2 100644 --- a/packages/core/.openzeppelin/sepolia.json +++ b/packages/core/.openzeppelin/sepolia.json @@ -727,6 +727,155 @@ }, "namespaces": {} } + }, + "d8e7c667c3c32b70d946e17a08d17aae9f2e8940b3ea8209c7275e6769c902a9": { + "address": "0x5B4Ec73BAB648c68cabbFB3CA1644EeD8FdC7652", + "txHash": "0x4d29f74b779d0d2c239b8af412babe422cff4cc4f31667717dde443ed1490575", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:121" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/unknown-80002.json b/packages/core/.openzeppelin/unknown-80002.json index 03fae86cfc..77c67dfd9e 100644 --- a/packages/core/.openzeppelin/unknown-80002.json +++ b/packages/core/.openzeppelin/unknown-80002.json @@ -727,6 +727,155 @@ }, "namespaces": {} } + }, + "d8e7c667c3c32b70d946e17a08d17aae9f2e8940b3ea8209c7275e6769c902a9": { + "address": "0x3C14F4900F5f59F29f8B684394A2748a71531dd7", + "txHash": "0xb019793912df50978e1ebe31b943320312d5a53399be8bfb7c8806f059021723", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:121" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/contracts/EscrowFactory.sol b/packages/core/contracts/EscrowFactory.sol index 2b0bf87fd4..47c87d82e4 100644 --- a/packages/core/contracts/EscrowFactory.sol +++ b/packages/core/contracts/EscrowFactory.sol @@ -19,12 +19,8 @@ contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable { address public staking; uint256 public minimumStake; - event Launched(address indexed token, address indexed escrow); - event LaunchedV2( - address indexed token, - address indexed escrow, - string jobRequesterId - ); + event Launched(address token, address escrow); + event LaunchedV2(address token, address escrow, string jobRequesterId); event SetStakingAddress(address indexed stakingAddress); event SetMinumumStake(uint256 indexed minimumStake); diff --git a/packages/core/contracts/test/EscrowFactoryV0.sol b/packages/core/contracts/test/EscrowFactoryV0.sol index af421729d4..08f87b486c 100644 --- a/packages/core/contracts/test/EscrowFactoryV0.sol +++ b/packages/core/contracts/test/EscrowFactoryV0.sol @@ -19,12 +19,8 @@ contract EscrowFactoryV0 is OwnableUpgradeable, UUPSUpgradeable { address public staking; uint256 public minimumStake; - event Launched(address indexed token, address indexed escrow); - event LaunchedV2( - address indexed token, - address indexed escrow, - string jobRequesterId - ); + event Launched(address token, address escrow); + event LaunchedV2(address token, address escrow, string jobRequesterId); event SetStakingAddress(address indexed stakingAddress); event SetMinumumStake(uint256 indexed minimumStake); diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py index 51cf738311..65d1b89416 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py @@ -72,7 +72,7 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/sepolia/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmYycE8kMaMcKmGizepi8pcFkRfyRmqBt2qwiNbkd6oCQt" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmXVFVCLm2XxupxdKgnLRzvmkPJnpRbcoe4RNXoTqSRHsg" ), "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", "factory_address": "0x5987A5558d961ee674efe4A8c8eB7B1b5495D3bf", @@ -104,7 +104,7 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/bsc-testnet/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmZ5fFGPrDSQBfvZHAVQbkaPAgymcCmbhTVk7iuqHXY72P" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmW6JqXvhDnhRVHU6ixKVSD65U1GKWUf3xwJo8E6mTBsAu" ), "hmt_address": "0xE3D74BBFa45B4bCa69FF28891fBE392f4B4d4e4d", "factory_address": "0x2bfA592DBDaF434DDcbb893B1916120d181DAD18", @@ -156,7 +156,7 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/amoy/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmTZ33SRoH4o4HE9JMrH9kPTYS11z3T1N7evePrNZrEvBh" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmawobiPUYsGNK9chtb5PvicUtaa8Jsjpwvv8dNyMVXQ9r" ), "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", "factory_address": "0xAFf5a986A530ff839d49325A5dF69F96627E8D29", diff --git a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts index 753b30774f..036f091fb2 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts @@ -81,7 +81,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/sepolia/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmYycE8kMaMcKmGizepi8pcFkRfyRmqBt2qwiNbkd6oCQt', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmXVFVCLm2XxupxdKgnLRzvmkPJnpRbcoe4RNXoTqSRHsg', oldSubgraphUrl: '', oldFactoryAddress: '', }, @@ -111,7 +111,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/bsc-testnet/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmZ5fFGPrDSQBfvZHAVQbkaPAgymcCmbhTVk7iuqHXY72P', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmW6JqXvhDnhRVHU6ixKVSD65U1GKWUf3xwJo8E6mTBsAu', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/bsctest', oldFactoryAddress: '0xaae6a2646c1f88763e62e0cd08ad050ea66ac46f', @@ -158,7 +158,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/amoy/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmTZ33SRoH4o4HE9JMrH9kPTYS11z3T1N7evePrNZrEvBh', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmawobiPUYsGNK9chtb5PvicUtaa8Jsjpwvv8dNyMVXQ9r', oldSubgraphUrl: '', oldFactoryAddress: '', }, diff --git a/packages/sdk/typescript/subgraph/template.yaml b/packages/sdk/typescript/subgraph/template.yaml index 5b38f4ebe6..dc871ade09 100644 --- a/packages/sdk/typescript/subgraph/template.yaml +++ b/packages/sdk/typescript/subgraph/template.yaml @@ -21,9 +21,9 @@ dataSources: - name: EscrowFactory file: '{{{ EscrowFactory.abi }}}' eventHandlers: - - event: Launched(indexed address,indexed address) + - event: Launched(address,address) handler: handleLaunched - - event: LaunchedV2(indexed address,indexed address,string) + - event: LaunchedV2(address,address,string) handler: handleLaunchedV2 - kind: ethereum name: HMToken From 16d740b7cf561708bc0f5972c4c0d44756a53c40 Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Mon, 2 Dec 2024 15:38:56 +0100 Subject: [PATCH 33/92] [Dashboard] feat: add close button for menu drawer (#2866) --- .../apps/dashboard/ui-2024/src/components/Header/Header.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx index 65258762ea..787ba4bedf 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx @@ -13,6 +13,7 @@ import { useNavigate } from 'react-router-dom'; import { LogoBlockIcon } from '@components/Icons/LogoBlockIcon'; import { LogoBlockIconMobile } from '@components/Icons/LogoBlockIconMobile'; import TopSearchBar from '@components/Search/TopBarSearch'; +import CloseIcon from '@mui/icons-material/Close'; const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { const navigate = useNavigate(); @@ -115,6 +116,10 @@ const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { }} > + + toggleDrawer(false)} /> + +
Date: Wed, 4 Dec 2024 11:08:00 +0300 Subject: [PATCH 34/92] fix: change yarn workspaces pattern (#2858) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9abab48991..dd77f647da 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "workspaces": { "packages": [ - "packages/**/*" + "packages/**/!(dist)" ] }, "devDependencies": { From ab22ac019e57fa9bad8633de06f941a42d8e3629 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:09:04 +0100 Subject: [PATCH 35/92] chore(deps): bump pg from 8.12.0 to 8.13.1 (#2873) Bumps [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) from 8.12.0 to 8.13.1. - [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md) - [Commits](https://github.com/brianc/node-postgres/commits/pg@8.13.1/packages/pg) --- updated-dependencies: - dependency-name: pg dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../exchange-oracle/server/package.json | 2 +- .../apps/job-launcher/server/package.json | 2 +- .../reputation-oracle/server/package.json | 2 +- yarn.lock | 58 +++++++++++-------- 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index 0f1015a155..e9e7ba7963 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -53,7 +53,7 @@ "eslint-plugin-prettier": "^5.2.1", "jest": "29.7.0", "prettier": "^3.2.5", - "pg": "8.13.0", + "pg": "8.13.1", "source-map-support": "^0.5.20", "supertest": "^7.0.0", "ts-jest": "29.2.2", diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index 3d5befccd7..f0b4a765b5 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -52,7 +52,7 @@ "nestjs-minio-client": "^2.2.0", "passport": "^0.7.0", "passport-jwt": "^4.0.1", - "pg": "8.12.0", + "pg": "8.13.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.2.0", "stripe": "^17.4.0", diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 43f6b80bc6..0d0fdffd8a 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -51,7 +51,7 @@ "nestjs-minio-client": "^2.2.0", "passport": "^0.7.0", "passport-jwt": "^4.0.1", - "pg": "8.12.0", + "pg": "8.13.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.2.0", "typeorm": "^0.3.16", diff --git a/yarn.lock b/yarn.lock index d35095c2ac..007aed8fe1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16485,7 +16485,7 @@ pg-cloudflare@^1.1.1: resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== -pg-connection-string@^2.6.4, pg-connection-string@^2.7.0: +pg-connection-string@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.7.0.tgz#f1d3489e427c62ece022dba98d5262efcb168b37" integrity sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA== @@ -16500,12 +16500,12 @@ pg-numeric@1.0.2: resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a" integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== -pg-pool@^3.6.2, pg-pool@^3.7.0: +pg-pool@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.7.0.tgz#d4d3c7ad640f8c6a2245adc369bafde4ebb8cbec" integrity sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g== -pg-protocol@*, pg-protocol@^1.6.1, pg-protocol@^1.7.0: +pg-protocol@*, pg-protocol@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.7.0.tgz#ec037c87c20515372692edac8b63cf4405448a93" integrity sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ== @@ -16534,23 +16534,10 @@ pg-types@^4.0.1: postgres-interval "^3.0.0" postgres-range "^1.1.1" -pg@8.12.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.12.0.tgz#9341724db571022490b657908f65aee8db91df79" - integrity sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ== - dependencies: - pg-connection-string "^2.6.4" - pg-pool "^3.6.2" - pg-protocol "^1.6.1" - pg-types "^2.1.0" - pgpass "1.x" - optionalDependencies: - pg-cloudflare "^1.1.1" - -pg@8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.13.0.tgz#e3d245342eb0158112553fcc1890a60720ae2a3d" - integrity sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw== +pg@8.13.1: + version "8.13.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.13.1.tgz#6498d8b0a87ff76c2df7a32160309d3168c0c080" + integrity sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ== dependencies: pg-connection-string "^2.7.0" pg-pool "^3.7.0" @@ -18649,7 +18636,16 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18766,7 +18762,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18780,6 +18776,13 @@ strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -20974,7 +20977,7 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20992,6 +20995,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 6587304788e860c9727bfe431cccd7f66e8173e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:09:25 +0100 Subject: [PATCH 36/92] chore(deps): bump secp256k1 from 4.0.4 to 5.0.1 (#2872) Bumps [secp256k1](https://github.com/cryptocoinjs/secp256k1-node) from 4.0.4 to 5.0.1. - [Release notes](https://github.com/cryptocoinjs/secp256k1-node/releases) - [Commits](https://github.com/cryptocoinjs/secp256k1-node/compare/v4.0.4...v5.0.1) --- updated-dependencies: - dependency-name: secp256k1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../sdk/typescript/human-protocol-sdk/package.json | 2 +- yarn.lock | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/sdk/typescript/human-protocol-sdk/package.json b/packages/sdk/typescript/human-protocol-sdk/package.json index 96fa91425d..f2771bf517 100644 --- a/packages/sdk/typescript/human-protocol-sdk/package.json +++ b/packages/sdk/typescript/human-protocol-sdk/package.json @@ -46,7 +46,7 @@ "graphql-tag": "^2.12.6", "minio": "7.1.3", "openpgp": "^5.11.2", - "secp256k1": "^4.0.3", + "secp256k1": "^5.0.1", "vitest": "^1.6.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 007aed8fe1..9417b1de22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17975,7 +17975,7 @@ scss-tokenizer@^0.4.3: js-base64 "^2.4.9" source-map "^0.7.3" -secp256k1@^4.0.1, secp256k1@^4.0.3: +secp256k1@^4.0.1: version "4.0.4" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.4.tgz#58f0bfe1830fe777d9ca1ffc7574962a8189f8ab" integrity sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw== @@ -17984,6 +17984,15 @@ secp256k1@^4.0.1, secp256k1@^4.0.3: node-addon-api "^5.0.0" node-gyp-build "^4.2.0" +secp256k1@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.1.tgz#dc2c86187d48ff2da756f0f7e96417ee03c414b1" + integrity sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA== + dependencies: + elliptic "^6.5.7" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + "semver@2 || 3 || 4 || 5", semver@7.3.5, semver@7.4.0, semver@^5.5.0, semver@^6.0.0, semver@^6.3.0, semver@^6.3.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" From 80b786377cfa828e59aa34cbf1deccabc56a5fc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:09:46 +0100 Subject: [PATCH 37/92] chore(deps): bump @stripe/react-stripe-js from 2.9.0 to 3.0.0 (#2871) Bumps [@stripe/react-stripe-js](https://github.com/stripe/react-stripe-js) from 2.9.0 to 3.0.0. - [Release notes](https://github.com/stripe/react-stripe-js/releases) - [Changelog](https://github.com/stripe/react-stripe-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/stripe/react-stripe-js/compare/v2.9.0...v3.0.0) --- updated-dependencies: - dependency-name: "@stripe/react-stripe-js" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/job-launcher/client/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 57cbf1a6fb..83e032bb9e 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -12,7 +12,7 @@ "@mui/material": "^5.16.7", "@mui/x-date-pickers": "^7.5.0", "@reduxjs/toolkit": "^2.2.7", - "@stripe/react-stripe-js": "^2.4.0", + "@stripe/react-stripe-js": "^3.0.0", "@stripe/stripe-js": "^4.2.0", "@tanstack/query-sync-storage-persister": "^5.59.0", "@tanstack/react-query": "^5.60.5", diff --git a/yarn.lock b/yarn.lock index 9417b1de22..8e8a6a94f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4976,10 +4976,10 @@ "@stablelib/random" "^1.0.2" "@stablelib/wipe" "^1.0.1" -"@stripe/react-stripe-js@^2.4.0": - version "2.9.0" - resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-2.9.0.tgz#1f1a9a3d5eab8ca144e060df1e9fd855a7658aca" - integrity sha512-+/j2g6qKAKuWSurhgRMfdlIdKM+nVVJCy/wl0US2Ccodlqx0WqfIIBhUkeONkCG+V/b+bZzcj4QVa3E/rXtT4Q== +"@stripe/react-stripe-js@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-3.0.0.tgz#8970af4283478662a277870ddb1ea173de635ba8" + integrity sha512-Crn9t+uvfEJnFSEE8Le9Boj3+J4QdB7DrIa+VyhDgTAHC1z9fk7d/cfSrjNO2RcdRh9zN9Blk/XKccHq9kUlTw== dependencies: prop-types "^15.7.2" From 28db5f8664b7f9d76a2eebbd042ee935bb06a823 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:39:50 +0100 Subject: [PATCH 38/92] chore(deps-dev): bump @types/express from 4.17.21 to 5.0.0 (#2809) Bumps [@types/express](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/express) from 4.17.21 to 5.0.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/express) --- updated-dependencies: - dependency-name: "@types/express" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/dashboard/server/package.json | 2 +- packages/apps/faucet/server/package.json | 2 +- .../exchange-oracle/server/package.json | 2 +- .../fortune/recording-oracle/package.json | 2 +- packages/apps/human-app/server/package.json | 2 +- .../apps/job-launcher/server/package.json | 2 +- .../reputation-oracle/server/package.json | 2 +- yarn.lock | 22 +------------------ 8 files changed, 8 insertions(+), 28 deletions(-) diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 8d0b68e7e1..3b9f48d28c 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -38,7 +38,7 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^4.17.13", + "@types/express": "^5.0.0", "@types/jest": "29.5.1", "@types/node": "22.5.4", "@types/supertest": "^2.0.11", diff --git a/packages/apps/faucet/server/package.json b/packages/apps/faucet/server/package.json index 75eaab6455..c29c4aa853 100644 --- a/packages/apps/faucet/server/package.json +++ b/packages/apps/faucet/server/package.json @@ -24,6 +24,6 @@ }, "devDependencies": { "@types/cors": "^2.8.17", - "@types/express": "^4.17.14" + "@types/express": "^5.0.0" } } diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index e9e7ba7963..4b31241448 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -41,7 +41,7 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^4.17.13", + "@types/express": "^5.0.0", "@types/jest": "29.5.12", "@types/pg": "8.11.10", "@types/node": "22.5.4", diff --git a/packages/apps/fortune/recording-oracle/package.json b/packages/apps/fortune/recording-oracle/package.json index 6e0f294dfe..5c8fed84c3 100644 --- a/packages/apps/fortune/recording-oracle/package.json +++ b/packages/apps/fortune/recording-oracle/package.json @@ -39,6 +39,6 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^4.17.13" + "@types/express": "^5.0.0" } } diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index c786dab218..ea61a6d1e0 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -45,7 +45,7 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^4.17.13", + "@types/express": "^5.0.0", "@types/jest": "29.5.12", "@types/node": "22.5.4", "@types/supertest": "^2.0.15", diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index f0b4a765b5..368eca3530 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -66,7 +66,7 @@ "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", "@types/bcrypt": "^5.0.2", - "@types/express": "^4.17.13", + "@types/express": "^5.0.0", "@types/jest": "29.5.12", "@types/json-stable-stringify": "^1.0.36", "@types/node": "22.5.4", diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 0d0fdffd8a..0adbe3ad6e 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -64,7 +64,7 @@ "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", "@types/bcrypt": "^5.0.2", - "@types/express": "^4.17.13", + "@types/express": "^5.0.0", "@types/jest": "29.5.12", "@types/node": "22.5.4", "@types/supertest": "^6.0.2", diff --git a/yarn.lock b/yarn.lock index 8e8a6a94f0..8497673d06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5516,16 +5516,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== -"@types/express-serve-static-core@^4.17.33": - version "4.19.6" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" - integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - "@types/express-serve-static-core@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz#812d2871e5eea17fb0bd5214dda7a7b748c0e12a" @@ -5536,7 +5526,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@*": +"@types/express@*", "@types/express@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c" integrity sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ== @@ -5546,16 +5536,6 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/express@^4.17.13", "@types/express@^4.17.14": - version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.33" - "@types/qs" "*" - "@types/serve-static" "*" - "@types/file-saver@^2.0.7": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.7.tgz#8dbb2f24bdc7486c54aa854eb414940bbd056f7d" From e407b2a2b2111509f3fef578d4f3bb02a841da4f Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:02:20 +0100 Subject: [PATCH 39/92] Revert "chore(deps-dev): bump @types/express from 4.17.21 to 5.0.0 (#2809)" (#2878) This reverts commit 28db5f8664b7f9d76a2eebbd042ee935bb06a823. --- packages/apps/dashboard/server/package.json | 2 +- packages/apps/faucet/server/package.json | 2 +- .../exchange-oracle/server/package.json | 2 +- .../fortune/recording-oracle/package.json | 2 +- packages/apps/human-app/server/package.json | 2 +- .../apps/job-launcher/server/package.json | 2 +- .../reputation-oracle/server/package.json | 2 +- yarn.lock | 22 ++++++++++++++++++- 8 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 3b9f48d28c..8d0b68e7e1 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -38,7 +38,7 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^5.0.0", + "@types/express": "^4.17.13", "@types/jest": "29.5.1", "@types/node": "22.5.4", "@types/supertest": "^2.0.11", diff --git a/packages/apps/faucet/server/package.json b/packages/apps/faucet/server/package.json index c29c4aa853..75eaab6455 100644 --- a/packages/apps/faucet/server/package.json +++ b/packages/apps/faucet/server/package.json @@ -24,6 +24,6 @@ }, "devDependencies": { "@types/cors": "^2.8.17", - "@types/express": "^5.0.0" + "@types/express": "^4.17.14" } } diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index 4b31241448..e9e7ba7963 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -41,7 +41,7 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^5.0.0", + "@types/express": "^4.17.13", "@types/jest": "29.5.12", "@types/pg": "8.11.10", "@types/node": "22.5.4", diff --git a/packages/apps/fortune/recording-oracle/package.json b/packages/apps/fortune/recording-oracle/package.json index 5c8fed84c3..6e0f294dfe 100644 --- a/packages/apps/fortune/recording-oracle/package.json +++ b/packages/apps/fortune/recording-oracle/package.json @@ -39,6 +39,6 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^5.0.0" + "@types/express": "^4.17.13" } } diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index ea61a6d1e0..c786dab218 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -45,7 +45,7 @@ "@nestjs/cli": "^10.3.2", "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", - "@types/express": "^5.0.0", + "@types/express": "^4.17.13", "@types/jest": "29.5.12", "@types/node": "22.5.4", "@types/supertest": "^2.0.15", diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index 368eca3530..f0b4a765b5 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -66,7 +66,7 @@ "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", "@types/bcrypt": "^5.0.2", - "@types/express": "^5.0.0", + "@types/express": "^4.17.13", "@types/jest": "29.5.12", "@types/json-stable-stringify": "^1.0.36", "@types/node": "22.5.4", diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 0adbe3ad6e..0d0fdffd8a 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -64,7 +64,7 @@ "@nestjs/schematics": "^10.1.3", "@nestjs/testing": "^10.4.6", "@types/bcrypt": "^5.0.2", - "@types/express": "^5.0.0", + "@types/express": "^4.17.13", "@types/jest": "29.5.12", "@types/node": "22.5.4", "@types/supertest": "^6.0.2", diff --git a/yarn.lock b/yarn.lock index 8497673d06..8e8a6a94f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5516,6 +5516,16 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== +"@types/express-serve-static-core@^4.17.33": + version "4.19.6" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" + integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + "@types/express-serve-static-core@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz#812d2871e5eea17fb0bd5214dda7a7b748c0e12a" @@ -5526,7 +5536,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@*", "@types/express@^5.0.0": +"@types/express@*": version "5.0.0" resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c" integrity sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ== @@ -5536,6 +5546,16 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/express@^4.17.13", "@types/express@^4.17.14": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/file-saver@^2.0.7": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.7.tgz#8dbb2f24bdc7486c54aa854eb414940bbd056f7d" From e4053d123b90ff080ab2784a728249f5dd387b96 Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:36:12 +0300 Subject: [PATCH 40/92] [Dashboard Server] Fixed roles values (#2881) * Fixed roles values * Removed console log --- packages/apps/dashboard/server/src/common/enums/roles.ts | 6 ++++++ .../server/src/modules/details/details.service.ts | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 packages/apps/dashboard/server/src/common/enums/roles.ts diff --git a/packages/apps/dashboard/server/src/common/enums/roles.ts b/packages/apps/dashboard/server/src/common/enums/roles.ts new file mode 100644 index 0000000000..5b35824c36 --- /dev/null +++ b/packages/apps/dashboard/server/src/common/enums/roles.ts @@ -0,0 +1,6 @@ +export enum OracleRole { + JOB_LAUNCHER = 'job_launcher', + EXCHANGE_ORACLE = 'exchange_oracle', + RECORDING_ORACLE = 'recording_oracle', + REPUTATION_ORACLE = 'reputation_oracle', +} diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index 088230342a..22c1b82469 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -20,6 +20,7 @@ import { firstValueFrom } from 'rxjs'; import { HMToken__factory } from '@human-protocol/core/typechain-types'; import { ethers } from 'ethers'; import { NetworkConfigService } from '../../common/config/network-config.service'; +import { OracleRole } from '../../common/enums/roles'; @Injectable() export class DetailsService { @@ -243,10 +244,10 @@ export class DetailsService { params: { chain_id: ChainId.POLYGON, roles: [ - 'JOB_LAUNCHER', - 'EXCHANGE_ORACLE', - 'RECORDING_ORACLE', - 'REPUTATION_ORACLE', + OracleRole.JOB_LAUNCHER, + OracleRole.EXCHANGE_ORACLE, + OracleRole.RECORDING_ORACLE, + OracleRole.REPUTATION_ORACLE, ], }, }, From 0142f29107368571ec5b9c78af98563c62f4087b Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Thu, 5 Dec 2024 12:33:58 +0100 Subject: [PATCH 41/92] [Dashboard] fix: address search component hover/active state fix (#2868) --- .../ui-2024/src/assets/styles/_header.scss | 12 +- .../src/assets/styles/_page-wrapper.scss | 4 +- .../ui-2024/src/assets/styles/_search.scss | 6 +- .../ui-2024/src/components/Header/Header.tsx | 7 +- .../ui-2024/src/components/Loader/index.tsx | 9 +- .../ui-2024/src/components/Search/Search.tsx | 258 ------------------ .../src/components/Search/TopBarSearch.tsx | 248 ----------------- .../ui-2024/src/components/Search/index.ts | 1 - .../components/SearchBar/SearchBar.styles.ts | 88 ++++++ .../src/components/SearchBar/SearchBar.tsx | 206 ++++++++++++++ .../Leaderboard/components/SelectNetwork.tsx | 11 +- .../dashboard/ui-2024/src/pages/Home/Home.tsx | 4 +- .../src/pages/SearchResults/SearchResults.tsx | 8 +- packages/apps/dashboard/ui-2024/src/theme.tsx | 11 +- 14 files changed, 343 insertions(+), 530 deletions(-) delete mode 100644 packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx delete mode 100644 packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx delete mode 100644 packages/apps/dashboard/ui-2024/src/components/Search/index.ts create mode 100644 packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts create mode 100644 packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss b/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss index 2e06e6d3ed..c5d9226ae8 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss @@ -32,7 +32,7 @@ } } - @media (max-width: 1100px) { + @media (max-width: 1280px) { height: 62px; .mobile-icon, .search-header-mobile { @@ -42,11 +42,19 @@ .search-header { display: none; } + + .logo-mobile { + margin-left: 24px; + } + + .mobile-icon { + margin-right: 16px; + } } } .header-toolbar-search { - @media (max-width: 1100px) { + @media (max-width: 1280px) { height: 118px; flex-wrap: wrap; } diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss b/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss index e74a61a18c..e61b976157 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss @@ -8,7 +8,7 @@ padding: 14px 0; height: 100vh; - @media (max-width: 1100px) { + @media (max-width: 1280px) { border-radius: 0; height: auto; } @@ -22,7 +22,7 @@ } } - @media (max-width: 1100px) { + @media (max-width: 1280px) { min-height: calc(100vh - 386px); margin: 0 24px; &.search-white-header { diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss b/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss index c9c14424fc..4ecd62206c 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss @@ -37,7 +37,7 @@ .search-results-bar { display: block; - @media (max-width: 1100px) { + @media (max-width: 1280px) { display: none; } } @@ -68,7 +68,7 @@ max-width: 20%; } - @media (max-width: 1100px) { + @media (max-width: 1280px) { max-width: 100%; #search-bar{ @@ -77,7 +77,7 @@ } } -@media (max-width: 1100px) { +@media (max-width: 1280px) { .search-white{ padding: 8px 0; diff --git a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx index 787ba4bedf..f0dc922aa5 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx @@ -7,12 +7,11 @@ import MenuIcon from '@mui/icons-material/Menu'; import Drawer from '@mui/material/Drawer'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; -import Search from '@components/Search'; +import SearchBar from '@components/SearchBar/SearchBar'; import { env } from '@helpers/env'; import { useNavigate } from 'react-router-dom'; import { LogoBlockIcon } from '@components/Icons/LogoBlockIcon'; import { LogoBlockIconMobile } from '@components/Icons/LogoBlockIconMobile'; -import TopSearchBar from '@components/Search/TopBarSearch'; import CloseIcon from '@mui/icons-material/Close'; const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { @@ -34,7 +33,7 @@ const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { })} > {displaySearchBar && ( - + )} { @@ -56,7 +55,7 @@ const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { {displaySearchBar && ( - + )}
diff --git a/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx b/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx index 86ecff1223..138a5965e9 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Loader/index.tsx @@ -1,13 +1,20 @@ import CircularProgress from '@mui/material/CircularProgress'; import Box from '@mui/material/Box'; -const Loader = ({ height = '100vh' }: { height?: string }) => { +const Loader = ({ + height = '100vh', + paddingTop = 'unset', +}: { + height?: string; + paddingTop?: string; +}) => { return ( diff --git a/packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx b/packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx deleted file mode 100644 index 4c740ce52f..0000000000 --- a/packages/apps/dashboard/ui-2024/src/components/Search/Search.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import clsx from 'clsx'; -import { useNavigate } from 'react-router-dom'; -import IconButton from '@mui/material/IconButton'; -import SearchIcon from '@mui/icons-material/Search'; -import CloseIcon from '@mui/icons-material/Close'; -import { - InputAdornment, - TextField, - MenuItem, - Select as MuiSelect, - SelectChangeEvent, - Grid, -} from '@mui/material'; -import { colorPalette } from '@assets/styles/color-palette'; -import { getNetwork, networks } from '@utils/config/networks'; -import { useWalletSearch } from '@utils/hooks/use-wallet-search'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; -import { NetworkIcon } from '@components/NetworkIcon'; - -const Search: FC<{ - className?: string; - displaySearchBar?: boolean; - borderColor?: string; -}> = ({ - className, - displaySearchBar, - borderColor = colorPalette.secondary.main, -}) => { - const { mobile } = useBreakPoints(); - const { filterParams, setAddress, setChainId } = useWalletSearch(); - const [inputValue, setInputValue] = useState(''); - const [selectValue, setSelectValue] = useState(''); - const [focus, setFocus] = useState(false); - const navigate = useNavigate(); - - const handleInputChange = (event: React.ChangeEvent) => { - setInputValue(event.target.value); - }; - - const handleSelectChange = (event: SelectChangeEvent) => { - const chainId = Number(event.target.value); - setChainId(chainId); - const networkName = getNetwork(chainId)?.name || ''; - setSelectValue(networkName); - }; - - const handleClearClick = () => { - setInputValue(''); - setAddress(''); - }; - - const handleInputBlur = () => { - setFocus(false); - }; - - const handleInputFocus = () => { - setFocus(true); - }; - - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - setAddress(inputValue); - navigate(`/search/${filterParams.chainId || -1}/${inputValue || '0x0'}`); - }; - - useEffect(() => { - const networkName = getNetwork(filterParams.chainId || -1)?.name || ''; - if (networkName) { - setSelectValue(networkName); - } - }, [filterParams.chainId]); - - useEffect(() => { - setInputValue(filterParams.address); - }, [filterParams.address]); - - return ( -
- - ( - - Network - - ) - : () => { - return ( - - -
- {mobile.isMobile - ? null - : getNetwork(filterParams.chainId)?.name} -
-
- ); - } - } - > - {networks.map((network) => ( - - - {network.name} - - - ))} -
- - ), - endAdornment: inputValue && ( - - - - - - - - - ), - }} - /> - - ); -}; - -export default Search; diff --git a/packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx b/packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx deleted file mode 100644 index 4185408e06..0000000000 --- a/packages/apps/dashboard/ui-2024/src/components/Search/TopBarSearch.tsx +++ /dev/null @@ -1,248 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import clsx from 'clsx'; -import { useNavigate } from 'react-router-dom'; -import IconButton from '@mui/material/IconButton'; -import SearchIcon from '@mui/icons-material/Search'; -import CloseIcon from '@mui/icons-material/Close'; -import { - InputAdornment, - TextField, - MenuItem, - Select as MuiSelect, - SelectChangeEvent, - Grid, -} from '@mui/material'; -import { colorPalette } from '@assets/styles/color-palette'; -import { getNetwork, networks } from '@utils/config/networks'; -import { useWalletSearch } from '@utils/hooks/use-wallet-search'; -import { useBreakPoints } from '@utils/hooks/use-is-mobile'; -import { NetworkIcon } from '@components/NetworkIcon'; - -const TopSearchBar: FC<{ className?: string; displaySearchBar?: boolean }> = ({ - className, - displaySearchBar, -}) => { - const { mobile } = useBreakPoints(); - const { filterParams, setAddress, setChainId } = useWalletSearch(); - const [inputValue, setInputValue] = useState(''); - const [selectValue, setSelectValue] = useState(''); - const [focus, setFocus] = useState(false); - const navigate = useNavigate(); - - const handleInputChange = (event: React.ChangeEvent) => { - setAddress(event.target.value); - }; - - const handleSelectChange = (event: SelectChangeEvent) => { - const chainId = Number(event.target.value); - setChainId(chainId); - const networkName = getNetwork(chainId)?.name || ''; - setSelectValue(networkName); - }; - - const handleClearClick = () => { - setInputValue(''); - setAddress(''); - }; - - const handleInputBlur = () => { - setFocus(false); - }; - - const handleInputFocus = () => { - setFocus(true); - }; - - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - navigate( - `/search/${filterParams.chainId || -1}/${filterParams.address || '0x0'}` - ); - }; - - useEffect(() => { - const networkName = getNetwork(filterParams.chainId || -1)?.name || ''; - if (networkName) { - setSelectValue(networkName); - } - }, [filterParams.chainId]); - - useEffect(() => { - setInputValue(filterParams.address); - }, [filterParams.address]); - - return ( -
- - ( - - Network - - ) - : () => { - return ( - - -
- {mobile.isMobile - ? null - : getNetwork(filterParams.chainId)?.name} -
-
- ); - } - } - > - {networks.map((network) => ( - - - {network.name} - - - ))} -
- - ), - endAdornment: inputValue && ( - - - - - - - - - ), - }} - /> - - ); -}; - -export default TopSearchBar; diff --git a/packages/apps/dashboard/ui-2024/src/components/Search/index.ts b/packages/apps/dashboard/ui-2024/src/components/Search/index.ts deleted file mode 100644 index 85bb434b22..0000000000 --- a/packages/apps/dashboard/ui-2024/src/components/Search/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Search'; diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts new file mode 100644 index 0000000000..52ec4fbf79 --- /dev/null +++ b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts @@ -0,0 +1,88 @@ +import { colorPalette } from '@assets/styles/color-palette'; + +export const endAdornmentInputAdornmentSx = { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + gap: '0.7rem', +}; + +export const startAdornmentInputAdornmentSx = { + height: '100%', + backgroundColor: `${colorPalette.white}`, + marginLeft: '1rem', +}; + +export const gridSx = { + display: 'flex', + justifyContent: 'flex-start', + alignItems: 'center', + gap: '8px', + textOverflow: 'ellipsis', + overflow: 'hidden', +}; + +export const muiSelectSx = ( + isTopBar: boolean, + mobile: { isMobile: boolean; mediaQuery: string } +) => ({ + backgroundColor: `${colorPalette.white}`, + width: isTopBar ? '220px' : 'unset', + fontSize: '16px', + boxShadow: 'none', + outline: 'none', + '& .MuiOutlinedInput-notchedOutline': { + border: 0, + outline: 'none', + }, + '& .MuiSelect-select': { + padding: 0, + paddingRight: '24px', + backgroundColor: `${colorPalette.white}`, + border: 0, + }, + [mobile.mediaQuery]: { + width: 'unset', + }, +}); + +export const menuItemSx = (isSelected: boolean) => ({ + display: 'flex', + gap: '10px', + backgroundColor: isSelected ? 'rgba(50, 10, 141, 0.08)' : 'inherit', +}); + +export const muiTextFieldInputPropsSx = (borderColor: string) => ({ + width: '100%', + height: '100%', + borderRadius: '10px', + border: `1px solid ${borderColor}`, + backgroundColor: `${colorPalette.white}`, + fontSize: 'inherit', + 'input::placeholder': { + color: `${colorPalette.sky.main}`, + opacity: 1, + }, + padding: '0 5px', +}); + +export const muiTextFieldSx = (mobile: { + isMobile: boolean; + mediaQuery: string; +}) => ({ + fontSize: '16px', + '& .MuiOutlinedInput-root': { + '& input': { + [mobile.mediaQuery]: { + padding: '12px 0px', + }, + }, + '& fieldset': { + border: 'none', + }, + }, + '& .MuiInputBase-input': { + overflow: 'hidden', + textOverflow: 'ellipsis', + }, +}); diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx new file mode 100644 index 0000000000..1f65a19bcd --- /dev/null +++ b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx @@ -0,0 +1,206 @@ +import { FC, useCallback, useEffect, useState } from 'react'; +import clsx from 'clsx'; +import { useNavigate } from 'react-router-dom'; +import IconButton from '@mui/material/IconButton'; +import SearchIcon from '@mui/icons-material/Search'; +import CloseIcon from '@mui/icons-material/Close'; +import { + InputAdornment, + TextField, + Select as MuiSelect, + SelectChangeEvent, + Grid, + MenuItem, + Box, +} from '@mui/material'; +import { colorPalette } from '@assets/styles/color-palette'; +import { getNetwork, networks } from '@utils/config/networks'; +import { useBreakPoints } from '@utils/hooks/use-is-mobile'; +import { NetworkIcon } from '@components/NetworkIcon'; +import { useWalletSearch } from '@utils/hooks/use-wallet-search'; +import { + endAdornmentInputAdornmentSx, + startAdornmentInputAdornmentSx, + muiSelectSx, + menuItemSx, + muiTextFieldInputPropsSx, + muiTextFieldSx, + gridSx, +} from './SearchBar.styles'; + +interface SearchBarProps { + className?: string; + displaySearchBar?: boolean; + isTopBar?: boolean; + initialInputValue?: string; +} + +const SearchBar: FC = ({ + className = '', + displaySearchBar, + initialInputValue = '', + isTopBar = false, +}) => { + const { mobile } = useBreakPoints(); + const [inputValue, setInputValue] = useState(initialInputValue); + const [selectValue, setSelectValue] = useState(null); + const [focus, setFocus] = useState(false); + const { filterParams, setAddress, setChainId } = useWalletSearch(); + const navigate = useNavigate(); + + const navigateToAddress = useCallback( + (chainIdParam?: number | undefined) => { + const chainId = chainIdParam || filterParams.chainId || -1; + const address = (isTopBar ? filterParams.address : inputValue) || ''; + navigate(`/search/${chainId}/${address}`); + }, + [filterParams.address, filterParams.chainId, inputValue, isTopBar, navigate] + ); + + useEffect(() => { + const networkName = getNetwork(filterParams.chainId || -1)?.name || ''; + if (networkName) { + setSelectValue(filterParams.chainId); + } + }, [filterParams.chainId, navigateToAddress]); + + useEffect(() => { + setInputValue(filterParams.address); + }, [filterParams.address]); + + const handleInputChange = (event: React.ChangeEvent) => { + if (isTopBar) { + setAddress(event.target.value); + } else { + setInputValue(event.target.value); + } + }; + + const handleSelectChange = (event: SelectChangeEvent) => { + const chainId = Number(event.target.value); + if (inputValue && !!inputValue.length) { + navigateToAddress(chainId); + } else { + setChainId(chainId); + } + }; + + const handleClearClick = () => { + setInputValue(''); + }; + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + if (!isTopBar) { + setAddress(inputValue); + } + if (inputValue && !!inputValue.length) { + navigateToAddress(); + } + }; + + const renderEmptyValue = ( + Network + ); + + const renderSelectedValue = ( + + n.id === selectValue)?.id || -1} + /> +
+ {mobile.isMobile || !selectValue + ? null + : getNetwork(selectValue)?.name || ''} +
+
+ ); + + return ( +
+ setFocus(true)} + onBlur={() => setFocus(false)} + fullWidth + sx={muiTextFieldSx(mobile)} + InputProps={{ + sx: muiTextFieldInputPropsSx( + focus ? colorPalette.secondary.main : colorPalette.skyOpacity + ), + startAdornment: ( + + + value={selectValue} + displayEmpty + sx={muiSelectSx(isTopBar, mobile)} + onChange={handleSelectChange} + renderValue={() => + selectValue === null ? renderEmptyValue : renderSelectedValue + } + > + {networks.map((network) => ( + + + + + {network.name} + + ))} + + + ), + endAdornment: inputValue && ( + + + + + + + + + ), + }} + /> + + ); +}; + +export default SearchBar; diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx index 55c70dfc99..02e6739ff2 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/SelectNetwork.tsx @@ -2,14 +2,14 @@ import Select, { SelectChangeEvent } from '@mui/material/Select'; import FormControl from '@mui/material/FormControl'; import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; +import Box from '@mui/material/Box'; import HumanIcon from '@components/Icons/HumanIcon'; import { leaderboardSearchSelectConfig, useLeaderboardSearch, } from '@utils/hooks/use-leaderboard-search'; -import { NetworkIcon } from '@components/NetworkIcon'; -import { Box } from '@mui/material'; import { useBreakPoints } from '@utils/hooks/use-is-mobile'; +import { NetworkIcon } from '@components/NetworkIcon'; export const SelectNetwork = () => { const { @@ -58,9 +58,12 @@ export const SelectNetwork = () => { return ( diff --git a/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx b/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx index 3203107681..8082578b9f 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Home/Home.tsx @@ -1,5 +1,5 @@ import PageWrapper from '@components/PageWrapper'; -import Search from '@components/Search'; +import SearchBar from '@components/SearchBar/SearchBar'; import ShadowIcon from '@components/ShadowIcon'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; @@ -30,7 +30,7 @@ const Home: React.FC = () => { > All HUMAN activity. In one place. - +
diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx index 9759f254ff..a094badbd8 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/SearchResults.tsx @@ -8,7 +8,7 @@ import EscrowAddress from '@pages/SearchResults/EscrowAddress'; import WalletAddress from '@pages/SearchResults/WalletAddress'; import NothingFound from '@components/NothingFound'; import Breadcrumbs from '@components/Breadcrumbs'; -import Search from '@components/Search'; +import SearchBar from '@components/SearchBar/SearchBar'; import { useWalletSearch } from '@utils/hooks/use-wallet-search'; import Loader from '@components/Loader'; import { getNetwork } from '@utils/config/networks'; @@ -77,7 +77,7 @@ const Results = () => { const { filterParams } = useWalletSearch(); if (status === 'pending' && !data) { - return ; + return ; } if (status === 'error') { @@ -161,8 +161,8 @@ const SearchResults = () => { return ( - - {paramsStatus === 'loading' && } + + {paramsStatus === 'loading' && } {paramsStatus === 'error' && ( Something went wrong )} diff --git a/packages/apps/dashboard/ui-2024/src/theme.tsx b/packages/apps/dashboard/ui-2024/src/theme.tsx index 4bd94edfad..be2039100f 100644 --- a/packages/apps/dashboard/ui-2024/src/theme.tsx +++ b/packages/apps/dashboard/ui-2024/src/theme.tsx @@ -212,7 +212,7 @@ const theme: ThemeOptions = createTheme({ MuiToolbar: { styleOverrides: { root: { - '@media (min-width:1001px)': { + '@media (min-width:1280px)': { paddingX: 56, }, }, @@ -272,6 +272,15 @@ const theme: ThemeOptions = createTheme({ }, }, }, + MuiMenuItem: { + styleOverrides: { + root: { + '&:hover': { + backgroundColor: '#1406B207', + }, + }, + }, + }, }, }); From f27e0ae0d1293459e3a288c2e3838b0aa4050427 Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Thu, 5 Dec 2024 14:03:18 +0100 Subject: [PATCH 42/92] [Dashboard] fix: double footer scroll (#2867) --- .../RoleDetailsEscrowsTable.tsx | 1 - packages/apps/dashboard/ui-2024/src/theme.tsx | 62 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx index fa1421228d..89d05a56f7 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/RoleDetailsEscrowsTable.tsx @@ -47,7 +47,6 @@ export const RoleDetailsEscrowsTable = ({ Date: Fri, 6 Dec 2024 15:28:36 +0100 Subject: [PATCH 43/92] [Dashboard] feat: use BE sort order by default (#2883) --- .../src/features/Leaderboard/components/DataGridWrapper.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/DataGridWrapper.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/DataGridWrapper.tsx index d070265168..53283c7ada 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/DataGridWrapper.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/DataGridWrapper.tsx @@ -51,11 +51,6 @@ export const DataGridWrapper = ({ expand: true, }} onSortModelChange={handleSortModelChange} - initialState={{ - sorting: { - sortModel: [{ field: 'amountStaked', sort: 'desc' }], - }, - }} slots={{ noRowsOverlay() { if (status === 'error') { From e939332abb5c6437ac3b095f4d41f317f9bbe613 Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Fri, 6 Dec 2024 15:53:04 +0100 Subject: [PATCH 44/92] [Dashboard] feat: update link colors for hover/visited states (#2880) --- .../ui-2024/src/assets/styles/color-palette.ts | 3 +++ .../SearchResults/AbbreviateClipboard.tsx | 9 ++++++++- .../tableComponents/EscrowsTableBody.tsx | 5 +++-- packages/apps/dashboard/ui-2024/src/theme.tsx | 13 +++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts b/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts index 523ee4d844..c84f434d04 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts @@ -3,6 +3,9 @@ export const colorPalette = { whiteBackground: '#FFF', whiteSolid: '#F6F5FC', skyOpacity: '#DADEF0CC', + link: '#0000EE', + linkHover: '#1406B2', + linkVisited: '#551A8B', primary: { main: '#320a8d', light: '#320a8d', diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx b/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx index 2a3bfa3acd..c7af5e42d5 100644 --- a/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx @@ -29,7 +29,14 @@ const AbbreviateClipboard = ({ value, link }: AbbreviateClipboardProps) => { }); }} > - + {abbreviateValue(value)} diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx index 1084611602..3e9847760c 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/RoleDetails/RoleDetailsEscrows/tableComponents/EscrowsTableBody.tsx @@ -10,6 +10,7 @@ import { useEscrowDetailsDto } from '@utils/hooks/use-escrows-details-dto'; import { useWalletSearch } from '@utils/hooks/use-wallet-search'; import { useNavigate } from 'react-router-dom'; import { Stack, TableRow } from '@mui/material'; +import Link from '@mui/material/Link'; export const EscrowsTableBody = ({ role, @@ -81,7 +82,7 @@ export const EscrowsTableBody = ({ navigate(`/search/${filterParams.chainId}/${elem.address}`); }} > - {elem.address} - + diff --git a/packages/apps/dashboard/ui-2024/src/theme.tsx b/packages/apps/dashboard/ui-2024/src/theme.tsx index e919a60d4d..0fb6b27439 100644 --- a/packages/apps/dashboard/ui-2024/src/theme.tsx +++ b/packages/apps/dashboard/ui-2024/src/theme.tsx @@ -343,6 +343,19 @@ const theme: ThemeOptions = createTheme({ }, }, }, + MuiLink: { + styleOverrides: { + root: { + color: colorPalette.link, + '&:hover': { + color: `${colorPalette.linkHover}!important`, + }, + '&:visited': { + color: colorPalette.linkVisited, + }, + }, + }, + }, }, }); From b3335c6f802f81fd1a94a68f0821397d0e6681fd Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:46:37 +0100 Subject: [PATCH 45/92] enable whitelist and fix some UI issues for billing system (#2884) --- .../BillingDetails/BillingDetailsModal.tsx | 17 ++- .../components/Jobs/Create/FiatPayForm.tsx | 56 +++++--- .../components/Jobs/Create/FundingMethod.tsx | 125 +++++++++--------- .../src/components/Jobs/Create/PayJob.tsx | 16 ++- .../TopUpAccount/CryptoTopUpForm.tsx | 4 +- .../components/TopUpAccount/TopUpMethod.tsx | 109 +++++++-------- .../src/pages/Profile/Settings/index.tsx | 65 +++++---- .../src/pages/Profile/TopUpAccount/index.tsx | 16 ++- .../client/src/state/auth/reducer.ts | 4 +- .../client/src/state/auth/types.ts | 1 + .../apps/job-launcher/client/src/utils/jwt.ts | 10 +- .../src/common/guards/whitelist.auth.spec.ts | 79 +++++++++++ .../server/src/modules/auth/auth.module.ts | 4 + .../src/modules/auth/auth.service.spec.ts | 9 ++ .../server/src/modules/auth/auth.service.ts | 6 + .../src/modules/cron-job/cron-job.service.ts | 4 +- .../src/modules/payment/payment.controller.ts | 7 +- .../src/modules/payment/payment.service.ts | 37 ++---- 18 files changed, 349 insertions(+), 220 deletions(-) create mode 100644 packages/apps/job-launcher/server/src/common/guards/whitelist.auth.spec.ts diff --git a/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx b/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx index 1477fc6641..463937f463 100644 --- a/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx +++ b/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx @@ -23,12 +23,25 @@ const BillingDetailsModal = ({ }: { open: boolean; onClose: () => void; - billingInfo: BillingInfo; + billingInfo: BillingInfo | null; setBillingInfo: (value: BillingInfo) => void; }) => { const theme = useTheme(); const [isLoading, setIsLoading] = useState(false); - const [formData, setFormData] = useState(billingInfo); + const [formData, setFormData] = useState( + billingInfo ?? { + name: '', + email: '', + address: { + city: '', + country: '', + postalCode: '', + line: '', + }, + vat: '', + vatType: '', + }, + ); const [errors, setErrors] = useState<{ [key: string]: string }>({}); const { showError } = useSnackbar(); diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx index 44dd1859be..cfdc6e15e5 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx @@ -70,6 +70,14 @@ export const FiatPayForm = ({ const [successMessage, setSuccessMessage] = useState(''); const [isBillingDetailsOpen, setIsBillingDetailsOpen] = useState(false); const [openBillingAfterAddCard, setOpenBillingAfterAddCard] = useState(false); + const [fundAmount, setFundAmount] = useState(0); + const [feeAmount, setFeeAmount] = useState(0); + const [totalAmount, setTotalAmount] = useState(0); + const [balancePayAmount, setBalancePayAmount] = useState(0); + const [creditCardPayAmount, setCreditCardPayAmount] = useState(0); + const [accountAmount] = useState( + user?.balance ? Number(user?.balance?.amount) : 0, + ); useEffect(() => { const fetchJobLauncherData = async () => { @@ -117,25 +125,30 @@ export const FiatPayForm = ({ }, }); - const fundAmount = amount ? Number(amount) : 0; - const feeAmount = Math.max( - minFee, - fundAmount * (Number(jobLauncherFee) / 100), - ); - const totalAmount = fundAmount + feeAmount; - const accountAmount = user?.balance ? Number(user?.balance?.amount) : 0; + useMemo(() => { + setFundAmount(amount ? Number(amount) : 0); + if (Number(jobLauncherFee) >= 0) + setFeeAmount( + Math.max(minFee, fundAmount * (Number(jobLauncherFee) / 100)), + ); + setTotalAmount(fundAmount + feeAmount); + if (!payWithAccountBalance) setBalancePayAmount(0); + else if (totalAmount < accountAmount) setBalancePayAmount(totalAmount); + else setBalancePayAmount(accountAmount); - const balancePayAmount = useMemo(() => { - if (!payWithAccountBalance) return 0; - if (totalAmount < accountAmount) return totalAmount; - return accountAmount; - }, [payWithAccountBalance, totalAmount, accountAmount]); - - const creditCardPayAmount = useMemo(() => { - if (!payWithAccountBalance) return totalAmount; - if (totalAmount < accountAmount) return 0; - return totalAmount - accountAmount; - }, [payWithAccountBalance, totalAmount, accountAmount]); + if (!payWithAccountBalance) setCreditCardPayAmount(totalAmount); + else if (totalAmount < accountAmount) setCreditCardPayAmount(0); + else setCreditCardPayAmount(totalAmount - accountAmount); + }, [ + accountAmount, + amount, + feeAmount, + fundAmount, + jobLauncherFee, + minFee, + payWithAccountBalance, + totalAmount, + ]); const handleSuccessAction = (message: string) => { setSuccessMessage(message); @@ -272,6 +285,7 @@ export const FiatPayForm = ({ onClick={() => setIsAddCardOpen(true)} size="large" sx={{ mb: 2 }} + disabled={payWithAccountBalance} > Add Payment Method @@ -318,7 +332,11 @@ export const FiatPayForm = ({ > Fees - ({Number(jobLauncherFee)}%) {feeAmount.toFixed(2)} USD + ( + {Number(jobLauncherFee) >= 0 + ? `${Number(jobLauncherFee)}%` + : 'loading...'} + ) {feeAmount.toFixed(2)} USD diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx index b6cc9e148a..13c00da135 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx @@ -4,8 +4,8 @@ import { useNavigate } from 'react-router-dom'; import { useAccount } from 'wagmi'; import fundCryptoImg from '../../../assets/fund-crypto.png'; import fundFiatImg from '../../../assets/fund-fiat.png'; -import { IS_MAINNET, IS_TESTNET } from '../../../constants/chains'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; +import { useAppSelector } from '../../../state'; import { PayMethod } from '../../../types'; import WalletModal from '../../WalletModal'; @@ -14,6 +14,7 @@ export const FundingMethod = () => { const { isConnected } = useAccount(); const navigate = useNavigate(); const { changePayMethod, goToNextStep } = useCreateJobPageUI(); + const { user } = useAppSelector((state) => state.auth); const handleClickCrypto = () => { if (isConnected) { @@ -44,7 +45,42 @@ export const FundingMethod = () => { }} > - + {user?.whitelisted && ( + + + crypto + + Click to connect your wallet + + + + + )} + { boxSizing: 'border-box', background: '#fbfbfe', borderRadius: '10px', - textAlign: 'center', display: 'flex', justifyContent: 'flex-end', alignItems: 'center', @@ -61,76 +96,42 @@ export const FundingMethod = () => { }} > crypto - Click to connect your wallet + Click to pay with credit card - - - - {IS_TESTNET && ( - - fiat - - Click to pay with credit card - - { + changePayMethod?.(PayMethod.Fiat); + goToNextStep?.(); }} > - - - + Pay with Credit Card + + - - )} + + { const { payMethod, changePayMethod, goToNextStep } = useCreateJobPageUI(); const [isPaying, setIsPaying] = useState(false); const { showError } = useSnackbar(); + const { user } = useAppSelector((state) => state.auth); const handleStart = () => { setIsPaying(true); @@ -56,8 +57,10 @@ export const PayJob = () => { marginBottom: '-2px', }} > - - {IS_TESTNET && } + {user?.whitelisted && ( + + )} + { background: '#fff', border: '1px solid #dbe1f6', borderRadius: '20px', - borderTopLeftRadius: payMethod === 0 ? '0px' : '20px', - borderTopRightRadius: payMethod === 1 ? '0px' : '20px', + borderTopLeftRadius: + payMethod === PayMethod.Crypto || !user?.whitelisted + ? '0px' + : '20px', + borderTopRightRadius: '20px', px: '10%', pt: 10, pb: 5, diff --git a/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx b/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx index b9365f9f3e..de6fb14bdf 100644 --- a/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx +++ b/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx @@ -82,8 +82,8 @@ export const CryptoTopUpForm = () => { return ( - You are on wrong network, please switch to one of the supported - networks. + Your wallet is connected to an unsupported network. Please switch to a + supported network. ); diff --git a/packages/apps/job-launcher/client/src/components/TopUpAccount/TopUpMethod.tsx b/packages/apps/job-launcher/client/src/components/TopUpAccount/TopUpMethod.tsx index 0d10b12dc4..cc8cb3bf9c 100644 --- a/packages/apps/job-launcher/client/src/components/TopUpAccount/TopUpMethod.tsx +++ b/packages/apps/job-launcher/client/src/components/TopUpAccount/TopUpMethod.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react'; import { useAccount } from 'wagmi'; import fundCryptoImg from '../../assets/fund-crypto.png'; import fundFiatImg from '../../assets/fund-fiat.png'; -import { IS_MAINNET, IS_TESTNET } from '../../constants/chains'; +import { useAppSelector } from '../../state'; import { PayMethod } from '../../types'; import WalletModal from '../WalletModal'; @@ -14,6 +14,7 @@ export const TopUpMethod = ({ }) => { const [walletModalOpen, setWalletModalOpen] = useState(false); const { isConnected } = useAccount(); + const { user } = useAppSelector((state) => state.auth); const handleClickCrypto = () => { if (isConnected) { @@ -43,7 +44,42 @@ export const TopUpMethod = ({ }} > - + {user?.whitelisted && ( + + + crypto + + Click to connect your wallet + + + + + )} + crypto - Click to connect your wallet + Click to pay with credit card - - - - {IS_TESTNET && ( - - fiat - - Click to pay with credit card - - { + onSelectMethod(PayMethod.Fiat); }} > - - + Pay with Credit Card + - - )} + + { const [openBillingAfterAddCard, setOpenBillingAfterAddCard] = useState(false); const [successMessage, setSuccessMessage] = useState(''); const [cards, setCards] = useState([]); - const [billingInfo, setBillingInfo] = useState({ - name: '', - email: '', - address: { - city: '', - country: '', - postalCode: '', - line: '', - }, - vat: '', - vatType: '', - }); + const [billingInfo, setBillingInfo] = useState(null); const fetchCards = async () => { try { @@ -51,7 +40,7 @@ const Settings = () => { const fetchBillingInfo = async () => { try { const data = await getUserBillingInfo(); - setBillingInfo({ ...billingInfo, ...data }); + if (data) setBillingInfo({ ...billingInfo, ...data }); } catch (error) { showError('Error fetching billing info'); } @@ -90,7 +79,7 @@ const Settings = () => { - + Billing Details @@ -104,30 +93,36 @@ const Settings = () => { > {billingInfo ? 'Edit Billing Details' - : 'Add Billing Details'} + : '+ Add Billing Details'} - - Details - - Full Name / Company Name: {billingInfo?.name} - - Email: {billingInfo?.email} - Address: {billingInfo?.address.line} - - Postal code: {billingInfo?.address.postalCode} - - City: {billingInfo?.address.city} - - Country: {countryOptions[billingInfo?.address.country]} - - - VAT Type: {vatTypeOptions[billingInfo?.vatType]} + {billingInfo ? ( + + Details + + Full Name / Company Name: {billingInfo.name} + + Email: {billingInfo.email} + Address: {billingInfo.address.line} + + Postal code: {billingInfo.address.postalCode} + + City: {billingInfo.address.city} + + Country: {countryOptions[billingInfo.address.country]} + + + VAT Type: {vatTypeOptions[billingInfo.vatType]} + + VAT Number: {billingInfo.vat} + + ) : ( + + No billing details added yet - VAT Number: {billingInfo?.vat} - + )} @@ -157,7 +152,7 @@ const Settings = () => { - + { onComplete={() => { handleSuccessAction('Your card has been successfully added.'); fetchCards(); - if (!billingInfo.name || !billingInfo.address) + if (!billingInfo?.name || !billingInfo?.address) setOpenBillingAfterAddCard(true); }} /> diff --git a/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx b/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx index a96d27ab0b..a165c31613 100644 --- a/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Profile/TopUpAccount/index.tsx @@ -4,11 +4,12 @@ import { StyledTab, StyledTabs } from '../../../components/Tabs'; import { CryptoTopUpForm } from '../../../components/TopUpAccount/CryptoTopUpForm'; import { FiatTopUpForm } from '../../../components/TopUpAccount/FiatTopUpForm'; import { TopUpMethod } from '../../../components/TopUpAccount/TopUpMethod'; -import { IS_TESTNET } from '../../../constants/chains'; +import { useAppSelector } from '../../../state'; import { PayMethod } from '../../../types'; export default function TopUpAccount() { const [payMethod, setPayMethod] = useState(); + const { user } = useAppSelector((state) => state.auth); const handleSelectMethod = (method: PayMethod) => { setPayMethod(method); @@ -35,8 +36,10 @@ export default function TopUpAccount() { value={payMethod} onChange={(e, newValue) => setPayMethod(newValue)} > - - {IS_TESTNET && } + {user?.whitelisted && ( + + )} + { localStorage.setItem(LOCAL_STORAGE_KEYS.refreshToken, refreshToken); state.isAuthed = true; - const { email, status } = getJwtPayload(accessToken); - state.user = { email: email, status: status }; + const { email, status, whitelisted } = getJwtPayload(accessToken); + state.user = { email, status, whitelisted }; state.accessToken = accessToken; state.refreshToken = refreshToken; }); diff --git a/packages/apps/job-launcher/client/src/state/auth/types.ts b/packages/apps/job-launcher/client/src/state/auth/types.ts index e00f4bebce..0986f2a1b4 100644 --- a/packages/apps/job-launcher/client/src/state/auth/types.ts +++ b/packages/apps/job-launcher/client/src/state/auth/types.ts @@ -13,6 +13,7 @@ export type User = { balance?: UserBalance; email: string; status: UserStatus; + whitelisted: boolean; }; export type AuthState = { diff --git a/packages/apps/job-launcher/client/src/utils/jwt.ts b/packages/apps/job-launcher/client/src/utils/jwt.ts index 243c9f092b..d04b5f7100 100644 --- a/packages/apps/job-launcher/client/src/utils/jwt.ts +++ b/packages/apps/job-launcher/client/src/utils/jwt.ts @@ -2,10 +2,12 @@ import { jwtDecode, JwtPayload } from 'jwt-decode'; import { UserStatus } from '../state/auth/types'; export function getJwtPayload(token: string) { - const { email, status } = jwtDecode<{ email: string; status: UserStatus }>( - token, - ); - return { email, status }; + const { email, status, whitelisted } = jwtDecode<{ + email: string; + status: UserStatus; + whitelisted: boolean; + }>(token); + return { email, status, whitelisted }; } export function isJwtExpired(token: string) { diff --git a/packages/apps/job-launcher/server/src/common/guards/whitelist.auth.spec.ts b/packages/apps/job-launcher/server/src/common/guards/whitelist.auth.spec.ts new file mode 100644 index 0000000000..d2f686626f --- /dev/null +++ b/packages/apps/job-launcher/server/src/common/guards/whitelist.auth.spec.ts @@ -0,0 +1,79 @@ +import { ExecutionContext, HttpStatus } from '@nestjs/common'; +import { Test, TestingModule } from '@nestjs/testing'; +import { WhitelistAuthGuard } from './whitelist.auth'; +import { WhitelistService } from '../../modules/whitelist/whitelist.service'; +import { ControlledError } from '../errors/controlled'; + +describe('WhitelistAuthGuard', () => { + let guard: WhitelistAuthGuard; + let whitelistService: Partial; + + beforeEach(async () => { + whitelistService = { + isUserWhitelisted: jest.fn(), + }; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + WhitelistAuthGuard, + { provide: WhitelistService, useValue: whitelistService }, + ], + }).compile(); + + guard = module.get(WhitelistAuthGuard); + }); + + it('should be defined', () => { + expect(guard).toBeDefined(); + }); + + it('should throw an error if user is not found in the request', async () => { + const mockContext = { + switchToHttp: () => ({ + getRequest: () => ({ user: null }), + }), + }; + + await expect( + guard.canActivate(mockContext as ExecutionContext), + ).rejects.toThrow( + new ControlledError('User not found.', HttpStatus.UNAUTHORIZED), + ); + }); + + it('should throw an error if the user is not whitelisted', async () => { + const mockContext = { + switchToHttp: () => ({ + getRequest: () => ({ + user: { id: 'user-id-123' }, + }), + }), + }; + + (whitelistService.isUserWhitelisted as jest.Mock).mockResolvedValue(false); + + await expect( + guard.canActivate(mockContext as ExecutionContext), + ).rejects.toThrow( + new ControlledError('Unauthorized.', HttpStatus.UNAUTHORIZED), + ); + }); + + it('should return true if the user is whitelisted', async () => { + const mockContext = { + switchToHttp: () => ({ + getRequest: () => ({ + user: { id: 'user-id-123' }, + }), + }), + }; + + (whitelistService.isUserWhitelisted as jest.Mock).mockResolvedValue(true); + + const result = await guard.canActivate(mockContext as ExecutionContext); + expect(result).toBe(true); + expect(whitelistService.isUserWhitelisted).toHaveBeenCalledWith( + 'user-id-123', + ); + }); +}); diff --git a/packages/apps/job-launcher/server/src/modules/auth/auth.module.ts b/packages/apps/job-launcher/server/src/modules/auth/auth.module.ts index 73962fab03..dd65c8c56e 100644 --- a/packages/apps/job-launcher/server/src/modules/auth/auth.module.ts +++ b/packages/apps/job-launcher/server/src/modules/auth/auth.module.ts @@ -14,6 +14,8 @@ import { ApiKeyRepository } from './apikey.repository'; import { ApiKeyEntity } from './apikey.entity'; import { UserEntity } from '../user/user.entity'; import { UserRepository } from '../user/user.repository'; +import { WhitelistModule } from '../whitelist/whitelist.module'; +import { WhitelistService } from '../whitelist/whitelist.service'; @Module({ imports: [ @@ -30,6 +32,7 @@ import { UserRepository } from '../user/user.repository'; }), TypeOrmModule.forFeature([TokenEntity, ApiKeyEntity, UserEntity]), SendGridModule, + WhitelistModule, ], providers: [ JwtHttpStrategy, @@ -37,6 +40,7 @@ import { UserRepository } from '../user/user.repository'; TokenRepository, ApiKeyRepository, UserRepository, + WhitelistService, ], controllers: [AuthJwtController], exports: [AuthService], diff --git a/packages/apps/job-launcher/server/src/modules/auth/auth.service.spec.ts b/packages/apps/job-launcher/server/src/modules/auth/auth.service.spec.ts index bef394b697..0a25d4d542 100644 --- a/packages/apps/job-launcher/server/src/modules/auth/auth.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/auth/auth.service.spec.ts @@ -30,6 +30,7 @@ import { ServerConfigService } from '../../common/config/server-config.service'; import { AuthConfigService } from '../../common/config/auth-config.service'; import { ControlledError } from '../../common/errors/controlled'; import { HttpStatus } from '@nestjs/common'; +import { WhitelistService } from '../whitelist/whitelist.service'; jest.mock('@human-protocol/sdk'); jest.mock('../../common/utils/hcaptcha', () => ({ @@ -47,6 +48,7 @@ describe('AuthService', () => { let userRepository: UserRepository; let jwtService: JwtService; let sendGridService: SendGridService; + let whitelistService: WhitelistService; beforeAll(async () => { const moduleRef = await Test.createTestingModule({ @@ -79,6 +81,7 @@ describe('AuthService', () => { { provide: PaymentService, useValue: createMock() }, { provide: SendGridService, useValue: createMock() }, { provide: ApiKeyRepository, useValue: createMock() }, + { provide: WhitelistService, useValue: createMock() }, ], }).compile(); @@ -88,6 +91,7 @@ describe('AuthService', () => { userRepository = moduleRef.get(UserRepository); jwtService = moduleRef.get(JwtService); sendGridService = moduleRef.get(SendGridService); + whitelistService = moduleRef.get(WhitelistService); }); afterEach(() => { @@ -233,6 +237,9 @@ describe('AuthService', () => { jwtSignMock = jest .spyOn(jwtService, 'signAsync') .mockResolvedValueOnce(MOCK_ACCESS_TOKEN); + jest + .spyOn(whitelistService, 'isUserWhitelisted') + .mockResolvedValue(false); }); afterEach(() => { @@ -253,6 +260,7 @@ describe('AuthService', () => { { email: userEntity.email, userId: userEntity.id, + whitelisted: false, }, { expiresIn: MOCK_EXPIRES_IN, @@ -280,6 +288,7 @@ describe('AuthService', () => { { email: userEntity.email, userId: userEntity.id, + whitelisted: false, }, { expiresIn: MOCK_EXPIRES_IN, diff --git a/packages/apps/job-launcher/server/src/modules/auth/auth.service.ts b/packages/apps/job-launcher/server/src/modules/auth/auth.service.ts index f1ae9f8086..534cd4afc2 100644 --- a/packages/apps/job-launcher/server/src/modules/auth/auth.service.ts +++ b/packages/apps/job-launcher/server/src/modules/auth/auth.service.ts @@ -31,6 +31,7 @@ import { verifyToken } from '../../common/utils/hcaptcha'; import { UserRepository } from '../user/user.repository'; import { ApiKeyEntity } from './apikey.entity'; import { ControlledError } from '../../common/errors/controlled'; +import { WhitelistService } from '../whitelist/whitelist.service'; @Injectable() export class AuthService { @@ -43,6 +44,7 @@ export class AuthService { private readonly sendgridService: SendGridService, private readonly apiKeyRepository: ApiKeyRepository, private readonly userRepository: UserRepository, + private readonly whitelistService: WhitelistService, ) {} public async signin(data: SignInDto, _ip?: string): Promise { @@ -152,12 +154,16 @@ export class AuthService { userEntity.id, TokenType.REFRESH, ); + const whitelisted = await this.whitelistService.isUserWhitelisted( + userEntity.id, + ); const accessToken = await this.jwtService.signAsync( { email: userEntity.email, userId: userEntity.id, status: userEntity.status, + whitelisted, }, { expiresIn: this.authConfigService.accessTokenExpiresIn, diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts index 3d67201deb..3e4c3b313b 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts @@ -276,11 +276,11 @@ export class CronJobService { return true; } - @Cron('*/5 * * * *') /** * Process a pending webhook job. * @returns {Promise} - Returns a promise that resolves when the operation is complete. */ + @Cron('*/5 * * * *') public async processPendingWebhooks(): Promise { const isCronJobRunning = await this.isCronJobRunning( CronJobType.ProcessPendingWebhook, @@ -380,11 +380,11 @@ export class CronJobService { // await this.completeCronJob(cronJob); // } - @Cron('30 */2 * * * *') /** * Process a job that syncs job statuses. * @returns {Promise} - Returns a promise that resolves when the operation is complete. */ + @Cron('30 */2 * * * *') public async syncJobStuses(): Promise { const lastCronJob = await this.cronJobRepository.findOneByType( CronJobType.SyncJobStatuses, diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts index 9f180d50e2..8bb5c395eb 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.controller.ts @@ -40,7 +40,7 @@ import { ControlledError } from '../../common/errors/controlled'; import { ServerConfigService } from '../../common/config/server-config.service'; import { RateService } from './rate.service'; import { PageDto } from '../../common/pagination/pagination.dto'; -// import { WhitelistAuthGuard } from 'src/common/guards/whitelist.auth'; +import { WhitelistAuthGuard } from 'src/common/guards/whitelist.auth'; @ApiBearerAuth() @UseGuards(JwtAuthGuard) @@ -79,8 +79,7 @@ export class PaymentController { status: 409, description: 'Conflict. Conflict with the current state of the server.', }) - // Disabled until billing system is active - // @UseGuards(WhitelistAuthGuard) + @UseGuards(WhitelistAuthGuard) @Post('/crypto') public async createCryptoPayment( @Headers(HEADER_SIGNATURE_KEY) signature: string, @@ -309,7 +308,7 @@ export class PaymentController { @Get('/fiat/billing-info') public async getBillingInfo( @Request() req: RequestWithUser, - ): Promise { + ): Promise { return this.paymentService.getUserBillingInfo(req.user); } diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts index 3d7c75ab4b..0eed621319 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts @@ -498,12 +498,10 @@ export class PaymentService { // return; // } - async listUserPaymentMethods(user: UserEntity) { + async listUserPaymentMethods(user: UserEntity): Promise { + const cards: CardDto[] = []; if (!user.stripeCustomerId) { - throw new ControlledError( - ErrorPayment.CustomerNotFound, - HttpStatus.BAD_REQUEST, - ); + return cards; } // List all the payment methods (cards) associated with the user's Stripe account @@ -515,7 +513,6 @@ export class PaymentService { }, ); - const cards: CardDto[] = []; // Get the default payment method for the user const defaultPaymentMethod = await this.getDefaultPaymentMethod( user.stripeCustomerId, @@ -555,12 +552,9 @@ export class PaymentService { return this.stripe.paymentMethods.detach(paymentMethodId); } - async getUserBillingInfo(user: UserEntity) { + async getUserBillingInfo(user: UserEntity): Promise { if (!user.stripeCustomerId) { - throw new ControlledError( - ErrorPayment.CustomerNotFound, - HttpStatus.BAD_REQUEST, - ); + return null; } // Retrieve the customer's tax IDs and customer information @@ -568,24 +562,21 @@ export class PaymentService { user.stripeCustomerId, ); - const customer = await this.stripe.customers.retrieve( + const customer = (await this.stripe.customers.retrieve( user.stripeCustomerId, - ); + )) as Stripe.Customer; const userBillingInfo = new BillingInfoDto(); - if ((customer as Stripe.Customer).address) { + if (customer.address) { const address = new AddressDto(); - address.country = ( - (customer as Stripe.Customer).address?.country as string - ).toLowerCase(); - address.postalCode = (customer as Stripe.Customer).address - ?.postal_code as string; - address.city = (customer as Stripe.Customer).address?.city as string; - address.line = (customer as Stripe.Customer).address?.line1 as string; + address.country = (customer.address.country as string).toLowerCase(); + address.postalCode = customer.address.postal_code as string; + address.city = customer.address.city as string; + address.line = customer.address.line1 as string; userBillingInfo.address = address; } - userBillingInfo.name = (customer as Stripe.Customer)?.name as string; - userBillingInfo.email = (customer as Stripe.Customer)?.email as string; + userBillingInfo.name = customer.name as string; + userBillingInfo.email = customer.email as string; userBillingInfo.vat = taxIds.data[0]?.value; userBillingInfo.vatType = taxIds.data[0]?.type as VatType; return userBillingInfo; From 00df1db34ef1b6fd684ba6d0437a3bc8a7b670da Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:21:34 +0300 Subject: [PATCH 46/92] [Reputation Oracle] Refactoring Cron Module (#2834) --- .../server/src/app.module.ts | 10 +- .../server/src/common/constants/errors.ts | 10 +- .../server/src/common/enums/webhook.ts | 2 +- .../server/src/common/utils/index.ts | 4 + .../server/src/database/database.module.ts | 4 +- .../src/modules/cron-job/cron-job.module.ts | 27 +- .../modules/cron-job/cron-job.service.spec.ts | 888 +++++------------- .../src/modules/cron-job/cron-job.service.ts | 293 +----- .../escrow-completion-tracking.module.ts | 21 - ...escrow-completion-tracking.service.spec.ts | 181 ---- .../escrow-completion-tracking.service.ts | 73 -- .../escrow-completion.entity.ts} | 8 +- .../escrow-completion.module.ts | 25 + .../escrow-completion.repository.ts} | 14 +- .../escrow-completion.service.spec.ts | 529 +++++++++++ .../escrow-completion.service.ts | 261 +++++ .../src/modules/payout/payout.service.spec.ts | 28 +- .../src/modules/payout/payout.service.ts | 22 +- .../server/src/modules/user/user.dto.ts | 2 +- ...k.module.ts => webhook-incoming.module.ts} | 19 +- .../webhook/webhook-incoming.service.spec.ts | 290 ++++++ .../webhook/webhook-incoming.service.ts | 115 +++ .../webhook/webhook-outgoing.module.ts | 20 + .../webhook/webhook-outgoing.service.spec.ts | 291 ++++++ ...service.ts => webhook-outgoing.service.ts} | 111 +-- .../src/modules/webhook/webhook.controller.ts | 8 +- .../modules/webhook/webhook.service.spec.ts | 296 ------ 27 files changed, 1910 insertions(+), 1642 deletions(-) delete mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.module.ts delete mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.spec.ts delete mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.ts rename packages/apps/reputation-oracle/server/src/modules/{escrow-completion-tracking/escrow-completion-tracking.entity.ts => escrow-completion/escrow-completion.entity.ts} (78%) create mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.module.ts rename packages/apps/reputation-oracle/server/src/modules/{escrow-completion-tracking/escrow-completion-tracking.repository.ts => escrow-completion/escrow-completion.repository.ts} (57%) create mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts rename packages/apps/reputation-oracle/server/src/modules/webhook/{webhook.module.ts => webhook-incoming.module.ts} (55%) create mode 100644 packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.spec.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.module.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.spec.ts rename packages/apps/reputation-oracle/server/src/modules/webhook/{webhook.service.ts => webhook-outgoing.service.ts} (58%) delete mode 100644 packages/apps/reputation-oracle/server/src/modules/webhook/webhook.service.spec.ts diff --git a/packages/apps/reputation-oracle/server/src/app.module.ts b/packages/apps/reputation-oracle/server/src/app.module.ts index b8f89f9639..d9e3963b3f 100644 --- a/packages/apps/reputation-oracle/server/src/app.module.ts +++ b/packages/apps/reputation-oracle/server/src/app.module.ts @@ -7,7 +7,6 @@ import { DatabaseModule } from './database/database.module'; import { HttpValidationPipe } from './common/pipes'; import { HealthModule } from './modules/health/health.module'; import { ReputationModule } from './modules/reputation/reputation.module'; -import { WebhookModule } from './modules/webhook/webhook.module'; import { Web3Module } from './modules/web3/web3.module'; import { envValidator } from './common/config'; import { AuthModule } from './modules/auth/auth.module'; @@ -21,7 +20,9 @@ import { EnvConfigModule } from './common/config/config.module'; import { HCaptchaModule } from './integrations/hcaptcha/hcaptcha.module'; import { ExceptionFilter } from './common/exceptions/exception.filter'; import { QualificationModule } from './modules/qualification/qualification.module'; -import { EscrowCompletionTrackingModule } from './modules/escrow-completion-tracking/escrow-completion-tracking.module'; +import { EscrowCompletionModule } from './modules/escrow-completion/escrow-completion.module'; +import { WebhookIncomingModule } from './modules/webhook/webhook-incoming.module'; +import { WebhookOutgoingModule } from './modules/webhook/webhook-outgoing.module'; @Module({ providers: [ @@ -49,7 +50,8 @@ import { EscrowCompletionTrackingModule } from './modules/escrow-completion-trac DatabaseModule, HealthModule, ReputationModule, - WebhookModule, + WebhookIncomingModule, + WebhookOutgoingModule, Web3Module, AuthModule, KycModule, @@ -65,7 +67,7 @@ import { EscrowCompletionTrackingModule } from './modules/escrow-completion-trac EnvConfigModule, HCaptchaModule, QualificationModule, - EscrowCompletionTrackingModule, + EscrowCompletionModule, ], controllers: [AppController], }) diff --git a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts index 898a7205b9..08400a470b 100644 --- a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts +++ b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts @@ -12,11 +12,13 @@ export enum ErrorWebhook { } /** - * Represents error messages related to escrow completion tracking. + * Represents error messages related to escrow completion. */ -export enum ErrorEscrowCompletionTracking { - NotFound = 'Escrow completion tracking not found', - NotCreated = 'Escrow completion tracking has not been created', +export enum ErrorEscrowCompletion { + NotFound = 'Escrow completion not found', + NotCreated = 'Escrow completion has not been created', + PendingProcessingFailed = 'Failed to process pending escrow completion', + PaidProcessingFailed = 'Failed to process paid escrow completion', } /** diff --git a/packages/apps/reputation-oracle/server/src/common/enums/webhook.ts b/packages/apps/reputation-oracle/server/src/common/enums/webhook.ts index e439755723..a4144a83a8 100644 --- a/packages/apps/reputation-oracle/server/src/common/enums/webhook.ts +++ b/packages/apps/reputation-oracle/server/src/common/enums/webhook.ts @@ -15,7 +15,7 @@ export enum WebhookOutgoingStatus { FAILED = 'failed', } -export enum EscrowCompletionTrackingStatus { +export enum EscrowCompletionStatus { PENDING = 'pending', PAID = 'paid', COMPLETED = 'completed', diff --git a/packages/apps/reputation-oracle/server/src/common/utils/index.ts b/packages/apps/reputation-oracle/server/src/common/utils/index.ts index 0825070608..8e09c0d290 100644 --- a/packages/apps/reputation-oracle/server/src/common/utils/index.ts +++ b/packages/apps/reputation-oracle/server/src/common/utils/index.ts @@ -42,3 +42,7 @@ export function getRequestType( return requestType; } + +export function isValidJobRequestType(value: string): value is JobRequestType { + return Object.values(JobRequestType).includes(value as JobRequestType); +} diff --git a/packages/apps/reputation-oracle/server/src/database/database.module.ts b/packages/apps/reputation-oracle/server/src/database/database.module.ts index cdd2166783..269a2cee04 100644 --- a/packages/apps/reputation-oracle/server/src/database/database.module.ts +++ b/packages/apps/reputation-oracle/server/src/database/database.module.ts @@ -21,7 +21,7 @@ import { QualificationEntity } from '../modules/qualification/qualification.enti import { UserQualificationEntity } from '../modules/qualification/user-qualification.entity'; import { WebhookIncomingEntity } from '../modules/webhook/webhook-incoming.entity'; import { WebhookOutgoingEntity } from '../modules/webhook/webhook-outgoing.entity'; -import { EscrowCompletionTrackingEntity } from 'src/modules/escrow-completion-tracking/escrow-completion-tracking.entity'; +import { EscrowCompletionEntity } from '../modules/escrow-completion/escrow-completion.entity'; @Module({ imports: [ @@ -49,7 +49,7 @@ import { EscrowCompletionTrackingEntity } from 'src/modules/escrow-completion-tr entities: [ WebhookIncomingEntity, WebhookOutgoingEntity, - EscrowCompletionTrackingEntity, + EscrowCompletionEntity, ReputationEntity, CredentialEntity, CredentialValidationEntity, diff --git a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.module.ts b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.module.ts index 548e0bb07f..d73d6b8138 100644 --- a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.module.ts +++ b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.module.ts @@ -4,34 +4,21 @@ import { CronJobService } from './cron-job.service'; import { CronJobRepository } from './cron-job.repository'; import { TypeOrmModule } from '@nestjs/typeorm'; import { CronJobEntity } from './cron-job.entity'; -import { Web3Module } from '../web3/web3.module'; -import { WebhookModule } from '../webhook/webhook.module'; import { ConfigModule } from '@nestjs/config'; -import { PayoutModule } from '../payout/payout.module'; -import { ReputationModule } from '../reputation/reputation.module'; -import { WebhookIncomingRepository } from '../webhook/webhook-incoming.repository'; -import { WebhookOutgoingRepository } from '../webhook/webhook-outgoing.repository'; -import { EscrowCompletionTrackingRepository } from '../escrow-completion-tracking/escrow-completion-tracking.repository'; -import { EscrowCompletionTrackingModule } from '../escrow-completion-tracking/escrow-completion-tracking.module'; +import { EscrowCompletionModule } from '../escrow-completion/escrow-completion.module'; +import { WebhookIncomingModule } from '../webhook/webhook-incoming.module'; +import { WebhookOutgoingModule } from '../webhook/webhook-outgoing.module'; @Global() @Module({ imports: [ TypeOrmModule.forFeature([CronJobEntity]), ConfigModule, - Web3Module, - WebhookModule, - EscrowCompletionTrackingModule, - PayoutModule, - ReputationModule, - ], - providers: [ - CronJobService, - CronJobRepository, - WebhookIncomingRepository, - WebhookOutgoingRepository, - EscrowCompletionTrackingRepository, + WebhookIncomingModule, + WebhookOutgoingModule, + EscrowCompletionModule, ], + providers: [CronJobService, CronJobRepository], exports: [CronJobService], }) export class CronJobModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.spec.ts index f46829edca..00694e1b2e 100644 --- a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.spec.ts @@ -1,830 +1,396 @@ import { Test, TestingModule } from '@nestjs/testing'; - -import { CronJobType } from '../../common/enums/cron-job'; - import { CronJobService } from './cron-job.service'; +import { HttpStatus, Logger } from '@nestjs/common'; import { CronJobRepository } from './cron-job.repository'; import { CronJobEntity } from './cron-job.entity'; -import { createMock } from '@golevelup/ts-jest'; -import { - MOCK_ADDRESS, - MOCK_FILE_HASH, - MOCK_FILE_URL, - MOCK_MAX_RETRY_COUNT, - MOCK_WEBHOOK_URL, - mockConfig, -} from '../../../test/constants'; -import { ChainId, EscrowClient, EscrowStatus } from '@human-protocol/sdk'; -import { WebhookService } from '../webhook/webhook.service'; -import { Web3Service } from '../web3/web3.service'; -import { ConfigService } from '@nestjs/config'; -import { - EventType, - WebhookIncomingStatus, - WebhookOutgoingStatus, - EscrowCompletionTrackingStatus, -} from '../../common/enums/webhook'; -import { PayoutService } from '../payout/payout.service'; -import { ReputationService } from '../reputation/reputation.service'; -import { StorageService } from '../storage/storage.service'; -import { ReputationRepository } from '../reputation/reputation.repository'; -import { HttpService } from '@nestjs/axios'; -import { ServerConfigService } from '../../common/config/server-config.service'; -import { Web3ConfigService } from '../../common/config/web3-config.service'; -import { ReputationConfigService } from '../../common/config/reputation-config.service'; +import { CronJobType } from '../../common/enums/cron-job'; +import { ErrorCronJob } from '../../common/constants/errors'; import { ControlledError } from '../../common/errors/controlled'; -import { ErrorCronJob, ErrorWebhook } from '../../common/constants/errors'; -import { HttpStatus } from '@nestjs/common'; -import { WebhookOutgoingRepository } from '../webhook/webhook-outgoing.repository'; -import { WebhookIncomingRepository } from '../webhook/webhook-incoming.repository'; -import { WebhookIncomingEntity } from '../webhook/webhook-incoming.entity'; -import { WebhookOutgoingEntity } from '../webhook/webhook-outgoing.entity'; -import { EscrowCompletionTrackingRepository } from '../escrow-completion-tracking/escrow-completion-tracking.repository'; -import { EscrowCompletionTrackingService } from '../escrow-completion-tracking/escrow-completion-tracking.service'; -import { PostgresErrorCodes } from '../../common/enums/database'; -import { DatabaseError } from '../../common/errors/database'; - -jest.mock('@human-protocol/sdk', () => ({ - ...jest.requireActual('@human-protocol/sdk'), - EscrowClient: { - build: jest.fn().mockImplementation(() => ({ - createEscrow: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getRecordingOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - setup: jest.fn().mockResolvedValue(null), - fund: jest.fn().mockResolvedValue(null), - getManifestUrl: jest.fn().mockResolvedValue(MOCK_FILE_URL), - complete: jest.fn().mockResolvedValue(null), - getStatus: jest.fn(), - })), - }, - KVStoreUtils: { - get: jest.fn(), - }, - OperatorUtils: { - getLeader: jest.fn().mockImplementation(() => { - return { webhookUrl: MOCK_WEBHOOK_URL }; - }), - }, -})); +import { WebhookOutgoingService } from '../webhook/webhook-outgoing.service'; +import { WebhookIncomingService } from '../webhook/webhook-incoming.service'; +import { EscrowCompletionService } from '../escrow-completion/escrow-completion.service'; describe('CronJobService', () => { - let service: CronJobService, - repository: CronJobRepository, - webhookIncomingRepository: WebhookIncomingRepository, - webhookOutgoingRepository: WebhookOutgoingRepository, - escrowCompletionTrackingRepository: EscrowCompletionTrackingRepository, - webhookService: WebhookService, - escrowCompletionTrackingService: EscrowCompletionTrackingService, - reputationService: ReputationService, - payoutService: PayoutService; - - const signerMock = { - address: MOCK_ADDRESS, - getNetwork: jest.fn().mockResolvedValue({ chainId: 1 }), - }; + let service: CronJobService; + let cronJobRepository: jest.Mocked; + let webhookIncomingService: jest.Mocked; + let webhookOutgoingService: jest.Mocked; + let escrowCompletionService: jest.Mocked; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ - { - provide: ConfigService, - useValue: { - get: jest.fn((key: string) => mockConfig[key]), - getOrThrow: jest.fn((key: string) => { - if (!mockConfig[key]) { - throw new Error(`Configuration key "${key}" does not exist`); - } - return mockConfig[key]; - }), - }, - }, CronJobService, { provide: CronJobRepository, - useValue: createMock(), - }, - { - provide: Web3Service, useValue: { - getSigner: jest.fn().mockReturnValue(signerMock), - validateChainId: jest.fn().mockReturnValue(new Error()), - calculateGasPrice: jest.fn().mockReturnValue(1000n), + findOneByType: jest.fn(), + createUnique: jest.fn(), + updateOne: jest.fn(), }, }, - WebhookService, - EscrowCompletionTrackingService, { - provide: PayoutService, - useValue: createMock(), - }, - ReputationService, - ServerConfigService, - Web3ConfigService, - ReputationConfigService, - { provide: HttpService, useValue: createMock() }, - - { - provide: WebhookIncomingRepository, - useValue: createMock(), + provide: WebhookIncomingService, + useValue: { + processPendingIncomingWebhooks: jest.fn(), + }, }, { - provide: WebhookOutgoingRepository, - useValue: createMock(), + provide: WebhookOutgoingService, + useValue: { + processPendingOutgoingWebhooks: jest.fn(), + }, }, { - provide: EscrowCompletionTrackingRepository, - useValue: createMock(), + provide: EscrowCompletionService, + useValue: { + processPendingEscrowCompletion: jest.fn(), + processPaidEscrowCompletion: jest.fn(), + }, }, - { provide: StorageService, useValue: createMock() }, { - provide: ReputationRepository, - useValue: createMock(), + provide: Logger, + useValue: { + log: jest.fn(), + error: jest.fn(), + }, }, ], }).compile(); service = module.get(CronJobService); - repository = module.get(CronJobRepository); - reputationService = module.get(ReputationService); - webhookIncomingRepository = module.get(WebhookIncomingRepository); - webhookOutgoingRepository = module.get(WebhookOutgoingRepository); - escrowCompletionTrackingRepository = module.get( - EscrowCompletionTrackingRepository, - ); - payoutService = module.get(PayoutService); - - webhookService = module.get(WebhookService); - escrowCompletionTrackingService = - module.get( - EscrowCompletionTrackingService, - ); + cronJobRepository = module.get(CronJobRepository); + webhookIncomingService = module.get(WebhookIncomingService); + webhookOutgoingService = module.get(WebhookOutgoingService); + escrowCompletionService = module.get(EscrowCompletionService); }); describe('startCronJob', () => { - it('should create a cron job if not exists', async () => { - const cronJobType = CronJobType.ProcessPendingIncomingWebhook; + it('should create a new cron job if none exists', async () => { + cronJobRepository.findOneByType.mockResolvedValue(null); + cronJobRepository.createUnique.mockResolvedValue(new CronJobEntity()); - const cronJobEntity = new CronJobEntity(); - cronJobEntity.cronJobType = cronJobType; - cronJobEntity.startedAt = new Date(); - - jest.spyOn(repository, 'findOneByType').mockResolvedValue(null); - - const createUniqueSpy = jest - .spyOn(repository, 'createUnique') - .mockResolvedValue(cronJobEntity); - - const result = await service.startCronJob(cronJobType); + const result = await service.startCronJob( + CronJobType.ProcessPendingIncomingWebhook, + ); - expect(createUniqueSpy).toHaveBeenCalledWith({ + expect(cronJobRepository.findOneByType).toHaveBeenCalledWith( + CronJobType.ProcessPendingIncomingWebhook, + ); + expect(cronJobRepository.createUnique).toHaveBeenCalledWith({ cronJobType: CronJobType.ProcessPendingIncomingWebhook, }); - expect(result).toEqual(cronJobEntity); + expect(result).toBeInstanceOf(CronJobEntity); }); - it('should start a cron job if exists', async () => { - const cronJobType = CronJobType.ProcessPendingIncomingWebhook; - const cronJobEntity: Partial = { - cronJobType: cronJobType, + it('should update an existing cron job', async () => { + const existingCronJob = new CronJobEntity(); + existingCronJob.startedAt = new Date(); + cronJobRepository.findOneByType.mockResolvedValue(existingCronJob); + + const updatedCronJob = { + ...existingCronJob, startedAt: new Date(), - completedAt: new Date(), + completedAt: null, }; + cronJobRepository.updateOne.mockResolvedValue(updatedCronJob as any); - const mockDate = new Date(2023, 12, 23); - jest.useFakeTimers(); - jest.setSystemTime(mockDate); - - const findOneByTypeSpy = jest - .spyOn(repository, 'findOneByType') - .mockResolvedValue(cronJobEntity as any); - - const updateOneSpy = jest - .spyOn(repository, 'updateOne') - .mockResolvedValue(cronJobEntity as any); - - const result = await service.startCronJob(cronJobType); - - expect(findOneByTypeSpy).toHaveBeenCalledWith(cronJobType); - expect(updateOneSpy).toHaveBeenCalled(); - cronJobEntity.startedAt = mockDate; - expect(result).toEqual(cronJobEntity); + const result = await service.startCronJob( + CronJobType.ProcessPendingIncomingWebhook, + ); - jest.useRealTimers(); + expect(cronJobRepository.findOneByType).toHaveBeenCalledWith( + CronJobType.ProcessPendingIncomingWebhook, + ); + expect(cronJobRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + startedAt: expect.any(Date), + completedAt: null, + }), + ); + expect( + Math.abs( + new Date(updatedCronJob.startedAt).getTime() - + existingCronJob.startedAt.getTime(), + ), + ).toBeLessThanOrEqual(1000); + expect(result).toEqual(updatedCronJob); }); }); describe('isCronJobRunning', () => { - it('should return false if no cron job is running', async () => { - const cronJobType = CronJobType.ProcessPendingIncomingWebhook; - const cronJobEntity = new CronJobEntity(); - cronJobEntity.cronJobType = cronJobType; + it('should return false if no cron job exists', async () => { + cronJobRepository.findOneByType.mockResolvedValue(null); - const findOneByTypeSpy = jest - .spyOn(repository, 'findOneByType') - .mockResolvedValue(null); - - const result = await service.isCronJobRunning(cronJobType); + const result = await service.isCronJobRunning( + CronJobType.ProcessPendingIncomingWebhook, + ); - expect(findOneByTypeSpy).toHaveBeenCalledWith(cronJobType); - expect(result).toEqual(false); + expect(cronJobRepository.findOneByType).toHaveBeenCalledWith( + CronJobType.ProcessPendingIncomingWebhook, + ); + expect(result).toBe(false); }); - it('should return false if last cron job is completed', async () => { - const cronJobType = CronJobType.ProcessPendingIncomingWebhook; - const cronJobEntity = new CronJobEntity(); - cronJobEntity.cronJobType = cronJobType; - cronJobEntity.completedAt = new Date(); + it('should return false if the last cron job is completed', async () => { + const completedCronJob = new CronJobEntity(); + completedCronJob.completedAt = new Date(); + cronJobRepository.findOneByType.mockResolvedValue(completedCronJob); - const findOneByTypeSpy = jest - .spyOn(repository, 'findOneByType') - .mockResolvedValue(cronJobEntity); - - const result = await service.isCronJobRunning(cronJobType); + const result = await service.isCronJobRunning( + CronJobType.ProcessPendingIncomingWebhook, + ); - expect(findOneByTypeSpy).toHaveBeenCalledWith(cronJobType); - expect(result).toEqual(false); + expect(cronJobRepository.findOneByType).toHaveBeenCalledWith( + CronJobType.ProcessPendingIncomingWebhook, + ); + expect(result).toBe(false); }); - it('should return true if last cron job is not completed', async () => { - const cronJobType = CronJobType.ProcessPendingIncomingWebhook; - const cronJobEntity = new CronJobEntity(); - cronJobEntity.cronJobType = cronJobType; + it('should return true if the last cron job is not completed', async () => { + const runningCronJob = new CronJobEntity(); + cronJobRepository.findOneByType.mockResolvedValue(runningCronJob); - const findOneByTypeSpy = jest - .spyOn(repository, 'findOneByType') - .mockResolvedValue(cronJobEntity); + const result = await service.isCronJobRunning( + CronJobType.ProcessPendingIncomingWebhook, + ); - const result = await service.isCronJobRunning(cronJobType); - expect(findOneByTypeSpy).toHaveBeenCalledWith(cronJobType); - expect(result).toEqual(true); + expect(cronJobRepository.findOneByType).toHaveBeenCalledWith( + CronJobType.ProcessPendingIncomingWebhook, + ); + expect(result).toBe(true); }); }); describe('completeCronJob', () => { it('should complete a cron job', async () => { - const cronJobType = CronJobType.ProcessPendingIncomingWebhook; const cronJobEntity = new CronJobEntity(); - cronJobEntity.cronJobType = cronJobType; - const mockDate = new Date(2023, 12, 23); - - jest.useFakeTimers(); - jest.setSystemTime(mockDate); + const completedCronJob = { + ...cronJobEntity, + completedAt: new Date(), + }; - const updateOneSpy = jest - .spyOn(repository, 'updateOne') - .mockResolvedValue(cronJobEntity); + cronJobRepository.updateOne.mockResolvedValue(completedCronJob as any); const result = await service.completeCronJob(cronJobEntity); - expect(updateOneSpy).toHaveBeenCalled(); - expect(cronJobEntity.completedAt).toEqual(mockDate); - expect(result).toEqual(cronJobEntity); + expect(cronJobRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + ...cronJobEntity, + completedAt: expect.any(Date), + }), + ); + + expect(result.completedAt).toBeInstanceOf(Date); - jest.useRealTimers(); + expect( + Math.abs( + new Date(result.completedAt!).getTime() - + completedCronJob.completedAt.getTime(), + ), + ).toBeLessThanOrEqual(1000); }); - it('should throw an error if cron job is already completed', async () => { - const cronJobType = CronJobType.ProcessPendingIncomingWebhook; + it('should throw an error if the cron job is already completed', async () => { const cronJobEntity = new CronJobEntity(); - cronJobEntity.cronJobType = cronJobType; cronJobEntity.completedAt = new Date(); - const updateOneSpy = jest - .spyOn(repository, 'updateOne') - .mockResolvedValue(cronJobEntity); - await expect(service.completeCronJob(cronJobEntity)).rejects.toThrow( new ControlledError(ErrorCronJob.Completed, HttpStatus.BAD_REQUEST), ); - expect(updateOneSpy).not.toHaveBeenCalled(); }); }); - describe('processPendingIncomingWebhooksCronJob', () => { - let createEscrowCompletionTrackingMock: any; - let cronJobEntityMock: Partial; - let webhookEntity1: Partial, - webhookEntity2: Partial; - - let completeCronJobMock: jest.SpyInstance; - - beforeEach(() => { - completeCronJobMock = jest - .spyOn(service, 'completeCronJob') - .mockResolvedValue({} as CronJobEntity); - - cronJobEntityMock = { - cronJobType: CronJobType.ProcessPendingIncomingWebhook, - startedAt: new Date(), - }; - - webhookEntity1 = { - id: 1, - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - status: WebhookIncomingStatus.PENDING, - waitUntil: new Date(), - retriesCount: 0, - }; - - webhookEntity2 = { - id: 2, - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - status: WebhookIncomingStatus.PENDING, - waitUntil: new Date(), - retriesCount: 0, - }; - - jest - .spyOn(webhookIncomingRepository, 'findByStatus') - .mockResolvedValue([webhookEntity1 as any, webhookEntity2 as any]); - - createEscrowCompletionTrackingMock = jest.spyOn( - escrowCompletionTrackingService as any, - 'createEscrowCompletionTracking', - ); - createEscrowCompletionTrackingMock.mockResolvedValue(undefined); - - jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); - - jest.spyOn(repository, 'findOneByType').mockResolvedValue(null); - jest - .spyOn(repository, 'createUnique') - .mockResolvedValue(cronJobEntityMock as any); - }); - - afterEach(() => { - jest.restoreAllMocks(); - }); - - it('should not run if cron job is already running', async () => { - jest.spyOn(service, 'isCronJobRunning').mockResolvedValueOnce(true); - - const startCronJobMock = jest.spyOn(service, 'startCronJob'); + describe('processPendingIncomingWebhooks', () => { + it('should skip processing if a cron job is already running', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(true); await service.processPendingIncomingWebhooks(); - expect(startCronJobMock).not.toHaveBeenCalled(); + expect( + webhookIncomingService.processPendingIncomingWebhooks, + ).not.toHaveBeenCalled(); }); - it('should create cron job entity to lock the process', async () => { + it('should process pending webhooks and complete the cron job', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); jest .spyOn(service, 'startCronJob') - .mockResolvedValueOnce(cronJobEntityMock as any); - - await service.processPendingIncomingWebhooks(); - - expect(service.startCronJob).toHaveBeenCalledWith( - CronJobType.ProcessPendingIncomingWebhook, - ); - }); - - it('should send webhook for all of the pending incoming webhooks', async () => { - await service.processPendingIncomingWebhooks(); - - expect(createEscrowCompletionTrackingMock).toHaveBeenCalledTimes(2); - expect(createEscrowCompletionTrackingMock).toHaveBeenCalledWith( - webhookEntity1.chainId, - webhookEntity1.escrowAddress, - ); - expect(createEscrowCompletionTrackingMock).toHaveBeenCalledWith( - webhookEntity2.chainId, - webhookEntity2.escrowAddress, - ); - - expect(webhookIncomingRepository.updateOne).toHaveBeenCalledTimes(2); - expect(webhookEntity1.status).toBe(WebhookIncomingStatus.COMPLETED); - expect(webhookEntity2.status).toBe(WebhookIncomingStatus.COMPLETED); - }); - - it('should increase retriesCount by 1 if sending webhook fails', async () => { - createEscrowCompletionTrackingMock.mockRejectedValueOnce(new Error()); - await service.processPendingIncomingWebhooks(); - - expect(webhookIncomingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity1.status).toBe(WebhookIncomingStatus.PENDING); - expect(webhookEntity1.retriesCount).toBe(1); - expect(webhookEntity1.waitUntil).toBeInstanceOf(Date); - }); - - it('should mark webhook as failed if retriesCount exceeds threshold', async () => { - createEscrowCompletionTrackingMock.mockRejectedValueOnce(new Error()); - - webhookEntity1.retriesCount = MOCK_MAX_RETRY_COUNT; + .mockResolvedValue(new CronJobEntity()); + jest + .spyOn(service, 'completeCronJob') + .mockResolvedValue(new CronJobEntity()); await service.processPendingIncomingWebhooks(); - expect(webhookIncomingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity1.status).toBe(WebhookIncomingStatus.FAILED); + expect( + webhookIncomingService.processPendingIncomingWebhooks, + ).toHaveBeenCalled(); + expect(service.startCronJob).toHaveBeenCalled(); + expect(service.completeCronJob).toHaveBeenCalled(); }); - it('should complete the cron job entity to unlock', async () => { + it('should complete the cron job after processing', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); + jest + .spyOn(service, 'startCronJob') + .mockResolvedValue(new CronJobEntity()); jest .spyOn(service, 'completeCronJob') - .mockResolvedValueOnce(cronJobEntityMock as any); + .mockResolvedValue(new CronJobEntity()); - await service.processPendingIncomingWebhooks(); - - expect(service.completeCronJob).toHaveBeenCalledWith( - cronJobEntityMock as any, + webhookIncomingService.processPendingIncomingWebhooks.mockRejectedValue( + new Error('Processing error'), ); - }); - - it('should handle duplicate errors when creating escrow completion tracking and not update entity status', async () => { - const mockEntity = { id: 1, status: EscrowCompletionTrackingStatus.PAID }; - - const updateOneMock = jest - .spyOn(escrowCompletionTrackingRepository, 'updateOne') - .mockResolvedValue(mockEntity as any); - - const createEscrowCompletionTrackingMock = jest - .spyOn( - escrowCompletionTrackingService, - 'createEscrowCompletionTracking', - ) - .mockImplementation(() => { - throw new DatabaseError( - 'Duplicate entry error', - PostgresErrorCodes.Duplicated, - ); - }); await service.processPendingIncomingWebhooks(); - expect(createEscrowCompletionTrackingMock).toHaveBeenCalled(); - expect(updateOneMock).not.toHaveBeenCalledWith({ - id: mockEntity.id, - status: EscrowCompletionTrackingStatus.COMPLETED, - }); - expect(completeCronJobMock).toHaveBeenCalled(); + expect(service.completeCronJob).toHaveBeenCalled(); }); }); describe('processPendingEscrowCompletion', () => { - let startCronJobMock: jest.SpyInstance; - let completeCronJobMock: jest.SpyInstance; - - beforeEach(() => { - startCronJobMock = jest - .spyOn(service, 'startCronJob') - .mockResolvedValue({} as CronJobEntity); - completeCronJobMock = jest - .spyOn(service, 'completeCronJob') - .mockResolvedValue({} as CronJobEntity); - - jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); - - EscrowClient.build = jest.fn().mockResolvedValue({ - getStatus: jest.fn().mockResolvedValue(EscrowStatus.Pending), - }); - }); - it('should skip processing if a cron job is already running', async () => { jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(true); await service.processPendingEscrowCompletion(); - expect(startCronJobMock).not.toHaveBeenCalled(); + expect( + escrowCompletionService.processPendingEscrowCompletion, + ).not.toHaveBeenCalled(); }); - it('should start and complete the cron job successfully', async () => { - const mockEntity = { - id: 1, - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - status: EscrowCompletionTrackingStatus.PENDING, - }; + it('should process pending escrow completion and complete the cron job', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); jest - .spyOn(escrowCompletionTrackingRepository, 'findByStatus') - .mockResolvedValue([mockEntity as any]); - - const saveResultsMock = jest - .spyOn(payoutService, 'saveResults') - .mockResolvedValueOnce({ url: MOCK_FILE_URL, hash: MOCK_FILE_HASH }); - - const updateOneMock = jest - .spyOn(escrowCompletionTrackingRepository, 'updateOne') - .mockResolvedValue(mockEntity as any); + .spyOn(service, 'startCronJob') + .mockResolvedValue(new CronJobEntity()); + jest + .spyOn(service, 'completeCronJob') + .mockResolvedValue(new CronJobEntity()); await service.processPendingEscrowCompletion(); - expect(startCronJobMock).toHaveBeenCalledWith( - CronJobType.ProcessPendingEscrowCompletionTracking, - ); - expect(saveResultsMock).toHaveBeenCalledWith( - mockEntity.chainId, - mockEntity.escrowAddress, - ); - expect(payoutService.executePayouts).toHaveBeenCalledWith( - mockEntity.chainId, - mockEntity.escrowAddress, - MOCK_FILE_URL, - MOCK_FILE_HASH, - ); - expect(updateOneMock).toHaveBeenCalledTimes(2); - expect(completeCronJobMock).toHaveBeenCalled(); + expect( + escrowCompletionService.processPendingEscrowCompletion, + ).toHaveBeenCalled(); + expect(service.startCronJob).toHaveBeenCalled(); + expect(service.completeCronJob).toHaveBeenCalled(); }); - it('should handle errors and continue processing other entities', async () => { - const mockEntity1 = { - id: 1, - status: EscrowCompletionTrackingStatus.PENDING, - }; - const mockEntity2 = { - id: 2, - status: EscrowCompletionTrackingStatus.PENDING, - }; - + it('should complete the cron job after processing', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); jest - .spyOn(escrowCompletionTrackingRepository, 'findByStatus') - .mockResolvedValue([mockEntity1 as any, mockEntity2 as any]); - + .spyOn(service, 'startCronJob') + .mockResolvedValue(new CronJobEntity()); jest - .spyOn(escrowCompletionTrackingRepository, 'updateOne') - .mockImplementationOnce(() => { - throw new Error('Test error'); - }) // Fails for mockEntity1 - .mockResolvedValue(mockEntity2 as any); // Succeeds for mockEntity2 - - const handleErrorMock = jest.spyOn( - escrowCompletionTrackingService, - 'handleEscrowCompletionTrackingError', + .spyOn(service, 'completeCronJob') + .mockResolvedValue(new CronJobEntity()); + + escrowCompletionService.processPendingEscrowCompletion.mockRejectedValue( + new Error('Processing error'), ); await service.processPendingEscrowCompletion(); - // Verify cron job completes - expect(completeCronJobMock).toHaveBeenCalled(); - - expect(handleErrorMock).toHaveBeenCalledWith( - mockEntity1, - expect.stringContaining(ErrorWebhook.PendingProcessingFailed), - ); - - // Ensure the second entity is processed successfully - expect(escrowCompletionTrackingRepository.updateOne).toHaveBeenCalledWith( - mockEntity2, - ); + expect(service.completeCronJob).toHaveBeenCalled(); }); }); describe('processPaidEscrowCompletion', () => { - let startCronJobMock: jest.SpyInstance; - let completeCronJobMock: jest.SpyInstance; - let assessReputationScoresMock: jest.SpyInstance; - - beforeEach(() => { - startCronJobMock = jest - .spyOn(service, 'startCronJob') - .mockResolvedValue({} as CronJobEntity); - completeCronJobMock = jest - .spyOn(service, 'completeCronJob') - .mockResolvedValue({} as CronJobEntity); - - jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); - assessReputationScoresMock = jest - .spyOn(reputationService, 'assessReputationScores') - .mockResolvedValue(); - - EscrowClient.build = jest.fn().mockResolvedValue({ - getStatus: jest.fn().mockResolvedValue(EscrowStatus.Paid), - complete: jest.fn().mockResolvedValue(true), - getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - }); - }); - it('should skip processing if a cron job is already running', async () => { jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(true); await service.processPaidEscrowCompletion(); - expect(startCronJobMock).not.toHaveBeenCalled(); - expect(assessReputationScoresMock).not.toHaveBeenCalled(); + expect( + escrowCompletionService.processPaidEscrowCompletion, + ).not.toHaveBeenCalled(); }); - it('should start, process, and complete cron job for entities with PAID status', async () => { - const mockEntity = { id: 1, status: EscrowCompletionTrackingStatus.PAID }; - + it('should process paid escrow completion and complete the cron job', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); jest - .spyOn(escrowCompletionTrackingRepository, 'findByStatus') - .mockResolvedValue([mockEntity as any]); - - const updateOneMock = jest - .spyOn(escrowCompletionTrackingRepository, 'updateOne') - .mockResolvedValue(mockEntity as any); - - await service.processPaidEscrowCompletion(); - - expect(startCronJobMock).toHaveBeenCalledWith( - CronJobType.ProcessPaidEscrowCompletionTracking, - ); - expect(updateOneMock).toHaveBeenCalledWith({ - id: mockEntity.id, - status: EscrowCompletionTrackingStatus.COMPLETED, - }); - expect(completeCronJobMock).toHaveBeenCalled(); - expect(assessReputationScoresMock).toHaveBeenCalledTimes(1); - }); - - it('should handle errors during entity processing without skipping remaining entities', async () => { - const mockEntity1 = { - id: 1, - status: EscrowCompletionTrackingStatus.PAID, - }; - const mockEntity2 = { - id: 2, - status: EscrowCompletionTrackingStatus.PAID, - }; - + .spyOn(service, 'startCronJob') + .mockResolvedValue(new CronJobEntity()); jest - .spyOn(escrowCompletionTrackingRepository, 'findByStatus') - .mockResolvedValue([mockEntity1 as any, mockEntity2 as any]); - - const updateOneMock = jest - .spyOn(escrowCompletionTrackingRepository, 'updateOne') - .mockImplementationOnce(() => { - throw new Error('Test error'); - }) - .mockResolvedValueOnce(mockEntity2 as any); + .spyOn(service, 'completeCronJob') + .mockResolvedValue(new CronJobEntity()); await service.processPaidEscrowCompletion(); - expect(updateOneMock).toHaveBeenCalledTimes(3); - expect(completeCronJobMock).toHaveBeenCalled(); - expect(assessReputationScoresMock).toHaveBeenCalledTimes(2); + expect( + escrowCompletionService.processPaidEscrowCompletion, + ).toHaveBeenCalled(); + expect(service.startCronJob).toHaveBeenCalled(); + expect(service.completeCronJob).toHaveBeenCalled(); }); - it('should complete cron job even if no PAID entities are found', async () => { + it('should complete the cron job after processing', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); jest - .spyOn(escrowCompletionTrackingRepository, 'findByStatus') - .mockResolvedValue([]); - - await service.processPaidEscrowCompletion(); - - expect(startCronJobMock).toHaveBeenCalled(); - expect(completeCronJobMock).toHaveBeenCalled(); - expect(assessReputationScoresMock).not.toHaveBeenCalled(); - }); - - it('should not call completeCronJob if startCronJob fails', async () => { - startCronJobMock.mockRejectedValue(new Error('Start cron job failed')); + .spyOn(service, 'startCronJob') + .mockResolvedValue(new CronJobEntity()); + jest + .spyOn(service, 'completeCronJob') + .mockResolvedValue(new CronJobEntity()); - await expect(service.processPaidEscrowCompletion()).rejects.toThrow( - 'Start cron job failed', + escrowCompletionService.processPaidEscrowCompletion.mockRejectedValue( + new Error('Processing error'), ); - expect(startCronJobMock).toHaveBeenCalled(); - expect(completeCronJobMock).not.toHaveBeenCalled(); - }); - - it('should handle duplicate errors when creating outgoing webhooks and not update entity status', async () => { - const mockEntity = { id: 1, status: EscrowCompletionTrackingStatus.PAID }; - - jest - .spyOn(escrowCompletionTrackingRepository, 'findByStatus') - .mockResolvedValue([mockEntity as any]); - - const updateOneMock = jest - .spyOn(escrowCompletionTrackingRepository, 'updateOne') - .mockResolvedValue(mockEntity as any); - - const createOutgoingWebhookMock = jest - .spyOn(webhookService, 'createOutgoingWebhook') - .mockImplementation(() => { - throw new DatabaseError( - 'Duplicate entry error', - PostgresErrorCodes.Duplicated, - ); - }); - await service.processPaidEscrowCompletion(); - expect(createOutgoingWebhookMock).toHaveBeenCalled(); - expect(updateOneMock).not.toHaveBeenCalledWith({ - id: mockEntity.id, - status: EscrowCompletionTrackingStatus.COMPLETED, - }); - expect(completeCronJobMock).toHaveBeenCalled(); + expect(service.completeCronJob).toHaveBeenCalled(); }); }); describe('processPendingOutgoingWebhooks', () => { - let sendWebhookMock: any; - let cronJobEntityMock: Partial; - let webhookEntity1: Partial, - webhookEntity2: Partial; - - beforeEach(() => { - cronJobEntityMock = { - cronJobType: CronJobType.ProcessPendingOutgoingWebhook, - startedAt: new Date(), - }; - - webhookEntity1 = { - id: 1, - payload: { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - eventType: EventType.ESCROW_COMPLETED, - }, - hash: MOCK_FILE_HASH, - url: MOCK_FILE_URL, - status: WebhookOutgoingStatus.PENDING, - waitUntil: new Date(), - retriesCount: 0, - }; - - webhookEntity2 = { - id: 2, - payload: { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - eventType: EventType.ESCROW_COMPLETED, - }, - hash: MOCK_FILE_HASH, - url: MOCK_FILE_URL, - status: WebhookOutgoingStatus.PENDING, - waitUntil: new Date(), - retriesCount: 0, - }; - - jest - .spyOn(webhookOutgoingRepository, 'findByStatus') - .mockResolvedValue([webhookEntity1 as any, webhookEntity2 as any]); - - jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); - - jest.spyOn(repository, 'findOneByType').mockResolvedValue(null); - jest - .spyOn(repository, 'createUnique') - .mockResolvedValue(cronJobEntityMock as any); - - sendWebhookMock = jest.spyOn(webhookService as any, 'sendWebhook'); - sendWebhookMock.mockResolvedValue(); - }); - - afterEach(() => { - jest.restoreAllMocks(); - }); - - it('should not run if cron job is already running', async () => { - jest.spyOn(service, 'isCronJobRunning').mockResolvedValueOnce(true); - - const startCronJobMock = jest.spyOn(service, 'startCronJob'); + it('should skip processing if a cron job is already running', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(true); await service.processPendingOutgoingWebhooks(); - expect(startCronJobMock).not.toHaveBeenCalled(); + expect( + webhookOutgoingService.processPendingOutgoingWebhooks, + ).not.toHaveBeenCalled(); }); - it('should create cron job entity to lock the process', async () => { + it('should process pending outgoing webhooks and complete the cron job', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); jest .spyOn(service, 'startCronJob') - .mockResolvedValueOnce(cronJobEntityMock as any); - - await service.processPendingOutgoingWebhooks(); - - expect(service.startCronJob).toHaveBeenCalledWith( - CronJobType.ProcessPendingOutgoingWebhook, - ); - }); - - it('should increase retriesCount by 1 if sending webhook fails', async () => { - sendWebhookMock.mockRejectedValueOnce(new Error()); - await service.processPendingOutgoingWebhooks(); - - expect(webhookOutgoingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity1.status).toBe(WebhookOutgoingStatus.PENDING); - expect(webhookEntity1.retriesCount).toBe(1); - expect(webhookEntity1.waitUntil).toBeInstanceOf(Date); - }); - - it('should mark webhook as failed if retriesCount exceeds threshold', async () => { - sendWebhookMock.mockRejectedValueOnce(new Error()); - - webhookEntity1.retriesCount = MOCK_MAX_RETRY_COUNT; + .mockResolvedValue(new CronJobEntity()); + jest + .spyOn(service, 'completeCronJob') + .mockResolvedValue(new CronJobEntity()); await service.processPendingOutgoingWebhooks(); - expect(webhookOutgoingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity1.status).toBe(WebhookOutgoingStatus.FAILED); + expect( + webhookOutgoingService.processPendingOutgoingWebhooks, + ).toHaveBeenCalled(); + expect(service.startCronJob).toHaveBeenCalled(); + expect(service.completeCronJob).toHaveBeenCalled(); }); - it('should complete the cron job entity to unlock', async () => { + it('should complete the cron job after processing', async () => { + jest.spyOn(service, 'isCronJobRunning').mockResolvedValue(false); + jest + .spyOn(service, 'startCronJob') + .mockResolvedValue(new CronJobEntity()); jest .spyOn(service, 'completeCronJob') - .mockResolvedValueOnce(cronJobEntityMock as any); + .mockResolvedValue(new CronJobEntity()); + + webhookOutgoingService.processPendingOutgoingWebhooks.mockRejectedValue( + new Error('Processing error'), + ); await service.processPendingOutgoingWebhooks(); - expect(service.completeCronJob).toHaveBeenCalledWith( - cronJobEntityMock as any, - ); + expect(service.completeCronJob).toHaveBeenCalled(); }); }); }); diff --git a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts index 05e7d5a7c2..77b4d1482d 100644 --- a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts @@ -1,31 +1,15 @@ import { HttpStatus, Injectable, Logger } from '@nestjs/common'; -import { v4 as uuidv4 } from 'uuid'; -import * as crypto from 'crypto'; -import stringify from 'json-stable-stringify'; import { CronJobType } from '../../common/enums/cron-job'; -import { ErrorCronJob, ErrorWebhook } from '../../common/constants/errors'; +import { ErrorCronJob } from '../../common/constants/errors'; import { CronJobEntity } from './cron-job.entity'; import { CronJobRepository } from './cron-job.repository'; -import { WebhookService } from '../webhook/webhook.service'; -import { - EscrowCompletionTrackingStatus, - EventType, - WebhookIncomingStatus, - WebhookOutgoingStatus, -} from '../../common/enums/webhook'; -import { PayoutService } from '../payout/payout.service'; -import { ReputationService } from '../reputation/reputation.service'; -import { Web3Service } from '../web3/web3.service'; -import { EscrowClient, EscrowStatus, OperatorUtils } from '@human-protocol/sdk'; import { ControlledError } from '../../common/errors/controlled'; import { Cron } from '@nestjs/schedule'; -import { WebhookIncomingRepository } from '../webhook/webhook-incoming.repository'; -import { WebhookOutgoingRepository } from '../webhook/webhook-outgoing.repository'; -import { EscrowCompletionTrackingRepository } from '../escrow-completion-tracking/escrow-completion-tracking.repository'; -import { EscrowCompletionTrackingService } from '../escrow-completion-tracking/escrow-completion-tracking.service'; -import { isDuplicatedError } from '../../common/utils/database'; +import { WebhookIncomingService } from '../webhook/webhook-incoming.service'; +import { WebhookOutgoingService } from '../webhook/webhook-outgoing.service'; +import { EscrowCompletionService } from '../escrow-completion/escrow-completion.service'; @Injectable() export class CronJobService { @@ -33,14 +17,9 @@ export class CronJobService { constructor( private readonly cronJobRepository: CronJobRepository, - private readonly webhookService: WebhookService, - private readonly escrowCompletionTrackingService: EscrowCompletionTrackingService, - private readonly reputationService: ReputationService, - private readonly webhookIncomingRepository: WebhookIncomingRepository, - private readonly webhookOutgoingRepository: WebhookOutgoingRepository, - private readonly escrowCompletionTrackingRepository: EscrowCompletionTrackingRepository, - private readonly payoutService: PayoutService, - private readonly web3Service: Web3Service, + private readonly webhookIncomingService: WebhookIncomingService, + private readonly webhookOutgoingService: WebhookOutgoingService, + private readonly escrowCompletionService: EscrowCompletionService, ) {} /** @@ -118,45 +97,7 @@ export class CronJobService { ); try { - const webhookEntities = await this.webhookIncomingRepository.findByStatus( - WebhookIncomingStatus.PENDING, - ); - - for (const webhookEntity of webhookEntities) { - try { - const { chainId, escrowAddress } = webhookEntity; - - await this.escrowCompletionTrackingService.createEscrowCompletionTracking( - chainId, - escrowAddress, - ); - - webhookEntity.status = WebhookIncomingStatus.COMPLETED; - await this.webhookIncomingRepository.updateOne(webhookEntity); - } catch (err) { - const errorId = uuidv4(); - const failureDetail = `${ErrorWebhook.PendingProcessingFailed} (Error ID: ${errorId})`; - - if (isDuplicatedError(err)) { - // Handle duplicated error: log and mark as completed - this.logger.warn( - `Duplicate tracking entity for escrowAddress: ${webhookEntity.escrowAddress}. Marking webhook as completed.`, - ); - webhookEntity.status = WebhookIncomingStatus.COMPLETED; - await this.webhookIncomingRepository.updateOne(webhookEntity); - } else { - // Handle other errors (general failure) - this.logger.error( - `Error processing webhook. Error ID: ${errorId}, Webhook ID: ${webhookEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, - ); - await this.webhookService.handleWebhookIncomingError( - webhookEntity, - failureDetail, - ); - } - continue; - } - } + await this.webhookIncomingService.processPendingIncomingWebhooks(); } catch (e) { this.logger.error(e); } @@ -167,7 +108,7 @@ export class CronJobService { @Cron('*/2 * * * *') /** - * Processes pending escrow completion tracking webhooks to manage escrow lifecycle actions. + * Processes pending escrow completion tracking to manage escrow lifecycle actions. * Checks escrow status and, if appropriate, saves results and initiates payouts. * Handles errors and logs detailed messages. * @returns {Promise} A promise that resolves when the operation is complete. @@ -187,61 +128,7 @@ export class CronJobService { ); try { - const escrowCompletionTrackingEntities = - await this.escrowCompletionTrackingRepository.findByStatus( - EscrowCompletionTrackingStatus.PENDING, - ); - - for (const escrowCompletionTrackingEntity of escrowCompletionTrackingEntities) { - try { - const signer = this.web3Service.getSigner( - escrowCompletionTrackingEntity.chainId, - ); - const escrowClient = await EscrowClient.build(signer); - - const escrowStatus = await escrowClient.getStatus( - escrowCompletionTrackingEntity.escrowAddress, - ); - if (escrowStatus === EscrowStatus.Pending) { - if (!escrowCompletionTrackingEntity.finalResultsUrl) { - const { url, hash } = await this.payoutService.saveResults( - escrowCompletionTrackingEntity.chainId, - escrowCompletionTrackingEntity.escrowAddress, - ); - - escrowCompletionTrackingEntity.finalResultsUrl = url; - escrowCompletionTrackingEntity.finalResultsHash = hash; - await this.escrowCompletionTrackingRepository.updateOne( - escrowCompletionTrackingEntity, - ); - } - - await this.payoutService.executePayouts( - escrowCompletionTrackingEntity.chainId, - escrowCompletionTrackingEntity.escrowAddress, - escrowCompletionTrackingEntity.finalResultsUrl, - escrowCompletionTrackingEntity.finalResultsHash, - ); - } - - escrowCompletionTrackingEntity.status = - EscrowCompletionTrackingStatus.PAID; - await this.escrowCompletionTrackingRepository.updateOne( - escrowCompletionTrackingEntity, - ); - } catch (err) { - const errorId = uuidv4(); - const failureDetail = `${ErrorWebhook.PendingProcessingFailed} (Error ID: ${errorId})`; - this.logger.error( - `Error processing escrow completion tracking. Error ID: ${errorId}, Escrow completion tracking ID: ${escrowCompletionTrackingEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, - ); - await this.escrowCompletionTrackingService.handleEscrowCompletionTrackingError( - escrowCompletionTrackingEntity, - failureDetail, - ); - continue; - } - } + await this.escrowCompletionService.processPendingEscrowCompletion(); } catch (e) { this.logger.error(e); } @@ -252,7 +139,7 @@ export class CronJobService { @Cron('*/2 * * * *') /** - * Processes paid escrow completion tracking webhooks, finalizing escrow operations if completed. + * Processes paid escrow completion tracking, finalizing escrow operations if completed. * Notifies oracles via callbacks, logs errors, and updates tracking status. * @returns {Promise} A promise that resolves when the paid escrow tracking has been processed. */ @@ -271,130 +158,12 @@ export class CronJobService { ); try { - const escrowCompletionTrackingEntities = - await this.escrowCompletionTrackingRepository.findByStatus( - EscrowCompletionTrackingStatus.PAID, - ); - - // TODO: Add DB transactions - for (const escrowCompletionTrackingEntity of escrowCompletionTrackingEntities) { - try { - const { chainId, escrowAddress } = escrowCompletionTrackingEntity; - - const signer = this.web3Service.getSigner(chainId); - const escrowClient = await EscrowClient.build(signer); - - const escrowStatus = await escrowClient.getStatus(escrowAddress); - if (escrowStatus === EscrowStatus.Paid) { - await escrowClient.complete(escrowAddress, { - gasPrice: await this.web3Service.calculateGasPrice(chainId), - }); - - // TODO: Technically it's possible that the escrow completion could occur before the reputation scores are assessed, - // and the app might go down during this window. Currently, there isn’t a clear approach to handle this situation. - // Consider revisiting this section to explore potential solutions to improve resilience in such scenarios. - await this.reputationService.assessReputationScores( - chainId, - escrowAddress, - ); - } - - const callbackUrls = [ - ( - await OperatorUtils.getLeader( - chainId, - await escrowClient.getJobLauncherAddress(escrowAddress), - ) - ).webhookUrl, - ( - await OperatorUtils.getLeader( - chainId, - await escrowClient.getExchangeOracleAddress(escrowAddress), - ) - ).webhookUrl, - // Temporarily disable sending webhook to Recording Oracle - // ( - // await OperatorUtils.getLeader( - // chainId, - // await escrowClient.getRecordingOracleAddress(escrowAddress), - // ) - // ).webhookUrl, - ]; - - let allWebhooksCreated = true; - - for (const url of callbackUrls) { - if (!url) { - throw new ControlledError( - ErrorWebhook.UrlNotFound, - HttpStatus.NOT_FOUND, - ); - } - - const payload = { - chainId, - escrowAddress, - eventType: EventType.ESCROW_COMPLETED, - }; - - const hash = crypto - .createHash('sha1') - .update(stringify({ payload, url })) - .digest('hex'); - - try { - await this.webhookService.createOutgoingWebhook( - payload, - hash, - url, - ); - } catch (err) { - if (isDuplicatedError(err)) { - this.logger.warn( - `Duplicate outgoing webhook for escrowAddress: ${escrowAddress}. Webhook creation skipped, but will not complete escrow until all URLs are successful.`, - ); - continue; - } else { - const errorId = uuidv4(); - const failureDetail = `${ErrorWebhook.PendingProcessingFailed} (Error ID: ${errorId})`; - this.logger.error( - `Error creating outgoing webhook. Error ID: ${errorId}, Escrow Address: ${escrowAddress}, Reason: ${failureDetail}, Message: ${err.message}`, - ); - await this.escrowCompletionTrackingService.handleEscrowCompletionTrackingError( - escrowCompletionTrackingEntity, - failureDetail, - ); - allWebhooksCreated = false; - break; - } - } - } - - // Only set the status to COMPLETED if all webhooks were created successfully - if (allWebhooksCreated) { - escrowCompletionTrackingEntity.status = - EscrowCompletionTrackingStatus.COMPLETED; - await this.escrowCompletionTrackingRepository.updateOne( - escrowCompletionTrackingEntity, - ); - } - } catch (err) { - const errorId = uuidv4(); - const failureDetail = `${ErrorWebhook.PendingProcessingFailed} (Error ID: ${errorId})`; - this.logger.error( - `Error processing escrow completion tracking. Error ID: ${errorId}, Escrow completion tracking ID: ${escrowCompletionTrackingEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, - ); - await this.escrowCompletionTrackingService.handleEscrowCompletionTrackingError( - escrowCompletionTrackingEntity, - failureDetail, - ); - } - } + await this.escrowCompletionService.processPaidEscrowCompletion(); } catch (e) { this.logger.error(e); } - this.logger.log('Pending escrow completion tracking STOP'); + this.logger.log('Paid escrow completion tracking STOP'); await this.completeCronJob(cronJob); } @@ -405,13 +174,8 @@ export class CronJobService { * @returns {Promise} A promise that resolves once all pending outgoing webhooks have been processed. */ public async processPendingOutgoingWebhooks(): Promise { - const isCronJobRunning = await this.isCronJobRunning( - CronJobType.ProcessPendingOutgoingWebhook, - ); - - if (isCronJobRunning) { + if (await this.isCronJobRunning(CronJobType.ProcessPendingOutgoingWebhook)) return; - } this.logger.log('Pending outgoing webhooks START'); const cronJob = await this.startCronJob( @@ -419,32 +183,9 @@ export class CronJobService { ); try { - const webhookEntities = await this.webhookOutgoingRepository.findByStatus( - WebhookOutgoingStatus.PENDING, - ); - - for (const webhookEntity of webhookEntities) { - try { - const { url, payload } = webhookEntity; - - await this.webhookService.sendWebhook(url, payload); - } catch (err) { - const errorId = uuidv4(); - const failureDetail = `${ErrorWebhook.PendingProcessingFailed} (Error ID: ${errorId})`; - this.logger.error( - `Error processing pending outgoing webhook. Error ID: ${errorId}, Webhook ID: ${webhookEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, - ); - await this.webhookService.handleWebhookOutgoingError( - webhookEntity, - failureDetail, - ); - continue; - } - webhookEntity.status = WebhookOutgoingStatus.SENT; - await this.webhookOutgoingRepository.updateOne(webhookEntity); - } - } catch (e) { - this.logger.error(e); + await this.webhookOutgoingService.processPendingOutgoingWebhooks(); + } catch (err) { + this.logger.error(err); } this.logger.log('Pending outgoing webhooks STOP'); diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.module.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.module.ts deleted file mode 100644 index e655fdc0d3..0000000000 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Logger, Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { EscrowCompletionTrackingEntity } from './escrow-completion-tracking.entity'; -import { EscrowCompletionTrackingRepository } from './escrow-completion-tracking.repository'; -import { EscrowCompletionTrackingService } from './escrow-completion-tracking.service'; - -@Module({ - imports: [ - TypeOrmModule.forFeature([EscrowCompletionTrackingEntity]), - ConfigModule, - ], - providers: [ - Logger, - EscrowCompletionTrackingService, - EscrowCompletionTrackingRepository, - ], - exports: [EscrowCompletionTrackingService], -}) -export class EscrowCompletionTrackingModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.spec.ts deleted file mode 100644 index bb99458786..0000000000 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.spec.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { createMock } from '@golevelup/ts-jest'; -import { ChainId } from '@human-protocol/sdk'; -import { HttpService } from '@nestjs/axios'; -import { ConfigService } from '@nestjs/config'; -import { Test } from '@nestjs/testing'; -import { - MOCK_ADDRESS, - MOCK_BACKOFF_INTERVAL_SECONDS, - MOCK_MAX_RETRY_COUNT, - MOCK_PRIVATE_KEY, - mockConfig, -} from '../../../test/constants'; -import { EscrowCompletionTrackingStatus } from '../../common/enums/webhook'; -import { Web3Service } from '../web3/web3.service'; -import { EscrowCompletionTrackingRepository } from './escrow-completion-tracking.repository'; -import { EscrowCompletionTrackingEntity } from './escrow-completion-tracking.entity'; -import { Web3ConfigService } from '../../common/config/web3-config.service'; -import { ServerConfigService } from '../../common/config/server-config.service'; -import { EscrowCompletionTrackingService } from './escrow-completion-tracking.service'; - -jest.mock('@human-protocol/sdk', () => ({ - ...jest.requireActual('@human-protocol/sdk'), - EscrowClient: { - build: jest.fn(), - }, - KVStoreClient: { - build: jest.fn(), - }, -})); - -jest.mock('../../common/utils/backoff', () => ({ - ...jest.requireActual('../../common/utils/backoff'), - calculateExponentialBackoffMs: jest - .fn() - .mockReturnValue(MOCK_BACKOFF_INTERVAL_SECONDS * 1000), -})); - -describe('escrowCompletionTrackingService', () => { - let escrowCompletionTrackingService: EscrowCompletionTrackingService, - escrowCompletionTrackingRepository: EscrowCompletionTrackingRepository, - web3ConfigService: Web3ConfigService; - - const signerMock = { - address: MOCK_ADDRESS, - getNetwork: jest.fn().mockResolvedValue({ chainId: 1 }), - }; - - beforeEach(async () => { - const moduleRef = await Test.createTestingModule({ - providers: [ - { - provide: ConfigService, - useValue: { - get: jest.fn((key: string) => mockConfig[key]), - getOrThrow: jest.fn((key: string) => { - if (!mockConfig[key]) { - throw new Error(`Configuration key "${key}" does not exist`); - } - return mockConfig[key]; - }), - }, - }, - EscrowCompletionTrackingService, - { - provide: Web3Service, - useValue: { - getSigner: jest.fn().mockReturnValue(signerMock), - }, - }, - { - provide: EscrowCompletionTrackingRepository, - useValue: createMock(), - }, - Web3ConfigService, - ServerConfigService, - { provide: HttpService, useValue: createMock() }, - ], - }).compile(); - - escrowCompletionTrackingService = - moduleRef.get( - EscrowCompletionTrackingService, - ); - escrowCompletionTrackingRepository = moduleRef.get( - EscrowCompletionTrackingRepository, - ); - web3ConfigService = moduleRef.get(Web3ConfigService); - - jest - .spyOn(web3ConfigService, 'privateKey', 'get') - .mockReturnValue(MOCK_PRIVATE_KEY); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('createEscrowCompletionTracking', () => { - const escrowCompletionTrackingEntity: Partial = - { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - status: EscrowCompletionTrackingStatus.PENDING, - waitUntil: new Date(), - retriesCount: 0, - }; - - it('should successfully create escrow completion tracking with valid DTO', async () => { - jest - .spyOn(escrowCompletionTrackingRepository, 'createUnique') - .mockResolvedValue( - escrowCompletionTrackingEntity as EscrowCompletionTrackingEntity, - ); - - await escrowCompletionTrackingService.createEscrowCompletionTracking( - ChainId.LOCALHOST, - MOCK_ADDRESS, - ); - - expect( - escrowCompletionTrackingRepository.createUnique, - ).toHaveBeenCalledWith( - expect.objectContaining({ - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - status: EscrowCompletionTrackingStatus.PENDING, - retriesCount: 0, - waitUntil: expect.any(Date), - }), - ); - }); - }); - - describe('handleEscrowCompletionTrackingError', () => { - it('should set escrow completion tracking status to FAILED if retries exceed threshold', async () => { - const escrowCompletionTrackingEntity: Partial = - { - id: 1, - status: EscrowCompletionTrackingStatus.PENDING, - retriesCount: MOCK_MAX_RETRY_COUNT, - }; - await ( - escrowCompletionTrackingService as any - ).handleEscrowCompletionTrackingError( - escrowCompletionTrackingEntity, - new Error('Sample error'), - ); - expect(escrowCompletionTrackingRepository.updateOne).toHaveBeenCalled(); - expect(escrowCompletionTrackingEntity.status).toBe( - EscrowCompletionTrackingStatus.FAILED, - ); - }); - - it('should increment retries count if below threshold and set waitUntil to a future date', async () => { - const escrowCompletionTrackingEntity: Partial = - { - id: 1, - status: EscrowCompletionTrackingStatus.PENDING, - retriesCount: 0, - waitUntil: new Date(), - }; - await ( - escrowCompletionTrackingService as any - ).handleEscrowCompletionTrackingError( - escrowCompletionTrackingEntity, - new Error('Sample error'), - ); - expect(escrowCompletionTrackingRepository.updateOne).toHaveBeenCalled(); - expect(escrowCompletionTrackingEntity.status).toBe( - EscrowCompletionTrackingStatus.PENDING, - ); - expect(escrowCompletionTrackingEntity.retriesCount).toBe(1); - expect(escrowCompletionTrackingEntity.waitUntil).toBeInstanceOf(Date); - - const now = new Date(); - const waitUntil = escrowCompletionTrackingEntity.waitUntil as Date; - expect(waitUntil).toBeInstanceOf(Date); - expect(waitUntil.getTime()).toBeGreaterThan(now.getTime()); - }); - }); -}); diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.ts deleted file mode 100644 index 7659cb54fd..0000000000 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.service.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { Injectable } from '@nestjs/common'; -import { EscrowCompletionTrackingStatus } from '../../common/enums'; -import { ServerConfigService } from '../../common/config/server-config.service'; -import { EscrowCompletionTrackingRepository } from './escrow-completion-tracking.repository'; -import { EscrowCompletionTrackingEntity } from './escrow-completion-tracking.entity'; -import { ChainId } from '@human-protocol/sdk'; -import { calculateExponentialBackoffMs } from '../../common/utils/backoff'; -import { BACKOFF_INTERVAL_SECONDS } from '../../common/constants'; - -@Injectable() -export class EscrowCompletionTrackingService { - constructor( - private readonly escrowCompletionTrackingRepository: EscrowCompletionTrackingRepository, - public readonly serverConfigService: ServerConfigService, - ) {} - - /** - * Creates a tracking record for escrow completion in the repository. - * Sets initial status to 'PENDING'. - * @param {ChainId} chainId - The blockchain chain ID. - * @param {string} escrowAddress - The address of the escrow contract. - */ - public async createEscrowCompletionTracking( - chainId: ChainId, - escrowAddress: string, - ): Promise { - let escrowCompletionTrackingEntity = new EscrowCompletionTrackingEntity(); - escrowCompletionTrackingEntity.chainId = chainId; - escrowCompletionTrackingEntity.escrowAddress = escrowAddress; - escrowCompletionTrackingEntity.status = - EscrowCompletionTrackingStatus.PENDING; - escrowCompletionTrackingEntity.waitUntil = new Date(); - escrowCompletionTrackingEntity.retriesCount = 0; - - escrowCompletionTrackingEntity = - await this.escrowCompletionTrackingRepository.createUnique( - escrowCompletionTrackingEntity, - ); - } - - /** - * Handles errors that occur during escrow completion tracking. - * If retry count is below the maximum, increments retry count and reschedules; otherwise, marks as 'FAILED'. - * @param escrowCompletionTrackingEntity - The escrow tracking entity. - * @param failureDetail - Reason for the failure. - */ - public async handleEscrowCompletionTrackingError( - escrowCompletionTrackingEntity: EscrowCompletionTrackingEntity, - failureDetail: string, - ): Promise { - if ( - escrowCompletionTrackingEntity.retriesCount < - this.serverConfigService.maxRetryCount - ) { - const exponentialBackoff = calculateExponentialBackoffMs( - escrowCompletionTrackingEntity.retriesCount, - BACKOFF_INTERVAL_SECONDS, - ); - escrowCompletionTrackingEntity.waitUntil = new Date( - Date.now() + exponentialBackoff, - ); - escrowCompletionTrackingEntity.retriesCount += 1; - } else { - escrowCompletionTrackingEntity.failureDetail = failureDetail; - escrowCompletionTrackingEntity.status = - EscrowCompletionTrackingStatus.FAILED; - } - await this.escrowCompletionTrackingRepository.updateOne( - escrowCompletionTrackingEntity, - ); - } -} diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.entity.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.entity.ts similarity index 78% rename from packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.entity.ts rename to packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.entity.ts index f3e3207f51..a1eaa004c1 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.entity.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.entity.ts @@ -2,12 +2,12 @@ import { Column, Entity, Index } from 'typeorm'; import { NS } from '../../common/constants'; import { BaseEntity } from '../../database/base.entity'; -import { EscrowCompletionTrackingStatus } from '../../common/enums'; +import { EscrowCompletionStatus } from '../../common/enums'; import { ChainId } from '@human-protocol/sdk'; @Entity({ schema: NS, name: 'escrow_completion_tracking' }) @Index(['escrowAddress', 'chainId'], { unique: true }) -export class EscrowCompletionTrackingEntity extends BaseEntity { +export class EscrowCompletionEntity extends BaseEntity { @Column({ type: 'int' }) public chainId: ChainId; @@ -31,7 +31,7 @@ export class EscrowCompletionTrackingEntity extends BaseEntity { @Column({ type: 'enum', - enum: EscrowCompletionTrackingStatus, + enum: EscrowCompletionStatus, }) - public status: EscrowCompletionTrackingStatus; + public status: EscrowCompletionStatus; } diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.module.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.module.ts new file mode 100644 index 0000000000..eb9198f256 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.module.ts @@ -0,0 +1,25 @@ +import { Logger, Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { EscrowCompletionEntity } from './escrow-completion.entity'; +import { EscrowCompletionRepository } from './escrow-completion.repository'; +import { EscrowCompletionService } from './escrow-completion.service'; +import { PayoutModule } from '../payout/payout.module'; +import { ReputationModule } from '../reputation/reputation.module'; +import { Web3Module } from '../web3/web3.module'; +import { WebhookOutgoingModule } from '../webhook/webhook-outgoing.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([EscrowCompletionEntity]), + ConfigModule, + Web3Module, + PayoutModule, + ReputationModule, + WebhookOutgoingModule, + ], + providers: [Logger, EscrowCompletionService, EscrowCompletionRepository], + exports: [EscrowCompletionService], +}) +export class EscrowCompletionModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.repository.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.repository.ts similarity index 57% rename from packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.repository.ts rename to packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.repository.ts index 9523e0c769..2b2493264e 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion-tracking/escrow-completion-tracking.repository.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.repository.ts @@ -2,22 +2,22 @@ import { Injectable, Logger } from '@nestjs/common'; import { BaseRepository } from '../../database/base.repository'; import { DataSource, LessThanOrEqual } from 'typeorm'; import { ServerConfigService } from '../../common/config/server-config.service'; -import { EscrowCompletionTrackingEntity } from './escrow-completion-tracking.entity'; -import { EscrowCompletionTrackingStatus } from '../../common/enums'; +import { EscrowCompletionEntity } from './escrow-completion.entity'; +import { EscrowCompletionStatus } from '../../common/enums'; @Injectable() -export class EscrowCompletionTrackingRepository extends BaseRepository { - private readonly logger = new Logger(EscrowCompletionTrackingRepository.name); +export class EscrowCompletionRepository extends BaseRepository { + private readonly logger = new Logger(EscrowCompletionRepository.name); constructor( private dataSource: DataSource, public readonly serverConfigService: ServerConfigService, ) { - super(EscrowCompletionTrackingEntity, dataSource); + super(EscrowCompletionEntity, dataSource); } public findByStatus( - status: EscrowCompletionTrackingStatus, - ): Promise { + status: EscrowCompletionStatus, + ): Promise { return this.find({ where: { status, diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts new file mode 100644 index 0000000000..4971631222 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts @@ -0,0 +1,529 @@ +import { createMock } from '@golevelup/ts-jest'; +import { ChainId, EscrowClient, EscrowStatus } from '@human-protocol/sdk'; +import { HttpService } from '@nestjs/axios'; +import { ConfigService } from '@nestjs/config'; +import { Test } from '@nestjs/testing'; +import { + MOCK_ADDRESS, + MOCK_BACKOFF_INTERVAL_SECONDS, + MOCK_FILE_HASH, + MOCK_FILE_URL, + MOCK_MAX_RETRY_COUNT, + MOCK_PRIVATE_KEY, + MOCK_WEBHOOK_URL, + mockConfig, +} from '../../../test/constants'; +import { EscrowCompletionStatus } from '../../common/enums/webhook'; +import { Web3Service } from '../web3/web3.service'; +import { EscrowCompletionRepository } from './escrow-completion.repository'; +import { EscrowCompletionEntity } from './escrow-completion.entity'; +import { Web3ConfigService } from '../../common/config/web3-config.service'; +import { ServerConfigService } from '../../common/config/server-config.service'; +import { EscrowCompletionService } from './escrow-completion.service'; +import { PostgresErrorCodes } from '../../common/enums/database'; +import { WebhookOutgoingService } from '../webhook/webhook-outgoing.service'; +import { PayoutService } from '../payout/payout.service'; +import { ReputationService } from '../reputation/reputation.service'; +import { DatabaseError } from '../../common/errors/database'; +import { ErrorEscrowCompletion } from '../../common/constants/errors'; +import { WebhookOutgoingRepository } from '../webhook/webhook-outgoing.repository'; +import { StorageService } from '../storage/storage.service'; +import { ReputationRepository } from '../reputation/reputation.repository'; +import { ReputationConfigService } from '../../common/config/reputation-config.service'; +import { PGPConfigService } from '../../common/config/pgp-config.service'; +import { S3ConfigService } from '../../common/config/s3-config.service'; + +jest.mock('@human-protocol/sdk', () => ({ + ...jest.requireActual('@human-protocol/sdk'), + EscrowClient: { + build: jest.fn().mockImplementation(() => ({ + getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getRecordingOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + complete: jest.fn().mockResolvedValue(null), + getStatus: jest.fn(), + })), + }, + OperatorUtils: { + getLeader: jest.fn().mockImplementation(() => { + return { webhookUrl: MOCK_WEBHOOK_URL }; + }), + }, +})); + +jest.mock('../../common/utils/backoff', () => ({ + ...jest.requireActual('../../common/utils/backoff'), + calculateExponentialBackoffMs: jest + .fn() + .mockReturnValue(MOCK_BACKOFF_INTERVAL_SECONDS * 1000), +})); + +describe('escrowCompletionService', () => { + let escrowCompletionService: EscrowCompletionService, + escrowCompletionRepository: EscrowCompletionRepository, + web3ConfigService: Web3ConfigService, + webhookOutgoingService: WebhookOutgoingService, + reputationService: ReputationService, + payoutService: PayoutService; + + const signerMock = { + address: MOCK_ADDRESS, + getNetwork: jest.fn().mockResolvedValue({ chainId: 1 }), + }; + + const mockConfigService = { + get: jest.fn((key: string) => mockConfig[key]), + getOrThrow: jest.fn((key: string) => { + if (!mockConfig[key]) + throw new Error(`Configuration key "${key}" does not exist`); + return mockConfig[key]; + }), + }; + + // Mock Web3Service + const mockWeb3Service = { + getSigner: jest.fn().mockReturnValue(signerMock), + validateChainId: jest.fn().mockReturnValue(new Error()), + calculateGasPrice: jest.fn().mockReturnValue(1000n), + getOperatorAddress: jest.fn().mockReturnValue(MOCK_ADDRESS), + }; + + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + providers: [ + { + provide: ConfigService, + useValue: { + get: jest.fn((key: string) => mockConfig[key]), + getOrThrow: jest.fn((key: string) => { + if (!mockConfig[key]) { + throw new Error(`Configuration key "${key}" does not exist`); + } + return mockConfig[key]; + }), + }, + }, + EscrowCompletionService, + { + provide: Web3Service, + useValue: { + getSigner: jest.fn().mockReturnValue(signerMock), + }, + }, + { + provide: EscrowCompletionRepository, + useValue: createMock(), + }, + { + provide: WebhookOutgoingRepository, + useValue: createMock(), + }, + { + provide: ReputationRepository, + useValue: createMock(), + }, + // Mocked services + { + provide: ConfigService, + useValue: mockConfigService, + }, + { + provide: Web3Service, + useValue: mockWeb3Service, + }, + WebhookOutgoingService, + PayoutService, + ReputationService, + Web3ConfigService, + ServerConfigService, + StorageService, + ReputationConfigService, + S3ConfigService, + PGPConfigService, + { provide: HttpService, useValue: createMock() }, + ], + }).compile(); + + escrowCompletionService = moduleRef.get( + EscrowCompletionService, + ); + + webhookOutgoingService = moduleRef.get( + WebhookOutgoingService, + ); + payoutService = moduleRef.get(PayoutService); + reputationService = moduleRef.get(ReputationService); + escrowCompletionRepository = moduleRef.get(EscrowCompletionRepository); + web3ConfigService = moduleRef.get(Web3ConfigService); + + jest + .spyOn(web3ConfigService, 'privateKey', 'get') + .mockReturnValue(MOCK_PRIVATE_KEY); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('createEscrowCompletion', () => { + const escrowCompletionEntity: Partial = { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + status: EscrowCompletionStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + it('should successfully create escrow completion with valid DTO', async () => { + jest + .spyOn(escrowCompletionRepository, 'createUnique') + .mockResolvedValue(escrowCompletionEntity as EscrowCompletionEntity); + + await escrowCompletionService.createEscrowCompletion( + ChainId.LOCALHOST, + MOCK_ADDRESS, + ); + + expect(escrowCompletionRepository.createUnique).toHaveBeenCalledWith( + expect.objectContaining({ + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + status: EscrowCompletionStatus.PENDING, + retriesCount: 0, + waitUntil: expect.any(Date), + }), + ); + }); + }); + + describe('processPendingEscrowCompletion', () => { + let processResultsMock: any, executePayoutsMock: any; + let escrowCompletionEntity1: Partial, + escrowCompletionEntity2: Partial; + + beforeEach(() => { + escrowCompletionEntity1 = { + id: 1, + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + status: EscrowCompletionStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + escrowCompletionEntity2 = { + id: 2, + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + status: EscrowCompletionStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + EscrowClient.build = jest.fn().mockResolvedValue({ + getStatus: jest.fn().mockResolvedValue(EscrowStatus.Pending), + }); + + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([ + escrowCompletionEntity1 as any, + escrowCompletionEntity2 as any, + ]); + + processResultsMock = jest.spyOn(payoutService as any, 'processResults'); + processResultsMock.mockResolvedValue({ + url: MOCK_FILE_URL, + hash: MOCK_FILE_HASH, + }); + + executePayoutsMock = jest.spyOn(payoutService as any, 'executePayouts'); + executePayoutsMock.mockResolvedValue(); + }); + + it('should save results and execute payouts for all of the pending escrows completion', async () => { + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const updateOneMock = jest + .spyOn(escrowCompletionRepository, 'updateOne') + .mockResolvedValue(escrowCompletionEntity1 as any); + + await escrowCompletionService.processPendingEscrowCompletion(); + + expect(updateOneMock).toHaveBeenCalledTimes(2); + expect(processResultsMock).toHaveBeenCalledTimes(1); + expect(executePayoutsMock).toHaveBeenCalledTimes(1); + }); + + it('should handle errors and continue processing other entities', async () => { + escrowCompletionEntity1.finalResultsUrl = MOCK_FILE_URL; + escrowCompletionEntity2.finalResultsUrl = MOCK_FILE_URL; + + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([ + escrowCompletionEntity1 as any, + escrowCompletionEntity2 as any, + ]); + + jest + .spyOn(payoutService, 'executePayouts') + .mockImplementationOnce(() => { + throw new Error('Test error'); + }) // Fails for escrowCompletionEntity1 + .mockResolvedValue(); // Succeeds for escrowCompletionEntity2 + + await escrowCompletionService.processPendingEscrowCompletion(); + + // Verify that the first entity's error is handled, with retriesCount incremented to 1 + expect(escrowCompletionRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + id: escrowCompletionEntity1.id, + status: EscrowCompletionStatus.PENDING, + retriesCount: 1, // Retries count should be 1 after the error + }), + ); + // Verify that the second entity is successfully processed and its status is updated to 'PAID' + expect(escrowCompletionRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + id: escrowCompletionEntity2.id, + status: EscrowCompletionStatus.PAID, + retriesCount: 0, + }), + ); + }); + + it('should mark the escrow completion as FAILED if retries exceed the threshold', async () => { + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const error = new Error('Processing error'); + const loggerErrorSpy = jest.spyOn( + escrowCompletionService['logger'], + 'error', + ); + + escrowCompletionEntity1.retriesCount = MOCK_MAX_RETRY_COUNT; + processResultsMock.mockRejectedValueOnce(error); + + await escrowCompletionService.processPendingEscrowCompletion(); + + expect(escrowCompletionRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + status: EscrowCompletionStatus.FAILED, + retriesCount: MOCK_MAX_RETRY_COUNT, + }), + ); + expect(loggerErrorSpy).toHaveBeenCalledWith( + expect.stringContaining(`Message: ${error.message}`), + ); + }); + + it('should skip processResults when finalResultsUrl is not empty', async () => { + escrowCompletionEntity1.finalResultsUrl = MOCK_FILE_URL; + + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const updateOneMock = jest + .spyOn(escrowCompletionRepository, 'updateOne') + .mockResolvedValue(escrowCompletionEntity1 as any); + + await escrowCompletionService.processPendingEscrowCompletion(); + + expect(updateOneMock).toHaveBeenCalledTimes(1); + expect(processResultsMock).toHaveBeenCalledTimes(0); + expect(executePayoutsMock).toHaveBeenCalledTimes(1); + }); + + it('should skip executePayouts when escrowStatus is not pending', async () => { + EscrowClient.build = jest.fn().mockResolvedValue({ + getStatus: jest.fn().mockResolvedValue(EscrowStatus.Launched), + }); + + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const updateOneMock = jest + .spyOn(escrowCompletionRepository, 'updateOne') + .mockResolvedValue(escrowCompletionEntity1 as any); + + await escrowCompletionService.processPendingEscrowCompletion(); + + expect(updateOneMock).toHaveBeenCalledTimes(1); + expect(processResultsMock).toHaveBeenCalledTimes(0); + expect(executePayoutsMock).toHaveBeenCalledTimes(0); + }); + }); + + describe('processPaidEscrowCompletion', () => { + let assessReputationScoresMock: jest.SpyInstance, + createOutgoingWebhookMock: jest.SpyInstance; + let escrowCompletionEntity1: Partial, + escrowCompletionEntity2: Partial; + + beforeEach(() => { + escrowCompletionEntity1 = { + id: 1, + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + finalResultsUrl: MOCK_FILE_URL, + finalResultsHash: MOCK_FILE_HASH, + status: EscrowCompletionStatus.PAID, + waitUntil: new Date(), + retriesCount: 0, + }; + + escrowCompletionEntity2 = { + id: 2, + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + finalResultsUrl: MOCK_FILE_URL, + finalResultsHash: MOCK_FILE_HASH, + status: EscrowCompletionStatus.PAID, + waitUntil: new Date(), + retriesCount: 0, + }; + + assessReputationScoresMock = jest + .spyOn(reputationService, 'assessReputationScores') + .mockResolvedValue(); + + createOutgoingWebhookMock = jest + .spyOn(webhookOutgoingService, 'createOutgoingWebhook') + .mockResolvedValue(); + + EscrowClient.build = jest.fn().mockResolvedValue({ + getStatus: jest.fn().mockResolvedValue(EscrowStatus.Paid), + complete: jest.fn().mockResolvedValue(true), + getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getRecordingOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + }); + }); + + it('should assess reputation scores and create outgoing webhook for all of the paid escrows completion', async () => { + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const updateOneMock = jest + .spyOn(escrowCompletionRepository, 'updateOne') + .mockResolvedValue(escrowCompletionEntity1 as any); + + await escrowCompletionService.processPaidEscrowCompletion(); + + expect(updateOneMock).toHaveBeenCalledWith( + expect.objectContaining({ + id: escrowCompletionEntity1.id, + status: EscrowCompletionStatus.COMPLETED, + }), + ); + expect(assessReputationScoresMock).toHaveBeenCalledTimes(1); + }); + + it('should handle errors during entity processing without skipping remaining entities', async () => { + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([ + escrowCompletionEntity1 as any, + escrowCompletionEntity2 as any, + ]); + + const updateOneMock = jest + .spyOn(escrowCompletionRepository, 'updateOne') + .mockImplementationOnce(() => { + throw new Error('Test error'); + }) + .mockResolvedValueOnce(escrowCompletionEntity2 as any); + + await escrowCompletionService.processPaidEscrowCompletion(); + + expect(updateOneMock).toHaveBeenCalledTimes(3); + expect(assessReputationScoresMock).toHaveBeenCalledTimes(2); + }); + + it('should mark the escrow completion as FAILED if retries exceed the threshold', async () => { + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const error = new Error('Processing error'); + const loggerErrorSpy = jest.spyOn( + escrowCompletionService['logger'], + 'error', + ); + + escrowCompletionEntity1.retriesCount = MOCK_MAX_RETRY_COUNT; + assessReputationScoresMock.mockRejectedValueOnce(error); + + await escrowCompletionService.processPaidEscrowCompletion(); + + expect(escrowCompletionRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + status: EscrowCompletionStatus.FAILED, + retriesCount: MOCK_MAX_RETRY_COUNT, + }), + ); + expect(loggerErrorSpy).toHaveBeenCalledWith( + expect.stringContaining(`Message: ${error.message}`), + ); + }); + + it('should handle duplicate errors when creating outgoing webhooks and not update entity status', async () => { + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const updateOneMock = jest + .spyOn(escrowCompletionRepository, 'updateOne') + .mockResolvedValue(escrowCompletionEntity1 as any); + + createOutgoingWebhookMock = jest + .spyOn(webhookOutgoingService, 'createOutgoingWebhook') + .mockImplementation(() => { + throw new DatabaseError( + 'Duplicate entry error', + PostgresErrorCodes.Duplicated, + ); + }); + + await escrowCompletionService.processPaidEscrowCompletion(); + + expect(createOutgoingWebhookMock).toHaveBeenCalled(); + expect(updateOneMock).not.toHaveBeenCalledWith({ + id: escrowCompletionEntity1.id, + status: EscrowCompletionStatus.COMPLETED, + }); + }); + + it('should skip assessReputationScores when escrowStatus is not paid', async () => { + EscrowClient.build = jest.fn().mockResolvedValue({ + getStatus: jest.fn().mockResolvedValue(EscrowStatus.Launched), + complete: jest.fn().mockResolvedValue(true), + getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getRecordingOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + }); + + jest + .spyOn(escrowCompletionRepository, 'findByStatus') + .mockResolvedValue([escrowCompletionEntity1 as any]); + + const updateOneMock = jest + .spyOn(escrowCompletionRepository, 'updateOne') + .mockResolvedValue(escrowCompletionEntity1 as any); + + await escrowCompletionService.processPaidEscrowCompletion(); + + expect(updateOneMock).toHaveBeenCalledTimes(1); + expect(assessReputationScoresMock).toHaveBeenCalledTimes(0); + expect(createOutgoingWebhookMock).toHaveBeenCalledTimes(2); + }); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts new file mode 100644 index 0000000000..f251bf0024 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts @@ -0,0 +1,261 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { v4 as uuidv4 } from 'uuid'; +import { HttpStatus, Injectable, Logger } from '@nestjs/common'; +import { EscrowCompletionStatus, EventType } from '../../common/enums'; +import { ServerConfigService } from '../../common/config/server-config.service'; +import { EscrowCompletionRepository } from './escrow-completion.repository'; +import { EscrowCompletionEntity } from './escrow-completion.entity'; +import { + ChainId, + EscrowClient, + EscrowStatus, + OperatorUtils, +} from '@human-protocol/sdk'; +import { calculateExponentialBackoffMs } from '../../common/utils/backoff'; +import { BACKOFF_INTERVAL_SECONDS } from '../../common/constants'; +import { WebhookIncomingService } from '../webhook/webhook-incoming.service'; +import { PayoutService } from '../payout/payout.service'; +import { ReputationService } from '../reputation/reputation.service'; +import { Web3Service } from '../web3/web3.service'; +import { + ErrorEscrowCompletion, + ErrorWebhook, +} from '../../common/constants/errors'; +import { ControlledError } from '../../common/errors/controlled'; +import { WebhookOutgoingService } from '../webhook/webhook-outgoing.service'; +import { isDuplicatedError } from '../../common/utils/database'; + +@Injectable() +export class EscrowCompletionService { + private readonly logger = new Logger(WebhookIncomingService.name); + + constructor( + private readonly escrowCompletionRepository: EscrowCompletionRepository, + private readonly web3Service: Web3Service, + private readonly webhookOutgoingService: WebhookOutgoingService, + private readonly payoutService: PayoutService, + private readonly reputationService: ReputationService, + public readonly serverConfigService: ServerConfigService, + ) {} + + /** + * Creates a tracking record for escrow completion in the repository. + * Sets initial status to 'PENDING'. + * @param {ChainId} chainId - The blockchain chain ID. + * @param {string} escrowAddress - The address of the escrow contract. + */ + public async createEscrowCompletion( + chainId: ChainId, + escrowAddress: string, + ): Promise { + let escrowCompletionEntity = new EscrowCompletionEntity(); + escrowCompletionEntity.chainId = chainId; + escrowCompletionEntity.escrowAddress = escrowAddress; + escrowCompletionEntity.status = EscrowCompletionStatus.PENDING; + escrowCompletionEntity.waitUntil = new Date(); + escrowCompletionEntity.retriesCount = 0; + + escrowCompletionEntity = await this.escrowCompletionRepository.createUnique( + escrowCompletionEntity, + ); + } + + /** + * Handles errors that occur during escrow completion. + * If retry count is below the maximum, increments retry count and reschedules; otherwise, marks as 'FAILED'. + * @param escrowCompletionEntity - The escrow entity. + * @param failureDetail - Reason for the failure. + */ + private async handleEscrowCompletionError( + escrowCompletionEntity: EscrowCompletionEntity, + failureDetail: string, + ): Promise { + if ( + escrowCompletionEntity.retriesCount < + this.serverConfigService.maxRetryCount + ) { + const exponentialBackoff = calculateExponentialBackoffMs( + escrowCompletionEntity.retriesCount, + BACKOFF_INTERVAL_SECONDS, + ); + escrowCompletionEntity.waitUntil = new Date( + Date.now() + exponentialBackoff, + ); + escrowCompletionEntity.retriesCount += 1; + } else { + escrowCompletionEntity.failureDetail = failureDetail; + escrowCompletionEntity.status = EscrowCompletionStatus.FAILED; + } + await this.escrowCompletionRepository.updateOne(escrowCompletionEntity); + } + + public async processPendingEscrowCompletion(): Promise { + const escrowCompletionEntities = + await this.escrowCompletionRepository.findByStatus( + EscrowCompletionStatus.PENDING, + ); + + for (const escrowCompletionEntity of escrowCompletionEntities) { + try { + const signer = this.web3Service.getSigner( + escrowCompletionEntity.chainId, + ); + const escrowClient = await EscrowClient.build(signer); + + const escrowStatus = await escrowClient.getStatus( + escrowCompletionEntity.escrowAddress, + ); + if (escrowStatus === EscrowStatus.Pending) { + if (!escrowCompletionEntity.finalResultsUrl) { + const { url, hash } = await this.payoutService.processResults( + escrowCompletionEntity.chainId, + escrowCompletionEntity.escrowAddress, + ); + + escrowCompletionEntity.finalResultsUrl = url; + escrowCompletionEntity.finalResultsHash = hash; + await this.escrowCompletionRepository.updateOne( + escrowCompletionEntity, + ); + } + + await this.payoutService.executePayouts( + escrowCompletionEntity.chainId, + escrowCompletionEntity.escrowAddress, + escrowCompletionEntity.finalResultsUrl, + escrowCompletionEntity.finalResultsHash, + ); + } + + escrowCompletionEntity.status = EscrowCompletionStatus.PAID; + await this.escrowCompletionRepository.updateOne(escrowCompletionEntity); + } catch (err) { + const errorId = uuidv4(); + const failureDetail = `${ErrorEscrowCompletion.PendingProcessingFailed} (Error ID: ${errorId})`; + this.logger.error( + `Error processing escrow completion. Error ID: ${errorId}, Escrow completion ID: ${escrowCompletionEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, + ); + await this.handleEscrowCompletionError( + escrowCompletionEntity, + failureDetail, + ); + continue; + } + } + } + + public async processPaidEscrowCompletion(): Promise { + const escrowCompletionEntities = + await this.escrowCompletionRepository.findByStatus( + EscrowCompletionStatus.PAID, + ); + + // TODO: Add DB transactions + for (const escrowCompletionEntity of escrowCompletionEntities) { + try { + const { chainId, escrowAddress } = escrowCompletionEntity; + + const signer = this.web3Service.getSigner(chainId); + const escrowClient = await EscrowClient.build(signer); + + const escrowStatus = await escrowClient.getStatus(escrowAddress); + + if (escrowStatus === EscrowStatus.Paid) { + await escrowClient.complete(escrowAddress, { + gasPrice: await this.web3Service.calculateGasPrice(chainId), + }); + + // TODO: Technically it's possible that the escrow completion could occur before the reputation scores are assessed, + // and the app might go down during this window. Currently, there isn’t a clear approach to handle this situation. + // Consider revisiting this section to explore potential solutions to improve resilience in such scenarios. + await this.reputationService.assessReputationScores( + chainId, + escrowAddress, + ); + } + + const callbackUrls = [ + ( + await OperatorUtils.getLeader( + chainId, + await escrowClient.getJobLauncherAddress(escrowAddress), + ) + ).webhookUrl, + ( + await OperatorUtils.getLeader( + chainId, + await escrowClient.getExchangeOracleAddress(escrowAddress), + ) + ).webhookUrl, + /*( + await OperatorUtils.getLeader( + chainId, + await escrowClient.getRecordingOracleAddress(escrowAddress), + ) + ).webhookUrl,*/ + ]; + + let allWebhooksCreated = true; + + const payload = { + chainId, + escrowAddress, + eventType: EventType.ESCROW_COMPLETED, + }; + + for (const url of callbackUrls) { + if (!url) { + throw new ControlledError( + ErrorWebhook.UrlNotFound, + HttpStatus.NOT_FOUND, + ); + } + + try { + await this.webhookOutgoingService.createOutgoingWebhook( + payload, + url, + ); + } catch (err) { + if (isDuplicatedError(err)) { + this.logger.warn( + `Duplicate outgoing webhook for escrowAddress: ${escrowAddress}. Webhook creation skipped, but will not complete escrow until all URLs are successful.`, + ); + continue; + } else { + const errorId = uuidv4(); + const failureDetail = `${ErrorEscrowCompletion.PaidProcessingFailed} (Error ID: ${errorId})`; + this.logger.error( + `Error creating outgoing webhook. Error ID: ${errorId}, Escrow Address: ${escrowAddress}, Reason: ${failureDetail}, Message: ${err.message}`, + ); + await this.handleEscrowCompletionError( + escrowCompletionEntity, + failureDetail, + ); + allWebhooksCreated = false; + break; + } + } + } + + // Only set the status to COMPLETED if all webhooks were created successfully + if (allWebhooksCreated) { + escrowCompletionEntity.status = EscrowCompletionStatus.COMPLETED; + await this.escrowCompletionRepository.updateOne( + escrowCompletionEntity, + ); + } + } catch (err) { + const errorId = uuidv4(); + const failureDetail = `${ErrorEscrowCompletion.PaidProcessingFailed} (Error ID: ${errorId})`; + this.logger.error( + `Error processing escrow completion. Error ID: ${errorId}, Escrow completion ID: ${escrowCompletionEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, + ); + await this.handleEscrowCompletionError( + escrowCompletionEntity, + failureDetail, + ); + } + } + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.spec.ts index 526166c000..6139530ca3 100644 --- a/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.spec.ts @@ -110,7 +110,7 @@ describe('PayoutService', () => { jest.resetAllMocks(); }); - describe('saveResults', () => { + describe('processResults', () => { const results: SaveResultDto = { url: MOCK_FILE_URL, hash: MOCK_FILE_HASH, @@ -153,7 +153,7 @@ describe('PayoutService', () => { const escrowAddress = MOCK_ADDRESS; const chainId = ChainId.LOCALHOST; - const result = await payoutService.saveResults(chainId, escrowAddress); + const result = await payoutService.processResults(chainId, escrowAddress); expect(result).toEqual(results); }); @@ -182,7 +182,7 @@ describe('PayoutService', () => { const escrowAddress = MOCK_ADDRESS; const chainId = ChainId.LOCALHOST; - const result = await payoutService.saveResults(chainId, escrowAddress); + const result = await payoutService.processResults(chainId, escrowAddress); expect(result).toEqual(results); }); @@ -195,7 +195,7 @@ describe('PayoutService', () => { const chainId = ChainId.LOCALHOST; await expect( - payoutService.saveResults(chainId, escrowAddress), + payoutService.processResults(chainId, escrowAddress), ).rejects.toThrow( new ControlledError( ErrorManifest.ManifestUrlDoesNotExist, @@ -307,7 +307,7 @@ describe('PayoutService', () => { const chainId = ChainId.LOCALHOST; await expect( - payoutService.saveResults(chainId, escrowAddress), + payoutService.processResults(chainId, escrowAddress), ).rejects.toThrow( new ControlledError( ErrorManifest.ManifestUrlDoesNotExist, @@ -315,6 +315,24 @@ describe('PayoutService', () => { ), ); }); + + it('should throw an error for unsupported request types', async () => { + const mockManifest = { requestType: 'unsupportedType' }; + + jest.spyOn(EscrowClient, 'build').mockResolvedValue({ + getManifestUrl: jest.fn().mockResolvedValue(MOCK_FILE_URL), + } as any); + + jest + .spyOn(storageService, 'downloadJsonLikeData') + .mockResolvedValue(mockManifest); + + await expect( + payoutService.processResults(ChainId.LOCALHOST, MOCK_ADDRESS), + ).rejects.toThrow( + `Unsupported request type: ${mockManifest.requestType.toLowerCase()}`, + ); + }); }); describe('saveResultsFortune', () => { diff --git a/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts b/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts index aa94175724..fd75b794ed 100644 --- a/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/payout/payout.service.ts @@ -23,7 +23,7 @@ import { SaveResultDto, } from '../../common/dto/result'; import { RequestAction } from './payout.interface'; -import { getRequestType } from '../../common/utils'; +import { getRequestType, isValidJobRequestType } from '../../common/utils'; import { ControlledError } from '../../common/errors/controlled'; @Injectable() @@ -43,7 +43,7 @@ export class PayoutService { * @param escrowAddress The escrow contract address. * @returns {Promise} The URL and hash for the stored results. */ - public async saveResults( + public async processResults( chainId: ChainId, escrowAddress: string, ): Promise { @@ -63,7 +63,14 @@ export class PayoutService { const manifest = await this.storageService.downloadJsonLikeData(manifestUrl); - const requestType = getRequestType(manifest); + const requestType = getRequestType(manifest).toLowerCase(); + + if (!isValidJobRequestType(requestType)) { + throw new ControlledError( + `Unsupported request type: ${requestType}`, + HttpStatus.BAD_REQUEST, + ); + } const { saveResults } = this.createPayoutSpecificActions[requestType]; @@ -106,7 +113,14 @@ export class PayoutService { const manifest = await this.storageService.downloadJsonLikeData(manifestUrl); - const requestType = getRequestType(manifest); + const requestType = getRequestType(manifest).toLowerCase(); + + if (!isValidJobRequestType(requestType)) { + throw new ControlledError( + `Unsupported request type: ${requestType}`, + HttpStatus.BAD_REQUEST, + ); + } const { calculatePayouts } = this.createPayoutSpecificActions[requestType]; diff --git a/packages/apps/reputation-oracle/server/src/modules/user/user.dto.ts b/packages/apps/reputation-oracle/server/src/modules/user/user.dto.ts index 4e0cf57c7e..1db6ffc89e 100644 --- a/packages/apps/reputation-oracle/server/src/modules/user/user.dto.ts +++ b/packages/apps/reputation-oracle/server/src/modules/user/user.dto.ts @@ -9,7 +9,7 @@ import { Transform } from 'class-transformer'; import { UserStatus, Role } from '../../common/enums/user'; import { ValidatePasswordDto } from '../auth/auth.dto'; import { SignatureType } from '../../common/enums/web3'; -import { IsEnumCaseInsensitive } from 'src/common/decorators'; +import { IsEnumCaseInsensitive } from '../../common/decorators'; export class UserCreateDto extends ValidatePasswordDto { @ApiProperty() diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.module.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.module.ts similarity index 55% rename from packages/apps/reputation-oracle/server/src/modules/webhook/webhook.module.ts rename to packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.module.ts index 9b5ed57f77..0a3652ca6a 100644 --- a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.module.ts +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.module.ts @@ -5,26 +5,21 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { HttpModule } from '@nestjs/axios'; import { Web3Module } from '../web3/web3.module'; import { WebhookController } from './webhook.controller'; -import { WebhookService } from './webhook.service'; import { WebhookIncomingEntity } from './webhook-incoming.entity'; -import { WebhookOutgoingEntity } from './webhook-outgoing.entity'; import { WebhookIncomingRepository } from './webhook-incoming.repository'; -import { WebhookOutgoingRepository } from './webhook-outgoing.repository'; +import { EscrowCompletionModule } from '../escrow-completion/escrow-completion.module'; +import { WebhookIncomingService } from './webhook-incoming.service'; @Module({ imports: [ - TypeOrmModule.forFeature([WebhookIncomingEntity, WebhookOutgoingEntity]), + TypeOrmModule.forFeature([WebhookIncomingEntity]), ConfigModule, Web3Module, HttpModule, + EscrowCompletionModule, ], controllers: [WebhookController], - providers: [ - Logger, - WebhookService, - WebhookIncomingRepository, - WebhookOutgoingRepository, - ], - exports: [WebhookService], + providers: [Logger, WebhookIncomingService, WebhookIncomingRepository], + exports: [WebhookIncomingService], }) -export class WebhookModule {} +export class WebhookIncomingModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.spec.ts new file mode 100644 index 0000000000..3cf74c1e8a --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.spec.ts @@ -0,0 +1,290 @@ +import { createMock } from '@golevelup/ts-jest'; +import { ChainId } from '@human-protocol/sdk'; +import { HttpService } from '@nestjs/axios'; +import { ConfigService } from '@nestjs/config'; +import { Test } from '@nestjs/testing'; +import { + MOCK_ADDRESS, + MOCK_MAX_RETRY_COUNT, + MOCK_PRIVATE_KEY, + mockConfig, +} from '../../../test/constants'; +import { EventType, WebhookIncomingStatus } from '../../common/enums/webhook'; +import { Web3Service } from '../web3/web3.service'; +import { WebhookIncomingRepository } from './webhook-incoming.repository'; +import { WebhookOutgoingRepository } from './webhook-outgoing.repository'; +import { WebhookIncomingService } from './webhook-incoming.service'; +import { WebhookIncomingEntity } from './webhook-incoming.entity'; +import { IncomingWebhookDto } from './webhook.dto'; +import { ErrorWebhook } from '../../common/constants/errors'; +import { HttpStatus } from '@nestjs/common'; +import { Web3ConfigService } from '../../common/config/web3-config.service'; +import { ServerConfigService } from '../../common/config/server-config.service'; +import { ControlledError } from '../../common/errors/controlled'; +import { ReputationService } from '../reputation/reputation.service'; +import { EscrowCompletionRepository } from '../escrow-completion/escrow-completion.repository'; +import { EscrowCompletionService } from '../escrow-completion/escrow-completion.service'; +import { PostgresErrorCodes } from '../../common/enums/database'; +import { DatabaseError } from '../../common/errors/database'; +import { WebhookOutgoingService } from './webhook-outgoing.service'; +import { PayoutService } from '../payout/payout.service'; +import { StorageService } from '../storage/storage.service'; +import { ReputationRepository } from '../reputation/reputation.repository'; +import { ReputationConfigService } from '../../common/config/reputation-config.service'; +import { S3ConfigService } from '../../common/config/s3-config.service'; +import { PGPConfigService } from '../../common/config/pgp-config.service'; + +describe('WebhookIncomingService', () => { + let webhookIncomingService: WebhookIncomingService, + webhookIncomingRepository: WebhookIncomingRepository, + web3ConfigService: Web3ConfigService, + escrowCompletionService: EscrowCompletionService; + + const signerMock = { + address: MOCK_ADDRESS, + getNetwork: jest.fn().mockResolvedValue({ chainId: 1 }), + }; + + // Mock ConfigService to return the mock configuration values + const mockConfigService = { + get: jest.fn((key: string) => mockConfig[key]), + getOrThrow: jest.fn((key: string) => { + if (!mockConfig[key]) + throw new Error(`Configuration key "${key}" does not exist`); + return mockConfig[key]; + }), + }; + + // Mock Web3Service + const mockWeb3Service = { + getSigner: jest.fn().mockReturnValue(signerMock), + validateChainId: jest.fn().mockReturnValue(new Error()), + calculateGasPrice: jest.fn().mockReturnValue(1000n), + getOperatorAddress: jest.fn().mockReturnValue(MOCK_ADDRESS), + }; + + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + providers: [ + WebhookIncomingService, + WebhookOutgoingService, + EscrowCompletionService, + Web3ConfigService, + ServerConfigService, + PayoutService, + ReputationService, + HttpService, + StorageService, + ReputationConfigService, + S3ConfigService, + PGPConfigService, + { + provide: EscrowCompletionRepository, + useValue: createMock(), + }, + { + provide: WebhookOutgoingRepository, + useValue: createMock(), + }, + { + provide: ReputationRepository, + useValue: createMock(), + }, + // Mocked services + { + provide: ConfigService, + useValue: mockConfigService, + }, + { + provide: Web3Service, + useValue: mockWeb3Service, + }, + { + provide: WebhookIncomingRepository, + useValue: createMock(), + }, + { provide: HttpService, useValue: createMock() }, + ], + }).compile(); + + // Assign injected dependencies to variables + webhookIncomingService = moduleRef.get( + WebhookIncomingService, + ); + webhookIncomingRepository = moduleRef.get(WebhookIncomingRepository); + escrowCompletionService = moduleRef.get( + EscrowCompletionService, + ); + web3ConfigService = moduleRef.get(Web3ConfigService); + + // Mocking privateKey getter + jest + .spyOn(web3ConfigService, 'privateKey', 'get') + .mockReturnValue(MOCK_PRIVATE_KEY); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('createIncomingWebhook', () => { + const validDto: IncomingWebhookDto = { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + eventType: EventType.JOB_COMPLETED, + }; + + const invalidDto: IncomingWebhookDto = { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + eventType: 'JOB_FAILED' as EventType, + }; + + const webhookEntity: Partial = { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + status: WebhookIncomingStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + it('should successfully create an incoming webhook with valid DTO', async () => { + jest + .spyOn(webhookIncomingRepository, 'createUnique') + .mockResolvedValue(webhookEntity as WebhookIncomingEntity); + + await webhookIncomingService.createIncomingWebhook(validDto); + + expect(webhookIncomingRepository.createUnique).toHaveBeenCalledWith( + expect.objectContaining({ + chainId: validDto.chainId, + escrowAddress: validDto.escrowAddress, + }), + ); + }); + + it('should throw BadRequestException with an invalid event type', async () => { + await expect( + webhookIncomingService.createIncomingWebhook(invalidDto), + ).rejects.toThrow( + new ControlledError( + ErrorWebhook.InvalidEventType, + HttpStatus.BAD_REQUEST, + ), + ); + }); + }); + + describe('processPendingIncomingWebhooks', () => { + let createEscrowCompletionMock: any; + let webhookEntity1: Partial, + webhookEntity2: Partial; + + beforeEach(() => { + webhookEntity1 = { + id: 1, + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + status: WebhookIncomingStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + webhookEntity2 = { + id: 2, + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + status: WebhookIncomingStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + jest + .spyOn(webhookIncomingRepository, 'findByStatus') + .mockResolvedValue([webhookEntity1 as any, webhookEntity2 as any]); + + createEscrowCompletionMock = jest.spyOn( + escrowCompletionService as any, + 'createEscrowCompletion', + ); + createEscrowCompletionMock.mockResolvedValue(undefined); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should process pending incoming webhooks and mark them as COMPLETED', async () => { + await webhookIncomingService.processPendingIncomingWebhooks(); + + expect(createEscrowCompletionMock).toHaveBeenCalledTimes(2); + expect(createEscrowCompletionMock).toHaveBeenCalledWith( + webhookEntity1.chainId, + webhookEntity1.escrowAddress, + ); + expect(createEscrowCompletionMock).toHaveBeenCalledWith( + webhookEntity2.chainId, + webhookEntity2.escrowAddress, + ); + + expect(webhookIncomingRepository.updateOne).toHaveBeenCalledTimes(2); + expect(webhookEntity1.status).toBe(WebhookIncomingStatus.COMPLETED); + expect(webhookEntity2.status).toBe(WebhookIncomingStatus.COMPLETED); + }); + + it('should retry the webhook if processing fails and retries are below threshold', async () => { + createEscrowCompletionMock.mockRejectedValueOnce( + new Error('Processing error'), + ); + + await webhookIncomingService.processPendingIncomingWebhooks(); + + expect(webhookIncomingRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + status: WebhookIncomingStatus.PENDING, + retriesCount: 1, + }), + ); + }); + + it('should mark the webhook as FAILED if retries exceed the threshold', async () => { + const error = new Error('Processing error'); + const loggerErrorSpy = jest.spyOn( + webhookIncomingService['logger'], + 'error', + ); + + webhookEntity1.retriesCount = MOCK_MAX_RETRY_COUNT; + createEscrowCompletionMock.mockRejectedValueOnce(error); + + await webhookIncomingService.processPendingIncomingWebhooks(); + + expect(webhookIncomingRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + status: WebhookIncomingStatus.FAILED, + retriesCount: MOCK_MAX_RETRY_COUNT, + }), + ); + expect(loggerErrorSpy).toHaveBeenCalledWith( + expect.stringContaining(`Message: ${error.message}`), + ); + }); + + it('should handle duplicated errors and mark the webhook as COMPLETED', async () => { + createEscrowCompletionMock.mockImplementationOnce(() => { + throw new DatabaseError( + 'Duplicate entry', + PostgresErrorCodes.Duplicated, + ); + }); + + await webhookIncomingService.processPendingIncomingWebhooks(); + + expect(webhookIncomingRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + status: WebhookIncomingStatus.COMPLETED, + }), + ); + }); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts new file mode 100644 index 0000000000..4923841f39 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts @@ -0,0 +1,115 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { v4 as uuidv4 } from 'uuid'; +import { HttpStatus, Injectable, Logger } from '@nestjs/common'; +import { IncomingWebhookDto } from './webhook.dto'; +import { ErrorWebhook } from '../../common/constants/errors'; +import { EventType, WebhookIncomingStatus } from '../../common/enums'; +import { BACKOFF_INTERVAL_SECONDS } from '../../common/constants'; +import { ServerConfigService } from '../../common/config/server-config.service'; +import { Web3ConfigService } from '../../common/config/web3-config.service'; +import { ControlledError } from '../../common/errors/controlled'; +import { WebhookIncomingEntity } from './webhook-incoming.entity'; +import { WebhookIncomingRepository } from './webhook-incoming.repository'; +import { calculateExponentialBackoffMs } from '../../common/utils/backoff'; +import { EscrowCompletionService } from '../escrow-completion/escrow-completion.service'; +import { isDuplicatedError } from '../../common/utils/database'; + +@Injectable() +export class WebhookIncomingService { + private readonly logger = new Logger(WebhookIncomingService.name); + + constructor( + private readonly webhookIncomingRepository: WebhookIncomingRepository, + private readonly escrowCompletionService: EscrowCompletionService, + public readonly serverConfigService: ServerConfigService, + public readonly web3ConfigService: Web3ConfigService, + ) {} + + /** + * Creates an incoming webhook entry in the repository. + * Validates that the event type is 'JOB_COMPLETED' and sets initial status to 'PENDING'. + * @param {IncomingWebhookDto} dto - Contains webhook details like chain ID and escrow address. + * @throws {ControlledError} If the event type is invalid or the webhook cannot be created. + */ + public async createIncomingWebhook(dto: IncomingWebhookDto): Promise { + if (dto.eventType !== EventType.JOB_COMPLETED) { + throw new ControlledError( + ErrorWebhook.InvalidEventType, + HttpStatus.BAD_REQUEST, + ); + } + + let webhookEntity = new WebhookIncomingEntity(); + webhookEntity.chainId = dto.chainId; + webhookEntity.escrowAddress = dto.escrowAddress; + webhookEntity.status = WebhookIncomingStatus.PENDING; + webhookEntity.waitUntil = new Date(); + webhookEntity.retriesCount = 0; + + webhookEntity = + await this.webhookIncomingRepository.createUnique(webhookEntity); + } + + /** + * Handles errors that occur while processing an incoming webhook. + * If retry count is below the maximum, increments retry count and reschedules; otherwise, marks as 'FAILED'. + * @param webhookEntity - The incoming webhook entity. + * @param failureDetail - Reason for the failure. + */ + private async handleWebhookIncomingError( + webhookEntity: WebhookIncomingEntity, + failureDetail: string, + ): Promise { + if (webhookEntity.retriesCount < this.serverConfigService.maxRetryCount) { + const exponentialBackoff = calculateExponentialBackoffMs( + webhookEntity.retriesCount, + BACKOFF_INTERVAL_SECONDS, + ); + webhookEntity.waitUntil = new Date(Date.now() + exponentialBackoff); + webhookEntity.retriesCount += 1; + } else { + webhookEntity.failureDetail = failureDetail; + webhookEntity.status = WebhookIncomingStatus.FAILED; + } + await this.webhookIncomingRepository.updateOne(webhookEntity); + } + + public async processPendingIncomingWebhooks(): Promise { + const webhookEntities = await this.webhookIncomingRepository.findByStatus( + WebhookIncomingStatus.PENDING, + ); + + for (const webhookEntity of webhookEntities) { + try { + const { chainId, escrowAddress } = webhookEntity; + + await this.escrowCompletionService.createEscrowCompletion( + chainId, + escrowAddress, + ); + + webhookEntity.status = WebhookIncomingStatus.COMPLETED; + await this.webhookIncomingRepository.updateOne(webhookEntity); + } catch (err) { + const errorId = uuidv4(); + const failureDetail = `${ErrorWebhook.PendingProcessingFailed} (Error ID: ${errorId})`; + + if (isDuplicatedError(err)) { + // Handle duplicated error: log and mark as completed + this.logger.warn( + `Duplicate tracking entity for escrowAddress: ${webhookEntity.escrowAddress}. Marking webhook as completed.`, + ); + webhookEntity.status = WebhookIncomingStatus.COMPLETED; + await this.webhookIncomingRepository.updateOne(webhookEntity); + } else { + // Handle other errors (general failure) + this.logger.error( + `Error processing webhook. Error ID: ${errorId}, Webhook ID: ${webhookEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, + ); + await this.handleWebhookIncomingError(webhookEntity, failureDetail); + } + continue; + } + } + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.module.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.module.ts new file mode 100644 index 0000000000..27858fd0c1 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.module.ts @@ -0,0 +1,20 @@ +import { Logger, Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { HttpModule } from '@nestjs/axios'; +import { Web3Module } from '../web3/web3.module'; +import { WebhookOutgoingEntity } from './webhook-outgoing.entity'; +import { WebhookOutgoingRepository } from './webhook-outgoing.repository'; +import { WebhookOutgoingService } from './webhook-outgoing.service'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([WebhookOutgoingEntity]), + ConfigModule, + Web3Module, + HttpModule, + ], + providers: [Logger, WebhookOutgoingService, WebhookOutgoingRepository], + exports: [WebhookOutgoingService], +}) +export class WebhookOutgoingModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.spec.ts new file mode 100644 index 0000000000..a60915f8de --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.spec.ts @@ -0,0 +1,291 @@ +import * as crypto from 'crypto'; +import stringify from 'json-stable-stringify'; +import { createMock } from '@golevelup/ts-jest'; +import { ChainId } from '@human-protocol/sdk'; +import { HttpService } from '@nestjs/axios'; +import { ConfigService } from '@nestjs/config'; +import { Test } from '@nestjs/testing'; +import { + MOCK_ADDRESS, + MOCK_FILE_HASH, + MOCK_FILE_URL, + MOCK_MAX_RETRY_COUNT, + MOCK_PRIVATE_KEY, + MOCK_WEBHOOK_URL, + mockConfig, +} from '../../../test/constants'; +import { EventType, WebhookOutgoingStatus } from '../../common/enums/webhook'; +import { Web3Service } from '../web3/web3.service'; +import { WebhookOutgoingRepository } from './webhook-outgoing.repository'; +import { WebhookOutgoingService } from './webhook-outgoing.service'; +import { WebhookOutgoingEntity } from './webhook-outgoing.entity'; +import { ErrorWebhook } from '../../common/constants/errors'; +import { of } from 'rxjs'; +import { HEADER_SIGNATURE_KEY } from '../../common/constants'; +import { signMessage } from '../../common/utils/signature'; +import { HttpStatus } from '@nestjs/common'; +import { Web3ConfigService } from '../../common/config/web3-config.service'; +import { ServerConfigService } from '../../common/config/server-config.service'; +import { ControlledError } from '../../common/errors/controlled'; + +describe('WebhookOutgoingService', () => { + let webhookOutgoingService: WebhookOutgoingService, + webhookOutgoingRepository: WebhookOutgoingRepository, + httpService: HttpService, + web3ConfigService: Web3ConfigService; + + const signerMock = { + address: MOCK_ADDRESS, + getNetwork: jest.fn().mockResolvedValue({ chainId: 1 }), + }; + + // Mock ConfigService to return the mock configuration values + const mockConfigService = { + get: jest.fn((key: string) => mockConfig[key]), + getOrThrow: jest.fn((key: string) => { + if (!mockConfig[key]) + throw new Error(`Configuration key "${key}" does not exist`); + return mockConfig[key]; + }), + }; + + // Mock Web3Service + const mockWeb3Service = { + getSigner: jest.fn().mockReturnValue(signerMock), + validateChainId: jest.fn().mockReturnValue(new Error()), + calculateGasPrice: jest.fn().mockReturnValue(1000n), + getOperatorAddress: jest.fn().mockReturnValue(MOCK_ADDRESS), + }; + + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + providers: [ + WebhookOutgoingService, + Web3ConfigService, + ServerConfigService, + HttpService, + // Mocked services + { + provide: ConfigService, + useValue: mockConfigService, + }, + { + provide: Web3Service, + useValue: mockWeb3Service, + }, + { + provide: WebhookOutgoingRepository, + useValue: createMock(), + }, + { provide: HttpService, useValue: createMock() }, + ], + }).compile(); + + // Assign injected dependencies to variables + webhookOutgoingService = moduleRef.get( + WebhookOutgoingService, + ); + webhookOutgoingRepository = moduleRef.get(WebhookOutgoingRepository); + httpService = moduleRef.get(HttpService); + web3ConfigService = moduleRef.get(Web3ConfigService); + + // Mocking privateKey getter + jest + .spyOn(web3ConfigService, 'privateKey', 'get') + .mockReturnValue(MOCK_PRIVATE_KEY); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('createOutgoingWebhook', () => { + const payload = { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + eventType: EventType.ESCROW_COMPLETED, + waitUntil: new Date(), + retriesCount: 0, + }; + + const url = MOCK_FILE_URL; + + const hash = crypto + .createHash('sha1') + .update(stringify({ payload, url })) + .digest('hex'); + + const webhookEntity: Partial = { + payload, + url, + hash, + status: WebhookOutgoingStatus.PENDING, + }; + + it('should successfully create outgoing webhook with valid DTO', async () => { + jest + .spyOn(webhookOutgoingRepository, 'createUnique') + .mockResolvedValue(webhookEntity as WebhookOutgoingEntity); + + await webhookOutgoingService.createOutgoingWebhook(payload, url); + + expect(webhookOutgoingRepository.createUnique).toHaveBeenCalledWith({ + ...webhookEntity, + waitUntil: expect.any(Date), + retriesCount: 0, + }); + }); + }); + + describe('sendWebhook', () => { + const payload = { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + eventType: EventType.ESCROW_COMPLETED, + }; + + it('should successfully send a webhook', async () => { + jest.spyOn(httpService as any, 'post').mockImplementation(() => { + return of({ + status: HttpStatus.CREATED, + }); + }); + expect( + await webhookOutgoingService.sendWebhook(MOCK_WEBHOOK_URL, payload), + ).toBe(undefined); + + const expectedBody = { + chain_id: payload.chainId, + escrow_address: payload.escrowAddress, + event_type: payload.eventType, + }; + + expect(httpService.post).toHaveBeenCalledWith( + MOCK_WEBHOOK_URL, + expectedBody, + { + headers: { + [HEADER_SIGNATURE_KEY]: await signMessage( + expectedBody, + MOCK_PRIVATE_KEY, + ), + }, + }, + ); + }); + it('should return an error if there is no response', async () => { + jest.spyOn(httpService as any, 'post').mockImplementation(() => { + return of({}); + }); + await expect( + webhookOutgoingService.sendWebhook(MOCK_WEBHOOK_URL, payload), + ).rejects.toThrow( + new ControlledError(ErrorWebhook.NotSent, HttpStatus.BAD_REQUEST), + ); + }); + }); + + describe('processPendingOutgoingWebhooks', () => { + let sendWebhookMock: any; + let webhookEntity1: Partial, + webhookEntity2: Partial; + + beforeEach(() => { + webhookEntity1 = { + id: 1, + payload: { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + eventType: EventType.ESCROW_COMPLETED, + }, + hash: MOCK_FILE_HASH, + url: MOCK_FILE_URL, + status: WebhookOutgoingStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + webhookEntity2 = { + id: 2, + payload: { + chainId: ChainId.LOCALHOST, + escrowAddress: MOCK_ADDRESS, + eventType: EventType.ESCROW_COMPLETED, + }, + hash: MOCK_FILE_HASH, + url: MOCK_FILE_URL, + status: WebhookOutgoingStatus.PENDING, + waitUntil: new Date(), + retriesCount: 0, + }; + + jest + .spyOn(webhookOutgoingRepository, 'findByStatus') + .mockResolvedValue([webhookEntity1 as any, webhookEntity2 as any]); + + sendWebhookMock = jest.spyOn( + webhookOutgoingService as any, + 'sendWebhook', + ); + sendWebhookMock.mockResolvedValue(); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should mark the webhook as SENT when sending webhook succeeds', async () => { + sendWebhookMock.mockResolvedValueOnce(undefined); + + await webhookOutgoingService.processPendingOutgoingWebhooks(); + + expect(webhookOutgoingRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + id: webhookEntity1.id, + status: WebhookOutgoingStatus.SENT, + }), + ); + expect(webhookEntity1.status).toBe(WebhookOutgoingStatus.SENT); + }); + + it('should increment retriesCount and set waitUntil when sending webhook fails', async () => { + sendWebhookMock.mockRejectedValueOnce(new Error('Network error')); + + await webhookOutgoingService.processPendingOutgoingWebhooks(); + + expect(webhookOutgoingRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + id: webhookEntity1.id, + retriesCount: 1, + waitUntil: expect.any(Date), + status: WebhookOutgoingStatus.PENDING, + }), + ); + expect(webhookEntity1.retriesCount).toBe(1); + expect(webhookEntity1.waitUntil).toBeInstanceOf(Date); + }); + + it('should mark webhook as FAILED if retry count exceeds threshold', async () => { + const error = new Error('Random Error'); + const loggerErrorSpy = jest.spyOn( + webhookOutgoingService['logger'], + 'error', + ); + + sendWebhookMock.mockRejectedValueOnce(error); + + webhookEntity1.retriesCount = MOCK_MAX_RETRY_COUNT; + + await webhookOutgoingService.processPendingOutgoingWebhooks(); + + expect(webhookOutgoingRepository.updateOne).toHaveBeenCalledWith( + expect.objectContaining({ + status: WebhookOutgoingStatus.FAILED, + }), + ); + expect(loggerErrorSpy).toHaveBeenCalledWith( + expect.stringContaining(`Message: ${error.message}`), + ); + }); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.service.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.ts similarity index 58% rename from packages/apps/reputation-oracle/server/src/modules/webhook/webhook.service.ts rename to packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.ts index f7fc0d7503..2e5a956f68 100644 --- a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.ts @@ -1,12 +1,10 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { HttpStatus, Injectable } from '@nestjs/common'; -import { IncomingWebhookDto } from './webhook.dto'; +import { v4 as uuidv4 } from 'uuid'; +import * as crypto from 'crypto'; +import stringify from 'json-stable-stringify'; +import { HttpStatus, Injectable, Logger } from '@nestjs/common'; import { ErrorWebhook } from '../../common/constants/errors'; -import { - EventType, - WebhookIncomingStatus, - WebhookOutgoingStatus, -} from '../../common/enums'; +import { WebhookOutgoingStatus } from '../../common/enums'; import { firstValueFrom } from 'rxjs'; import { signMessage } from '../../common/utils/signature'; import { @@ -18,47 +16,21 @@ import { CaseConverter } from '../../common/utils/case-converter'; import { ServerConfigService } from '../../common/config/server-config.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { ControlledError } from '../../common/errors/controlled'; -import { WebhookIncomingEntity } from './webhook-incoming.entity'; import { WebhookOutgoingEntity } from './webhook-outgoing.entity'; -import { WebhookIncomingRepository } from './webhook-incoming.repository'; import { WebhookOutgoingRepository } from './webhook-outgoing.repository'; import { calculateExponentialBackoffMs } from '../../common/utils/backoff'; @Injectable() -export class WebhookService { +export class WebhookOutgoingService { + private readonly logger = new Logger(WebhookOutgoingService.name); + constructor( private readonly httpService: HttpService, - private readonly webhookIncomingRepository: WebhookIncomingRepository, private readonly webhookOutgoingRepository: WebhookOutgoingRepository, public readonly serverConfigService: ServerConfigService, public readonly web3ConfigService: Web3ConfigService, ) {} - /** - * Creates an incoming webhook entry in the repository. - * Validates that the event type is 'JOB_COMPLETED' and sets initial status to 'PENDING'. - * @param {IncomingWebhookDto} dto - Contains webhook details like chain ID and escrow address. - * @throws {ControlledError} If the event type is invalid or the webhook cannot be created. - */ - public async createIncomingWebhook(dto: IncomingWebhookDto): Promise { - if (dto.eventType !== EventType.JOB_COMPLETED) { - throw new ControlledError( - ErrorWebhook.InvalidEventType, - HttpStatus.BAD_REQUEST, - ); - } - - let webhookEntity = new WebhookIncomingEntity(); - webhookEntity.chainId = dto.chainId; - webhookEntity.escrowAddress = dto.escrowAddress; - webhookEntity.status = WebhookIncomingStatus.PENDING; - webhookEntity.waitUntil = new Date(); - webhookEntity.retriesCount = 0; - - webhookEntity = - await this.webhookIncomingRepository.createUnique(webhookEntity); - } - /** * Creates an outgoing webhook entry in the repository. * Sets initial status to 'PENDING' and stores the provided payload, hash, and URL. @@ -68,9 +40,13 @@ export class WebhookService { */ public async createOutgoingWebhook( payload: Record, - hash: string, url: string, ): Promise { + const hash = crypto + .createHash('sha1') + .update(stringify({ payload, url })) + .digest('hex'); + let webhookEntity = new WebhookOutgoingEntity(); webhookEntity.payload = payload; webhookEntity.hash = hash; @@ -83,37 +59,13 @@ export class WebhookService { await this.webhookOutgoingRepository.createUnique(webhookEntity); } - /** - * Handles errors that occur while processing an incoming webhook. - * If retry count is below the maximum, increments retry count and reschedules; otherwise, marks as 'FAILED'. - * @param webhookEntity - The incoming webhook entity. - * @param failureDetail - Reason for the failure. - */ - public async handleWebhookIncomingError( - webhookEntity: WebhookIncomingEntity, - failureDetail: string, - ): Promise { - if (webhookEntity.retriesCount < this.serverConfigService.maxRetryCount) { - const exponentialBackoff = calculateExponentialBackoffMs( - webhookEntity.retriesCount, - BACKOFF_INTERVAL_SECONDS, - ); - webhookEntity.waitUntil = new Date(Date.now() + exponentialBackoff); - webhookEntity.retriesCount += 1; - } else { - webhookEntity.failureDetail = failureDetail; - webhookEntity.status = WebhookIncomingStatus.FAILED; - } - await this.webhookIncomingRepository.updateOne(webhookEntity); - } - /** * Handles errors that occur while processing an outgoing webhook. * If retry count is below the maximum, increments retry count and reschedules; otherwise, marks as 'FAILED'. * @param webhookEntity - The outgoing webhook entity. * @param failureDetail - Reason for the failure. */ - public async handleWebhookOutgoingError( + private async handleWebhookOutgoingError( webhookEntity: WebhookOutgoingEntity, failureDetail: string, ): Promise { @@ -138,19 +90,44 @@ export class WebhookService { * @param {object} payload - The data payload to send. * @throws {ControlledError} If the webhook request fails. */ - public async sendWebhook( - url: string, - payload: Record, - ): Promise { + public async sendWebhook(url: string, payload: object): Promise { const snake_case_body = CaseConverter.transformToSnakeCase(payload); const signedBody = await signMessage( snake_case_body, this.web3ConfigService.privateKey, ); - await firstValueFrom( + const { status } = await firstValueFrom( await this.httpService.post(url, snake_case_body, { headers: { [HEADER_SIGNATURE_KEY]: signedBody }, }), ); + + if (status !== HttpStatus.CREATED) { + throw new ControlledError(ErrorWebhook.NotSent, HttpStatus.NOT_FOUND); + } + } + + public async processPendingOutgoingWebhooks(): Promise { + const webhookEntities = await this.webhookOutgoingRepository.findByStatus( + WebhookOutgoingStatus.PENDING, + ); + + for (const webhookEntity of webhookEntities) { + try { + const { url, payload } = webhookEntity; + + await this.sendWebhook(url, payload); + } catch (err) { + const errorId = uuidv4(); + const failureDetail = `${ErrorWebhook.PendingProcessingFailed} (Error ID: ${errorId})`; + this.logger.error( + `Error processing pending outgoing webhook. Error ID: ${errorId}, Webhook ID: ${webhookEntity.id}, Reason: ${failureDetail}, Message: ${err.message}`, + ); + await this.handleWebhookOutgoingError(webhookEntity, failureDetail); + continue; + } + webhookEntity.status = WebhookOutgoingStatus.SENT; + await this.webhookOutgoingRepository.updateOne(webhookEntity); + } } } diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.controller.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.controller.ts index d837859e1f..be74f93adf 100644 --- a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.controller.ts +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.controller.ts @@ -9,7 +9,7 @@ import { import { HEADER_SIGNATURE_KEY } from '../../common/constants'; import { SignatureAuthGuard } from '../../common/guards'; import { Public } from '../../common/decorators'; -import { WebhookService } from './webhook.service'; +import { WebhookIncomingService } from './webhook-incoming.service'; import { AuthSignatureRole } from '../../common/enums/role'; import { IncomingWebhookDto } from './webhook.dto'; @@ -17,7 +17,9 @@ import { IncomingWebhookDto } from './webhook.dto'; @ApiTags('Webhook') @Controller('/webhook') export class WebhookController { - constructor(private readonly webhookService: WebhookService) {} + constructor( + private readonly webhookIncomingService: WebhookIncomingService, + ) {} @UseGuards(new SignatureAuthGuard([AuthSignatureRole.Recording])) @Post('/') @@ -51,7 +53,7 @@ export class WebhookController { @Headers(HEADER_SIGNATURE_KEY) _: string, @Body() data: IncomingWebhookDto, ): Promise { - await this.webhookService.createIncomingWebhook(data); + await this.webhookIncomingService.createIncomingWebhook(data); return; } } diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.service.spec.ts deleted file mode 100644 index f2648fa6e4..0000000000 --- a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook.service.spec.ts +++ /dev/null @@ -1,296 +0,0 @@ -import { createMock } from '@golevelup/ts-jest'; -import { ChainId } from '@human-protocol/sdk'; -import { HttpService } from '@nestjs/axios'; -import { ConfigService } from '@nestjs/config'; -import { Test } from '@nestjs/testing'; -import { - MOCK_ADDRESS, - MOCK_FILE_HASH, - MOCK_FILE_URL, - MOCK_MAX_RETRY_COUNT, - MOCK_PRIVATE_KEY, - MOCK_WEBHOOK_URL, - mockConfig, -} from '../../../test/constants'; -import { - EventType, - WebhookIncomingStatus, - WebhookOutgoingStatus, -} from '../../common/enums/webhook'; -import { Web3Service } from '../web3/web3.service'; -import { WebhookIncomingRepository } from './webhook-incoming.repository'; -import { WebhookOutgoingRepository } from './webhook-outgoing.repository'; -import { WebhookService } from './webhook.service'; -import { WebhookIncomingEntity } from './webhook-incoming.entity'; -import { WebhookOutgoingEntity } from './webhook-outgoing.entity'; -import { IncomingWebhookDto } from './webhook.dto'; -import { ErrorWebhook } from '../../common/constants/errors'; -import { of, throwError } from 'rxjs'; -import { HEADER_SIGNATURE_KEY } from '../../common/constants'; -import { signMessage } from '../../common/utils/signature'; -import { HttpStatus } from '@nestjs/common'; -import { Web3ConfigService } from '../../common/config/web3-config.service'; -import { ServerConfigService } from '../../common/config/server-config.service'; -import { ControlledError } from '../../common/errors/controlled'; - -jest.mock('@human-protocol/sdk', () => ({ - ...jest.requireActual('@human-protocol/sdk'), - EscrowClient: { - build: jest.fn(), - }, - KVStoreClient: { - build: jest.fn(), - }, -})); - -describe('WebhookService', () => { - let webhookService: WebhookService, - webhookIncomingRepository: WebhookIncomingRepository, - webhookOutgoingRepository: WebhookOutgoingRepository, - httpService: HttpService, - web3ConfigService: Web3ConfigService; - - const signerMock = { - address: MOCK_ADDRESS, - getNetwork: jest.fn().mockResolvedValue({ chainId: 1 }), - }; - - beforeEach(async () => { - const moduleRef = await Test.createTestingModule({ - providers: [ - { - provide: ConfigService, - useValue: { - get: jest.fn((key: string) => mockConfig[key]), - getOrThrow: jest.fn((key: string) => { - if (!mockConfig[key]) { - throw new Error(`Configuration key "${key}" does not exist`); - } - return mockConfig[key]; - }), - }, - }, - WebhookService, - { - provide: Web3Service, - useValue: { - getSigner: jest.fn().mockReturnValue(signerMock), - }, - }, - { - provide: WebhookIncomingRepository, - useValue: createMock(), - }, - { - provide: WebhookOutgoingRepository, - useValue: createMock(), - }, - Web3ConfigService, - ServerConfigService, - { provide: HttpService, useValue: createMock() }, - ], - }).compile(); - - webhookService = moduleRef.get(WebhookService); - webhookIncomingRepository = moduleRef.get(WebhookIncomingRepository); - webhookOutgoingRepository = moduleRef.get(WebhookOutgoingRepository); - httpService = moduleRef.get(HttpService); - web3ConfigService = moduleRef.get(Web3ConfigService); - - jest - .spyOn(web3ConfigService, 'privateKey', 'get') - .mockReturnValue(MOCK_PRIVATE_KEY); - }); - - afterEach(() => { - jest.resetAllMocks(); - }); - - describe('createIncomingWebhook', () => { - const webhookEntity: Partial = { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - status: WebhookIncomingStatus.PENDING, - waitUntil: new Date(), - retriesCount: 0, - }; - - it('should successfully create incoming webhook with valid DTO', async () => { - const validDto: IncomingWebhookDto = { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - eventType: EventType.JOB_COMPLETED, - }; - - jest - .spyOn(webhookIncomingRepository, 'createUnique') - .mockResolvedValue(webhookEntity as WebhookIncomingEntity); - - await webhookService.createIncomingWebhook(validDto); - - expect(webhookIncomingRepository.createUnique).toHaveBeenCalledWith( - expect.any(Object), - ); - }); - - it('should throw BadRequestException with invalid event type', async () => { - const invalidDto: IncomingWebhookDto = { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - eventType: 'JOB_FAILED' as EventType, - }; - - await expect( - webhookService.createIncomingWebhook(invalidDto), - ).rejects.toThrow( - new ControlledError( - ErrorWebhook.InvalidEventType, - HttpStatus.BAD_REQUEST, - ), - ); - }); - }); - - describe('createOutgoingWebhook', () => { - const payload = { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - eventType: EventType.ESCROW_COMPLETED, - waitUntil: new Date(), - retriesCount: 0, - }; - - const url = MOCK_FILE_URL; - const hash = MOCK_FILE_HASH; - - const webhookEntity: Partial = { - payload, - url: MOCK_FILE_URL, - hash: MOCK_FILE_HASH, - status: WebhookOutgoingStatus.PENDING, - }; - - it('should successfully create outgoing webhook with valid DTO', async () => { - jest - .spyOn(webhookOutgoingRepository, 'createUnique') - .mockResolvedValue(webhookEntity as WebhookOutgoingEntity); - - await webhookService.createOutgoingWebhook(payload, url, hash); - - expect(webhookOutgoingRepository.createUnique).toHaveBeenCalledWith( - expect.any(Object), - ); - }); - }); - - describe('handleWebhookIncomingError', () => { - it('should set incoming webhook status to FAILED if retries exceed threshold', async () => { - const webhookEntity: Partial = { - id: 1, - status: WebhookIncomingStatus.PENDING, - retriesCount: MOCK_MAX_RETRY_COUNT, - }; - await (webhookService as any).handleWebhookIncomingError( - webhookEntity, - new Error('Sample error'), - ); - expect(webhookIncomingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity.status).toBe(WebhookIncomingStatus.FAILED); - }); - - it('should increment retries count if below threshold', async () => { - const webhookEntity: Partial = { - id: 1, - status: WebhookIncomingStatus.PENDING, - retriesCount: 0, - }; - await (webhookService as any).handleWebhookIncomingError( - webhookEntity, - new Error('Sample error'), - ); - expect(webhookIncomingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity.status).toBe(WebhookIncomingStatus.PENDING); - expect(webhookEntity.retriesCount).toBe(1); - expect(webhookEntity.waitUntil).toBeInstanceOf(Date); - }); - }); - - describe('handleWebhookOutgoingError', () => { - it('should set outgoing webhook status to FAILED if retries exceed threshold', async () => { - const webhookEntity: Partial = { - id: 1, - status: WebhookOutgoingStatus.PENDING, - retriesCount: MOCK_MAX_RETRY_COUNT, - }; - await (webhookService as any).handleWebhookOutgoingError( - webhookEntity, - new Error('Sample error'), - ); - expect(webhookOutgoingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity.status).toBe(WebhookOutgoingStatus.FAILED); - }); - - it('should increment retries count if below threshold', async () => { - const webhookEntity: Partial = { - id: 1, - status: WebhookOutgoingStatus.PENDING, - retriesCount: 0, - }; - await (webhookService as any).handleWebhookOutgoingError( - webhookEntity, - new Error('Sample error'), - ); - expect(webhookOutgoingRepository.updateOne).toHaveBeenCalled(); - expect(webhookEntity.status).toBe(WebhookOutgoingStatus.PENDING); - expect(webhookEntity.retriesCount).toBe(1); - expect(webhookEntity.waitUntil).toBeInstanceOf(Date); - }); - }); - - describe('sendWebhook', () => { - const payload = { - chainId: ChainId.LOCALHOST, - escrowAddress: MOCK_ADDRESS, - eventType: EventType.ESCROW_COMPLETED, - }; - - it('should successfully send a webhook', async () => { - jest.spyOn(httpService as any, 'post').mockImplementation(() => { - return of({ - status: HttpStatus.CREATED, - }); - }); - expect(await webhookService.sendWebhook(MOCK_WEBHOOK_URL, payload)).toBe( - undefined, - ); - - const expectedBody = { - chain_id: payload.chainId, - escrow_address: payload.escrowAddress, - event_type: payload.eventType, - }; - - expect(httpService.post).toHaveBeenCalledWith( - MOCK_WEBHOOK_URL, - expectedBody, - { - headers: { - [HEADER_SIGNATURE_KEY]: await signMessage( - expectedBody, - MOCK_PRIVATE_KEY, - ), - }, - }, - ); - }); - it('throws an error if there request webhook sending fails', async () => { - const testError = new Error('non-axios error'); - jest.spyOn(httpService as any, 'post').mockImplementation(() => { - return throwError(() => testError); - }); - await expect( - webhookService.sendWebhook(MOCK_WEBHOOK_URL, payload), - ).rejects.toThrow(testError); - }); - }); -}); From d7c2163eb6d737644fe4e633ac91e8fdfc2ed876 Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:23:47 +0100 Subject: [PATCH 47/92] [Dashboard] Dashboard fixes after subgraph and contract upgrades (#2879) * add a flag to disable hcaptcha stats in dashboard server * add log * update if * add logs and rename * fix networks config * dashboard fixes * nullable values * filter leaders without stake * dashboard leaderboard fixes * fix if condition * fix PR comments * fix get transactions in sdks * use bigint for stake comparison * resolve PR comments * solve reduce error * Fix slice to get 4 elements Co-authored-by: Dmitry Nechay --------- Co-authored-by: Dmitry Nechay --- packages/apps/dashboard/server/.env.example | 1 + .../apps/dashboard/server/src/app.module.ts | 1 + .../src/common/config/env-config.service.ts | 9 ++ .../config/network-config.service.spec.ts | 25 ++--- .../common/config/network-config.service.ts | 17 ++- .../server/src/common/utils/constants.ts | 12 --- .../src/modules/details/details.controller.ts | 11 +- .../src/modules/details/details.service.ts | 102 +++++++----------- .../details/dto/details-pagination.dto.ts | 9 +- .../src/modules/details/dto/leader.dto.ts | 5 +- .../server/src/modules/stats/stats.service.ts | 36 +++++-- packages/apps/dashboard/ui-2024/.env.example | 1 + .../Leaderboard/hooks/useDataGrid.tsx | 2 +- .../apps/dashboard/ui-2024/src/helpers/env.ts | 1 + .../tableComponents/TransactionsTableBody.tsx | 3 + .../tableComponents/TransactionsTableHead.tsx | 7 +- .../services/api/use-leaderboard-details.tsx | 31 +++--- .../ui-2024/src/utils/config/networks.ts | 5 +- .../src/utils/hooks/use-wallet-search.ts | 3 +- .../human_protocol_sdk/gql/transaction.py | 29 +++-- .../src/graphql/queries/transaction.ts | 19 ++-- .../human-protocol-sdk/src/interfaces.ts | 2 +- .../human-protocol-sdk/src/operator.ts | 2 + .../human-protocol-sdk/test/operator.test.ts | 8 +- 24 files changed, 180 insertions(+), 161 deletions(-) diff --git a/packages/apps/dashboard/server/.env.example b/packages/apps/dashboard/server/.env.example index 73e98cca79..053bef6647 100644 --- a/packages/apps/dashboard/server/.env.example +++ b/packages/apps/dashboard/server/.env.example @@ -11,6 +11,7 @@ HMT_PRICE_SOURCE_API_KEY= HMT_PRICE_FROM= HMT_PRICE_TO= HCAPTCHA_API_KEY= +HCAPTCHA_STATS_ENABLED= NETWORK_USAGE_FILTER_MONTHS= NETWORKS_AVAILABLE_CACHE_TTL= diff --git a/packages/apps/dashboard/server/src/app.module.ts b/packages/apps/dashboard/server/src/app.module.ts index 63d2d03153..32a3f3a478 100644 --- a/packages/apps/dashboard/server/src/app.module.ts +++ b/packages/apps/dashboard/server/src/app.module.ts @@ -27,6 +27,7 @@ import { StatsModule } from './modules/stats/stats.module'; HCAPTCHA_API_KEY: Joi.string().required(), CACHE_HMT_PRICE_TTL: Joi.number(), CACHE_HMT_GENERAL_STATS_TTL: Joi.number(), + HCAPTCHA_STATS_ENABLED: Joi.boolean().default(true), }), }), CacheModule.registerAsync(CacheFactoryConfig), diff --git a/packages/apps/dashboard/server/src/common/config/env-config.service.ts b/packages/apps/dashboard/server/src/common/config/env-config.service.ts index d600003f87..dcd11ebed7 100644 --- a/packages/apps/dashboard/server/src/common/config/env-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/env-config.service.ts @@ -13,6 +13,7 @@ const DEFAULT_HCAPTCHA_STATS_SOURCE = const DEFAULT_HCAPTCHA_STATS_FILE = 'hcaptchaStats.json'; export const HCAPTCHA_STATS_START_DATE = '2022-07-01'; export const HCAPTCHA_STATS_API_START_DATE = '2024-09-14'; +export const DEFAULT_HCAPTCHA_STATS_ENABLED = true; export const HMT_STATS_START_DATE = '2021-04-06'; export const MINIMUM_HMT_TRANSFERS = 5; export const DEFAULT_NETWORK_USAGE_FILTER_MONTHS = 1; @@ -82,6 +83,14 @@ export class EnvironmentConfigService { DEFAULT_HCAPTCHA_STATS_FILE, ); } + + get hCaptchaStatsEnabled(): boolean { + return this.configService.get( + 'HCAPTCHA_STATS_ENABLED', + DEFAULT_HCAPTCHA_STATS_ENABLED, + ); + } + get reputationSource(): string { return this.configService.getOrThrow('REPUTATION_SOURCE_URL'); } diff --git a/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts b/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts index 9116d86992..44ba5f464d 100644 --- a/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts +++ b/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts @@ -6,7 +6,6 @@ import { Logger } from '@nestjs/common'; import { StatisticsClient } from '@human-protocol/sdk'; import { EnvironmentConfigService } from '../../common/config/env-config.service'; import { ChainId, NETWORKS } from '@human-protocol/sdk'; -import { MainnetsId } from '../../common/utils/constants'; import { HttpService } from '@nestjs/axios'; import { NetworkConfigService } from './network-config.service'; import { ConfigService } from '@nestjs/config'; @@ -20,6 +19,12 @@ describe('NetworkConfigService', () => { let networkConfigService: NetworkConfigService; let cacheManager: Cache; + beforeAll(async () => { + process.env.RPC_URL_POLYGON = 'https://testrpc.com'; + process.env.RPC_URL_ETHEREUM = 'https://testrpc.com'; + process.env.WEB3_ENV = 'mainnet'; + }); + beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ @@ -50,15 +55,7 @@ describe('NetworkConfigService', () => { }); it('should regenerate network list when cache TTL expires', async () => { - const mockNetworkList = [ - ChainId.MAINNET, - ChainId.BSC_MAINNET, - ChainId.POLYGON, - ChainId.XLAYER, - ChainId.MOONBEAM, - ChainId.CELO, - ChainId.AVALANCHE, - ]; + const mockNetworkList = [ChainId.MAINNET, ChainId.POLYGON]; // Step 1: Initial request - populate cache jest.spyOn(cacheManager, 'get').mockResolvedValue(null); @@ -154,8 +151,8 @@ describe('NetworkConfigService', () => { it('should handle missing network configuration gracefully', async () => { jest.spyOn(cacheManager, 'get').mockResolvedValue(null); - const originalNetworkConfig = NETWORKS[MainnetsId.MAINNET]; - NETWORKS[MainnetsId.MAINNET] = undefined; + const originalNetworkConfig = NETWORKS[ChainId.MAINNET]; + NETWORKS[ChainId.MAINNET] = undefined; const mockStatisticsClient = { getHMTDailyData: jest @@ -172,10 +169,10 @@ describe('NetworkConfigService', () => { const result = await networkConfigService.getAvailableNetworks(); - expect(result).not.toContain(MainnetsId.MAINNET); + expect(result).not.toContain(ChainId.MAINNET); expect(result).toEqual(expect.arrayContaining([])); - NETWORKS[MainnetsId.MAINNET] = originalNetworkConfig; + NETWORKS[ChainId.MAINNET] = originalNetworkConfig; }); it('should handle errors in getHMTDailyData gracefully', async () => { diff --git a/packages/apps/dashboard/server/src/common/config/network-config.service.ts b/packages/apps/dashboard/server/src/common/config/network-config.service.ts index fbbe48aa3c..07e13c5f57 100644 --- a/packages/apps/dashboard/server/src/common/config/network-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/network-config.service.ts @@ -2,12 +2,6 @@ import { ChainId, NETWORKS, StatisticsClient } from '@human-protocol/sdk'; import { Inject, Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Web3Env } from '../enums/web3'; -import { - LOCALHOST_CHAIN_IDS, - MAINNET_CHAIN_IDS, - MainnetsId, - TESTNET_CHAIN_IDS, -} from '../utils/constants'; import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager'; import { AVAILABLE_NETWORKS_CACHE_KEY } from './redis-config.service'; import { @@ -15,6 +9,11 @@ import { MINIMUM_ESCROWS_COUNT, MINIMUM_HMT_TRANSFERS, } from './env-config.service'; +import { + LOCALHOST_CHAIN_IDS, + MAINNET_CHAIN_IDS, + TESTNET_CHAIN_IDS, +} from '../utils/constants'; export interface TokensList { [key: string]: string | undefined; @@ -149,8 +148,8 @@ export class NetworkConfigService { const availableNetworks = []; - for (const networkKey of Object.values(MainnetsId)) { - const chainId = MainnetsId[networkKey as keyof typeof MainnetsId]; + for (const network of Object.values(this.networks)) { + const chainId = network.chainId; const networkConfig = NETWORKS[chainId]; @@ -186,7 +185,7 @@ export class NetworkConfigService { } } catch (error) { this.logger.error( - `Error processing network ${networkKey} (Chain ID: ${chainId}): ${error.message}`, + `Error processing network Chain ID: ${chainId}): ${error.message}`, ); } } diff --git a/packages/apps/dashboard/server/src/common/utils/constants.ts b/packages/apps/dashboard/server/src/common/utils/constants.ts index 8244aa85a0..71594d0819 100644 --- a/packages/apps/dashboard/server/src/common/utils/constants.ts +++ b/packages/apps/dashboard/server/src/common/utils/constants.ts @@ -1,26 +1,14 @@ import { ChainId } from '@human-protocol/sdk'; -export enum MainnetsId { - MAINNET = ChainId.MAINNET, - BSC_MAINNET = ChainId.BSC_MAINNET, - POLYGON = ChainId.POLYGON, - MOONBEAM = ChainId.MOONBEAM, - AVALANCHE = ChainId.AVALANCHE, - CELO = ChainId.CELO, - XLAYER = ChainId.XLAYER, -} - export const LOCALHOST_CHAIN_IDS = [ChainId.LOCALHOST]; export const TESTNET_CHAIN_IDS = [ ChainId.BSC_TESTNET, ChainId.POLYGON_AMOY, ChainId.SEPOLIA, - ChainId.XLAYER_TESTNET, ]; export const MAINNET_CHAIN_IDS = [ ChainId.MAINNET, ChainId.BSC_MAINNET, ChainId.POLYGON, - ChainId.MOONBEAM, ]; diff --git a/packages/apps/dashboard/server/src/modules/details/details.controller.ts b/packages/apps/dashboard/server/src/modules/details/details.controller.ts index 4cf3683bf5..a8400a05c6 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.controller.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.controller.ts @@ -24,7 +24,6 @@ import { WalletDto } from './dto/wallet.dto'; import { EscrowDto, EscrowPaginationDto } from './dto/escrow.dto'; import { LeaderDto } from './dto/leader.dto'; import { TransactionPaginationDto } from './dto/transaction.dto'; -import { MainnetsId } from '../../common/utils/constants'; @ApiTags('Details') @Controller('/details') @@ -33,7 +32,7 @@ export class DetailsController { constructor(private readonly detailsService: DetailsService) {} @Get('/leaders') - @ApiQuery({ name: 'chainId', enum: MainnetsId, required: false }) + @ApiQuery({ name: 'chainId', enum: ChainId, required: false }) @HttpCode(200) @ApiOperation({ summary: 'Get the best leaders by role', @@ -49,11 +48,11 @@ export class DetailsController { public async leaders( @Query('chainId') chainId?: ChainId, ): Promise { - return this.detailsService.getBestLeadersByRole(chainId); + return this.detailsService.getLeadersByChainId(chainId, 4); } @Get('/leaders/all') - @ApiQuery({ name: 'chainId', enum: MainnetsId, required: false }) + @ApiQuery({ name: 'chainId', enum: ChainId, required: false }) @HttpCode(200) @ApiOperation({ summary: 'Get all leaders', @@ -68,11 +67,11 @@ export class DetailsController { public async allLeaders( @Query('chainId') chainId?: ChainId, ): Promise { - return this.detailsService.getAllLeaders(chainId); + return this.detailsService.getLeadersByChainId(chainId); } @Get('/:address') - @ApiQuery({ name: 'chainId', enum: MainnetsId }) + @ApiQuery({ name: 'chainId', enum: ChainId }) @HttpCode(200) @ApiOperation({ summary: 'Get address details', diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index 22c1b82469..d17f2e63e0 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -8,6 +8,7 @@ import { IEscrowsFilter, Role, NETWORKS, + ILeader, } from '@human-protocol/sdk'; import { WalletDto } from './dto/wallet.dto'; @@ -147,68 +148,40 @@ export class DetailsService { return result; } - public async getBestLeadersByRole(chainId?: ChainId): Promise { + public async getLeadersByChainId( + chainId?: ChainId, + take?: number, + ): Promise { const chainIds = !chainId ? await this.networkConfig.getAvailableNetworks() : [chainId]; - const leadersByRole: { [role: string]: LeaderDto } = {}; - + let allLeadersData: ILeader[] = []; for (const id of chainIds) { const leadersData = await OperatorUtils.getLeaders({ chainId: id }); - - for (const leaderData of leadersData) { - const leaderDto: LeaderDto = plainToInstance(LeaderDto, leaderData, { - excludeExtraneousValues: true, - }); - leaderDto.chainId = id; - - const role = leaderDto.role; - - if (Object.values(Role).includes(role)) { - if ( - !leadersByRole[role] || - BigInt(leaderDto.amountStaked) > - BigInt(leadersByRole[role].amountStaked) - ) { - leadersByRole[role] = leaderDto; - } - } - } + allLeadersData = allLeadersData.concat( + leadersData.filter((leader) => leader.amountStaked > 0 && leader.role), + ); } - const reputations = await this.fetchReputations(); - this.assignReputationsToLeaders(Object.values(leadersByRole), reputations); - - return Object.values(leadersByRole); - } - - public async getAllLeaders(chainId?: ChainId): Promise { - const chainIds = !chainId - ? await this.networkConfig.getAvailableNetworks() - : [chainId]; - - const allLeaders: LeaderDto[] = []; + allLeadersData.sort((a, b) => + BigInt(a.amountStaked) >= BigInt(b.amountStaked) ? -1 : 1, + ); + if (take && take > 0) { + allLeadersData = allLeadersData.slice(0, take); + } + const leaders = allLeadersData.map((leader) => + plainToInstance(LeaderDto, leader, { + excludeExtraneousValues: true, + }), + ); for (const id of chainIds) { - const leadersData = await OperatorUtils.getLeaders({ chainId: id }); - - for (const leaderData of leadersData) { - const leaderDto: LeaderDto = plainToInstance(LeaderDto, leaderData, { - excludeExtraneousValues: true, - }); - leaderDto.chainId = id; - - if (leaderDto.role) { - allLeaders.push(leaderDto); - } - } + const reputations = await this.fetchReputations(id); + this.assignReputationsToLeaders(leaders, reputations, id); } - const reputations = await this.fetchReputations(); - this.assignReputationsToLeaders(allLeaders, reputations); - - return allLeaders; + return leaders; } private async fetchReputation( @@ -233,16 +206,16 @@ export class DetailsService { } } - private async fetchReputations(): Promise< - { address: string; reputation: string }[] - > { + private async fetchReputations( + chainId: ChainId, + ): Promise<{ address: string; reputation: string }[]> { try { const response = await firstValueFrom( this.httpService.get( this.configService.reputationSource + '/reputation', { params: { - chain_id: ChainId.POLYGON, + chain_id: chainId, roles: [ OracleRole.JOB_LAUNCHER, OracleRole.EXCHANGE_ORACLE, @@ -255,7 +228,10 @@ export class DetailsService { ); return response.data; } catch (error) { - this.logger.error('Error fetching reputations:', error); + this.logger.error( + `Error fetching reputations for chain id ${chainId}`, + error, + ); return []; } } @@ -263,15 +239,19 @@ export class DetailsService { private assignReputationsToLeaders( leaders: LeaderDto[], reputations: { address: string; reputation: string }[], + chainId: ChainId, ) { const reputationMap = new Map( reputations.map((rep) => [rep.address.toLowerCase(), rep.reputation]), ); - leaders.forEach((leader) => { - const reputation = reputationMap.get(leader.address.toLowerCase()); - if (reputation) { - leader.reputation = reputation; - } - }); + + leaders + .filter((leader) => leader.chainId === chainId) + .forEach((leader) => { + const reputation = reputationMap.get(leader.address.toLowerCase()); + if (reputation) { + leader.reputation = reputation; + } + }); } } diff --git a/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts index fafe9b7ca9..a672b6b450 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts @@ -12,12 +12,11 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ChainId } from '@human-protocol/sdk'; import { IsRoleValid } from './validation/role-validation'; -import { MainnetsId } from '../../../common/utils/constants'; export class DetailsTransactionsPaginationDto { - @ApiProperty({ enum: MainnetsId }) + @ApiProperty({ enum: ChainId }) @IsEnum(ChainId) - @IsIn(Object.values(MainnetsId)) + @IsIn(Object.values(ChainId)) @Transform(({ value }) => parseInt(value)) public chainId: ChainId; @@ -45,9 +44,9 @@ export class DetailsTransactionsPaginationDto { } export class DetailsEscrowsPaginationDto { - @ApiProperty({ enum: MainnetsId }) + @ApiProperty({ enum: ChainId }) @IsEnum(ChainId) - @IsIn(Object.values(MainnetsId)) + @IsIn(Object.values(ChainId)) @Transform(({ value }) => parseInt(value)) public chainId: ChainId; diff --git a/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts index 75e868ece5..ed495d2627 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/leader.dto.ts @@ -13,6 +13,7 @@ import { ChainId, Role } from '@human-protocol/sdk'; export class LeaderDto { @ApiProperty({ example: ChainId.POLYGON_AMOY }) @IsEnum(ChainId) + @Expose() public chainId: ChainId; @ApiProperty({ example: '0xb794f5ea0ba39494ce839613fffba74279579268' }) @@ -32,13 +33,13 @@ export class LeaderDto { public role?: string; @ApiProperty({ example: '0.07007358932392' }) - @Transform(({ value }) => value.toString()) + @Transform(({ value }) => value?.toString()) @IsString() @Expose() public amountStaked: string; @ApiProperty({ example: 'High' }) - @Transform(({ value }) => value.toString()) + @Transform(({ value }) => value?.toString()) @IsString() @Expose() public reputation: string; diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts index 34b653c953..223afe5326 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts @@ -23,6 +23,8 @@ import { CachedHMTData } from './stats.interface'; import { HmtDailyStatsData } from './dto/hmt.dto'; import { StorageService } from '../storage/storage.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; +import { CronJob } from 'cron'; +import { SchedulerRegistry } from '@nestjs/schedule'; @Injectable() export class StatsService implements OnModuleInit { @@ -34,13 +36,27 @@ export class StatsService implements OnModuleInit { private readonly envConfigService: EnvironmentConfigService, private readonly httpService: HttpService, private readonly storageService: StorageService, - ) {} + private schedulerRegistry: SchedulerRegistry, + ) { + if (this.envConfigService.hCaptchaStatsEnabled === true) { + const job = new CronJob('*/15 * * * *', () => { + this.fetchTodayHcaptchaStats(); + }); + + this.schedulerRegistry.addCronJob('fetchTodayHcaptchaStats', job); + job.start(); + } + } async onModuleInit() { const isHistoricalDataFetched = await this.isHistoricalDataFetched(); const isHmtGeneralStatsFetched = await this.isHmtGeneralStatsFetched(); const isHmtDailyStatsFetched = await this.isHmtDailyStatsFetched(); - if (!isHistoricalDataFetched) { + + if ( + this.envConfigService.hCaptchaStatsEnabled === true && + !isHistoricalDataFetched + ) { await this.fetchHistoricalHcaptchaStats(); } if (!isHmtGeneralStatsFetched) { @@ -115,7 +131,6 @@ export class StatsService implements OnModuleInit { return !!data; } - @Cron('*/15 * * * *') async fetchTodayHcaptchaStats() { this.logger.log('Fetching hCaptcha stats for today.'); const today = dayjs().format('YYYY-MM-DD'); @@ -374,12 +389,15 @@ export class StatsService implements OnModuleInit { }), ); - const aggregatedStats: HcaptchaStats = stats.reduce((acc, stat) => { - if (stat) { - acc.solved += stat.solved; - } - return acc; - }); + const aggregatedStats: HcaptchaStats = stats.reduce( + (acc, stat) => { + if (stat) { + acc.solved += stat.solved; + } + return acc; + }, + { solved: 0 }, + ); return aggregatedStats; } diff --git a/packages/apps/dashboard/ui-2024/.env.example b/packages/apps/dashboard/ui-2024/.env.example index 6e12058f14..62ebf481d3 100644 --- a/packages/apps/dashboard/ui-2024/.env.example +++ b/packages/apps/dashboard/ui-2024/.env.example @@ -19,3 +19,4 @@ VITE_FOOTER_LINK_TERMS_OF_SERVICE= VITE_FOOTER_LINK_PRIVACY_POLICY= VITE_FOOTER_LINK_HUMAN_PROTOCOL= +VITE_ENABLED_CHAIN_IDS= diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/hooks/useDataGrid.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/hooks/useDataGrid.tsx index 2cab0dc949..af0af375c5 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/hooks/useDataGrid.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/hooks/useDataGrid.tsx @@ -27,7 +27,7 @@ export const useDataGrid = (data: LeaderBoardData) => { return data.map((row, idx) => { return { ...row, - id: row.address, + id: `${row.address}${row.chainId}`, rowIndex: idx, }; }); diff --git a/packages/apps/dashboard/ui-2024/src/helpers/env.ts b/packages/apps/dashboard/ui-2024/src/helpers/env.ts index 07a00a5e84..c3705d0224 100644 --- a/packages/apps/dashboard/ui-2024/src/helpers/env.ts +++ b/packages/apps/dashboard/ui-2024/src/helpers/env.ts @@ -16,6 +16,7 @@ const envSchema = z.object({ VITE_FOOTER_LINK_X: z.string(), VITE_FOOTER_LINK_TELEGRAM: z.string(), VITE_FOOTER_LINK_LINKEDIN: z.string(), + VITE_ENABLED_CHAIN_IDS: z.string(), }); let validEnvs; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx index bcffdb7470..90de6c0603 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx @@ -74,6 +74,9 @@ export const TransactionsTableBody = () => { + + + diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx index 692f774955..eecfa4c5d4 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx @@ -83,9 +83,10 @@ export const TransactionsTableHead = () => { - - Escrow Address - + From + + + To diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx index 693151ad61..29b0d02cb7 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-leaderboard-details.tsx @@ -22,23 +22,26 @@ export type Reputation = z.infer; const leaderBoardEntity = z.object({ address: z.string(), role: z.string(), - amountStaked: z.string().transform((value, ctx) => { - const valueAsNumber = Number(value); + amountStaked: z + .string() + .transform((value, ctx) => { + const valueAsNumber = Number(value); - if (Number.isNaN(valueAsNumber)) { - ctx.addIssue({ - path: ['amountStaked'], - code: z.ZodIssueCode.custom, - }); - } + if (Number.isNaN(valueAsNumber)) { + ctx.addIssue({ + path: ['amountStaked'], + code: z.ZodIssueCode.custom, + }); + } - return valueAsNumber / 10 ** 18; - }), + return valueAsNumber / 10 ** 18; + }) + .nullable(), reputation: reputationSchema, - fee: z.number(), - jobTypes: z.array(z.string()), - url: z.string(), - website: z.string().optional(), + fee: z.number().nullable(), + jobTypes: z.array(z.string()).nullable(), + url: z.string().nullable(), + website: z.string().nullable(), chainId: z.number(), }); diff --git a/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts b/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts index 208e722704..db3fd5cdda 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts +++ b/packages/apps/dashboard/ui-2024/src/utils/config/networks.ts @@ -1,7 +1,10 @@ import type { Chain } from 'viem/chains'; import * as chains from 'viem/chains'; +import { env } from '@helpers/env'; -const chainIdsList = [1, 56, 137, 1284, 43114, 42220, 196]; +//TODO: temporal fix. Should be fetched from API. https://github.com/humanprotocol/human-protocol/issues/2855 +const ENABLED_CHAIN_IDS = env.VITE_ENABLED_CHAIN_IDS; +const chainIdsList = ENABLED_CHAIN_IDS.split(',').map((id) => parseInt(id, 10)); const viemChains = Object.values(chains); diff --git a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts index a550725ec3..fcefb87180 100644 --- a/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts +++ b/packages/apps/dashboard/ui-2024/src/utils/hooks/use-wallet-search.ts @@ -1,3 +1,4 @@ +import { networks } from '../config/networks'; import { create } from 'zustand'; export interface WalletSearchStore { @@ -12,7 +13,7 @@ export interface WalletSearchStore { export const useWalletSearch = create((set) => ({ filterParams: { address: '', - chainId: 137, + chainId: networks[0].id, }, setAddress: (address) => { set((state) => ({ diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py index 2e301f444b..84ab386a74 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/transaction.py @@ -27,27 +27,34 @@ def get_transactions_query(filter: TransactionFilter) -> str: + start_date = filter.start_date + end_date = filter.end_date + start_block = filter.start_block + end_block = filter.end_block from_address = filter.from_address to_address = filter.to_address - if from_address == to_address: - address_condition = f""" + address_condition = ( + f""" {f'{{ from: $fromAddress }}' if from_address else ''} {f'{{ or: [{{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }}, {{ internalTransactions_: {{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }} }}] }}' if to_address else ''} """ - else: - address_condition = f""" - {f'from: $fromAddress' if from_address else ''} - {f'or: [{{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }}, {{ internalTransactions_: {{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }} }}]' if to_address else ''} + if from_address == to_address + else f""" + {f'{{ from: $fromAddress }}' if from_address else ''} + {f'{{ or: [{{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }}, {{ internalTransactions_: {{ or: [{{ to: $toAddress }}, {{ receiver: $toAddress }}] }} }}] }}' if to_address else ''} """ + ) where_clause = f""" where: {{ - {"or: [" + address_condition + "]," if from_address and from_address == to_address else address_condition} - {f'timestamp_gte: $startDate,' if filter.start_date else ''} - {f'timestamp_lte: $endDate,' if filter.end_date else ''} - {f'block_gte: $startBlock,' if filter.start_block else ''} - {f'block_lte: $endBlock,' if filter.end_block else ''} + and: [ + {f'{{ or: [ {address_condition} ] }},' if from_address and from_address == to_address else address_condition} + {f'{{ timestamp_gte: $startDate }},' if start_date else ''} + {f'{{ timestamp_lte: $endDate }},' if end_date else ''} + {f'{{ block_gte: $startBlock }},' if start_block else ''} + {f'{{ block_lte: $endBlock }},' if end_block else ''} + ] }} """ diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts index 04d0edeecc..a10533c7fc 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/transaction.ts @@ -29,25 +29,26 @@ const TRANSACTION_FRAGMENT = gql` export const GET_TRANSACTIONS_QUERY = (filter: ITransactionsFilter) => { const { startDate, endDate, startBlock, endBlock, fromAddress, toAddress } = filter; - const addressCondition = fromAddress === toAddress ? ` ${fromAddress ? `{ from: $fromAddress }` : ''} - ${toAddress ? `{ or: [{ or: [{ to: $toAddress }, { receiver: $toAddress }] }, {internalTransactions_: { or: [{ to: $toAddress }, { receiver: $toAddress }] } ]}` : ''} + ${toAddress ? `{ or: [{ or: [{ to: $toAddress }, { receiver: $toAddress }] }, {internalTransactions_: { or: [{ to: $toAddress }, { receiver: $toAddress }] } }] }` : ''} ` : ` - ${fromAddress ? `from: $fromAddress` : ''} - ${toAddress ? `or: [{ or: [{ to: $toAddress }, { receiver: $toAddress }] }, { internalTransactions_: { or: [{ to: $toAddress }, { receiver: $toAddress }] } }]` : ''} + ${fromAddress ? `{ from: $fromAddress }` : ''} + ${toAddress ? `{ or: [{ or: [{ to: $toAddress }, { receiver: $toAddress }] }, { internalTransactions_: { or: [{ to: $toAddress }, { receiver: $toAddress }] } }] }` : ''} `; const WHERE_CLAUSE = ` where: { - ${fromAddress && fromAddress === toAddress ? `or: [ ${addressCondition} ],` : addressCondition} - ${startDate ? `timestamp_gte: $startDate,` : ''} - ${endDate ? `timestamp_lte: $endDate,` : ''} - ${startBlock ? `block_gte: $startBlock,` : ''} - ${endBlock ? `block_lte: $endBlock,` : ''} + and: [ + ${fromAddress && fromAddress === toAddress ? `{or: [ ${addressCondition} ]},` : `${addressCondition}`} + ${startDate ? `{timestamp_gte: $startDate},` : ''} + ${endDate ? `{timestamp_lte: $endDate},` : ''} + ${startBlock ? `{block_gte: $startBlock},` : ''} + ${endBlock ? `{block_lte: $endBlock},` : ''} + ] } `; diff --git a/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts b/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts index 005b9fdc58..eae61b94d3 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts @@ -30,7 +30,7 @@ export interface ILeader { } export interface ILeaderSubgraph - extends Omit { + extends Omit { jobTypes?: string; reputationNetworks?: { address: string }[]; } diff --git a/packages/sdk/typescript/human-protocol-sdk/src/operator.ts b/packages/sdk/typescript/human-protocol-sdk/src/operator.ts index f62ba07001..1f220ced6d 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/operator.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/operator.ts @@ -83,6 +83,7 @@ export class OperatorUtils { ...leader, jobTypes, reputationNetworks, + chainId, }; } @@ -147,6 +148,7 @@ export class OperatorUtils { ...leader, jobTypes, reputationNetworks, + chainId: filter.chainId, }; }) ); diff --git a/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts index d4be89f1a4..b2216c4c42 100644 --- a/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts +++ b/packages/sdk/typescript/human-protocol-sdk/test/operator.test.ts @@ -36,7 +36,6 @@ describe('OperatorUtils', () => { const mockLeaderSubgraph: ILeaderSubgraph = { id: stakerAddress, - chainId: ChainId.LOCALHOST, address: stakerAddress, amountStaked: ethers.parseEther('100'), amountLocked: ethers.parseEther('25'), @@ -60,6 +59,7 @@ describe('OperatorUtils', () => { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2'], reputationNetworks: ['0x01'], + chainId: ChainId.LOCALHOST, }; test('should return staker information', async () => { @@ -88,6 +88,7 @@ describe('OperatorUtils', () => { ...mockLeaderSubgraph, jobTypes: [], reputationNetworks: ['0x01'], + chainId: ChainId.LOCALHOST, }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ @@ -115,6 +116,7 @@ describe('OperatorUtils', () => { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2', 'type3'], reputationNetworks: ['0x01'], + chainId: ChainId.LOCALHOST, }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ @@ -179,7 +181,6 @@ describe('OperatorUtils', () => { const mockLeaderSubgraph: ILeaderSubgraph = { id: stakerAddress, - chainId: ChainId.LOCALHOST, address: stakerAddress, amountStaked: ethers.parseEther('100'), amountLocked: ethers.parseEther('25'), @@ -203,6 +204,7 @@ describe('OperatorUtils', () => { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2'], reputationNetworks: ['0x01'], + chainId: ChainId.LOCALHOST, }; test('should return an array of stakers', async () => { @@ -229,6 +231,7 @@ describe('OperatorUtils', () => { ...mockLeaderSubgraph, jobTypes: [], reputationNetworks: ['0x01'], + chainId: ChainId.LOCALHOST, }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ @@ -254,6 +257,7 @@ describe('OperatorUtils', () => { ...mockLeaderSubgraph, jobTypes: ['type1', 'type2', 'type3'], reputationNetworks: ['0x01'], + chainId: ChainId.LOCALHOST, }; const gqlFetchSpy = vi.spyOn(gqlFetch, 'default').mockResolvedValueOnce({ From fc09b6c763264dd6a441429a468d694b6bd003c9 Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Tue, 10 Dec 2024 15:12:50 +0100 Subject: [PATCH 48/92] [Dashboard] feat: remove address search from header (#2885) --- .../ui-2024/src/assets/styles/_header.scss | 10 ---- .../src/assets/styles/_page-wrapper.scss | 3 -- .../ui-2024/src/assets/styles/_search.scss | 9 ++-- .../ui-2024/src/components/Header/Header.tsx | 16 +----- .../components/PageWrapper/PageWrapper.tsx | 6 +-- .../components/SearchBar/SearchBar.styles.ts | 10 ++-- .../src/components/SearchBar/SearchBar.tsx | 50 ++++++------------- .../ui-2024/src/pages/Graph/Graph.tsx | 2 +- .../ui-2024/src/pages/Leaderboard/index.tsx | 2 +- .../src/pages/SearchResults/SearchResults.tsx | 4 +- 10 files changed, 32 insertions(+), 80 deletions(-) diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss b/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss index c5d9226ae8..348816444b 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/_header.scss @@ -53,16 +53,6 @@ } } -.header-toolbar-search { - @media (max-width: 1280px) { - height: 118px; - flex-wrap: wrap; - } - .search-header-mobile { - width: 100%; - } -} - .header-mobile-menu { padding: 20px 10px; .header-list-link { diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss b/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss index e61b976157..6891dda980 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/_page-wrapper.scss @@ -25,9 +25,6 @@ @media (max-width: 1280px) { min-height: calc(100vh - 386px); margin: 0 24px; - &.search-white-header { - min-height: calc(100vh - 438px); - } } @media (max-width: 600px) { diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss b/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss index 4ecd62206c..014fe3047c 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/_search.scss @@ -2,6 +2,9 @@ position: relative; width: 920px; max-width: 100%; + border: 1px solid #DADEF0CC; + border-radius: 13px; + #search-bar{ width: 100%; @@ -16,6 +19,7 @@ -webkit-text-fill-color: $primary; box-shadow: 0 0 0px 1000px $white inset; } + } .search-close{ @@ -36,10 +40,7 @@ .search-results-bar { display: block; - - @media (max-width: 1280px) { - display: none; - } + } .search-white{ diff --git a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx index f0dc922aa5..97db534fe9 100644 --- a/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/Header/Header.tsx @@ -7,14 +7,13 @@ import MenuIcon from '@mui/icons-material/Menu'; import Drawer from '@mui/material/Drawer'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; -import SearchBar from '@components/SearchBar/SearchBar'; import { env } from '@helpers/env'; import { useNavigate } from 'react-router-dom'; import { LogoBlockIcon } from '@components/Icons/LogoBlockIcon'; import { LogoBlockIconMobile } from '@components/Icons/LogoBlockIconMobile'; import CloseIcon from '@mui/icons-material/Close'; -const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { +const Header: FC = () => { const navigate = useNavigate(); const [open, setState] = useState(false); @@ -27,14 +26,7 @@ const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { }; return ( - - {displaySearchBar && ( - - )} + { navigate('/'); @@ -54,10 +46,6 @@ const Header: FC<{ displaySearchBar?: boolean }> = ({ displaySearchBar }) => { - {displaySearchBar && ( - - )} -
-> = ({ children, violetHeader, displaySearchBar, className }) => { +> = ({ children, violetHeader, className }) => { return (
-
+
{children}
diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts index 52ec4fbf79..228cd04a4c 100644 --- a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts +++ b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.styles.ts @@ -22,12 +22,12 @@ export const gridSx = { overflow: 'hidden', }; -export const muiSelectSx = ( - isTopBar: boolean, - mobile: { isMobile: boolean; mediaQuery: string } -) => ({ +export const muiSelectSx = (mobile: { + isMobile: boolean; + mediaQuery: string; +}) => ({ backgroundColor: `${colorPalette.white}`, - width: isTopBar ? '220px' : 'unset', + width: 'unset', fontSize: '16px', boxShadow: 'none', outline: 'none', diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx index 1f65a19bcd..b9ca414eb7 100644 --- a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx @@ -30,31 +30,27 @@ import { interface SearchBarProps { className?: string; - displaySearchBar?: boolean; - isTopBar?: boolean; initialInputValue?: string; } const SearchBar: FC = ({ className = '', - displaySearchBar, initialInputValue = '', - isTopBar = false, }) => { const { mobile } = useBreakPoints(); const [inputValue, setInputValue] = useState(initialInputValue); - const [selectValue, setSelectValue] = useState(null); + const [selectValue, setSelectValue] = useState(''); const [focus, setFocus] = useState(false); - const { filterParams, setAddress, setChainId } = useWalletSearch(); + const { filterParams } = useWalletSearch(); const navigate = useNavigate(); const navigateToAddress = useCallback( (chainIdParam?: number | undefined) => { - const chainId = chainIdParam || filterParams.chainId || -1; - const address = (isTopBar ? filterParams.address : inputValue) || ''; + const chainId = chainIdParam || selectValue || -1; + const address = inputValue || ''; navigate(`/search/${chainId}/${address}`); }, - [filterParams.address, filterParams.chainId, inputValue, isTopBar, navigate] + [inputValue, selectValue, navigate] ); useEffect(() => { @@ -62,27 +58,19 @@ const SearchBar: FC = ({ if (networkName) { setSelectValue(filterParams.chainId); } - }, [filterParams.chainId, navigateToAddress]); + }, [filterParams.chainId]); useEffect(() => { setInputValue(filterParams.address); }, [filterParams.address]); const handleInputChange = (event: React.ChangeEvent) => { - if (isTopBar) { - setAddress(event.target.value); - } else { - setInputValue(event.target.value); - } + setInputValue(event.target.value); }; - const handleSelectChange = (event: SelectChangeEvent) => { + const handleSelectChange = (event: SelectChangeEvent) => { const chainId = Number(event.target.value); - if (inputValue && !!inputValue.length) { - navigateToAddress(chainId); - } else { - setChainId(chainId); - } + setSelectValue(chainId); }; const handleClearClick = () => { @@ -91,9 +79,6 @@ const SearchBar: FC = ({ const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); - if (!isTopBar) { - setAddress(inputValue); - } if (inputValue && !!inputValue.length) { navigateToAddress(); } @@ -111,18 +96,13 @@ const SearchBar: FC = ({
{mobile.isMobile || !selectValue ? null - : getNetwork(selectValue)?.name || ''} + : getNetwork(Number(selectValue))?.name || ''}
); return ( -
+ = ({ position="start" sx={startAdornmentInputAdornmentSx} > - + value={selectValue} displayEmpty - sx={muiSelectSx(isTopBar, mobile)} + sx={muiSelectSx(mobile)} onChange={handleSelectChange} renderValue={() => selectValue === null ? renderEmptyValue : renderSelectedValue @@ -189,9 +169,7 @@ const SearchBar: FC = ({ > diff --git a/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx b/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx index 22e6e35593..acd739e787 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx @@ -24,7 +24,7 @@ const Graph = () => { }, []); return ( - + { const isMoreThatFiveEntries = data?.length && data.length > 5; return ( - + { return ( <> { }, [address, chainId, paramsStatus]); return ( - + {paramsStatus === 'loading' && } From 245fb6e6d95fd0147127602058803da10006576b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:01:07 +0100 Subject: [PATCH 49/92] Show network name in job details (#2897) --- .../job-launcher/client/src/pages/Job/JobDetail/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx index d5f2f15fca..2e82d61122 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx @@ -1,3 +1,4 @@ +import { ChainId, NETWORKS } from '@human-protocol/sdk'; import { LoadingButton } from '@mui/lab'; import { Box, Card, Grid, IconButton, Stack, Typography } from '@mui/material'; import { styled } from '@mui/material/styles'; @@ -155,8 +156,8 @@ export default function JobDetail() { {data.manifest.title && ( From c16c9236f581525b0e49263f43700eee501cbb66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:29:42 +0100 Subject: [PATCH 50/92] Allow direct call to complete after bulkPayOut (#2896) * Allow direct call to complete after bulkPayOut * redeploy contract on testnets --------- Co-authored-by: portuu3 --- packages/core/.openzeppelin/bsc-testnet.json | 149 ++++++++++++++++++ packages/core/.openzeppelin/sepolia.json | 149 ++++++++++++++++++ .../core/.openzeppelin/unknown-80002.json | 149 ++++++++++++++++++ packages/core/contracts/Escrow.sol | 26 +-- packages/core/test/Escrow-USDT.ts | 84 +++++++++- packages/core/test/Escrow.ts | 85 +++++++++- 6 files changed, 628 insertions(+), 14 deletions(-) diff --git a/packages/core/.openzeppelin/bsc-testnet.json b/packages/core/.openzeppelin/bsc-testnet.json index dd0690a620..6c7ae72df7 100644 --- a/packages/core/.openzeppelin/bsc-testnet.json +++ b/packages/core/.openzeppelin/bsc-testnet.json @@ -1709,6 +1709,155 @@ }, "namespaces": {} } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0xb9D3688D0ECE314c1bDAf14BeD36eD589c8d31A5", + "txHash": "0xb69e2d7a7f390b636f597358c41ecc377fdbdd250b04cba0d16f06aad1b9aae8", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/sepolia.json b/packages/core/.openzeppelin/sepolia.json index b91768abe2..345bff1701 100644 --- a/packages/core/.openzeppelin/sepolia.json +++ b/packages/core/.openzeppelin/sepolia.json @@ -876,6 +876,155 @@ }, "namespaces": {} } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0x683874D7578f480f48CE2fA1C13fCBC621C2e7c8", + "txHash": "0x47651e1b2a3c6985251125ccdffaeb2b70e176861c2250b7a21f23382fa40778", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/unknown-80002.json b/packages/core/.openzeppelin/unknown-80002.json index 77c67dfd9e..c23989064e 100644 --- a/packages/core/.openzeppelin/unknown-80002.json +++ b/packages/core/.openzeppelin/unknown-80002.json @@ -876,6 +876,155 @@ }, "namespaces": {} } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0xF70D3dF4Dd79Bb679Bea3C88689c9758D57c3556", + "txHash": "0x1384d3805b2b53d7db38c56b87f5526eec32a5b6c31ee094953449d1ec89d3b2", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/contracts/Escrow.sol b/packages/core/contracts/Escrow.sol index 7d890dd3f7..bf8a6550a2 100644 --- a/packages/core/contracts/Escrow.sol +++ b/packages/core/contracts/Escrow.sol @@ -217,10 +217,19 @@ contract Escrow is IEscrow, ReentrancyGuard { return true; } - // For backward compatibility: this function can only be called on existing escrows, - // as the "Paid" status is not set anywhere for new escrows. function complete() external override notExpired trustedOrReputationOracle { - require(status == EscrowStatuses.Paid, 'Escrow not in Paid state'); + require( + status == EscrowStatuses.Paid || status == EscrowStatuses.Partial, + 'Escrow not in Paid or Partial state' + ); + _complete(); + } + + function _complete() private { + if (remainingFunds > 0) { + _safeTransfer(token, launcher, remainingFunds); + remainingFunds = 0; + } status = EscrowStatuses.Complete; emit Completed(); } @@ -345,14 +354,7 @@ contract Escrow is IEscrow, ReentrancyGuard { remainingFunds = cachedRemainingFunds; - // Check the forceComplete flag and transfer remaining funds if true - if (forceComplete && cachedRemainingFunds > 0) { - _safeTransfer(token, launcher, cachedRemainingFunds); - cachedRemainingFunds = 0; - } - - if (cachedRemainingFunds == 0) { - status = EscrowStatuses.Complete; + if (cachedRemainingFunds == 0 || forceComplete) { emit BulkTransferV2( _txId, _recipients, @@ -360,7 +362,7 @@ contract Escrow is IEscrow, ReentrancyGuard { false, finalResultsUrl ); - emit Completed(); + _complete(); } else { status = EscrowStatuses.Partial; emit BulkTransferV2( diff --git a/packages/core/test/Escrow-USDT.ts b/packages/core/test/Escrow-USDT.ts index 62853600f9..c8cb771f5d 100644 --- a/packages/core/test/Escrow-USDT.ts +++ b/packages/core/test/Escrow-USDT.ts @@ -841,7 +841,7 @@ describe('Escrow with USDT', function () { (finalBalanceExchangeOracle - initialBalanceExchangeOracle).toString() ).to.equal('6'); - expect(await escrow.remainingFunds()).to.equal('40'); + expect(await escrow.remainingFunds()).to.equal('0'); }); it('Should runs from setup to bulkPayOut to complete correctly', async () => { @@ -976,4 +976,86 @@ describe('Escrow with USDT', function () { }); }); }); + describe('complete', () => { + describe('Validations', function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should revert with the right error if escrow not in Paid or Partial state', async function () { + await expect(escrow.connect(owner).complete()).to.be.revertedWith( + 'Escrow not in Paid or Partial state' + ); + }); + }); + + describe('Events', function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + + const recipients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recipients, amounts, MOCK_URL, MOCK_HASH, '000', false); + }); + + it('Should emit a Completed event when escrow is completed', async function () { + await expect(escrow.connect(owner).complete()).to.emit( + escrow, + 'Completed' + ); + }); + }); + + describe('Complete escrow', async function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should succeed if escrow is in Partial state', async function () { + const recipients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recipients, amounts, MOCK_URL, MOCK_HASH, '000', false); + expect(await escrow.status()).to.equal(Status.Partial); + + await escrow.connect(owner).complete(); + expect(await escrow.status()).to.equal(Status.Complete); + expect(await escrow.remainingFunds()).to.equal('0'); + }); + + it('Should transfer remaining funds to launcher on complete', async function () { + const initialLauncherBalance = await usdt + .connect(owner) + .balanceOf(await launcher.getAddress()); + + const recipients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recipients, amounts, MOCK_URL, MOCK_HASH, '000', false); + await escrow.connect(owner).complete(); + + const finalLauncherBalance = await usdt + .connect(owner) + .balanceOf(await launcher.getAddress()); + + expect(finalLauncherBalance - initialLauncherBalance).to.equal('90'); + }); + }); + }); }); diff --git a/packages/core/test/Escrow.ts b/packages/core/test/Escrow.ts index 82c4903af1..85c01fc5a9 100644 --- a/packages/core/test/Escrow.ts +++ b/packages/core/test/Escrow.ts @@ -833,7 +833,7 @@ describe('Escrow', function () { (finalBalanceExchangeOracle - initialBalanceExchangeOracle).toString() ).to.equal('6'); - expect(await escrow.remainingFunds()).to.equal('40'); + expect(await escrow.remainingFunds()).to.equal('0'); }); it('Should runs from setup to bulkPayOut to complete correctly', async () => { @@ -901,4 +901,87 @@ describe('Escrow', function () { }); }); }); + describe('complete', () => { + describe('Validations', function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should revert with the right error if escrow not in Paid or Partial state', async function () { + await expect(escrow.connect(owner).complete()).to.be.revertedWith( + 'Escrow not in Paid or Partial state' + ); + }); + }); + + describe('Events', function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should emit a Completed event when escrow is completed', async function () { + const recipients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + + await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recipients, amounts, MOCK_URL, MOCK_HASH, '000', false); + + await expect(escrow.connect(owner).complete()).to.emit( + escrow, + 'Completed' + ); + }); + }); + + describe('Complete escrow', async function () { + beforeEach(async () => { + await deployEscrow(); + await fundEscrow(); + await setupEscrow(); + }); + + it('Should succeed if escrow is in Partial state', async function () { + const recipients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recipients, amounts, MOCK_URL, MOCK_HASH, '000', false); + expect(await escrow.status()).to.equal(Status.Partial); + + await escrow.connect(owner).complete(); + expect(await escrow.status()).to.equal(Status.Complete); + expect(await escrow.remainingFunds()).to.equal('0'); + }); + + it('Should transfer remaining funds to launcher on complete', async function () { + const initialLauncherBalance = await token + .connect(owner) + .balanceOf(await launcher.getAddress()); + + const recipients = [await restAccounts[0].getAddress()]; + const amounts = [10]; + await escrow + .connect(owner) + [ + 'bulkPayOut(address[],uint256[],string,string,uint256,bool)' + ](recipients, amounts, MOCK_URL, MOCK_HASH, '000', false); + await escrow.connect(owner).complete(); + + const finalLauncherBalance = await token + .connect(owner) + .balanceOf(await launcher.getAddress()); + + expect(finalLauncherBalance - initialLauncherBalance).to.equal('90'); + }); + }); + }); }); From 92f42e70dc715897789056ed03f6b6d1a25a1245 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:32:10 +0100 Subject: [PATCH 51/92] chore(deps-dev): bump ts-jest from 29.2.2 to 29.2.5 (#2889) Bumps [ts-jest](https://github.com/kulshekhar/ts-jest) from 29.2.2 to 29.2.5. - [Release notes](https://github.com/kulshekhar/ts-jest/releases) - [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.2.2...v29.2.5) --- updated-dependencies: - dependency-name: ts-jest dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- packages/apps/dashboard/server/package.json | 2 +- .../exchange-oracle/server/package.json | 2 +- packages/apps/human-app/server/package.json | 2 +- .../apps/job-launcher/server/package.json | 2 +- .../reputation-oracle/server/package.json | 2 +- yarn.lock | 27 +++++-------------- 7 files changed, 12 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index dd77f647da..e79139e449 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "jest-environment-jsdom": "^29.7.0", "lint-staged": "^15.2.7", "prettier": "^3.2.5", - "ts-jest": "^29.2.2", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "^5.6.3" }, diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 8d0b68e7e1..1811a71c5c 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -51,7 +51,7 @@ "prettier": "^2.3.2", "source-map-support": "^0.5.20", "supertest": "^7.0.0", - "ts-jest": "29.2.2", + "ts-jest": "29.2.5", "ts-loader": "^9.2.3", "ts-node": "^10.0.0", "tsconfig-paths": "4.2.0", diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index e9e7ba7963..24f6440a91 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -56,7 +56,7 @@ "pg": "8.13.1", "source-map-support": "^0.5.20", "supertest": "^7.0.0", - "ts-jest": "29.2.2", + "ts-jest": "29.2.5", "ts-loader": "^9.2.3", "ts-node": "^10.9.2", "tsconfig-paths": "4.2.0", diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index c786dab218..b1eec6f47c 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -59,7 +59,7 @@ "prettier": "^3.1.1", "source-map-support": "^0.5.20", "supertest": "^7.0.0", - "ts-jest": "29.2.2", + "ts-jest": "29.2.5", "ts-loader": "^9.2.3", "ts-node": "^10.9.2", "tsconfig-paths": "4.2.0", diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index f0b4a765b5..df1fa493cf 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -83,7 +83,7 @@ "prettier": "^3.2.5", "source-map-support": "^0.5.20", "supertest": "^7.0.0", - "ts-jest": "29.2.2", + "ts-jest": "29.2.5", "ts-loader": "^9.2.3", "ts-node": "^10.9.2", "tsconfig-paths": "4.2.0", diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 0d0fdffd8a..cdb4cf82ca 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -79,7 +79,7 @@ "prettier": "^3.2.5", "source-map-support": "^0.5.20", "supertest": "^7.0.0", - "ts-jest": "29.2.2", + "ts-jest": "29.2.5", "ts-loader": "^9.2.3", "ts-node": "^10.9.2", "tsconfig-paths": "4.2.0", diff --git a/yarn.lock b/yarn.lock index 8e8a6a94f0..369f3f3c16 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8209,7 +8209,7 @@ browserslist@^4.24.0, browserslist@^4.24.2: node-releases "^2.0.18" update-browserslist-db "^1.1.1" -bs-logger@0.x, bs-logger@^0.2.6: +bs-logger@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== @@ -10055,7 +10055,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -ejs@3.1.8, ejs@^3.0.0, ejs@^3.1.10, ejs@^3.1.8: +ejs@3.1.8, ejs@^3.1.10, ejs@^3.1.8: version "3.1.10" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== @@ -14641,7 +14641,7 @@ lodash.lowerfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.lowerfirst/-/lodash.lowerfirst-4.3.1.tgz#de3c7b12e02c6524a0059c2f6cb7c5c52655a13d" integrity sha512-UUKX7VhP1/JL54NXg2aq/E1Sfnjjes8fNYTNkPU8ZmsaVeBvPHKdbNaN79Re5XRL01u6wbq3j0cbYZj71Fcu5w== -lodash.memoize@4.x, lodash.memoize@^4.1.2: +lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -14855,7 +14855,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@1.x, make-error@^1.1.1, make-error@^1.3.6: +make-error@^1.1.1, make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -19433,22 +19433,7 @@ ts-invariant@^0.10.3: dependencies: tslib "^2.1.0" -ts-jest@29.2.2: - version "29.2.2" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.2.tgz#0d2387bb04d39174b20a05172a968f258aedff4d" - integrity sha512-sSW7OooaKT34AAngP6k1VS669a0HdLxkQZnlC7T76sckGCokXFnvJ3yRlQZGRTAoV5K19HfSgCiSwWOSIfcYlg== - dependencies: - bs-logger "0.x" - ejs "^3.0.0" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" - -ts-jest@^29.2.2: +ts-jest@29.2.5, ts-jest@^29.2.5: version "29.2.5" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== @@ -21140,7 +21125,7 @@ yaml@~2.5.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.1.tgz#c9772aacf62cb7494a95b0c4f1fb065b563db130" integrity sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q== -yargs-parser@21.1.1, yargs-parser@^21.0.0, yargs-parser@^21.0.1, yargs-parser@^21.1.1: +yargs-parser@21.1.1, yargs-parser@^21.0.0, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== From 7d16ddf03d361af6896f9b26aaabc245c30ddf5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:33:23 +0100 Subject: [PATCH 52/92] chore(deps-dev): bump typedoc from 0.26.11 to 0.27.4 (#2890) Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.26.11 to 0.27.4. - [Release notes](https://github.com/TypeStrong/TypeDoc/releases) - [Changelog](https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md) - [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.26.11...v0.27.4) --- updated-dependencies: - dependency-name: typedoc dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../human-protocol-sdk/package.json | 2 +- yarn.lock | 307 ++---------------- 2 files changed, 30 insertions(+), 279 deletions(-) diff --git a/packages/sdk/typescript/human-protocol-sdk/package.json b/packages/sdk/typescript/human-protocol-sdk/package.json index f2771bf517..697bfd2c4d 100644 --- a/packages/sdk/typescript/human-protocol-sdk/package.json +++ b/packages/sdk/typescript/human-protocol-sdk/package.json @@ -50,7 +50,7 @@ "vitest": "^1.6.0" }, "devDependencies": { - "typedoc": "^0.26.5", + "typedoc": "^0.27.4", "typedoc-plugin-markdown": "^4.2.3" }, "typedocOptions": { diff --git a/yarn.lock b/yarn.lock index 369f3f3c16..45447c02f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2143,6 +2143,15 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@gerrit0/mini-shiki@^1.24.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@gerrit0/mini-shiki/-/mini-shiki-1.24.1.tgz#60ef10f4e2cfac7a9223e10b88c128438aa44fd8" + integrity sha512-PNP/Gjv3VqU7z7DjRgO3F9Ok5frTKqtpV+LJW1RzMcr2zpRk0ulhEWnbcNGXzPC7BZyWMIHrkfQX2GZRfxrn6Q== + dependencies: + "@shikijs/engine-oniguruma" "^1.24.0" + "@shikijs/types" "^1.24.0" + "@shikijs/vscode-textmate" "^9.3.0" + "@golevelup/ts-jest@^0.6.1": version "0.6.1" resolved "https://registry.yarnpkg.com/@golevelup/ts-jest/-/ts-jest-0.6.1.tgz#d3aa4aa337d84477b06b0d25a81254da73cccbe9" @@ -4737,39 +4746,18 @@ "@sentry/types" "5.30.0" tslib "^1.9.3" -"@shikijs/core@1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.24.0.tgz#5a90301df89f3a60d5ed9610d6537631fcd1c506" - integrity sha512-6pvdH0KoahMzr6689yh0QJ3rCgF4j1XsXRHNEeEN6M4xJTfQ6QPWrmHzIddotg+xPJUPEPzYzYCKzpYyhTI6Gw== - dependencies: - "@shikijs/engine-javascript" "1.24.0" - "@shikijs/engine-oniguruma" "1.24.0" - "@shikijs/types" "1.24.0" - "@shikijs/vscode-textmate" "^9.3.0" - "@types/hast" "^3.0.4" - hast-util-to-html "^9.0.3" - -"@shikijs/engine-javascript@1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.24.0.tgz#7f7f7afd3210601ba9c7d966f00c7a167f9f6453" - integrity sha512-ZA6sCeSsF3Mnlxxr+4wGEJ9Tto4RHmfIS7ox8KIAbH0MTVUkw3roHPHZN+LlJMOHJJOVupe6tvuAzRpN8qK1vA== - dependencies: - "@shikijs/types" "1.24.0" - "@shikijs/vscode-textmate" "^9.3.0" - oniguruma-to-es "0.7.0" - -"@shikijs/engine-oniguruma@1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.0.tgz#4e6f49413fbc96dabfa30cb232ca1acf5ca1a446" - integrity sha512-Eua0qNOL73Y82lGA4GF5P+G2+VXX9XnuUxkiUuwcxQPH4wom+tE39kZpBFXfUuwNYxHSkrSxpB1p4kyRW0moSg== +"@shikijs/engine-oniguruma@^1.24.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.1.tgz#cf9f74867987a786057dbf599f571800f7ec5b30" + integrity sha512-KdrTIBIONWd+Xs61eh8HdIpfigtrseat9dpARvaOe2x0g/FNTbwbkGr3y92VSOVD1XotzEskh3v/nCzyWjkf7g== dependencies: - "@shikijs/types" "1.24.0" + "@shikijs/types" "1.24.1" "@shikijs/vscode-textmate" "^9.3.0" -"@shikijs/types@1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.24.0.tgz#a1755b125cb8fb1780a876a0a57242939eafd79f" - integrity sha512-aptbEuq1Pk88DMlCe+FzXNnBZ17LCiLIGWAeCWhoFDzia5Q5Krx3DgnULLiouSdd6+LUM39XwXGppqYE0Ghtug== +"@shikijs/types@1.24.1", "@shikijs/types@^1.24.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.24.1.tgz#669c7165f9ee3caa475fadd61f7ed4ca0009e848" + integrity sha512-ZwZFbShFY/APfKNt3s9Gv8rhTm29GodSKsOW66X6N+HGsZuaHalE1VUEX4fv93UXHTZTLjb3uxn63F96RhGfXw== dependencies: "@shikijs/vscode-textmate" "^9.3.0" "@types/hast" "^3.0.4" @@ -5583,7 +5571,7 @@ dependencies: "@types/node" "*" -"@types/hast@^3.0.0", "@types/hast@^3.0.4": +"@types/hast@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== @@ -5716,13 +5704,6 @@ resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.4.2.tgz#e4fc7214a420173cea47739c33cdf10874694db7" integrity sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA== -"@types/mdast@^4.0.0": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" - integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== - dependencies: - "@types/unist" "*" - "@types/methods@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547" @@ -6013,7 +5994,7 @@ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== -"@types/unist@*", "@types/unist@^3.0.0": +"@types/unist@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== @@ -6377,7 +6358,7 @@ "@typescript-eslint/types" "8.16.0" eslint-visitor-keys "^4.2.0" -"@ungap/structured-clone@^1.0.0", "@ungap/structured-clone@^1.2.0": +"@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== @@ -8540,11 +8521,6 @@ cborg@^1.5.4, cborg@^1.6.0: preact "^10.16.0" sha.js "^2.4.11" -ccount@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" - integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== - chai-as-promised@^7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" @@ -8623,16 +8599,6 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -character-entities-html4@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" - integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== - -character-entities-legacy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" - integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== - chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -9006,11 +8972,6 @@ combined-stream@^1.0.6, combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -comma-separated-tokens@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" - integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== - command-exists@^1.2.8: version "1.2.9" resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" @@ -9790,7 +9751,7 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -dequal@^2.0.0, dequal@^2.0.3: +dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== @@ -9843,13 +9804,6 @@ detect-newline@^4.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-4.0.1.tgz#fcefdb5713e1fb8cb2839b8b6ee22e6716ab8f23" integrity sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog== -devlop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" - integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== - dependencies: - dequal "^2.0.0" - dezalgo@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" @@ -10105,11 +10059,6 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== -emoji-regex-xs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz#e8af22e5d9dbd7f7f22d280af3d19d2aab5b0724" - integrity sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg== - emoji-regex@^10.3.0: version "10.4.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" @@ -12489,30 +12438,6 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" -hast-util-to-html@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz#a9999a0ba6b4919576a9105129fead85d37f302b" - integrity sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg== - dependencies: - "@types/hast" "^3.0.0" - "@types/unist" "^3.0.0" - ccount "^2.0.0" - comma-separated-tokens "^2.0.0" - hast-util-whitespace "^3.0.0" - html-void-elements "^3.0.0" - mdast-util-to-hast "^13.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - stringify-entities "^4.0.0" - zwitch "^2.0.4" - -hast-util-whitespace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" - integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== - dependencies: - "@types/hast" "^3.0.0" - he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -12609,11 +12534,6 @@ html-parse-stringify@^3.0.1: dependencies: void-elements "3.1.0" -html-void-elements@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" - integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== - http-basic@^8.1.1: version "8.1.3" resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" @@ -14989,21 +14909,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -mdast-util-to-hast@^13.0.0: - version "13.2.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" - integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA== - dependencies: - "@types/hast" "^3.0.0" - "@types/mdast" "^4.0.0" - "@ungap/structured-clone" "^1.0.0" - devlop "^1.0.0" - micromark-util-sanitize-uri "^2.0.0" - trim-lines "^3.0.0" - unist-util-position "^5.0.0" - unist-util-visit "^5.0.0" - vfile "^6.0.0" - mdurl@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" @@ -15081,38 +14986,6 @@ micro-ftch@^0.3.1: resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== -micromark-util-character@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz#2f987831a40d4c510ac261e89852c4e9703ccda6" - integrity sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q== - dependencies: - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-util-encode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz#0d51d1c095551cfaac368326963cf55f15f540b8" - integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw== - -micromark-util-sanitize-uri@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz#ab89789b818a58752b73d6b55238621b7faa8fd7" - integrity sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ== - dependencies: - micromark-util-character "^2.0.0" - micromark-util-encode "^2.0.0" - micromark-util-symbol "^2.0.0" - -micromark-util-symbol@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz#e5da494e8eb2b071a0d08fb34f6cefec6c0a19b8" - integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q== - -micromark-util-types@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.1.tgz#a3edfda3022c6c6b55bfb049ef5b75d70af50709" - integrity sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ== - micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@~4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" @@ -16088,15 +15961,6 @@ onetime@^7.0.0: dependencies: mimic-function "^5.0.0" -oniguruma-to-es@0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-0.7.0.tgz#999fe7df1e6acae4507e2d77afc6de4fc8533116" - integrity sha512-HRaRh09cE0gRS3+wi2zxekB+I5L8C/gN60S+vb11eADHUaB/q4u8wGGOX3GvwvitG8ixaeycZfeoyruKQzUgNg== - dependencies: - emoji-regex-xs "^1.0.0" - regex "^5.0.2" - regex-recursion "^4.3.0" - open@^8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" @@ -16913,11 +16777,6 @@ property-expr@^2.0.5: resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.6.tgz#f77bc00d5928a6c748414ad12882e83f24aec1e8" integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA== -property-information@^6.0.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" - integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== - proto3-json-serializer@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz#5b705203b4d58f3880596c95fad64902617529dd" @@ -17519,25 +17378,6 @@ regenerator-transform@^0.15.2: dependencies: "@babel/runtime" "^7.8.4" -regex-recursion@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/regex-recursion/-/regex-recursion-4.3.0.tgz#32c3a42a57d78bf2d0c83875074c2f7ebaf2a4f6" - integrity sha512-5LcLnizwjcQ2ALfOj95MjcatxyqF5RPySx9yT+PaXu3Gox2vyAtLDjHB8NTJLtMGkvyau6nI3CfpwFCjPUIs/A== - dependencies: - regex-utilities "^2.3.0" - -regex-utilities@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/regex-utilities/-/regex-utilities-2.3.0.tgz#87163512a15dce2908cf079c8960d5158ff43280" - integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng== - -regex@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/regex/-/regex-5.0.2.tgz#291d960467e6499a79ceec022d20a4e0df67c54f" - integrity sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ== - dependencies: - regex-utilities "^2.3.0" - regexp-tree@^0.1.27: version "0.1.27" resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" @@ -18148,18 +17988,6 @@ shelljs@^0.8.3: interpret "^1.0.0" rechoir "^0.6.2" -shiki@^1.16.2: - version "1.24.0" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.24.0.tgz#ea374523cbf32df0141ad3e5f79d16aea901ab69" - integrity sha512-qIneep7QRwxRd5oiHb8jaRzH15V/S8F3saCXOdjwRLgozZJr5x2yeBhQtqkO3FSzQDwYEFAYuifg4oHjpDghrg== - dependencies: - "@shikijs/core" "1.24.0" - "@shikijs/engine-javascript" "1.24.0" - "@shikijs/engine-oniguruma" "1.24.0" - "@shikijs/types" "1.24.0" - "@shikijs/vscode-textmate" "^9.3.0" - "@types/hast" "^3.0.4" - side-channel@^1.0.4, side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -18428,11 +18256,6 @@ source-map@~0.2.0: dependencies: amdefine ">=0.0.4" -space-separated-tokens@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" - integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== - spawn-command@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" @@ -18763,14 +18586,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -stringify-entities@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" - integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== - dependencies: - character-entities-html4 "^2.0.0" - character-entities-legacy "^3.0.0" - "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -19391,11 +19206,6 @@ tree-kill@1.2.2, tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -trim-lines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" - integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== - trim-newlines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" @@ -19729,16 +19539,16 @@ typedoc-plugin-markdown@^4.2.3: resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.3.0.tgz#d4ee289ea8e04b03801dc476eb3090142983bfe5" integrity sha512-yAR7+JGSwHWNzQhS8AFlGX6GmbWnK7/Q2Y8hHy5pkL/WB9ooJqhsI6B1abldhM3lOQCWqCdkzu9yFMPuvl2HUw== -typedoc@^0.26.5: - version "0.26.11" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.26.11.tgz#124b43a5637b7f3237b8c721691b44738c5c9dc9" - integrity sha512-sFEgRRtrcDl2FxVP58Ze++ZK2UQAEvtvvH8rRlig1Ja3o7dDaMHmaBfvJmdGnNEFaLTpQsN8dpvZaTqJSu/Ugw== +typedoc@^0.27.4: + version "0.27.4" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.27.4.tgz#45be59ccf9383d3c52f4a96636d823345c6ff0e6" + integrity sha512-wXPQs1AYC2Crk+1XFpNuutLIkNWleokZf1UNf/X8w9KsMnirkvT+LzxTXDvfF6ug3TSLf3Xu5ZXRKGfoXPX7IA== dependencies: + "@gerrit0/mini-shiki" "^1.24.0" lunr "^2.3.9" markdown-it "^14.1.0" minimatch "^9.0.5" - shiki "^1.16.2" - yaml "^2.5.1" + yaml "^2.6.1" typeorm-naming-strategies@^4.1.0: version "4.1.0" @@ -19938,44 +19748,6 @@ unique-slug@^4.0.0: dependencies: imurmurhash "^0.1.4" -unist-util-is@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" - integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-position@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" - integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-stringify-position@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" - integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-visit-parents@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" - integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== - dependencies: - "@types/unist" "^3.0.0" - unist-util-is "^6.0.0" - -unist-util-visit@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" - integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== - dependencies: - "@types/unist" "^3.0.0" - unist-util-is "^6.0.0" - unist-util-visit-parents "^6.0.0" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -20195,22 +19967,6 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -vfile-message@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181" - integrity sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw== - dependencies: - "@types/unist" "^3.0.0" - unist-util-stringify-position "^4.0.0" - -vfile@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab" - integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q== - dependencies: - "@types/unist" "^3.0.0" - vfile-message "^4.0.0" - victory-vendor@^36.6.8: version "36.9.2" resolved "https://registry.yarnpkg.com/victory-vendor/-/victory-vendor-36.9.2.tgz#668b02a448fa4ea0f788dbf4228b7e64669ff801" @@ -21115,7 +20871,7 @@ yaml@1.10.2, yaml@^1.10.0, yaml@^1.10.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.5.1: +yaml@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.1.tgz#42f2b1ba89203f374609572d5349fb8686500773" integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== @@ -21260,11 +21016,6 @@ zustand@^4.5.0, zustand@^4.5.4: dependencies: use-sync-external-store "1.2.2" -zwitch@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" - integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== - zxcvbn@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30" From 4a4252909d59d53d743b0484e797c5f1cadf6a21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:33:45 +0100 Subject: [PATCH 53/92] chore(deps-dev): bump eslint-plugin-react-hooks from 4.6.2 to 5.1.0 (#2891) Bumps [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks) from 4.6.2 to 5.1.0. - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/HEAD/packages/eslint-plugin-react-hooks) --- updated-dependencies: - dependency-name: eslint-plugin-react-hooks dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/dashboard/ui-2024/package.json | 2 +- packages/apps/faucet/client/package.json | 2 +- packages/apps/fortune/exchange-oracle/client/package.json | 2 +- packages/apps/job-launcher/client/package.json | 2 +- yarn.lock | 7 ++++++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/apps/dashboard/ui-2024/package.json b/packages/apps/dashboard/ui-2024/package.json index a7f36a64a2..5abf592ce1 100644 --- a/packages/apps/dashboard/ui-2024/package.json +++ b/packages/apps/dashboard/ui-2024/package.json @@ -46,7 +46,7 @@ "@typescript-eslint/parser": "^7.2.0", "@vitejs/plugin-react": "^4.2.1", "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.11", "prettier": "3.2.5", "sass": "^1.78.0", diff --git a/packages/apps/faucet/client/package.json b/packages/apps/faucet/client/package.json index 70736ced0e..015111815b 100644 --- a/packages/apps/faucet/client/package.json +++ b/packages/apps/faucet/client/package.json @@ -21,7 +21,7 @@ "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.29.0", "eslint-plugin-react": "^7.34.3", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-hooks": "^5.1.0", "vite": "^5.4.7", "vite-plugin-node-polyfills": "^0.22.0", "vitest": "^1.6.0" diff --git a/packages/apps/fortune/exchange-oracle/client/package.json b/packages/apps/fortune/exchange-oracle/client/package.json index 8dc8f03065..969ea82292 100644 --- a/packages/apps/fortune/exchange-oracle/client/package.json +++ b/packages/apps/fortune/exchange-oracle/client/package.json @@ -48,7 +48,7 @@ "@typescript-eslint/parser": "^7.13.1", "@vitejs/plugin-react": "^4.3.1", "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.11", "typescript": "^5.6.3", "vite": "^5.4.7" diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 83e032bb9e..aeb45efbfc 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -75,7 +75,7 @@ "eslint-import-resolver-typescript": "^3.5.3", "eslint-plugin-import": "^2.29.0", "eslint-plugin-react": "^7.34.3", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-hooks": "^5.1.0", "happy-dom": "^12.9.1", "identity-obj-proxy": "^3.0.0", "jsdom": "^25.0.1", diff --git a/yarn.lock b/yarn.lock index 45447c02f9..cc9cb8a29c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10704,11 +10704,16 @@ eslint-plugin-prettier@^5.2.1: prettier-linter-helpers "^1.0.0" synckit "^0.9.1" -eslint-plugin-react-hooks@^4.3.0, eslint-plugin-react-hooks@^4.6.0, eslint-plugin-react-hooks@^4.6.2: +eslint-plugin-react-hooks@^4.3.0, eslint-plugin-react-hooks@^4.6.0: version "4.6.2" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== +eslint-plugin-react-hooks@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz#3d34e37d5770866c34b87d5b499f5f0b53bf0854" + integrity sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw== + eslint-plugin-react-refresh@^0.4.11: version "0.4.14" resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.14.tgz#e3c611ead69bbf7436d01295c853d4abb8c59f68" From fb44b265403abfa0ac2ce9dc3d7f09ef31af0bab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:34:13 +0100 Subject: [PATCH 54/92] chore(deps-dev): bump eslint-import-resolver-typescript (#2892) Bumps [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) from 3.6.3 to 3.7.0. - [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases) - [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md) - [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v3.6.3...v3.7.0) --- updated-dependencies: - dependency-name: eslint-import-resolver-typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/faucet/client/package.json | 2 +- .../apps/job-launcher/client/package.json | 2 +- yarn.lock | 19 ++++++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/apps/faucet/client/package.json b/packages/apps/faucet/client/package.json index 015111815b..4fad0baadd 100644 --- a/packages/apps/faucet/client/package.json +++ b/packages/apps/faucet/client/package.json @@ -18,7 +18,7 @@ "devDependencies": { "dotenv": "^16.3.2", "eslint-config-react-app": "^7.0.1", - "eslint-import-resolver-typescript": "^3.5.2", + "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-import": "^2.29.0", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^5.1.0", diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index aeb45efbfc..3eab477085 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -72,7 +72,7 @@ "@types/xml2js": "^0.4.14", "@vitejs/plugin-react": "^4.2.1", "eslint-config-react-app": "^7.0.1", - "eslint-import-resolver-typescript": "^3.5.3", + "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-import": "^2.29.0", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^5.1.0", diff --git a/yarn.lock b/yarn.lock index cc9cb8a29c..0769667c52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10585,21 +10585,21 @@ eslint-import-resolver-node@^0.3.9: is-core-module "^2.13.0" resolve "^1.22.4" -eslint-import-resolver-typescript@^3.5.2, eslint-import-resolver-typescript@^3.5.3, eslint-import-resolver-typescript@^3.6.1: - version "3.6.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz#bb8e388f6afc0f940ce5d2c5fd4a3d147f038d9e" - integrity sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA== +eslint-import-resolver-typescript@^3.6.1, eslint-import-resolver-typescript@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz#e69925936a771a9cb2de418ccebc4cdf6c0818aa" + integrity sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow== dependencies: "@nolyfill/is-core-module" "1.0.39" - debug "^4.3.5" + debug "^4.3.7" enhanced-resolve "^5.15.0" - eslint-module-utils "^2.8.1" fast-glob "^3.3.2" get-tsconfig "^4.7.5" is-bun-module "^1.0.2" is-glob "^4.0.3" + stable-hash "^0.0.4" -eslint-module-utils@^2.12.0, eslint-module-utils@^2.8.1: +eslint-module-utils@^2.12.0: version "2.12.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz#fe4cfb948d61f49203d7b08871982b65b9af0b0b" integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== @@ -18350,6 +18350,11 @@ ssri@^9.0.0: dependencies: minipass "^3.1.1" +stable-hash@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stable-hash/-/stable-hash-0.0.4.tgz#55ae7dadc13e4b3faed13601587cec41859b42f7" + integrity sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g== + stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" From 3d163ed3065753edc069ca4277b5461fa4cca57f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:34:35 +0100 Subject: [PATCH 55/92] chore(deps-dev): bump @types/react-test-renderer from 18.3.0 to 19.0.0 (#2893) Bumps [@types/react-test-renderer](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-test-renderer) from 18.3.0 to 19.0.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-test-renderer) --- updated-dependencies: - dependency-name: "@types/react-test-renderer" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/job-launcher/client/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 3eab477085..6cd3e465e3 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -68,7 +68,7 @@ "@types/file-saver": "^2.0.7", "@types/react": "^18.3.12", "@types/react-dom": "^18.2.25", - "@types/react-test-renderer": "^18.0.0", + "@types/react-test-renderer": "^19.0.0", "@types/xml2js": "^0.4.14", "@vitejs/plugin-react": "^4.2.1", "eslint-config-react-app": "^7.0.1", diff --git a/yarn.lock b/yarn.lock index 0769667c52..39527c865c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5880,10 +5880,10 @@ "@types/history" "^4.7.11" "@types/react" "*" -"@types/react-test-renderer@^18.0.0": - version "18.3.0" - resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz#839502eae70058a4ae161f63385a8e7929cef4c0" - integrity sha512-HW4MuEYxfDbOHQsVlY/XtOvNHftCVEPhJF2pQXXwcUiUF+Oyb0usgp48HSgpK5rt8m9KZb22yqOeZm+rrVG8gw== +"@types/react-test-renderer@^19.0.0": + version "19.0.0" + resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-19.0.0.tgz#4cdeace7561bf359ee167f51704f420c07d4bd8d" + integrity sha512-qDVnNybqFm2eZKJ4jD34EvRd6VHD67KjgnWaEMM0Id9L22EpWe3nOSVKHWL1XWRCxUWe3lhXwlEeCKD1BlJCQA== dependencies: "@types/react" "*" From aa106a7ff079765408b6a456bdc689f635ad6ace Mon Sep 17 00:00:00 2001 From: Arseny Boykov <36469655+Bobronium@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:23:15 +0100 Subject: [PATCH 56/92] Add debug.py for ease of local development (#2763) * Add debug.py for ease of local development * [Exchange Oracle] Make `generate_jwt_token` reusable in local development scripts * [Exchange Oracle] Add local development keys to .gitignore * [Exchange Oracle] Fix lenient_validate_oracle_webhook_signature patch * [Exchange Oracle] Patch request signing function in debug.py This simplifies communication between oracles when running locally. * [Exchange Oracle] Add bucket for manifests * [Exchange Oracle] Allow plain json as token for local development * Add start_debug.sh and mention it in readme * Fix linting problems * Use url for storage from the config * [Exchange Oracle] Support host substitution for CVAT storage config * Add logging whenever patches happen for transparency * Update ENV variables names --- .../examples/cvat/exchange-oracle/.gitignore | 4 + .../examples/cvat/exchange-oracle/README.md | 17 +- .../cvat/exchange-oracle/bin/start_debug.sh | 4 + .../examples/cvat/exchange-oracle/debug.py | 173 ++++++++++++++++++ .../exchange-oracle/docker-compose.dev.yml | 1 + .../cvat/exchange-oracle/src/.env.template | 5 + .../cvat/exchange-oracle/src/core/config.py | 7 + .../src/endpoints/authentication.py | 10 +- .../tests/api/test_exchange_api.py | 23 +-- .../examples/cvat/recording-oracle/README.MD | 17 +- .../cvat/recording-oracle/bin/start_debug.sh | 4 + .../examples/cvat/recording-oracle/debug.py | 129 +++++++++++++ .../recording-oracle/docker-compose.dev.yml | 2 +- 13 files changed, 375 insertions(+), 21 deletions(-) create mode 100755 packages/examples/cvat/exchange-oracle/bin/start_debug.sh create mode 100644 packages/examples/cvat/exchange-oracle/debug.py create mode 100755 packages/examples/cvat/recording-oracle/bin/start_debug.sh create mode 100644 packages/examples/cvat/recording-oracle/debug.py diff --git a/packages/examples/cvat/exchange-oracle/.gitignore b/packages/examples/cvat/exchange-oracle/.gitignore index a5aacf7cb6..12f5b4f876 100644 --- a/packages/examples/cvat/exchange-oracle/.gitignore +++ b/packages/examples/cvat/exchange-oracle/.gitignore @@ -5,3 +5,7 @@ __pycache__/ # Env file .env .python-version + +# Local development keys +human_app_public_key.pem +human_app_private_key.pem diff --git a/packages/examples/cvat/exchange-oracle/README.md b/packages/examples/cvat/exchange-oracle/README.md index 6a4412aa03..11ba79973b 100644 --- a/packages/examples/cvat/exchange-oracle/README.md +++ b/packages/examples/cvat/exchange-oracle/README.md @@ -19,10 +19,23 @@ For deployment it is required to have PostgreSQL(v14.4) ### Run the oracle locally: ``` -1. docker-compose -f docker-compose.dev.yml up -d -2. ./bin/start_dev.sh +docker-compose -f docker-compose.dev.yml up -d +./bin/start_dev.sh ``` +or + +``` +docker-compose -f docker-compose.dev.yml up -d +./bin/start_debug.sh +``` + +When running service from `./bin/start_debug.sh` (`debug.py`), simplified development flow is available: + +- When JWT token is required, simple JSON can be used instead of JWT token. +- When webhook signature is required, `{oracle_name}:unique_string` can be used +- You can upload manifest.json to minio `manifests` bucket and use its filename as an escrow_address + ### Environemt Env example file: [.env.example](https://github.com/humanprotocol/human-protocol/blob/feat/cvat/exchange-oracle/packages/examples/cvat/exchange-oracle/src/.env.example) diff --git a/packages/examples/cvat/exchange-oracle/bin/start_debug.sh b/packages/examples/cvat/exchange-oracle/bin/start_debug.sh new file mode 100755 index 0000000000..ff93f4765c --- /dev/null +++ b/packages/examples/cvat/exchange-oracle/bin/start_debug.sh @@ -0,0 +1,4 @@ +export ENVIRONMENT=development + +alembic upgrade head +python debug.py \ No newline at end of file diff --git a/packages/examples/cvat/exchange-oracle/debug.py b/packages/examples/cvat/exchange-oracle/debug.py new file mode 100644 index 0000000000..aa8052cdd1 --- /dev/null +++ b/packages/examples/cvat/exchange-oracle/debug.py @@ -0,0 +1,173 @@ +import datetime +import hashlib +import json +from pathlib import Path +from typing import Any + +import uvicorn +from httpx import URL + +from src.chain.kvstore import register_in_kvstore +from src.core.config import Config +from src.services import cloud +from src.services.cloud import BucketAccessInfo +from src.utils.logging import get_function_logger + + +def apply_local_development_patches(): + """ + Applies local development patches to avoid manual source code modification.: + - Overrides `EscrowUtils.get_escrow` to return local escrow data with mock values if the escrow + address matches a local manifest. + - Loads local manifest files from cloud storage into `LOCAL_MANIFEST_FILES`. + - Disables address validation by overriding `validate_address`. + - Replaces `validate_oracle_webhook_signature` with a lenient version that uses + partial signature parsing. + - Generates ECDSA keys if not already present for local JWT signing, + and sets the public key in `Config.human_app_config`. + """ + import src.handlers.job_creation + + original_make_cvat_cloud_storage_params = ( + src.handlers.job_creation._make_cvat_cloud_storage_params + ) + + def patched_make_cvat_cloud_storage_params(bucket_info: BucketAccessInfo) -> dict: + original_host_url = bucket_info.host_url + + if Config.development_config.cvat_in_docker: + bucket_info.host_url = str( + URL(original_host_url).copy_with(host=Config.development_config.cvat_local_host) + ) + logger.info( + f"DEV: Changed {original_host_url} to {bucket_info.host_url} for CVAT storage" + ) + try: + return original_make_cvat_cloud_storage_params(bucket_info) + finally: + bucket_info.host_url = original_host_url + + src.handlers.job_creation._make_cvat_cloud_storage_params = ( + patched_make_cvat_cloud_storage_params + ) + + def prepare_signed_message( + escrow_address, + chain_id, + message: str | None = None, + body: dict | None = None, + ) -> tuple[None, str]: + digest = hashlib.sha256( + (escrow_address + ":".join(map(str, (chain_id, message, body)))).encode() + ).hexdigest() + signature = f"{OracleWebhookTypes.recording_oracle}:{digest}" + logger.info(f"DEV: Generated patched signature {signature}") + return None, signature + + src.utils.webhooks.prepare_signed_message = prepare_signed_message + + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.escrow import EscrowData, EscrowUtils + + logger = get_function_logger(apply_local_development_patches.__name__) + + minio_client = cloud.make_client(BucketAccessInfo.parse_obj(Config.storage_config)) + + def get_local_escrow(chain_id: int, escrow_address: str) -> EscrowData: + possible_manifest_name = escrow_address.split(":")[0] + local_manifests = minio_client.list_files(bucket="manifests") + logger.info(f"DEV: Local manifests: {local_manifests}") + if possible_manifest_name in local_manifests: + logger.info(f"DEV: Using local manifest {escrow_address}") + return EscrowData( + chain_id=ChainId(chain_id), + id="test", + address=escrow_address, + amount_paid=10, + balance=10, + count=1, + factory_address="", + launcher="", + status="Pending", + token="HMT", # noqa: S106 + total_funded_amount=10, + created_at=datetime.datetime(2023, 1, 1, tzinfo=datetime.timezone.utc), + manifest_url=( + f"http://{Config.storage_config.endpoint_url}/manifests/{possible_manifest_name}" + ), + ) + return original_get_escrow(ChainId(chain_id), escrow_address) + + original_get_escrow = EscrowUtils.get_escrow + EscrowUtils.get_escrow = get_local_escrow + + import src.schemas.webhook + from src.core.types import OracleWebhookTypes + + src.schemas.webhook.validate_address = lambda x: x + + async def lenient_validate_oracle_webhook_signature(request, signature, webhook): + from src.validators.signature import validate_oracle_webhook_signature + + try: + parsed_type = OracleWebhookTypes(signature.split(":")[0]) + logger.info(f"DEV: Recovered {parsed_type} from the signature {signature}") + except (ValueError, TypeError): + return await validate_oracle_webhook_signature(request, signature, webhook) + + import src.endpoints.webhook + + src.endpoints.webhook.validate_oracle_webhook_signature = ( + lenient_validate_oracle_webhook_signature + ) + + import src.endpoints.authentication + + original_decode_token = src.endpoints.authentication.TokenAuthenticator._decode_token + + def decode_plain_json_token(self, token) -> dict[str, Any]: + """ + Allows Authentication: Bearer {"wallet_address": "...", "email": "..."} + """ + try: + decoded = json.loads(token) + logger.info(f"DEV: Decoded plain JSON auth token: {decoded}") + except (ValueError, TypeError): + return original_decode_token(self, token) + + src.endpoints.authentication.TokenAuthenticator._decode_token = decode_plain_json_token + + from tests.api.test_exchange_api import generate_ecdsa_keys + + # generating keys for local development + repo_root = Path(__file__).parent + human_app_private_key_file, human_app_public_key_file = ( + repo_root / "human_app_private_key.pem", + repo_root / "human_app_public_key.pem", + ) + if not (human_app_public_key_file.exists() and human_app_private_key_file.exists()): + private_key, public_key = generate_ecdsa_keys() + human_app_private_key_file.write_text(private_key) + human_app_public_key_file.write_text(public_key) + else: + public_key = human_app_public_key_file.read_text() + + Config.human_app_config.jwt_public_key = public_key + + logger.warning("DEV: Local development patches applied.") + + +if __name__ == "__main__": + is_dev = Config.environment == "development" + if is_dev: + apply_local_development_patches() + + Config.validate() + register_in_kvstore() + + uvicorn.run( + app="src:app", + host="0.0.0.0", # noqa: S104 + port=int(Config.port), + workers=Config.workers_amount, + ) diff --git a/packages/examples/cvat/exchange-oracle/docker-compose.dev.yml b/packages/examples/cvat/exchange-oracle/docker-compose.dev.yml index 52e2218b80..cce17d493e 100644 --- a/packages/examples/cvat/exchange-oracle/docker-compose.dev.yml +++ b/packages/examples/cvat/exchange-oracle/docker-compose.dev.yml @@ -66,6 +66,7 @@ services: entrypoint: > /bin/sh -c " /usr/bin/mc config host add myminio http://minio:9010 dev devdevdev; + /usr/bin/mc mb myminio/manifests; /usr/bin/mc anonymous set public myminio/manifests; /usr/bin/mc mb myminio/excor-data; /usr/bin/mc anonymous set public myminio/excor-data; diff --git a/packages/examples/cvat/exchange-oracle/src/.env.template b/packages/examples/cvat/exchange-oracle/src/.env.template index ceb14f3e75..d05a9f1828 100644 --- a/packages/examples/cvat/exchange-oracle/src/.env.template +++ b/packages/examples/cvat/exchange-oracle/src/.env.template @@ -124,3 +124,8 @@ LOCALHOST_REPUTATION_ORACLE_URL= PGP_PRIVATE_KEY= PGP_PASSPHRASE= PGP_PUBLIC_KEY_URL= + + +# Development +DEV_CVAT_IN_DOCKER= +DEV_CVAT_LOCAL_HOST= diff --git a/packages/examples/cvat/exchange-oracle/src/core/config.py b/packages/examples/cvat/exchange-oracle/src/core/config.py index 3081d48684..d1b3c0c2b6 100644 --- a/packages/examples/cvat/exchange-oracle/src/core/config.py +++ b/packages/examples/cvat/exchange-oracle/src/core/config.py @@ -298,6 +298,12 @@ def validate(cls) -> None: raise Exception(" ".join([ex_prefix, str(ex)])) +class Development: + cvat_in_docker = bool(int(os.environ.get("DEV_CVAT_IN_DOCKER", "0"))) + # might be `host.docker.internal` or `172.22.0.1` if CVAT is running in docker + cvat_local_host = os.environ.get("DEV_CVAT_LOCAL_HOST", "localhost") + + class Environment(str, Enum): PRODUCTION = "production" DEVELOPMENT = "development" @@ -337,6 +343,7 @@ class Config: features = FeaturesConfig core_config = CoreConfig encryption_config = EncryptionConfig + development_config = Development @classmethod def is_development_mode(cls) -> bool: diff --git a/packages/examples/cvat/exchange-oracle/src/endpoints/authentication.py b/packages/examples/cvat/exchange-oracle/src/endpoints/authentication.py index 2cf4356c17..38ebcca10b 100644 --- a/packages/examples/cvat/exchange-oracle/src/endpoints/authentication.py +++ b/packages/examples/cvat/exchange-oracle/src/endpoints/authentication.py @@ -1,4 +1,4 @@ -from typing import Annotated, TypeVar +from typing import Annotated, Any, TypeVar import jwt import pydantic @@ -65,11 +65,8 @@ async def authenticate_token( # Read more https://github.com/tiangolo/fastapi/issues/1474 # Without Depends schema works, but not validation. # Thus, just use it as a separate function explicitly. - try: - payload = jwt.decode( - token.credentials, Config.human_app_config.jwt_public_key, algorithms=["ES256"] - ) + payload = self._decode_token(token.credentials) return self._auth_data_class.model_validate(payload) except (jwt.PyJWTError, pydantic.ValidationError) as e: raise HTTPException( @@ -78,6 +75,9 @@ async def authenticate_token( headers={"WWW-Authenticate": "Bearer"}, ) from e + def _decode_token(self, credentials: str) -> dict[str, Any]: + return jwt.decode(credentials, Config.human_app_config.jwt_public_key, algorithms=["ES256"]) + def make_auth_dependency(auth_data_class: AuthDataT | None = None) -> params.Depends: if auth_data_class: diff --git a/packages/examples/cvat/exchange-oracle/tests/api/test_exchange_api.py b/packages/examples/cvat/exchange-oracle/tests/api/test_exchange_api.py index a5eebfd58d..ef6e0b02c4 100644 --- a/packages/examples/cvat/exchange-oracle/tests/api/test_exchange_api.py +++ b/packages/examples/cvat/exchange-oracle/tests/api/test_exchange_api.py @@ -56,20 +56,19 @@ def generate_ecdsa_keys() -> tuple[str, str]: def generate_jwt_token( *, - wallet_address: str | None = user_address, + wallet_address: str | None = None, email: str = cvat_email, + private_key: str = PRIVATE_KEY, ) -> str: - return jwt.encode( - { - **({"wallet_address": wallet_address} if wallet_address else {"role": "human_app"}), - "email": email, - }, - PRIVATE_KEY, - algorithm="ES256", - ) + data = { + **({"wallet_address": wallet_address} if wallet_address else {"role": "human_app"}), + "email": email, + } + return jwt.encode(data, private_key, algorithm="ES256") -def get_auth_header(token: str = generate_jwt_token()) -> dict: + +def get_auth_header(token: str = generate_jwt_token(wallet_address=user_address)) -> dict: return {"Authorization": f"Bearer {token}"} @@ -724,7 +723,9 @@ def test_cannot_register_400_with_duplicated_address(client: TestClient, session response = client.post( "/register", - headers=get_auth_header(generate_jwt_token(email=new_cvat_email)), + headers=get_auth_header( + generate_jwt_token(wallet_address=user_address, email=new_cvat_email) + ), ) assert response.status_code == 400 assert response.json() == {"message": "User already exists"} diff --git a/packages/examples/cvat/recording-oracle/README.MD b/packages/examples/cvat/recording-oracle/README.MD index fb873e9ca3..c7c4e6ad1a 100644 --- a/packages/examples/cvat/recording-oracle/README.MD +++ b/packages/examples/cvat/recording-oracle/README.MD @@ -19,10 +19,23 @@ For deployment it is required to have PostgreSQL(v14.4) ### Run the oracle locally: ``` -1. docker-compose -f docker-compose.dev.yml up -d -2. ./bin/start_dev.sh +docker-compose -f docker-compose.dev.yml up -d +./bin/start_dev.sh ``` +or + +``` +docker-compose -f docker-compose.dev.yml up -d +./bin/start_debug.sh +``` + +When running service from `./bin/start_debug.sh` (`debug.py`), simplified development flow is available: + +- When webhook signature is required, `{oracle_name}:unique_string` can be used +- You can upload manifest.json to minio `manifests` bucket and use its filename as an escrow_address + + ### Environemt Env example file: `/src/.env.example` diff --git a/packages/examples/cvat/recording-oracle/bin/start_debug.sh b/packages/examples/cvat/recording-oracle/bin/start_debug.sh new file mode 100755 index 0000000000..ff93f4765c --- /dev/null +++ b/packages/examples/cvat/recording-oracle/bin/start_debug.sh @@ -0,0 +1,4 @@ +export ENVIRONMENT=development + +alembic upgrade head +python debug.py \ No newline at end of file diff --git a/packages/examples/cvat/recording-oracle/debug.py b/packages/examples/cvat/recording-oracle/debug.py new file mode 100644 index 0000000000..3915e79929 --- /dev/null +++ b/packages/examples/cvat/recording-oracle/debug.py @@ -0,0 +1,129 @@ +import datetime +import hashlib + +import uvicorn + +from src.chain.kvstore import register_in_kvstore +from src.core.config import Config +from src.services import cloud +from src.services.cloud import BucketAccessInfo +from src.utils.logging import get_function_logger + + +def apply_local_development_patches(): + """ + Applies local development patches to bypass direct source code modifications: + - Overrides `EscrowUtils.get_escrow` to retrieve local escrow data for specific addresses, + using mock data if the address corresponds to a local manifest. + - Updates local manifest files from cloud storage. + - Overrides `validate_address` to disable address validation. + - Replaces `validate_oracle_webhook_signature` with a lenient version for oracle signature + validation in development. + - Replaces `src.chain.escrow.store_results` to avoid attempting to store results on chain. + - Replaces `src.validators.signature.validate_oracle_webhook_signature` to always return + `OracleWebhookTypes.exchange_oracle`. + """ + logger = get_function_logger(apply_local_development_patches.__name__) + + import src.crons._utils + + def prepare_signed_message( + escrow_address, + chain_id, + message: str | None = None, + body: dict | None = None, + ) -> tuple[None, str]: + digest = hashlib.sha256( + (escrow_address + ":".join(map(str, (chain_id, message, body)))).encode() + ).hexdigest() + signature = f"{OracleWebhookTypes.recording_oracle}:{digest}" + logger.info(f"DEV: Generated patched signature {signature}") + return None, signature + + src.crons._utils.prepare_signed_message = prepare_signed_message + + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.escrow import EscrowData, EscrowUtils + + minio_client = cloud.make_client(BucketAccessInfo.parse_obj(Config.storage_config)) + + def get_local_escrow(chain_id: int, escrow_address: str) -> EscrowData: + possible_manifest_name = escrow_address.split(":")[0] + local_manifests = minio_client.list_files(bucket="manifests") + logger.info(f"Local manifests: {local_manifests}") + if possible_manifest_name in local_manifests: + logger.info(f"DEV: Using local manifest {escrow_address}") + return EscrowData( + chain_id=ChainId(chain_id), + id="test", + address=escrow_address, + amount_paid=10, + balance=10, + count=1, + factory_address="", + launcher="", + status="Pending", + token="HMT", # noqa: S106 + total_funded_amount=10, + created_at=datetime.datetime(2023, 1, 1, tzinfo=datetime.timezone.utc), + manifest_url=( + f"http://{Config.storage_config.endpoint_url}/manifests/{possible_manifest_name}" + ), + ) + return original_get_escrow(ChainId(chain_id), escrow_address) + + original_get_escrow = EscrowUtils.get_escrow + EscrowUtils.get_escrow = get_local_escrow + + import src.schemas.webhook + from src.core.types import OracleWebhookTypes + + src.schemas.webhook.validate_address = lambda x: x + + async def lenient_validate_oracle_webhook_signature( + request, # noqa: ARG001 (not relevant here) + signature, + webhook, # noqa: ARG001 (not relevant here) + ): + try: + parsed_type = OracleWebhookTypes(signature.split(":")[0]) + logger.info(f"DEV: Recovered {parsed_type} from the signature {signature}") + except (ValueError, TypeError): + logger.info(f"DEV: Falling back to {OracleWebhookTypes.exchange_oracle} webhook sender") + return OracleWebhookTypes.exchange_oracle + + import src.endpoints.webhook + + src.endpoints.webhook.validate_oracle_webhook_signature = ( + lenient_validate_oracle_webhook_signature + ) + + import src.chain.escrow + + def store_results( + chain_id: int, # noqa: ARG001 (not relevant here) + escrow_address: str, + url: str, + hash: str, + ) -> None: + logger.info(f"Would store results for escrow {escrow_address} on chain: {url}, {hash}") + + src.chain.escrow.store_results = store_results + + logger.warning("Local development patches applied.") + + +if __name__ == "__main__": + is_dev = Config.environment == "development" + if is_dev: + apply_local_development_patches() + + Config.validate() + register_in_kvstore() + + uvicorn.run( + app="src:app", + host="0.0.0.0", # noqa: S104 + port=int(Config.port), + workers=Config.workers_amount, + ) diff --git a/packages/examples/cvat/recording-oracle/docker-compose.dev.yml b/packages/examples/cvat/recording-oracle/docker-compose.dev.yml index 30196702d4..b6e2efe34d 100644 --- a/packages/examples/cvat/recording-oracle/docker-compose.dev.yml +++ b/packages/examples/cvat/recording-oracle/docker-compose.dev.yml @@ -10,7 +10,7 @@ services: volumes: - postgres:/var/lib/postgresql/data/pgdata ports: - - 5431:5432 + - 5434:5432 command: ["postgres", "-c", "log_statement=all"] volumes: From 1398bb056dc16ce0682c923ecfce73b7fd4864d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:33:47 +0100 Subject: [PATCH 57/92] Add circular progress when loading card data and refactor billing details modal (#2901) --- .../BillingDetails/BillingDetailsModal.tsx | 29 +- .../components/CreditCard/SelectCardModal.tsx | 1 + .../components/Jobs/Create/FiatPayForm.tsx | 503 ++++++++++-------- .../components/TopUpAccount/FiatTopUpForm.tsx | 263 ++++----- .../src/pages/Profile/Settings/index.tsx | 106 ++-- .../src/modules/payment/payment.service.ts | 6 + 6 files changed, 499 insertions(+), 409 deletions(-) diff --git a/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx b/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx index 463937f463..883fb28ebd 100644 --- a/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx +++ b/packages/apps/job-launcher/client/src/components/BillingDetails/BillingDetailsModal.tsx @@ -73,21 +73,21 @@ const BillingDetailsModal = ({ const validateForm = () => { let newErrors: { [key: string]: string } = {}; - if (!formData.name) { + if (!formData?.name) { newErrors.name = 'name required'; } const addressFields = ['line', 'postalCode', 'city', 'country']; addressFields.forEach((field) => { - if (!formData.address[field as keyof typeof formData.address]) { + if (!formData?.address[field as keyof typeof formData.address]) { newErrors[field] = `${field} required`; } }); - if (!formData.vat) { + if (!formData?.vat) { newErrors.vat = 'Tax ID required'; } - if (!formData.vatType) { + if (!formData?.vatType) { newErrors.vatType = 'Tax ID type required'; } @@ -100,9 +100,10 @@ const BillingDetailsModal = ({ if (validateForm()) { setIsLoading(true); try { - delete formData.email; + const email = formData?.email; + delete formData?.email; await editUserBillingInfo(formData); - setBillingInfo(formData); + setBillingInfo({ ...formData, email }); } catch (err: any) { showError( err.message || 'An error occurred while saving billing details.', @@ -154,7 +155,7 @@ const BillingDetailsModal = ({ - {billingInfo ? 'Save Changes' : 'Add Billing Details'} + {billingInfo?.name ? 'Save Changes' : 'Add Billing Details'} diff --git a/packages/apps/job-launcher/client/src/components/CreditCard/SelectCardModal.tsx b/packages/apps/job-launcher/client/src/components/CreditCard/SelectCardModal.tsx index d4a60dc1d6..56d2790fca 100644 --- a/packages/apps/job-launcher/client/src/components/CreditCard/SelectCardModal.tsx +++ b/packages/apps/job-launcher/client/src/components/CreditCard/SelectCardModal.tsx @@ -93,6 +93,7 @@ const SelectCardModal = ({ fullWidth size="large" disabled={!selectedCardId} + sx={{ mt: 2 }} onClick={() => { const selected = cards.find((card) => card.id === selectedCardId); if (selected) { diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx index cfdc6e15e5..c756b4cd7c 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx @@ -5,6 +5,7 @@ import { Box, Button, Checkbox, + CircularProgress, FormControl, FormControlLabel, Grid, @@ -25,6 +26,7 @@ import { CardIcon } from '../../../components/Icons/CardIcon'; import SuccessModal from '../../../components/SuccessModal'; import { CURRENCY } from '../../../constants/payment'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; +import { useSnackbar } from '../../../providers/SnackProvider'; import { createCvatJob, createFortuneJob, @@ -54,11 +56,14 @@ export const FiatPayForm = ({ }) => { const stripe = useStripe(); const elements = useElements(); + const { showError } = useSnackbar(); const { user } = useAppSelector((state) => state.auth); const dispatch = useAppDispatch(); const [jobLauncherAddress, setJobLauncherAddress] = useState(); const [minFee, setMinFee] = useState(0.01); const [cards, setCards] = useState([]); + const [loadingInitialData, setLoadingInitialData] = useState(true); + const [hasError, setHasError] = useState(false); const [selectedCard, setSelectedCard] = useState(null); const [isSelectCardModalOpen, setIsSelectCardModalOpen] = useState(false); const [amount, setAmount] = useState(''); @@ -104,6 +109,7 @@ export const FiatPayForm = ({ }, []); const fetchCards = async () => { + setLoadingInitialData(true); const data = await getUserCards(); setCards(data); @@ -111,9 +117,13 @@ export const FiatPayForm = ({ if (defaultCard) { setSelectedCard(defaultCard); } + setLoadingInitialData(false); }; - - const { data: jobLauncherFee } = useReadContract({ + const { + data: jobLauncherFee, + error, + isError, + } = useReadContract({ address: NETWORKS[jobRequest.chainId!]?.kvstoreAddress as Address, abi: KVStoreABI, functionName: 'get', @@ -123,8 +133,18 @@ export const FiatPayForm = ({ query: { enabled: !!jobLauncherAddress, }, + chainId: jobRequest.chainId, }); + useEffect(() => { + if (isError && error) { + showError(`Error getting fee, please try again`); + setHasError(true); + } else { + setHasError(false); + } + }, [isError, error, showError]); + useMemo(() => { setFundAmount(amount ? Number(amount) : 0); if (Number(jobLauncherFee) >= 0) @@ -216,254 +236,273 @@ export const FiatPayForm = ({ return ( - - - - + {loadingInitialData ? ( + + + + ) : ( + + + + + + + + setPayWithAccountBalance(e.target.checked) + } + /> + } + label="I want to pay with my account balance" + /> + + + + + setAmount(e.target.value)} + sx={{ mb: 2 }} + /> + {selectedCard ? ( + + + + ), + endAdornment: ( + + + + ), + }} + sx={{ mb: 2 }} + /> + ) : ( + + )} + + + + + - - setPayWithAccountBalance(e.target.checked) - } - /> - } - label="I want to pay with my account balance" - /> + + Account Balance + {user?.balance && ( + + {user?.balance?.amount?.toFixed(2)} USD + + )} + + + Fees + + ( + {Number(jobLauncherFee) >= 0 + ? `${Number(jobLauncherFee)}%` + : 'loading...'} + ) {feeAmount.toFixed(2)} USD + + + + Payment method + + + Balance + + {balancePayAmount.toFixed(2)} USD + + + + + Credit Card + + + {creditCardPayAmount.toFixed(2)} USD + + + + Total + {totalAmount.toFixed(2)} USD + + + - - - setAmount(e.target.value)} - sx={{ mb: 2 }} - /> - {selectedCard ? ( - - - - ), - endAdornment: ( - - - - ), - }} - sx={{ mb: 2 }} - /> - ) : ( - - )} - - - - - - Account Balance - {user?.balance && ( - - {user?.balance?.amount?.toFixed(2)} USD - - )} + + + Pay now + + - - Fees - - ( - {Number(jobLauncherFee) >= 0 - ? `${Number(jobLauncherFee)}%` - : 'loading...'} - ) {feeAmount.toFixed(2)} USD + + Terms & conditions - - - Payment method - - - Balance - - {balancePayAmount.toFixed(2)} USD - - - - Credit Card - - {creditCardPayAmount.toFixed(2)} USD - - - - Total - {totalAmount.toFixed(2)} USD - - - - - - - - - - Pay now - - - - - - Terms & conditions - - + - setIsSelectCardModalOpen(false)} - cards={cards} - onSelect={(card) => { - setSelectedCard(card); - setIsSelectCardModalOpen(false); - }} - /> - setIsAddCardOpen(false)} - onComplete={() => { - handleSuccessAction('Your card has been successfully added.'); - fetchCards(); - }} - /> - { - if (openBillingAfterAddCard) { - setIsBillingDetailsOpen(true); - } - setIsSuccessOpen(false); - }} - message={successMessage} - /> + setIsSelectCardModalOpen(false)} + cards={cards} + onSelect={(card) => { + setSelectedCard(card); + setIsSelectCardModalOpen(false); + }} + /> + setIsAddCardOpen(false)} + onComplete={() => { + handleSuccessAction('Your card has been successfully added.'); + fetchCards(); + }} + /> + { + if (openBillingAfterAddCard) { + setIsBillingDetailsOpen(true); + } + setIsSuccessOpen(false); + }} + message={successMessage} + /> - setIsBillingDetailsOpen(false)} - billingInfo={{ - name: '', - email: '', - address: { - city: '', - country: '', - postalCode: '', - line: '', - }, - vat: '', - vatType: '', - }} - setBillingInfo={(info) => { - handleSuccessAction( - 'Your billing details have been successfully updated.', - ); - }} - /> - + setIsBillingDetailsOpen(false)} + billingInfo={{ + name: '', + email: '', + address: { + city: '', + country: '', + postalCode: '', + line: '', + }, + vat: '', + vatType: '', + }} + setBillingInfo={(info) => { + handleSuccessAction( + 'Your billing details have been successfully updated.', + ); + }} + /> + + + )} ); }; diff --git a/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx b/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx index 2c40289b12..c5bb0dfdcb 100644 --- a/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx +++ b/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx @@ -2,6 +2,7 @@ import { LoadingButton } from '@mui/lab'; import { Box, Button, + CircularProgress, FormControl, Grid, InputAdornment, @@ -39,6 +40,7 @@ export const FiatTopUpForm = () => { const [openBillingAfterAddCard, setOpenBillingAfterAddCard] = useState(false); const [successMessage, setSuccessMessage] = useState(''); const [isBillingDetailsOpen, setIsBillingDetailsOpen] = useState(false); + const [loadingInitialData, setLoadingInitialData] = useState(true); useEffect(() => { const fetchBillingInfo = async () => { @@ -57,6 +59,7 @@ export const FiatTopUpForm = () => { }, []); const fetchCards = async () => { + setLoadingInitialData(true); const data = await paymentService.getUserCards(); setCards(data); @@ -64,6 +67,7 @@ export const FiatTopUpForm = () => { if (defaultCard) { setSelectedCard(defaultCard); } + setLoadingInitialData(false); }; const handleSuccessAction = (message: string) => { @@ -120,132 +124,145 @@ export const FiatTopUpForm = () => { return isSuccess ? ( ) : ( - - - - - setAmount(e.target.value)} - sx={{ mb: 2 }} - /> - {selectedCard ? ( - - - - ), - endAdornment: ( - - - - ), - }} - sx={{ mb: 2 }} - /> - ) : ( - + + ), + }} + sx={{ mb: 2 }} + /> + ) : ( + + )} + + + + setIsAddCardOpen(true)} + fullWidth size="large" - sx={{ mb: 2 }} + onClick={handleTopUpAccount} + loading={isLoading} + disabled={!amount || !selectedCard} + > + Top up account + + + + - Add Payment Method - - )} - - - - - Top up account - - - - - - Terms & conditions - - - - - - setIsSelectCardModalOpen(false)} - cards={cards} - onSelect={(card) => { - setSelectedCard(card); - setIsSelectCardModalOpen(false); - }} - /> - setIsAddCardOpen(false)} - onComplete={() => { - handleSuccessAction('Your card has been successfully added.'); - fetchCards(); - }} - /> - { - if (openBillingAfterAddCard) { - setIsBillingDetailsOpen(true); - } - setIsSuccessOpen(false); - }} - message={successMessage} - /> - - setIsBillingDetailsOpen(false)} - billingInfo={{ - name: '', - email: '', - address: { - city: '', - country: '', - postalCode: '', - line: '', - }, - vat: '', - vatType: '', - }} - setBillingInfo={(info) => { - handleSuccessAction( - 'Your billing details have been successfully updated.', - ); - }} - /> + + Terms & conditions + + + + + + setIsSelectCardModalOpen(false)} + cards={cards} + onSelect={(card) => { + setSelectedCard(card); + setIsSelectCardModalOpen(false); + }} + /> + setIsAddCardOpen(false)} + onComplete={() => { + handleSuccessAction('Your card has been successfully added.'); + fetchCards(); + }} + /> + { + if (openBillingAfterAddCard) { + setIsBillingDetailsOpen(true); + } + setIsSuccessOpen(false); + }} + message={successMessage} + /> + + setIsBillingDetailsOpen(false)} + billingInfo={{ + name: '', + email: '', + address: { + city: '', + country: '', + postalCode: '', + line: '', + }, + vat: '', + vatType: '', + }} + setBillingInfo={(info) => { + handleSuccessAction( + 'Your billing details have been successfully updated.', + ); + }} + /> + + )} ); }; diff --git a/packages/apps/job-launcher/client/src/pages/Profile/Settings/index.tsx b/packages/apps/job-launcher/client/src/pages/Profile/Settings/index.tsx index 63b29d6cd5..bfd32d1e4b 100644 --- a/packages/apps/job-launcher/client/src/pages/Profile/Settings/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Profile/Settings/index.tsx @@ -6,6 +6,7 @@ import { Divider, Grid, Typography, + CircularProgress, } from '@mui/material'; import { useEffect, useState } from 'react'; import BillingDetailsModal from '../../../components/BillingDetails/BillingDetailsModal'; @@ -26,6 +27,7 @@ const Settings = () => { const [openBillingAfterAddCard, setOpenBillingAfterAddCard] = useState(false); const [successMessage, setSuccessMessage] = useState(''); const [cards, setCards] = useState([]); + const [loadingInitialData, setLoadingInitialData] = useState(true); const [billingInfo, setBillingInfo] = useState(null); const fetchCards = async () => { @@ -40,15 +42,20 @@ const Settings = () => { const fetchBillingInfo = async () => { try { const data = await getUserBillingInfo(); - if (data) setBillingInfo({ ...billingInfo, ...data }); + setBillingInfo({ ...billingInfo, ...data }); } catch (error) { showError('Error fetching billing info'); } }; useEffect(() => { - fetchCards(); - fetchBillingInfo(); + const fetchInfo = async () => { + setLoadingInitialData(true); + await fetchCards(); + await fetchBillingInfo(); + setLoadingInitialData(false); + }; + fetchInfo(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -57,7 +64,16 @@ const Settings = () => { setIsSuccessOpen(true); }; - return ( + return loadingInitialData ? ( + + + + ) : ( { - + Billing Details @@ -90,39 +106,46 @@ const Settings = () => { variant="contained" color="primary" onClick={() => setIsEditBillingOpen(true)} + disabled={cards.length === 0} > - {billingInfo + {billingInfo?.name ? 'Edit Billing Details' : '+ Add Billing Details'} - {billingInfo ? ( - - Details - - Full Name / Company Name: {billingInfo.name} - - Email: {billingInfo.email} - Address: {billingInfo.address.line} - - Postal code: {billingInfo.address.postalCode} - - City: {billingInfo.address.city} - - Country: {countryOptions[billingInfo.address.country]} - - - VAT Type: {vatTypeOptions[billingInfo.vatType]} + + {billingInfo?.name ? ( + <> + Details + + Full Name / Company Name: {billingInfo?.name} + + Email: {billingInfo?.email} + + Address: {billingInfo?.address?.line} + + + Postal code: {billingInfo?.address?.postalCode} + + + City: {billingInfo?.address?.city} + + + Country: {countryOptions[billingInfo?.address?.country]} + + + VAT Type: {vatTypeOptions[billingInfo?.vatType]} + + VAT Number: {billingInfo?.vat} + + ) : ( + + No billing details added yet - VAT Number: {billingInfo.vat} - - ) : ( - - No billing details added yet - - )} + )} + @@ -133,7 +156,7 @@ const Settings = () => { - + Payment Details @@ -151,15 +174,18 @@ const Settings = () => { - - - handleSuccessAction(message)} - openAddCreditCardModal={setIsAddCardOpen} - /> - + + handleSuccessAction(message)} + openAddCreditCardModal={setIsAddCardOpen} + /> diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts index 0eed621319..a5f14c5336 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts @@ -586,6 +586,12 @@ export class PaymentService { user: UserEntity, updateBillingInfoDto: BillingInfoDto, ) { + if (!user.stripeCustomerId) { + throw new ControlledError( + ErrorPayment.CustomerNotFound, + HttpStatus.BAD_REQUEST, + ); + } // If the VAT or VAT type has changed, update it in Stripe if (updateBillingInfoDto.vat && updateBillingInfoDto.vatType) { const existingTaxIds = await this.stripe.customers.listTaxIds( From c68acfb6ccfdba2eac5d9f92894d41498536d4c0 Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Thu, 12 Dec 2024 12:03:12 +0300 Subject: [PATCH 58/92] fix: hcaptcha stats request (#2900) --- .../server/src/common/config/gateway-config.service.ts | 6 ++++++ .../spec/h-captcha-labeling.gateways.spec.ts | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/apps/human-app/server/src/common/config/gateway-config.service.ts b/packages/apps/human-app/server/src/common/config/gateway-config.service.ts index 11439c7036..7a692a6425 100644 --- a/packages/apps/human-app/server/src/common/config/gateway-config.service.ts +++ b/packages/apps/human-app/server/src/common/config/gateway-config.service.ts @@ -128,6 +128,12 @@ export class GatewayConfigService { params: { api_key: this.envConfig.hcaptchaLabelingApiKey, actual: false, + /** + * Required param. + * Only one value is available for now + * so hardcoded + */ + network: 'polygon', }, }, } as Record, diff --git a/packages/apps/human-app/server/src/integrations/h-captcha-labeling/spec/h-captcha-labeling.gateways.spec.ts b/packages/apps/human-app/server/src/integrations/h-captcha-labeling/spec/h-captcha-labeling.gateways.spec.ts index 1cb819676c..d1010b72da 100644 --- a/packages/apps/human-app/server/src/integrations/h-captcha-labeling/spec/h-captcha-labeling.gateways.spec.ts +++ b/packages/apps/human-app/server/src/integrations/h-captcha-labeling/spec/h-captcha-labeling.gateways.spec.ts @@ -103,7 +103,11 @@ describe('HCaptchaLabelingGateway', () => { method: 'GET', url: `${environmentConfigServiceMock.hcaptchaLabelingStatsApiUrl}/requester/daily_hmt_spend`, headers: {}, - params: { api_key: 'mock-api-key', actual: false }, + params: { + api_key: 'mock-api-key', + actual: false, + network: 'polygon', + }, }; expect(httpServiceMock.request).toHaveBeenCalledWith(expectedOptions); }); From 9caf81b31885cebe66e480248ba60c6f2e4a480a Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Thu, 12 Dec 2024 16:45:06 +0300 Subject: [PATCH 59/92] [Human App] feat: filter out oracle jobs as per enabled chain id (#2886) --- .../src/api/services/worker/oracles.ts | 12 +- .../src/modules/cron-job/cron-job.module.ts | 2 + .../src/modules/cron-job/cron-job.service.ts | 62 ++---- .../cron-job/spec/cron-job.service.spec.ts | 154 ++++---------- .../jobs-discovery/jobs-discovery.service.ts | 35 ++- .../spec/jobs-discovery.service.spec.ts | 10 +- .../model/oracle-discovery.model.ts | 47 +++-- .../oracle-discovery.controller.ts | 22 +- .../oracle-discovery.mapper.profile.ts | 8 +- .../oracle-discovery.service.ts | 199 ++++++++++-------- .../spec/oracle-discovery.controller.spec.ts | 20 +- .../spec/oracle-discovery.fixture.ts | 21 +- .../spec/oracle-discovery.service.mock.ts | 2 +- .../spec/oracle-discovery.service.spec.ts | 27 +-- 14 files changed, 299 insertions(+), 322 deletions(-) diff --git a/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts b/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts index a5aa7f7c9a..810b7df7fc 100644 --- a/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts +++ b/packages/apps/human-app/frontend/src/api/services/worker/oracles.ts @@ -53,7 +53,16 @@ export async function getOracles({ selected_job_types: string[]; signal: AbortSignal; }) { - let oracles = [H_CAPTCHA_ORACLE]; + let oracles: Oracle[] = []; + if ( + selected_job_types.length === 0 || + selected_job_types.some((selected_job_type) => + H_CAPTCHA_ORACLE.jobTypes.includes(selected_job_type) + ) + ) { + oracles.push(H_CAPTCHA_ORACLE); + } + if (env.VITE_FEATURE_FLAG_JOBS_DISCOVERY) { const queryParams = selected_job_types.length ? `?${stringifyUrlQueryObject({ selected_job_types })}` @@ -75,6 +84,7 @@ export async function getOracles({ })) ); } + return oracles; } diff --git a/packages/apps/human-app/server/src/modules/cron-job/cron-job.module.ts b/packages/apps/human-app/server/src/modules/cron-job/cron-job.module.ts index ea6a885d78..74bd8b7277 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/cron-job.module.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/cron-job.module.ts @@ -4,12 +4,14 @@ import { ExchangeOracleModule } from '../../integrations/exchange-oracle/exchang import { CronJobService } from './cron-job.service'; import { OracleDiscoveryModule } from '../oracle-discovery/oracle-discovery.module'; import { WorkerModule } from '../user-worker/worker.module'; +import { JobsDiscoveryModule } from '../jobs-discovery/jobs-discovery.module'; @Module({ imports: [ ScheduleModule.forRoot(), ExchangeOracleModule, OracleDiscoveryModule, + JobsDiscoveryModule, WorkerModule, ], providers: [CronJobService], diff --git a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts index 711c2ede55..e3a86ee28a 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts @@ -1,6 +1,4 @@ -import { Injectable, Inject, Logger } from '@nestjs/common'; -import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { Cache } from 'cache-manager'; +import { Injectable, Logger } from '@nestjs/common'; import { CronJob } from 'cron'; import { ExchangeOracleGateway } from '../../integrations/exchange-oracle/exchange-oracle.gateway'; import { @@ -9,24 +7,21 @@ import { JobsDiscoveryResponseItem, } from '../jobs-discovery/model/jobs-discovery.model'; import { EnvironmentConfigService } from '../../common/config/environment-config.service'; -import { JOB_DISCOVERY_CACHE_KEY } from '../../common/constants/cache'; import { OracleDiscoveryService } from '../oracle-discovery/oracle-discovery.service'; -import { - OracleDiscoveryCommand, - OracleDiscoveryResult, -} from '../oracle-discovery/model/oracle-discovery.model'; +import { DiscoveredOracle } from '../oracle-discovery/model/oracle-discovery.model'; import { WorkerService } from '../user-worker/worker.service'; import { JobDiscoveryFieldName } from '../../common/enums/global-common'; import { SchedulerRegistry } from '@nestjs/schedule'; +import { JobsDiscoveryService } from '../jobs-discovery/jobs-discovery.service'; @Injectable() export class CronJobService { private readonly logger = new Logger(CronJobService.name); constructor( private readonly exchangeOracleGateway: ExchangeOracleGateway, - @Inject(CACHE_MANAGER) private cacheManager: Cache, private configService: EnvironmentConfigService, private oracleDiscoveryService: OracleDiscoveryService, + private jobsDiscoveryService: JobsDiscoveryService, private workerService: WorkerService, private schedulerRegistry: SchedulerRegistry, ) { @@ -47,12 +42,11 @@ export class CronJobService { async updateJobsListCron() { this.logger.log('CRON START'); - const oracleDiscoveryCommand: OracleDiscoveryCommand = {}; - const oracles = await this.oracleDiscoveryService.processOracleDiscovery( - oracleDiscoveryCommand, - ); + const oracles = await this.oracleDiscoveryService.discoverOracles(); - if (!oracles || oracles.length < 1) return; + if (oracles.length === 0) { + return; + } try { const response = await this.workerService.signinWorker({ @@ -66,7 +60,8 @@ export class CronJobService { `Skipping execution for oracle: ${oracle.address}. Remaining skips: ${oracle.executionsToSkip}`, ); - await this.updateOracleInCache(oracle, { + await this.oracleDiscoveryService.updateOracleInCache({ + ...oracle, executionsToSkip: oracle.executionsToSkip - 1, }); continue; @@ -84,7 +79,7 @@ export class CronJobService { this.logger.log('CRON END'); } - async updateJobsListCache(oracle: OracleDiscoveryResult, token: string) { + async updateJobsListCache(oracle: DiscoveredOracle, token: string) { try { let allResults: JobsDiscoveryResponseItem[] = []; @@ -120,51 +115,28 @@ export class CronJobService { allResults = this.mergeJobs(allResults, response.results); } - await this.updateOracleInCache(oracle, { + await this.oracleDiscoveryService.updateOracleInCache({ + ...oracle, retriesCount: 0, executionsToSkip: 0, }); - await this.cacheManager.set( - `${JOB_DISCOVERY_CACHE_KEY}:${oracle.address}`, - allResults, - ); + await this.jobsDiscoveryService.setCachedJobs(oracle.address, allResults); } catch (e) { this.logger.error(e); await this.handleJobListError(oracle); } } - private async updateOracleInCache( - oracleData: OracleDiscoveryResult, - updates: Partial, - ) { - const updatedOracle = { ...oracleData, ...updates }; - - const chainId = oracleData.chainId?.toString(); - const cachedOracles = - await this.cacheManager.get(chainId); - - if (cachedOracles) { - const updatedOracles = cachedOracles.map((oracle) => - oracle.address === oracleData.address ? updatedOracle : oracle, - ); - await this.cacheManager.set( - chainId, - updatedOracles, - this.configService.cacheTtlOracleDiscovery, - ); - } - } - - private async handleJobListError(oracleData: OracleDiscoveryResult) { + private async handleJobListError(oracleData: DiscoveredOracle) { const retriesCount = oracleData.retriesCount || 0; const newExecutionsToSkip = Math.min( (oracleData.executionsToSkip || 0) + Math.pow(2, retriesCount), this.configService.maxExecutionToSkip, ); - await this.updateOracleInCache(oracleData, { + await this.oracleDiscoveryService.updateOracleInCache({ + ...oracleData, retriesCount: retriesCount + 1, executionsToSkip: newExecutionsToSkip, }); diff --git a/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts b/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts index 9d43beb509..f6e1375dd5 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/spec/cron-job.service.spec.ts @@ -1,4 +1,3 @@ -import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Test, TestingModule } from '@nestjs/testing'; import { CronJobService } from '../cron-job.service'; import { ExchangeOracleGateway } from '../../../integrations/exchange-oracle/exchange-oracle.gateway'; @@ -9,9 +8,8 @@ import { JobsDiscoveryParamsCommand, JobsDiscoveryResponseItem, } from '../../../modules/jobs-discovery/model/jobs-discovery.model'; -import { JOB_DISCOVERY_CACHE_KEY } from '../../../common/constants/cache'; import { JobStatus } from '../../../common/enums/global-common'; -import { OracleDiscoveryResult } from '../../../modules/oracle-discovery/model/oracle-discovery.model'; +import { JobsDiscoveryService } from '../../../modules/jobs-discovery/jobs-discovery.service'; import { SchedulerRegistry } from '@nestjs/schedule'; import { generateOracleDiscoveryResponseBody } from '../../../modules/oracle-discovery/spec/oracle-discovery.fixture'; import { ChainId } from '@human-protocol/sdk'; @@ -28,8 +26,8 @@ describe('CronJobService', () => { let service: CronJobService; let exchangeOracleGatewayMock: Partial; let oracleDiscoveryServiceMock: Partial; + let jobDiscoveryServiceMock: Partial; let workerServiceMock: Partial; - let cacheManagerMock: any; let configServiceMock: Partial; beforeEach(async () => { @@ -38,16 +36,16 @@ describe('CronJobService', () => { }; oracleDiscoveryServiceMock = { - processOracleDiscovery: jest.fn(), + discoverOracles: jest.fn(), + updateOracleInCache: jest.fn(), }; - workerServiceMock = { - signinWorker: jest.fn(), + jobDiscoveryServiceMock = { + setCachedJobs: jest.fn(), }; - cacheManagerMock = { - get: jest.fn(), - set: jest.fn(), + workerServiceMock = { + signinWorker: jest.fn(), }; configServiceMock = { @@ -67,8 +65,11 @@ describe('CronJobService', () => { provide: OracleDiscoveryService, useValue: oracleDiscoveryServiceMock, }, + { + provide: JobsDiscoveryService, + useValue: jobDiscoveryServiceMock, + }, { provide: WorkerService, useValue: workerServiceMock }, - { provide: CACHE_MANAGER, useValue: cacheManagerMock }, { provide: EnvironmentConfigService, useValue: configServiceMock }, SchedulerRegistry, ], @@ -95,9 +96,9 @@ describe('CronJobService', () => { service = new CronJobService( exchangeOracleGatewayMock as ExchangeOracleGateway, - cacheManagerMock, configServiceMock as any, oracleDiscoveryServiceMock as OracleDiscoveryService, + jobDiscoveryServiceMock as JobsDiscoveryService, workerServiceMock as WorkerService, schedulerRegistryMock, ); @@ -110,9 +111,9 @@ describe('CronJobService', () => { service = new CronJobService( exchangeOracleGatewayMock as ExchangeOracleGateway, - cacheManagerMock, configServiceMock as any, oracleDiscoveryServiceMock as OracleDiscoveryService, + jobDiscoveryServiceMock as JobsDiscoveryService, workerServiceMock as WorkerService, schedulerRegistryMock, ); @@ -124,21 +125,19 @@ describe('CronJobService', () => { describe('updateJobsListCron', () => { it('should not proceed if no oracles are found', async () => { ( - oracleDiscoveryServiceMock.processOracleDiscovery as jest.Mock + oracleDiscoveryServiceMock.discoverOracles as jest.Mock ).mockResolvedValue([]); await service.updateJobsListCron(); - expect( - oracleDiscoveryServiceMock.processOracleDiscovery, - ).toHaveBeenCalledWith({}); + expect(oracleDiscoveryServiceMock.discoverOracles).toHaveBeenCalledWith(); expect(workerServiceMock.signinWorker).not.toHaveBeenCalled(); }); it('should proceed with valid oracles and update jobs list cache', async () => { const oraclesDiscovery = generateOracleDiscoveryResponseBody(); ( - oracleDiscoveryServiceMock.processOracleDiscovery as jest.Mock + oracleDiscoveryServiceMock.discoverOracles as jest.Mock ).mockResolvedValue(oraclesDiscovery); (workerServiceMock.signinWorker as jest.Mock).mockResolvedValue({ access_token: 'token', @@ -150,9 +149,7 @@ describe('CronJobService', () => { await service.updateJobsListCron(); - expect( - oracleDiscoveryServiceMock.processOracleDiscovery, - ).toHaveBeenCalledWith({}); + expect(oracleDiscoveryServiceMock.discoverOracles).toHaveBeenCalledWith(); expect(workerServiceMock.signinWorker).toHaveBeenCalledWith({ email: configServiceMock.email, password: configServiceMock.password, @@ -165,15 +162,10 @@ describe('CronJobService', () => { }); describe('updateJobsListCache', () => { + const oracle = generateOracleDiscoveryResponseBody()[0]; + const token = 'Bearer token'; + it('should fetch all jobs and update the cache', async () => { - const oracle: OracleDiscoveryResult = { - address: 'mockAddress1', - role: 'validator', - chainId: ChainId.POLYGON, - retriesCount: 0, - executionsToSkip: 0, - }; - const token = 'Bearer token'; const initialResponse = { results: [{ escrow_address: '0xabc', chain_id: '1' }], total_pages: 1, @@ -187,21 +179,13 @@ describe('CronJobService', () => { expect(exchangeOracleGatewayMock.fetchJobs).toHaveBeenCalledWith( expect.any(JobsDiscoveryParamsCommand), ); - expect(cacheManagerMock.set).toHaveBeenCalledWith( - `${JOB_DISCOVERY_CACHE_KEY}:${oracle.address}`, + expect(jobDiscoveryServiceMock.setCachedJobs).toHaveBeenCalledWith( + oracle.address, initialResponse.results, ); }); it('should handle errors and call handleJobListError', async () => { - const oracle: OracleDiscoveryResult = { - address: 'mockAddress1', - role: 'validator', - chainId: ChainId.POLYGON, - retriesCount: 0, - executionsToSkip: 0, - }; - const token = 'Bearer token'; const error = new Error('Test error'); (exchangeOracleGatewayMock.fetchJobs as jest.Mock).mockRejectedValue( error, @@ -220,14 +204,6 @@ describe('CronJobService', () => { }); it('should reset retries count after successful job fetch', async () => { - const oracle: OracleDiscoveryResult = { - address: 'mockAddress1', - role: 'validator', - chainId: ChainId.POLYGON, - retriesCount: 3, - executionsToSkip: 0, - }; - const token = 'Bearer token'; const initialResponse = { results: [{ escrow_address: '0xabc', chain_id: '1' }], total_pages: 1, @@ -236,14 +212,12 @@ describe('CronJobService', () => { initialResponse, ); - const updateOracleInCacheSpy = jest.spyOn( - service as any, - 'updateOracleInCache', - ); - await service.updateJobsListCache(oracle, token); - expect(updateOracleInCacheSpy).toHaveBeenCalledWith(oracle, { + expect( + oracleDiscoveryServiceMock.updateOracleInCache, + ).toHaveBeenCalledWith({ + ...oracle, retriesCount: 0, executionsToSkip: 0, }); @@ -318,79 +292,41 @@ describe('CronJobService', () => { }); }); - describe('updateOracleInCache', () => { - it('should update oracle in cache', async () => { - const oracleData: OracleDiscoveryResult = { - address: 'mockAddress1', - role: 'validator', - chainId: ChainId.POLYGON, - retriesCount: 5, - executionsToSkip: 2, - }; - - cacheManagerMock.get.mockResolvedValue([oracleData]); - - await (service as any).updateOracleInCache(oracleData, { - retriesCount: 0, - executionsToSkip: 0, - }); - - expect(cacheManagerMock.set).toHaveBeenCalledWith( - oracleData.chainId.toString(), - [{ ...oracleData, retriesCount: 0, executionsToSkip: 0 }], - configServiceMock.cacheTtlOracleDiscovery, - ); - }); - }); - describe('handleJobListError', () => { it('should increment retries count and executions to skip but not exceed the limit', async () => { - const oracleData: OracleDiscoveryResult = { - address: 'mockAddress1', - role: 'validator', - - chainId: ChainId.POLYGON, + const oracleData = { + ...generateOracleDiscoveryResponseBody()[0], retriesCount: 6, executionsToSkip: 0, }; - cacheManagerMock.get.mockResolvedValue([oracleData]); - await (service as any).handleJobListError(oracleData); - expect(cacheManagerMock.set).toHaveBeenCalledWith( - oracleData.chainId.toString(), - [{ ...oracleData, retriesCount: 7, executionsToSkip: 32 }], - configServiceMock.cacheTtlOracleDiscovery, - ); + expect( + oracleDiscoveryServiceMock.updateOracleInCache, + ).toHaveBeenCalledWith({ + ...oracleData, + retriesCount: 7, + executionsToSkip: 32, + }); }); it('should increment retries count and executions to skip', async () => { - const oracleData: OracleDiscoveryResult = { - address: 'mockAddress1', - role: 'validator', - chainId: ChainId.POLYGON, + const oracleData = { + ...generateOracleDiscoveryResponseBody()[0], retriesCount: 2, executionsToSkip: 0, }; - cacheManagerMock.get.mockResolvedValue([oracleData]); - await (service as any).handleJobListError(oracleData); - expect(cacheManagerMock.set).toHaveBeenCalledWith( - oracleData.chainId.toString(), - [{ ...oracleData, retriesCount: 3, executionsToSkip: 4 }], - configServiceMock.cacheTtlOracleDiscovery, - ); - }); - - it('should do nothing if chainId is not found in cache', async () => { - cacheManagerMock.get.mockResolvedValue(undefined); - - await (service as any).handleJobListError('unknownAddress'); - - expect(cacheManagerMock.set).not.toHaveBeenCalled(); + expect( + oracleDiscoveryServiceMock.updateOracleInCache, + ).toHaveBeenCalledWith({ + ...oracleData, + retriesCount: 3, + executionsToSkip: 4, + }); }); }); }); diff --git a/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.service.ts b/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.service.ts index 48b15ae16c..52a8584f17 100644 --- a/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.service.ts +++ b/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.service.ts @@ -7,18 +7,25 @@ import { } from './model/jobs-discovery.model'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; +import { EnvironmentConfigService } from '../../common/config/environment-config.service'; import { JOB_DISCOVERY_CACHE_KEY } from '../../common/constants/cache'; import { JobDiscoveryFieldName } from '../../common/enums/global-common'; @Injectable() export class JobsDiscoveryService { - constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} + constructor( + @Inject(CACHE_MANAGER) private cacheManager: Cache, + private configService: EnvironmentConfigService, + ) {} async processJobsDiscovery( command: JobsDiscoveryParamsCommand, ): Promise { const allJobs = await this.getCachedJobs(command.oracleAddress); - const filteredJobs = this.applyFilters(allJobs || [], command.data); + let filteredJobs = this.applyFilters(allJobs, command.data); + filteredJobs = filteredJobs.filter((job) => + this.configService.chainIdsEnabled.includes(job.chain_id), + ); return paginateAndSortResults( filteredJobs, @@ -81,13 +88,27 @@ export class JobsDiscoveryService { }); } + static makeCacheKeyForOracle(oracleAddress: string): string { + return `${JOB_DISCOVERY_CACHE_KEY}:${oracleAddress}`; + } + async getCachedJobs( oracleAddress: string, ): Promise { - return ( - (await this.cacheManager.get( - `${JOB_DISCOVERY_CACHE_KEY}:${oracleAddress}`, - )) || [] - ); + const cacheKey = JobsDiscoveryService.makeCacheKeyForOracle(oracleAddress); + + const cachedJobs = await this.cacheManager.get< + JobsDiscoveryResponseItem[] | undefined + >(cacheKey); + + return cachedJobs || []; + } + + async setCachedJobs( + oracleAddress: string, + jobs: JobsDiscoveryResponseItem[], + ): Promise { + const cacheKey = JobsDiscoveryService.makeCacheKeyForOracle(oracleAddress); + await this.cacheManager.set(cacheKey, jobs); } } diff --git a/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.service.spec.ts b/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.service.spec.ts index a5c1f56836..566a1f0734 100644 --- a/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.service.spec.ts @@ -1,3 +1,5 @@ +import { ChainId } from '@human-protocol/sdk'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { JobsDiscoveryService } from '../jobs-discovery.service'; import { ExchangeOracleGateway } from '../../../integrations/exchange-oracle/exchange-oracle.gateway'; import { Test, TestingModule } from '@nestjs/testing'; @@ -7,7 +9,7 @@ import { responseItemFixture1, responseItemFixture3, } from './jobs-discovery.fixtures'; -import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { EnvironmentConfigService } from '../../../common/config/environment-config.service'; describe('JobsDiscoveryService', () => { let service: JobsDiscoveryService; @@ -29,6 +31,12 @@ describe('JobsDiscoveryService', () => { JobsDiscoveryService, { provide: ExchangeOracleGateway, useValue: exchangeOracleGatewayMock }, { provide: CACHE_MANAGER, useValue: cacheManagerMock }, + { + provide: EnvironmentConfigService, + useValue: { + chainIdsEnabled: [ChainId.MAINNET], + }, + }, ], }).compile(); diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts index 77b0feb75d..d2df12edca 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/model/oracle-discovery.model.ts @@ -4,27 +4,37 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsArray, IsOptional } from 'class-validator'; import { Exclude, Transform } from 'class-transformer'; -export class OracleDiscoveryResult implements IOperator { +type DiscoveredOracleCreateProps = { + address: string; + chainId: ChainId; + role?: string; + url: string; + jobTypes: string[]; + registrationNeeded?: boolean; + registrationInstructions?: string; +}; + +export class DiscoveredOracle implements IOperator { @ApiProperty({ description: 'Address of the oracle operator' }) address: string; @ApiProperty({ description: 'Chain ID where the oracle is registered' }) chainId: ChainId; + @ApiPropertyOptional({ description: 'URL of the oracle operator' }) + url: string; + @ApiPropertyOptional({ description: 'Role of the oracle operator' }) role?: string; - @ApiPropertyOptional({ description: 'URL of the oracle operator' }) - url?: string; - @ApiPropertyOptional({ type: [String], description: 'Types of jobs the oracle supports', }) - jobTypes?: string[]; + jobTypes: string[]; @ApiPropertyOptional({ description: 'Indicates if registration is needed' }) - registrationNeeded?: boolean; + registrationNeeded: boolean; @ApiPropertyOptional({ description: 'Instructions for registration, if needed', @@ -37,32 +47,33 @@ export class OracleDiscoveryResult implements IOperator { @Exclude() executionsToSkip = 0; - constructor( - address: string, - chainId: ChainId, - role?: string, - url?: string, - jobTypes?: string[], - registrationNeeded?: boolean, - registrationInstructions?: string, - ) { + constructor({ + address, + chainId, + role, + url, + jobTypes, + registrationNeeded, + registrationInstructions, + }: DiscoveredOracleCreateProps) { this.address = address; this.chainId = chainId; this.role = role; this.url = url; this.jobTypes = jobTypes; - this.registrationNeeded = registrationNeeded; + this.registrationNeeded = registrationNeeded || false; this.registrationInstructions = registrationInstructions; } } -export class OracleDiscoveryDto { + +export class GetOraclesQuery { @ApiPropertyOptional({ type: [String] }) @IsArray() @IsOptional() @Transform(({ value }) => (Array.isArray(value) ? value : Array(value))) selected_job_types?: string[]; } -export class OracleDiscoveryCommand { +export class GetOraclesCommand { @AutoMap() @Transform(({ value }) => (Array.isArray(value) ? value : [value])) selectedJobTypes?: string[]; diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts index 66782d6cc4..9e442a620d 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.controller.ts @@ -10,9 +10,9 @@ import { import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; import { OracleDiscoveryService } from './oracle-discovery.service'; import { - OracleDiscoveryCommand, - OracleDiscoveryDto, - OracleDiscoveryResult, + GetOraclesCommand, + GetOraclesQuery, + DiscoveredOracle, } from './model/oracle-discovery.model'; import { InjectMapper } from '@automapper/nestjs'; import { Mapper } from '@automapper/core'; @@ -21,7 +21,7 @@ import { EnvironmentConfigService } from '../../common/config/environment-config @Controller() export class OracleDiscoveryController { constructor( - private readonly service: OracleDiscoveryService, + private readonly oracleDiscoveryService: OracleDiscoveryService, private readonly environmentConfigService: EnvironmentConfigService, @InjectMapper() private readonly mapper: Mapper, ) {} @@ -29,24 +29,20 @@ export class OracleDiscoveryController { @Get('/oracles') @ApiOperation({ summary: 'Oracles discovery' }) @ApiOkResponse({ - type: Array, + type: Array, description: 'List of oracles', }) @UsePipes(new ValidationPipe()) public async getOracles( - @Query() dto: OracleDiscoveryDto, - ): Promise { + @Query() query: GetOraclesQuery, + ): Promise { if (!this.environmentConfigService.jobsDiscoveryFlag) { throw new HttpException( 'Oracles discovery is disabled', HttpStatus.FORBIDDEN, ); } - const command = this.mapper.map( - dto, - OracleDiscoveryDto, - OracleDiscoveryCommand, - ); - return await this.service.processOracleDiscovery(command); + const command = this.mapper.map(query, GetOraclesQuery, GetOraclesCommand); + return await this.oracleDiscoveryService.getOracles(command); } } diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.mapper.profile.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.mapper.profile.ts index 4c34b9c3f5..0744fc3242 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.mapper.profile.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.mapper.profile.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { AutomapperProfile, InjectMapper } from '@automapper/nestjs'; import { createMap, forMember, mapFrom, Mapper } from '@automapper/core'; import { - OracleDiscoveryCommand, - OracleDiscoveryDto, + GetOraclesCommand, + GetOraclesQuery, } from './model/oracle-discovery.model'; @Injectable() @@ -16,8 +16,8 @@ export class OracleDiscoveryProfile extends AutomapperProfile { return (mapper: Mapper) => { createMap( mapper, - OracleDiscoveryDto, - OracleDiscoveryCommand, + GetOraclesQuery, + GetOraclesCommand, forMember( (destination) => destination.selectedJobTypes, mapFrom((source) => source.selected_job_types), diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts index cc6f71a626..76cb3d51f2 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts @@ -1,11 +1,12 @@ +import _ from 'lodash'; +import { ChainId, IOperator, OperatorUtils, Role } from '@human-protocol/sdk'; import { Inject, Injectable, Logger } from '@nestjs/common'; -import { - OracleDiscoveryCommand, - OracleDiscoveryResult, -} from './model/oracle-discovery.model'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; -import { ChainId, OperatorUtils, Role } from '@human-protocol/sdk'; +import { + DiscoveredOracle, + GetOraclesCommand, +} from './model/oracle-discovery.model'; import { EnvironmentConfigService } from '../../common/config/environment-config.service'; import { KvStoreGateway } from '../../integrations/kv-store/kv-store.gateway'; @@ -19,106 +20,140 @@ export class OracleDiscoveryService { private kvStoreGateway: KvStoreGateway, ) {} - async processOracleDiscovery( - command: OracleDiscoveryCommand, - ): Promise { - const address = this.configService.reputationOracleAddress; - const chainIds = this.configService.chainIdsEnabled; - - const oraclesForChainIds = await Promise.all( - chainIds.map(async (chainId) => { - const jobTypes = ( - (await this.kvStoreGateway.getJobTypesByAddress(chainId, address)) ?? - '' - ) - .split(',') - .map((job) => job.trim().toLowerCase()); - - return this.findOraclesByChainIdAndJobTypes(chainId, address, jobTypes); - }), - ); + async getOracles(command: GetOraclesCommand): Promise { + const oracles = await this.discoverOracles(); - const oracles: OracleDiscoveryResult[] = []; - for (const oraclesForChainId of oraclesForChainIds) { - for (const oracle of oraclesForChainId) { - if (command.selectedJobTypes?.length) { - // Keep only oracles that have at least one selected job type - const oracleJobTypesSet = new Set(oracle.jobTypes || []); - let oracleHasSomeSelectedJobType = false; - for (const selectedJobType of command.selectedJobTypes) { - if (oracleJobTypesSet.has(selectedJobType)) { - oracleHasSomeSelectedJobType = true; - break; - } - } - if (!oracleHasSomeSelectedJobType) { - continue; - } - } + if (!command.selectedJobTypes?.length) { + return oracles; + } - oracles.push(oracle); - } + const selectedJobTypesSet = new Set(command.selectedJobTypes); + return oracles.filter((oracle) => + oracle.jobTypes.some((jobType) => selectedJobTypesSet.has(jobType)), + ); + } + + async discoverOracles(): Promise { + const discoveryPromises = []; + for (const enabledChainId of this.configService.chainIdsEnabled) { + discoveryPromises.push(this.discoverOraclesForChain(enabledChainId)); } - return oracles; + const oraclesDiscoveredForChains = await Promise.all(discoveryPromises); + + return oraclesDiscoveredForChains.flat(); } - private async findOraclesByChainIdAndJobTypes( + private async discoverOraclesForChain( chainId: ChainId, - address: string, - jobTypes: string[], - ): Promise { + ): Promise { try { + const cacheKey = chainId.toString(); + const cachedOracles = await this.cacheManager.get< - OracleDiscoveryResult[] - >(chainId.toString()); - if (cachedOracles) return cachedOracles; + DiscoveredOracle[] | undefined + >(cacheKey); + + if (cachedOracles) { + return cachedOracles; + } - const operators = await OperatorUtils.getReputationNetworkOperators( - Number(chainId), - address, + const reputationOracleAddress = + this.configService.reputationOracleAddress; + + const reputationOracleJobTypesValue = + await this.kvStoreGateway.getJobTypesByAddress( + chainId, + reputationOracleAddress, + ); + + if (!reputationOracleJobTypesValue) { + return []; + } + const reputationOracleJobTypes = reputationOracleJobTypesValue.split(','); + + const exchangeOracles = await OperatorUtils.getReputationNetworkOperators( + chainId, + reputationOracleAddress, Role.ExchangeOracle, ); - const jobTypeSet = new Set(jobTypes.map((j) => j.toLowerCase())); - - const oraclesWithRetryData: OracleDiscoveryResult[] = operators - .filter( - (operator) => - operator.url && this.hasJobTypes(operator.jobTypes, jobTypeSet), - ) - .map( - (operator) => - new OracleDiscoveryResult( - operator.address, + const discoveredOracles: DiscoveredOracle[] = []; + for (const exchangeOracle of exchangeOracles) { + if ( + OracleDiscoveryService.checkExpectationsOfDiscoveredOracle( + exchangeOracle, + reputationOracleJobTypes, + ) + ) { + discoveredOracles.push( + new DiscoveredOracle({ + address: exchangeOracle.address, + role: exchangeOracle.role, + url: exchangeOracle.url, + jobTypes: exchangeOracle.jobTypes, + registrationNeeded: exchangeOracle.registrationNeeded, + registrationInstructions: exchangeOracle.registrationInstructions, chainId, - operator.role, - operator.url, - operator.jobTypes, - operator.registrationNeeded, - operator.registrationInstructions, - ), - ); + }), + ); + } + } await this.cacheManager.set( - chainId.toString(), - oraclesWithRetryData, + cacheKey, + discoveredOracles, this.configService.cacheTtlOracleDiscovery, ); - return oraclesWithRetryData; + return discoveredOracles; } catch (error) { - this.logger.error(`Error processing chainId ${chainId}:`, error); + this.logger.error( + `Failed to discover oracles for chain '${chainId}':`, + error, + ); return []; } } - private hasJobTypes( - oracleJobTypes: string[] | undefined, - jobTypeSet: Set, - ) { - return oracleJobTypes - ? oracleJobTypes.some((job) => jobTypeSet.has(job.toLowerCase())) - : false; + static checkExpectationsOfDiscoveredOracle( + operator: IOperator, + possibleJobTypes: string[], + ): operator is DiscoveredOracle { + if (!operator.url) { + return false; + } + + if (_.intersection(operator.jobTypes, possibleJobTypes).length === 0) { + return false; + } + + return true; + } + + async updateOracleInCache( + oracleWithUpdates: DiscoveredOracle, + ): Promise { + const cacheKey = oracleWithUpdates.chainId.toString(); + + const cachedOracles = await this.cacheManager.get< + DiscoveredOracle[] | undefined + >(cacheKey); + + if (!cachedOracles) { + return; + } + + const updatedOracles = cachedOracles.map((cachedOracle) => + cachedOracle.address === oracleWithUpdates.address + ? oracleWithUpdates + : cachedOracle, + ); + + await this.cacheManager.set( + cacheKey, + updatedOracles, + this.configService.cacheTtlOracleDiscovery, + ); } } diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts index 1aab6707e1..31a08a42e5 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.controller.spec.ts @@ -5,9 +5,8 @@ import { OracleDiscoveryController } from '../oracle-discovery.controller'; import { OracleDiscoveryService } from '../oracle-discovery.service'; import { oracleDiscoveryServiceMock } from './oracle-discovery.service.mock'; import { - OracleDiscoveryCommand, - OracleDiscoveryDto, - OracleDiscoveryResult, + GetOraclesQuery, + DiscoveredOracle, } from '../model/oracle-discovery.model'; import { generateOracleDiscoveryResponseBody } from './oracle-discovery.fixture'; import { OracleDiscoveryProfile } from '../oracle-discovery.mapper.profile'; @@ -62,26 +61,21 @@ describe('OracleDiscoveryController', () => { }); describe('oracle discovery', () => { - it('oracle discovery should be return OracleDiscoveryData', async () => { + it('should return discovered oracles', async () => { const dtoFixture = { selected_job_types: ['job-type-1', 'job-type-2'], - } as OracleDiscoveryDto; - const commandFixture = { - selectedJobTypes: ['job-type-1', 'job-type-2'], - } as OracleDiscoveryCommand; - const result: OracleDiscoveryResult[] = + } as GetOraclesQuery; + const result: DiscoveredOracle[] = await controller.getOracles(dtoFixture); const expectedResponse = generateOracleDiscoveryResponseBody(); - expect(serviceMock.processOracleDiscovery).toHaveBeenCalledWith( - commandFixture, - ); + expect(serviceMock.getOracles).toHaveBeenCalled(); expect(result).toEqual(expectedResponse); }); it('should throw an error if jobsDiscoveryFlag is disabled', async () => { const dtoFixture = { selected_job_types: ['job-type-1', 'job-type-2'], - } as OracleDiscoveryDto; + } as GetOraclesQuery; (configServiceMock as any).jobsDiscoveryFlag = false; diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts index 27269ec273..37dd12011d 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.fixture.ts @@ -1,10 +1,10 @@ import { ChainId } from '@human-protocol/sdk'; import { - OracleDiscoveryCommand, - OracleDiscoveryResult, + GetOraclesCommand, + DiscoveredOracle, } from '../model/oracle-discovery.model'; -const response1: OracleDiscoveryResult = { +const response1: DiscoveredOracle = { address: '0xd06eac24a0c47c776Ce6826A93162c4AfC029047', chainId: ChainId.POLYGON_AMOY, role: 'role1', @@ -15,17 +15,18 @@ const response1: OracleDiscoveryResult = { registrationNeeded: true, registrationInstructions: 'https://instructions.com', }; -const response2: OracleDiscoveryResult = { +const response2: DiscoveredOracle = { address: '0xd10c3402155c058D78e4D5fB5f50E125F06eb39d', chainId: ChainId.POLYGON_AMOY, role: 'role2', + url: '', jobTypes: ['job-type-1', 'job-type-3', 'job-type-4'], retriesCount: 0, executionsToSkip: 0, registrationNeeded: false, registrationInstructions: undefined, }; -const response3: OracleDiscoveryResult = { +const response3: DiscoveredOracle = { address: '0xd83422155c058D78e4D5fB5f50E125F06eb39d', chainId: ChainId.POLYGON_AMOY, role: 'role3', @@ -36,7 +37,7 @@ const response3: OracleDiscoveryResult = { registrationNeeded: false, registrationInstructions: undefined, }; -const response4: OracleDiscoveryResult = { +const response4: DiscoveredOracle = { address: '0xd83422155c058D78e4D5fB5f50E125F06eb39d', chainId: ChainId.MOONBASE_ALPHA, role: 'role3', @@ -73,12 +74,12 @@ export function generateOracleDiscoveryResponseBodyByJobType(jobType: string) { ); } -export const reputationOracleSupportedJobTypes = 'job-type-1, job-type-4'; +export const reputationOracleSupportedJobTypes = 'job-type-1,job-type-4'; export const filledCommandFixture = { selectedJobTypes: ['job-type-1'], -} as OracleDiscoveryCommand; +} as GetOraclesCommand; export const emptyCommandFixture = { selectedJobTypes: [], -} as OracleDiscoveryCommand; -export const notSetCommandFixture = {} as OracleDiscoveryCommand; +} as GetOraclesCommand; +export const notSetCommandFixture = {} as GetOraclesCommand; export const errorResponse = []; diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.mock.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.mock.ts index b9d98d5256..246444e69d 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.mock.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.mock.ts @@ -1,7 +1,7 @@ import { generateOracleDiscoveryResponseBody } from './oracle-discovery.fixture'; export const oracleDiscoveryServiceMock = { - processOracleDiscovery: jest + getOracles: jest .fn() .mockResolvedValue(generateOracleDiscoveryResponseBody()), }; diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts index 6184473528..5bbcc85dba 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/spec/oracle-discovery.service.spec.ts @@ -33,7 +33,7 @@ describe('OracleDiscoveryService', () => { const EXPECTED_CHAIN_IDS = [ChainId.POLYGON_AMOY, ChainId.MOONBASE_ALPHA]; const REPUTATION_ORACLE_ADDRESS = 'the_oracle'; const TTL = '300'; - const JOB_TYPES = 'job-type-1, job-type-2, job-type-3'; + const JOB_TYPES = 'job-type-1,job-type-2,job-type-3'; let oracleDiscoveryService: OracleDiscoveryService; let cacheManager: Cache; let kvStoreGateway: KvStoreGateway; @@ -99,14 +99,13 @@ describe('OracleDiscoveryService', () => { }); const result = - await oracleDiscoveryService.processOracleDiscovery(notSetCommandFixture); + await oracleDiscoveryService.getOracles(notSetCommandFixture); expect(result).toEqual(mockData); expect(OperatorUtils.getReputationNetworkOperators).not.toHaveBeenCalled(); }); it('should fetch and cache data if not already cached', async () => { - jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(undefined); EXPECTED_CHAIN_IDS.forEach((chainId) => { jest .spyOn(OperatorUtils, 'getReputationNetworkOperators') @@ -115,8 +114,7 @@ describe('OracleDiscoveryService', () => { ); }); - const result = - await oracleDiscoveryService.processOracleDiscovery(emptyCommandFixture); + const result = await oracleDiscoveryService.discoverOracles(); expect(result).toEqual(generateOracleDiscoveryResponseBody()); EXPECTED_CHAIN_IDS.forEach((chainId) => { @@ -135,7 +133,6 @@ describe('OracleDiscoveryService', () => { }); it('should filter oracles if selectedJobTypes not empty, or url not set', async () => { - jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(undefined); EXPECTED_CHAIN_IDS.forEach((chainId) => { jest .spyOn(OperatorUtils, 'getReputationNetworkOperators') @@ -145,7 +142,7 @@ describe('OracleDiscoveryService', () => { }); const result = - await oracleDiscoveryService.processOracleDiscovery(filledCommandFixture); + await oracleDiscoveryService.getOracles(filledCommandFixture); expect(result).toEqual( generateOracleDiscoveryResponseBodyByJobType('job-type-1'), @@ -153,7 +150,6 @@ describe('OracleDiscoveryService', () => { }); it('should not filter responses if selectedJobTypes is empty', async () => { - jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(undefined); EXPECTED_CHAIN_IDS.forEach((chainId) => { jest .spyOn(OperatorUtils, 'getReputationNetworkOperators') @@ -162,7 +158,7 @@ describe('OracleDiscoveryService', () => { ); }); - const result = await oracleDiscoveryService.processOracleDiscovery({ + const result = await oracleDiscoveryService.getOracles({ selectedJobTypes: [], }); @@ -171,7 +167,6 @@ describe('OracleDiscoveryService', () => { it('should handle errors and return an empty array of oracles', async () => { const error = new Error('Test error'); - jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(undefined); jest .spyOn(OperatorUtils, 'getReputationNetworkOperators') .mockRejectedValueOnce(error); @@ -181,24 +176,21 @@ describe('OracleDiscoveryService', () => { 'error', ); - const result = - await oracleDiscoveryService.processOracleDiscovery(emptyCommandFixture); + const result = await oracleDiscoveryService.discoverOracles(); expect(result).toEqual(errorResponse); expect(loggerErrorSpy).toHaveBeenCalledWith( - `Error processing chainId ${ChainId.POLYGON_AMOY}:`, + `Failed to discover oracles for chain '${ChainId.POLYGON_AMOY}':`, error, ); }); it('should return an empty array of oracles if no oracles are found', async () => { - jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(undefined); jest .spyOn(OperatorUtils, 'getReputationNetworkOperators') .mockResolvedValueOnce([]); - const result = - await oracleDiscoveryService.processOracleDiscovery(emptyCommandFixture); + const result = await oracleDiscoveryService.getOracles(emptyCommandFixture); expect(result).toEqual(errorResponse); EXPECTED_CHAIN_IDS.forEach((chainId) => { @@ -210,7 +202,6 @@ describe('OracleDiscoveryService', () => { jest .spyOn(kvStoreGateway, 'getJobTypesByAddress') .mockResolvedValueOnce('job-type-1'); - jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(undefined); EXPECTED_CHAIN_IDS.forEach((chainId) => { jest @@ -220,7 +211,7 @@ describe('OracleDiscoveryService', () => { ); }); - const result = await oracleDiscoveryService.processOracleDiscovery({}); + const result = await oracleDiscoveryService.getOracles({}); const expectedResponse = generateOracleDiscoveryResponseBodyByJobType('job-type-1'); From 6b705c7bd55f9e86d46fccf72eb94c0ac2b37827 Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Thu, 12 Dec 2024 15:20:09 +0100 Subject: [PATCH 60/92] [Dashboard] feat: wrap white space for network column (#2887) --- .../ui-2024/src/features/Leaderboard/components/ChainCell.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx index a1ac7d3606..32b40e4831 100644 --- a/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx +++ b/packages/apps/dashboard/ui-2024/src/features/Leaderboard/components/ChainCell.tsx @@ -5,7 +5,7 @@ import { getNetwork } from '@utils/config/networks'; export const ChainCell = ({ chainId }: { chainId: number }) => ( Date: Thu, 12 Dec 2024 15:24:31 +0100 Subject: [PATCH 61/92] [Human App] feat: set max width for solve button (#2888) --- .../src/pages/worker/jobs/components/my-jobs-table-actions.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx index 57c45c6170..1989e74707 100644 --- a/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx +++ b/packages/apps/human-app/frontend/src/pages/worker/jobs/components/my-jobs-table-actions.tsx @@ -29,6 +29,7 @@ export function MyJobsTableActions({ job }: MyJobsTableRejectActionProps) { fullWidth target="_blank" to={job.url} + sx={{ maxWidth: '160px ' }} > {t('worker.jobs.solve')} From faa806094d9e3738aabd131578a50bd0bc645e04 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Thu, 12 Dec 2024 20:31:58 +0300 Subject: [PATCH 62/92] Upgrade uvicorn dep (#2910) --- .../examples/cvat/exchange-oracle/poetry.lock | 83 ++++++++--------- .../cvat/exchange-oracle/pyproject.toml | 5 +- .../cvat/recording-oracle/poetry.lock | 91 +++++++++---------- .../cvat/recording-oracle/pyproject.toml | 5 +- 4 files changed, 92 insertions(+), 92 deletions(-) diff --git a/packages/examples/cvat/exchange-oracle/poetry.lock b/packages/examples/cvat/exchange-oracle/poetry.lock index 24fdb3b1b5..47fe648f0f 100644 --- a/packages/examples/cvat/exchange-oracle/poetry.lock +++ b/packages/examples/cvat/exchange-oracle/poetry.lock @@ -732,38 +732,38 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "cryptography" -version = "43.0.1" +version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"}, - {file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"}, - {file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"}, - {file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"}, - {file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"}, - {file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2"}, - {file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"}, + {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, + {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, + {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, + {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, + {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, + {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, + {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, ] [package.dependencies] @@ -776,18 +776,18 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] name = "cvat-sdk" -version = "2.22.0" +version = "2.23.1" description = "CVAT REST API" optional = false python-versions = ">=3.9" files = [ - {file = "cvat_sdk-2.22.0-py3-none-any.whl", hash = "sha256:a7e2e89b6bbf523fa8f4be9b5d4fec37f73b00dd800cb83537cd3113f6ddaad1"}, - {file = "cvat_sdk-2.22.0.tar.gz", hash = "sha256:a08f31314f1134c7a11fdf2ead90468fddfa98ecd549b8f1773eceb934b85209"}, + {file = "cvat_sdk-2.23.1-py3-none-any.whl", hash = "sha256:31064d51064505916c77044372463c62689c0ac04c70d7c25b2ceaf462899548"}, + {file = "cvat_sdk-2.23.1.tar.gz", hash = "sha256:dad9d637103029fd089bbce80e5af4561e0b4aaa305499945d90021b51248164"}, ] [package.dependencies] @@ -795,15 +795,16 @@ attrs = ">=21.4.0" packaging = ">=21.3" Pillow = ">=10.3.0" platformdirs = ">=2.1.0" -python-dateutil = ">=2.5.3" +python_dateutil = ">=2.5.3" setuptools = ">=21.0.0" tqdm = ">=4.64.0" tuspy = "0.2.5" -typing-extensions = ">=4.2.0" +typing_extensions = ">=4.2.0" urllib3 = ">=1.25.3" [package.extras] -pytorch = ["torch", "torchvision"] +masks = ["numpy (>=2)"] +pytorch = ["cvat_sdk[masks]", "scikit-image (>=0.24)", "torch", "torchvision"] [[package]] name = "cycler" @@ -4479,20 +4480,20 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.30.0" +version = "0.32.1" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.30.0-py3-none-any.whl", hash = "sha256:78fa0b5f56abb8562024a59041caeb555c86e48d0efdd23c3fe7de7a4075bdab"}, - {file = "uvicorn-0.30.0.tar.gz", hash = "sha256:f678dec4fa3a39706bbf49b9ec5fc40049d42418716cea52b53f07828a60aa37"}, + {file = "uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e"}, + {file = "uvicorn-0.32.1.tar.gz", hash = "sha256:ee9519c246a72b1c084cea8d3b44ed6026e78a4a309cbedae9c37e4cb9fbb175"}, ] [package.dependencies] click = ">=7.0" colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} h11 = ">=0.8" -httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +httptools = {version = ">=0.6.3", optional = true, markers = "extra == \"standard\""} python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} @@ -4501,7 +4502,7 @@ watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standar websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} [package.extras] -standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] [[package]] name = "uvloop" @@ -4918,4 +4919,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10,<3.13" -content-hash = "540388c203215a865ee870a26989be15fee75b56f1ec3ed9ed486c9ab6b0f958" +content-hash = "590a6c9434302dc1fa402a31364007ad17350b927f68f8a4c65936fcad7cdc22" diff --git a/packages/examples/cvat/exchange-oracle/pyproject.toml b/packages/examples/cvat/exchange-oracle/pyproject.toml index e8ab10a095..e48e4e1837 100644 --- a/packages/examples/cvat/exchange-oracle/pyproject.toml +++ b/packages/examples/cvat/exchange-oracle/pyproject.toml @@ -9,14 +9,14 @@ packages = [{include = "exchange_oracle"}] [tool.poetry.dependencies] python = "^3.10,<3.13" fastapi = {version = "^0.115.4", extras = ["standard"]} -uvicorn = "^0.30.0" +uvicorn = ">=0.32.1" # post https://github.com/encode/uvicorn/pull/2397, where using several workers was fixed. Read more https://github.com/encode/uvicorn/discussions/2450 python-dotenv = "^1.0.0" psycopg2 = "^2.9.6" sqlalchemy-utils = "^0.41.1" alembic = "^1.11.1" httpx = "^0.24.1" pytest = "^7.2.2" -cvat-sdk = "^2.22.0" +cvat-sdk = "^2.23.1" sqlalchemy = "^2.0.16" apscheduler = "^3.10.1" xmltodict = "^0.13.0" @@ -33,6 +33,7 @@ fastapi-limiter = "^0.1.6" strenum = "^0.4.15" pyjwt = "^2.9.0" starlette = ">=0.40.0" # avoid the vulnerability with multipart/form-data +cryptography = "<44.0.0" # human-protocol-sdk -> pgpy dep requires cryptography < 45 [tool.poetry.group.dev.dependencies] diff --git a/packages/examples/cvat/recording-oracle/poetry.lock b/packages/examples/cvat/recording-oracle/poetry.lock index 69fcf74c3f..5d455f4875 100644 --- a/packages/examples/cvat/recording-oracle/poetry.lock +++ b/packages/examples/cvat/recording-oracle/poetry.lock @@ -732,43 +732,38 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "cryptography" -version = "42.0.3" +version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a"}, - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b"}, - {file = "cryptography-42.0.3-cp37-abi3-win32.whl", hash = "sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5"}, - {file = "cryptography-42.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54"}, - {file = "cryptography-42.0.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65"}, - {file = "cryptography-42.0.3-cp39-abi3-win32.whl", hash = "sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3"}, - {file = "cryptography-42.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd"}, - {file = "cryptography-42.0.3.tar.gz", hash = "sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe"}, + {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, + {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, + {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, + {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, + {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, + {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, + {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, ] [package.dependencies] @@ -781,18 +776,18 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] name = "cvat-sdk" -version = "2.21.3" +version = "2.23.1" description = "CVAT REST API" optional = false python-versions = ">=3.9" files = [ - {file = "cvat_sdk-2.21.3-py3-none-any.whl", hash = "sha256:07fc2930df6ee3c567b60f4c4eca10b4d1cade31d840a383a56933dbbabb5d2c"}, - {file = "cvat_sdk-2.21.3.tar.gz", hash = "sha256:749c3d010646a4e7d31a2743e113cda47cc803cb82dfa7f19a086aff28753999"}, + {file = "cvat_sdk-2.23.1-py3-none-any.whl", hash = "sha256:31064d51064505916c77044372463c62689c0ac04c70d7c25b2ceaf462899548"}, + {file = "cvat_sdk-2.23.1.tar.gz", hash = "sha256:dad9d637103029fd089bbce80e5af4561e0b4aaa305499945d90021b51248164"}, ] [package.dependencies] @@ -800,15 +795,16 @@ attrs = ">=21.4.0" packaging = ">=21.3" Pillow = ">=10.3.0" platformdirs = ">=2.1.0" -python-dateutil = ">=2.5.3" +python_dateutil = ">=2.5.3" setuptools = ">=21.0.0" tqdm = ">=4.64.0" tuspy = "0.2.5" -typing-extensions = ">=4.2.0" +typing_extensions = ">=4.2.0" urllib3 = ">=1.25.3" [package.extras] -pytorch = ["torch", "torchvision"] +masks = ["numpy (>=2)"] +pytorch = ["cvat_sdk[masks]", "scikit-image (>=0.24)", "torch", "torchvision"] [[package]] name = "cycler" @@ -4284,28 +4280,29 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.22.0" +version = "0.32.1" description = "The lightning-fast ASGI server." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "uvicorn-0.22.0-py3-none-any.whl", hash = "sha256:e9434d3bbf05f310e762147f769c9f21235ee118ba2d2bf1155a7196448bd996"}, - {file = "uvicorn-0.22.0.tar.gz", hash = "sha256:79277ae03db57ce7d9aa0567830bbb51d7a612f54d6e1e3e92da3ef24c2c8ed8"}, + {file = "uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e"}, + {file = "uvicorn-0.32.1.tar.gz", hash = "sha256:ee9519c246a72b1c084cea8d3b44ed6026e78a4a309cbedae9c37e4cb9fbb175"}, ] [package.dependencies] click = ">=7.0" colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} h11 = ">=0.8" -httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +httptools = {version = ">=0.6.3", optional = true, markers = "extra == \"standard\""} python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} [package.extras] -standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] [[package]] name = "uvloop" @@ -4711,4 +4708,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10, <3.13" -content-hash = "ece72f10bc9ea88f5cc3947f80003d8e5f41dcf7434e17edfc55edf8594b0369" +content-hash = "78655be01ca9c1a86d9b7ca513f92076c8a432ded888d42c119da19a68995b81" diff --git a/packages/examples/cvat/recording-oracle/pyproject.toml b/packages/examples/cvat/recording-oracle/pyproject.toml index 280a7eae22..7ec842536a 100644 --- a/packages/examples/cvat/recording-oracle/pyproject.toml +++ b/packages/examples/cvat/recording-oracle/pyproject.toml @@ -9,7 +9,7 @@ packages = [{include = "recording_oracle"}] [tool.poetry.dependencies] python = "^3.10, <3.13" fastapi = {version = "^0.115.4", extras = ["standard"]} -uvicorn = "^0.22.0" +uvicorn = ">=0.32.1" # post https://github.com/encode/uvicorn/pull/2397, where using several workers was fixed. Read more https://github.com/encode/uvicorn/discussions/2450 python-dotenv = "^1.0.0" SQLAlchemy = "^2.0.17" psycopg2 = "^2.9.6" @@ -25,7 +25,8 @@ datumaro = {git = "https://github.com/cvat-ai/datumaro.git", rev = "ff83c00c2c1b human-protocol-sdk = ">=3.0.7b0,<3.1.0" hexbytes = ">=1.2.0" # required for to_0x_hex() function starlette = ">=0.40.0" # avoid the vulnerability with multipart/form-data -cvat-sdk = "^2.21.3" +cvat-sdk = "^2.23.1" +cryptography = "<44.0.0" # human-protocol-sdk -> pgpy dep requires cryptography < 45 [tool.poetry.group.dev.dependencies] hypothesis = "^6.82.6" From 12f0dd15e5bb3eed761d6f0fb5fc2dc8dacf1590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:51:48 +0100 Subject: [PATCH 63/92] Fix some old configuration for core scripts (#2911) --- packages/core/scripts/deploy-proxies.ts | 21 ++++++--------------- packages/core/scripts/deploy.ts | 2 +- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/packages/core/scripts/deploy-proxies.ts b/packages/core/scripts/deploy-proxies.ts index 1f82d40f10..a5510394d2 100644 --- a/packages/core/scripts/deploy-proxies.ts +++ b/packages/core/scripts/deploy-proxies.ts @@ -8,27 +8,18 @@ async function main() { return; } - const Staking = await ethers.getContractFactory('Staking'); - const stakingContract = await upgrades.deployProxy( - Staking, - [hmtAddress, 1, 1, 1], - { initializer: 'initialize', kind: 'uups' } - ); - await stakingContract.waitForDeployment(); - console.log('Staking Proxy Address: ', await stakingContract.getAddress()); - console.log( - 'Staking Implementation Address: ', - await upgrades.erc1967.getImplementationAddress( - await stakingContract.getAddress() - ) - ); + const stakingAddress = process.env.STAKING_ADDRESS; + if (!stakingAddress) { + console.error('STAKING_ADDRESS env variable missing'); + return; + } const EscrowFactory = await ethers.getContractFactory( 'contracts/EscrowFactory.sol:EscrowFactory' ); const escrowFactoryContract = await upgrades.deployProxy( EscrowFactory, - [await stakingContract.getAddress()], + [stakingAddress, 1], { initializer: 'initialize', kind: 'uups' } ); await escrowFactoryContract.waitForDeployment(); diff --git a/packages/core/scripts/deploy.ts b/packages/core/scripts/deploy.ts index 095e2321ba..7ef9c22a5c 100644 --- a/packages/core/scripts/deploy.ts +++ b/packages/core/scripts/deploy.ts @@ -28,7 +28,7 @@ async function main() { ); const escrowFactoryContract = await upgrades.deployProxy( EscrowFactory, - [await stakingContract.getAddress()], + [await stakingContract.getAddress(), 1], { initializer: 'initialize', kind: 'uups' } ); await escrowFactoryContract.waitForDeployment(); From 772b66bf3484e0c57d3d7fdf53f353ad1a27ec8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:06:24 +0100 Subject: [PATCH 64/92] [CVAT Recording Oracle] Fix blockchain-node healthcheck (#2914) * Adjust the number of transactions that must take place on the blockchain node to pass the healthcheck * Fix oracle addresses --- packages/apps/job-launcher/server/test/setup.ts | 2 +- .../examples/cvat/recording-oracle/docker-compose.test.yml | 4 ++-- .../human-protocol-sdk/human_protocol_sdk/constants.py | 6 +++--- packages/sdk/typescript/human-protocol-sdk/src/constants.ts | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/apps/job-launcher/server/test/setup.ts b/packages/apps/job-launcher/server/test/setup.ts index bdf17255fb..05d8861d22 100644 --- a/packages/apps/job-launcher/server/test/setup.ts +++ b/packages/apps/job-launcher/server/test/setup.ts @@ -17,7 +17,7 @@ export async function setup(): Promise { } const provider = new ethers.JsonRpcProvider('http://0.0.0.0:8545'); const hmtTokenAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3'; - const stakingAddress = '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0'; + const stakingAddress = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512'; const wallet = new Wallet(privateKey, provider); const hmtContract = HMToken__factory.connect(hmtTokenAddress, wallet); diff --git a/packages/examples/cvat/recording-oracle/docker-compose.test.yml b/packages/examples/cvat/recording-oracle/docker-compose.test.yml index d30f7a69c8..af02533a32 100644 --- a/packages/examples/cvat/recording-oracle/docker-compose.test.yml +++ b/packages/examples/cvat/recording-oracle/docker-compose.test.yml @@ -18,8 +18,8 @@ services: context: ./ dockerfile: dockerfiles/blockchain-node.Dockerfile healthcheck: - # Using a magic nubmer of 28 here because this is a block number when blockchain-node container is ready to use - test: if [ $(( $(wget -q --post-data='{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' -O- http://blockchain-node:8545 | grep -o '"result":"[^"]*"' | awk -F'"' '{print $4}' ) )) -ge 28 ]; then exit 0; else exit 1; fi + # Using a magic nubmer of 23 here because this is a block number when blockchain-node container is ready to use + test: if [ $(( $(wget -q --post-data='{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' -O- http://blockchain-node:8545 | grep -o '"result":"[^"]*"' | awk -F'"' '{print $4}' ) )) -ge 23 ]; then exit 0; else exit 1; fi interval: 15s timeout: 5s retries: 15 diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py index 65d1b89416..d96a4efb3d 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py @@ -305,9 +305,9 @@ class OrderDirection(Enum): "subgraph_url": "http://localhost:8000/subgraphs/name/humanprotocol/localhost", "subgraph_url_api_key": "", "hmt_address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "factory_address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", - "staking_address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", - "kvstore_address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707", + "factory_address": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", + "staking_address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + "kvstore_address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", "old_subgraph_url": "", "old_factory_address": "", }, diff --git a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts index 036f091fb2..61f19bd3f7 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts @@ -289,10 +289,10 @@ export const NETWORKS: { chainId: ChainId.LOCALHOST, title: 'Localhost', scanUrl: '', - factoryAddress: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9', + factoryAddress: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9', hmtAddress: '0x5FbDB2315678afecb367f032d93F642f64180aa3', - stakingAddress: '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0', - kvstoreAddress: '0x5FC8d32690cc91D4c39d9d3abcBD16989F875707', + stakingAddress: '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512', + kvstoreAddress: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9', subgraphUrl: 'http://localhost:8000/subgraphs/name/humanprotocol/localhost', subgraphUrlApiKey: '', oldSubgraphUrl: '', From 1957372787fa6279e6e2983e4ece58a75aa8b744 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Fri, 13 Dec 2024 17:57:25 +0300 Subject: [PATCH 65/92] [CVAT] Fix parallel escrow validations (#2915) * Use simple locks in escrow validations * Improve parameter description * Fix error handling logic * Fix linter error --- .../cvat/exchange-oracle/src/core/config.py | 4 +- .../src/handlers/completed_escrows.py | 59 ++++++++----------- .../cvat/exchange-oracle/src/services/cvat.py | 44 ++------------ .../test_track_completed_escrows.py | 16 ++--- 4 files changed, 42 insertions(+), 81 deletions(-) diff --git a/packages/examples/cvat/exchange-oracle/src/core/config.py b/packages/examples/cvat/exchange-oracle/src/core/config.py index d1b3c0c2b6..66c5192cf5 100644 --- a/packages/examples/cvat/exchange-oracle/src/core/config.py +++ b/packages/examples/cvat/exchange-oracle/src/core/config.py @@ -147,12 +147,12 @@ class CronConfig: ) track_escrow_validations_int = int(os.environ.get("TRACK_COMPLETED_ESCROWS_INT", 60)) track_escrow_validations_chunk_size = int( - os.environ.get("TRACK_ESCROW_VALIDATIONS_CHUNK_SIZE", 5) + os.environ.get("TRACK_ESCROW_VALIDATIONS_CHUNK_SIZE", 1) ) track_completed_escrows_max_downloading_retries = int( os.environ.get("TRACK_COMPLETED_ESCROWS_MAX_DOWNLOADING_RETRIES", 10) ) - "Maximum number of downloading attempts per job during results downloading" + "Maximum number of downloading attempts per job or project during results downloading" track_completed_escrows_jobs_downloading_batch_size = int( os.environ.get("TRACK_COMPLETED_ESCROWS_JOBS_DOWNLOADING_BATCH_SIZE", 500) diff --git a/packages/examples/cvat/exchange-oracle/src/handlers/completed_escrows.py b/packages/examples/cvat/exchange-oracle/src/handlers/completed_escrows.py index 6666f48a65..1900024b4f 100644 --- a/packages/examples/cvat/exchange-oracle/src/handlers/completed_escrows.py +++ b/packages/examples/cvat/exchange-oracle/src/handlers/completed_escrows.py @@ -11,7 +11,6 @@ import src.services.cloud as cloud_service import src.services.cvat as cvat_service import src.services.webhook as oracle_db_service -from src import db from src.chain.escrow import get_escrow_manifest, validate_escrow from src.core.annotation_meta import ANNOTATION_RESULTS_METAFILE_NAME, RESULTING_ANNOTATIONS_FILE from src.core.config import CronConfig, StorageConfig @@ -19,7 +18,6 @@ from src.core.storage import compose_results_bucket_filename from src.core.types import EscrowValidationStatuses, OracleWebhookTypes, TaskTypes from src.db import SessionLocal -from src.db import errors as db_errors from src.db.utils import ForUpdateParams from src.handlers.job_export import ( CVAT_EXPORT_FORMAT_MAPPING, @@ -238,48 +236,41 @@ def _handle_escrow_validation( session: Session, escrow_address: str, chain_id: int, -) -> bool: - try: - validate_escrow(chain_id, escrow_address) - except Exception as e: - logger.exception(f"Failed to handle completed projects for escrow {escrow_address}: {e}") - return False - - # try to get pessimistic lock for projects and lock escrow validation - # if we fail to do that, simply skip the escrow - with db.suppress(db_errors.LockNotAvailable): - cvat_service.lock_escrow_for_validation( - session, escrow_address=escrow_address, chain_id=chain_id - ) - escrow_projects = cvat_service.get_projects_by_escrow_address( - session, escrow_address, limit=None, for_update=ForUpdateParams(nowait=True) - ) - _export_escrow_annotations(logger, chain_id, escrow_address, escrow_projects, session) - return True - return False +): + validate_escrow(chain_id, escrow_address) + escrow_projects = cvat_service.get_projects_by_escrow_address( + session, escrow_address, limit=None, for_update=ForUpdateParams(nowait=True) + ) + _export_escrow_annotations(logger, chain_id, escrow_address, escrow_projects, session) -def handle_escrows_validations(logger: logging.Logger) -> None: - with SessionLocal.begin() as session: - escrow_validations = cvat_service.prepare_escrows_for_validation( - session, - limit=CronConfig.track_escrow_validations_chunk_size, - ) - for escrow_address, chain_id in escrow_validations: +def handle_escrows_validations(logger: logging.Logger) -> None: + for _ in range(CronConfig.track_escrow_validations_chunk_size): with SessionLocal.begin() as session: # Need to work in separate transactions for each escrow, as a failing DB call # (e.g. a failed lock attempt) will abort the transaction. A nested transaction # can also be used for handling this. - handled = _handle_escrow_validation(logger, session, escrow_address, chain_id) - if not handled: - # either escrow is invalid, or we couldn't get lock for projects/validations - continue + escrow_validation = cvat_service.lock_escrow_for_validation(session) + if not escrow_validation: + break + + escrow_address = escrow_validation.escrow_address + chain_id = escrow_validation.chain_id + + update_kwargs = {} + try: + _handle_escrow_validation(logger, session, escrow_address, chain_id) + + # Change status so validation won't be attempted again + update_kwargs["status"] = EscrowValidationStatuses.in_progress + except Exception as e: + logger.exception(e) - # change status so validation won't be attempted again cvat_service.update_escrow_validation( session, escrow_address=escrow_address, chain_id=chain_id, - status=EscrowValidationStatuses.in_progress, + increase_attempts=True, # increase attempts always to allow escrow rotation + **update_kwargs, ) diff --git a/packages/examples/cvat/exchange-oracle/src/services/cvat.py b/packages/examples/cvat/exchange-oracle/src/services/cvat.py index e6b58f5ccb..e0f249f8e1 100644 --- a/packages/examples/cvat/exchange-oracle/src/services/cvat.py +++ b/packages/examples/cvat/exchange-oracle/src/services/cvat.py @@ -504,38 +504,15 @@ def finish_escrow_creations_by_escrow_address( # EscrowValidation -def prepare_escrows_for_validation( - session: Session, *, limit: int = 5 -) -> Sequence[tuple[str, int]]: - subquery = ( - select(EscrowValidation.id) +def lock_escrow_for_validation(session: Session) -> EscrowValidation | None: + query = ( + select(EscrowValidation) .where(EscrowValidation.status == EscrowValidationStatuses.awaiting) - .limit(limit) .order_by(EscrowValidation.attempts.asc()) + .limit(1) + .with_for_update(skip_locked=True) ) - update_stmt = ( - update(EscrowValidation) - .where(EscrowValidation.id.in_(subquery)) - .values(attempts=EscrowValidation.attempts + 1) - .returning(EscrowValidation.escrow_address, EscrowValidation.chain_id) - ) - return session.execute(update_stmt).all() - - -def lock_escrow_for_validation( - session: Session, - *, - escrow_address: str, - chain_id: int, -) -> Sequence[tuple[str, str, int]]: - stmt = ( - select(EscrowValidation.escrow_address, EscrowValidation.chain_id) - .where( - EscrowValidation.escrow_address == escrow_address, EscrowValidation.chain_id == chain_id - ) - .with_for_update(nowait=True) - ) - return session.execute(stmt) + return session.execute(query).scalar() def update_escrow_validation( @@ -562,15 +539,6 @@ def update_escrow_validation( session.execute(stmt) -def update_escrow_validation_statuses_by_ids( - session: Session, - ids: Iterable[str], - status: EscrowValidationStatuses, -) -> None: - stmt = update(EscrowValidation).where(EscrowValidation.id.in_(ids)).values(status=status) - session.execute(stmt) - - def get_escrow_validation_by_escrow_address( session: Session, escrow_address: str, chain_id: int ) -> EscrowValidation | None: diff --git a/packages/examples/cvat/exchange-oracle/tests/integration/cron/state_trackers/test_track_completed_escrows.py b/packages/examples/cvat/exchange-oracle/tests/integration/cron/state_trackers/test_track_completed_escrows.py index 57eaef4501..8bc4f9f67a 100644 --- a/packages/examples/cvat/exchange-oracle/tests/integration/cron/state_trackers/test_track_completed_escrows.py +++ b/packages/examples/cvat/exchange-oracle/tests/integration/cron/state_trackers/test_track_completed_escrows.py @@ -10,7 +10,6 @@ from unittest.mock import Mock, patch import datumaro as dm -import pytest from sqlalchemy import select from src.core.types import ( @@ -384,7 +383,7 @@ def test_retrieve_annotations_error_getting_annotations(self): patch("src.handlers.completed_escrows.validate_escrow"), patch( "src.handlers.completed_escrows.cvat_api.request_job_annotations" - ) as mock_annotations, + ) as mock_request_job_annotations, patch("src.handlers.completed_escrows.cloud_service") as mock_cloud_service, ): manifest = json.load(data) @@ -395,9 +394,11 @@ def test_retrieve_annotations_error_getting_annotations(self): mock_storage_client.create_file = mock_create_file mock_cloud_service.make_client = Mock(return_value=mock_storage_client) - mock_annotations.side_effect = _TestException() - with pytest.raises(_TestException): - track_escrow_validations() + mock_request_job_annotations.side_effect = _TestException() + + track_escrow_validations() + + mock_request_job_annotations.assert_called() webhook = ( self.session.query(Webhook) @@ -527,8 +528,9 @@ def test_retrieve_annotations_error_uploading_files(self): mock_cvat_api.get_project_annotations.return_value = dummy_zip_file mock_cloud_service.make_client.return_value.create_file.side_effect = _TestException() - with pytest.raises(_TestException): - track_escrow_validations() + track_escrow_validations() + + mock_cloud_service.make_client.return_value.create_file.assert_called() webhook = ( self.session.query(Webhook) From d71ce0dd098c4455d97d165f0ee0341b3e4fa500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:44:53 +0100 Subject: [PATCH 66/92] [Dashboard] Transactions table (#2902) * Update transaction table format to the new transaction schema * Refactor colors * Negative value for outgoing transactions * Added links to addresses and display receiver instead of to when available --- .../src/modules/details/details.service.ts | 1 - .../modules/details/dto/transaction.dto.ts | 38 ++++-- .../src/assets/styles/color-palette.ts | 5 + .../SearchResults/AbbreviateClipboard.tsx | 8 +- .../cells/TransactionTableCellMethod.tsx | 66 ++++++++-- .../tableComponents/TransactionsTableBody.tsx | 121 ++++++++++++++---- .../tableComponents/TransactionsTableHead.tsx | 12 +- .../services/api/use-transaction-details.tsx | 15 ++- 8 files changed, 206 insertions(+), 60 deletions(-) diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index d17f2e63e0..b69b7de1ec 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -85,7 +85,6 @@ export class DetailsService { first: number, skip: number, ): Promise { - // TODO: Switch to fetch all transactions related to this wallet address once SDK is changed const transactions = await TransactionUtils.getTransactions({ chainId, fromAddress: address, diff --git a/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts index 0e5cd2711c..08baf89d9b 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/transaction.dto.ts @@ -1,20 +1,18 @@ import { Expose, Transform } from 'class-transformer'; -import { IsNumber, IsString } from 'class-validator'; +import { IsNumber, IsOptional, IsString } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export interface Transfer { +export interface InternalTransaction { from: string; to: string; value: string; + method: string; + receiver?: string; + escrow?: string; + token?: string; } export class TransactionPaginationDto { - @ApiProperty({ example: 12345 }) - @Transform(({ value }) => Number(value)) - @IsNumber() - @Expose() - public block: number; - @ApiProperty({ example: '0x020efc94ef6d9d7aa9a4886cc9e1659f4f2b63557133c29d51f387bcb0c4afd7', @@ -23,6 +21,11 @@ export class TransactionPaginationDto { @Expose() public txHash: string; + @ApiProperty({ example: 'Transfer' }) + @IsString() + @Expose() + public method: string; + @ApiProperty({ example: '0xad1F7e45D83624A0c628F1B03477c6E129EddB78' }) @IsString() @Expose() @@ -33,6 +36,18 @@ export class TransactionPaginationDto { @Expose() public to: string; + @ApiProperty({ example: '0xad1F7e45D83624A0c628F1B03477c6E129EddB78' }) + @IsOptional() + @IsString() + @Expose() + public receiver?: string; + + @ApiProperty({ example: 12345 }) + @Transform(({ value }) => Number(value)) + @IsNumber() + @Expose() + public block: number; + @ApiProperty({ example: '0.123' }) @Transform(({ value, obj }) => { return obj.currentAddress.toLowerCase() === obj.from.toLowerCase() @@ -43,15 +58,10 @@ export class TransactionPaginationDto { @Expose() public value: string; - @ApiProperty({ example: 'Transfer' }) - @IsString() - @Expose() - public method: string; - @ApiProperty({ type: [Object], description: 'List of transfers associated with the transaction', }) @Expose() - public transfers: Transfer[]; + public internalTransactions: InternalTransaction[]; } diff --git a/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts b/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts index c84f434d04..0d1b0e298e 100644 --- a/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts +++ b/packages/apps/dashboard/ui-2024/src/assets/styles/color-palette.ts @@ -61,4 +61,9 @@ export const colorPalette = { dark: '#858ec6', contrastText: '#858ec6', }, + table: { + main: '#FFFFFF01', + selected: '#1406B21F', + secondary: '#1406B20A', + }, } as const; diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx b/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx index c7af5e42d5..22abd401aa 100644 --- a/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/SearchResults/AbbreviateClipboard.tsx @@ -18,7 +18,13 @@ const AbbreviateClipboard = ({ value, link }: AbbreviateClipboardProps) => { const navigate = useNavigate(); return ( - + {link ? ( { diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx index af088b3ff5..9480c5cd7d 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod.tsx @@ -8,28 +8,66 @@ export const TransactionTableCellMethod = ({ method }: { method: string }) => { string, { color: { text: string; border: string } } > = { - transfer: { + withdraw: { color: { - text: colorPalette.success.main, - border: colorPalette.success.light, + text: colorPalette.error.main, + border: colorPalette.error.light, }, }, - complete: { + cancel: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, + }, + }, + stake: { color: { text: colorPalette.success.main, border: colorPalette.success.light, }, }, - payout: { + unstake: { color: { - text: colorPalette.secondary.main, - border: colorPalette.secondary.light, + text: colorPalette.error.main, + border: colorPalette.error.light, + }, + }, + slash: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, + }, + }, + stakeWithdrawn: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, + }, + }, + withdrawFees: { + color: { + text: colorPalette.error.main, + border: colorPalette.error.light, + }, + }, + approve: { + color: { + text: colorPalette.warning.main, + border: colorPalette.warning.light, + }, + }, + complete: { + color: { + text: colorPalette.success.main, + border: colorPalette.success.light, }, }, }; - const currentStatusColors = - methodAttributes[method]?.color || colorPalette.success.main; + const currentStatusColors = methodAttributes[method]?.color || { + text: colorPalette.primary.main, + border: colorPalette.primary.light, + }; return ( { display: 'inline-flex', paddingX: 2, paddingY: 1, - borderRadius: 4, + borderRadius: 6, border: `1px solid ${currentStatusColors.border}`, }} > - {capitalize(method)} + + {capitalize(method)} + ); }; diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx index 90de6c0603..1bc9c3a454 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBody.tsx @@ -1,18 +1,24 @@ +import React, { useEffect, useState } from 'react'; import TableRow from '@mui/material/TableRow'; import TableCell from '@mui/material/TableCell'; import MuiTableBody from '@mui/material/TableBody'; +import Box from '@mui/material/Box'; +import IconButton from '@mui/material/IconButton'; +import CircularProgress from '@mui/material/CircularProgress'; +import AddCircleIcon from '@mui/icons-material/AddCircle'; +import RemoveCircleIcon from '@mui/icons-material/RemoveCircle'; import AbbreviateClipboard from '@components/SearchResults/AbbreviateClipboard'; -import { useTransactionDetails } from '@services/api/use-transaction-details'; -import { useEffect } from 'react'; -import { useTransactionDetailsDto } from '@utils/hooks/use-transactions-details-dto'; +import { colorPalette } from '@assets/styles/color-palette'; + import { TransactionTableCellMethod } from '@pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellMethod'; import { TransactionTableCellValue } from '@pages/SearchResults/WalletAddress/WalletAddressTransactions/cells/TransactionTableCellValue'; +import { useTransactionDetails } from '@services/api/use-transaction-details'; import { TransactionsTableBodyContainer } from '@pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableBodyContainer'; import { handleErrorMessage } from '@services/handle-error-message'; -import CircularProgress from '@mui/material/CircularProgress'; import { useWalletSearch } from '@utils/hooks/use-wallet-search'; +import { useTransactionDetailsDto } from '@utils/hooks/use-transactions-details-dto'; -export const TransactionsTableBody = () => { +export const TransactionsTableBody: React.FC = () => { const { data, isPending, isError, error } = useTransactionDetails(); const { filterParams } = useWalletSearch(); const { @@ -32,6 +38,15 @@ export const TransactionsTableBody = () => { setLastPageIndex(undefined); }, [filterParams.address, filterParams.chainId, setLastPageIndex]); + const [expandedRows, setExpandedRows] = useState>({}); + + const toggleRow = (idx: number) => { + setExpandedRows((prev) => ({ + ...prev, + [idx]: !prev[idx], + })); + }; + if (isPending) { return ( @@ -57,30 +72,86 @@ export const TransactionsTableBody = () => { } return ( - + {data.results.map((elem, idx) => ( - - + - - - - - - {elem.block} - - - - - - - - - - + + + + {elem.internalTransactions.length > 0 && ( + toggleRow(idx)} size="small"> + {expandedRows[idx] ? ( + + ) : ( + + )} + + )} + + + + + + + + + + + + {' '} + + + {elem.block} + + + + + {elem.internalTransactions?.map((internalTx, internalIdx) => ( + + + + + + + + + + + + + + + + + ))} + ))} ); diff --git a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx index eecfa4c5d4..24d5723e1d 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/SearchResults/WalletAddress/WalletAddressTransactions/tableComponents/TransactionsTableHead.tsx @@ -52,6 +52,12 @@ export const TransactionsTableHead = () => { Method + + From + + + To + @@ -82,12 +88,6 @@ export const TransactionsTableHead = () => { Value - - From - - - To - ); diff --git a/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx b/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx index 3596cd0266..a5d06bb1fd 100644 --- a/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx +++ b/packages/apps/dashboard/ui-2024/src/services/api/use-transaction-details.tsx @@ -6,13 +6,24 @@ import { useWalletSearch } from '@utils/hooks/use-wallet-search'; import { useTransactionDetailsDto } from '@utils/hooks/use-transactions-details-dto'; import { validateResponse } from '@services/validate-response'; -const transactionDetailsSuccessResponseSchema = z.object({ - block: z.number(), +const internalTransactionSchema = z.object({ from: z.string(), to: z.string(), value: z.string(), method: z.string(), + receiver: z.string().nullable(), + escrow: z.string().nullable(), + token: z.string().nullable(), +}); +const transactionDetailsSuccessResponseSchema = z.object({ txHash: z.string(), + method: z.string(), + from: z.string(), + to: z.string(), + receiver: z.string().nullable(), + block: z.number(), + value: z.string(), + internalTransactions: z.array(internalTransactionSchema), }); export type TransactionDetails = z.infer< From 29f70a5a3bf6260eb2be80f86fc8aa3443a6697e Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:29:16 +0100 Subject: [PATCH 67/92] change dist filename to snake case (#2917) --- packages/sdk/python/human-protocol-sdk/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/python/human-protocol-sdk/pyproject.toml b/packages/sdk/python/human-protocol-sdk/pyproject.toml index a084044f24..5badb3def8 100644 --- a/packages/sdk/python/human-protocol-sdk/pyproject.toml +++ b/packages/sdk/python/human-protocol-sdk/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "human-protocol-sdk" +name = "human_protocol_sdk" dynamic = ["version"] [tool.setuptools.dynamic] From 1b44f4fd47247a125ca5ded095b6bb4002411c43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:29:30 +0100 Subject: [PATCH 68/92] chore(deps): bump @mui/icons-material from 6.1.9 to 6.2.0 (#2918) Bumps [@mui/icons-material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material) from 6.1.9 to 6.2.0. - [Release notes](https://github.com/mui/material-ui/releases) - [Changelog](https://github.com/mui/material-ui/blob/master/CHANGELOG.md) - [Commits](https://github.com/mui/material-ui/commits/v6.2.0/packages/mui-icons-material) --- updated-dependencies: - dependency-name: "@mui/icons-material" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/dashboard/ui-2024/package.json | 2 +- packages/apps/faucet/client/package.json | 2 +- packages/apps/human-app/frontend/package.json | 2 +- packages/apps/job-launcher/client/package.json | 2 +- yarn.lock | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/apps/dashboard/ui-2024/package.json b/packages/apps/dashboard/ui-2024/package.json index 5abf592ce1..f09fab503a 100644 --- a/packages/apps/dashboard/ui-2024/package.json +++ b/packages/apps/dashboard/ui-2024/package.json @@ -15,7 +15,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@mui/icons-material": "^6.1.1", + "@mui/icons-material": "^6.2.0", "@mui/material": "^5.15.18", "@mui/styled-engine-sc": "6.1.3", "@mui/x-data-grid": "^7.22.2", diff --git a/packages/apps/faucet/client/package.json b/packages/apps/faucet/client/package.json index 4fad0baadd..56a538be25 100644 --- a/packages/apps/faucet/client/package.json +++ b/packages/apps/faucet/client/package.json @@ -6,7 +6,7 @@ "license": "MIT", "dependencies": { "@human-protocol/sdk": "*", - "@mui/icons-material": "^6.1.1", + "@mui/icons-material": "^6.2.0", "@mui/material": "^5.16.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/apps/human-app/frontend/package.json b/packages/apps/human-app/frontend/package.json index 1a6d0ad4e3..be9b3456fd 100644 --- a/packages/apps/human-app/frontend/package.json +++ b/packages/apps/human-app/frontend/package.json @@ -21,7 +21,7 @@ "@hcaptcha/react-hcaptcha": "^0.3.6", "@hookform/resolvers": "^3.3.4", "@human-protocol/sdk": "*", - "@mui/icons-material": "^6.1.1", + "@mui/icons-material": "^6.2.0", "@mui/material": "^5.16.7", "@reown/appkit": "1.3.2", "@reown/appkit-adapter-wagmi": "1.3.2", diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 6cd3e465e3..55386e53b0 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -7,7 +7,7 @@ "@emotion/styled": "^11.10.5", "@hcaptcha/react-hcaptcha": "^1.10.1", "@human-protocol/sdk": "*", - "@mui/icons-material": "^6.1.5", + "@mui/icons-material": "^6.2.0", "@mui/lab": "^5.0.0-alpha.141", "@mui/material": "^5.16.7", "@mui/x-date-pickers": "^7.5.0", diff --git a/yarn.lock b/yarn.lock index 39527c865c..377abed2a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3177,10 +3177,10 @@ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.8.tgz#b83316d14dad08fac7cd0574f2643b01959b4464" integrity sha512-DARxShbBsWz6azwkTmv05rR7rJfcd9cXFsQtbcr24A+5esQBSnK2N3cbg/izlvuMGxonfWaysz/ae+6Ij9RAHQ== -"@mui/icons-material@^6.1.1", "@mui/icons-material@^6.1.5": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-6.1.9.tgz#68b1003d3e29db4f5d5e5f46a4333f34762aeeeb" - integrity sha512-AzlhIT51rdjkZ/EcUV2dbhNkNSUHIqCnNoUxodpiTw8buyAUBd+qnxg5OBSuPpun/ZEdSSB8Q7Uyh6zqjiMsEQ== +"@mui/icons-material@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-6.2.0.tgz#8815b7b064234f525a174dd8bc59eb2f8986e79b" + integrity sha512-WR1EEhGOSvxAsoTSzWZBlrWFjul8wziDrII4rC3PvMBHhBYBqEc2n/0aamfFbwkH5EiYb96aqc6kYY6tB310Sw== dependencies: "@babel/runtime" "^7.26.0" From 014216ccde044ff4c2665c11b3c146f518d67112 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:30:17 +0100 Subject: [PATCH 69/92] chore(deps-dev): bump typedoc from 0.27.4 to 0.27.5 (#2919) Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.27.4 to 0.27.5. - [Release notes](https://github.com/TypeStrong/TypeDoc/releases) - [Changelog](https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md) - [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.27.4...v0.27.5) --- updated-dependencies: - dependency-name: typedoc dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/sdk/typescript/human-protocol-sdk/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/sdk/typescript/human-protocol-sdk/package.json b/packages/sdk/typescript/human-protocol-sdk/package.json index 697bfd2c4d..f5446eaef5 100644 --- a/packages/sdk/typescript/human-protocol-sdk/package.json +++ b/packages/sdk/typescript/human-protocol-sdk/package.json @@ -50,7 +50,7 @@ "vitest": "^1.6.0" }, "devDependencies": { - "typedoc": "^0.27.4", + "typedoc": "^0.27.5", "typedoc-plugin-markdown": "^4.2.3" }, "typedocOptions": { diff --git a/yarn.lock b/yarn.lock index 377abed2a6..357c05a84f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19549,10 +19549,10 @@ typedoc-plugin-markdown@^4.2.3: resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.3.0.tgz#d4ee289ea8e04b03801dc476eb3090142983bfe5" integrity sha512-yAR7+JGSwHWNzQhS8AFlGX6GmbWnK7/Q2Y8hHy5pkL/WB9ooJqhsI6B1abldhM3lOQCWqCdkzu9yFMPuvl2HUw== -typedoc@^0.27.4: - version "0.27.4" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.27.4.tgz#45be59ccf9383d3c52f4a96636d823345c6ff0e6" - integrity sha512-wXPQs1AYC2Crk+1XFpNuutLIkNWleokZf1UNf/X8w9KsMnirkvT+LzxTXDvfF6ug3TSLf3Xu5ZXRKGfoXPX7IA== +typedoc@^0.27.5: + version "0.27.5" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.27.5.tgz#a86c89589213d7b36301eeafb4ddf6ad9dfd1ab3" + integrity sha512-x+fhKJtTg4ozXwKayh/ek4wxZQI/+2hmZUdO2i2NGDBRUflDble70z+ewHod3d4gRpXSO6fnlnjbDTnJk7HlkQ== dependencies: "@gerrit0/mini-shiki" "^1.24.0" lunr "^2.3.9" From 3cc7ed42f523294997205931c778cc78eaf2b3cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:31:00 +0100 Subject: [PATCH 70/92] chore(deps): bump @reduxjs/toolkit from 2.3.0 to 2.5.0 (#2921) Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.3.0 to 2.5.0. - [Release notes](https://github.com/reduxjs/redux-toolkit/releases) - [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.3.0...v2.5.0) --- updated-dependencies: - dependency-name: "@reduxjs/toolkit" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/job-launcher/client/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 55386e53b0..fd443712a2 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -11,7 +11,7 @@ "@mui/lab": "^5.0.0-alpha.141", "@mui/material": "^5.16.7", "@mui/x-date-pickers": "^7.5.0", - "@reduxjs/toolkit": "^2.2.7", + "@reduxjs/toolkit": "^2.5.0", "@stripe/react-stripe-js": "^3.0.0", "@stripe/stripe-js": "^4.2.0", "@tanstack/query-sync-storage-persister": "^5.59.0", diff --git a/yarn.lock b/yarn.lock index 357c05a84f..01f2d28461 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4251,10 +4251,10 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.1.0.tgz#cba454c05ec201bd5547aaf55286d44682ac8eb5" integrity sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g== -"@reduxjs/toolkit@^2.2.7": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.3.0.tgz#d00134634d6c1678e8563ac50026e429e3b64420" - integrity sha512-WC7Yd6cNGfHx8zf+iu+Q1UPTfEcXhQ+ATi7CV1hlrSAaQBdlPzg7Ww/wJHNQem7qG9rxmWoFCDCPubSvFObGzA== +"@reduxjs/toolkit@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.5.0.tgz#4679b09b4da211cb9a821803aabf86a13c96fbfa" + integrity sha512-awNe2oTodsZ6LmRqmkFhtb/KH03hUhxOamEQy411m3Njj3BbFvoBovxo4Q1cBWnV1ErprVj9MlF0UPXkng0eyg== dependencies: immer "^10.0.3" redux "^5.0.1" From 73d77798e022f1dfdef9c10ac8da5e18cfabf0f6 Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Mon, 16 Dec 2024 17:10:55 +0100 Subject: [PATCH 71/92] Use networks avialable TTL in seconds (#2924) --- .../server/src/common/config/env-config.service.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/apps/dashboard/server/src/common/config/env-config.service.ts b/packages/apps/dashboard/server/src/common/config/env-config.service.ts index dcd11ebed7..3032ec230a 100644 --- a/packages/apps/dashboard/server/src/common/config/env-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/env-config.service.ts @@ -17,7 +17,7 @@ export const DEFAULT_HCAPTCHA_STATS_ENABLED = true; export const HMT_STATS_START_DATE = '2021-04-06'; export const MINIMUM_HMT_TRANSFERS = 5; export const DEFAULT_NETWORK_USAGE_FILTER_MONTHS = 1; -export const DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL = 2 * 60; +export const DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL = 60 * 60; export const MINIMUM_ESCROWS_COUNT = 1; @Injectable() @@ -103,9 +103,11 @@ export class EnvironmentConfigService { } get networkAvailableCacheTtl(): number { - return this.configService.get( - 'NETWORKS_AVAILABLE_CACHE_TTL', - DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL, + return ( + this.configService.get( + 'NETWORKS_AVAILABLE_CACHE_TTL', + DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL, + ) * 1000 ); } } From 3ed8302ebf41816ceb27a507074abbb57f84b0bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 17:12:04 +0100 Subject: [PATCH 72/92] chore(deps): bump @mui/x-data-grid from 7.22.3 to 7.23.2 (#2920) Bumps [@mui/x-data-grid](https://github.com/mui/mui-x/tree/HEAD/packages/x-data-grid) from 7.22.3 to 7.23.2. - [Release notes](https://github.com/mui/mui-x/releases) - [Changelog](https://github.com/mui/mui-x/blob/master/CHANGELOG.md) - [Commits](https://github.com/mui/mui-x/commits/v7.23.2/packages/x-data-grid) --- updated-dependencies: - dependency-name: "@mui/x-data-grid" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/dashboard/ui-2024/package.json | 2 +- yarn.lock | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/apps/dashboard/ui-2024/package.json b/packages/apps/dashboard/ui-2024/package.json index f09fab503a..d8f7127848 100644 --- a/packages/apps/dashboard/ui-2024/package.json +++ b/packages/apps/dashboard/ui-2024/package.json @@ -18,7 +18,7 @@ "@mui/icons-material": "^6.2.0", "@mui/material": "^5.15.18", "@mui/styled-engine-sc": "6.1.3", - "@mui/x-data-grid": "^7.22.2", + "@mui/x-data-grid": "^7.23.2", "@mui/x-date-pickers": "^7.5.0", "@tanstack/react-query": "^5.48.0", "@types/react-router-dom": "^5.3.3", diff --git a/yarn.lock b/yarn.lock index 01f2d28461..9222405fed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3287,14 +3287,14 @@ prop-types "^15.8.1" react-is "^18.3.1" -"@mui/x-data-grid@^7.22.2": - version "7.22.3" - resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-7.22.3.tgz#22c4c23212434c6256ed5d11f7ba12a8310f9c4b" - integrity sha512-O6kBf6yt/GkOcWjHca5xWN10qBQ/MkITvJmBuIOtX+LH7YtOAriMgD2zkhNbXxHChi7QdEud3bNC3jw5RLRVCA== +"@mui/x-data-grid@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-7.23.2.tgz#3cc82c609a56b02dfe0317d74ab21d0e69dbe964" + integrity sha512-Xhm4Bh+WiU5MSLFIZ8mE1egHoS0xPEVlwvjYvairPIkxNPubB7f+gtLkuAJ2+m+BYbgO7yDte+Pp7dfjkU+vOA== dependencies: "@babel/runtime" "^7.25.7" "@mui/utils" "^5.16.6 || ^6.0.0" - "@mui/x-internals" "7.21.0" + "@mui/x-internals" "7.23.0" clsx "^2.1.1" prop-types "^15.8.1" reselect "^5.1.1" @@ -3320,6 +3320,14 @@ "@babel/runtime" "^7.25.7" "@mui/utils" "^5.16.6 || ^6.0.0" +"@mui/x-internals@7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@mui/x-internals/-/x-internals-7.23.0.tgz#3b1d0e47f1504cbd74c60b6a514eb18c108cc6dd" + integrity sha512-bPclKpqUiJYIHqmTxSzMVZi6MH51cQsn5U+8jskaTlo3J4QiMeCYJn/gn7YbeR9GOZFp8hetyHjoQoVHKRXCig== + dependencies: + "@babel/runtime" "^7.25.7" + "@mui/utils" "^5.16.6 || ^6.0.0" + "@nestjs/axios@^3.1.2": version "3.1.2" resolved "https://registry.yarnpkg.com/@nestjs/axios/-/axios-3.1.2.tgz#e55c39cfd2e0ed24304b9aa31d1854ecbfe760c7" From a3038c49f505be5c133b341a3dcb3c7f14bfd96f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 09:30:30 +0100 Subject: [PATCH 73/92] chore(deps-dev): bump prettier from 2.8.8 to 3.4.2 (#2922) Bumps [prettier](https://github.com/prettier/prettier) from 2.8.8 to 3.4.2. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.8.8...3.4.2) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- packages/apps/dashboard/server/package.json | 2 +- packages/apps/dashboard/ui-2024/package.json | 2 +- .../fortune/exchange-oracle/server/package.json | 2 +- packages/apps/human-app/frontend/package.json | 2 +- packages/apps/human-app/server/package.json | 2 +- packages/apps/job-launcher/server/package.json | 2 +- .../apps/reputation-oracle/server/package.json | 2 +- yarn.lock | 15 +++++---------- 9 files changed, 13 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index e79139e449..8871815e01 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "lint-staged": "^15.2.7", - "prettier": "^3.2.5", + "prettier": "^3.4.2", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "^5.6.3" diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 1811a71c5c..4a027ca1eb 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -48,7 +48,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "jest": "29.5.0", - "prettier": "^2.3.2", + "prettier": "^3.4.2", "source-map-support": "^0.5.20", "supertest": "^7.0.0", "ts-jest": "29.2.5", diff --git a/packages/apps/dashboard/ui-2024/package.json b/packages/apps/dashboard/ui-2024/package.json index d8f7127848..1a659c616b 100644 --- a/packages/apps/dashboard/ui-2024/package.json +++ b/packages/apps/dashboard/ui-2024/package.json @@ -48,7 +48,7 @@ "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.11", - "prettier": "3.2.5", + "prettier": "3.4.2", "sass": "^1.78.0", "stylelint-prettier": "^5.0.0", "typescript": "^5.2.2", diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index 24f6440a91..15f17a0dc5 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -52,7 +52,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "jest": "29.7.0", - "prettier": "^3.2.5", + "prettier": "^3.4.2", "pg": "8.13.1", "source-map-support": "^0.5.20", "supertest": "^7.0.0", diff --git a/packages/apps/human-app/frontend/package.json b/packages/apps/human-app/frontend/package.json index be9b3456fd..5705e79a12 100644 --- a/packages/apps/human-app/frontend/package.json +++ b/packages/apps/human-app/frontend/package.json @@ -69,7 +69,7 @@ "husky": "^9.1.6", "jsdom": "^25.0.1", "lint-staged": "^15.2.1", - "prettier": "^3.2.5", + "prettier": "^3.4.2", "typescript": "^5.6.3", "vite": "^5.4.7", "vitest": "^1.2.2" diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index b1eec6f47c..da46f64f8a 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -56,7 +56,7 @@ "eslint-plugin-prettier": "^5.2.1", "jest": "29.7.0", "nock": "^13.5.1", - "prettier": "^3.1.1", + "prettier": "^3.4.2", "source-map-support": "^0.5.20", "supertest": "^7.0.0", "ts-jest": "29.2.5", diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index df1fa493cf..030a971ee1 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -80,7 +80,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "jest": "29.7.0", - "prettier": "^3.2.5", + "prettier": "^3.4.2", "source-map-support": "^0.5.20", "supertest": "^7.0.0", "ts-jest": "29.2.5", diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index cdb4cf82ca..06921ce4d2 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -76,7 +76,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "jest": "29.7.0", - "prettier": "^3.2.5", + "prettier": "^3.4.2", "source-map-support": "^0.5.20", "supertest": "^7.0.0", "ts-jest": "29.2.5", diff --git a/yarn.lock b/yarn.lock index 9222405fed..da49f8a956 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16669,21 +16669,16 @@ prettier@3.0.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== -prettier@3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" - integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== +prettier@3.4.2, prettier@^3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f" + integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ== -prettier@^2.3.1, prettier@^2.3.2: +prettier@^2.3.1: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== -prettier@^3.1.1, prettier@^3.2.5: - version "3.4.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.1.tgz#e211d451d6452db0a291672ca9154bc8c2579f7b" - integrity sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg== - pretty-format@^27.0.2: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" From 25f118d5dac1bfed161202fdb75e57e3f641adb1 Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Tue, 17 Dec 2024 11:49:14 +0100 Subject: [PATCH 74/92] fix to use CACHE_TTL_JOB_TYPES in seconds (#2929) --- .../src/common/config/environment-config.service.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/apps/human-app/server/src/common/config/environment-config.service.ts b/packages/apps/human-app/server/src/common/config/environment-config.service.ts index 4a81f4468b..8621f011fa 100644 --- a/packages/apps/human-app/server/src/common/config/environment-config.service.ts +++ b/packages/apps/human-app/server/src/common/config/environment-config.service.ts @@ -223,9 +223,11 @@ export class EnvironmentConfigService { * Default: 24 hours */ get cacheTtlJobTypes(): number { - return this.configService.get( - 'CACHE_TTL_JOB_TYPES', - DEFAULT_CACHE_TTL_JOB_TYPES, + return ( + this.configService.get( + 'CACHE_TTL_JOB_TYPES', + DEFAULT_CACHE_TTL_JOB_TYPES, + ) * 1000 ); } From 4e6fab7b3cd931449c87e193d1ed1f1c36fc9596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:09:38 +0100 Subject: [PATCH 75/92] [Exchange Oracle] Refactor JwtHttpStrategy (#2930) * Refactor JwtHttpStrategy to query RPC instead of Subgraph to reduce the amount of request sent * Move getFileUrlAndVerifyHash out of the constructor --- .../src/common/guards/strategy/jwt.http.ts | 71 +++++++++++++++++-- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts b/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts index 93df8eb70b..5bd6bce9f1 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts @@ -1,13 +1,20 @@ -import { Injectable, Req, UnauthorizedException } from '@nestjs/common'; +import { + BadRequestException, + Injectable, + Req, + UnauthorizedException, +} from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; -import { StorageClient, KVStoreUtils } from '@human-protocol/sdk'; +import { KVStore__factory } from '@human-protocol/core/typechain-types'; +import { ChainId, NETWORKS, StorageClient } from '@human-protocol/sdk'; +import { ethers } from 'ethers'; import * as jwt from 'jsonwebtoken'; -import { JwtUser } from '../../../common/types/jwt'; import { JWT_KVSTORE_KEY, KYC_APPROVED } from '../../../common/constant'; import { Role } from '../../../common/enums/role'; -import { Web3Service } from 'src/modules/web3/web3.service'; +import { JwtUser } from '../../../common/types/jwt'; +import { Web3Service } from '../../../modules/web3/web3.service'; @Injectable() export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') { @@ -23,8 +30,10 @@ export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') { try { const payload = jwt.decode(rawJwtToken); const chainId = this.web3Service.getValidChains()[0]; + const signer = this.web3Service.getSigner(chainId); - const url = await KVStoreUtils.getFileUrlAndVerifyHash( + const url = await this.getFileUrlAndVerifyHash( + signer, chainId, (payload as any).reputation_network, JWT_KVSTORE_KEY, @@ -93,4 +102,56 @@ export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') { qualifications: payload.qualifications, }; } + + private async getFileUrlAndVerifyHash( + signer: ethers.Wallet, + chainId: ChainId, + address: string, + urlKey = 'url', + ): Promise { + if (!ethers.isAddress(address)) { + throw new BadRequestException('Invalid address'); + } + + const hashKey = urlKey + '_hash'; + let url = '', + hash = ''; + + const contract = KVStore__factory.connect( + NETWORKS[chainId]!.kvstoreAddress, + signer, + ); + + try { + url = await contract.get(address, urlKey); + } catch (e) { + if (e instanceof Error) { + throw new Error(`Failed to get URL: ${e.message}`); + } + } + + if (!url?.length) { + return ''; + } + + try { + hash = await contract.get(address, hashKey); + } catch (e) { + if (e instanceof Error) { + throw new Error(`Failed to get Hash: ${e.message}`); + } + } + + const content = await fetch(url).then((res) => res.text()); + const contentHash = ethers.keccak256(ethers.toUtf8Bytes(content)); + + const formattedHash = hash?.replace(/^0x/, ''); + const formattedContentHash = contentHash?.replace(/^0x/, ''); + + if (formattedHash !== formattedContentHash) { + throw new BadRequestException('Invalid hash'); + } + + return url; + } } From 777dd0966339b74e8444c224cec11ee1c1662b85 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Tue, 17 Dec 2024 14:15:59 +0300 Subject: [PATCH 76/92] Bump human sdk to 3.0.8b0 (#2925) --- packages/examples/cvat/exchange-oracle/poetry.lock | 8 ++++---- packages/examples/cvat/exchange-oracle/pyproject.toml | 2 +- packages/examples/cvat/recording-oracle/poetry.lock | 8 ++++---- packages/examples/cvat/recording-oracle/pyproject.toml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/examples/cvat/exchange-oracle/poetry.lock b/packages/examples/cvat/exchange-oracle/poetry.lock index 47fe648f0f..833c968241 100644 --- a/packages/examples/cvat/exchange-oracle/poetry.lock +++ b/packages/examples/cvat/exchange-oracle/poetry.lock @@ -1960,13 +1960,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "human-protocol-sdk" -version = "3.0.7b0" +version = "3.0.8b0" description = "A python library to launch escrow contracts to the HUMAN network." optional = false python-versions = "*" files = [ - {file = "human-protocol-sdk-3.0.7b0.tar.gz", hash = "sha256:bccdc8f2c25f21495a2d938b8020b40e6d2db2e29b9c43931a077895ff5794dc"}, - {file = "human_protocol_sdk-3.0.7b0-py3-none-any.whl", hash = "sha256:3fad4c7f38e3e8d38be53b594e3123e353f9fdf28918f9b0754a37ea7f10c904"}, + {file = "human_protocol_sdk-3.0.8b0-py3-none-any.whl", hash = "sha256:749c28b2a1177c3f31c7edcb040afb6b106f6f5e9b480b0a5db21ecab468e448"}, + {file = "human_protocol_sdk-3.0.8b0.tar.gz", hash = "sha256:cc4500dc4e458594933730d339544f86c0597ea68096c5ff291535e23a5a6088"}, ] [package.dependencies] @@ -4919,4 +4919,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10,<3.13" -content-hash = "590a6c9434302dc1fa402a31364007ad17350b927f68f8a4c65936fcad7cdc22" +content-hash = "49b01380ca146e1c095dafd861b81b11ab34812f483d6db6d2ef010f9f0ba0e0" diff --git a/packages/examples/cvat/exchange-oracle/pyproject.toml b/packages/examples/cvat/exchange-oracle/pyproject.toml index e48e4e1837..042010213b 100644 --- a/packages/examples/cvat/exchange-oracle/pyproject.toml +++ b/packages/examples/cvat/exchange-oracle/pyproject.toml @@ -24,7 +24,7 @@ datumaro = {git = "https://github.com/cvat-ai/datumaro.git", rev = "ff83c00c2c1b boto3 = "^1.28.33" google-cloud-storage = "^2.14.0" pyinstrument = "^4.6.2" -human-protocol-sdk = ">=3.0.7b0,<3.1.0" +human-protocol-sdk = ">=3.0.8b0,<3.1.0" hexbytes = ">=1.2.0" # required for to_0x_hex() function pydantic = ">=2.6.1,<2.7.0" fastapi-pagination = "^0.12.17" diff --git a/packages/examples/cvat/recording-oracle/poetry.lock b/packages/examples/cvat/recording-oracle/poetry.lock index 5d455f4875..41545db4b0 100644 --- a/packages/examples/cvat/recording-oracle/poetry.lock +++ b/packages/examples/cvat/recording-oracle/poetry.lock @@ -1894,13 +1894,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "human-protocol-sdk" -version = "3.0.7b0" +version = "3.0.8b0" description = "A python library to launch escrow contracts to the HUMAN network." optional = false python-versions = "*" files = [ - {file = "human-protocol-sdk-3.0.7b0.tar.gz", hash = "sha256:bccdc8f2c25f21495a2d938b8020b40e6d2db2e29b9c43931a077895ff5794dc"}, - {file = "human_protocol_sdk-3.0.7b0-py3-none-any.whl", hash = "sha256:3fad4c7f38e3e8d38be53b594e3123e353f9fdf28918f9b0754a37ea7f10c904"}, + {file = "human_protocol_sdk-3.0.8b0-py3-none-any.whl", hash = "sha256:749c28b2a1177c3f31c7edcb040afb6b106f6f5e9b480b0a5db21ecab468e448"}, + {file = "human_protocol_sdk-3.0.8b0.tar.gz", hash = "sha256:cc4500dc4e458594933730d339544f86c0597ea68096c5ff291535e23a5a6088"}, ] [package.dependencies] @@ -4708,4 +4708,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10, <3.13" -content-hash = "78655be01ca9c1a86d9b7ca513f92076c8a432ded888d42c119da19a68995b81" +content-hash = "940378d2c17d34e3f34f2b39131f5de343dc660f370daeb4df92c1b8400b2d58" diff --git a/packages/examples/cvat/recording-oracle/pyproject.toml b/packages/examples/cvat/recording-oracle/pyproject.toml index 7ec842536a..cf78ffa49b 100644 --- a/packages/examples/cvat/recording-oracle/pyproject.toml +++ b/packages/examples/cvat/recording-oracle/pyproject.toml @@ -22,7 +22,7 @@ numpy = "^1.25.2" boto3 = "^1.28.40" google-cloud-storage = "^2.14.0" datumaro = {git = "https://github.com/cvat-ai/datumaro.git", rev = "ff83c00c2c1bc4b8fdfcc55067fcab0a9b5b6b11"} -human-protocol-sdk = ">=3.0.7b0,<3.1.0" +human-protocol-sdk = ">=3.0.8b0,<3.1.0" hexbytes = ">=1.2.0" # required for to_0x_hex() function starlette = ">=0.40.0" # avoid the vulnerability with multipart/form-data cvat-sdk = "^2.23.1" From c3d2709018bf588ba21ba910dd78fd74244bdf1a Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Tue, 17 Dec 2024 16:01:06 +0300 Subject: [PATCH 77/92] fix: unhandled errors from updateAssigmentsCache (#2932) --- .../exchange-oracle.gateway.ts | 6 ++-- .../job-assignment/job-assignment.service.ts | 19 ++++++++-- .../spec/job-assignment.service.spec.ts | 36 +++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts b/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts index 300c5797fe..df6e6c38db 100644 --- a/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { AxiosRequestConfig } from 'axios'; import { lastValueFrom } from 'rxjs'; import { @@ -41,6 +41,8 @@ import { @Injectable() export class ExchangeOracleGateway { + logger = new Logger(ExchangeOracleGateway.name); + constructor( private httpService: HttpService, private kvStoreGateway: KvStoreGateway, @@ -54,7 +56,7 @@ export class ExchangeOracleGateway { const response = await lastValueFrom(this.httpService.request(options)); return response.data as T; } catch (e) { - console.error( + this.logger.error( `Error, while executing exchange oracle API call to ${options.url}, error details: ${e.message}`, ); throw e; diff --git a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts index 55dec3b197..42852294e1 100644 --- a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts +++ b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts @@ -1,5 +1,5 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { Inject, Injectable } from '@nestjs/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import { Cache } from 'cache-manager'; import { decode } from 'jsonwebtoken'; import { EscrowUtilsGateway } from '../../integrations/escrow/escrow-utils-gateway.service'; @@ -19,6 +19,8 @@ import { JOB_ASSIGNMENT_CACHE_KEY } from '../../common/constants/cache'; @Injectable() export class JobAssignmentService { + logger = new Logger(JobAssignmentService.name); + constructor( private readonly configService: EnvironmentConfigService, private readonly exchangeOracleGateway: ExchangeOracleGateway, @@ -50,6 +52,7 @@ export class JobAssignmentService { ): Promise { const response = await this.exchangeOracleGateway.postNewJobAssignment(command); + const assignmentsParamsCommand = new JobsFetchParamsCommand(); assignmentsParamsCommand.oracleAddress = await this.escrowUtilsGateway.getExchangeOracleAddressByEscrowAddress( @@ -58,7 +61,12 @@ export class JobAssignmentService { ); assignmentsParamsCommand.token = command.token; - this.updateAssignmentsCache(assignmentsParamsCommand); + this.updateAssignmentsCache(assignmentsParamsCommand).catch((error) => { + this.logger.error( + `Failed to update assignments cache after processing assignment: ${error.message}`, + error.stack, + ); + }); return response; } @@ -71,7 +79,12 @@ export class JobAssignmentService { assignmentsParamsCommand.oracleAddress = command.oracleAddress; assignmentsParamsCommand.token = command.token; - await this.updateAssignmentsCache(assignmentsParamsCommand); + this.updateAssignmentsCache(assignmentsParamsCommand).catch((error) => { + this.logger.error( + `Failed to update assignments cache after processing resignment: ${error.message}`, + error.stack, + ); + }); return response; } diff --git a/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.service.spec.ts b/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.service.spec.ts index b8530186b9..875e2e6887 100644 --- a/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.service.spec.ts +++ b/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.service.spec.ts @@ -87,6 +87,25 @@ describe('JobAssignmentService', () => { ).toHaveBeenCalledWith(command); expect(result).toEqual({ assignment_id: '123' }); }); + + it('handles errors when updating cached assignments', async () => { + const mockResult = { + assignment_id: '123', + }; + + const command = jobAssignmentCommandFixture; + ( + exchangeOracleGatewayMock.postNewJobAssignment as jest.Mock + ).mockResolvedValue(mockResult); + + ( + exchangeOracleGatewayMock.fetchAssignedJobs as jest.Mock + ).mockRejectedValueOnce(new Error('Unhandled error')); + + const result = await service.processJobAssignment(command); + + expect(result).toEqual(mockResult); + }); }); describe('processGetAssignedJobs', () => { @@ -226,5 +245,22 @@ describe('JobAssignmentService', () => { command, ); }); + + it('handles errors when updating cached assignments', async () => { + const command = new ResignJobCommand(); + + const mockResult = { success: true }; + ( + exchangeOracleGatewayMock.resignAssignedJob as jest.Mock + ).mockResolvedValue(mockResult); + + ( + exchangeOracleGatewayMock.fetchAssignedJobs as jest.Mock + ).mockRejectedValueOnce(new Error('Unhandled error')); + + const result = await service.resignJob(command); + + expect(result).toEqual(mockResult); + }); }); }); From 794b9a2817b5768eef8e8d4d69f9bc3adeaaff53 Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Tue, 17 Dec 2024 14:54:17 +0100 Subject: [PATCH 78/92] [Dashboard] feat: remove tabs implementation from charts page (#2926) --- .../ui-2024/src/pages/Graph/Graph.tsx | 43 +------------------ 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx b/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx index acd739e787..0441976ec4 100644 --- a/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx +++ b/packages/apps/dashboard/ui-2024/src/pages/Graph/Graph.tsx @@ -1,21 +1,10 @@ import { AreaChart } from '@components/Charts'; -import Tabs from '@mui/material/Tabs'; -import TabPanel from '@mui/lab/TabPanel'; -import Tab from '@mui/material/Tab'; -import { useEffect, useState } from 'react'; -import TabContext from '@mui/lab/TabContext'; -import Typography from '@mui/material/Typography'; +import { useEffect } from 'react'; import PageWrapper from '@components/PageWrapper'; import Breadcrumbs from '@components/Breadcrumbs'; import { useGraphPageChartParams } from '@utils/hooks/use-graph-page-chart-params'; -type graphType = 'bucketed'; - const Graph = () => { - const [graphType, setGraphType] = useState('bucketed'); - const handleGraphTypeChange = (_: unknown, newValue: graphType) => { - setGraphType(newValue); - }; const { revertToInitialParams } = useGraphPageChartParams(); useEffect(() => { @@ -26,35 +15,7 @@ const Graph = () => { return ( - - - - Bucketed - - } - value="bucketed" - /> - - - - - + ); }; From 396c69fb68c0313507238926e7fc0b0b11ce875b Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Tue, 17 Dec 2024 17:05:23 +0300 Subject: [PATCH 79/92] [Job Launcher] fix: get rid of job types mapping in job creation (#2907) --- .../server/src/common/utils/index.ts | 18 --------------- .../src/modules/job/job.service.spec.ts | 4 +--- .../server/src/modules/job/job.service.ts | 23 +++++++++++-------- .../job/routing-protocol.service.spec.ts | 17 ++++++-------- .../modules/job/routing-protocol.service.ts | 5 ++-- 5 files changed, 25 insertions(+), 42 deletions(-) diff --git a/packages/apps/job-launcher/server/src/common/utils/index.ts b/packages/apps/job-launcher/server/src/common/utils/index.ts index 6d6f617d90..a8cf2bbd7d 100644 --- a/packages/apps/job-launcher/server/src/common/utils/index.ts +++ b/packages/apps/job-launcher/server/src/common/utils/index.ts @@ -2,7 +2,6 @@ import { HttpStatus } from '@nestjs/common'; import * as crypto from 'crypto'; import { Readable } from 'stream'; import { ControlledError } from '../errors/controlled'; -import { JobRequestType } from '../enums/job'; export const parseUrl = ( url: string, @@ -116,20 +115,3 @@ export function isPGPMessage(str: string): boolean { /-----BEGIN PGP MESSAGE-----\n\n[\s\S]+?\n-----END PGP MESSAGE-----/; return pattern.test(str); } - -export const mapJobType = (requestType: JobRequestType): string => { - switch (requestType) { - case JobRequestType.IMAGE_POINTS: - return 'Points'; - case JobRequestType.IMAGE_POLYGONS: - return 'Polygons'; - case JobRequestType.IMAGE_BOXES: - return 'Bounding Boxes'; - case JobRequestType.IMAGE_BOXES_FROM_POINTS: - return 'Bounding Boxes from Points'; - case JobRequestType.IMAGE_SKELETONS_FROM_BOXES: - return 'Skeletons from Bounding Boxes'; - default: - return 'Fortune'; - } -}; diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts index a292dc6662..ec21124117 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts @@ -119,7 +119,6 @@ import { QualificationService } from '../qualification/qualification.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; const rate = 1.5; -const mappedJobType = 'mappedType'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), EscrowClient: { @@ -154,7 +153,6 @@ jest.mock('../../common/utils', () => ({ bucket: MOCK_BUCKET_NAME, }; }), - mapJobType: jest.fn().mockImplementation(() => 'mappedType'), })); jest.mock('../../common/utils/storage', () => ({ @@ -344,7 +342,7 @@ describe('JobService', () => { expect(routingProtocolService.validateOracles).toHaveBeenCalledWith( MOCK_CHAIN_ID, - mappedJobType, + JobRequestType.FORTUNE, providedReputationOracle, providedExchangeOracle, providedRecordingOracle, diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.ts index 70968b7f37..893dabe426 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.ts @@ -46,7 +46,7 @@ import { PaymentType, TokenId, } from '../../common/enums/payment'; -import { mapJobType, parseUrl } from '../../common/utils'; +import { parseUrl } from '../../common/utils'; import { add, div, lt, mul, max } from '../../common/utils/decimal'; import { PaymentRepository } from '../payment/payment.repository'; import { PaymentService } from '../payment/payment.service'; @@ -773,11 +773,16 @@ export class JobService { public async createJob( userId: number, - requestType: JobRequestType, + jobRequestType: JobRequestType, dto: CreateJob, ): Promise { let { chainId, reputationOracle, exchangeOracle, recordingOracle } = dto; - const mappedJobType = mapJobType(requestType); + if (!Object.values(JobRequestType).includes(jobRequestType)) { + throw new ControlledError( + ErrorJob.InvalidRequestType, + HttpStatus.BAD_REQUEST, + ); + } // Select network chainId = chainId || this.routingProtocolService.selectNetwork(); @@ -787,7 +792,7 @@ export class JobService { if (!reputationOracle || !exchangeOracle || !recordingOracle) { const selectedOracles = await this.routingProtocolService.selectOracles( chainId, - mappedJobType, + jobRequestType, ); exchangeOracle = exchangeOracle || selectedOracles.exchangeOracle; @@ -797,7 +802,7 @@ export class JobService { // Validate if all oracles are provided await this.routingProtocolService.validateOracles( chainId, - mappedJobType, + jobRequestType, reputationOracle, exchangeOracle, recordingOracle, @@ -824,7 +829,7 @@ export class JobService { const rate = await this.rateService.getRate(Currency.USD, TokenId.HMT); const { calculateFundAmount, createManifest } = - this.createJobSpecificActions[requestType]; + this.createJobSpecificActions[jobRequestType]; const userBalance = await this.paymentService.getUserBalance( userId, @@ -896,12 +901,12 @@ export class JobService { } else { const manifestOrigin = await createManifest( dto, - requestType, + jobRequestType, tokenFundAmount, ); const { url, hash } = await this.uploadManifest( - requestType, + jobRequestType, chainId, manifestOrigin, ); @@ -915,7 +920,7 @@ export class JobService { jobEntity.exchangeOracle = exchangeOracle; jobEntity.recordingOracle = recordingOracle; jobEntity.userId = userId; - jobEntity.requestType = requestType; + jobEntity.requestType = jobRequestType; jobEntity.fee = tokenFee; jobEntity.fundAmount = tokenFundAmount; jobEntity.status = JobStatus.PENDING; diff --git a/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts index 30983783e0..50fe915b0e 100644 --- a/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.spec.ts @@ -8,6 +8,7 @@ import { NetworkConfigService } from '../../common/config/network-config.service import { Web3Service } from '../web3/web3.service'; import { ConfigService } from '@nestjs/config'; import { ControlledError } from '../../common/errors/controlled'; +import { JobRequestType } from '../../common/enums/job'; import { ErrorRoutingProtocol } from '../../common/constants/errors'; import { HttpStatus } from '@nestjs/common'; import { hashString } from '../../common/utils'; @@ -353,7 +354,7 @@ describe('RoutingProtocolService', () => { const result = await routingProtocolService.selectOracles( ChainId.POLYGON_AMOY, - 'jobType', + JobRequestType.FORTUNE, ); expect(result.reputationOracle).toBeDefined(); expect(result.exchangeOracle).toBe('0xExchangeOracle1'); @@ -365,7 +366,7 @@ describe('RoutingProtocolService', () => { const result = await routingProtocolService.selectOracles( ChainId.POLYGON_AMOY, - 'jobType', + JobRequestType.FORTUNE, ); expect(result.exchangeOracle).toBe(''); expect(result.recordingOracle).toBe(''); @@ -375,7 +376,6 @@ describe('RoutingProtocolService', () => { describe('validateOracles', () => { it('should validate oracles successfully', async () => { const chainId = ChainId.POLYGON_AMOY; - const jobType = 'someJobType'; const reputationOracle = '0xReputationOracle'; const exchangeOracle = '0xExchangeOracle'; const recordingOracle = '0xRecordingOracle'; @@ -395,7 +395,7 @@ describe('RoutingProtocolService', () => { await expect( routingProtocolService.validateOracles( chainId, - jobType, + JobRequestType.FORTUNE, reputationOracle, exchangeOracle, recordingOracle, @@ -405,7 +405,6 @@ describe('RoutingProtocolService', () => { it('should throw error if reputation oracle not found', async () => { const chainId = ChainId.POLYGON_AMOY; - const jobType = 'someJobType'; const invalidReputationOracle = 'invalidOracle'; jest @@ -419,7 +418,7 @@ describe('RoutingProtocolService', () => { await expect( routingProtocolService.validateOracles( chainId, - jobType, + JobRequestType.FORTUNE, invalidReputationOracle, ), ).rejects.toThrow( @@ -432,7 +431,6 @@ describe('RoutingProtocolService', () => { it('should throw error if exchange oracle not found', async () => { const chainId = ChainId.POLYGON_AMOY; - const jobType = 'someJobType'; const reputationOracle = '0xReputationOracle'; jest @@ -451,7 +449,7 @@ describe('RoutingProtocolService', () => { await expect( routingProtocolService.validateOracles( chainId, - jobType, + JobRequestType.FORTUNE, reputationOracle, 'invalidExchangeOracle', ), @@ -465,7 +463,6 @@ describe('RoutingProtocolService', () => { it('should throw error if recording oracle not found', async () => { const chainId = ChainId.POLYGON_AMOY; - const jobType = 'someJobType'; const reputationOracle = '0xReputationOracle'; jest @@ -484,7 +481,7 @@ describe('RoutingProtocolService', () => { await expect( routingProtocolService.validateOracles( chainId, - jobType, + JobRequestType.FORTUNE, reputationOracle, undefined, 'invalidRecordingOracle', diff --git a/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.ts b/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.ts index 336eff9937..ec605f12b3 100644 --- a/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/routing-protocol.service.ts @@ -4,6 +4,7 @@ import { Web3Service } from '../web3/web3.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { hashString } from '../../common/utils'; import { ErrorRoutingProtocol } from '../../common/constants/errors'; +import { JobRequestType } from '../../common/enums/job'; import { ControlledError } from '../../common/errors/controlled'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { @@ -148,7 +149,7 @@ export class RoutingProtocolService { public async selectOracles( chainId: ChainId, - jobType: string, + jobType: JobRequestType, ): Promise<{ reputationOracle: string; exchangeOracle: string; @@ -181,7 +182,7 @@ export class RoutingProtocolService { public async validateOracles( chainId: ChainId, - jobType: string, + jobType: JobRequestType, reputationOracle: string, exchangeOracle?: string | null, recordingOracle?: string | null, From 513461fb468f7dc325a665fbf81871039ff2a7a9 Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:20:48 +0300 Subject: [PATCH 80/92] [Dashboard] Implemented Network module with get operating networks logic (#2874) --- packages/apps/dashboard/server/.env.example | 5 +- packages/apps/dashboard/server/.gitignore | 3 +- packages/apps/dashboard/server/package.json | 3 +- .../apps/dashboard/server/src/app.module.ts | 3 + .../src/common/config/env-config.service.ts | 8 +- .../common/config/network-config.service.ts | 88 +------------------ .../src/common/config/redis-config.service.ts | 2 +- .../config/test-environment-config.service.ts | 20 +++++ .../src/modules/details/details.module.ts | 3 +- .../src/modules/details/details.service.ts | 4 +- .../networks/network.service.spec.ts} | 43 ++++----- .../modules/networks/networks.controller.ts | 32 +++++++ .../src/modules/networks/networks.module.ts | 13 +++ .../src/modules/networks/networks.service.ts | 83 +++++++++++++++++ .../src/modules/stats/stats.controller.ts | 22 +---- .../server/src/modules/stats/stats.module.ts | 3 +- .../server/src/modules/stats/stats.service.ts | 13 ++- .../dashboard/server/test/app.e2e-spec.ts | 68 ++++++++++++++ .../apps/dashboard/server/test/jest-e2e.json | 12 +++ 19 files changed, 284 insertions(+), 144 deletions(-) create mode 100644 packages/apps/dashboard/server/src/common/config/test-environment-config.service.ts rename packages/apps/dashboard/server/src/{common/config/network-config.service.spec.ts => modules/networks/network.service.spec.ts} (84%) create mode 100644 packages/apps/dashboard/server/src/modules/networks/networks.controller.ts create mode 100644 packages/apps/dashboard/server/src/modules/networks/networks.module.ts create mode 100644 packages/apps/dashboard/server/src/modules/networks/networks.service.ts create mode 100644 packages/apps/dashboard/server/test/app.e2e-spec.ts create mode 100644 packages/apps/dashboard/server/test/jest-e2e.json diff --git a/packages/apps/dashboard/server/.env.example b/packages/apps/dashboard/server/.env.example index 053bef6647..d8532b39e4 100644 --- a/packages/apps/dashboard/server/.env.example +++ b/packages/apps/dashboard/server/.env.example @@ -13,7 +13,7 @@ HMT_PRICE_TO= HCAPTCHA_API_KEY= HCAPTCHA_STATS_ENABLED= NETWORK_USAGE_FILTER_MONTHS= -NETWORKS_AVAILABLE_CACHE_TTL= +NETWORKS_OPERATING_CACHE_TTL= # Redis REDIS_HOST=localhost @@ -34,3 +34,6 @@ S3_BUCKET= #Web3 WEB3_ENV= RPC_URL_POLYGON= + +# e2e testing +E2E_TESTING_EMAIL_ADDRESS= diff --git a/packages/apps/dashboard/server/.gitignore b/packages/apps/dashboard/server/.gitignore index 6a917ab004..f31e4e1788 100644 --- a/packages/apps/dashboard/server/.gitignore +++ b/packages/apps/dashboard/server/.gitignore @@ -38,4 +38,5 @@ lerna-debug.log* /redis_data .env.development -.env.production \ No newline at end of file +.env.production +.env.test \ No newline at end of file diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 4a027ca1eb..0309e77817 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -16,7 +16,8 @@ "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand" + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { "@human-protocol/sdk": "*", diff --git a/packages/apps/dashboard/server/src/app.module.ts b/packages/apps/dashboard/server/src/app.module.ts index 32a3f3a478..2017d3cf92 100644 --- a/packages/apps/dashboard/server/src/app.module.ts +++ b/packages/apps/dashboard/server/src/app.module.ts @@ -10,6 +10,7 @@ import { CacheFactoryConfig } from './common/config/cache-factory.config'; import { CommonConfigModule } from './common/config/config.module'; import { DetailsModule } from './modules/details/details.module'; import { StatsModule } from './modules/stats/stats.module'; +import { NetworksModule } from './modules/networks/networks.module'; @Module({ imports: [ @@ -28,6 +29,7 @@ import { StatsModule } from './modules/stats/stats.module'; CACHE_HMT_PRICE_TTL: Joi.number(), CACHE_HMT_GENERAL_STATS_TTL: Joi.number(), HCAPTCHA_STATS_ENABLED: Joi.boolean().default(true), + NETWORKS_OPERATING_CACHE_TTL: Joi.number(), }), }), CacheModule.registerAsync(CacheFactoryConfig), @@ -35,6 +37,7 @@ import { StatsModule } from './modules/stats/stats.module'; DetailsModule, ScheduleModule.forRoot(), StatsModule, + NetworksModule, ], controllers: [AppController], }) diff --git a/packages/apps/dashboard/server/src/common/config/env-config.service.ts b/packages/apps/dashboard/server/src/common/config/env-config.service.ts index 3032ec230a..24bcf0af71 100644 --- a/packages/apps/dashboard/server/src/common/config/env-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/env-config.service.ts @@ -17,7 +17,7 @@ export const DEFAULT_HCAPTCHA_STATS_ENABLED = true; export const HMT_STATS_START_DATE = '2021-04-06'; export const MINIMUM_HMT_TRANSFERS = 5; export const DEFAULT_NETWORK_USAGE_FILTER_MONTHS = 1; -export const DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL = 60 * 60; +export const DEFAULT_NETWORKS_OPERATING_CACHE_TTL = 2 * 60; export const MINIMUM_ESCROWS_COUNT = 1; @Injectable() @@ -102,11 +102,11 @@ export class EnvironmentConfigService { ); } - get networkAvailableCacheTtl(): number { + get networkOperatingCacheTtl(): number { return ( this.configService.get( - 'NETWORKS_AVAILABLE_CACHE_TTL', - DEFAULT_NETWORKS_AVAILABLE_CACHE_TTL, + 'NETWORKS_OPERATING_CACHE_TTL', + DEFAULT_NETWORKS_OPERATING_CACHE_TTL, ) * 1000 ); } diff --git a/packages/apps/dashboard/server/src/common/config/network-config.service.ts b/packages/apps/dashboard/server/src/common/config/network-config.service.ts index 07e13c5f57..6437fbacdd 100644 --- a/packages/apps/dashboard/server/src/common/config/network-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/network-config.service.ts @@ -1,14 +1,7 @@ -import { ChainId, NETWORKS, StatisticsClient } from '@human-protocol/sdk'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { ChainId } from '@human-protocol/sdk'; +import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Web3Env } from '../enums/web3'; -import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager'; -import { AVAILABLE_NETWORKS_CACHE_KEY } from './redis-config.service'; -import { - EnvironmentConfigService, - MINIMUM_ESCROWS_COUNT, - MINIMUM_HMT_TRANSFERS, -} from './env-config.service'; import { LOCALHOST_CHAIN_IDS, MAINNET_CHAIN_IDS, @@ -30,13 +23,8 @@ interface NetworkMapDto { @Injectable() export class NetworkConfigService { private readonly networkMap: NetworkMapDto; - private readonly logger = new Logger(NetworkConfigService.name); - constructor( - @Inject(CACHE_MANAGER) private cacheManager: Cache, - private readonly envConfigService: EnvironmentConfigService, - private configService: ConfigService, - ) { + constructor(private configService: ConfigService) { this.networkMap = { ...(this.configService.get('RPC_URL_ETHEREUM') && { ethereum: { @@ -127,74 +115,4 @@ export class NetworkConfigService { get networks(): NetworkDto[] { return Object.values(this.networkMap).map((network) => network); } - - public async getAvailableNetworks(): Promise { - const cachedNetworks = await this.cacheManager.get( - AVAILABLE_NETWORKS_CACHE_KEY, - ); - - if (cachedNetworks) { - return cachedNetworks; - } - - const currentMonth = new Date(); - const oneMonthAgo = new Date(currentMonth); - oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); - - const filterDate = new Date(currentMonth); - filterDate.setMonth( - filterDate.getMonth() - this.envConfigService.networkUsageFilterMonths, - ); - - const availableNetworks = []; - - for (const network of Object.values(this.networks)) { - const chainId = network.chainId; - - const networkConfig = NETWORKS[chainId]; - - if (!networkConfig) { - continue; - } - - const statisticsClient = new StatisticsClient(networkConfig); - - try { - const hmtData = await statisticsClient.getHMTDailyData({ - from: new Date(Math.floor(filterDate.getTime() / 1000) * 1000), - }); - const escrowStats = await statisticsClient.getEscrowStatistics({ - from: new Date(Math.floor(oneMonthAgo.getTime() / 1000) * 1000), - }); - - // Calculate total HMT transaction count across the period - const totalTransactionCount = hmtData.reduce( - (sum, day) => sum + day.totalTransactionCount, - 0, - ); - - // At least 1 escrow created in the last month - const recentEscrowsCreated = - escrowStats.totalEscrows >= MINIMUM_ESCROWS_COUNT; - // Total HMT transactions > MINIMUM_HMT_TRANSFERS in the last X months - const sufficientHMTTransfers = - totalTransactionCount > MINIMUM_HMT_TRANSFERS; - - if (recentEscrowsCreated && sufficientHMTTransfers) { - availableNetworks.push(chainId); - } - } catch (error) { - this.logger.error( - `Error processing network Chain ID: ${chainId}): ${error.message}`, - ); - } - } - - await this.cacheManager.set( - AVAILABLE_NETWORKS_CACHE_KEY, - availableNetworks, - this.envConfigService.networkAvailableCacheTtl, - ); - return availableNetworks; - } } diff --git a/packages/apps/dashboard/server/src/common/config/redis-config.service.ts b/packages/apps/dashboard/server/src/common/config/redis-config.service.ts index 09b15ff2b7..be75022da2 100644 --- a/packages/apps/dashboard/server/src/common/config/redis-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/redis-config.service.ts @@ -7,7 +7,7 @@ const DEFAULT_CACHE_HMT_PRICE_TTL = 60; const DEFAULT_CACHE_HMT_GENERAL_STATS_TTL = 2 * 60; const DEFAULT_HMT_PRICE_CACHE_KEY = 'hmt-price'; const DEFAULT_HMT_GENERAL_STATS_CACHE_KEY = 'hmt-general'; -export const AVAILABLE_NETWORKS_CACHE_KEY = 'available-networks'; +export const OPERATING_NETWORKS_CACHE_KEY = 'operating-networks'; export const HCAPTCHA_PREFIX = 'hcaptcha-'; export const HMT_PREFIX = 'hmt-'; diff --git a/packages/apps/dashboard/server/src/common/config/test-environment-config.service.ts b/packages/apps/dashboard/server/src/common/config/test-environment-config.service.ts new file mode 100644 index 0000000000..fbcd16506f --- /dev/null +++ b/packages/apps/dashboard/server/src/common/config/test-environment-config.service.ts @@ -0,0 +1,20 @@ +import Joi from 'joi'; +import { ConfigService } from '@nestjs/config'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class TestEnvironmentConfigService { + constructor(private configService: ConfigService) {} + + /** + * The email address used for end-to-end (E2E) testing. + * Default: empty string + */ + get e2eTestingEmailAddress(): string { + return this.configService.get('E2E_TESTING_EMAIL_ADDRESS', ''); + } +} + +export const testEnvValidator = Joi.object({ + E2E_TESTING_EMAIL_ADDRESS: Joi.string().required(), +}); diff --git a/packages/apps/dashboard/server/src/modules/details/details.module.ts b/packages/apps/dashboard/server/src/modules/details/details.module.ts index bd78792e09..9edd0f2dad 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.module.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.module.ts @@ -3,9 +3,10 @@ import { Module } from '@nestjs/common'; import { DetailsService } from './details.service'; import { DetailsController } from './details.controller'; import { HttpModule } from '@nestjs/axios'; +import { NetworksModule } from '../networks/networks.module'; @Module({ - imports: [HttpModule], + imports: [HttpModule, NetworksModule], controllers: [DetailsController], providers: [DetailsService], }) diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index b69b7de1ec..e4f1e6d8ab 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -21,6 +21,7 @@ import { firstValueFrom } from 'rxjs'; import { HMToken__factory } from '@human-protocol/core/typechain-types'; import { ethers } from 'ethers'; import { NetworkConfigService } from '../../common/config/network-config.service'; +import { NetworksService } from '../networks/networks.service'; import { OracleRole } from '../../common/enums/roles'; @Injectable() @@ -29,6 +30,7 @@ export class DetailsService { constructor( private readonly configService: EnvironmentConfigService, private readonly httpService: HttpService, + private readonly networksService: NetworksService, private readonly networkConfig: NetworkConfigService, ) {} @@ -152,7 +154,7 @@ export class DetailsService { take?: number, ): Promise { const chainIds = !chainId - ? await this.networkConfig.getAvailableNetworks() + ? await this.networksService.getOperatingNetworks() : [chainId]; let allLeadersData: ILeader[] = []; diff --git a/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts b/packages/apps/dashboard/server/src/modules/networks/network.service.spec.ts similarity index 84% rename from packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts rename to packages/apps/dashboard/server/src/modules/networks/network.service.spec.ts index 44ba5f464d..5b8e5430f0 100644 --- a/packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts +++ b/packages/apps/dashboard/server/src/modules/networks/network.service.spec.ts @@ -7,16 +7,16 @@ import { StatisticsClient } from '@human-protocol/sdk'; import { EnvironmentConfigService } from '../../common/config/env-config.service'; import { ChainId, NETWORKS } from '@human-protocol/sdk'; import { HttpService } from '@nestjs/axios'; -import { NetworkConfigService } from './network-config.service'; import { ConfigService } from '@nestjs/config'; +import { NetworksService } from './networks.service'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), StatisticsClient: jest.fn(), })); -describe('NetworkConfigService', () => { - let networkConfigService: NetworkConfigService; +describe('NetworksService', () => { + let networksService: NetworksService; let cacheManager: Cache; beforeAll(async () => { @@ -28,7 +28,7 @@ describe('NetworkConfigService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ - NetworkConfigService, + NetworksService, { provide: HttpService, useValue: createMock() }, { provide: CACHE_MANAGER, @@ -41,7 +41,7 @@ describe('NetworkConfigService', () => { provide: EnvironmentConfigService, useValue: { networkUsageFilterMonths: 3, - networkAvailableCacheTtl: 1000, + networkOperatingCacheTtl: 1000, }, }, ConfigService, @@ -49,13 +49,16 @@ describe('NetworkConfigService', () => { ], }).compile(); - networkConfigService = - module.get(NetworkConfigService); + networksService = module.get(NetworksService); cacheManager = module.get(CACHE_MANAGER); }); it('should regenerate network list when cache TTL expires', async () => { - const mockNetworkList = [ChainId.MAINNET, ChainId.POLYGON]; + const mockNetworkList = [ + ChainId.MAINNET, + ChainId.BSC_MAINNET, + ChainId.POLYGON, + ]; // Step 1: Initial request - populate cache jest.spyOn(cacheManager, 'get').mockResolvedValue(null); @@ -72,11 +75,11 @@ describe('NetworkConfigService', () => { ); // First call should populate cache - const firstCallResult = await networkConfigService.getAvailableNetworks(); + const firstCallResult = await networksService.getOperatingNetworks(); expect(firstCallResult).toEqual(mockNetworkList); expect(cacheManager.set).toHaveBeenCalledWith( - 'available-networks', + 'operating-networks', mockNetworkList, 1000, ); @@ -85,12 +88,12 @@ describe('NetworkConfigService', () => { jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(null); // Second call after TTL should re-generate the network list - const secondCallResult = await networkConfigService.getAvailableNetworks(); + const secondCallResult = await networksService.getOperatingNetworks(); expect(secondCallResult).toEqual(mockNetworkList); // Ensure the cache is set again with the regenerated network list expect(cacheManager.set).toHaveBeenCalledWith( - 'available-networks', + 'operating-networks', mockNetworkList, 1000, ); @@ -100,9 +103,9 @@ describe('NetworkConfigService', () => { const cachedNetworks = [ChainId.MAINNET, ChainId.POLYGON]; jest.spyOn(cacheManager, 'get').mockResolvedValue(cachedNetworks); - const result = await networkConfigService.getAvailableNetworks(); + const result = await networksService.getOperatingNetworks(); expect(result).toEqual(cachedNetworks); - expect(cacheManager.get).toHaveBeenCalledWith('available-networks'); + expect(cacheManager.get).toHaveBeenCalledWith('operating-networks'); }); it('should fetch and filter available networks correctly', async () => { @@ -120,13 +123,13 @@ describe('NetworkConfigService', () => { () => mockStatisticsClient, ); - const result = await networkConfigService.getAvailableNetworks(); + const result = await networksService.getOperatingNetworks(); expect(result).toEqual( expect.arrayContaining([ChainId.MAINNET, ChainId.POLYGON]), ); expect(cacheManager.set).toHaveBeenCalledWith( - 'available-networks', + 'operating-networks', result, 1000, ); @@ -144,7 +147,7 @@ describe('NetworkConfigService', () => { () => mockStatisticsClient, ); - const result = await networkConfigService.getAvailableNetworks(); + const result = await networksService.getOperatingNetworks(); expect(result).toEqual([]); }); @@ -167,7 +170,7 @@ describe('NetworkConfigService', () => { () => mockStatisticsClient, ); - const result = await networkConfigService.getAvailableNetworks(); + const result = await networksService.getOperatingNetworks(); expect(result).not.toContain(ChainId.MAINNET); expect(result).toEqual(expect.arrayContaining([])); @@ -187,7 +190,7 @@ describe('NetworkConfigService', () => { () => mockStatisticsClient, ); - const result = await networkConfigService.getAvailableNetworks(); + const result = await networksService.getOperatingNetworks(); expect(result).toEqual([]); }); @@ -208,7 +211,7 @@ describe('NetworkConfigService', () => { () => mockStatisticsClient, ); - const result = await networkConfigService.getAvailableNetworks(); + const result = await networksService.getOperatingNetworks(); expect(result).toEqual([]); }); }); diff --git a/packages/apps/dashboard/server/src/modules/networks/networks.controller.ts b/packages/apps/dashboard/server/src/modules/networks/networks.controller.ts new file mode 100644 index 0000000000..b0802edb7d --- /dev/null +++ b/packages/apps/dashboard/server/src/modules/networks/networks.controller.ts @@ -0,0 +1,32 @@ +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { + Controller, + Get, + HttpCode, + UsePipes, + ValidationPipe, +} from '@nestjs/common'; +import { NetworksService } from './networks.service'; +import { ChainId } from '@human-protocol/sdk'; + +@ApiTags('Networks') +@Controller('/networks') +@UsePipes(new ValidationPipe({ transform: true })) +export class NetworksController { + constructor(private readonly networksService: NetworksService) {} + + @Get('/operating') + @HttpCode(200) + @ApiOperation({ + summary: 'Get recently used networks', + description: 'Endpoint to return networks filtered by recent activity.', + }) + @ApiResponse({ + status: 200, + description: 'Networks retrieved successfully', + type: Array, + }) + public async getOperatingNetworks(): Promise { + return this.networksService.getOperatingNetworks(); + } +} diff --git a/packages/apps/dashboard/server/src/modules/networks/networks.module.ts b/packages/apps/dashboard/server/src/modules/networks/networks.module.ts new file mode 100644 index 0000000000..a530329da6 --- /dev/null +++ b/packages/apps/dashboard/server/src/modules/networks/networks.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; + +import { NetworksService } from './networks.service'; +import { NetworksController } from './networks.controller'; +import { HttpModule } from '@nestjs/axios'; + +@Module({ + imports: [HttpModule], + controllers: [NetworksController], + providers: [NetworksService], + exports: [NetworksService], +}) +export class NetworksModule {} diff --git a/packages/apps/dashboard/server/src/modules/networks/networks.service.ts b/packages/apps/dashboard/server/src/modules/networks/networks.service.ts new file mode 100644 index 0000000000..6b5b9cb6d5 --- /dev/null +++ b/packages/apps/dashboard/server/src/modules/networks/networks.service.ts @@ -0,0 +1,83 @@ +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { ChainId, NETWORKS, StatisticsClient } from '@human-protocol/sdk'; +import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager'; + +import { + EnvironmentConfigService, + MINIMUM_ESCROWS_COUNT, + MINIMUM_HMT_TRANSFERS, +} from '../../common/config/env-config.service'; +import { OPERATING_NETWORKS_CACHE_KEY } from '../../common/config/redis-config.service'; +import { MAINNET_CHAIN_IDS } from '../../common/utils/constants'; + +@Injectable() +export class NetworksService { + private readonly logger = new Logger(NetworksService.name); + constructor( + @Inject(CACHE_MANAGER) private cacheManager: Cache, + private readonly envConfigService: EnvironmentConfigService, + ) {} + + public async getOperatingNetworks(): Promise { + const cachedNetworks = await this.cacheManager.get( + OPERATING_NETWORKS_CACHE_KEY, + ); + + if (cachedNetworks) { + return cachedNetworks; + } + + const currentMonth = new Date(); + const oneMonthAgo = new Date(currentMonth); + oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); + + const filterDate = new Date(currentMonth); + filterDate.setMonth( + filterDate.getMonth() - this.envConfigService.networkUsageFilterMonths, + ); + + const availableNetworks = []; + + for (const chainId of Object.values(MAINNET_CHAIN_IDS)) { + const networkConfig = NETWORKS[chainId]; + if (!networkConfig) continue; + + const statisticsClient = new StatisticsClient(networkConfig); + try { + const [hmtData, escrowStats] = await Promise.all([ + statisticsClient.getHMTDailyData({ + from: new Date(Math.floor(filterDate.getTime() / 1000) * 1000), + }), + statisticsClient.getEscrowStatistics({ + from: new Date(Math.floor(oneMonthAgo.getTime() / 1000) * 1000), + }), + ]); + + const totalTransactionCount = hmtData.reduce( + (sum, day) => sum + day.totalTransactionCount, + 0, + ); + + const recentEscrowsCreated = + escrowStats.totalEscrows >= MINIMUM_ESCROWS_COUNT; + const sufficientHMTTransfers = + totalTransactionCount > MINIMUM_HMT_TRANSFERS; + + if (recentEscrowsCreated && sufficientHMTTransfers) { + availableNetworks.push(chainId); + } + } catch (error) { + this.logger.error( + `Error processing network ${chainId}: ${error.message}`, + ); + } + } + + await this.cacheManager.set( + OPERATING_NETWORKS_CACHE_KEY, + availableNetworks, + this.envConfigService.networkOperatingCacheTtl, + ); + return availableNetworks; + } +} diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts b/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts index 62625544f5..22fafe4c88 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.controller.ts @@ -10,16 +10,11 @@ import { import { HmtDailyStatsResponseDto } from './dto/hmt.dto'; import { DateValidationPipe } from '../../common/pipes/date-validation.pipe'; import { HmtGeneralStatsDto } from './dto/hmt-general-stats.dto'; -import { ChainId } from '@human-protocol/sdk'; -import { NetworkConfigService } from '../../common/config/network-config.service'; @ApiTags('Stats') @Controller('/stats') export class StatsController { - constructor( - private readonly statsService: StatsService, - private readonly networkConfigService: NetworkConfigService, - ) {} + constructor(private readonly statsService: StatsService) {} @Get('/hmt-price') @HttpCode(200) @@ -132,19 +127,4 @@ export class StatsController { const results = await this.statsService.hmtDailyStats(from, to); return { from, to, results }; } - - @Get('/available-networks') - @HttpCode(200) - @ApiOperation({ - summary: 'Get available networks with recent usage', - description: 'Endpoint to return networks filtered by recent activity.', - }) - @ApiResponse({ - status: 200, - description: 'Networks retrieved successfully', - type: Array, - }) - public async getAvailableNetworks(): Promise { - return this.networkConfigService.getAvailableNetworks(); - } } diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.module.ts b/packages/apps/dashboard/server/src/modules/stats/stats.module.ts index efaea6cf81..4bed88e38b 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.module.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.module.ts @@ -4,9 +4,10 @@ import { Module } from '@nestjs/common'; import { StatsService } from './stats.service'; import { StatsController } from './stats.controller'; import { StorageModule } from '../storage/storage.module'; +import { NetworksModule } from '../networks/networks.module'; @Module({ - imports: [HttpModule, StorageModule], + imports: [HttpModule, StorageModule, NetworksModule], controllers: [StatsController], exports: [StatsService], providers: [StatsService], diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts index 223afe5326..d8702151ee 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts @@ -25,6 +25,7 @@ import { StorageService } from '../storage/storage.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { CronJob } from 'cron'; import { SchedulerRegistry } from '@nestjs/schedule'; +import { NetworksService } from '../networks/networks.service'; @Injectable() export class StatsService implements OnModuleInit { @@ -32,7 +33,7 @@ export class StatsService implements OnModuleInit { constructor( @Inject(CACHE_MANAGER) private cacheManager: Cache, private readonly redisConfigService: RedisConfigService, - private readonly networkConfigService: NetworkConfigService, + private readonly networksService: NetworksService, private readonly envConfigService: EnvironmentConfigService, private readonly httpService: HttpService, private readonly storageService: StorageService, @@ -193,9 +194,8 @@ export class StatsService implements OnModuleInit { totalHolders: 0, totalTransactions: 0, }; - const availableNetworks = - await this.networkConfigService.getAvailableNetworks(); - for (const network of availableNetworks) { + const operatingNetworks = await this.networksService.getOperatingNetworks(); + for (const network of operatingNetworks) { const statisticsClient = new StatisticsClient(NETWORKS[network]); const generalStats = await statisticsClient.getHMTStatistics(); aggregatedStats.totalHolders += generalStats.totalHolders; @@ -232,12 +232,11 @@ export class StatsService implements OnModuleInit { const dailyData: Record = {}; const monthlyData: Record = {}; - const availableNetworks = - await this.networkConfigService.getAvailableNetworks(); + const operatingNetworks = await this.networksService.getOperatingNetworks(); // Fetch daily data for each network await Promise.all( - availableNetworks.map(async (network) => { + operatingNetworks.map(async (network) => { const statisticsClient = new StatisticsClient(NETWORKS[network]); let skip = 0; let fetchedRecords: DailyHMTData[] = []; diff --git a/packages/apps/dashboard/server/test/app.e2e-spec.ts b/packages/apps/dashboard/server/test/app.e2e-spec.ts new file mode 100644 index 0000000000..35f4ae9f85 --- /dev/null +++ b/packages/apps/dashboard/server/test/app.e2e-spec.ts @@ -0,0 +1,68 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { INestApplication } from '@nestjs/common'; +import request from 'supertest'; +import { AppModule } from '../src/app.module'; +import { beforeAll, afterAll, describe, it, expect } from '@jest/globals'; +import { ConfigService } from '@nestjs/config'; +import { + TestEnvironmentConfigService, + testEnvValidator, +} from '../src/common/config/test-environment-config.service'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { Cache } from 'cache-manager'; + +describe('Dashboard (e2e) tests', () => { + let app: INestApplication; + let configService: ConfigService; + let envConfigService: TestEnvironmentConfigService; + let cacheManager: Cache; + + beforeAll(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + configService = moduleFixture.get(ConfigService); + envConfigService = new TestEnvironmentConfigService(configService); + cacheManager = app.get(CACHE_MANAGER); + + const { error } = testEnvValidator.validate({ + E2E_TESTING_EMAIL_ADDRESS: envConfigService.e2eTestingEmailAddress, + }); + + if (error) { + throw new Error(`Test environment is not valid: ${error.message}`); + } + + await app.init(); + }); + + describe('Networks API', () => { + it('should successfully retrieve operating networks and validate chain IDs', async () => { + const response = await request(app.getHttpServer()) + .get('/networks/operating') + .expect(200); + + expect(Array.isArray(response.body)).toBe(true); + expect(response.body.every((id: any) => typeof id === 'number')).toBe( + true, + ); + }); + + it('should retrieve from cache when it exists', async () => { + const mockData = [1, 2, 3]; + await cacheManager.set('operating-networks', mockData); + + const response = await request(app.getHttpServer()) + .get('/networks/operating') + .expect(200); + + expect(response.body).toEqual(mockData); + }); + }); + + afterAll(async () => { + await app.close(); + }); +}); diff --git a/packages/apps/dashboard/server/test/jest-e2e.json b/packages/apps/dashboard/server/test/jest-e2e.json new file mode 100644 index 0000000000..d530a8f8d9 --- /dev/null +++ b/packages/apps/dashboard/server/test/jest-e2e.json @@ -0,0 +1,12 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": ".", + "testEnvironment": "node", + "testRegex": ".e2e-spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "transformIgnorePatterns": [ + "/node_modules/(?!(@nestjs/config|uuid)).+\\.js$" + ] +} From c9d8688c5523b961539d27b5a925bae87e892b4a Mon Sep 17 00:00:00 2001 From: adrian-oleskiewicz Date: Wed, 18 Dec 2024 09:57:02 +0100 Subject: [PATCH 81/92] [Dashboard] feat: added EVM address validation to search (#2908) --- .../src/components/SearchBar/SearchBar.tsx | 53 +++++++++++++------ .../ui-2024/src/helpers/isValidEVMAddress.ts | 4 ++ packages/apps/dashboard/ui-2024/src/theme.tsx | 16 +++--- 3 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 packages/apps/dashboard/ui-2024/src/helpers/isValidEVMAddress.ts diff --git a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx index b9ca414eb7..6abd09b890 100644 --- a/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx +++ b/packages/apps/dashboard/ui-2024/src/components/SearchBar/SearchBar.tsx @@ -12,6 +12,7 @@ import { Grid, MenuItem, Box, + Tooltip, } from '@mui/material'; import { colorPalette } from '@assets/styles/color-palette'; import { getNetwork, networks } from '@utils/config/networks'; @@ -27,6 +28,7 @@ import { muiTextFieldSx, gridSx, } from './SearchBar.styles'; +import { isValidEVMAddress } from '../../helpers/isValidEVMAddress'; interface SearchBarProps { className?: string; @@ -43,6 +45,7 @@ const SearchBar: FC = ({ const [focus, setFocus] = useState(false); const { filterParams } = useWalletSearch(); const navigate = useNavigate(); + const [error, setError] = useState(null); const navigateToAddress = useCallback( (chainIdParam?: number | undefined) => { @@ -65,7 +68,14 @@ const SearchBar: FC = ({ }, [filterParams.address]); const handleInputChange = (event: React.ChangeEvent) => { - setInputValue(event.target.value); + const value = event.target.value; + setInputValue(value); + + if (isValidEVMAddress(value)) { + setError(null); + } else if (value.length > 0) { + setError('Invalid EVM address. Must start with 0x and be 42 characters.'); + } }; const handleSelectChange = (event: SelectChangeEvent) => { @@ -79,6 +89,11 @@ const SearchBar: FC = ({ const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); + + if (!isValidEVMAddress(inputValue)) { + return; + } + if (inputValue && !!inputValue.length) { navigateToAddress(); } @@ -110,6 +125,7 @@ const SearchBar: FC = ({ onChange={handleInputChange} onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} + error={!!error} fullWidth sx={muiTextFieldSx(mobile)} InputProps={{ @@ -156,23 +172,26 @@ const SearchBar: FC = ({ }} /> - - + - + > + + + ), }} diff --git a/packages/apps/dashboard/ui-2024/src/helpers/isValidEVMAddress.ts b/packages/apps/dashboard/ui-2024/src/helpers/isValidEVMAddress.ts new file mode 100644 index 0000000000..8b4e86d412 --- /dev/null +++ b/packages/apps/dashboard/ui-2024/src/helpers/isValidEVMAddress.ts @@ -0,0 +1,4 @@ +export const isValidEVMAddress = (input: string): boolean => { + const evmRegex = /^0x[a-fA-F0-9]{40}$/; + return evmRegex.test(input); +}; diff --git a/packages/apps/dashboard/ui-2024/src/theme.tsx b/packages/apps/dashboard/ui-2024/src/theme.tsx index 0fb6b27439..955fb4009c 100644 --- a/packages/apps/dashboard/ui-2024/src/theme.tsx +++ b/packages/apps/dashboard/ui-2024/src/theme.tsx @@ -221,11 +221,11 @@ const theme: ThemeOptions = createTheme({ MuiTooltip: { styleOverrides: { tooltip: { - backgroundColor: '#320a8d', - color: '#fff', + backgroundColor: colorPalette.secondary.main, + color: colorPalette.whiteSolid, }, arrow: { - color: '#320a8d', + color: colorPalette.secondary.main, }, }, }, @@ -241,19 +241,19 @@ const theme: ThemeOptions = createTheme({ root: { borderRadius: 4, borderWidth: 2, - color: '#320a8d', + color: colorPalette.primary.main, '& .MuiOutlinedInput-notchedOutline': { - borderColor: '#320a8d', + borderColor: colorPalette.primary.main, borderWidth: 2, }, '&:hover .MuiOutlinedInput-notchedOutline': { - borderColor: '#320a8d', + borderColor: colorPalette.primary.main, }, '&.Mui-focused .MuiOutlinedInput-notchedOutline': { - borderColor: '#320a8d', + borderColor: colorPalette.primary.main, }, '& .MuiSvgIcon-root': { - color: '#320a8d', + color: colorPalette.primary.main, }, }, }, From 9b2e2efc2026a2c53071221e4a1a55a0b36008af Mon Sep 17 00:00:00 2001 From: eugenvoronov <104138627+eugenvoronov@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:32:12 +0300 Subject: [PATCH 82/92] Added role to reputation endpoint (#2935) --- .../server/src/modules/reputation/reputation.dto.ts | 4 ++++ .../src/modules/reputation/reputation.service.spec.ts | 9 +++++++++ .../server/src/modules/reputation/reputation.service.ts | 3 +++ 3 files changed, 16 insertions(+) diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.dto.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.dto.ts index e1317ab389..c1c6810a21 100644 --- a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.dto.ts +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.dto.ts @@ -84,4 +84,8 @@ export class ReputationDto { @IsEnumCaseInsensitive(ReputationLevel) @Transform(({ value }) => Number(value)) reputation: ReputationLevel; + + @ApiProperty({ enum: ReputationEntityType }) + @IsEnumCaseInsensitive(ReputationEntityType) + role: ReputationEntityType; } diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts index 9923482936..867aa57394 100644 --- a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts @@ -382,6 +382,7 @@ describe('ReputationService', () => { const reputationEntity: Partial = { address, reputationPoints: 1, + type: ReputationEntityType.RECORDING_ORACLE, save: jest.fn(), }; @@ -427,6 +428,7 @@ describe('ReputationService', () => { const reputationEntity: Partial = { address, reputationPoints: 1, + type: ReputationEntityType.RECORDING_ORACLE, save: jest.fn(), }; @@ -447,6 +449,7 @@ describe('ReputationService', () => { const reputationEntity: Partial = { address, reputationPoints: 701, + type: ReputationEntityType.RECORDING_ORACLE, save: jest.fn(), }; @@ -496,6 +499,7 @@ describe('ReputationService', () => { chainId, address, reputationPoints: 1, + type: ReputationEntityType.RECORDING_ORACLE, }; jest @@ -508,6 +512,7 @@ describe('ReputationService', () => { chainId, address, reputation: ReputationLevel.HIGH, + role: ReputationEntityType.REPUTATION_ORACLE, }; expect(result).toEqual(resultReputation); @@ -519,6 +524,7 @@ describe('ReputationService', () => { chainId, address: NOT_ORACLE_ADDRESS, reputationPoints: 1, + type: ReputationEntityType.RECORDING_ORACLE, }; jest @@ -534,6 +540,7 @@ describe('ReputationService', () => { chainId, address: NOT_ORACLE_ADDRESS, reputation: ReputationLevel.LOW, + role: ReputationEntityType.RECORDING_ORACLE, }; expect( @@ -553,6 +560,7 @@ describe('ReputationService', () => { chainId, address, reputationPoints: 1, + type: ReputationEntityType.RECORDING_ORACLE, }; jest @@ -565,6 +573,7 @@ describe('ReputationService', () => { chainId, address, reputation: ReputationLevel.LOW, + role: ReputationEntityType.RECORDING_ORACLE, }; expect(reputationRepository.findByChainIdAndTypes).toHaveBeenCalled(); diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts index c591712862..b17ebbea80 100644 --- a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts @@ -346,6 +346,7 @@ export class ReputationService { chainId, address, reputation: ReputationLevel.HIGH, + role: ReputationEntityType.REPUTATION_ORACLE, }; } @@ -366,6 +367,7 @@ export class ReputationService { chainId: reputationEntity.chainId, address: reputationEntity.address, reputation: this.getReputationLevel(reputationEntity.reputationPoints), + role: reputationEntity.type, }; } @@ -404,6 +406,7 @@ export class ReputationService { chainId: reputation.chainId, address: reputation.address, reputation: this.getReputationLevel(reputation.reputationPoints), + role: reputation.type, })); } } From 3877a6f1e503ed9fe34960cfebdf1a6efa2655f0 Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Wed, 18 Dec 2024 15:56:02 +0100 Subject: [PATCH 83/92] change balance label from balance of to balance (#2939) --- .../apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx index 2e82d61122..6107d08449 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx @@ -132,7 +132,7 @@ export default function JobDetail() { value={data.details.manifestHash} /> Date: Thu, 19 Dec 2024 12:17:10 +0300 Subject: [PATCH 84/92] [Reputation Oracle] refactoring: exception handling for `kyc` module (#2937) * refactoring: exception handling for `kyc` module * fix: removed unused value from `KycErrorMessage`; `userId` in `KycError` is not optional now; --- .../server/src/common/constants/errors.ts | 10 ---- .../src/common/exceptions/exception.filter.ts | 6 +++ .../src/common/guards/kyc-webhook.auth.ts | 24 ++++++++-- .../server/src/modules/kyc/kyc.controller.ts | 3 ++ .../src/modules/kyc/kyc.error.filter.ts | 30 ++++++++++++ .../server/src/modules/kyc/kyc.error.ts | 20 ++++++++ .../src/modules/kyc/kyc.service.spec.ts | 31 ++++++------- .../server/src/modules/kyc/kyc.service.ts | 46 ++++++++----------- 8 files changed, 114 insertions(+), 56 deletions(-) create mode 100644 packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.ts diff --git a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts index 08400a470b..e26795fc85 100644 --- a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts +++ b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts @@ -116,16 +116,6 @@ export enum ErrorSendGrid { InvalidApiKey = 'Invalid SendGrid API key', } -export enum ErrorKyc { - NotFound = 'KYC session not found', - AlreadyApproved = 'KYC session already approved', - VerificationInProgress = 'KYC session verification in progress', - Declined = 'KYC session declined', - InvalidKycProviderAPIResponse = 'Invalid KYC provider API response', - InvalidWebhookSecret = 'Invalid webhook secret', - CountryNotSet = 'Сountry is not set for the user', -} - /** * Represents error messages associated with a cron job. */ diff --git a/packages/apps/reputation-oracle/server/src/common/exceptions/exception.filter.ts b/packages/apps/reputation-oracle/server/src/common/exceptions/exception.filter.ts index 8f4944455f..312f11689b 100644 --- a/packages/apps/reputation-oracle/server/src/common/exceptions/exception.filter.ts +++ b/packages/apps/reputation-oracle/server/src/common/exceptions/exception.filter.ts @@ -4,6 +4,7 @@ import { ExceptionFilter as IExceptionFilter, HttpStatus, Logger, + HttpException, } from '@nestjs/common'; import { Request, Response } from 'express'; import { DatabaseError } from '../errors/database'; @@ -34,6 +35,11 @@ export class ExceptionFilter implements IExceptionFilter { `Database error: ${exception.message}`, exception.stack, ); + // Temp hack for the in progress exception handling refactoring + } else if (exception instanceof HttpException) { + return response + .status(exception.getStatus()) + .json(exception.getResponse()); } else { if (exception.statusCode === HttpStatus.BAD_REQUEST) { status = exception.statusCode; diff --git a/packages/apps/reputation-oracle/server/src/common/guards/kyc-webhook.auth.ts b/packages/apps/reputation-oracle/server/src/common/guards/kyc-webhook.auth.ts index f5eded9ae2..4e11b72508 100644 --- a/packages/apps/reputation-oracle/server/src/common/guards/kyc-webhook.auth.ts +++ b/packages/apps/reputation-oracle/server/src/common/guards/kyc-webhook.auth.ts @@ -3,14 +3,16 @@ import { CanActivate, ExecutionContext, HttpStatus, + HttpException, + Logger, } from '@nestjs/common'; import { Request } from 'express'; -import { ControlledError } from '../errors/controlled'; import { createHmac } from 'crypto'; import { KycConfigService } from '../config/kyc-config.service'; @Injectable() export class KycWebhookAuthGuard implements CanActivate { + logger = new Logger(KycWebhookAuthGuard.name); constructor(private readonly kycConfigService: KycConfigService) {} canActivate(context: ExecutionContext): boolean { const request: Request = context.switchToHttp().getRequest(); @@ -20,7 +22,15 @@ export class KycWebhookAuthGuard implements CanActivate { const hmacSignature = headers['x-hmac-signature']; if (!hmacSignature) { - throw new ControlledError('Unauthorized', HttpStatus.UNAUTHORIZED); + const message = 'HMAC Signature not provided'; + this.logger.error(message, request.path); + throw new HttpException( + { + message, + timestamp: new Date().toISOString(), + }, + HttpStatus.UNAUTHORIZED, + ); } const signedPayload = createHmac( @@ -34,7 +44,15 @@ export class KycWebhookAuthGuard implements CanActivate { signedPayload !== hmacSignature || this.kycConfigService.apiKey !== apiKey ) { - throw new ControlledError('Unauthorized', HttpStatus.UNAUTHORIZED); + const message = 'HMAC Signature does not match'; + this.logger.error(message, request.path); + throw new HttpException( + { + message, + timestamp: new Date().toISOString(), + }, + HttpStatus.UNAUTHORIZED, + ); } return true; diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.controller.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.controller.ts index 0662cce88d..cbd7493ee8 100644 --- a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.controller.ts +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.controller.ts @@ -13,6 +13,7 @@ import { HttpCode, Post, Req, + UseFilters, UseGuards, } from '@nestjs/common'; import { JwtAuthGuard } from '../../common/guards'; @@ -20,9 +21,11 @@ import { RequestWithUser } from '../../common/types'; import { KycSessionDto, KycSignedAddressDto, KycStatusDto } from './kyc.dto'; import { KycService } from './kyc.service'; import { KycWebhookAuthGuard } from '../../common/guards/kyc-webhook.auth'; +import { KycErrorFilter } from './kyc.error.filter'; @ApiTags('Kyc') @Controller('/kyc') +@UseFilters(KycErrorFilter) export class KycController { constructor(private readonly kycService: KycService) {} diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts new file mode 100644 index 0000000000..f5ca2c3752 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts @@ -0,0 +1,30 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpException, + HttpStatus, + Logger, +} from '@nestjs/common'; +import { Request, Response } from 'express'; + +import { KycError, KycErrorMessage } from './kyc.error'; + +@Catch(KycError) +export class KycErrorFilter implements ExceptionFilter { + private logger = new Logger(KycErrorFilter.name); + catch(exception: KycError, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + const status = HttpStatus.BAD_REQUEST; + + this.logger.error(exception.message, exception.stack, exception.userId); + + return response.status(status).json({ + message: exception.message, + timestamp: new Date().toISOString(), + path: request.url, + }); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.ts new file mode 100644 index 0000000000..dead033221 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.ts @@ -0,0 +1,20 @@ +import { BaseError } from '../../common/errors/base'; + +export enum KycErrorMessage { + NOT_FOUND = 'KYC session not found', + ALREADY_APPROVED = 'KYC session already approved', + VERIFICATION_IN_PROGRESS = 'KYC session verification in progress', + DECLINED = 'KYC session declined', + INVALID_KYC_PROVIDER_API_RESPONSE = 'Invalid KYC provider API response', + COUNTRY_NOT_SET = 'Сountry is not set for the user', + NO_WALLET_ADDRESS_REGISTERED = 'No wallet address registered on your account', + KYC_NOT_APPROVED = 'KYC not approved', +} + +export class KycError extends BaseError { + userId: number; + constructor(message: KycErrorMessage, userId: number) { + super(message); + this.userId = userId; + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.spec.ts index 803193a621..2109ac4095 100644 --- a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.spec.ts @@ -1,7 +1,6 @@ import { createMock } from '@golevelup/ts-jest'; import { ChainId } from '@human-protocol/sdk'; import { HttpService } from '@nestjs/axios'; -import { HttpStatus } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Test } from '@nestjs/testing'; import { of } from 'rxjs'; @@ -10,13 +9,12 @@ import { MOCK_ADDRESS, mockConfig } from '../../../test/constants'; import { HCaptchaConfigService } from '../../common/config/hcaptcha-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { KycConfigService } from '../../common/config/kyc-config.service'; -import { ErrorKyc, ErrorUser } from '../../common/constants/errors'; import { KycStatus } from '../../common/enums/user'; -import { ControlledError } from '../../common/errors/controlled'; import { Web3Service } from '../web3/web3.service'; import { KycEntity } from './kyc.entity'; import { KycRepository } from './kyc.repository'; import { KycService } from './kyc.service'; +import { KycError, KycErrorMessage } from './kyc.error'; describe('Kyc Service', () => { let kycService: KycService; @@ -127,6 +125,7 @@ describe('Kyc Service', () => { it('Should throw an error if user already has an active Kyc session, but is approved already', async () => { const mockUserEntity = { + id: 1, kyc: { sessionId: '123', url: 'https://randomurl.test', @@ -137,12 +136,13 @@ describe('Kyc Service', () => { await expect( kycService.initSession(mockUserEntity as any), ).rejects.toThrow( - new ControlledError(ErrorKyc.AlreadyApproved, HttpStatus.BAD_REQUEST), + new KycError(KycErrorMessage.ALREADY_APPROVED, mockUserEntity.id), ); }); it("Should throw an error if user already has an active Kyc session, but it's in review", async () => { const mockUserEntity = { + id: 1, kyc: { sessionId: '123', url: 'https://randomurl.test', @@ -153,15 +153,16 @@ describe('Kyc Service', () => { await expect( kycService.initSession(mockUserEntity as any), ).rejects.toThrow( - new ControlledError( - ErrorKyc.VerificationInProgress, - HttpStatus.BAD_REQUEST, + new KycError( + KycErrorMessage.VERIFICATION_IN_PROGRESS, + mockUserEntity.id, ), ); }); it("Should throw an error if user already has an active Kyc session, but it's declined", async () => { const mockUserEntity = { + id: 1, kyc: { sessionId: '123', url: 'https://randomurl.test', @@ -173,10 +174,7 @@ describe('Kyc Service', () => { await expect( kycService.initSession(mockUserEntity as any), ).rejects.toThrow( - new ControlledError( - `${ErrorKyc.Declined}. Reason: ${mockUserEntity.kyc.message}`, - HttpStatus.BAD_REQUEST, - ), + new KycError(KycErrorMessage.DECLINED, mockUserEntity.id), ); }); @@ -266,20 +264,21 @@ describe('Kyc Service', () => { describe('getSignedAddress', () => { it('Should throw an error if the user has no wallet address registered', async () => { - const mockUserEntity = {}; + const mockUserEntity = { id: 1 }; await expect( kycService.getSignedAddress(mockUserEntity as any), ).rejects.toThrow( - new ControlledError( - ErrorUser.NoWalletAddresRegistered, - HttpStatus.BAD_REQUEST, + new KycError( + KycErrorMessage.NO_WALLET_ADDRESS_REGISTERED, + mockUserEntity.id, ), ); }); it('Should throw an error if the user KYC status is not approved', async () => { const mockUserEntity = { + id: 1, evmAddress: MOCK_ADDRESS, kyc: { status: KycStatus.NONE, @@ -289,7 +288,7 @@ describe('Kyc Service', () => { await expect( kycService.getSignedAddress(mockUserEntity as any), ).rejects.toThrow( - new ControlledError(ErrorUser.KycNotApproved, HttpStatus.BAD_REQUEST), + new KycError(KycErrorMessage.KYC_NOT_APPROVED, mockUserEntity.id), ); }); diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts index e50bcfd207..7504c9dc30 100644 --- a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { UserEntity } from '../user/user.entity'; import { HttpService } from '@nestjs/axios'; @@ -6,13 +6,13 @@ import { KycSessionDto, KycSignedAddressDto, KycStatusDto } from './kyc.dto'; import { KycRepository } from './kyc.repository'; import { KycStatus } from '../../common/enums/user'; import { firstValueFrom } from 'rxjs'; -import { ErrorKyc, ErrorUser } from '../../common/constants/errors'; import { KycConfigService } from '../../common/config/kyc-config.service'; import { KycEntity } from './kyc.entity'; -import { ControlledError } from '../../common/errors/controlled'; import { Web3Service } from '../web3/web3.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; +import { KycErrorMessage, KycError } from './kyc.error'; + @Injectable() export class KycService { constructor( @@ -26,24 +26,18 @@ export class KycService { public async initSession(userEntity: UserEntity): Promise { if (userEntity.kyc?.sessionId) { if (userEntity.kyc.status === KycStatus.APPROVED) { - throw new ControlledError( - ErrorKyc.AlreadyApproved, - HttpStatus.BAD_REQUEST, - ); + throw new KycError(KycErrorMessage.ALREADY_APPROVED, userEntity.id); } if (userEntity.kyc.status === KycStatus.REVIEW) { - throw new ControlledError( - ErrorKyc.VerificationInProgress, - HttpStatus.BAD_REQUEST, + throw new KycError( + KycErrorMessage.VERIFICATION_IN_PROGRESS, + userEntity.id, ); } if (userEntity.kyc.status === KycStatus.DECLINED) { - throw new ControlledError( - `${ErrorKyc.Declined}. Reason: ${userEntity.kyc.message}`, - HttpStatus.BAD_REQUEST, - ); + throw new KycError(KycErrorMessage.DECLINED, userEntity.id); } return { @@ -69,9 +63,9 @@ export class KycService { ); if (data?.status !== 'success' || !data?.verification?.url) { - throw new ControlledError( - ErrorKyc.InvalidKycProviderAPIResponse, - HttpStatus.INTERNAL_SERVER_ERROR, + throw new KycError( + KycErrorMessage.INVALID_KYC_PROVIDER_API_RESPONSE, + userEntity.id, ); } @@ -94,11 +88,15 @@ export class KycService { const kycEntity = await this.kycRepository.findOneBySessionId(sessionId); if (!kycEntity) { - throw new ControlledError(ErrorKyc.NotFound, HttpStatus.BAD_REQUEST); + // vendorData is a userId + throw new KycError( + KycErrorMessage.NOT_FOUND, + Number(data.verification.vendorData), + ); } if (!country) { - throw new ControlledError(ErrorKyc.CountryNotSet, HttpStatus.BAD_REQUEST); + throw new KycError(KycErrorMessage.COUNTRY_NOT_SET, kycEntity.userId); } kycEntity.status = status; @@ -112,16 +110,10 @@ export class KycService { user: UserEntity, ): Promise { if (!user.evmAddress) - throw new ControlledError( - ErrorUser.NoWalletAddresRegistered, - HttpStatus.BAD_REQUEST, - ); + throw new KycError(KycErrorMessage.NO_WALLET_ADDRESS_REGISTERED, user.id); if (user.kyc?.status !== KycStatus.APPROVED) - throw new ControlledError( - ErrorUser.KycNotApproved, - HttpStatus.BAD_REQUEST, - ); + throw new KycError(KycErrorMessage.KYC_NOT_APPROVED, user.id); const address = user.evmAddress.toLowerCase(); const signature = await this.web3Service From 31b29a698c1c724998c9092ffff64e2559803c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Thu, 19 Dec 2024 13:18:41 +0100 Subject: [PATCH 85/92] [Job Launcher] Disable fortune jobs creation in mainnets (#2942) * Disable fortune on mainnets * Use Web3Env enum --- .../server/src/modules/job/job.controller.spec.ts | 4 ++++ .../job-launcher/server/src/modules/job/job.controller.ts | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/packages/apps/job-launcher/server/src/modules/job/job.controller.spec.ts b/packages/apps/job-launcher/server/src/modules/job/job.controller.spec.ts index e2cee1efaf..a1529dfdb7 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.controller.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.controller.spec.ts @@ -20,6 +20,8 @@ import { MOCK_REQUESTER_TITLE, } from '../../../test/constants'; import { AWSRegions, StorageProviders } from 'src/common/enums/storage'; +import { Web3ConfigService } from '../../common/config/web3-config.service'; +import { ConfigService } from '@nestjs/config'; describe('JobController', () => { let jobController: JobController; @@ -48,6 +50,8 @@ describe('JobController', () => { provide: MutexManagerService, useValue: mockMutexManagerService, }, + Web3ConfigService, + ConfigService, ], }) .overrideGuard(JwtAuthGuard) diff --git a/packages/apps/job-launcher/server/src/modules/job/job.controller.ts b/packages/apps/job-launcher/server/src/modules/job/job.controller.ts index 8734008ce7..6b214e444a 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.controller.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.controller.ts @@ -40,6 +40,8 @@ import { ControlledError } from '../../common/errors/controlled'; import { PageDto } from '../../common/pagination/pagination.dto'; import { MutexManagerService } from '../mutex/mutex-manager.service'; import { MUTEX_TIMEOUT } from '../../common/constants'; +import { Web3ConfigService } from '../../common/config/web3-config.service'; +import { Web3Env } from '../../common/enums/web3'; @ApiBearerAuth() @UseGuards(JwtAuthGuard) @@ -50,6 +52,7 @@ export class JobController { constructor( private readonly jobService: JobService, private readonly mutexManagerService: MutexManagerService, + private readonly web3ConfigService: Web3ConfigService, ) {} @ApiOperation({ @@ -120,6 +123,10 @@ export class JobController { @Body() data: JobFortuneDto, @Request() req: RequestWithUser, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError('Disabled', HttpStatus.METHOD_NOT_ALLOWED); + } + return await this.mutexManagerService.runExclusive( { id: `user${req.user.id}` }, MUTEX_TIMEOUT, From 3b77496352218825572cb2d9aa22be9051bfc0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:05:43 +0100 Subject: [PATCH 86/92] [Job Launcher] Show most recent jobs first (#2943) * Show most recent jobs first * Remove sortable fields in jobs table and specify filter parameter in the request --- .../apps/job-launcher/client/src/components/Jobs/Table.tsx | 4 +--- packages/apps/job-launcher/client/src/services/job.ts | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx index 444183cc73..aa3d6eb183 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx @@ -42,7 +42,6 @@ export const JobTable = ({ { id: 'escrowAddress', label: 'Address', - sortable: true, render: ({ escrowAddress }) => escrowAddress ? ( @@ -59,11 +58,10 @@ export const JobTable = ({ <> ), }, - { id: 'network', label: 'Network', sortable: true }, + { id: 'network', label: 'Network' }, { id: 'fundAmount', label: 'Fund Amount', - sortable: true, render: ({ fundAmount }) => `${fundAmount} HMT`, }, { id: 'status', label: 'Status' }, diff --git a/packages/apps/job-launcher/client/src/services/job.ts b/packages/apps/job-launcher/client/src/services/job.ts index 1455e903eb..973b281af9 100644 --- a/packages/apps/job-launcher/client/src/services/job.ts +++ b/packages/apps/job-launcher/client/src/services/job.ts @@ -80,7 +80,9 @@ export const getJobList = async ({ queryString += `&status=${status}`; } queryString += `&page=${page}&page_size=${pageSize}`; - const { data } = await api.get(`/job/list?${queryString}`); + const { data } = await api.get( + `/job/list?${queryString}&sort=DESC&sort_field=created_at`, + ); return data; }; From 3603ff67866c15924fdc8e8d444e8640983d49f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:17:05 +0100 Subject: [PATCH 87/92] Disable billing system (#2941) * Disable billing system * Disable whitelist in server * Disable whitelist tests untill it's enabled again * Disable endpoints and reenable transactions page --- packages/apps/job-launcher/client/src/App.tsx | 24 +++-- .../components/Jobs/Create/FundingMethod.tsx | 95 ++++++++++--------- .../components/TopUpAccount/TopUpMethod.tsx | 79 +++++++-------- .../src/modules/payment/payment.controller.ts | 65 ++++++++++++- .../whitelist/whitelist.service.spec.ts | 21 ++-- .../modules/whitelist/whitelist.service.ts | 2 + 6 files changed, 181 insertions(+), 105 deletions(-) diff --git a/packages/apps/job-launcher/client/src/App.tsx b/packages/apps/job-launcher/client/src/App.tsx index 17310db791..603fbe19b8 100644 --- a/packages/apps/job-launcher/client/src/App.tsx +++ b/packages/apps/job-launcher/client/src/App.tsx @@ -1,5 +1,7 @@ import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom'; import { ProtectedRoute } from './components/ProtectedRoute'; +import { IS_MAINNET } from './constants/chains'; +import './index.css'; import Layout from './layouts'; import Dashboard from './pages/Dashboard'; import ForgotPassword from './pages/ForgotPassword'; @@ -14,8 +16,6 @@ import ResetPassword from './pages/ResetPassword'; import ValidateEmail from './pages/ValidateEmail'; import VerifyEmail from './pages/VerifyEmail'; -import './index.css'; - export default function App() { return ( @@ -74,14 +74,18 @@ export default function App() { } /> - - - - } - /> + {!IS_MAINNET && ( + <> + + + + } + /> + + )} } /> diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx index 13c00da135..d63c25427f 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FundingMethod.tsx @@ -1,9 +1,10 @@ import { Box, Button, Grid, Typography } from '@mui/material'; -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAccount } from 'wagmi'; import fundCryptoImg from '../../../assets/fund-crypto.png'; import fundFiatImg from '../../../assets/fund-fiat.png'; +import { IS_MAINNET } from '../../../constants/chains'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; import { useAppSelector } from '../../../state'; import { PayMethod } from '../../../types'; @@ -46,7 +47,7 @@ export const FundingMethod = () => { > {user?.whitelisted && ( - + { )} - - - fiat - - Click to pay with credit card - + {!IS_MAINNET && ( + - - + + + - - + + )} {user?.whitelisted && ( - + )} - - - fiat - - Click to pay with credit card - + {!IS_MAINNET && ( + - + + - - + + )} { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } return this.paymentService.createCustomerAndAssignCard(req.user); } @@ -195,6 +204,12 @@ export class PaymentController { @Request() req: RequestWithUser, @Body() data: CardConfirmDto, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } return this.paymentService.confirmCard(req.user, data); } @@ -225,6 +240,12 @@ export class PaymentController { @Body() data: PaymentFiatCreateDto, @Request() req: RequestWithUser, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } return this.paymentService.createFiatPayment(req.user, data); } @@ -255,6 +276,12 @@ export class PaymentController { @Body() data: PaymentFiatConfirmDto, @Request() req: RequestWithUser, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } return this.paymentService.confirmFiatPayment(req.user.id, data); } @@ -269,6 +296,12 @@ export class PaymentController { }) @Get('/fiat/cards') public async listPaymentMethods(@Request() req: RequestWithUser) { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } return this.paymentService.listUserPaymentMethods(req.user); } @@ -290,6 +323,12 @@ export class PaymentController { @Request() req: RequestWithUser, @Query() data: PaymentMethodIdDto, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } await this.paymentService.deletePaymentMethod( req.user, data.paymentMethodId, @@ -309,6 +348,12 @@ export class PaymentController { public async getBillingInfo( @Request() req: RequestWithUser, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } return this.paymentService.getUserBillingInfo(req.user); } @@ -326,6 +371,12 @@ export class PaymentController { @Request() req: RequestWithUser, @Body() data: BillingInfoUpdateDto, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } await this.paymentService.updateUserBillingInfo(req.user, data); } @@ -348,6 +399,12 @@ export class PaymentController { @Request() req: RequestWithUser, @Body() data: PaymentMethodIdDto, ): Promise { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } await this.paymentService.changeDefaultPaymentMethod( req.user, data.paymentMethodId, @@ -394,6 +451,12 @@ export class PaymentController { @Param('paymentId') paymentId: string, @Request() req: RequestWithUser, ) { + if (this.web3ConfigService.env === Web3Env.MAINNET) { + throw new ControlledError( + 'Temporally disabled', + HttpStatus.METHOD_NOT_ALLOWED, + ); + } return this.paymentService.getReceipt(paymentId, req.user); } } diff --git a/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.spec.ts b/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.spec.ts index cdb5995884..eb7f01b040 100644 --- a/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.spec.ts @@ -23,6 +23,7 @@ describe('WhitelistService', () => { moduleRef.get(WhitelistRepository); }); + // TODO: Enable it when billing system is active describe('isUserWhitelisted', () => { it('should return true if user is whitelisted', async () => { const userId = 1; @@ -32,20 +33,20 @@ describe('WhitelistService', () => { const result = await whitelistService.isUserWhitelisted(userId); - expect(whitelistRepository.findOneByUserId).toHaveBeenCalledWith(userId); + // expect(whitelistRepository.findOneByUserId).toHaveBeenCalledWith(userId); expect(result).toBe(true); }); - it('should return false if user is not whitelisted', async () => { - const userId = 2; - jest - .spyOn(whitelistRepository, 'findOneByUserId') - .mockResolvedValue(null); + // it('should return false if user is not whitelisted', async () => { + // const userId = 2; + // jest + // .spyOn(whitelistRepository, 'findOneByUserId') + // .mockResolvedValue(null); - const result = await whitelistService.isUserWhitelisted(userId); + // const result = await whitelistService.isUserWhitelisted(userId); - expect(whitelistRepository.findOneByUserId).toHaveBeenCalledWith(userId); - expect(result).toBe(false); - }); + // expect(whitelistRepository.findOneByUserId).toHaveBeenCalledWith(userId); + // expect(result).toBe(false); + // }); }); }); diff --git a/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.ts b/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.ts index fc64f07319..5c8e55e861 100644 --- a/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.ts +++ b/packages/apps/job-launcher/server/src/modules/whitelist/whitelist.service.ts @@ -6,6 +6,8 @@ export class WhitelistService { constructor(private readonly whitelistRepository: WhitelistRepository) {} async isUserWhitelisted(userId: number): Promise { + // TODO: Enable it when billing system is active + return true; const user = await this.whitelistRepository.findOneByUserId(userId); return !!user; } From 54a44092661abd80881143e0c1f7f197b18db984 Mon Sep 17 00:00:00 2001 From: Dzeranov Date: Fri, 20 Dec 2024 15:07:45 +0300 Subject: [PATCH 88/92] [Reputation Oracle] refactoring: error handling for `qualification` module (#2944) * refactoring: error handling for `qualification` module; changed API schema for `/assign` and `/unassign` * refactor: `NO_WORKERS_FOUND` now causes 422 HTTP error --- .../server/src/common/constants/errors.ts | 11 -- .../server/src/common/pipes/validation.ts | 1 + .../src/modules/kyc/kyc.error.filter.ts | 3 +- .../qualification.controller.spec.ts | 2 - .../qualification/qualification.controller.ts | 7 + .../qualification/qualification.dto.ts | 21 +-- .../qualification.error.filter.ts | 40 ++++++ .../qualification/qualification.error.ts | 16 +++ .../qualification.service.spec.ts | 68 +++------ .../qualification/qualification.service.ts | 130 ++++++++---------- 10 files changed, 145 insertions(+), 154 deletions(-) create mode 100644 packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.filter.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.ts diff --git a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts index e26795fc85..f77f166af4 100644 --- a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts +++ b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts @@ -141,14 +141,3 @@ export enum ErrorOperator { OperatorAlreadyActive = 'Operator is already active', OperatorNotActive = 'Operator not active', } - -/** - * Represents error messages related to qualification. - */ -export enum ErrorQualification { - InvalidExpiresAt = 'Qualification should be valid for at least %minValidity% hours', - NotFound = 'Qualification not found', - NoWorkersFound = 'No workers found for the provided addresses or emails', - AddressesOrEmailsMustBeProvided = 'Either addresses or emails must be provided', - CannotDeleteAssignedQualification = 'Cannot delete qualification because it is assigned to users', -} diff --git a/packages/apps/reputation-oracle/server/src/common/pipes/validation.ts b/packages/apps/reputation-oracle/server/src/common/pipes/validation.ts index 61e3ddbe40..2e8d648406 100644 --- a/packages/apps/reputation-oracle/server/src/common/pipes/validation.ts +++ b/packages/apps/reputation-oracle/server/src/common/pipes/validation.ts @@ -7,6 +7,7 @@ import { } from '@nestjs/common'; import { ControlledError } from '../errors/controlled'; +// TODO: Revisit validation options @Injectable() export class HttpValidationPipe extends ValidationPipe { constructor(options?: ValidationPipeOptions) { diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts index f5ca2c3752..bc9ac74c27 100644 --- a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error.filter.ts @@ -2,13 +2,12 @@ import { ExceptionFilter, Catch, ArgumentsHost, - HttpException, HttpStatus, Logger, } from '@nestjs/common'; import { Request, Response } from 'express'; -import { KycError, KycErrorMessage } from './kyc.error'; +import { KycError } from './kyc.error'; @Catch(KycError) export class KycErrorFilter implements ExceptionFilter { diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.spec.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.spec.ts index 9d8e0f2d8d..f8c23b8e80 100644 --- a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.spec.ts @@ -114,7 +114,6 @@ describe('QualificationController', () => { const assignQualificationDto: AssignQualificationDto = { reference: 'test-ref', workerAddresses: ['0x123'], - workerEmails: ['test@example.com'], }; jest.spyOn(qualificationService, 'assign').mockResolvedValue(); @@ -131,7 +130,6 @@ describe('QualificationController', () => { const unassignQualificationDto: UnassignQualificationDto = { reference: 'test-ref', workerAddresses: ['0x123'], - workerEmails: ['test@example.com'], }; jest.spyOn(qualificationService, 'unassign').mockResolvedValue(); diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.ts index e7d1348a17..fb3a5a67eb 100644 --- a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.ts +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.controller.ts @@ -7,6 +7,7 @@ import { Param, UseGuards, HttpCode, + UseFilters, } from '@nestjs/common'; import { CreateQualificationDto, @@ -21,14 +22,18 @@ import { ApiResponse, ApiBody, } from '@nestjs/swagger'; +import { QualificationErrorFilter } from './qualification.error.filter'; import { JwtAuthGuard, RolesAuthGuard } from '../../common/guards'; import { QualificationService } from './qualification.service'; import { Roles } from '../../common/decorators'; import { Role } from '../../common/enums/user'; +// TODO: Revisit methods and status codes. + @ApiTags('Qualification') @Controller('qualification') @ApiBearerAuth() +@UseFilters(QualificationErrorFilter) export class QualificationController { constructor(private readonly qualificationService: QualificationService) {} @@ -69,6 +74,7 @@ export class QualificationController { }) @ApiResponse({ status: 400, description: 'Bad Request' }) @ApiResponse({ status: 404, description: 'Not Found' }) + @ApiResponse({ status: 422, description: 'Unprocessable entity' }) assign(@Body() assignQualificationDto: AssignQualificationDto) { return this.qualificationService.assign(assignQualificationDto); } @@ -85,6 +91,7 @@ export class QualificationController { }) @ApiResponse({ status: 400, description: 'Bad Request' }) @ApiResponse({ status: 404, description: 'Not Found' }) + @ApiResponse({ status: 422, description: 'Unprocessable entity' }) unassign(@Body() unassignQualificationDto: UnassignQualificationDto) { return this.qualificationService.unassign(unassignQualificationDto); } diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.dto.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.dto.ts index 4141a8d0af..07566da170 100644 --- a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.dto.ts +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.dto.ts @@ -4,7 +4,6 @@ import { IsOptional, IsDateString, IsEthereumAddress, - IsEmail, } from 'class-validator'; export class QualificationDto { @@ -38,15 +37,9 @@ export class AssignQualificationDto { @IsString() public reference: string; - @ApiPropertyOptional({ name: 'worker_addresses' }) - @IsOptional() + @ApiProperty({ name: 'worker_addresses' }) @IsEthereumAddress({ each: true }) - public workerAddresses?: string[]; - - @ApiPropertyOptional({ name: 'worker_emails' }) - @IsOptional() - @IsEmail({}, { each: true }) - public workerEmails?: string[]; + public workerAddresses: string[]; } export class UnassignQualificationDto { @@ -54,13 +47,7 @@ export class UnassignQualificationDto { @IsString() public reference: string; - @ApiPropertyOptional({ name: 'worker_addresses' }) - @IsOptional() + @ApiProperty({ name: 'worker_addresses' }) @IsEthereumAddress({ each: true }) - public workerAddresses?: string[]; - - @ApiPropertyOptional({ name: 'worker_emails' }) - @IsOptional() - @IsEmail({}, { each: true }) - public workerEmails?: string[]; + public workerAddresses: string[]; } diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.filter.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.filter.ts new file mode 100644 index 0000000000..b76718e881 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.filter.ts @@ -0,0 +1,40 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpStatus, + Logger, +} from '@nestjs/common'; +import { Request, Response } from 'express'; + +import { + QualificationError, + QualificationErrorMessage, +} from './qualification.error'; + +@Catch(QualificationError) +export class QualificationErrorFilter implements ExceptionFilter { + private logger = new Logger(QualificationErrorFilter.name); + catch(exception: QualificationError, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + let status = HttpStatus.BAD_REQUEST; + + if (exception.message === QualificationErrorMessage.NOT_FOUND) { + status = HttpStatus.NOT_FOUND; + } else if ( + exception.message === QualificationErrorMessage.NO_WORKERS_FOUND + ) { + status = HttpStatus.UNPROCESSABLE_ENTITY; + } + + this.logger.error(exception.message, exception.stack, exception.reference); + + return response.status(status).json({ + message: exception.message, + timestamp: new Date().toISOString(), + path: request.url, + }); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.ts new file mode 100644 index 0000000000..d6fab67aeb --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error.ts @@ -0,0 +1,16 @@ +import { BaseError } from '../../common/errors/base'; + +export enum QualificationErrorMessage { + INVALID_EXPIRATION_TIME = 'Qualification should be valid for at least %minValidity% day(s)', + NOT_FOUND = 'Qualification not found', + NO_WORKERS_FOUND = 'Workers not found', + CANNOT_DETELE_ASSIGNED_QUALIFICATION = 'Cannot delete qualification because it is assigned to users', +} + +export class QualificationError extends BaseError { + reference: string; + constructor(message: QualificationErrorMessage, reference: string) { + super(message); + this.reference = reference; + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.spec.ts index c76f3c342f..649318d949 100644 --- a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.spec.ts @@ -1,11 +1,12 @@ import { Test } from '@nestjs/testing'; import { createMock } from '@golevelup/ts-jest'; -import { HttpStatus } from '@nestjs/common'; import { QualificationService } from './qualification.service'; import { QualificationRepository } from './qualification.repository'; import { UserRepository } from '../user/user.repository'; -import { ControlledError } from '../../common/errors/controlled'; -import { ErrorQualification } from '../../common/constants/errors'; +import { + QualificationError, + QualificationErrorMessage, +} from './qualification.error'; import { CreateQualificationDto, AssignQualificationDto, @@ -126,15 +127,19 @@ describe('QualificationService', () => { expiresAt: new Date('2000-01-01'), }; - const errorMessage = ErrorQualification.InvalidExpiresAt.replace( - '%minValidity%', - '1', - ); + const errorMessage = + QualificationErrorMessage.INVALID_EXPIRATION_TIME.replace( + '%minValidity%', + '1', + ); await expect( qualificationService.createQualification(createQualificationDto), ).rejects.toThrow( - new ControlledError(errorMessage, HttpStatus.BAD_REQUEST), + new QualificationError( + errorMessage as QualificationErrorMessage, + 'ref1', + ), ); }); @@ -219,7 +224,7 @@ describe('QualificationService', () => { .mockResolvedValue(undefined); await expect(qualificationService.delete('ref1')).rejects.toThrow( - new ControlledError(ErrorQualification.NotFound, HttpStatus.NOT_FOUND), + new QualificationError(QualificationErrorMessage.NOT_FOUND, 'ref1'), ); }); }); @@ -233,7 +238,6 @@ describe('QualificationService', () => { const assignQualificationDto: AssignQualificationDto = { reference: 'ref1', workerAddresses: ['address1'], - workerEmails: ['email1@example.com'], }; const qualificationEntity = new QualificationEntity(); @@ -258,7 +262,6 @@ describe('QualificationService', () => { const assignQualificationDto: AssignQualificationDto = { reference: 'ref1', workerAddresses: ['address1'], - workerEmails: ['email1@example.com'], }; const qualificationEntity = new QualificationEntity(); @@ -289,10 +292,9 @@ describe('QualificationService', () => { qualificationService.assign({ reference: 'ref1', workerAddresses: [], - workerEmails: [], }), ).rejects.toThrow( - new ControlledError(ErrorQualification.NotFound, HttpStatus.NOT_FOUND), + new QualificationError(QualificationErrorMessage.NOT_FOUND, 'ref1'), ); }); }); @@ -306,7 +308,6 @@ describe('QualificationService', () => { const unassignQualificationDto: UnassignQualificationDto = { reference: 'ref1', workerAddresses: ['address1'], - workerEmails: ['email1@example.com'], }; const qualificationEntity = new QualificationEntity(); @@ -333,7 +334,6 @@ describe('QualificationService', () => { const unassignQualificationDto: UnassignQualificationDto = { reference: 'ref1', workerAddresses: ['address1'], - workerEmails: ['email1@example.com'], }; const qualificationEntity = new QualificationEntity(); @@ -366,57 +366,23 @@ describe('QualificationService', () => { qualificationService.unassign({ reference: 'ref1', workerAddresses: [], - workerEmails: [], }), ).rejects.toThrow( - new ControlledError(ErrorQualification.NotFound, HttpStatus.NOT_FOUND), + new QualificationError(QualificationErrorMessage.NOT_FOUND, 'ref1'), ); }); }); describe('getWorkers', () => { - it('should throw an error if neither addresses nor emails are provided', async () => { - await expect(qualificationService.getWorkers([], [])).rejects.toThrow( - new ControlledError( - ErrorQualification.AddressesOrEmailsMustBeProvided, - HttpStatus.BAD_REQUEST, - ), - ); - }); - it('should return workers by addresses', async () => { const addresses = ['address1']; const users = [{ id: 1 } as UserEntity]; userRepository.findByAddress = jest.fn().mockResolvedValue(users); - const result = await qualificationService.getWorkers(addresses, []); + const result = await qualificationService.getWorkers(addresses); expect(result).toEqual(users); }); - - it('should return workers by emails', async () => { - const emails = ['email1@example.com']; - const users = [{ id: 1 } as UserEntity]; - - userRepository.findByEmail = jest.fn().mockResolvedValue(users); - - const result = await qualificationService.getWorkers([], emails); - - expect(result).toEqual(users); - }); - - it('should throw an error if no workers are found', async () => { - userRepository.find = jest.fn().mockResolvedValue([]); - - await expect( - qualificationService.getWorkers(['address1'], []), - ).rejects.toThrow( - new ControlledError( - ErrorQualification.NoWorkersFound, - HttpStatus.NOT_FOUND, - ), - ); - }); }); }); diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts index 7f0118c8c0..4d8775b4a8 100644 --- a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Injectable, Logger } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { CreateQualificationDto, AssignQualificationDto, @@ -6,14 +6,16 @@ import { QualificationDto, } from './qualification.dto'; import { QualificationEntity } from './qualification.entity'; -import { ErrorQualification } from '../../common/constants/errors'; -import { ControlledError } from '../../common/errors/controlled'; import { QualificationRepository } from './qualification.repository'; import { UserEntity } from '../user/user.entity'; import { UserRepository } from '../user/user.repository'; import { UserStatus, Role } from '../../common/enums/user'; import { UserQualificationEntity } from './user-qualification.entity'; import { ServerConfigService } from '../../common/config/server-config.service'; +import { + QualificationError, + QualificationErrorMessage, +} from './qualification.error'; @Injectable() export class QualificationService { @@ -34,25 +36,29 @@ export class QualificationService { newQualification.description = createQualificationDto.description; if (createQualificationDto.expiresAt) { - const providedExpiresAt = new Date(createQualificationDto.expiresAt); + const providedExpirationTime = new Date(createQualificationDto.expiresAt); const now = new Date(); const minimumValidUntil = new Date( now.getTime() + - this.serverConfigService.qualificationMinValidity * 60 * 60 * 1000, // Convert hours to milliseconds, + this.serverConfigService.qualificationMinValidity * + 24 * + 60 * + 60 * + 1000, // Convert days to milliseconds, ); - if (providedExpiresAt <= minimumValidUntil) { - const minValidityHours = - this.serverConfigService.qualificationMinValidity; - const errorMessage = ErrorQualification.InvalidExpiresAt.replace( - '%minValidity%', - minValidityHours.toString(), + if (providedExpirationTime <= minimumValidUntil) { + const errorMessage = + QualificationErrorMessage.INVALID_EXPIRATION_TIME.replace( + '%minValidity%', + this.serverConfigService.qualificationMinValidity.toString(), + ); + throw new QualificationError( + errorMessage as QualificationErrorMessage, + createQualificationDto.reference, ); - - this.logger.log(errorMessage, QualificationService.name); - throw new ControlledError(errorMessage, HttpStatus.BAD_REQUEST); } else { - newQualification.expiresAt = providedExpiresAt; + newQualification.expiresAt = providedExpirationTime; } } @@ -89,16 +95,16 @@ export class QualificationService { await this.qualificationRepository.findByReference(reference); if (!qualificationEntity) { - throw new ControlledError( - ErrorQualification.NotFound, - HttpStatus.NOT_FOUND, + throw new QualificationError( + QualificationErrorMessage.NOT_FOUND, + reference, ); } if (qualificationEntity.userQualifications.length > 0) { - throw new ControlledError( - ErrorQualification.CannotDeleteAssignedQualification, - HttpStatus.BAD_REQUEST, + throw new QualificationError( + QualificationErrorMessage.CANNOT_DETELE_ASSIGNED_QUALIFICATION, + reference, ); } @@ -106,20 +112,26 @@ export class QualificationService { } public async assign(dto: AssignQualificationDto): Promise { - const { reference, workerAddresses, workerEmails } = dto; + const { reference, workerAddresses } = dto; const qualificationEntity = await this.qualificationRepository.findByReference(reference); if (!qualificationEntity) { - this.logger.log(`Qualification with reference "${reference}" not found`); - throw new ControlledError( - ErrorQualification.NotFound, - HttpStatus.NOT_FOUND, + throw new QualificationError( + QualificationErrorMessage.NOT_FOUND, + reference, ); } - const users = await this.getWorkers(workerAddresses, workerEmails); + const users = await this.getWorkers(workerAddresses); + + if (users.length === 0) { + throw new QualificationError( + QualificationErrorMessage.NO_WORKERS_FOUND, + reference, + ); + } const newUserQualifications = users .filter( @@ -141,64 +153,40 @@ export class QualificationService { } public async unassign(dto: UnassignQualificationDto): Promise { - const { reference, workerAddresses, workerEmails } = dto; + const { reference, workerAddresses } = dto; const qualificationEntity = await this.qualificationRepository.findByReference(reference); if (!qualificationEntity) { - this.logger.log(`Qualification with reference "${reference}" not found`); - throw new ControlledError( - ErrorQualification.NotFound, - HttpStatus.NOT_FOUND, + throw new QualificationError( + QualificationErrorMessage.NOT_FOUND, + reference, + ); + } + + const users = await this.getWorkers(workerAddresses); + + if (users.length === 0) { + throw new QualificationError( + QualificationErrorMessage.NO_WORKERS_FOUND, + reference, ); } - const users = await this.getWorkers(workerAddresses, workerEmails); await this.qualificationRepository.removeUserQualifications( users, qualificationEntity, ); } - public async getWorkers( - addresses?: string[], - emails?: string[], - ): Promise { - if ( - (!addresses || addresses.length === 0) === - (!emails || emails.length === 0) - ) { - throw new ControlledError( - ErrorQualification.AddressesOrEmailsMustBeProvided, - HttpStatus.BAD_REQUEST, - ); - } - - const users: UserEntity[] = []; - - if (addresses && addresses.length > 0) { - const addressUsers = await this.userRepository.findByAddress( - addresses, - Role.WORKER, - UserStatus.ACTIVE, - ); - users.push(...addressUsers); - } else if (emails && emails.length > 0) { - const emailUsers = await this.userRepository.findByEmail( - emails, - Role.WORKER, - UserStatus.ACTIVE, - ); - users.push(...emailUsers); - } - - if (users.length === 0) { - throw new ControlledError( - ErrorQualification.NoWorkersFound, - HttpStatus.NOT_FOUND, - ); - } + // TODO: Move this method to the `user` module. + public async getWorkers(addresses: string[]): Promise { + const users = await this.userRepository.findByAddress( + addresses, + Role.WORKER, + UserStatus.ACTIVE, + ); return users; } From e8bf6c69c7ad8ed5710e3c4a89fb997cf8134e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:55:39 +0100 Subject: [PATCH 89/92] [Reputation Oracle] Error handling for `reputation`module (#2947) --- .../server/src/common/constants/errors.ts | 8 -- .../reputation/reputation.controller.ts | 4 +- .../reputation/reputation.error.filter.ts | 37 +++++++ .../modules/reputation/reputation.error.ts | 20 ++++ .../reputation/reputation.service.spec.ts | 100 ++++-------------- .../modules/reputation/reputation.service.ts | 37 ++----- 6 files changed, 88 insertions(+), 118 deletions(-) create mode 100644 packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.filter.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.ts diff --git a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts index f77f166af4..4010ee9d7e 100644 --- a/packages/apps/reputation-oracle/server/src/common/constants/errors.ts +++ b/packages/apps/reputation-oracle/server/src/common/constants/errors.ts @@ -21,14 +21,6 @@ export enum ErrorEscrowCompletion { PaidProcessingFailed = 'Failed to process paid escrow completion', } -/** - * Represents error messages related to reputation. - */ -export enum ErrorReputation { - NotFound = 'Reputation not found', - NotCreated = 'Reputation has not been created', -} - /** * Represents error messages related to credential. */ diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.controller.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.controller.ts index 4eef13509b..a6734394cc 100644 --- a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.controller.ts +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param, Query } from '@nestjs/common'; +import { Controller, Get, Param, Query, UseFilters } from '@nestjs/common'; import { ApiTags, ApiOperation, @@ -14,10 +14,12 @@ import { ReputationGetParamsDto, ReputationGetQueryDto, } from './reputation.dto'; +import { ReputationErrorFilter } from './reputation.error.filter'; @Public() @ApiTags('Reputation') @Controller('reputation') +@UseFilters(ReputationErrorFilter) export class ReputationController { constructor(private readonly reputationService: ReputationService) {} diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.filter.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.filter.ts new file mode 100644 index 0000000000..ba0c775f6b --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.filter.ts @@ -0,0 +1,37 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpStatus, + Logger, +} from '@nestjs/common'; +import { Request, Response } from 'express'; + +import { ReputationError, ReputationErrorMessage } from './reputation.error'; + +@Catch(ReputationError) +export class ReputationErrorFilter implements ExceptionFilter { + private logger = new Logger(ReputationErrorFilter.name); + catch(exception: ReputationError, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + let status = HttpStatus.BAD_REQUEST; + + if (exception.message === ReputationErrorMessage.NOT_FOUND) { + status = HttpStatus.NOT_FOUND; + } + + this.logger.error( + exception.message, + exception.stack, + `${exception.chainId} - ${exception.address}`, + ); + + return response.status(status).json({ + message: exception.message, + timestamp: new Date().toISOString(), + path: request.url, + }); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.ts new file mode 100644 index 0000000000..1db32a4695 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.error.ts @@ -0,0 +1,20 @@ +import { ChainId } from '@human-protocol/sdk'; +import { BaseError } from '../../common/errors/base'; + +export enum ReputationErrorMessage { + NOT_FOUND = 'Reputation not found', +} + +export class ReputationError extends BaseError { + chainId: ChainId; + address: string; + constructor( + message: ReputationErrorMessage, + chainId: ChainId, + address: string, + ) { + super(message); + this.chainId = chainId; + this.address = address; + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts index 867aa57394..84affe4a28 100644 --- a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.spec.ts @@ -24,11 +24,9 @@ import { import { ConfigModule, ConfigService, registerAs } from '@nestjs/config'; import { Web3Service } from '../web3/web3.service'; import { StorageService } from '../storage/storage.service'; -import { ErrorManifest, ErrorResults } from '../../common/constants/errors'; import { EscrowClient } from '@human-protocol/sdk'; import { ReputationConfigService } from '../../common/config/reputation-config.service'; -import { ControlledError } from '../../common/errors/controlled'; -import { HttpStatus } from '@nestjs/common'; +import { ReputationError, ReputationErrorMessage } from './reputation.error'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), @@ -107,54 +105,7 @@ describe('ReputationService', () => { const chainId = ChainId.LOCALHOST; const escrowAddress = 'mockEscrowAddress'; - it('should handle manifest URL not found', async () => { - (EscrowClient.build as any).mockImplementation(() => ({ - getManifestUrl: jest.fn().mockResolvedValue(null), - })); - - await expect( - reputationService.assessReputationScores(chainId, escrowAddress), - ).rejects.toThrow( - new ControlledError( - ErrorManifest.ManifestUrlDoesNotExist, - HttpStatus.BAD_REQUEST, - ), - ); - }); - describe('fortune', () => { - it('should handle no verified results', async () => { - (EscrowClient.build as any).mockImplementation(() => ({ - getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getRecordingOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getResultsUrl: jest.fn().mockResolvedValue(MOCK_FILE_URL), - getManifestUrl: jest.fn().mockResolvedValue(MOCK_ADDRESS), - })); - - const manifest = { - requestType: JobRequestType.FORTUNE, - }; - - jest - .spyOn(storageService, 'downloadJsonLikeData') - .mockResolvedValueOnce(manifest) // Mock manifest - .mockResolvedValueOnce([]); // Mock final results - - jest - .spyOn(reputationService, 'increaseReputation') - .mockResolvedValueOnce(); - - await expect( - reputationService.assessReputationScores(chainId, escrowAddress), - ).rejects.toThrow( - new ControlledError( - ErrorResults.NoResultsHaveBeenVerified, - HttpStatus.BAD_REQUEST, - ), - ); - }); - it('should assess reputation scores', async () => { const manifest = { requestType: JobRequestType.FORTUNE, @@ -227,34 +178,14 @@ describe('ReputationService', () => { job_bounty: '10', }; - it('should handle annotation meta does not exist', async () => { - (EscrowClient.build as any).mockImplementation(() => ({ - getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getRecordingOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), - getResultsUrl: jest.fn().mockResolvedValue(MOCK_FILE_URL), - getIntermediateResultsUrl: jest.fn().mockResolvedValue(MOCK_FILE_URL), - getManifestUrl: jest.fn().mockResolvedValue(MOCK_ADDRESS), - })); - - jest - .spyOn(storageService, 'downloadJsonLikeData') - .mockResolvedValueOnce(manifest) // Mock manifest - .mockResolvedValueOnce([]); // Mock final results - - jest - .spyOn(reputationService, 'increaseReputation') - .mockResolvedValueOnce(); - - await expect( - reputationService.assessReputationScores(chainId, escrowAddress), - ).rejects.toThrow( - new ControlledError( - ErrorResults.NoAnnotationsMetaFound, - HttpStatus.BAD_REQUEST, - ), - ); - }); + (EscrowClient.build as any).mockImplementation(() => ({ + getJobLauncherAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getExchangeOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getRecordingOracleAddress: jest.fn().mockResolvedValue(MOCK_ADDRESS), + getResultsUrl: jest.fn().mockResolvedValue(MOCK_FILE_URL), + getIntermediateResultsUrl: jest.fn().mockResolvedValue(MOCK_FILE_URL), + getManifestUrl: jest.fn().mockResolvedValue(MOCK_ADDRESS), + })); it('should assess reputation scores', async () => { const annotationMeta = { @@ -549,6 +480,19 @@ describe('ReputationService', () => { expect(result).toEqual(resultReputation); }); + + it('should handle reputation not found', async () => { + const NOT_ORACLE_ADDRESS = '0x0000000000000000000000000000000000000000'; + jest + .spyOn(reputationRepository, 'findOneByAddressAndChainId') + .mockResolvedValueOnce(null); + + await expect( + reputationService.getReputation(chainId, NOT_ORACLE_ADDRESS), + ).rejects.toThrow( + new ReputationError(ReputationErrorMessage.NOT_FOUND, chainId, address), + ); + }); }); describe('getAllReputations', () => { diff --git a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts index b17ebbea80..73479828e8 100644 --- a/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/reputation/reputation.service.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Inject, Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { ChainId } from '@human-protocol/sdk'; import { CVAT_VALIDATION_META_FILENAME, @@ -11,11 +11,6 @@ import { SolutionError, } from '../../common/enums'; import { ReputationRepository } from './reputation.repository'; -import { - ErrorManifest, - ErrorReputation, - ErrorResults, -} from '../../common/constants/errors'; import { ReputationDto } from './reputation.dto'; import { StorageService } from '../storage/storage.service'; import { Web3Service } from '../web3/web3.service'; @@ -30,7 +25,7 @@ import { getRequestType } from '../../common/utils'; import { CvatManifestDto } from '../../common/dto/manifest'; import { ReputationConfigService } from '../../common/config/reputation-config.service'; import { ReputationEntity } from './reputation.entity'; -import { ControlledError } from '../../common/errors/controlled'; +import { ReputationError, ReputationErrorMessage } from './reputation.error'; @Injectable() export class ReputationService { @@ -58,12 +53,6 @@ export class ReputationService { const escrowClient = await EscrowClient.build(signer); const manifestUrl = await escrowClient.getManifestUrl(escrowAddress); - if (!manifestUrl) { - throw new ControlledError( - ErrorManifest.ManifestUrlDoesNotExist, - HttpStatus.BAD_REQUEST, - ); - } const manifest = await this.storageService.downloadJsonLikeData(manifestUrl); @@ -171,13 +160,6 @@ export class ReputationService { const finalResults = await this.storageService.downloadJsonLikeData(finalResultsUrl); - if (finalResults.length === 0) { - throw new ControlledError( - ErrorResults.NoResultsHaveBeenVerified, - HttpStatus.BAD_REQUEST, - ); - } - // Assess reputation scores for workers based on the final results of a job. // Decreases or increases worker reputation based on the success or failure of their contributions. await Promise.all( @@ -216,14 +198,6 @@ export class ReputationService { `${intermediateResultsUrl}/${CVAT_VALIDATION_META_FILENAME}`, ); - // If annotation meta does not exist - if (annotations && Array.isArray(annotations) && annotations.length === 0) { - throw new ControlledError( - ErrorResults.NoAnnotationsMetaFound, - HttpStatus.BAD_REQUEST, - ); - } - // Assess reputation scores for workers based on the annoation quality. // Decreases or increases worker reputation based on comparison annoation quality to minimum threshold. await Promise.all( @@ -357,9 +331,10 @@ export class ReputationService { ); if (!reputationEntity) { - throw new ControlledError( - ErrorReputation.NotFound, - HttpStatus.BAD_REQUEST, + throw new ReputationError( + ReputationErrorMessage.NOT_FOUND, + chainId, + address, ); } From d5af0b73bc67e9c50aff4d7227d80603c17d5f4d Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:33:34 +0100 Subject: [PATCH 90/92] Contracts deployment 20241219 (#2951) * deployed fuji, xlayer testnet and moombase alpha * deploy mainnet contracs and subgraphs, and update docs --- ...uman_protocol_sdk.encryption.encryption.md | 6 +- ...an_protocol_sdk.operator.operator_utils.md | 6 +- docs/sdk/typescript/README.md | 2 +- docs/sdk/typescript/base/README.md | 2 +- .../base/classes/BaseEthersClient.md | 16 +- docs/sdk/typescript/encryption/README.md | 2 +- .../encryption/classes/Encryption.md | 48 ++-- .../encryption/classes/EncryptionUtils.md | 48 ++-- docs/sdk/typescript/enums/README.md | 2 +- .../typescript/enums/enumerations/ChainId.md | 40 +-- .../enums/enumerations/OrderDirection.md | 6 +- docs/sdk/typescript/escrow/README.md | 2 +- .../typescript/escrow/classes/EscrowClient.md | 236 ++++++++++++------ .../typescript/escrow/classes/EscrowUtils.md | 52 ++-- docs/sdk/typescript/graphql/types/README.md | 2 +- .../types/type-aliases/DailyEscrowData.md | 4 +- .../types/type-aliases/DailyHMTData.md | 4 +- .../types/type-aliases/DailyPaymentData.md | 4 +- .../types/type-aliases/DailyTaskData.md | 4 +- .../types/type-aliases/DailyWorkerData.md | 4 +- .../graphql/types/type-aliases/EscrowData.md | 4 +- .../types/type-aliases/EscrowStatistics.md | 4 +- .../type-aliases/EscrowStatisticsData.md | 4 +- .../types/type-aliases/EventDayData.md | 4 +- .../graphql/types/type-aliases/HMTHolder.md | 4 +- .../types/type-aliases/HMTHolderData.md | 4 +- .../types/type-aliases/HMTStatistics.md | 4 +- .../types/type-aliases/HMTStatisticsData.md | 4 +- .../graphql/types/type-aliases/IMData.md | 4 +- .../types/type-aliases/IMDataEntity.md | 4 +- .../graphql/types/type-aliases/KVStoreData.md | 4 +- .../types/type-aliases/PaymentStatistics.md | 4 +- .../graphql/types/type-aliases/PayoutData.md | 4 +- .../type-aliases/RewardAddedEventData.md | 4 +- .../graphql/types/type-aliases/StatusEvent.md | 4 +- .../types/type-aliases/TaskStatistics.md | 4 +- .../types/type-aliases/WorkerStatistics.md | 4 +- docs/sdk/typescript/interfaces/README.md | 2 +- .../interfaces/interfaces/IEscrowConfig.md | 18 +- .../interfaces/interfaces/IEscrowsFilter.md | 26 +- .../interfaces/IHMTHoldersParams.md | 10 +- .../interfaces/interfaces/IKVStore.md | 6 +- .../interfaces/interfaces/IKeyPair.md | 10 +- .../interfaces/interfaces/ILeader.md | 50 ++-- .../interfaces/interfaces/ILeaderSubgraph.md | 68 ++--- .../interfaces/interfaces/ILeadersFilter.md | 6 +- .../interfaces/interfaces/IOperator.md | 14 +- .../interfaces/IOperatorSubgraph.md | 14 +- .../interfaces/interfaces/IPagination.md | 8 +- .../interfaces/interfaces/IPayoutFilter.md | 10 +- .../interfaces/IReputationNetwork.md | 8 +- .../interfaces/IReputationNetworkSubgraph.md | 8 +- .../interfaces/interfaces/IReward.md | 6 +- .../interfaces/IStatisticsFilter.md | 12 +- .../interfaces/interfaces/ITransaction.md | 24 +- .../interfaces/ITransactionsFilter.md | 22 +- .../interfaces/InternalTransaction.md | 16 +- docs/sdk/typescript/kvstore/README.md | 2 +- .../kvstore/classes/KVStoreClient.md | 64 +++-- .../kvstore/classes/KVStoreUtils.md | 50 ++-- docs/sdk/typescript/modules.md | 2 +- docs/sdk/typescript/operator/README.md | 2 +- .../operator/classes/OperatorUtils.md | 42 +++- docs/sdk/typescript/staking/README.md | 2 +- .../staking/classes/StakingClient.md | 86 ++++--- docs/sdk/typescript/statistics/README.md | 2 +- .../statistics/classes/StatisticsClient.md | 44 ++-- docs/sdk/typescript/storage/README.md | 2 +- .../storage/classes/StorageClient.md | 50 ++-- docs/sdk/typescript/transaction/README.md | 2 +- .../transaction/classes/TransactionUtils.md | 18 +- docs/sdk/typescript/types/README.md | 2 +- .../types/enumerations/EscrowStatus.md | 14 +- .../types/type-aliases/EscrowCancel.md | 4 +- .../types/type-aliases/EscrowWithdraw.md | 4 +- .../types/type-aliases/NetworkData.md | 4 +- .../types/type-aliases/StorageCredentials.md | 4 +- .../types/type-aliases/StorageParams.md | 4 +- .../types/type-aliases/UploadFile.md | 4 +- .../core/.openzeppelin/avalanche-fuji.json | 149 +++++++++++ packages/core/.openzeppelin/bsc.json | 149 +++++++++++ packages/core/.openzeppelin/mainnet.json | 149 +++++++++++ packages/core/.openzeppelin/polygon.json | 149 +++++++++++ packages/core/.openzeppelin/unknown-1287.json | 149 +++++++++++ packages/core/.openzeppelin/unknown-195.json | 149 +++++++++++ .../human_protocol_sdk/constants.py | 24 +- .../human-protocol-sdk/src/constants.ts | 24 +- .../sdk/typescript/subgraph/config/bsc.json | 4 +- .../typescript/subgraph/config/ethereum.json | 4 +- .../sdk/typescript/subgraph/config/fuji.json | 4 +- .../subgraph/config/moonbase-alpha.json | 4 +- .../typescript/subgraph/config/polygon.json | 4 +- .../subgraph/config/xlayer-testnet.json | 4 +- 93 files changed, 1726 insertions(+), 544 deletions(-) diff --git a/docs/sdk/python/human_protocol_sdk.encryption.encryption.md b/docs/sdk/python/human_protocol_sdk.encryption.encryption.md index 10c2e82ebc..3e62e0dcdc 100644 --- a/docs/sdk/python/human_protocol_sdk.encryption.encryption.md +++ b/docs/sdk/python/human_protocol_sdk.encryption.encryption.md @@ -60,7 +60,7 @@ Decrypts a message using the private key. * **message** (`str`) – Armored message to decrypt * **public_key** (`Optional`[`str`]) – Armored public key used for signature verification. Defaults to None. * **Return type:** - `str` + `bytes` * **Returns:** Decrypted message * **Example:** @@ -94,7 +94,7 @@ Decrypts a message using the private key. Signs a message using the private key. * **Parameters:** - **message** (`str`) – Message to sign + **message** (`Union`[`str`, `bytes`]) – Message to sign * **Return type:** `str` * **Returns:** @@ -130,7 +130,7 @@ Signs a message using the private key. Signs and encrypts a message using the private key and recipient’s public keys. * **Parameters:** - * **message** (`str`) – Message to sign and encrypt + * **message** (`Union`[`str`, `bytes`]) – Message to sign and encrypt * **public_keys** (`List`[`str`]) – List of armored public keys of the recipients * **Return type:** `str` diff --git a/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md b/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md index 24c72c6fea..a04ced3502 100644 --- a/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md +++ b/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md @@ -17,11 +17,11 @@ print( ## Module -### *class* human_protocol_sdk.operator.operator_utils.LeaderData(chain_id, id, address, amount_staked, amount_allocated, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, reputation_networks=None) +### *class* human_protocol_sdk.operator.operator_utils.LeaderData(chain_id, id, address, amount_staked, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, website=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, reputation_networks=None) Bases: `object` -#### \_\_init_\_(chain_id, id, address, amount_staked, amount_allocated, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, reputation_networks=None) +#### \_\_init_\_(chain_id, id, address, amount_staked, amount_locked, locked_until_timestamp, amount_withdrawn, amount_slashed, reward, amount_jobs_processed, role=None, fee=None, public_key=None, webhook_url=None, website=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, reputation_networks=None) Initializes an LeaderData instance. @@ -30,7 +30,6 @@ Initializes an LeaderData instance. * **id** (`str`) – Identifier * **address** (`str`) – Address * **amount_staked** (`int`) – Amount staked - * **amount_allocated** (`int`) – Amount allocated * **amount_locked** (`int`) – Amount locked * **locked_until_timestamp** (`int`) – Locked until timestamp * **amount_withdrawn** (`int`) – Amount withdrawn @@ -41,6 +40,7 @@ Initializes an LeaderData instance. * **fee** (`Optional`[`int`]) – Fee * **public_key** (`Optional`[`str`]) – Public key * **webhook_url** (`Optional`[`str`]) – Webhook url + * **website** (`Optional`[`str`]) – Website url * **url** (`Optional`[`str`]) – Url * **job_types** (`Optional`[`List`[`str`]]) – Job types * **registration_needed** (`Optional`[`bool`]) – True diff --git a/docs/sdk/typescript/README.md b/docs/sdk/typescript/README.md index 43efb8cc51..7644187242 100644 --- a/docs/sdk/typescript/README.md +++ b/docs/sdk/typescript/README.md @@ -1,4 +1,4 @@ -**@human-protocol/sdk** • [**Docs**](modules.md) +**@human-protocol/sdk** *** diff --git a/docs/sdk/typescript/base/README.md b/docs/sdk/typescript/base/README.md index 2eab692472..6cf08fb2ef 100644 --- a/docs/sdk/typescript/base/README.md +++ b/docs/sdk/typescript/base/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/base/classes/BaseEthersClient.md b/docs/sdk/typescript/base/classes/BaseEthersClient.md index 025f3ee132..5c8aea4f73 100644 --- a/docs/sdk/typescript/base/classes/BaseEthersClient.md +++ b/docs/sdk/typescript/base/classes/BaseEthersClient.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -26,11 +26,15 @@ This class is used as a base class for other clients making on-chain calls. #### Parameters -• **runner**: `ContractRunner` +##### runner + +`ContractRunner` The Signer or Provider object to interact with the Ethereum network -• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) +##### networkData + +[`NetworkData`](../../types/type-aliases/NetworkData.md) The network information required to connect to the contracts @@ -40,7 +44,7 @@ The network information required to connect to the contracts #### Defined in -[base.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L20) +[base.ts:20](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L20) ## Properties @@ -50,7 +54,7 @@ The network information required to connect to the contracts #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -60,4 +64,4 @@ The network information required to connect to the contracts #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) diff --git a/docs/sdk/typescript/encryption/README.md b/docs/sdk/typescript/encryption/README.md index cd0a892bdb..428b9d1e11 100644 --- a/docs/sdk/typescript/encryption/README.md +++ b/docs/sdk/typescript/encryption/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/encryption/classes/Encryption.md b/docs/sdk/typescript/encryption/classes/Encryption.md index b15ad69cbc..4f001979e7 100644 --- a/docs/sdk/typescript/encryption/classes/Encryption.md +++ b/docs/sdk/typescript/encryption/classes/Encryption.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -55,7 +55,9 @@ Constructor for the Encryption class. #### Parameters -• **privateKey**: `PrivateKey` +##### privateKey + +`PrivateKey` The private key. @@ -65,29 +67,33 @@ The private key. #### Defined in -[encryption.ts:52](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L52) +[encryption.ts:62](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L62) ## Methods ### decrypt() -> **decrypt**(`message`, `publicKey`?): `Promise`\<`string`\> +> **decrypt**(`message`, `publicKey`?): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\> This function decrypts messages using the private key. In addition, the public key can be added for signature verification. #### Parameters -• **message**: `string` +##### message + +`string` Message to decrypt. -• **publicKey?**: `string` +##### publicKey? + +`string` Public key used to verify signature if needed. This is optional. #### Returns -`Promise`\<`string`\> +`Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\> Message decrypted. @@ -117,7 +123,7 @@ const resultMessage = await encription.decrypt('message'); #### Defined in -[encryption.ts:179](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L179) +[encryption.ts:190](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L190) *** @@ -129,7 +135,9 @@ This function signs a message using the private key used to initialize the clien #### Parameters -• **message**: `string` +##### message + +`string` Message to sign. @@ -153,7 +161,7 @@ const resultMessage = await encription.sign('message'); #### Defined in -[encryption.ts:216](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L216) +[encryption.ts:247](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L247) *** @@ -165,11 +173,15 @@ This function signs and encrypts a message using the private key used to initial #### Parameters -• **message**: `string` +##### message + +`MessageDataType` Message to sign and encrypt. -• **publicKeys**: `string`[] +##### publicKeys + +`string`[] Array of public keys to use for encryption. @@ -218,7 +230,7 @@ const resultMessage = await encription.signAndEncrypt('message', publicKeys); #### Defined in -[encryption.ts:128](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L128) +[encryption.ts:138](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L138) *** @@ -230,11 +242,15 @@ Builds an Encryption instance by decrypting the private key from an encrypted pr #### Parameters -• **privateKeyArmored**: `string` +##### privateKeyArmored + +`string` The encrypted private key in armored format. -• **passphrase?**: `string` +##### passphrase? + +`string` Optional: The passphrase for the private key. @@ -246,4 +262,4 @@ Optional: The passphrase for the private key. #### Defined in -[encryption.ts:63](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L63) +[encryption.ts:73](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L73) diff --git a/docs/sdk/typescript/encryption/classes/EncryptionUtils.md b/docs/sdk/typescript/encryption/classes/EncryptionUtils.md index a42bc83af4..87c09e196a 100644 --- a/docs/sdk/typescript/encryption/classes/EncryptionUtils.md +++ b/docs/sdk/typescript/encryption/classes/EncryptionUtils.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -50,11 +50,15 @@ This function encrypts a message using the specified public keys. #### Parameters -• **message**: `string` +##### message + +`MessageDataType` Message to encrypt. -• **publicKeys**: `string`[] +##### publicKeys + +`string`[] Array of public keys to use for encryption. @@ -99,7 +103,7 @@ const result = await EncriptionUtils.encrypt('message', publicKeys); #### Defined in -[encryption.ts:421](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L421) +[encryption.ts:452](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L452) *** @@ -111,15 +115,21 @@ This function generates a key pair for encryption and decryption. #### Parameters -• **name**: `string` +##### name + +`string` Name for the key pair. -• **email**: `string` +##### email + +`string` Email for the key pair. -• **passphrase**: `string` = `''` +##### passphrase + +`string` = `''` Passphrase to encrypt the private key. Optional. @@ -154,7 +164,7 @@ const result = await EncriptionUtils.generateKeyPair(name, email, passphrase); #### Defined in -[encryption.ts:359](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L359) +[encryption.ts:390](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L390) *** @@ -166,7 +176,9 @@ This function gets signed data from a signed message. #### Parameters -• **message**: `string` +##### message + +`string` Message. @@ -186,7 +198,7 @@ const signedData = await EncriptionUtils.getSignedData('message'); #### Defined in -[encryption.ts:316](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L316) +[encryption.ts:347](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L347) *** @@ -198,7 +210,9 @@ Verifies if a message appears to be encrypted with OpenPGP. #### Parameters -• **message**: `string` +##### message + +`string` Message to verify. @@ -234,7 +248,7 @@ if (isEncrypted) { #### Defined in -[encryption.ts:470](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L470) +[encryption.ts:502](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L502) *** @@ -246,11 +260,15 @@ This function verifies the signature of a signed message using the public key. #### Parameters -• **message**: `string` +##### message + +`string` Message to verify. -• **publicKey**: `string` +##### publicKey + +`string` Public key to verify that the message was sign by a specific source. @@ -282,4 +300,4 @@ const result = await EncriptionUtils.verify('message', publicKey); #### Defined in -[encryption.ts:283](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L283) +[encryption.ts:314](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L314) diff --git a/docs/sdk/typescript/enums/README.md b/docs/sdk/typescript/enums/README.md index 3aad554085..ea796f9dd0 100644 --- a/docs/sdk/typescript/enums/README.md +++ b/docs/sdk/typescript/enums/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/enums/enumerations/ChainId.md b/docs/sdk/typescript/enums/enumerations/ChainId.md index 9ddfef832d..5581f1e887 100644 --- a/docs/sdk/typescript/enums/enumerations/ChainId.md +++ b/docs/sdk/typescript/enums/enumerations/ChainId.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[enums.ts:2](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L2) +[enums.ts:2](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L2) *** @@ -24,7 +24,7 @@ #### Defined in -[enums.ts:15](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L15) +[enums.ts:15](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L15) *** @@ -34,7 +34,7 @@ #### Defined in -[enums.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L14) +[enums.ts:14](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L14) *** @@ -44,7 +44,7 @@ #### Defined in -[enums.ts:7](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L7) +[enums.ts:7](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L7) *** @@ -54,7 +54,7 @@ #### Defined in -[enums.ts:8](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L8) +[enums.ts:8](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L8) *** @@ -64,7 +64,7 @@ #### Defined in -[enums.ts:16](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L16) +[enums.ts:16](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L16) *** @@ -74,7 +74,7 @@ #### Defined in -[enums.ts:17](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L17) +[enums.ts:17](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L17) *** @@ -84,7 +84,7 @@ #### Defined in -[enums.ts:5](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L5) +[enums.ts:5](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L5) *** @@ -94,7 +94,7 @@ #### Defined in -[enums.ts:19](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L19) +[enums.ts:19](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L19) *** @@ -104,7 +104,7 @@ #### Defined in -[enums.ts:3](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L3) +[enums.ts:3](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L3) *** @@ -114,7 +114,7 @@ #### Defined in -[enums.ts:13](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L13) +[enums.ts:13](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L13) *** @@ -124,7 +124,7 @@ #### Defined in -[enums.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L12) +[enums.ts:12](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L12) *** @@ -134,7 +134,7 @@ #### Defined in -[enums.ts:9](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L9) +[enums.ts:9](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L9) *** @@ -144,7 +144,7 @@ #### Defined in -[enums.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L11) +[enums.ts:11](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L11) *** @@ -154,7 +154,7 @@ #### Defined in -[enums.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L10) +[enums.ts:10](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L10) *** @@ -164,7 +164,7 @@ #### Defined in -[enums.ts:4](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L4) +[enums.ts:4](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L4) *** @@ -174,7 +174,7 @@ #### Defined in -[enums.ts:6](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L6) +[enums.ts:6](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L6) *** @@ -184,7 +184,7 @@ #### Defined in -[enums.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L20) +[enums.ts:20](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L20) *** @@ -194,4 +194,4 @@ #### Defined in -[enums.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L18) +[enums.ts:18](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L18) diff --git a/docs/sdk/typescript/enums/enumerations/OrderDirection.md b/docs/sdk/typescript/enums/enumerations/OrderDirection.md index eb4b89ac14..871fd34269 100644 --- a/docs/sdk/typescript/enums/enumerations/OrderDirection.md +++ b/docs/sdk/typescript/enums/enumerations/OrderDirection.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[enums.ts:24](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L24) +[enums.ts:24](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L24) *** @@ -24,4 +24,4 @@ #### Defined in -[enums.ts:25](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L25) +[enums.ts:25](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L25) diff --git a/docs/sdk/typescript/escrow/README.md b/docs/sdk/typescript/escrow/README.md index b22561f928..bace86f7e8 100644 --- a/docs/sdk/typescript/escrow/README.md +++ b/docs/sdk/typescript/escrow/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/escrow/classes/EscrowClient.md b/docs/sdk/typescript/escrow/classes/EscrowClient.md index 24cab9fbfc..dbaf2fb297 100644 --- a/docs/sdk/typescript/escrow/classes/EscrowClient.md +++ b/docs/sdk/typescript/escrow/classes/EscrowClient.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -88,11 +88,15 @@ const escrowClient = await EscrowClient.build(provider); #### Parameters -• **runner**: `ContractRunner` +##### runner + +`ContractRunner` The Runner object to interact with the Ethereum network -• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) +##### networkData + +[`NetworkData`](../../types/type-aliases/NetworkData.md) The network information required to connect to the Escrow contract @@ -106,7 +110,7 @@ The network information required to connect to the Escrow contract #### Defined in -[escrow.ts:136](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L136) +[escrow.ts:136](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L136) ## Properties @@ -120,7 +124,7 @@ The network information required to connect to the Escrow contract #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -134,7 +138,7 @@ The network information required to connect to the Escrow contract #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) ## Methods @@ -146,15 +150,21 @@ This function adds an array of addresses to the trusted handlers list. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. -• **trustedHandlers**: `string`[] +##### trustedHandlers + +`string`[] Array of addresses of trusted handlers to add. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -185,7 +195,7 @@ await escrowClient.addTrustedHandlers('0x62dD51230A30401C455c8398d06F85e4EaB6309 #### Defined in -[escrow.ts:802](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L802) +[escrow.ts:802](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L802) *** @@ -197,31 +207,45 @@ This function pays out the amounts specified to the workers and sets the URL of #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Escrow address to payout. -• **recipients**: `string`[] +##### recipients + +`string`[] Array of recipient addresses. -• **amounts**: `bigint`[] +##### amounts + +`bigint`[] Array of amounts the recipients will receive. -• **finalResultsUrl**: `string` +##### finalResultsUrl + +`string` Final results file url. -• **finalResultsHash**: `string` +##### finalResultsHash + +`string` Final results file hash. -• **forceComplete**: `boolean` = `false` +##### forceComplete + +`boolean` = `false` Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -256,7 +280,7 @@ await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', reci #### Defined in -[escrow.ts:595](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L595) +[escrow.ts:595](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L595) *** @@ -268,11 +292,15 @@ This function cancels the specified escrow and sends the balance to the canceler #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow to cancel. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -302,7 +330,7 @@ await escrowClient.cancel('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); #### Defined in -[escrow.ts:716](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L716) +[escrow.ts:716](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L716) *** @@ -314,11 +342,15 @@ This function sets the status of an escrow to completed. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -348,7 +380,7 @@ await escrowClient.complete('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); #### Defined in -[escrow.ts:536](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L536) +[escrow.ts:536](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L536) *** @@ -360,19 +392,27 @@ This function creates an escrow contract that uses the token passed to pay oracl #### Parameters -• **tokenAddress**: `string` +##### tokenAddress + +`string` Token address to use for pay outs. -• **trustedHandlers**: `string`[] +##### trustedHandlers + +`string`[] Array of addresses that can perform actions on the contract. -• **jobRequesterId**: `string` +##### jobRequesterId + +`string` Job Requester Id -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -405,7 +445,7 @@ const escrowAddress = await escrowClient.createEscrow(tokenAddress, trustedHandl #### Defined in -[escrow.ts:216](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L216) +[escrow.ts:216](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L216) *** @@ -417,15 +457,21 @@ This function adds funds of the chosen token to the escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow to fund. -• **amount**: `bigint` +##### amount + +`bigint` Amount to be added as funds. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -454,7 +500,7 @@ await escrowClient.fund('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); #### Defined in -[escrow.ts:407](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L407) +[escrow.ts:407](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L407) *** @@ -466,7 +512,9 @@ This function returns the balance for a specified escrow address. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -492,7 +540,7 @@ const balance = await escrowClient.getBalance('0x62dD51230A30401C455c8398d06F85e #### Defined in -[escrow.ts:950](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L950) +[escrow.ts:950](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L950) *** @@ -504,7 +552,9 @@ This function returns the exchange oracle address for a given escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -530,7 +580,7 @@ const oracleAddress = await escrowClient.getExchangeOracleAddress('0x62dD51230A3 #### Defined in -[escrow.ts:1336](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1336) +[escrow.ts:1336](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1336) *** @@ -542,7 +592,9 @@ This function returns the escrow factory address for a given escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -568,7 +620,7 @@ const factoryAddress = await escrowClient.getFactoryAddress('0x62dD51230A30401C4 #### Defined in -[escrow.ts:1374](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1374) +[escrow.ts:1374](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1374) *** @@ -580,7 +632,9 @@ This function returns the intermediate results file URL. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -606,7 +660,7 @@ const intemediateResultsUrl = await escrowClient.getIntermediateResultsUrl('0x62 #### Defined in -[escrow.ts:1108](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1108) +[escrow.ts:1108](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1108) *** @@ -618,7 +672,9 @@ This function returns the job launcher address for a given escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -644,7 +700,7 @@ const jobLauncherAddress = await escrowClient.getJobLauncherAddress('0x62dD51230 #### Defined in -[escrow.ts:1260](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1260) +[escrow.ts:1260](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1260) *** @@ -656,7 +712,9 @@ This function returns the manifest file hash. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -682,7 +740,7 @@ const manifestHash = await escrowClient.getManifestHash('0x62dD51230A30401C455c8 #### Defined in -[escrow.ts:994](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L994) +[escrow.ts:994](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L994) *** @@ -694,7 +752,9 @@ This function returns the manifest file URL. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -720,7 +780,7 @@ const manifestUrl = await escrowClient.getManifestUrl('0x62dD51230A30401C455c839 #### Defined in -[escrow.ts:1032](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1032) +[escrow.ts:1032](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1032) *** @@ -732,7 +792,9 @@ This function returns the recording oracle address for a given escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -758,7 +820,7 @@ const oracleAddress = await escrowClient.getRecordingOracleAddress('0x62dD51230A #### Defined in -[escrow.ts:1222](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1222) +[escrow.ts:1222](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1222) *** @@ -770,7 +832,9 @@ This function returns the reputation oracle address for a given escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -796,7 +860,7 @@ const oracleAddress = await escrowClient.getReputationOracleAddress('0x62dD51230 #### Defined in -[escrow.ts:1298](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1298) +[escrow.ts:1298](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1298) *** @@ -808,7 +872,9 @@ This function returns the results file URL. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -834,7 +900,7 @@ const resultsUrl = await escrowClient.getResultsUrl('0x62dD51230A30401C455c8398d #### Defined in -[escrow.ts:1070](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1070) +[escrow.ts:1070](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1070) *** @@ -846,7 +912,9 @@ This function returns the current status of the escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -872,7 +940,7 @@ const status = await escrowClient.getStatus('0x62dD51230A30401C455c8398d06F85e4E #### Defined in -[escrow.ts:1184](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1184) +[escrow.ts:1184](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1184) *** @@ -884,7 +952,9 @@ This function returns the token address used for funding the escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. @@ -910,7 +980,7 @@ const tokenAddress = await escrowClient.getTokenAddress('0x62dD51230A30401C455c8 #### Defined in -[escrow.ts:1146](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1146) +[escrow.ts:1146](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1146) *** @@ -922,15 +992,21 @@ This function sets up the parameters of the escrow. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow to set up. -• **escrowConfig**: [`IEscrowConfig`](../../interfaces/interfaces/IEscrowConfig.md) +##### escrowConfig + +[`IEscrowConfig`](../../interfaces/interfaces/IEscrowConfig.md) Escrow configuration parameters. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -971,7 +1047,7 @@ await escrowClient.setup(escrowAddress, escrowConfig); #### Defined in -[escrow.ts:297](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L297) +[escrow.ts:297](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L297) *** @@ -983,19 +1059,27 @@ This function stores the results url and hash. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow. -• **url**: `string` +##### url + +`string` Results file url. -• **hash**: `string` +##### hash + +`string` Results file hash. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -1025,7 +1109,7 @@ await storeResults.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'h #### Defined in -[escrow.ts:472](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L472) +[escrow.ts:472](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L472) *** @@ -1037,15 +1121,21 @@ This function withdraws additional tokens in the escrow to the canceler. #### Parameters -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow to withdraw. -• **tokenAddress**: `string` +##### tokenAddress + +`string` Address of the token to withdraw. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -1078,7 +1168,7 @@ await escrowClient.withdraw( #### Defined in -[escrow.ts:868](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L868) +[escrow.ts:868](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L868) *** @@ -1090,7 +1180,9 @@ Creates an instance of EscrowClient from a Runner. #### Parameters -• **runner**: `ContractRunner` +##### runner + +`ContractRunner` The Runner object to interact with the Ethereum network @@ -1110,4 +1202,4 @@ Thrown if the network's chainId is not supported #### Defined in -[escrow.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L154) +[escrow.ts:154](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L154) diff --git a/docs/sdk/typescript/escrow/classes/EscrowUtils.md b/docs/sdk/typescript/escrow/classes/EscrowUtils.md index 4cec75c0b5..88fbaaeafd 100644 --- a/docs/sdk/typescript/escrow/classes/EscrowUtils.md +++ b/docs/sdk/typescript/escrow/classes/EscrowUtils.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -105,11 +105,15 @@ type EscrowData = { #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) Network in which the escrow has been deployed -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow @@ -129,7 +133,7 @@ const escrowData = new EscrowUtils.getEscrow(ChainId.POLYGON_AMOY, "0x1234567890 #### Defined in -[escrow.ts:1656](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1656) +[escrow.ts:1656](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1656) *** @@ -224,7 +228,9 @@ type EscrowData = { #### Parameters -• **filter**: [`IEscrowsFilter`](../../interfaces/interfaces/IEscrowsFilter.md) +##### filter + +[`IEscrowsFilter`](../../interfaces/interfaces/IEscrowsFilter.md) Filter parameters. @@ -250,7 +256,7 @@ const escrowDatas = await EscrowUtils.getEscrows(filters); #### Defined in -[escrow.ts:1530](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1530) +[escrow.ts:1530](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1530) *** @@ -305,35 +311,51 @@ type Status = { #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) List of network IDs to query for status events. -• **statuses?**: [`EscrowStatus`](../../types/enumerations/EscrowStatus.md)[] +##### statuses? + +[`EscrowStatus`](../../types/enumerations/EscrowStatus.md)[] Optional array of statuses to query for. If not provided, queries for all statuses. -• **from?**: `Date` +##### from? + +`Date` Optional start date to filter events. -• **to?**: `Date` +##### to? + +`Date` Optional end date to filter events. -• **launcher?**: `string` +##### launcher? + +`string` Optional launcher address to filter events. Must be a valid Ethereum address. -• **first?**: `number` +##### first? + +`number` Optional number of transactions per page. Default is 10. -• **skip?**: `number` +##### skip? + +`number` Optional number of transactions to skip. Default is 0. -• **orderDirection?**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) +##### orderDirection? + +[`OrderDirection`](../../enums/enumerations/OrderDirection.md) Optional order of the results. Default is DESC. @@ -363,4 +385,4 @@ import { ChainId, EscrowUtils, EscrowStatus } from '@human-protocol/sdk'; #### Defined in -[escrow.ts:1754](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1754) +[escrow.ts:1754](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1754) diff --git a/docs/sdk/typescript/graphql/types/README.md b/docs/sdk/typescript/graphql/types/README.md index 03598a4471..ae586ff40f 100644 --- a/docs/sdk/typescript/graphql/types/README.md +++ b/docs/sdk/typescript/graphql/types/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md index ce76bb4093..43f9c26d3d 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyEscrowData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -36,4 +36,4 @@ ## Defined in -[graphql/types.ts:83](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L83) +[graphql/types.ts:83](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L83) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md index 87bc73cdc7..a6829736ec 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyHMTData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -32,4 +32,4 @@ ## Defined in -[graphql/types.ts:127](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L127) +[graphql/types.ts:127](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L127) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md index c0ced96a7b..58b2ee2db4 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyPaymentData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -28,4 +28,4 @@ ## Defined in -[graphql/types.ts:106](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L106) +[graphql/types.ts:106](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L106) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md index d98df89ab9..251d9d7115 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyTaskData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -24,4 +24,4 @@ ## Defined in -[graphql/types.ts:148](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L148) +[graphql/types.ts:148](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L148) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md b/docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md index fbc5f60316..afbcc9f9e8 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/DailyWorkerData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -20,4 +20,4 @@ ## Defined in -[graphql/types.ts:97](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L97) +[graphql/types.ts:97](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L97) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md index 9d06032f8d..8ec17d1f52 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -88,4 +88,4 @@ ## Defined in -[graphql/types.ts:3](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L3) +[graphql/types.ts:3](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L3) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md index d8181e5caf..01132636c1 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatistics.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -20,4 +20,4 @@ ## Defined in -[graphql/types.ts:92](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L92) +[graphql/types.ts:92](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L92) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md index 0e41420d7b..8ea7e3d692 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -52,4 +52,4 @@ ## Defined in -[graphql/types.ts:42](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L42) +[graphql/types.ts:42](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L42) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md b/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md index 0dc23fc21b..4a1822bd86 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -84,4 +84,4 @@ ## Defined in -[graphql/types.ts:55](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L55) +[graphql/types.ts:55](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L55) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md index c670fa9a86..efc6ec65ea 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolder.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -20,4 +20,4 @@ ## Defined in -[graphql/types.ts:122](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L122) +[graphql/types.ts:122](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L122) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md index d4bbc27612..bf6ec36712 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -20,4 +20,4 @@ ## Defined in -[graphql/types.ts:117](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L117) +[graphql/types.ts:117](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L117) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md index 6b3c091d07..8b7be95e98 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatistics.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -24,4 +24,4 @@ ## Defined in -[graphql/types.ts:135](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L135) +[graphql/types.ts:135](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L135) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md index 294b5b1644..0fff5c8c8a 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -36,4 +36,4 @@ ## Defined in -[graphql/types.ts:33](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L33) +[graphql/types.ts:33](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L33) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/IMData.md b/docs/sdk/typescript/graphql/types/type-aliases/IMData.md index a9a537a0fd..9c8eb7c020 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/IMData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/IMData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -10,4 +10,4 @@ ## Defined in -[graphql/types.ts:146](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L146) +[graphql/types.ts:146](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L146) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md b/docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md index 5ee027f977..b4a5fa2959 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/IMDataEntity.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -20,4 +20,4 @@ ## Defined in -[graphql/types.ts:141](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L141) +[graphql/types.ts:141](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L141) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md b/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md index acb5759c07..95e4ff56ac 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -36,4 +36,4 @@ ## Defined in -[graphql/types.ts:165](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L165) +[graphql/types.ts:165](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L165) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md index 481d9804f2..667f5a8eb1 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/PaymentStatistics.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -16,4 +16,4 @@ ## Defined in -[graphql/types.ts:113](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L113) +[graphql/types.ts:113](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L113) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md b/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md index 09233b84e7..b920f462ed 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -32,4 +32,4 @@ ## Defined in -[graphql/types.ts:25](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L25) +[graphql/types.ts:25](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L25) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md b/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md index ecaf6b5230..8171093bcb 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -28,4 +28,4 @@ ## Defined in -[graphql/types.ts:76](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L76) +[graphql/types.ts:76](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L76) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md b/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md index 8e61dd6cf1..821b77a2df 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -28,4 +28,4 @@ ## Defined in -[graphql/types.ts:158](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L158) +[graphql/types.ts:158](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L158) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md index d0b80fa355..d6af185f10 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/TaskStatistics.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -16,4 +16,4 @@ ## Defined in -[graphql/types.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L154) +[graphql/types.ts:154](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L154) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md b/docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md index f2531743df..e21126a847 100644 --- a/docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md +++ b/docs/sdk/typescript/graphql/types/type-aliases/WorkerStatistics.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../../README.md) • **Docs** +[**@human-protocol/sdk**](../../../README.md) *** @@ -16,4 +16,4 @@ ## Defined in -[graphql/types.ts:102](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L102) +[graphql/types.ts:102](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L102) diff --git a/docs/sdk/typescript/interfaces/README.md b/docs/sdk/typescript/interfaces/README.md index d499b126ba..02fcc52d30 100644 --- a/docs/sdk/typescript/interfaces/README.md +++ b/docs/sdk/typescript/interfaces/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md index c1ef061547..758b2f1289 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md +++ b/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:81](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L81) +[interfaces.ts:82](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L82) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:84](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L84) +[interfaces.ts:85](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L85) *** @@ -34,7 +34,7 @@ #### Defined in -[interfaces.ts:86](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L86) +[interfaces.ts:87](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L87) *** @@ -44,7 +44,7 @@ #### Defined in -[interfaces.ts:85](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L85) +[interfaces.ts:86](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L86) *** @@ -54,7 +54,7 @@ #### Defined in -[interfaces.ts:79](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L79) +[interfaces.ts:80](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L80) *** @@ -64,7 +64,7 @@ #### Defined in -[interfaces.ts:82](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L82) +[interfaces.ts:83](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L83) *** @@ -74,7 +74,7 @@ #### Defined in -[interfaces.ts:80](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L80) +[interfaces.ts:81](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L81) *** @@ -84,4 +84,4 @@ #### Defined in -[interfaces.ts:83](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L83) +[interfaces.ts:84](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L84) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md index 508bce135a..424a2c0ef3 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md +++ b/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -18,7 +18,7 @@ #### Defined in -[interfaces.ts:75](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L75) +[interfaces.ts:76](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L76) *** @@ -28,7 +28,7 @@ #### Defined in -[interfaces.ts:70](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L70) +[interfaces.ts:71](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L71) *** @@ -42,7 +42,7 @@ #### Defined in -[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) *** @@ -52,7 +52,7 @@ #### Defined in -[interfaces.ts:73](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L73) +[interfaces.ts:74](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L74) *** @@ -62,7 +62,7 @@ #### Defined in -[interfaces.ts:71](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L71) +[interfaces.ts:72](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L72) *** @@ -72,7 +72,7 @@ #### Defined in -[interfaces.ts:67](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L67) +[interfaces.ts:68](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L68) *** @@ -86,7 +86,7 @@ #### Defined in -[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) +[interfaces.ts:155](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L155) *** @@ -96,7 +96,7 @@ #### Defined in -[interfaces.ts:69](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L69) +[interfaces.ts:70](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L70) *** @@ -106,7 +106,7 @@ #### Defined in -[interfaces.ts:68](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L68) +[interfaces.ts:69](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L69) *** @@ -120,7 +120,7 @@ #### Defined in -[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) *** @@ -130,7 +130,7 @@ #### Defined in -[interfaces.ts:72](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L72) +[interfaces.ts:73](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L73) *** @@ -140,4 +140,4 @@ #### Defined in -[interfaces.ts:74](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L74) +[interfaces.ts:75](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L75) diff --git a/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md b/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md index c9b5533d93..e3b23ff093 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md +++ b/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -18,7 +18,7 @@ #### Defined in -[interfaces.ts:102](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L102) +[interfaces.ts:103](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L103) *** @@ -32,7 +32,7 @@ #### Defined in -[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) *** @@ -46,7 +46,7 @@ #### Defined in -[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) +[interfaces.ts:155](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L155) *** @@ -60,4 +60,4 @@ #### Defined in -[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) diff --git a/docs/sdk/typescript/interfaces/interfaces/IKVStore.md b/docs/sdk/typescript/interfaces/interfaces/IKVStore.md index 377dc0e1a0..71a9267bd0 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IKVStore.md +++ b/docs/sdk/typescript/interfaces/interfaces/IKVStore.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:113](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L113) +[interfaces.ts:114](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L114) *** @@ -24,4 +24,4 @@ #### Defined in -[interfaces.ts:114](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L114) +[interfaces.ts:115](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L115) diff --git a/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md b/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md index 366d9b9dcc..a3a532a35c 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md +++ b/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:92](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L92) +[interfaces.ts:93](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L93) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:90](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L90) +[interfaces.ts:91](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L91) *** @@ -34,7 +34,7 @@ #### Defined in -[interfaces.ts:91](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L91) +[interfaces.ts:92](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L92) *** @@ -44,4 +44,4 @@ #### Defined in -[interfaces.ts:93](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L93) +[interfaces.ts:94](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L94) diff --git a/docs/sdk/typescript/interfaces/interfaces/ILeader.md b/docs/sdk/typescript/interfaces/interfaces/ILeader.md index b3664a5ab8..f980341d8f 100644 --- a/docs/sdk/typescript/interfaces/interfaces/ILeader.md +++ b/docs/sdk/typescript/interfaces/interfaces/ILeader.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L12) +[interfaces.ts:12](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L12) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:19](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L19) +[interfaces.ts:19](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L19) *** @@ -34,7 +34,7 @@ #### Defined in -[interfaces.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L14) +[interfaces.ts:14](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L14) *** @@ -44,7 +44,7 @@ #### Defined in -[interfaces.ts:17](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L17) +[interfaces.ts:17](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L17) *** @@ -54,7 +54,7 @@ #### Defined in -[interfaces.ts:13](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L13) +[interfaces.ts:13](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L13) *** @@ -64,7 +64,7 @@ #### Defined in -[interfaces.ts:16](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L16) +[interfaces.ts:16](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L16) *** @@ -74,7 +74,7 @@ #### Defined in -[interfaces.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L11) +[interfaces.ts:11](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L11) *** @@ -84,7 +84,7 @@ #### Defined in -[interfaces.ts:21](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L21) +[interfaces.ts:21](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L21) *** @@ -94,7 +94,7 @@ #### Defined in -[interfaces.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L10) +[interfaces.ts:10](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L10) *** @@ -104,7 +104,7 @@ #### Defined in -[interfaces.ts:25](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L25) +[interfaces.ts:26](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L26) *** @@ -114,7 +114,7 @@ #### Defined in -[interfaces.ts:15](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L15) +[interfaces.ts:15](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L15) *** @@ -124,7 +124,7 @@ #### Defined in -[interfaces.ts:22](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L22) +[interfaces.ts:22](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L22) *** @@ -134,7 +134,7 @@ #### Defined in -[interfaces.ts:27](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L27) +[interfaces.ts:28](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L28) *** @@ -144,7 +144,7 @@ #### Defined in -[interfaces.ts:26](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L26) +[interfaces.ts:27](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L27) *** @@ -154,7 +154,7 @@ #### Defined in -[interfaces.ts:28](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L28) +[interfaces.ts:29](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L29) *** @@ -164,7 +164,7 @@ #### Defined in -[interfaces.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L18) +[interfaces.ts:18](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L18) *** @@ -174,7 +174,7 @@ #### Defined in -[interfaces.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L20) +[interfaces.ts:20](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L20) *** @@ -184,7 +184,7 @@ #### Defined in -[interfaces.ts:24](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L24) +[interfaces.ts:25](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L25) *** @@ -194,4 +194,14 @@ #### Defined in -[interfaces.ts:23](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L23) +[interfaces.ts:23](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L23) + +*** + +### website? + +> `optional` **website**: `string` + +#### Defined in + +[interfaces.ts:24](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L24) diff --git a/docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md b/docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md index 674be64789..43146503cd 100644 --- a/docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md +++ b/docs/sdk/typescript/interfaces/interfaces/ILeaderSubgraph.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -8,7 +8,7 @@ ## Extends -- `Omit`\<[`ILeader`](ILeader.md), `"jobTypes"` \| `"reputationNetworks"`\> +- `Omit`\<[`ILeader`](ILeader.md), `"jobTypes"` \| `"reputationNetworks"` \| `"chainId"`\> ## Properties @@ -22,7 +22,7 @@ #### Defined in -[interfaces.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L12) +[interfaces.ts:12](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L12) *** @@ -36,7 +36,7 @@ #### Defined in -[interfaces.ts:19](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L19) +[interfaces.ts:19](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L19) *** @@ -50,7 +50,7 @@ #### Defined in -[interfaces.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L14) +[interfaces.ts:14](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L14) *** @@ -64,7 +64,7 @@ #### Defined in -[interfaces.ts:17](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L17) +[interfaces.ts:17](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L17) *** @@ -78,7 +78,7 @@ #### Defined in -[interfaces.ts:13](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L13) +[interfaces.ts:13](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L13) *** @@ -92,21 +92,7 @@ #### Defined in -[interfaces.ts:16](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L16) - -*** - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -#### Inherited from - -`Omit.chainId` - -#### Defined in - -[interfaces.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L11) +[interfaces.ts:16](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L16) *** @@ -120,7 +106,7 @@ #### Defined in -[interfaces.ts:21](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L21) +[interfaces.ts:21](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L21) *** @@ -134,7 +120,7 @@ #### Defined in -[interfaces.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L10) +[interfaces.ts:10](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L10) *** @@ -144,7 +130,7 @@ #### Defined in -[interfaces.ts:33](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L33) +[interfaces.ts:34](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L34) *** @@ -158,7 +144,7 @@ #### Defined in -[interfaces.ts:15](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L15) +[interfaces.ts:15](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L15) *** @@ -172,7 +158,7 @@ #### Defined in -[interfaces.ts:22](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L22) +[interfaces.ts:22](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L22) *** @@ -186,7 +172,7 @@ #### Defined in -[interfaces.ts:27](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L27) +[interfaces.ts:28](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L28) *** @@ -200,7 +186,7 @@ #### Defined in -[interfaces.ts:26](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L26) +[interfaces.ts:27](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L27) *** @@ -210,7 +196,7 @@ #### Defined in -[interfaces.ts:34](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L34) +[interfaces.ts:35](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L35) *** @@ -224,7 +210,7 @@ #### Defined in -[interfaces.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L18) +[interfaces.ts:18](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L18) *** @@ -238,7 +224,7 @@ #### Defined in -[interfaces.ts:20](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L20) +[interfaces.ts:20](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L20) *** @@ -252,7 +238,7 @@ #### Defined in -[interfaces.ts:24](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L24) +[interfaces.ts:25](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L25) *** @@ -266,4 +252,18 @@ #### Defined in -[interfaces.ts:23](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L23) +[interfaces.ts:23](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L23) + +*** + +### website? + +> `optional` **website**: `string` + +#### Inherited from + +`Omit.website` + +#### Defined in + +[interfaces.ts:24](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L24) diff --git a/docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md b/docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md index ff63886a6f..e81c0fd893 100644 --- a/docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md +++ b/docs/sdk/typescript/interfaces/interfaces/ILeadersFilter.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:38](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L38) +[interfaces.ts:39](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L39) *** @@ -24,4 +24,4 @@ #### Defined in -[interfaces.ts:39](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L39) +[interfaces.ts:40](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L40) diff --git a/docs/sdk/typescript/interfaces/interfaces/IOperator.md b/docs/sdk/typescript/interfaces/interfaces/IOperator.md index 4225706e07..cc6a52985e 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IOperator.md +++ b/docs/sdk/typescript/interfaces/interfaces/IOperator.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:54](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L54) +[interfaces.ts:55](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L55) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:57](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L57) +[interfaces.ts:58](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L58) *** @@ -34,7 +34,7 @@ #### Defined in -[interfaces.ts:59](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L59) +[interfaces.ts:60](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L60) *** @@ -44,7 +44,7 @@ #### Defined in -[interfaces.ts:58](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L58) +[interfaces.ts:59](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L59) *** @@ -54,7 +54,7 @@ #### Defined in -[interfaces.ts:55](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L55) +[interfaces.ts:56](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L56) *** @@ -64,4 +64,4 @@ #### Defined in -[interfaces.ts:56](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L56) +[interfaces.ts:57](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L57) diff --git a/docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md b/docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md index 1d4de67f0f..664a83421e 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md +++ b/docs/sdk/typescript/interfaces/interfaces/IOperatorSubgraph.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -22,7 +22,7 @@ #### Defined in -[interfaces.ts:54](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L54) +[interfaces.ts:55](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L55) *** @@ -32,7 +32,7 @@ #### Defined in -[interfaces.ts:63](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L63) +[interfaces.ts:64](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L64) *** @@ -46,7 +46,7 @@ #### Defined in -[interfaces.ts:59](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L59) +[interfaces.ts:60](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L60) *** @@ -60,7 +60,7 @@ #### Defined in -[interfaces.ts:58](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L58) +[interfaces.ts:59](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L59) *** @@ -74,7 +74,7 @@ #### Defined in -[interfaces.ts:55](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L55) +[interfaces.ts:56](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L56) *** @@ -88,4 +88,4 @@ #### Defined in -[interfaces.ts:56](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L56) +[interfaces.ts:57](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L57) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPagination.md b/docs/sdk/typescript/interfaces/interfaces/IPagination.md index 131d487a00..4ac1dc3c53 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IPagination.md +++ b/docs/sdk/typescript/interfaces/interfaces/IPagination.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -21,7 +21,7 @@ #### Defined in -[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) *** @@ -31,7 +31,7 @@ #### Defined in -[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) +[interfaces.ts:155](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L155) *** @@ -41,4 +41,4 @@ #### Defined in -[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md b/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md index f36a3f7b4f..10aa72eb68 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md +++ b/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:106](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L106) +[interfaces.ts:107](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L107) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:108](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L108) +[interfaces.ts:109](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L109) *** @@ -34,7 +34,7 @@ #### Defined in -[interfaces.ts:107](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L107) +[interfaces.ts:108](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L108) *** @@ -44,4 +44,4 @@ #### Defined in -[interfaces.ts:109](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L109) +[interfaces.ts:110](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L110) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md b/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md index f4ea07f386..a79cb7d264 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md +++ b/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:44](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L44) +[interfaces.ts:45](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L45) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:43](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L43) +[interfaces.ts:44](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L44) *** @@ -34,4 +34,4 @@ #### Defined in -[interfaces.ts:45](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L45) +[interfaces.ts:46](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L46) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md b/docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md index e67aa3ef0f..aee9378fb6 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md +++ b/docs/sdk/typescript/interfaces/interfaces/IReputationNetworkSubgraph.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -22,7 +22,7 @@ #### Defined in -[interfaces.ts:44](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L44) +[interfaces.ts:45](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L45) *** @@ -36,7 +36,7 @@ #### Defined in -[interfaces.ts:43](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L43) +[interfaces.ts:44](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L44) *** @@ -46,4 +46,4 @@ #### Defined in -[interfaces.ts:50](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L50) +[interfaces.ts:51](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L51) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReward.md b/docs/sdk/typescript/interfaces/interfaces/IReward.md index 2669959801..3744b69802 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IReward.md +++ b/docs/sdk/typescript/interfaces/interfaces/IReward.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:6](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L6) +[interfaces.ts:6](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L6) *** @@ -24,4 +24,4 @@ #### Defined in -[interfaces.ts:5](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L5) +[interfaces.ts:5](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L5) diff --git a/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md b/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md index 35e738be6d..ff896e3160 100644 --- a/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md +++ b/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -22,7 +22,7 @@ #### Defined in -[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) *** @@ -32,7 +32,7 @@ #### Defined in -[interfaces.ts:97](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L97) +[interfaces.ts:98](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L98) *** @@ -46,7 +46,7 @@ #### Defined in -[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) +[interfaces.ts:155](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L155) *** @@ -60,7 +60,7 @@ #### Defined in -[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) *** @@ -70,4 +70,4 @@ #### Defined in -[interfaces.ts:98](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L98) +[interfaces.ts:99](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L99) diff --git a/docs/sdk/typescript/interfaces/interfaces/ITransaction.md b/docs/sdk/typescript/interfaces/interfaces/ITransaction.md index f03ce6a4e2..8bd621bb12 100644 --- a/docs/sdk/typescript/interfaces/interfaces/ITransaction.md +++ b/docs/sdk/typescript/interfaces/interfaces/ITransaction.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:128](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L128) +[interfaces.ts:129](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L129) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:136](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L136) +[interfaces.ts:137](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L137) *** @@ -34,7 +34,7 @@ #### Defined in -[interfaces.ts:130](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L130) +[interfaces.ts:131](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L131) *** @@ -44,7 +44,7 @@ #### Defined in -[interfaces.ts:138](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L138) +[interfaces.ts:139](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L139) *** @@ -54,7 +54,7 @@ #### Defined in -[interfaces.ts:134](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L134) +[interfaces.ts:135](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L135) *** @@ -64,7 +64,7 @@ #### Defined in -[interfaces.ts:135](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L135) +[interfaces.ts:136](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L136) *** @@ -74,7 +74,7 @@ #### Defined in -[interfaces.ts:132](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L132) +[interfaces.ts:133](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L133) *** @@ -84,7 +84,7 @@ #### Defined in -[interfaces.ts:131](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L131) +[interfaces.ts:132](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L132) *** @@ -94,7 +94,7 @@ #### Defined in -[interfaces.ts:137](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L137) +[interfaces.ts:138](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L138) *** @@ -104,7 +104,7 @@ #### Defined in -[interfaces.ts:129](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L129) +[interfaces.ts:130](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L130) *** @@ -114,4 +114,4 @@ #### Defined in -[interfaces.ts:133](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L133) +[interfaces.ts:134](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L134) diff --git a/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md b/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md index 31cf0b30c7..e7ab0b1be4 100644 --- a/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md +++ b/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -18,7 +18,7 @@ #### Defined in -[interfaces.ts:142](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L142) +[interfaces.ts:143](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L143) *** @@ -28,7 +28,7 @@ #### Defined in -[interfaces.ts:144](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L144) +[interfaces.ts:145](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L145) *** @@ -38,7 +38,7 @@ #### Defined in -[interfaces.ts:146](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L146) +[interfaces.ts:147](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L147) *** @@ -52,7 +52,7 @@ #### Defined in -[interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) +[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) *** @@ -62,7 +62,7 @@ #### Defined in -[interfaces.ts:147](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L147) +[interfaces.ts:148](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L148) *** @@ -76,7 +76,7 @@ #### Defined in -[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) +[interfaces.ts:155](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L155) *** @@ -90,7 +90,7 @@ #### Defined in -[interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) +[interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) *** @@ -100,7 +100,7 @@ #### Defined in -[interfaces.ts:143](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L143) +[interfaces.ts:144](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L144) *** @@ -110,7 +110,7 @@ #### Defined in -[interfaces.ts:145](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L145) +[interfaces.ts:146](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L146) *** @@ -120,4 +120,4 @@ #### Defined in -[interfaces.ts:148](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L148) +[interfaces.ts:149](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L149) diff --git a/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md b/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md index c3376cae1d..34647cc879 100644 --- a/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md +++ b/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -14,7 +14,7 @@ #### Defined in -[interfaces.ts:123](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L123) +[interfaces.ts:124](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L124) *** @@ -24,7 +24,7 @@ #### Defined in -[interfaces.ts:118](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L118) +[interfaces.ts:119](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L119) *** @@ -34,7 +34,7 @@ #### Defined in -[interfaces.ts:121](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L121) +[interfaces.ts:122](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L122) *** @@ -44,7 +44,7 @@ #### Defined in -[interfaces.ts:122](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L122) +[interfaces.ts:123](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L123) *** @@ -54,7 +54,7 @@ #### Defined in -[interfaces.ts:119](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L119) +[interfaces.ts:120](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L120) *** @@ -64,7 +64,7 @@ #### Defined in -[interfaces.ts:124](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L124) +[interfaces.ts:125](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L125) *** @@ -74,4 +74,4 @@ #### Defined in -[interfaces.ts:120](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L120) +[interfaces.ts:121](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L121) diff --git a/docs/sdk/typescript/kvstore/README.md b/docs/sdk/typescript/kvstore/README.md index 1436bd8549..7e025ffc9c 100644 --- a/docs/sdk/typescript/kvstore/README.md +++ b/docs/sdk/typescript/kvstore/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/kvstore/classes/KVStoreClient.md b/docs/sdk/typescript/kvstore/classes/KVStoreClient.md index 512f87af1e..574073c60c 100644 --- a/docs/sdk/typescript/kvstore/classes/KVStoreClient.md +++ b/docs/sdk/typescript/kvstore/classes/KVStoreClient.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -88,11 +88,15 @@ const kvstoreClient = await KVStoreClient.build(signer); #### Parameters -• **runner**: `ContractRunner` +##### runner + +`ContractRunner` The Runner object to interact with the Ethereum network -• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) +##### networkData + +[`NetworkData`](../../types/type-aliases/NetworkData.md) The network information required to connect to the KVStore contract @@ -106,7 +110,7 @@ The network information required to connect to the KVStore contract #### Defined in -[kvstore.ts:108](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L108) +[kvstore.ts:108](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L108) ## Properties @@ -120,7 +124,7 @@ The network information required to connect to the KVStore contract #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -134,7 +138,7 @@ The network information required to connect to the KVStore contract #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) ## Methods @@ -146,15 +150,21 @@ This function sets a key-value pair associated with the address that submits the #### Parameters -• **key**: `string` +##### key + +`string` Key of the key-value pair -• **value**: `string` +##### value + +`string` Value of the key-value pair -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -184,7 +194,7 @@ await kvstoreClient.set('Role', 'RecordingOracle'); #### Defined in -[kvstore.ts:171](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L171) +[kvstore.ts:171](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L171) *** @@ -196,15 +206,21 @@ This function sets key-value pairs in bulk associated with the address that subm #### Parameters -• **keys**: `string`[] +##### keys + +`string`[] Array of keys (keys and value must have the same order) -• **values**: `string`[] +##### values + +`string`[] Array of values -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -236,7 +252,7 @@ await kvstoreClient.set(keys, values); #### Defined in -[kvstore.ts:214](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L214) +[kvstore.ts:214](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L214) *** @@ -248,15 +264,21 @@ Sets a URL value for the address that submits the transaction, and its hash. #### Parameters -• **url**: `string` +##### url + +`string` URL to set -• **urlKey**: `string` = `'url'` +##### urlKey + +`string` = `'url'` Configurable URL key. `url` by default. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -285,7 +307,7 @@ await kvstoreClient.setFileUrlAndHash('linkedin.com/example', 'linkedin_url); #### Defined in -[kvstore.ts:257](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L257) +[kvstore.ts:257](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L257) *** @@ -297,7 +319,9 @@ Creates an instance of KVStoreClient from a runner. #### Parameters -• **runner**: `ContractRunner` +##### runner + +`ContractRunner` The Runner object to interact with the Ethereum network @@ -317,4 +341,4 @@ The Runner object to interact with the Ethereum network #### Defined in -[kvstore.ts:126](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L126) +[kvstore.ts:126](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L126) diff --git a/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md b/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md index 092b9408d4..6954f0b98b 100644 --- a/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md +++ b/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -57,15 +57,21 @@ Gets the value of a key-value pair in the KVStore using the subgraph. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed -• **address**: `string` +##### address + +`string` Address from which to get the key value. -• **key**: `string` +##### key + +`string` Key to obtain the value. @@ -102,7 +108,7 @@ console.log(value); #### Defined in -[kvstore.ts:389](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L389) +[kvstore.ts:389](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L389) *** @@ -114,15 +120,21 @@ Gets the URL value of the given entity, and verifies its hash. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed -• **address**: `string` +##### address + +`string` Address from which to get the URL value. -• **urlKey**: `string` = `'url'` +##### urlKey + +`string` = `'url'` Configurable URL key. `url` by default. @@ -146,7 +158,7 @@ console.log(url); #### Defined in -[kvstore.ts:436](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L436) +[kvstore.ts:436](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L436) *** @@ -158,11 +170,15 @@ This function returns the KVStore data for a given address. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed -• **address**: `string` +##### address + +`string` Address of the KVStore @@ -191,7 +207,7 @@ console.log(kvStoreData); #### Defined in -[kvstore.ts:337](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L337) +[kvstore.ts:337](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L337) *** @@ -203,11 +219,15 @@ Gets the public key of the given entity, and verifies its hash. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) Network in which the KVStore is deployed -• **address**: `string` +##### address + +`string` Address from which to get the public key. @@ -231,4 +251,4 @@ console.log(publicKey); #### Defined in -[kvstore.ts:496](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L496) +[kvstore.ts:496](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L496) diff --git a/docs/sdk/typescript/modules.md b/docs/sdk/typescript/modules.md index a5dd8d10ce..b36bd138ca 100644 --- a/docs/sdk/typescript/modules.md +++ b/docs/sdk/typescript/modules.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](README.md) • **Docs** +[**@human-protocol/sdk**](README.md) *** diff --git a/docs/sdk/typescript/operator/README.md b/docs/sdk/typescript/operator/README.md index 2e8bce74ed..0f9c5319f1 100644 --- a/docs/sdk/typescript/operator/README.md +++ b/docs/sdk/typescript/operator/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/operator/classes/OperatorUtils.md b/docs/sdk/typescript/operator/classes/OperatorUtils.md index b638759b24..c0ac41c2fb 100644 --- a/docs/sdk/typescript/operator/classes/OperatorUtils.md +++ b/docs/sdk/typescript/operator/classes/OperatorUtils.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -26,9 +26,13 @@ This function returns the leader data for the given address. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId -• **address**: `string` +[`ChainId`](../../enums/enumerations/ChainId.md) + +##### address + +`string` Leader address. @@ -48,7 +52,7 @@ const leader = await OperatorUtils.getLeader(ChainId.POLYGON_AMOY, '0x62dD51230A #### Defined in -[operator.ts:44](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L44) +[operator.ts:44](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L44) *** @@ -60,7 +64,9 @@ This function returns all the leader details of the protocol. #### Parameters -• **filter**: [`ILeadersFilter`](../../interfaces/interfaces/ILeadersFilter.md) +##### filter + +[`ILeadersFilter`](../../interfaces/interfaces/ILeadersFilter.md) Filter for the leaders. @@ -83,7 +89,7 @@ const leaders = await OperatorUtils.getLeaders(filter); #### Defined in -[operator.ts:107](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L107) +[operator.ts:108](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L108) *** @@ -95,13 +101,19 @@ Retrieves the reputation network operators of the specified address. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) -• **address**: `string` +##### address + +`string` Address of the reputation oracle. -• **role?**: `string` +##### role? + +`string` (Optional) Role of the operator. @@ -121,7 +133,7 @@ const operators = await OperatorUtils.getReputationNetworkOperators(ChainId.POLY #### Defined in -[operator.ts:170](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L170) +[operator.ts:172](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L172) *** @@ -133,9 +145,13 @@ This function returns information about the rewards for a given slasher address. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) + +##### slasherAddress -• **slasherAddress**: `string` +`string` Slasher address. @@ -155,4 +171,4 @@ const rewards = await OperatorUtils.getRewards(ChainId.POLYGON_AMOY, '0x62dD5123 #### Defined in -[operator.ts:220](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L220) +[operator.ts:222](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L222) diff --git a/docs/sdk/typescript/staking/README.md b/docs/sdk/typescript/staking/README.md index b32a13ff45..3618a4695f 100644 --- a/docs/sdk/typescript/staking/README.md +++ b/docs/sdk/typescript/staking/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/staking/classes/StakingClient.md b/docs/sdk/typescript/staking/classes/StakingClient.md index bdf953ceff..d0c2a3ac51 100644 --- a/docs/sdk/typescript/staking/classes/StakingClient.md +++ b/docs/sdk/typescript/staking/classes/StakingClient.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -88,11 +88,15 @@ const stakingClient = await StakingClient.build(provider); #### Parameters -• **runner**: `ContractRunner` +##### runner + +`ContractRunner` The Runner object to interact with the Ethereum network -• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) +##### networkData + +[`NetworkData`](../../types/type-aliases/NetworkData.md) The network information required to connect to the Staking contract @@ -106,7 +110,7 @@ The network information required to connect to the Staking contract #### Defined in -[staking.ts:107](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L107) +[staking.ts:107](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L107) ## Properties @@ -116,7 +120,7 @@ The network information required to connect to the Staking contract #### Defined in -[staking.ts:99](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L99) +[staking.ts:99](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L99) *** @@ -130,7 +134,7 @@ The network information required to connect to the Staking contract #### Defined in -[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) +[base.ts:12](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) *** @@ -144,7 +148,7 @@ The network information required to connect to the Staking contract #### Defined in -[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) +[base.ts:11](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) *** @@ -154,7 +158,7 @@ The network information required to connect to the Staking contract #### Defined in -[staking.ts:98](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L98) +[staking.ts:98](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L98) *** @@ -164,7 +168,7 @@ The network information required to connect to the Staking contract #### Defined in -[staking.ts:97](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L97) +[staking.ts:97](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L97) ## Methods @@ -176,11 +180,15 @@ This function approves the staking contract to transfer a specified amount of to #### Parameters -• **amount**: `bigint` +##### amount + +`bigint` Amount in WEI of tokens to approve for stake. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -209,7 +217,7 @@ await stakingClient.approveStake(amount); #### Defined in -[staking.ts:193](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L193) +[staking.ts:193](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L193) *** @@ -221,23 +229,33 @@ This function reduces the allocated amount by an staker in an escrow and transfe #### Parameters -• **slasher**: `string` +##### slasher + +`string` Wallet address from who requested the slash -• **staker**: `string` +##### staker + +`string` Wallet address from who is going to be slashed -• **escrowAddress**: `string` +##### escrowAddress + +`string` Address of the escrow that the slash is made -• **amount**: `bigint` +##### amount + +`bigint` Amount in WEI of tokens to unstake. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -266,7 +284,7 @@ await stakingClient.slash('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd #### Defined in -[staking.ts:377](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L377) +[staking.ts:377](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L377) *** @@ -280,11 +298,15 @@ This function stakes a specified amount of tokens on a specific network. #### Parameters -• **amount**: `bigint` +##### amount + +`bigint` Amount in WEI of tokens to stake. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -314,7 +336,7 @@ await stakingClient.approveStake(amount); #### Defined in -[staking.ts:248](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L248) +[staking.ts:248](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L248) *** @@ -328,11 +350,15 @@ This function unstakes tokens from staking contract. The unstaked tokens stay lo #### Parameters -• **amount**: `bigint` +##### amount + +`bigint` Amount in WEI of tokens to unstake. -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -361,7 +387,7 @@ await stakingClient.unstake(amount); #### Defined in -[staking.ts:293](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L293) +[staking.ts:293](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L293) *** @@ -375,7 +401,9 @@ This function withdraws unstaked and non locked tokens form staking contract to #### Parameters -• **txOptions?**: `Overrides` = `{}` +##### txOptions? + +`Overrides` = `{}` Additional transaction parameters (optional, defaults to an empty object). @@ -403,7 +431,7 @@ await stakingClient.withdraw(); #### Defined in -[staking.ts:339](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L339) +[staking.ts:339](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L339) *** @@ -415,7 +443,9 @@ Creates an instance of StakingClient from a Runner. #### Parameters -• **runner**: `ContractRunner` +##### runner + +`ContractRunner` The Runner object to interact with the Ethereum network @@ -435,4 +465,4 @@ The Runner object to interact with the Ethereum network #### Defined in -[staking.ts:135](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L135) +[staking.ts:135](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L135) diff --git a/docs/sdk/typescript/statistics/README.md b/docs/sdk/typescript/statistics/README.md index d5cf580f8e..a4db8cb869 100644 --- a/docs/sdk/typescript/statistics/README.md +++ b/docs/sdk/typescript/statistics/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/statistics/classes/StatisticsClient.md b/docs/sdk/typescript/statistics/classes/StatisticsClient.md index 4b32bfffed..f49c11699c 100644 --- a/docs/sdk/typescript/statistics/classes/StatisticsClient.md +++ b/docs/sdk/typescript/statistics/classes/StatisticsClient.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -52,7 +52,9 @@ const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); #### Parameters -• **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) +##### networkData + +[`NetworkData`](../../types/type-aliases/NetworkData.md) The network information required to connect to the Statistics contract @@ -62,7 +64,7 @@ The network information required to connect to the Statistics contract #### Defined in -[statistics.ts:72](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L72) +[statistics.ts:72](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L72) ## Properties @@ -72,7 +74,7 @@ The network information required to connect to the Statistics contract #### Defined in -[statistics.ts:64](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L64) +[statistics.ts:64](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L64) *** @@ -82,7 +84,7 @@ The network information required to connect to the Statistics contract #### Defined in -[statistics.ts:65](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L65) +[statistics.ts:65](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L65) ## Methods @@ -122,7 +124,9 @@ type EscrowStatistics = { #### Parameters -• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` +##### filter + +[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data @@ -148,7 +152,7 @@ const escrowStatisticsApril = await statisticsClient.getEscrowStatistics({ #### Defined in -[statistics.ts:128](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L128) +[statistics.ts:128](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L128) *** @@ -182,7 +186,9 @@ type DailyHMTData = { #### Parameters -• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` +##### filter + +[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data @@ -213,7 +219,7 @@ console.log('HMT statistics from 5/8 - 6/8:', hmtStatisticsRange); #### Defined in -[statistics.ts:495](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L495) +[statistics.ts:497](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L497) *** @@ -227,7 +233,9 @@ This function returns the holders of the HMToken with optional filters and order #### Parameters -• **params**: [`IHMTHoldersParams`](../../interfaces/interfaces/IHMTHoldersParams.md) = `{}` +##### params + +[`IHMTHoldersParams`](../../interfaces/interfaces/IHMTHoldersParams.md) = `{}` HMT Holders params with filters and ordering @@ -256,7 +264,7 @@ console.log('HMT holders:', hmtHolders.map((h) => ({ #### Defined in -[statistics.ts:421](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L421) +[statistics.ts:423](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L423) *** @@ -296,7 +304,7 @@ console.log('HMT statistics:', { #### Defined in -[statistics.ts:378](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L378) +[statistics.ts:380](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L380) *** @@ -333,7 +341,9 @@ type PaymentStatistics = { #### Parameters -• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` +##### filter + +[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data @@ -380,7 +390,7 @@ console.log( #### Defined in -[statistics.ts:312](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L312) +[statistics.ts:314](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L314) *** @@ -415,7 +425,9 @@ type WorkerStatistics = { #### Parameters -• **filter**: [`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` +##### filter + +[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` Statistics params with duration data @@ -441,4 +453,4 @@ const workerStatisticsApril = await statisticsClient.getWorkerStatistics({ #### Defined in -[statistics.ts:213](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L213) +[statistics.ts:215](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L215) diff --git a/docs/sdk/typescript/storage/README.md b/docs/sdk/typescript/storage/README.md index 80e8da6d9f..c77d810c8c 100644 --- a/docs/sdk/typescript/storage/README.md +++ b/docs/sdk/typescript/storage/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/storage/classes/StorageClient.md b/docs/sdk/typescript/storage/classes/StorageClient.md index 8fa93cbb59..19625fed23 100644 --- a/docs/sdk/typescript/storage/classes/StorageClient.md +++ b/docs/sdk/typescript/storage/classes/StorageClient.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -63,11 +63,15 @@ const storageClient = new StorageClient(params, credentials); #### Parameters -• **params**: [`StorageParams`](../../types/type-aliases/StorageParams.md) +##### params + +[`StorageParams`](../../types/type-aliases/StorageParams.md) Cloud storage params -• **credentials?**: [`StorageCredentials`](../../types/type-aliases/StorageCredentials.md) +##### credentials? + +[`StorageCredentials`](../../types/type-aliases/StorageCredentials.md) Optional. Cloud storage access data. If credentials is not provided - use an anonymous access to the bucket @@ -77,7 +81,7 @@ Optional. Cloud storage access data. If credentials is not provided - use an ano #### Defined in -[storage.ts:73](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L73) +[storage.ts:73](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L73) ## Methods @@ -89,7 +93,9 @@ This function checks if a bucket exists. #### Parameters -• **bucket**: `string` +##### bucket + +`string` Bucket name. @@ -121,7 +127,7 @@ const exists = await storageClient.bucketExists('bucket-name'); #### Defined in -[storage.ts:266](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L266) +[storage.ts:266](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L266) *** @@ -133,11 +139,15 @@ This function downloads files from a bucket. #### Parameters -• **keys**: `string`[] +##### keys + +`string`[] Array of filenames to download. -• **bucket**: `string` +##### bucket + +`string` Bucket name. @@ -167,7 +177,7 @@ const files = await storageClient.downloadFiles(keys, 'bucket-name'); #### Defined in -[storage.ts:113](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L113) +[storage.ts:113](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L113) *** @@ -179,7 +189,9 @@ This function list all file names contained in the bucket. #### Parameters -• **bucket**: `string` +##### bucket + +`string` Bucket name. @@ -211,7 +223,7 @@ const fileNames = await storageClient.listObjects('bucket-name'); #### Defined in -[storage.ts:297](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L297) +[storage.ts:297](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L297) *** @@ -223,11 +235,15 @@ This function uploads files to a bucket. #### Parameters -• **files**: `any`[] +##### files + +`any`[] Array of objects to upload serialized into json. -• **bucket**: `string` +##### bucket + +`string` Bucket name. @@ -262,7 +278,7 @@ const uploadedFiles = await storageClient.uploadFiles(files, 'bucket-name'); #### Defined in -[storage.ts:201](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L201) +[storage.ts:201](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L201) *** @@ -274,7 +290,9 @@ This function downloads files from a Url. #### Parameters -• **url**: `string` +##### url + +`string` Url of the file to download. @@ -294,4 +312,4 @@ const file = await storageClient.downloadFileFromUrl('http://localhost/file.json #### Defined in -[storage.ts:148](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L148) +[storage.ts:148](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L148) diff --git a/docs/sdk/typescript/transaction/README.md b/docs/sdk/typescript/transaction/README.md index 8dd49468bd..7a6bf57441 100644 --- a/docs/sdk/typescript/transaction/README.md +++ b/docs/sdk/typescript/transaction/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/transaction/classes/TransactionUtils.md b/docs/sdk/typescript/transaction/classes/TransactionUtils.md index 8adc8de4f0..d87190140c 100644 --- a/docs/sdk/typescript/transaction/classes/TransactionUtils.md +++ b/docs/sdk/typescript/transaction/classes/TransactionUtils.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -26,11 +26,15 @@ This function returns the transaction data for the given hash. #### Parameters -• **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) +##### chainId + +[`ChainId`](../../enums/enumerations/ChainId.md) The chain ID. -• **hash**: `string` +##### hash + +`string` The transaction hash. @@ -50,7 +54,7 @@ const transaction = await TransactionUtils.getTransaction(ChainId.POLYGON, '0x62 #### Defined in -[transaction.ts:34](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L34) +[transaction.ts:34](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L34) *** @@ -93,7 +97,9 @@ type ITransaction = { #### Parameters -• **filter**: [`ITransactionsFilter`](../../interfaces/interfaces/ITransactionsFilter.md) +##### filter + +[`ITransactionsFilter`](../../interfaces/interfaces/ITransactionsFilter.md) Filter for the transactions. @@ -121,4 +127,4 @@ const transactions = await TransactionUtils.getTransactions(filter); #### Defined in -[transaction.ts:109](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L109) +[transaction.ts:109](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L109) diff --git a/docs/sdk/typescript/types/README.md b/docs/sdk/typescript/types/README.md index 90690e2e95..ed6ec3f590 100644 --- a/docs/sdk/typescript/types/README.md +++ b/docs/sdk/typescript/types/README.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../README.md) • **Docs** +[**@human-protocol/sdk**](../README.md) *** diff --git a/docs/sdk/typescript/types/enumerations/EscrowStatus.md b/docs/sdk/typescript/types/enumerations/EscrowStatus.md index 0c702534fd..846b8d4d48 100644 --- a/docs/sdk/typescript/types/enumerations/EscrowStatus.md +++ b/docs/sdk/typescript/types/enumerations/EscrowStatus.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -18,7 +18,7 @@ Escrow is cancelled. #### Defined in -[types.ts:30](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L30) +[types.ts:30](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L30) *** @@ -30,7 +30,7 @@ Escrow is finished.. #### Defined in -[types.ts:26](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L26) +[types.ts:26](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L26) *** @@ -42,7 +42,7 @@ Escrow is launched. #### Defined in -[types.ts:10](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L10) +[types.ts:10](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L10) *** @@ -54,7 +54,7 @@ Escrow is fully paid. #### Defined in -[types.ts:22](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L22) +[types.ts:22](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L22) *** @@ -66,7 +66,7 @@ Escrow is partially paid out. #### Defined in -[types.ts:18](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L18) +[types.ts:18](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L18) *** @@ -78,4 +78,4 @@ Escrow is funded, and waiting for the results to be submitted. #### Defined in -[types.ts:14](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L14) +[types.ts:14](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L14) diff --git a/docs/sdk/typescript/types/type-aliases/EscrowCancel.md b/docs/sdk/typescript/types/type-aliases/EscrowCancel.md index e47a9ae867..b3bf362bb3 100644 --- a/docs/sdk/typescript/types/type-aliases/EscrowCancel.md +++ b/docs/sdk/typescript/types/type-aliases/EscrowCancel.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -26,4 +26,4 @@ The hash of the transaction associated with the escrow cancellation. ## Defined in -[types.ts:143](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L143) +[types.ts:143](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L143) diff --git a/docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md b/docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md index d55ae18e29..187d592176 100644 --- a/docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md +++ b/docs/sdk/typescript/types/type-aliases/EscrowWithdraw.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -32,4 +32,4 @@ The hash of the transaction associated with the escrow withdrawal. ## Defined in -[types.ts:157](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L157) +[types.ts:157](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L157) diff --git a/docs/sdk/typescript/types/type-aliases/NetworkData.md b/docs/sdk/typescript/types/type-aliases/NetworkData.md index 00cc590c7b..746f2d4adf 100644 --- a/docs/sdk/typescript/types/type-aliases/NetworkData.md +++ b/docs/sdk/typescript/types/type-aliases/NetworkData.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -80,4 +80,4 @@ Network title ## Defined in -[types.ts:93](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L93) +[types.ts:93](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L93) diff --git a/docs/sdk/typescript/types/type-aliases/StorageCredentials.md b/docs/sdk/typescript/types/type-aliases/StorageCredentials.md index 1d5f6606e8..d99b41f6f0 100644 --- a/docs/sdk/typescript/types/type-aliases/StorageCredentials.md +++ b/docs/sdk/typescript/types/type-aliases/StorageCredentials.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -30,4 +30,4 @@ StorageClient is deprecated. Use Minio.Client directly. ## Defined in -[types.ts:38](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L38) +[types.ts:38](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L38) diff --git a/docs/sdk/typescript/types/type-aliases/StorageParams.md b/docs/sdk/typescript/types/type-aliases/StorageParams.md index c44be0f121..d8ca085e73 100644 --- a/docs/sdk/typescript/types/type-aliases/StorageParams.md +++ b/docs/sdk/typescript/types/type-aliases/StorageParams.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -40,4 +40,4 @@ StorageClient is deprecated. Use Minio.Client directly. ## Defined in -[types.ts:52](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L52) +[types.ts:52](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L52) diff --git a/docs/sdk/typescript/types/type-aliases/UploadFile.md b/docs/sdk/typescript/types/type-aliases/UploadFile.md index 3edf31e5e0..ca33318c3e 100644 --- a/docs/sdk/typescript/types/type-aliases/UploadFile.md +++ b/docs/sdk/typescript/types/type-aliases/UploadFile.md @@ -1,4 +1,4 @@ -[**@human-protocol/sdk**](../../README.md) • **Docs** +[**@human-protocol/sdk**](../../README.md) *** @@ -32,4 +32,4 @@ Uploaded object URL ## Defined in -[types.ts:75](https://github.com/humanprotocol/human-protocol/blob/2adb3114c920b5264832199f17e9531ba585c005/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L75) +[types.ts:75](https://github.com/humanprotocol/human-protocol/blob/d09ba07adfea005abceaa4b9fc19ef8d97dfa6cc/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L75) diff --git a/packages/core/.openzeppelin/avalanche-fuji.json b/packages/core/.openzeppelin/avalanche-fuji.json index 88a3009661..03d69a2994 100644 --- a/packages/core/.openzeppelin/avalanche-fuji.json +++ b/packages/core/.openzeppelin/avalanche-fuji.json @@ -575,6 +575,155 @@ } } } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0x7457d26a3C70Bd71F7557C773b303c1dB82BBB68", + "txHash": "0x931a49484fb40eb4a5a7ceaad75e0ea719e44094e1bef66793b243d0ec4bb71b", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/bsc.json b/packages/core/.openzeppelin/bsc.json index 0e0ebebfc5..85d546d749 100644 --- a/packages/core/.openzeppelin/bsc.json +++ b/packages/core/.openzeppelin/bsc.json @@ -1267,6 +1267,155 @@ } } } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0x4949C9DFFD83F0D5Ab0AB24C57C4D403D5c20C15", + "txHash": "0xfcdfb209a85d68468fe3a2cf4a67bb90dbd211ffc076209a107c00596686e6b7", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/mainnet.json b/packages/core/.openzeppelin/mainnet.json index 64e55bfe12..ed035a9370 100644 --- a/packages/core/.openzeppelin/mainnet.json +++ b/packages/core/.openzeppelin/mainnet.json @@ -1267,6 +1267,155 @@ } } } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0xE24e5C08E28331D24758b69A5E9f383D2bDD1c98", + "txHash": "0xa7ded33b01a555111a1d221a918ddf0768e4b88dfb8af2bb6de6f0992dd0d7c6", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/polygon.json b/packages/core/.openzeppelin/polygon.json index 7d9ae8b172..9dd6f83030 100644 --- a/packages/core/.openzeppelin/polygon.json +++ b/packages/core/.openzeppelin/polygon.json @@ -569,6 +569,155 @@ } } } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0x8D50dA7abe354a628a63ADfE23C19a2944612b83", + "txHash": "0x54a1686332d42d2a9025b9a211c978789d89cd3eb0381e66c2658b7d0db0ca0b", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/unknown-1287.json b/packages/core/.openzeppelin/unknown-1287.json index 1d9b505052..6b41c30fc6 100644 --- a/packages/core/.openzeppelin/unknown-1287.json +++ b/packages/core/.openzeppelin/unknown-1287.json @@ -2113,6 +2113,155 @@ } } } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", + "txHash": "0x31cf206807966e1bb54cd17fc616204a21a4b486cc7df5de5de97fe10f506b47", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/core/.openzeppelin/unknown-195.json b/packages/core/.openzeppelin/unknown-195.json index 4a25010315..a883a5c331 100644 --- a/packages/core/.openzeppelin/unknown-195.json +++ b/packages/core/.openzeppelin/unknown-195.json @@ -598,6 +598,155 @@ }, "namespaces": {} } + }, + "2d3fa01245b44969a8c2cf6a33f29f8d0e0c52f7b212797f69eb642a0697ba95": { + "address": "0x3C14F4900F5f59F29f8B684394A2748a71531dd7", + "txHash": "0x4626f8e04c689450f827e3b6896e73b6acf811dc2d7e76163e8e1f54ad29db67", + "layout": { + "solcVersion": "0.8.23", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "counter", + "offset": 0, + "slot": "201", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:16" + }, + { + "label": "escrowCounters", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_address,t_uint256)", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:17" + }, + { + "label": "lastEscrow", + "offset": 0, + "slot": "203", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:18" + }, + { + "label": "staking", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:19" + }, + { + "label": "minimumStake", + "offset": 0, + "slot": "205", + "type": "t_uint256", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "206", + "type": "t_array(t_uint256)45_storage", + "contract": "EscrowFactory", + "src": "contracts/EscrowFactory.sol:117" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py index d96a4efb3d..3242095373 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py @@ -40,11 +40,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/ethereum/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmaTcYR8NCzZuxwY7tBkMJAo1Q64BMqNNSzqjxd7FH9s2p" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmNTdYHpQLW4sbrCxihXNdQwhxa2zdyu1yPkCUuTbqESba" ), "hmt_address": "0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867", "factory_address": "0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a", - "staking_address": "0x05398211bA2046E296fBc9a9D3EB49e3F15C3123", + "staking_address": "0xEf6Da3aB52c33925Be3F84038193a7e1331F51E6", "kvstore_address": "0xB6d36B1CDaD50302BCB3DB43bAb0D349458e1b8D", "old_subgraph_url": "", "old_factory_address": "", @@ -88,11 +88,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/bsc/version/latest" ), "subgraph_url_api_key": ( - "hthttps://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmXZ4QJMi8kyfXDEJwtdizyKf5JdJui89iYCLCE79N8Xf5" + "hthttps://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmPMS6G5evLm5ZpbnmpCfUy8bHJPwzPkZTv9DgfNdFfrCM" ), "hmt_address": "0x711Fd6ab6d65A98904522d4e3586F492B989c527", "factory_address": "0x92FD968AcBd521c232f5fB8c33b342923cC72714", - "staking_address": "0xdFbB79dC35a3A53741be54a2C9b587d6BafAbd1C", + "staking_address": "0xE24e5C08E28331D24758b69A5E9f383D2bDD1c98", "kvstore_address": "0x21A0C4CED7aE447fCf87D9FE3A29FA9B3AB20Ff1", "old_subgraph_url": "https://api.thegraph.com/subgraphs/name/humanprotocol/bsc", "old_factory_address": "0xc88bC422cAAb2ac8812de03176402dbcA09533f4", @@ -122,11 +122,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/polygon/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmNdsofT4Cj2KRwr8vgyKgCWpZNmrMN41zUdygRz7eSGC9" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmTyCQMQd5QtogeTEuiqxnGQZa2PtgpUBsWLYwPCCFPbUe" ), "hmt_address": "0xc748B2A084F8eFc47E086ccdDD9b7e67aEb571BF", "factory_address": "0xBDBfD2cC708199C5640C6ECdf3B0F4A4C67AdfcB", - "staking_address": "0xcbAd56bE3f504E98bd70875823d3CC0242B7bB29", + "staking_address": "0x01D115E9E8bF0C58318793624CC662a030D07F1D", "kvstore_address": "0xbcB28672F826a50B03EE91B28145EAbddA73B2eD", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/polygon" @@ -190,11 +190,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/moonbase-alpha/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmeC4JrotcrXWJtJU519RX3KkxE5879wveRJJ58EheH3j1" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmSDPbm5xxMvYVSJzHFVsRiMekvJVYSJ7UfZw17DhPMdaH" ), "hmt_address": "0x2dd72db2bBA65cE663e476bA8b84A1aAF802A8e3", "factory_address": "0x5e622FF522D81aa426f082bDD95210BC25fCA7Ed", - "staking_address": "0xBFC7009F3371F93F3B54DdC8caCd02914a37495c", + "staking_address": "0xbA537fEF2442cD48f60686FE1Bbbe40F964a7940", "kvstore_address": "0xcC561f4482f4Ff051D2Dcc65c2cE1A0f291bbA46", "old_subgraph_url": "", "old_factory_address": "", @@ -224,11 +224,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/fuji/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmcFhecY6w3AhKGSg8XeidXwwuXCV9DAQ5SYGE1sTzydgR" + "https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmYXwNPwC5DcitK1SLVUR6gPANmEn3UsVvGeTbjCv1tTb2" ), "hmt_address": "0x9406d5c635AD22b0d76c75E52De57A2177919ca3", "factory_address": "0x56C2ba540726ED4f46E7a134b6b9Ee9C867FcF92", - "staking_address": "0x9890473B0b93E24d6D1a8Dfb739D577C6f25FFd3", + "staking_address": "0xbA537fEF2442cD48f60686FE1Bbbe40F964a7940", "kvstore_address": "0x3aD4B091E054f192a822D1406f4535eAd38580e4", "old_subgraph_url": ( "https://api.thegraph.com/subgraphs/name/humanprotocol/fuji" @@ -290,11 +290,11 @@ class OrderDirection(Enum): "https://api.studio.thegraph.com/query/74256/xlayer-testnet/version/latest" ), "subgraph_url_api_key": ( - "https://gateway-testnet-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmQrTmq89ZCdVABsFpLHtQUWuyyVzbcARoan9eztHd21oP" + "https://gateway-testnet-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmNoRyqZtJTRrkbKAmWMZQUHuah7YSs8U9R3nzPu8WEhtY" ), "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", "factory_address": "0x6Cd3ecAD36ee88E9ef3665CF381D9dAE0FE0a32e", - "staking_address": "0x187edb5651464427b312De2AD40F4C679cf6e02D", + "staking_address": "0xeF9849a904dF0d494D69ac0B0a6860a3A7936114", "kvstore_address": "0xdE8BE9E3C12E9F546309A429cd88d026a25EaF8C", "old_subgraph_url": "", "old_factory_address": "", diff --git a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts index 61f19bd3f7..031ad21c68 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts @@ -33,12 +33,12 @@ export const NETWORKS: { scanUrl: 'https://etherscan.io', factoryAddress: '0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a', hmtAddress: '0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867', - stakingAddress: '0x05398211bA2046E296fBc9a9D3EB49e3F15C3123', + stakingAddress: '0xEf6Da3aB52c33925Be3F84038193a7e1331F51E6', kvstoreAddress: '0xB6d36B1CDaD50302BCB3DB43bAb0D349458e1b8D', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/ethereum/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmaTcYR8NCzZuxwY7tBkMJAo1Q64BMqNNSzqjxd7FH9s2p', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmNTdYHpQLW4sbrCxihXNdQwhxa2zdyu1yPkCUuTbqESba', oldSubgraphUrl: '', oldFactoryAddress: '', }, @@ -91,12 +91,12 @@ export const NETWORKS: { scanUrl: 'https://bscscan.com', factoryAddress: '0x92FD968AcBd521c232f5fB8c33b342923cC72714', hmtAddress: '0x711Fd6ab6d65A98904522d4e3586F492B989c527', - stakingAddress: '0xdFbB79dC35a3A53741be54a2C9b587d6BafAbd1C', + stakingAddress: '0xE24e5C08E28331D24758b69A5E9f383D2bDD1c98', kvstoreAddress: '0x21A0C4CED7aE447fCf87D9FE3A29FA9B3AB20Ff1', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/bsc/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmXZ4QJMi8kyfXDEJwtdizyKf5JdJui89iYCLCE79N8Xf5', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmPMS6G5evLm5ZpbnmpCfUy8bHJPwzPkZTv9DgfNdFfrCM', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/bsc', oldFactoryAddress: '0xc88bC422cAAb2ac8812de03176402dbcA09533f4', }, @@ -122,12 +122,12 @@ export const NETWORKS: { scanUrl: 'https://polygonscan.com', factoryAddress: '0xBDBfD2cC708199C5640C6ECdf3B0F4A4C67AdfcB', hmtAddress: '0xc748B2A084F8eFc47E086ccdDD9b7e67aEb571BF', - stakingAddress: '0xcbAd56bE3f504E98bd70875823d3CC0242B7bB29', + stakingAddress: '0x01D115E9E8bF0C58318793624CC662a030D07F1D', kvstoreAddress: '0xbcB28672F826a50B03EE91B28145EAbddA73B2eD', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/polygon/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmNdsofT4Cj2KRwr8vgyKgCWpZNmrMN41zUdygRz7eSGC9', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmTyCQMQd5QtogeTEuiqxnGQZa2PtgpUBsWLYwPCCFPbUe', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/polygon', oldFactoryAddress: '0x45eBc3eAE6DA485097054ae10BA1A0f8e8c7f794', @@ -184,12 +184,12 @@ export const NETWORKS: { scanUrl: 'https://moonbase.moonscan.io/', factoryAddress: '0x5e622FF522D81aa426f082bDD95210BC25fCA7Ed', hmtAddress: '0x2dd72db2bBA65cE663e476bA8b84A1aAF802A8e3', - stakingAddress: '0xBFC7009F3371F93F3B54DdC8caCd02914a37495c', + stakingAddress: '0xbA537fEF2442cD48f60686FE1Bbbe40F964a7940', kvstoreAddress: '0xcC561f4482f4Ff051D2Dcc65c2cE1A0f291bbA46', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/moonbase-alpha/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmeC4JrotcrXWJtJU519RX3KkxE5879wveRJJ58EheH3j1', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmSDPbm5xxMvYVSJzHFVsRiMekvJVYSJ7UfZw17DhPMdaH', oldSubgraphUrl: '', oldFactoryAddress: '', }, @@ -199,12 +199,12 @@ export const NETWORKS: { scanUrl: 'https://testnet.snowtrace.io', factoryAddress: '0x56C2ba540726ED4f46E7a134b6b9Ee9C867FcF92', hmtAddress: '0x9406d5c635AD22b0d76c75E52De57A2177919ca3', - stakingAddress: '0x9890473B0b93E24d6D1a8Dfb739D577C6f25FFd3', + stakingAddress: '0xbA537fEF2442cD48f60686FE1Bbbe40F964a7940', kvstoreAddress: '0x3aD4B091E054f192a822D1406f4535eAd38580e4', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/fuji/version/latest', subgraphUrlApiKey: - 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmcFhecY6w3AhKGSg8XeidXwwuXCV9DAQ5SYGE1sTzydgR', + 'https://gateway-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmYXwNPwC5DcitK1SLVUR6gPANmEn3UsVvGeTbjCv1tTb2', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/fuji', oldFactoryAddress: '0xfb4469201951C3B9a7F1996c477cb7BDBEcE0A88', @@ -276,12 +276,12 @@ export const NETWORKS: { scanUrl: 'https://www.okx.com/explorer/xlayer-test', factoryAddress: '0x6Cd3ecAD36ee88E9ef3665CF381D9dAE0FE0a32e', hmtAddress: '0x792abbcC99c01dbDec49c9fa9A828a186Da45C33', - stakingAddress: '0x819069fEd50581587fAB9E583b5488fc2D33B7ea', + stakingAddress: '0xeF9849a904dF0d494D69ac0B0a6860a3A7936114', kvstoreAddress: '0xdE8BE9E3C12E9F546309A429cd88d026a25EaF8C', subgraphUrl: 'https://api.studio.thegraph.com/query/74256/xlayer-testnet/version/latest', subgraphUrlApiKey: - 'https://gateway-testnet-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmQrTmq89ZCdVABsFpLHtQUWuyyVzbcARoan9eztHd21oP', + 'https://gateway-testnet-arbitrum.network.thegraph.com/api/[SUBGRAPH_API_KEY]/deployments/id/QmNoRyqZtJTRrkbKAmWMZQUHuah7YSs8U9R3nzPu8WEhtY', oldSubgraphUrl: '', oldFactoryAddress: '', }, diff --git a/packages/sdk/typescript/subgraph/config/bsc.json b/packages/sdk/typescript/subgraph/config/bsc.json index eca5995ef8..0b741f1819 100644 --- a/packages/sdk/typescript/subgraph/config/bsc.json +++ b/packages/sdk/typescript/subgraph/config/bsc.json @@ -17,8 +17,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/Escrow.json" }, "Staking": { - "address": "0xdFbB79dC35a3A53741be54a2C9b587d6BafAbd1C", - "startBlock": 28745621, + "address": "0xE24e5C08E28331D24758b69A5E9f383D2bDD1c98", + "startBlock": 45120420, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "KVStore": { diff --git a/packages/sdk/typescript/subgraph/config/ethereum.json b/packages/sdk/typescript/subgraph/config/ethereum.json index 16d869de46..68a944588e 100644 --- a/packages/sdk/typescript/subgraph/config/ethereum.json +++ b/packages/sdk/typescript/subgraph/config/ethereum.json @@ -22,8 +22,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/KVStore.json" }, "Staking": { - "address": "0x05398211bA2046E296fBc9a9D3EB49e3F15C3123", - "startBlock": 16924055, + "address": "0xEf6Da3aB52c33925Be3F84038193a7e1331F51E6", + "startBlock": 21464165, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "RewardPool": { diff --git a/packages/sdk/typescript/subgraph/config/fuji.json b/packages/sdk/typescript/subgraph/config/fuji.json index 6714813cb9..70fbdc6504 100644 --- a/packages/sdk/typescript/subgraph/config/fuji.json +++ b/packages/sdk/typescript/subgraph/config/fuji.json @@ -17,8 +17,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/Escrow.json" }, "Staking": { - "address": "0x9890473B0b93E24d6D1a8Dfb739D577C6f25FFd3", - "startBlock": 26449192, + "address": "0xbA537fEF2442cD48f60686FE1Bbbe40F964a7940", + "startBlock": 37208323, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "KVStore": { diff --git a/packages/sdk/typescript/subgraph/config/moonbase-alpha.json b/packages/sdk/typescript/subgraph/config/moonbase-alpha.json index da9938891e..4f4e3c74bc 100644 --- a/packages/sdk/typescript/subgraph/config/moonbase-alpha.json +++ b/packages/sdk/typescript/subgraph/config/moonbase-alpha.json @@ -17,8 +17,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/Escrow.json" }, "Staking": { - "address": "0xBFC7009F3371F93F3B54DdC8caCd02914a37495c", - "startBlock": 3950927, + "address": "0xbA537fEF2442cD48f60686FE1Bbbe40F964a7940", + "startBlock": 9962637, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "KVStore": { diff --git a/packages/sdk/typescript/subgraph/config/polygon.json b/packages/sdk/typescript/subgraph/config/polygon.json index 10b4e312ae..154eb00dbd 100644 --- a/packages/sdk/typescript/subgraph/config/polygon.json +++ b/packages/sdk/typescript/subgraph/config/polygon.json @@ -17,8 +17,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/Escrow.json" }, "Staking": { - "address": "0xcbAd56bE3f504E98bd70875823d3CC0242B7bB29", - "startBlock": 38858545, + "address": "0x01D115E9E8bF0C58318793624CC662a030D07F1D", + "startBlock": 65832028, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "KVStore": { diff --git a/packages/sdk/typescript/subgraph/config/xlayer-testnet.json b/packages/sdk/typescript/subgraph/config/xlayer-testnet.json index 278081add9..0368adab56 100644 --- a/packages/sdk/typescript/subgraph/config/xlayer-testnet.json +++ b/packages/sdk/typescript/subgraph/config/xlayer-testnet.json @@ -17,8 +17,8 @@ "abi": "../../../../node_modules/@human-protocol/core/abis/Escrow.json" }, "Staking": { - "address": "0x187edb5651464427b312De2AD40F4C679cf6e02D", - "startBlock": 14184126, + "address": "0xeF9849a904dF0d494D69ac0B0a6860a3A7936114", + "startBlock": 20427547, "abi": "../../../../node_modules/@human-protocol/core/abis/Staking.json" }, "KVStore": { From e0cea9e214525de3fb95ca0fd655adc610346b08 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Mon, 23 Dec 2024 18:40:54 +0300 Subject: [PATCH 91/92] [CVAT] Add manifest caching (#2948) * add manifest caching * Update code formatting --- .../examples/cvat/exchange-oracle/poetry.lock | 106 ++++++++++++++++- .../cvat/exchange-oracle/pyproject.toml | 2 + .../cvat/exchange-oracle/src/.env.template | 1 + .../cvat/exchange-oracle/src/chain/escrow.py | 13 ++- .../cvat/exchange-oracle/src/core/config.py | 7 +- .../src/endpoints/throttling.py | 22 +--- .../exchange-oracle/src/endpoints/utils.py | 25 +++- .../exchange-oracle/src/services/cache.py | 107 ++++++++++++++++++ .../exchange-oracle/src/services/redis.py | 7 ++ 9 files changed, 267 insertions(+), 23 deletions(-) create mode 100644 packages/examples/cvat/exchange-oracle/src/services/cache.py create mode 100644 packages/examples/cvat/exchange-oracle/src/services/redis.py diff --git a/packages/examples/cvat/exchange-oracle/poetry.lock b/packages/examples/cvat/exchange-oracle/poetry.lock index 833c968241..75bba93cea 100644 --- a/packages/examples/cvat/exchange-oracle/poetry.lock +++ b/packages/examples/cvat/exchange-oracle/poetry.lock @@ -1,5 +1,25 @@ # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +[[package]] +name = "aiocache" +version = "0.12.3" +description = "multi backend asyncio cache" +optional = false +python-versions = "*" +files = [ + {file = "aiocache-0.12.3-py2.py3-none-any.whl", hash = "sha256:889086fc24710f431937b87ad3720a289f7fc31c4fd8b68e9f918b9bacd8270d"}, + {file = "aiocache-0.12.3.tar.gz", hash = "sha256:f528b27bf4d436b497a1d0d1a8f59a542c153ab1e37c3621713cb376d44c4713"}, +] + +[package.dependencies] +msgpack = {version = ">=0.5.5", optional = true, markers = "extra == \"msgpack\""} +redis = {version = ">=4.2.0", optional = true, markers = "extra == \"redis\""} + +[package.extras] +memcached = ["aiomcache (>=0.5.2)"] +msgpack = ["msgpack (>=0.5.5)"] +redis = ["redis (>=4.2.0)"] + [[package]] name = "aiohttp" version = "3.9.3" @@ -446,6 +466,17 @@ urllib3 = {version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""} [package.extras] crt = ["awscrt (==0.19.19)"] +[[package]] +name = "cachelib" +version = "0.13.0" +description = "A collection of cache libraries in the same API interface." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cachelib-0.13.0-py3-none-any.whl", hash = "sha256:8c8019e53b6302967d4e8329a504acf75e7bc46130291d30188a6e4e58162516"}, + {file = "cachelib-0.13.0.tar.gz", hash = "sha256:209d8996e3c57595bee274ff97116d1d73c4980b2fd9a34c7846cd07fd2e1a48"}, +] + [[package]] name = "cachetools" version = "5.3.2" @@ -2568,6 +2599,79 @@ pycryptodome = "*" typing-extensions = "*" urllib3 = "*" +[[package]] +name = "msgpack" +version = "1.1.0" +description = "MessagePack serializer" +optional = false +python-versions = ">=3.8" +files = [ + {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd"}, + {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d"}, + {file = "msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5"}, + {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5"}, + {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e"}, + {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b"}, + {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f"}, + {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68"}, + {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b"}, + {file = "msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044"}, + {file = "msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f"}, + {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7"}, + {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa"}, + {file = "msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701"}, + {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6"}, + {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59"}, + {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0"}, + {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e"}, + {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6"}, + {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5"}, + {file = "msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88"}, + {file = "msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788"}, + {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d"}, + {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2"}, + {file = "msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420"}, + {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2"}, + {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39"}, + {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f"}, + {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247"}, + {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c"}, + {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b"}, + {file = "msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b"}, + {file = "msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f"}, + {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf"}, + {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330"}, + {file = "msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734"}, + {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e"}, + {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca"}, + {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915"}, + {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d"}, + {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434"}, + {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c"}, + {file = "msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc"}, + {file = "msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f"}, + {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c40ffa9a15d74e05ba1fe2681ea33b9caffd886675412612d93ab17b58ea2fec"}, + {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1ba6136e650898082d9d5a5217d5906d1e138024f836ff48691784bbe1adf96"}, + {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0856a2b7e8dcb874be44fea031d22e5b3a19121be92a1e098f46068a11b0870"}, + {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:471e27a5787a2e3f974ba023f9e265a8c7cfd373632247deb225617e3100a3c7"}, + {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:646afc8102935a388ffc3914b336d22d1c2d6209c773f3eb5dd4d6d3b6f8c1cb"}, + {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13599f8829cfbe0158f6456374e9eea9f44eee08076291771d8ae93eda56607f"}, + {file = "msgpack-1.1.0-cp38-cp38-win32.whl", hash = "sha256:8a84efb768fb968381e525eeeb3d92857e4985aacc39f3c47ffd00eb4509315b"}, + {file = "msgpack-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:879a7b7b0ad82481c52d3c7eb99bf6f0645dbdec5134a4bddbd16f3506947feb"}, + {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1"}, + {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48"}, + {file = "msgpack-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c"}, + {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468"}, + {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74"}, + {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846"}, + {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346"}, + {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b"}, + {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8"}, + {file = "msgpack-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd"}, + {file = "msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325"}, + {file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"}, +] + [[package]] name = "multidict" version = "6.0.4" @@ -4919,4 +5023,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10,<3.13" -content-hash = "49b01380ca146e1c095dafd861b81b11ab34812f483d6db6d2ef010f9f0ba0e0" +content-hash = "b5d8c5e0b1572bcb5ca08cc33ad51abcfa1b657c11d42c9cb7a805abdde96850" diff --git a/packages/examples/cvat/exchange-oracle/pyproject.toml b/packages/examples/cvat/exchange-oracle/pyproject.toml index 042010213b..2b88e605a7 100644 --- a/packages/examples/cvat/exchange-oracle/pyproject.toml +++ b/packages/examples/cvat/exchange-oracle/pyproject.toml @@ -34,6 +34,8 @@ strenum = "^0.4.15" pyjwt = "^2.9.0" starlette = ">=0.40.0" # avoid the vulnerability with multipart/form-data cryptography = "<44.0.0" # human-protocol-sdk -> pgpy dep requires cryptography < 45 +aiocache = {extras = ["msgpack", "redis"], version = "^0.12.3"} # convenient api for redis (async) +cachelib = "^0.13.0" # convenient api for redis (sync) [tool.poetry.group.dev.dependencies] diff --git a/packages/examples/cvat/exchange-oracle/src/.env.template b/packages/examples/cvat/exchange-oracle/src/.env.template index d05a9f1828..ae4b9dfb05 100644 --- a/packages/examples/cvat/exchange-oracle/src/.env.template +++ b/packages/examples/cvat/exchange-oracle/src/.env.template @@ -96,6 +96,7 @@ STORAGE_USE_SSL= ENABLE_CUSTOM_CLOUD_HOST= REQUEST_LOGGING_ENABLED= +MANIFEST_CACHE_TTL= # Core diff --git a/packages/examples/cvat/exchange-oracle/src/chain/escrow.py b/packages/examples/cvat/exchange-oracle/src/chain/escrow.py index d389879289..bc4ac9b51e 100644 --- a/packages/examples/cvat/exchange-oracle/src/chain/escrow.py +++ b/packages/examples/cvat/exchange-oracle/src/chain/escrow.py @@ -1,4 +1,5 @@ import json +from functools import partial from human_protocol_sdk.constants import ChainId, Status from human_protocol_sdk.encryption import Encryption, EncryptionUtils @@ -7,6 +8,7 @@ from src.core.config import Config from src.core.types import OracleWebhookTypes +from src.services.cache import Cache def get_escrow(chain_id: int, escrow_address: str) -> EscrowData: @@ -42,7 +44,7 @@ def validate_escrow( raise ValueError("Escrow doesn't have funds") -def get_escrow_manifest(chain_id: int, escrow_address: str) -> dict: +def download_manifest(chain_id: int, escrow_address: str) -> dict: escrow = get_escrow(chain_id, escrow_address) manifest_content = StorageUtils.download_file_from_url(escrow.manifest_url).decode("utf-8") @@ -57,6 +59,15 @@ def get_escrow_manifest(chain_id: int, escrow_address: str) -> dict: return json.loads(manifest_content) +def get_escrow_manifest(chain_id: int, escrow_address: str) -> dict: + cache = Cache() + return cache.get_or_set_manifest( + escrow_address=escrow_address, + chain_id=chain_id, + set_callback=partial(download_manifest, chain_id, escrow_address), + ) + + def get_available_webhook_types( chain_id: int, escrow_address: str ) -> dict[str, OracleWebhookTypes]: diff --git a/packages/examples/cvat/exchange-oracle/src/core/config.py b/packages/examples/cvat/exchange-oracle/src/core/config.py index 66c5192cf5..cc5d560093 100644 --- a/packages/examples/cvat/exchange-oracle/src/core/config.py +++ b/packages/examples/cvat/exchange-oracle/src/core/config.py @@ -43,9 +43,9 @@ def connection_url(cls) -> str: class RedisConfig: - port = os.environ.get("REDIS_PORT", "6379") + port = int(os.environ.get("REDIS_PORT", "6379")) host = os.environ.get("REDIS_HOST", "0.0.0.0") # noqa: S104 - database = os.environ.get("REDIS_DB", "") + database = int(os.environ.get("REDIS_DB", "0")) user = os.environ.get("REDIS_USER", "") password = os.environ.get("REDIS_PASSWORD", "") use_ssl = to_bool(os.environ.get("REDIS_USE_SSL", "false")) @@ -245,6 +245,9 @@ class FeaturesConfig: profiling_enabled = to_bool(os.getenv("PROFILING_ENABLED", "0")) "Allow to profile specific requests" + manifest_cache_ttl = int(os.getenv("MANIFEST_CACHE_TTL", str(2 * 24 * 60 * 60))) + "TTL for cached manifests" + class CoreConfig: default_assignment_time = int(os.environ.get("DEFAULT_ASSIGNMENT_TIME", 1800)) diff --git a/packages/examples/cvat/exchange-oracle/src/endpoints/throttling.py b/packages/examples/cvat/exchange-oracle/src/endpoints/throttling.py index 2eb1961e4c..38e69cb936 100644 --- a/packages/examples/cvat/exchange-oracle/src/endpoints/throttling.py +++ b/packages/examples/cvat/exchange-oracle/src/endpoints/throttling.py @@ -1,19 +1,18 @@ -from collections.abc import AsyncIterator +from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from typing import Any -import redis.asyncio as redis from fastapi import FastAPI from fastapi_limiter import FastAPILimiter from fastapi_limiter.depends import RateLimiter -from src.core.config import Config +from src.endpoints.utils import register_lifespan_context +from src.services.redis import get_aredis_client @asynccontextmanager -async def lifespan(_: FastAPI) -> AsyncIterator[Any]: - redis_connection = redis.from_url(Config.redis_config.connection_url(), encoding="utf8") - await FastAPILimiter.init(redis_connection) +async def lifespan(_: FastAPI) -> AsyncGenerator[Any, None, None]: + await FastAPILimiter.init(get_aredis_client()) try: yield @@ -22,16 +21,7 @@ async def lifespan(_: FastAPI) -> AsyncIterator[Any]: def add_throttling(app: FastAPI): - router = app.router - original_lifespan_context = router.lifespan_context - - @asynccontextmanager - async def wrapped_lifespan(app: FastAPI) -> AsyncIterator[Any]: - async with lifespan(app), original_lifespan_context(app) as maybe_state: - yield maybe_state - - router.lifespan_context = wrapped_lifespan - return app + return register_lifespan_context(app, lifespan_context=lifespan) __all__ = ["add_throttling", "RateLimiter"] diff --git a/packages/examples/cvat/exchange-oracle/src/endpoints/utils.py b/packages/examples/cvat/exchange-oracle/src/endpoints/utils.py index f0d1d5fdbf..466de6e018 100644 --- a/packages/examples/cvat/exchange-oracle/src/endpoints/utils.py +++ b/packages/examples/cvat/exchange-oracle/src/endpoints/utils.py @@ -1,11 +1,13 @@ -from typing import Annotated, TypeVar +from collections.abc import AsyncGenerator, Callable +from contextlib import asynccontextmanager +from typing import Annotated, Any, TypeVar import fastapi import fastapi.params -T = TypeVar("T") +_T = TypeVar("_T") -OptionalQuery = Annotated[T | None, fastapi.Query()] +OptionalQuery = Annotated[_T | None, fastapi.Query()] """ Required to declare query parameters with default values in Depends. @@ -24,3 +26,20 @@ def endpoint( ): ... """ + +_App = TypeVar("_App", bound=fastapi.FastAPI) + + +def register_lifespan_context( + app: _App, lifespan_context: Callable[[_App], AsyncGenerator[Any, None, None]] +) -> _App: + router = app.router + original_lifespan_context = router.lifespan_context + + @asynccontextmanager + async def wrapped_lifespan(app: _App) -> AsyncGenerator[Any, None, None]: + async with lifespan_context(app), original_lifespan_context(app) as maybe_state: + yield maybe_state + + router.lifespan_context = wrapped_lifespan + return app diff --git a/packages/examples/cvat/exchange-oracle/src/services/cache.py b/packages/examples/cvat/exchange-oracle/src/services/cache.py new file mode 100644 index 0000000000..c706063efb --- /dev/null +++ b/packages/examples/cvat/exchange-oracle/src/services/cache.py @@ -0,0 +1,107 @@ +from collections.abc import Callable +from copy import deepcopy +from typing import Any, ClassVar + +import aiocache.serializers +import cachelib.serializers +from cachelib import BaseCache, RedisCache + +from src.core.config import Config + + +class _RedisSerializer(cachelib.serializers.RedisSerializer): + # The default Pickle-based serializer is not safe, here we use MsgPack as a safer alternative. + # JSON could also be used, but it is less efficient and has restrictions on message contents. + + def __init__(self): + super().__init__() + self._impl = aiocache.serializers.MsgPackSerializer() + + def dump(self, *args, **kwargs): # noqa: ARG002 + raise AssertionError("This method must not be called") + + def load(self, *args, **kwargs): # noqa: ARG002 + raise AssertionError("This method must not be called") + + def dumps(self, value: Any) -> bytes: + return self._impl.dumps(value) + + def loads(self, bvalue: bytes) -> Any: + return self._impl.loads(bvalue) + + +class _RedisCache(RedisCache): + def __init__(self, *args, **kwargs): + kwargs.setdefault("decode_responses", False) + kwargs.setdefault("key_prefix", kwargs.pop("namespace", "")) + + self.serializer = kwargs.pop("serializer", None) or _RedisSerializer() + + super().__init__(*args, **kwargs) + + +class CacheManager: + _configs: ClassVar[dict[str, dict]] = { + "default": { + "class": _RedisCache, + "host": Config.redis_config.host, + "port": Config.redis_config.port, + **({"password": Config.redis_config.password} if Config.redis_config.password else {}), + **({"username": Config.redis_config.user} if Config.redis_config.user else {}), + "ssl": Config.redis_config.use_ssl, + "db": Config.redis_config.database, + "namespace": "cache", + }, + } + + _caches: ClassVar[dict[str, BaseCache]] = {} + + def create_cache(self, name: str, **kwargs) -> BaseCache: + cache_config = deepcopy(self._configs[name]) + cache_config.setdefault("default_timeout", 0) + cache_config.update(kwargs) + + klass = cache_config.pop("class") + return klass(**cache_config) + + def get_cache(self, name: str = "default") -> BaseCache: + # Implements a singleton pattern, doesn't support multithreading + cache = self._caches.get(name) + if cache is None: + cache = self.create_cache(name) + self._caches[name] = cache + + return cache + + +def get_cache(name: str = "default") -> BaseCache: + manager = CacheManager() + return manager.get_cache(name) + + +class Cache: + def _get_cache(self) -> BaseCache: + return get_cache() + + @staticmethod + def _make_key(escrow_address: str, chain_id: int) -> str: + return f"{escrow_address}@{chain_id}" + + def _get_or_set(self, key: str, set_callback, *, ttl: int | None = None): + cache = self._get_cache() + item = cache.get(key) + + if not item: + item = set_callback() + success = cache.set(key, item, timeout=ttl) + if not success: + raise Exception(f"Failed to write key {key} to the cache") + + return item + + def get_or_set_manifest( + self, escrow_address: str, chain_id: int, *, set_callback: Callable[[], dict], **kwargs + ) -> dict: + kwargs.setdefault("ttl", Config.features.manifest_cache_ttl) + key = self._make_key(escrow_address, chain_id) + return self._get_or_set(key, set_callback=set_callback, **kwargs) diff --git a/packages/examples/cvat/exchange-oracle/src/services/redis.py b/packages/examples/cvat/exchange-oracle/src/services/redis.py new file mode 100644 index 0000000000..167f9d54ec --- /dev/null +++ b/packages/examples/cvat/exchange-oracle/src/services/redis.py @@ -0,0 +1,7 @@ +import redis.asyncio as aredis + +from src.core.config import Config + + +def get_aredis_client() -> aredis.Redis: + return aredis.Redis.from_url(Config.redis_config.connection_url(), encoding="utf-8") From 32bfe10aae7023cce19bbd40f3574618b5ba7a41 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Mon, 23 Dec 2024 18:52:21 +0300 Subject: [PATCH 92/92] [CVAT] Bump human sdk to 3.0.8 (#2958) * Bump human sdk to 3.0.8 * Fix merge --- packages/examples/cvat/exchange-oracle/poetry.lock | 8 ++++---- packages/examples/cvat/exchange-oracle/pyproject.toml | 2 +- packages/examples/cvat/recording-oracle/poetry.lock | 8 ++++---- packages/examples/cvat/recording-oracle/pyproject.toml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/examples/cvat/exchange-oracle/poetry.lock b/packages/examples/cvat/exchange-oracle/poetry.lock index 75bba93cea..449002e837 100644 --- a/packages/examples/cvat/exchange-oracle/poetry.lock +++ b/packages/examples/cvat/exchange-oracle/poetry.lock @@ -1991,13 +1991,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "human-protocol-sdk" -version = "3.0.8b0" +version = "3.0.8" description = "A python library to launch escrow contracts to the HUMAN network." optional = false python-versions = "*" files = [ - {file = "human_protocol_sdk-3.0.8b0-py3-none-any.whl", hash = "sha256:749c28b2a1177c3f31c7edcb040afb6b106f6f5e9b480b0a5db21ecab468e448"}, - {file = "human_protocol_sdk-3.0.8b0.tar.gz", hash = "sha256:cc4500dc4e458594933730d339544f86c0597ea68096c5ff291535e23a5a6088"}, + {file = "human_protocol_sdk-3.0.8-py3-none-any.whl", hash = "sha256:20b8d08f41ee906560388bbe3482b699ff6229285b7ccb3b9ea7b1b491e734fd"}, + {file = "human_protocol_sdk-3.0.8.tar.gz", hash = "sha256:537f7569b3f411c5c3d05827c1d1944751f46baaa2608907481312af30a88d62"}, ] [package.dependencies] @@ -5023,4 +5023,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10,<3.13" -content-hash = "b5d8c5e0b1572bcb5ca08cc33ad51abcfa1b657c11d42c9cb7a805abdde96850" +content-hash = "5f6bb7070f8d7cedb1bf66e576aaa6909d2600bb98030473cf15603636e31d51" diff --git a/packages/examples/cvat/exchange-oracle/pyproject.toml b/packages/examples/cvat/exchange-oracle/pyproject.toml index 2b88e605a7..b08e32026f 100644 --- a/packages/examples/cvat/exchange-oracle/pyproject.toml +++ b/packages/examples/cvat/exchange-oracle/pyproject.toml @@ -24,7 +24,7 @@ datumaro = {git = "https://github.com/cvat-ai/datumaro.git", rev = "ff83c00c2c1b boto3 = "^1.28.33" google-cloud-storage = "^2.14.0" pyinstrument = "^4.6.2" -human-protocol-sdk = ">=3.0.8b0,<3.1.0" +human-protocol-sdk = ">=3.0.8,<3.1.0" hexbytes = ">=1.2.0" # required for to_0x_hex() function pydantic = ">=2.6.1,<2.7.0" fastapi-pagination = "^0.12.17" diff --git a/packages/examples/cvat/recording-oracle/poetry.lock b/packages/examples/cvat/recording-oracle/poetry.lock index 41545db4b0..fb454c6414 100644 --- a/packages/examples/cvat/recording-oracle/poetry.lock +++ b/packages/examples/cvat/recording-oracle/poetry.lock @@ -1894,13 +1894,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "human-protocol-sdk" -version = "3.0.8b0" +version = "3.0.8" description = "A python library to launch escrow contracts to the HUMAN network." optional = false python-versions = "*" files = [ - {file = "human_protocol_sdk-3.0.8b0-py3-none-any.whl", hash = "sha256:749c28b2a1177c3f31c7edcb040afb6b106f6f5e9b480b0a5db21ecab468e448"}, - {file = "human_protocol_sdk-3.0.8b0.tar.gz", hash = "sha256:cc4500dc4e458594933730d339544f86c0597ea68096c5ff291535e23a5a6088"}, + {file = "human_protocol_sdk-3.0.8-py3-none-any.whl", hash = "sha256:20b8d08f41ee906560388bbe3482b699ff6229285b7ccb3b9ea7b1b491e734fd"}, + {file = "human_protocol_sdk-3.0.8.tar.gz", hash = "sha256:537f7569b3f411c5c3d05827c1d1944751f46baaa2608907481312af30a88d62"}, ] [package.dependencies] @@ -4708,4 +4708,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10, <3.13" -content-hash = "940378d2c17d34e3f34f2b39131f5de343dc660f370daeb4df92c1b8400b2d58" +content-hash = "753afd54ae56ed72aa334094ef173ad4d697f1fc4dd78e2e2c89439f377e5f60" diff --git a/packages/examples/cvat/recording-oracle/pyproject.toml b/packages/examples/cvat/recording-oracle/pyproject.toml index cf78ffa49b..6b42e915e8 100644 --- a/packages/examples/cvat/recording-oracle/pyproject.toml +++ b/packages/examples/cvat/recording-oracle/pyproject.toml @@ -22,7 +22,7 @@ numpy = "^1.25.2" boto3 = "^1.28.40" google-cloud-storage = "^2.14.0" datumaro = {git = "https://github.com/cvat-ai/datumaro.git", rev = "ff83c00c2c1bc4b8fdfcc55067fcab0a9b5b6b11"} -human-protocol-sdk = ">=3.0.8b0,<3.1.0" +human-protocol-sdk = ">=3.0.8,<3.1.0" hexbytes = ">=1.2.0" # required for to_0x_hex() function starlette = ">=0.40.0" # avoid the vulnerability with multipart/form-data cvat-sdk = "^2.23.1"