Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
try {
setQualificationsOptions(await getQualifications(jobRequest.chainId));
} catch (error) {
console.error('Error fetching data:', error);

Check warning on line 65 in packages/apps/job-launcher/client/src/components/Jobs/Create/CvatJobRequestForm.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected console statement
}
}
};
Expand Down Expand Up @@ -99,6 +99,7 @@
gtPath,
userGuide,
accuracyTarget,
jobBounty,
}: ReturnType<typeof mapCvatFormValues>) => {
let bp = undefined;
if (type === CvatJobType.IMAGE_BOXES_FROM_POINTS) {
Expand Down Expand Up @@ -154,7 +155,8 @@
path: gtPath,
},
userGuide,
accuracyTarget,
accuracyTarget: Number(accuracyTarget),
jobBounty: Number(jobBounty),
},
});
goToNextStep();
Expand Down Expand Up @@ -830,6 +832,35 @@
/>
</FormControl>
</Grid>
<Grid item xs={12} sm={12} md={6}>
<FormControl fullWidth>
<TextField
name="jobBounty"
label="Job bounty"
placeholder="Job bounty"
type="number"
value={values.jobBounty}
onChange={(e) =>
setFieldValue('jobBounty', e.target.value)
}
onBlur={handleBlur}
error={touched.jobBounty && Boolean(errors.jobBounty)}
helperText={errors.jobBounty}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<Tooltip title="Reward per CVAT job chunk used in the manifest.">
<HelpOutlineIcon
color="secondary"
sx={{ cursor: 'pointer' }}
/>
</Tooltip>
</InputAdornment>
),
}}
/>
</FormControl>
</Grid>
</Grid>
</Grid>
</AccordionDetails>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const mapCvatFormValues = (
: [],
userGuide: cvatRequest?.userGuide || '',
accuracyTarget: cvatRequest?.accuracyTarget || 80,
jobBounty: cvatRequest?.jobBounty || 0,
dataProvider: cvatRequest?.data?.dataset?.provider || StorageProviders.AWS,
dataRegion:
(cvatRequest?.data?.dataset?.region as AWSRegions | GCSRegions) || '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const CvatJobRequestValidationSchema = Yup.object().shape({
.required('Accuracy target is required')
.moreThan(0, 'Accuracy target must be greater than 0')
.max(100, 'Accuracy target must be less than or equal to 100'),
jobBounty: Yup.number()
.typeError('Job bounty is required')
.required('Job bounty is required')
.moreThan(0, 'Job bounty must be greater than 0'),
qualifications: Yup.array().of(Yup.object()),
});

Expand Down
2 changes: 2 additions & 0 deletions packages/apps/job-launcher/client/src/constants/cvat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const CVAT_JOB_SIZE = 10;
export const CVAT_VAL_SIZE = 2;
81 changes: 65 additions & 16 deletions packages/apps/job-launcher/client/src/services/job.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,88 @@
import { ChainId } from '@human-protocol/sdk';
import { CVAT_JOB_SIZE, CVAT_VAL_SIZE } from '../constants/cvat';
import {
CreateFortuneJobRequest,
CreateCvatJobRequest,
CreateJobRequest,
FortuneRequest,
CvatRequest,
JobStatus,
JobDetailsResponse,
FortuneFinalResult,
FortuneManifest,
CvatManifest,
JobType,
StorageProviders,
} from '../types';
import api from '../utils/api';
import { getFilenameFromContentDisposition } from '../utils/string';

const buildFortuneManifest = (data: FortuneRequest): FortuneManifest => ({
submissionsRequired: Number(data.fortunesRequested),
requesterTitle: data.title,
requesterDescription: data.description,
requestType: JobType.FORTUNE,
qualifications: data.qualifications,
});

const buildBucketUrl = ({
provider,
region,
bucketName,
path,
}: CvatRequest['data']['dataset']) => {
if (provider === StorageProviders.AWS) {
return `https://${bucketName}.s3.${region}.amazonaws.com${
path ? `/${path.replace(/\/$/, '')}` : ''
}`;
}

return `https://${bucketName}.storage.googleapis.com${path ? `/${path}` : ''}`;
};

const buildCvatManifest = (data: CvatRequest): CvatManifest => ({
data: {
dataUrl: buildBucketUrl(data.data.dataset),
...(data.data.points && {
pointsUrl: buildBucketUrl(data.data.points),
}),
...(data.data.boxes && {
boxesUrl: buildBucketUrl(data.data.boxes),
}),
},
annotation: {
labels: data.labels,
description: data.description,
userGuide: data.userGuide,
type: data.type,
jobSize: CVAT_JOB_SIZE,
...(data.qualifications?.length && {
qualifications: data.qualifications,
}),
},
validation: {
minQuality: Number(data.accuracyTarget) / 100,
valSize: CVAT_VAL_SIZE,
gtUrl: buildBucketUrl(data.groundTruth),
},
jobBounty: String(data.jobBounty),
});

