@human-protocol/sdk 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/example/simple-existing-job.ts +86 -0
- package/example/simple-new-job-public.ts +74 -0
- package/example/simple-new-job.ts +72 -0
- package/package.json +9 -4
- package/src/error.ts +5 -0
- package/src/job.ts +215 -35
- package/src/storage.ts +5 -4
- package/src/types.ts +13 -0
- package/src/utils.ts +67 -1
- package/test/job.test.ts +716 -0
- package/test/utils/constants.ts +30 -0
- package/test/utils/manifest.ts +33 -0
package/test/job.test.ts
ADDED
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
import { getPublicURL } from './../src/storage';
|
|
2
|
+
import { EscrowStatus, Job } from '../src';
|
|
3
|
+
import { upload } from '../src/storage';
|
|
4
|
+
import { toFullDigit } from '../src/utils';
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_GAS_PAYER_ADDR,
|
|
7
|
+
DEFAULT_GAS_PAYER_PRIVKEY,
|
|
8
|
+
DEFAULT_HMTOKEN_ADDR,
|
|
9
|
+
DEFAULT_STAKING_ADDR,
|
|
10
|
+
NOT_TRUSTED_OPERATOR_PRIVKEY,
|
|
11
|
+
REPUTATION_ORACLE_PRIVKEY,
|
|
12
|
+
TRUSTED_OPERATOR1_ADDR,
|
|
13
|
+
TRUSTED_OPERATOR1_PRIVKEY,
|
|
14
|
+
TRUSTED_OPERATOR2_ADDR,
|
|
15
|
+
WORKER1_ADDR,
|
|
16
|
+
WORKER2_ADDR,
|
|
17
|
+
WORKER3_ADDR,
|
|
18
|
+
} from './utils/constants';
|
|
19
|
+
import { manifest } from './utils/manifest';
|
|
20
|
+
|
|
21
|
+
jest.mock('../src/storage', () => ({
|
|
22
|
+
...jest.requireActual('../src/storage'),
|
|
23
|
+
upload: jest.fn().mockResolvedValue({
|
|
24
|
+
key: 'uploaded-key',
|
|
25
|
+
hash: 'uploaded-hash',
|
|
26
|
+
}),
|
|
27
|
+
download: jest.fn().mockResolvedValue({
|
|
28
|
+
results: 0,
|
|
29
|
+
}),
|
|
30
|
+
getPublicURL: jest.fn().mockResolvedValue('public-url'),
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
const setupJob = async (job: Job) => {
|
|
34
|
+
await job.initialize();
|
|
35
|
+
await job.stake(1);
|
|
36
|
+
await job.launch();
|
|
37
|
+
await job.setup();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
describe('Test Job', () => {
|
|
41
|
+
describe('New job', () => {
|
|
42
|
+
let job: Job;
|
|
43
|
+
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
job = new Job({
|
|
46
|
+
gasPayer: DEFAULT_GAS_PAYER_PRIVKEY,
|
|
47
|
+
reputationOracle: REPUTATION_ORACLE_PRIVKEY,
|
|
48
|
+
manifest: manifest,
|
|
49
|
+
hmTokenAddr: DEFAULT_HMTOKEN_ADDR,
|
|
50
|
+
stakingAddr: DEFAULT_STAKING_ADDR,
|
|
51
|
+
logLevel: 'error',
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
jest.clearAllMocks();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('Should be able to initializes the job by deploying escrow factory', async () => {
|
|
60
|
+
const initialized = await job.initialize();
|
|
61
|
+
expect(initialized).toBe(true);
|
|
62
|
+
|
|
63
|
+
expect(await job.contractData?.factory?.address).not.toBeNull();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('Should be able to launch the job after staking', async () => {
|
|
67
|
+
// Fail to launch the job before initialization
|
|
68
|
+
expect(await job.launch()).toBe(false);
|
|
69
|
+
|
|
70
|
+
await job.initialize();
|
|
71
|
+
await job.stake(1);
|
|
72
|
+
|
|
73
|
+
expect(await job.launch()).toBe(true);
|
|
74
|
+
expect(await job.status()).toBe(EscrowStatus.Launched);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('Should be able to setup the job', async () => {
|
|
78
|
+
// Fail to setup the job before launch
|
|
79
|
+
expect(await job.setup()).toBe(false);
|
|
80
|
+
|
|
81
|
+
await job.initialize();
|
|
82
|
+
await job.stake(1);
|
|
83
|
+
|
|
84
|
+
await job.launch();
|
|
85
|
+
|
|
86
|
+
expect(await job.setup()).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('Should be able to add trusted handlers', async () => {
|
|
90
|
+
await job.initialize();
|
|
91
|
+
await job.stake(1);
|
|
92
|
+
|
|
93
|
+
await job.launch();
|
|
94
|
+
|
|
95
|
+
expect(await job.isTrustedHandler(DEFAULT_GAS_PAYER_ADDR)).toBe(true);
|
|
96
|
+
|
|
97
|
+
expect(
|
|
98
|
+
await job.addTrustedHandlers([
|
|
99
|
+
TRUSTED_OPERATOR1_ADDR,
|
|
100
|
+
TRUSTED_OPERATOR2_ADDR,
|
|
101
|
+
])
|
|
102
|
+
).toBe(true);
|
|
103
|
+
|
|
104
|
+
expect(await job.isTrustedHandler(TRUSTED_OPERATOR1_ADDR)).toBe(true);
|
|
105
|
+
expect(await job.isTrustedHandler(TRUSTED_OPERATOR2_ADDR)).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('Should be able to bulk payout workers', async () => {
|
|
109
|
+
await setupJob(job);
|
|
110
|
+
|
|
111
|
+
expect(
|
|
112
|
+
await job.bulkPayout(
|
|
113
|
+
[
|
|
114
|
+
{
|
|
115
|
+
address: WORKER1_ADDR,
|
|
116
|
+
amount: 20,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
address: WORKER2_ADDR,
|
|
120
|
+
amount: 50,
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
{}
|
|
124
|
+
)
|
|
125
|
+
).toBe(true);
|
|
126
|
+
|
|
127
|
+
// The escrow contract is still in Partial state as there's still balance left.
|
|
128
|
+
expect((await job.balance())?.toString()).toBe(
|
|
129
|
+
toFullDigit(30).toString()
|
|
130
|
+
);
|
|
131
|
+
expect(await job.status()).toBe(EscrowStatus.Partial);
|
|
132
|
+
|
|
133
|
+
// Trying to pay more than the contract balance results in failure.
|
|
134
|
+
expect(
|
|
135
|
+
await job.bulkPayout(
|
|
136
|
+
[
|
|
137
|
+
{
|
|
138
|
+
address: WORKER3_ADDR,
|
|
139
|
+
amount: 50,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
{}
|
|
143
|
+
)
|
|
144
|
+
).toBe(false);
|
|
145
|
+
|
|
146
|
+
// Paying the remaining amount empties the escrow and updates the status correctly.
|
|
147
|
+
expect(
|
|
148
|
+
await job.bulkPayout(
|
|
149
|
+
[
|
|
150
|
+
{
|
|
151
|
+
address: WORKER3_ADDR,
|
|
152
|
+
amount: 30,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
{}
|
|
156
|
+
)
|
|
157
|
+
).toBe(true);
|
|
158
|
+
expect((await job.balance())?.toString()).toBe(toFullDigit(0).toString());
|
|
159
|
+
expect(await job.status()).toBe(EscrowStatus.Paid);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('Should encrypt result, when bulk paying out workers', async () => {
|
|
163
|
+
await setupJob(job);
|
|
164
|
+
|
|
165
|
+
jest.clearAllMocks();
|
|
166
|
+
const finalResults = { results: 0 };
|
|
167
|
+
await job.bulkPayout(
|
|
168
|
+
[
|
|
169
|
+
{
|
|
170
|
+
address: WORKER1_ADDR,
|
|
171
|
+
amount: 100,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
finalResults,
|
|
175
|
+
true
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
expect(upload).toHaveBeenCalledWith(
|
|
179
|
+
job.storageAccessData,
|
|
180
|
+
finalResults,
|
|
181
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
182
|
+
true,
|
|
183
|
+
false
|
|
184
|
+
);
|
|
185
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('Should not encrypt result, when bulk paying out workers', async () => {
|
|
189
|
+
await setupJob(job);
|
|
190
|
+
|
|
191
|
+
jest.clearAllMocks();
|
|
192
|
+
const finalResults = { results: 0 };
|
|
193
|
+
await job.bulkPayout(
|
|
194
|
+
[
|
|
195
|
+
{
|
|
196
|
+
address: WORKER1_ADDR,
|
|
197
|
+
amount: 100,
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
finalResults,
|
|
201
|
+
false
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
expect(upload).toHaveBeenCalledWith(
|
|
205
|
+
job.storageAccessData,
|
|
206
|
+
finalResults,
|
|
207
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
208
|
+
false,
|
|
209
|
+
false
|
|
210
|
+
);
|
|
211
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('Should store result in private storage, when bulk paying out workers', async () => {
|
|
215
|
+
await setupJob(job);
|
|
216
|
+
|
|
217
|
+
jest.clearAllMocks();
|
|
218
|
+
const finalResults = { results: 0 };
|
|
219
|
+
await job.bulkPayout(
|
|
220
|
+
[
|
|
221
|
+
{
|
|
222
|
+
address: WORKER1_ADDR,
|
|
223
|
+
amount: 100,
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
finalResults,
|
|
227
|
+
false,
|
|
228
|
+
false
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
expect(upload).toHaveBeenCalledWith(
|
|
232
|
+
job.storageAccessData,
|
|
233
|
+
finalResults,
|
|
234
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
235
|
+
false,
|
|
236
|
+
false
|
|
237
|
+
);
|
|
238
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('Should store result in public storage, when bulk paying out workers', async () => {
|
|
242
|
+
await setupJob(job);
|
|
243
|
+
|
|
244
|
+
jest.clearAllMocks();
|
|
245
|
+
const finalResults = { results: 0 };
|
|
246
|
+
await job.bulkPayout(
|
|
247
|
+
[
|
|
248
|
+
{
|
|
249
|
+
address: WORKER1_ADDR,
|
|
250
|
+
amount: 50,
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
finalResults,
|
|
254
|
+
false,
|
|
255
|
+
true
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
expect(upload).toHaveBeenCalledWith(
|
|
259
|
+
job.storageAccessData,
|
|
260
|
+
finalResults,
|
|
261
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
262
|
+
false,
|
|
263
|
+
true
|
|
264
|
+
);
|
|
265
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
266
|
+
expect(getPublicURL).toHaveBeenCalledTimes(1);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('Should return final result', async () => {
|
|
270
|
+
await setupJob(job);
|
|
271
|
+
|
|
272
|
+
const finalResults = { results: 0 };
|
|
273
|
+
await job.bulkPayout(
|
|
274
|
+
[
|
|
275
|
+
{
|
|
276
|
+
address: WORKER1_ADDR,
|
|
277
|
+
amount: 100,
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
finalResults,
|
|
281
|
+
true
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
expect(JSON.stringify(await job.finalResults())).toBe(
|
|
285
|
+
JSON.stringify(finalResults)
|
|
286
|
+
);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('Should be able to abort the job', async () => {
|
|
290
|
+
await setupJob(job);
|
|
291
|
+
|
|
292
|
+
expect(await job.abort()).toBe(true);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('Should be able to abort partially paid job', async () => {
|
|
296
|
+
await setupJob(job);
|
|
297
|
+
|
|
298
|
+
const finalResults = { results: 0 };
|
|
299
|
+
await job.bulkPayout(
|
|
300
|
+
[
|
|
301
|
+
{
|
|
302
|
+
address: WORKER1_ADDR,
|
|
303
|
+
amount: 50,
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
finalResults,
|
|
307
|
+
true
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
expect(await job.abort()).toBe(true);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('Should not be able to abort fully paid job', async () => {
|
|
314
|
+
await setupJob(job);
|
|
315
|
+
|
|
316
|
+
const finalResults = { results: 0 };
|
|
317
|
+
await job.bulkPayout(
|
|
318
|
+
[
|
|
319
|
+
{
|
|
320
|
+
address: WORKER1_ADDR,
|
|
321
|
+
amount: 100,
|
|
322
|
+
},
|
|
323
|
+
],
|
|
324
|
+
finalResults,
|
|
325
|
+
true
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
expect(await job.abort()).toBe(false);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('Should be able to cancel the job', async () => {
|
|
332
|
+
await setupJob(job);
|
|
333
|
+
|
|
334
|
+
expect(await job.cancel()).toBe(true);
|
|
335
|
+
expect((await job.balance())?.toString()).toBe(toFullDigit(0).toString());
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('Should be able to cancel partially paid job', async () => {
|
|
339
|
+
await setupJob(job);
|
|
340
|
+
|
|
341
|
+
const finalResults = { results: 0 };
|
|
342
|
+
await job.bulkPayout(
|
|
343
|
+
[
|
|
344
|
+
{
|
|
345
|
+
address: WORKER1_ADDR,
|
|
346
|
+
amount: 50,
|
|
347
|
+
},
|
|
348
|
+
],
|
|
349
|
+
finalResults,
|
|
350
|
+
true
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
expect(await job.cancel()).toBe(true);
|
|
354
|
+
expect((await job.balance())?.toString()).toBe(toFullDigit(0).toString());
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it('Should not be able to cancel paid job', async () => {
|
|
358
|
+
await setupJob(job);
|
|
359
|
+
|
|
360
|
+
const finalResults = { results: 0 };
|
|
361
|
+
await job.bulkPayout(
|
|
362
|
+
[
|
|
363
|
+
{
|
|
364
|
+
address: WORKER1_ADDR,
|
|
365
|
+
amount: 100,
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
finalResults,
|
|
369
|
+
true
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
expect(await job.cancel()).toBe(false);
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
describe('Access existing job from trusted handler', () => {
|
|
377
|
+
let job: Job;
|
|
378
|
+
|
|
379
|
+
beforeEach(async () => {
|
|
380
|
+
const originalJob = new Job({
|
|
381
|
+
gasPayer: DEFAULT_GAS_PAYER_PRIVKEY,
|
|
382
|
+
reputationOracle: REPUTATION_ORACLE_PRIVKEY,
|
|
383
|
+
manifest: manifest,
|
|
384
|
+
hmTokenAddr: DEFAULT_HMTOKEN_ADDR,
|
|
385
|
+
stakingAddr: DEFAULT_STAKING_ADDR,
|
|
386
|
+
trustedHandlers: [TRUSTED_OPERATOR1_PRIVKEY],
|
|
387
|
+
logLevel: 'error',
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
await setupJob(originalJob);
|
|
391
|
+
|
|
392
|
+
job = new Job({
|
|
393
|
+
gasPayer: NOT_TRUSTED_OPERATOR_PRIVKEY,
|
|
394
|
+
hmTokenAddr: DEFAULT_HMTOKEN_ADDR,
|
|
395
|
+
reputationOracle: REPUTATION_ORACLE_PRIVKEY,
|
|
396
|
+
escrowAddr: originalJob.contractData?.escrowAddr,
|
|
397
|
+
factoryAddr: originalJob.contractData?.factoryAddr,
|
|
398
|
+
trustedHandlers: [TRUSTED_OPERATOR1_PRIVKEY],
|
|
399
|
+
logLevel: 'error',
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
afterEach(() => {
|
|
404
|
+
jest.clearAllMocks();
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('Should be able to initializes the job by accessing existing escrow', async () => {
|
|
408
|
+
expect(await job.initialize()).toBe(true);
|
|
409
|
+
|
|
410
|
+
expect(await job.manifestData?.manifestlink?.url).toBe('uploaded-key');
|
|
411
|
+
expect(await job.manifestData?.manifestlink?.hash).toBe('uploaded-hash');
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it('Should not be able to launch the job again', async () => {
|
|
415
|
+
await job.initialize();
|
|
416
|
+
|
|
417
|
+
expect(await job.launch()).toBe(false);
|
|
418
|
+
expect(await job.status()).toBe(EscrowStatus.Pending);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('Should not be able to setup the job again', async () => {
|
|
422
|
+
await job.initialize();
|
|
423
|
+
|
|
424
|
+
expect(await job.setup()).toBe(false);
|
|
425
|
+
|
|
426
|
+
expect((await job.balance())?.toString()).toBe(
|
|
427
|
+
toFullDigit(100).toString()
|
|
428
|
+
);
|
|
429
|
+
expect(await job.manifestData?.manifestlink?.url).toBe('uploaded-key');
|
|
430
|
+
expect(await job.manifestData?.manifestlink?.hash).toBe('uploaded-hash');
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('Should be able to add trusted handlers', async () => {
|
|
434
|
+
await job.initialize();
|
|
435
|
+
|
|
436
|
+
expect(await job.isTrustedHandler(DEFAULT_GAS_PAYER_ADDR)).toBe(true);
|
|
437
|
+
|
|
438
|
+
expect(
|
|
439
|
+
await job.addTrustedHandlers([
|
|
440
|
+
TRUSTED_OPERATOR1_ADDR,
|
|
441
|
+
TRUSTED_OPERATOR2_ADDR,
|
|
442
|
+
])
|
|
443
|
+
).toBe(true);
|
|
444
|
+
|
|
445
|
+
expect(await job.isTrustedHandler(TRUSTED_OPERATOR1_ADDR)).toBe(true);
|
|
446
|
+
expect(await job.isTrustedHandler(TRUSTED_OPERATOR2_ADDR)).toBe(true);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('Should be able to bulk payout workers', async () => {
|
|
450
|
+
await job.initialize();
|
|
451
|
+
|
|
452
|
+
expect(
|
|
453
|
+
await job.bulkPayout(
|
|
454
|
+
[
|
|
455
|
+
{
|
|
456
|
+
address: WORKER1_ADDR,
|
|
457
|
+
amount: 20,
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
address: WORKER2_ADDR,
|
|
461
|
+
amount: 50,
|
|
462
|
+
},
|
|
463
|
+
],
|
|
464
|
+
{}
|
|
465
|
+
)
|
|
466
|
+
).toBe(true);
|
|
467
|
+
|
|
468
|
+
// The escrow contract is still in Partial state as there's still balance left.
|
|
469
|
+
expect((await job.balance())?.toString()).toBe(
|
|
470
|
+
toFullDigit(30).toString()
|
|
471
|
+
);
|
|
472
|
+
expect(await job.status()).toBe(EscrowStatus.Partial);
|
|
473
|
+
|
|
474
|
+
// Trying to pay more than the contract balance results in failure.
|
|
475
|
+
expect(
|
|
476
|
+
await job.bulkPayout(
|
|
477
|
+
[
|
|
478
|
+
{
|
|
479
|
+
address: WORKER3_ADDR,
|
|
480
|
+
amount: 50,
|
|
481
|
+
},
|
|
482
|
+
],
|
|
483
|
+
{}
|
|
484
|
+
)
|
|
485
|
+
).toBe(false);
|
|
486
|
+
|
|
487
|
+
// Paying the remaining amount empties the escrow and updates the status correctly.
|
|
488
|
+
expect(
|
|
489
|
+
await job.bulkPayout(
|
|
490
|
+
[
|
|
491
|
+
{
|
|
492
|
+
address: WORKER3_ADDR,
|
|
493
|
+
amount: 30,
|
|
494
|
+
},
|
|
495
|
+
],
|
|
496
|
+
{}
|
|
497
|
+
)
|
|
498
|
+
).toBe(true);
|
|
499
|
+
expect((await job.balance())?.toString()).toBe(toFullDigit(0).toString());
|
|
500
|
+
expect(await job.status()).toBe(EscrowStatus.Paid);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
it('Should encrypt result, when bulk paying out workers', async () => {
|
|
504
|
+
await job.initialize();
|
|
505
|
+
|
|
506
|
+
jest.clearAllMocks();
|
|
507
|
+
const finalResults = { results: 0 };
|
|
508
|
+
await job.bulkPayout(
|
|
509
|
+
[
|
|
510
|
+
{
|
|
511
|
+
address: WORKER1_ADDR,
|
|
512
|
+
amount: 100,
|
|
513
|
+
},
|
|
514
|
+
],
|
|
515
|
+
finalResults,
|
|
516
|
+
true
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
expect(upload).toHaveBeenCalledWith(
|
|
520
|
+
job.storageAccessData,
|
|
521
|
+
finalResults,
|
|
522
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
523
|
+
true,
|
|
524
|
+
false
|
|
525
|
+
);
|
|
526
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it('Should not encrypt result, when bulk paying out workers', async () => {
|
|
530
|
+
await job.initialize();
|
|
531
|
+
|
|
532
|
+
jest.clearAllMocks();
|
|
533
|
+
const finalResults = { results: 0 };
|
|
534
|
+
await job.bulkPayout(
|
|
535
|
+
[
|
|
536
|
+
{
|
|
537
|
+
address: WORKER1_ADDR,
|
|
538
|
+
amount: 100,
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
finalResults,
|
|
542
|
+
false
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
expect(upload).toHaveBeenCalledWith(
|
|
546
|
+
job.storageAccessData,
|
|
547
|
+
finalResults,
|
|
548
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
549
|
+
false,
|
|
550
|
+
false
|
|
551
|
+
);
|
|
552
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it('Should store result in private storage, when bulk paying out workers', async () => {
|
|
556
|
+
await job.initialize();
|
|
557
|
+
|
|
558
|
+
jest.clearAllMocks();
|
|
559
|
+
const finalResults = { results: 0 };
|
|
560
|
+
await job.bulkPayout(
|
|
561
|
+
[
|
|
562
|
+
{
|
|
563
|
+
address: WORKER1_ADDR,
|
|
564
|
+
amount: 100,
|
|
565
|
+
},
|
|
566
|
+
],
|
|
567
|
+
finalResults,
|
|
568
|
+
false,
|
|
569
|
+
false
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
expect(upload).toHaveBeenCalledWith(
|
|
573
|
+
job.storageAccessData,
|
|
574
|
+
finalResults,
|
|
575
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
576
|
+
false,
|
|
577
|
+
false
|
|
578
|
+
);
|
|
579
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it('Should store result in public storage, when bulk paying out workers', async () => {
|
|
583
|
+
await job.initialize();
|
|
584
|
+
|
|
585
|
+
jest.clearAllMocks();
|
|
586
|
+
const finalResults = { results: 0 };
|
|
587
|
+
await job.bulkPayout(
|
|
588
|
+
[
|
|
589
|
+
{
|
|
590
|
+
address: WORKER1_ADDR,
|
|
591
|
+
amount: 50,
|
|
592
|
+
},
|
|
593
|
+
],
|
|
594
|
+
finalResults,
|
|
595
|
+
false,
|
|
596
|
+
true
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
expect(upload).toHaveBeenCalledWith(
|
|
600
|
+
job.storageAccessData,
|
|
601
|
+
finalResults,
|
|
602
|
+
job.providerData?.reputationOracle?.publicKey,
|
|
603
|
+
false,
|
|
604
|
+
true
|
|
605
|
+
);
|
|
606
|
+
expect(upload).toHaveBeenCalledTimes(1);
|
|
607
|
+
expect(getPublicURL).toHaveBeenCalledTimes(1);
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it('Should return final result', async () => {
|
|
611
|
+
await job.initialize();
|
|
612
|
+
|
|
613
|
+
const finalResults = { results: 0 };
|
|
614
|
+
await job.bulkPayout(
|
|
615
|
+
[
|
|
616
|
+
{
|
|
617
|
+
address: WORKER1_ADDR,
|
|
618
|
+
amount: 100,
|
|
619
|
+
},
|
|
620
|
+
],
|
|
621
|
+
finalResults,
|
|
622
|
+
true
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
expect(JSON.stringify(await job.finalResults())).toBe(
|
|
626
|
+
JSON.stringify(finalResults)
|
|
627
|
+
);
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('Should be able to abort the job', async () => {
|
|
631
|
+
await job.initialize();
|
|
632
|
+
|
|
633
|
+
expect(await job.abort()).toBe(true);
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
it('Should be able to abort partially paid job', async () => {
|
|
637
|
+
await job.initialize();
|
|
638
|
+
|
|
639
|
+
const finalResults = { results: 0 };
|
|
640
|
+
await job.bulkPayout(
|
|
641
|
+
[
|
|
642
|
+
{
|
|
643
|
+
address: WORKER1_ADDR,
|
|
644
|
+
amount: 50,
|
|
645
|
+
},
|
|
646
|
+
],
|
|
647
|
+
finalResults,
|
|
648
|
+
true
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
expect(await job.abort()).toBe(true);
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
it('Should not be able to abort fully paid job', async () => {
|
|
655
|
+
await job.initialize();
|
|
656
|
+
|
|
657
|
+
const finalResults = { results: 0 };
|
|
658
|
+
await job.bulkPayout(
|
|
659
|
+
[
|
|
660
|
+
{
|
|
661
|
+
address: WORKER1_ADDR,
|
|
662
|
+
amount: 100,
|
|
663
|
+
},
|
|
664
|
+
],
|
|
665
|
+
finalResults,
|
|
666
|
+
true
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
expect(await job.abort()).toBe(false);
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
it('Should be able to cancel the job', async () => {
|
|
673
|
+
await job.initialize();
|
|
674
|
+
|
|
675
|
+
expect(await job.cancel()).toBe(true);
|
|
676
|
+
expect((await job.balance())?.toString()).toBe(toFullDigit(0).toString());
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('Should be able to cancel partially paid job', async () => {
|
|
680
|
+
await job.initialize();
|
|
681
|
+
|
|
682
|
+
const finalResults = { results: 0 };
|
|
683
|
+
await job.bulkPayout(
|
|
684
|
+
[
|
|
685
|
+
{
|
|
686
|
+
address: WORKER1_ADDR,
|
|
687
|
+
amount: 50,
|
|
688
|
+
},
|
|
689
|
+
],
|
|
690
|
+
finalResults,
|
|
691
|
+
true
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
expect(await job.cancel()).toBe(true);
|
|
695
|
+
expect((await job.balance())?.toString()).toBe(toFullDigit(0).toString());
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
it('Should not be able to cancel paid job', async () => {
|
|
699
|
+
await job.initialize();
|
|
700
|
+
|
|
701
|
+
const finalResults = { results: 0 };
|
|
702
|
+
await job.bulkPayout(
|
|
703
|
+
[
|
|
704
|
+
{
|
|
705
|
+
address: WORKER1_ADDR,
|
|
706
|
+
amount: 100,
|
|
707
|
+
},
|
|
708
|
+
],
|
|
709
|
+
finalResults,
|
|
710
|
+
true
|
|
711
|
+
);
|
|
712
|
+
|
|
713
|
+
expect(await job.cancel()).toBe(false);
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
});
|