diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/components/mobile/available-jobs-assign-job-button-mobile.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/components/mobile/available-jobs-assign-job-button-mobile.tsx index ea5216a575..3acd1102e0 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/components/mobile/available-jobs-assign-job-button-mobile.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/components/mobile/available-jobs-assign-job-button-mobile.tsx @@ -1,20 +1,14 @@ import { t } from 'i18next'; -import { useParams } from 'react-router-dom'; import { TableButton } from '@/shared/components/ui/table-button'; import { useJobsNotifications } from '../../../hooks'; import { useAssignJobMutation } from '../../hooks/use-assign-job'; import { type AssignJobBody } from '../../../types'; -import { useAddThirstyfiInfoModal } from '../../hooks/use-add-thirstyfi-info-modal'; - -const THIRSTYFI_ADDRESS = '0x5C08438d7d18734c5ee42ECAf81FB1D6A922A9cC'; export function AvailableJobsAssignJobButtonMobile({ assignJobPayload, }: Readonly<{ assignJobPayload: AssignJobBody; }>) { - const { address: oracleAddress } = useParams<{ address: string }>(); - const { openModal } = useAddThirstyfiInfoModal(); const { onJobAssignmentError, onJobAssignmentSuccess } = useJobsNotifications(); @@ -26,20 +20,12 @@ export function AvailableJobsAssignJobButtonMobile({ [`assignJob-${assignJobPayload.escrow_address}`] ); - const isThirstyfi = oracleAddress === THIRSTYFI_ADDRESS; - return ( { - if (isThirstyfi) { - openModal({ ...assignJobPayload }); - } else { - assignJobMutation(assignJobPayload); - } - }} + onClick={() => assignJobMutation(assignJobPayload)} size="small" sx={{ marginTop: '15px', diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-add-thirstyfi-info-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-add-thirstyfi-info-modal.tsx deleted file mode 100644 index 49be0eaf6f..0000000000 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-add-thirstyfi-info-modal.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useModal } from '@/shared/contexts/modal-context'; -import { ThirstyfiInfoModal } from '../thirstyfi-info-modal'; - -interface AddThirstyfiInfoModalProps { - escrow_address: string; - chain_id: number; -} - -export function useAddThirstyfiInfoModal() { - const { openModal, closeModal } = useModal(); - - return { - openModal: ({ escrow_address, chain_id }: AddThirstyfiInfoModalProps) => { - openModal({ - content: ( - - ), - }); - }, - }; -} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-get-available-jobs-columns.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-get-available-jobs-columns.tsx index 41226f9e8f..753ad47200 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-get-available-jobs-columns.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-get-available-jobs-columns.tsx @@ -2,7 +2,6 @@ import type { MRT_ColumnDef } from 'material-react-table'; import { t } from 'i18next'; import { Grid } from '@mui/material'; import { useMemo } from 'react'; -import { useParams } from 'react-router-dom'; import { getNetworkName } from '@/modules/smart-contracts/get-network-name'; import { Chip } from '@/shared/components/ui/chip'; import { TableButton } from '@/shared/components/ui/table-button'; @@ -17,18 +16,13 @@ import { } from '../components'; import { type AvailableJob } from '../../types'; import { useAssignJobMutation } from './use-assign-job'; -import { useAddThirstyfiInfoModal } from './use-add-thirstyfi-info-modal'; const COL_SIZE = 100; const COL_SIZE_LG = 200; -const THIRSTYFI_ADDRESS = '0x5C08438d7d18734c5ee42ECAf81FB1D6A922A9cC'; export const useGetAvailableJobsColumns = ( chainIdsEnabled: number[] ): MRT_ColumnDef[] => { - const { openModal } = useAddThirstyfiInfoModal(); - const { address: oracleAddress } = useParams<{ address: string }>(); - return useMemo( () => [ { @@ -127,20 +121,12 @@ export const useGetAvailableJobsColumns = ( [`assignJob-${escrow_address}`] ); - const isThirstyfi = oracleAddress === THIRSTYFI_ADDRESS; - return ( { - if (isThirstyfi) { - openModal({ escrow_address, chain_id }); - } else { - assignJobMutation({ escrow_address, chain_id }); - } - }} + onClick={() => assignJobMutation({ escrow_address, chain_id })} > {t('worker.jobs.selectJob')} @@ -149,6 +135,6 @@ export const useGetAvailableJobsColumns = ( }, }, ], - [chainIdsEnabled, openModal, oracleAddress] + [chainIdsEnabled] ); }; diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/thirstyfi-info-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/thirstyfi-info-modal.tsx deleted file mode 100644 index c8faa3bd4b..0000000000 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/thirstyfi-info-modal.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { z } from 'zod'; -import { FormProvider, useForm } from 'react-hook-form'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import { useTranslation } from 'react-i18next'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { useQueryClient } from '@tanstack/react-query'; -import Link from '@mui/material/Link'; -import { Button } from '@/shared/components/ui/button'; -import { Input } from '@/shared/components/data-entry/input'; -import { useIsMobile } from '@/shared/hooks/use-is-mobile'; -import { useJobsNotifications } from '../hooks'; -import { useAssignJobMutation } from './hooks/use-assign-job'; - -interface ThirstyfiInfoModalProps { - escrow_address: string; - chain_id: number; - onClose?: () => void; -} - -export function ThirstyfiInfoModal({ - escrow_address, - chain_id, - onClose, -}: ThirstyfiInfoModalProps) { - const { t } = useTranslation(); - const isMobile = useIsMobile(); - - const methods = useForm({ - defaultValues: { - wallet_address: '', - api_key: '', - api_secret: '', - }, - resolver: zodResolver( - z.object({ - wallet_address: z - .string() - .trim() - .length(42, t('thirstyfiModal.walletAddressError')) - .regex(/^0x/, t('thirstyfiModal.walletAddressRegexError')), - api_key: z.string().trim().min(1, t('validation.required')), - api_secret: z.string().trim().min(1, t('validation.required')), - }) - ), - }); - - const { onJobAssignmentError, onJobAssignmentSuccess } = - useJobsNotifications(); - const queryClient = useQueryClient(); - - const { mutate: assignJobMutation, isPending } = useAssignJobMutation( - { - onSuccess: () => { - const queryKey = isMobile - ? ['availableJobsInfinite'] - : ['availableJobs']; - onJobAssignmentSuccess(); - void queryClient.invalidateQueries({ queryKey }).then(() => { - methods.reset(); - onClose?.(); - }); - }, - onError: onJobAssignmentError, - }, - [`assignJob-${escrow_address}`] - ); - - const onSubmit = (data: { - wallet_address: string; - api_key: string; - api_secret: string; - }) => { - assignJobMutation({ escrow_address, chain_id, ...data }); - }; - - const handleSubmit = (event: React.FormEvent) => { - void methods.handleSubmit(onSubmit)(event); - }; - - return ( - -
- - - {t('thirstyfiModal.title')} - - - {t('thirstyfiModal.tutorialText1')} - - {t('thirstyfiModal.tutorialLink')} - - {t('thirstyfiModal.tutorialText2')} - - - - - {t('thirstyfiModal.walletAddressHelp', { - defaultValue: t('thirstyfiModal.walletAddressTooltip'), - })} - - - - - - {t('thirstyfiModal.apiKeyHelp', { - defaultValue: t('thirstyfiModal.apiKeyTooltip'), - })} - - - - - - {t('thirstyfiModal.apiSecretHelp', { - defaultValue: t('thirstyfiModal.apiSecretTooltip'), - })} - - - - -
-
- ); -} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx index f625eca99b..886dc72875 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx @@ -35,9 +35,7 @@ export function MyJobsTableActions({ > {t('worker.jobs.solve')}
- {job.escrow_address !== 'thirstyfi-task' && ( - - )} + ); } diff --git a/packages/apps/human-app/frontend/src/shared/i18n/en.json b/packages/apps/human-app/frontend/src/shared/i18n/en.json index 951559cb63..17bc5ea695 100644 --- a/packages/apps/human-app/frontend/src/shared/i18n/en.json +++ b/packages/apps/human-app/frontend/src/shared/i18n/en.json @@ -504,22 +504,6 @@ "image_skeletons_from_boxes": "Skeletons from Bounding Boxes", "image_polygons": "Polygons", "audio_transcription": "Audio Transcription", - "audio_attribute_annotation": "Audio Attribute Annotation", - "thirstyfi": "ThirstyFi" - }, - "thirstyfiModal": { - "title": "This information is required to participate in this task", - "tutorialText1": "Before filling out the form below, please checkout ", - "tutorialText2": " for instructions.", - "tutorialLink": "thirsty.fi", - "walletAddress": "Wallet address", - "walletAddressTooltip": "Your EVM wallet address on Polygon network. Used to receive the rewards.", - "apiKey": "API key", - "apiKeyTooltip": "Your exchange API key (read account details is enough). Stored encrypted and only used server-side to fetch your balance.", - "apiSecret": "API secret", - "apiSecretTooltip": "Your exchange API secret. Stored encrypted and only used server-side to fetch your balance.", - "submitBtn": "Submit", - "walletAddressError": "Wallet address must be exactly 42 characters", - "walletAddressRegexError": "Wallet address must start with 0x" + "audio_attribute_annotation": "Audio Attribute Annotation" } } diff --git a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts index bbfa432d1c..79e3a48663 100644 --- a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts +++ b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts @@ -1,7 +1,6 @@ import { Mapper } from '@automapper/core'; import { InjectMapper } from '@automapper/nestjs'; import { - BadRequestException, Body, Controller, Get, @@ -25,19 +24,11 @@ import { ResignJobCommand, ResignJobDto, } from './model/job-assignment.model'; -import { ChainId } from '@human-protocol/sdk'; -import axios from 'axios'; -import { JobStatus } from '../../common/enums/global-common'; -import logger from '../../logger'; @ApiTags('Job-Assignment') @ApiBearerAuth() @Controller('/assignment') export class JobAssignmentController { - private readonly logger = logger.child({ - context: JobAssignmentController.name, - }); - constructor( private readonly service: JobAssignmentService, @InjectMapper() private readonly mapper: Mapper, @@ -56,47 +47,6 @@ export class JobAssignmentController { if (!req.user?.is_stake_eligible) { throw new ForbiddenException('Stake requirement not met'); } - // TODO: temporal - THIRSTYFI - if (jobAssignmentDto.escrow_address === 'thirstyfi-task') { - if (new Date(process.env.THIRSTYFI_TASK_EXPIRATION_DATE!) < new Date()) { - throw new BadRequestException('Expired task'); - } - try { - const { data } = await axios.post( - `${process.env.THIRSTIFY_EXO}/join`, - { - walletAddress: jobAssignmentDto.wallet_address, - email: req.user.email, - apiKey: jobAssignmentDto.api_key, - apiSecret: jobAssignmentDto.api_secret, - }, - { - headers: { - Authorization: `Bearer ${process.env.THIRSTIFY_TOKEN}`, - 'Content-Type': 'application/json', - }, - }, - ); - - return { - assignment_id: data.id, - escrow_address: 'thirstyfi-task', - chain_id: ChainId.POLYGON, - job_type: 'thirstyfi', - status: 'ACTIVE', - reward_amount: '5 - 50', - reward_token: 'USDT', - created_at: new Date().toISOString(), - expires_at: process.env.THIRSTYFI_TASK_EXPIRATION_DATE ?? '', - }; - } catch (error) { - this.logger.error('Failed to assign thirstyfi job', { - userId: req.user.user_id, - error, - }); - throw new BadRequestException(error.response.data.error); - } - } const jobAssignmentCommand = this.mapper.map( jobAssignmentDto, @@ -125,50 +75,6 @@ export class JobAssignmentController { results: [], }; } - // TODO: temporal - THIRSTYFI - if ( - jobsAssignmentParamsDto.oracle_address === - process.env.THIRSTYFI_ORACLE_ADDRESS - ) { - const { data } = await axios.get( - `${process.env.THIRSTIFY_EXO}/participant`, - { - params: { email: req.user.email }, - headers: { Authorization: `Bearer ${process.env.THIRSTIFY_TOKEN}` }, - }, - ); - return Number(data?.id ?? 0) <= 0 - ? { - page: 0, - page_size: 1, - total_pages: 1, - total_results: 0, - results: [], - } - : { - page: 0, - page_size: 1, - total_pages: 1, - total_results: 1, - results: [ - { - chain_id: ChainId.POLYGON, - assignment_id: data.id, - escrow_address: 'thirstyfi-task', - job_type: 'thirstyfi', - reward_amount: '5 - 50', - reward_token: 'USDT', - status: - data.status === 'pending' - ? JobStatus.ACTIVE - : JobStatus.COMPLETED, - created_at: new Date().toISOString(), - expires_at: process.env.THIRSTYFI_TASK_EXPIRATION_DATE, - url: 'https://thirsty.fi/blog/campaign-human-protocol', - } as any, - ], - }; - } const jobsAssignmentParamsCommand = this.mapper.map( jobsAssignmentParamsDto, JobsFetchParamsDto, diff --git a/packages/apps/human-app/server/src/modules/job-assignment/model/job-assignment.model.ts b/packages/apps/human-app/server/src/modules/job-assignment/model/job-assignment.model.ts index fec22d2c06..df306bf0f9 100644 --- a/packages/apps/human-app/server/src/modules/job-assignment/model/job-assignment.model.ts +++ b/packages/apps/human-app/server/src/modules/job-assignment/model/job-assignment.model.ts @@ -19,22 +19,6 @@ export class JobAssignmentDto { @IsString() @ApiProperty() escrow_address: string; - // TODO: temporal - THIRSTYFI - @AutoMap() - @IsOptional() - @IsString() - @ApiPropertyOptional({ description: 'Optional wallet address for Thirstyfi' }) - wallet_address?: string; - @AutoMap() - @IsOptional() - @IsString() - @ApiPropertyOptional({ description: 'Optional api_key for Thirstyfi' }) - api_key?: string; - @AutoMap() - @IsOptional() - @IsString() - @ApiPropertyOptional({ description: 'Optional api_secret for Thirstyfi' }) - api_secret?: string; @AutoMap() @IsNumber() @Type(() => Number) diff --git a/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts b/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts index 85fe4c11f4..d2908c1c28 100644 --- a/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts +++ b/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts @@ -22,9 +22,6 @@ import { JobsDiscoveryParamsDto, JobsDiscoveryResponse, } from './model/jobs-discovery.model'; -import { ChainId } from '@human-protocol/sdk'; -import { JobStatus } from '../../common/enums/global-common'; -import axios from 'axios'; @Controller() @ApiBearerAuth() @@ -63,63 +60,6 @@ export class JobsDiscoveryController { }; } - // TODO: temporal - THIRSTYFI - if ( - jobsDiscoveryParamsDto.oracle_address === - process.env.THIRSTYFI_ORACLE_ADDRESS - ) { - let data: any; - - if (new Date(process.env.THIRSTYFI_TASK_EXPIRATION_DATE!) >= new Date()) { - const response = await axios.get( - `${process.env.THIRSTIFY_EXO}/participant`, - { - params: { email: req.user.email }, - headers: { Authorization: `Bearer ${process.env.THIRSTIFY_TOKEN}` }, - }, - ); - data = response.data; - - return (data?.id ?? 0 > 0) - ? { - page: 0, - page_size: 1, - total_pages: 1, - total_results: 0, - results: [], - } - : { - page: 0, - page_size: 1, - total_pages: 1, - total_results: 1, - results: [ - { - chain_id: ChainId.POLYGON, - escrow_address: 'thirstyfi-task', - job_type: 'thirstyfi', - job_description: - 'Check job description at https://thirsty.fi/blog/campaign-human-protocol', - reward_amount: '5 - 50', - reward_token: 'USDT', - status: JobStatus.ACTIVE, - created_at: new Date().toISOString(), - updated_at: new Date().toISOString(), - qualifications: [], - }, - ], - }; - } - - return { - page: 0, - page_size: 1, - total_pages: 1, - total_results: 0, - results: [], - }; - } - const jobsDiscoveryParamsCommand: JobsDiscoveryParamsCommand = this.mapper.map( jobsDiscoveryParamsDto, 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 a6d474d319..5adaa96875 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 @@ -21,7 +21,6 @@ import { GetOraclesQuery, } from './model/oracle-discovery.model'; import { OracleDiscoveryService } from './oracle-discovery.service'; -import { ChainId } from '@human-protocol/sdk'; @ApiTags('Oracle-Discovery') @ApiBearerAuth() @@ -52,32 +51,6 @@ export class OracleDiscoveryController { const command = this.mapper.map(query, GetOraclesQuery, GetOraclesCommand); const oracles = await this.oracleDiscoveryService.getOracles(command); - // TODO: temporal - THIRSTYFI - const thisrtyOracle = new DiscoveredOracle({ - id: 'thisrty-oracle', - address: process.env.THIRSTYFI_ORACLE_ADDRESS ?? '', - chainId: ChainId.POLYGON, - stakedAmount: 0n, - lockedAmount: 0n, - lockedUntilTimestamp: 0, - withdrawnAmount: 0n, - slashedAmount: 0n, - amountJobsProcessed: 0n, - role: 'exchange_oracle', - url: ' ', - jobTypes: ['thirstyfi'], - name: 'ThirstyFi', - registrationNeeded: false, - registrationInstructions: null, - publicKey: null, - webhookUrl: null, - website: null, - fee: null, - reputationNetworks: [], - category: null, - }); - oracles.push(thisrtyOracle); - return oracles; } } 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 3e6caaacce..58df22e460 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 @@ -6,9 +6,9 @@ import { OracleDiscoveryService } from '../oracle-discovery.service'; import { oracleDiscoveryServiceMock } from './oracle-discovery.service.mock'; import { GetOraclesQuery, - // DiscoveredOracle, + DiscoveredOracle, } from '../model/oracle-discovery.model'; -// import { generateOracleDiscoveryResponseBody } from './oracle-discovery.fixture'; +import { generateOracleDiscoveryResponseBody } from './oracle-discovery.fixture'; import { OracleDiscoveryProfile } from '../oracle-discovery.mapper.profile'; import { EnvironmentConfigService } from '../../../common/config/environment-config.service'; import { CommonConfigModule } from '../../../common/config/common-config.module'; @@ -18,7 +18,7 @@ import { ChainId } from '@human-protocol/sdk'; describe('OracleDiscoveryController', () => { let controller: OracleDiscoveryController; - // let serviceMock: OracleDiscoveryService; + let serviceMock: OracleDiscoveryService; const configServiceMock: Partial = { cacheTtlOracleDiscovery: 600, chainIdsEnabled: [ChainId.POLYGON, ChainId.MAINNET], @@ -51,7 +51,7 @@ describe('OracleDiscoveryController', () => { controller = module.get( OracleDiscoveryController, ); - // serviceMock = module.get(OracleDiscoveryService); + serviceMock = module.get(OracleDiscoveryService); }); it('should be defined', () => { @@ -59,19 +59,16 @@ describe('OracleDiscoveryController', () => { }); describe('oracle discovery', () => { - //TODO: temporal - THIRSTYFI - // it('should return discovered oracles', async () => { - // const dtoFixture = { - // selected_job_types: ['job-type-1', 'job-type-2'], - // } as GetOraclesQuery; - // const result: DiscoveredOracle[] = await controller.getOracles( - // { qualifications: [] } as any, - // dtoFixture, - // ); - // const expectedResponse = generateOracleDiscoveryResponseBody(); - // expect(serviceMock.getOracles).toHaveBeenCalled(); - // expect(result).toEqual(expectedResponse); - // }); + it('should return discovered oracles', async () => { + const dtoFixture = { + selected_job_types: ['job-type-1', 'job-type-2'], + } as GetOraclesQuery; + const result: DiscoveredOracle[] = + await controller.getOracles(dtoFixture); + const expectedResponse = generateOracleDiscoveryResponseBody(); + expect(serviceMock.getOracles).toHaveBeenCalled(); + expect(result).toEqual(expectedResponse); + }); it('should throw an error if jobsDiscoveryFlag is disabled', async () => { const dtoFixture = {