export const createFortuneJob = async (
chainId: number,
data: FortuneRequest,
paymentCurrency: string,
paymentAmount: number | string,
escrowFundToken: string,
) => {
const body: CreateFortuneJobRequest = {
const body: CreateJobRequest<FortuneManifest> = {
chainId,
submissionsRequired: Number(data.fortunesRequested),
requesterTitle: data.title,
requesterDescription: data.description,
requestType: JobType.FORTUNE,
paymentCurrency,
paymentAmount: Number(paymentAmount),
escrowFundToken,
qualifications: data.qualifications,
manifest: buildFortuneManifest(data),
};
await api.post('/job/fortune', body);
await api.post('/job', body);
};

export const createCvatJob = async (
Expand All @@ -38,21 +92,16 @@ export const createCvatJob = async (
paymentAmount: number | string,
escrowFundToken: string,
) => {
const body: CreateCvatJobRequest = {
const body: CreateJobRequest<CvatManifest> = {
chainId,
requesterDescription: data.description,
requestType: data.type,
paymentCurrency,
paymentAmount: Number(paymentAmount),
escrowFundToken,
data: data.data,
labels: data.labels,
minQuality: Number(data.accuracyTarget) / 100,
groundTruth: data.groundTruth,
userGuide: data.userGuide,
type: data.type,
qualifications: data.qualifications,
manifest: buildCvatManifest(data),
};
await api.post('/job/cvat', body);
await api.post('/job', body);
};

export const getJobList = async ({
Expand Down
46 changes: 32 additions & 14 deletions packages/apps/job-launcher/client/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,47 @@ export type FiatPaymentRequest = {
paymentMethodId: string;
};

export type CreateFortuneJobRequest = {
chainId: number;
export type FortuneManifest = {
submissionsRequired: number;
requesterTitle: string;
requesterDescription: string;
paymentCurrency: string;
paymentAmount: number;
escrowFundToken: string;
fundAmount?: number;
requestType: JobType.FORTUNE;
qualifications?: string[];
};

export type CreateCvatJobRequest = {
export type JobRequestType = JobType.FORTUNE | JobType.HCAPTCHA | CvatJobType;

export type CreateJobRequest<TManifest = Record<string, unknown>> = {
chainId: number;
requesterDescription: string;
qualifications?: string[];
requestType: JobRequestType;
paymentCurrency: string;
paymentAmount: number;
escrowFundToken: string;
data: CvatData;
labels: Label[];
minQuality: number;
groundTruth: CvatDataSource;
userGuide: string;
type: CvatJobType;
qualifications?: string[];
manifest: TManifest;
};

export type CvatManifest = {
data: {
dataUrl: string;
pointsUrl?: string;
boxesUrl?: string;
};
annotation: {
labels: Label[];
description: string;
userGuide: string;
type: CvatJobType;
jobSize: number;
qualifications?: string[];
};
validation: {
minQuality: number;
valSize: number;
gtUrl: string;
};
jobBounty: string;
};

export enum CreateJobStep {
Expand Down Expand Up @@ -215,6 +232,7 @@ export type CvatRequest = {
groundTruth: CvatDataSource;
userGuide: string;
accuracyTarget: number;
jobBounty: number;
};

export type JobRequest = {
Expand Down
10 changes: 5 additions & 5 deletions packages/apps/job-launcher/server/src/modules/job/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { faker } from '@faker-js/faker';
import { ChainId } from '@human-protocol/sdk';
import { EscrowFundToken, FortuneJobType } from '../../common/enums/job';
import { PaymentCurrency } from '../../common/enums/payment';
import { JobFortuneDto } from './job.dto';
import { createMockFortuneManifest } from '../manifest/fixtures';
import { JobManifestDto } from './job.dto';
import { JobEntity } from './job.entity';
import { JobStatus } from '../../common/enums/job';

Expand All @@ -14,11 +15,10 @@ const escrowFundTokens = (
Object.values(EscrowFundToken) as EscrowFundToken[]
).filter((c) => c !== EscrowFundToken.HMT);

export const createFortuneJobDto = (overrides = {}): JobFortuneDto => ({
export const createJobManifestDto = (overrides = {}): JobManifestDto => ({
chainId: ChainId.POLYGON_AMOY,
submissionsRequired: faker.number.int({ min: 1, max: 10 }),
requesterTitle: faker.lorem.words(3),
requesterDescription: faker.lorem.sentence(),
requestType: FortuneJobType.FORTUNE,
manifest: createMockFortuneManifest(),
paymentAmount: faker.number.float({ min: 1, max: 100, fractionDigits: 6 }),
paymentCurrency: faker.helpers.arrayElement(paymentCurrencies),
escrowFundToken: faker.helpers.arrayElement(escrowFundTokens),
Expand Down
Loading
Loading