@human-protocol/sdk 4.2.0 → 5.0.0-beta.0
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/dist/constants.js +4 -4
- package/dist/error.d.ts +16 -4
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +18 -6
- package/dist/escrow.d.ts +238 -28
- package/dist/escrow.d.ts.map +1 -1
- package/dist/escrow.js +255 -152
- package/dist/graphql/queries/escrow.d.ts +3 -1
- package/dist/graphql/queries/escrow.d.ts.map +1 -1
- package/dist/graphql/queries/escrow.js +49 -1
- package/dist/graphql/queries/operator.d.ts.map +1 -1
- package/dist/graphql/queries/operator.js +11 -9
- package/dist/graphql/queries/staking.d.ts +4 -0
- package/dist/graphql/queries/staking.d.ts.map +1 -0
- package/dist/graphql/queries/staking.js +71 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/interfaces.d.ts +56 -16
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/operator.d.ts.map +1 -1
- package/dist/operator.js +53 -58
- package/dist/staking.d.ts +21 -1
- package/dist/staking.d.ts.map +1 -1
- package/dist/staking.js +84 -1
- package/dist/types.d.ts +39 -15
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -0
- package/package.json +2 -2
- package/src/constants.ts +4 -4
- package/src/error.ts +25 -7
- package/src/escrow.ts +416 -113
- package/src/graphql/queries/escrow.ts +52 -1
- package/src/graphql/queries/operator.ts +11 -9
- package/src/graphql/queries/staking.ts +80 -0
- package/src/index.ts +2 -1
- package/src/interfaces.ts +63 -18
- package/src/operator.ts +62 -76
- package/src/staking.ts +106 -3
- package/src/types.ts +40 -15
package/src/escrow.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { ChainId, OrderDirection } from './enums';
|
|
|
18
18
|
import {
|
|
19
19
|
ErrorAmountMustBeGreaterThanZero,
|
|
20
20
|
ErrorAmountsCannotBeEmptyArray,
|
|
21
|
+
ErrorBulkPayOutVersion,
|
|
21
22
|
ErrorEscrowAddressIsNotProvidedByFactory,
|
|
22
23
|
ErrorEscrowDoesNotHaveEnoughBalance,
|
|
23
24
|
ErrorHashIsEmptyString,
|
|
@@ -30,18 +31,21 @@ import {
|
|
|
30
31
|
ErrorInvalidTokenAddress,
|
|
31
32
|
ErrorInvalidUrl,
|
|
32
33
|
ErrorLaunchedEventIsNotEmitted,
|
|
33
|
-
ErrorListOfHandlersCannotBeEmpty,
|
|
34
34
|
ErrorProviderDoesNotExist,
|
|
35
35
|
ErrorRecipientAndAmountsMustBeSameLength,
|
|
36
36
|
ErrorRecipientCannotBeEmptyArray,
|
|
37
|
+
ErrorStoreResultsVersion,
|
|
37
38
|
ErrorTooManyRecipients,
|
|
38
39
|
ErrorTotalFeeMustBeLessThanHundred,
|
|
39
40
|
ErrorTransferEventNotFoundInTransactionLogs,
|
|
40
41
|
ErrorUnsupportedChainID,
|
|
41
42
|
InvalidEthereumAddressError,
|
|
43
|
+
WarnVersionMismatch,
|
|
42
44
|
} from './error';
|
|
43
45
|
import {
|
|
44
46
|
EscrowData,
|
|
47
|
+
GET_CANCELLATION_REFUNDS_QUERY,
|
|
48
|
+
GET_CANCELLATION_REFUND_BY_ADDRESS_QUERY,
|
|
45
49
|
GET_ESCROWS_QUERY,
|
|
46
50
|
GET_ESCROW_BY_ADDRESS_QUERY,
|
|
47
51
|
GET_PAYOUTS_QUERY,
|
|
@@ -56,12 +60,12 @@ import {
|
|
|
56
60
|
IStatusEventFilter,
|
|
57
61
|
} from './interfaces';
|
|
58
62
|
import {
|
|
59
|
-
EscrowCancel,
|
|
60
63
|
EscrowStatus,
|
|
61
64
|
EscrowWithdraw,
|
|
62
65
|
NetworkData,
|
|
63
66
|
TransactionLikeWithNonce,
|
|
64
67
|
Payout,
|
|
68
|
+
CancellationRefund,
|
|
65
69
|
} from './types';
|
|
66
70
|
import {
|
|
67
71
|
getSubgraphUrl,
|
|
@@ -201,7 +205,6 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
201
205
|
* This function creates an escrow contract that uses the token passed to pay oracle fees and reward workers.
|
|
202
206
|
*
|
|
203
207
|
* @param {string} tokenAddress Token address to use for payouts.
|
|
204
|
-
* @param {string[]} trustedHandlers Array of addresses that can perform actions on the contract.
|
|
205
208
|
* @param {string} jobRequesterId Job Requester Id
|
|
206
209
|
* @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object).
|
|
207
210
|
* @returns {Promise<string>} Returns the address of the escrow created.
|
|
@@ -223,15 +226,13 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
223
226
|
* const escrowClient = await EscrowClient.build(signer);
|
|
224
227
|
*
|
|
225
228
|
* const tokenAddress = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4';
|
|
226
|
-
* const trustedHandlers = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'];
|
|
227
229
|
* const jobRequesterId = "job-requester-id";
|
|
228
|
-
* const escrowAddress = await escrowClient.createEscrow(tokenAddress,
|
|
230
|
+
* const escrowAddress = await escrowClient.createEscrow(tokenAddress, jobRequesterId);
|
|
229
231
|
* ```
|
|
230
232
|
*/
|
|
231
233
|
@requiresSigner
|
|
232
234
|
public async createEscrow(
|
|
233
235
|
tokenAddress: string,
|
|
234
|
-
trustedHandlers: string[],
|
|
235
236
|
jobRequesterId: string,
|
|
236
237
|
txOptions: Overrides = {}
|
|
237
238
|
): Promise<string> {
|
|
@@ -239,17 +240,10 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
239
240
|
throw ErrorInvalidTokenAddress;
|
|
240
241
|
}
|
|
241
242
|
|
|
242
|
-
trustedHandlers.forEach((trustedHandler) => {
|
|
243
|
-
if (!ethers.isAddress(trustedHandler)) {
|
|
244
|
-
throw new InvalidEthereumAddressError(trustedHandler);
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
|
|
248
243
|
try {
|
|
249
244
|
const result = await (
|
|
250
245
|
await this.escrowFactoryContract.createEscrow(
|
|
251
246
|
tokenAddress,
|
|
252
|
-
trustedHandlers,
|
|
253
247
|
jobRequesterId,
|
|
254
248
|
txOptions
|
|
255
249
|
)
|
|
@@ -282,7 +276,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
282
276
|
*
|
|
283
277
|
* **Code example**
|
|
284
278
|
*
|
|
285
|
-
* > Only Job Launcher or
|
|
279
|
+
* > Only Job Launcher or admin can call it.
|
|
286
280
|
*
|
|
287
281
|
* ```ts
|
|
288
282
|
* import { Wallet, providers } from 'ethers';
|
|
@@ -453,6 +447,44 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
453
447
|
}
|
|
454
448
|
}
|
|
455
449
|
|
|
450
|
+
/**
|
|
451
|
+
* This function stores the results URL and hash.
|
|
452
|
+
*
|
|
453
|
+
* @param {string} escrowAddress Address of the escrow.
|
|
454
|
+
* @param {string} url Results file URL.
|
|
455
|
+
* @param {string} hash Results file hash.
|
|
456
|
+
* @param {bigint} fundsToReserve Funds to reserve for payouts
|
|
457
|
+
* @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object).
|
|
458
|
+
* @returns Returns void if successful. Throws error if any.
|
|
459
|
+
*
|
|
460
|
+
*
|
|
461
|
+
* **Code example**
|
|
462
|
+
*
|
|
463
|
+
* > Only Recording Oracle or admin can call it.
|
|
464
|
+
*
|
|
465
|
+
* ```ts
|
|
466
|
+
* import { ethers, Wallet, providers } from 'ethers';
|
|
467
|
+
* import { EscrowClient } from '@human-protocol/sdk';
|
|
468
|
+
*
|
|
469
|
+
* const rpcUrl = 'YOUR_RPC_URL';
|
|
470
|
+
* const privateKey = 'YOUR_PRIVATE_KEY';
|
|
471
|
+
*
|
|
472
|
+
* const provider = new providers.JsonRpcProvider(rpcUrl);
|
|
473
|
+
* const signer = new Wallet(privateKey, provider);
|
|
474
|
+
* const escrowClient = await EscrowClient.build(signer);
|
|
475
|
+
*
|
|
476
|
+
* await escrowClient.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'http://localhost/results.json', 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079', ethers.parseEther('10'));
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
|
|
480
|
+
async storeResults(
|
|
481
|
+
escrowAddress: string,
|
|
482
|
+
url: string,
|
|
483
|
+
hash: string,
|
|
484
|
+
fundsToReserve: bigint,
|
|
485
|
+
txOptions?: Overrides
|
|
486
|
+
): Promise<void>;
|
|
487
|
+
|
|
456
488
|
/**
|
|
457
489
|
* This function stores the results URL and hash.
|
|
458
490
|
*
|
|
@@ -465,7 +497,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
465
497
|
*
|
|
466
498
|
* **Code example**
|
|
467
499
|
*
|
|
468
|
-
* > Only Recording Oracle or
|
|
500
|
+
* > Only Recording Oracle or admin can call it.
|
|
469
501
|
*
|
|
470
502
|
* ```ts
|
|
471
503
|
* import { ethers, Wallet, providers } from 'ethers';
|
|
@@ -481,26 +513,38 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
481
513
|
* await escrowClient.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'http://localhost/results.json', 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079');
|
|
482
514
|
* ```
|
|
483
515
|
*/
|
|
516
|
+
async storeResults(
|
|
517
|
+
escrowAddress: string,
|
|
518
|
+
url: string,
|
|
519
|
+
hash: string,
|
|
520
|
+
txOptions?: Overrides
|
|
521
|
+
): Promise<void>;
|
|
522
|
+
|
|
484
523
|
@requiresSigner
|
|
485
524
|
async storeResults(
|
|
486
525
|
escrowAddress: string,
|
|
487
526
|
url: string,
|
|
488
527
|
hash: string,
|
|
489
|
-
|
|
528
|
+
a?: bigint | Overrides,
|
|
529
|
+
b?: Overrides
|
|
490
530
|
): Promise<void> {
|
|
531
|
+
const escrowContract = this.getEscrowContract(escrowAddress);
|
|
532
|
+
|
|
533
|
+
const hasFundsToReserveParam = typeof a === 'bigint';
|
|
534
|
+
const fundsToReserve = hasFundsToReserveParam ? (a as bigint) : undefined;
|
|
535
|
+
const txOptions = (hasFundsToReserveParam ? b : a) || {};
|
|
536
|
+
// When fundsToReserve is provided and is 0, allow empty URL.
|
|
537
|
+
// In this situation not solutions might have been provided so the escrow can be straight cancelled.
|
|
538
|
+
const allowEmptyUrl = hasFundsToReserveParam && fundsToReserve === 0n;
|
|
539
|
+
|
|
491
540
|
if (!ethers.isAddress(escrowAddress)) {
|
|
492
541
|
throw ErrorInvalidEscrowAddressProvided;
|
|
493
542
|
}
|
|
494
|
-
|
|
495
|
-
if (!url) {
|
|
496
|
-
throw ErrorInvalidUrl;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (!isValidUrl(url)) {
|
|
543
|
+
if (!allowEmptyUrl && !isValidUrl(url)) {
|
|
500
544
|
throw ErrorInvalidUrl;
|
|
501
545
|
}
|
|
502
546
|
|
|
503
|
-
if (!hash) {
|
|
547
|
+
if (!hash && !allowEmptyUrl) {
|
|
504
548
|
throw ErrorHashIsEmptyString;
|
|
505
549
|
}
|
|
506
550
|
|
|
@@ -509,12 +553,30 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
509
553
|
}
|
|
510
554
|
|
|
511
555
|
try {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
556
|
+
if (fundsToReserve !== undefined) {
|
|
557
|
+
await (
|
|
558
|
+
await escrowContract['storeResults(string,string,uint256)'](
|
|
559
|
+
url,
|
|
560
|
+
hash,
|
|
561
|
+
fundsToReserve,
|
|
562
|
+
txOptions
|
|
563
|
+
)
|
|
564
|
+
).wait();
|
|
565
|
+
} else {
|
|
566
|
+
await (
|
|
567
|
+
await escrowContract['storeResults(string,string)'](
|
|
568
|
+
url,
|
|
569
|
+
hash,
|
|
570
|
+
txOptions
|
|
571
|
+
)
|
|
572
|
+
).wait();
|
|
573
|
+
}
|
|
517
574
|
} catch (e) {
|
|
575
|
+
if (!hasFundsToReserveParam && e.reason === 'DEPRECATED_SIGNATURE') {
|
|
576
|
+
throw ErrorStoreResultsVersion;
|
|
577
|
+
}
|
|
578
|
+
// eslint-disable-next-line no-console
|
|
579
|
+
console.warn(WarnVersionMismatch);
|
|
518
580
|
return throwError(e);
|
|
519
581
|
}
|
|
520
582
|
}
|
|
@@ -529,7 +591,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
529
591
|
*
|
|
530
592
|
* **Code example**
|
|
531
593
|
*
|
|
532
|
-
* > Only Recording Oracle or
|
|
594
|
+
* > Only Recording Oracle or admin can call it.
|
|
533
595
|
*
|
|
534
596
|
* ```ts
|
|
535
597
|
* import { Wallet, providers } from 'ethers';
|
|
@@ -584,7 +646,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
584
646
|
*
|
|
585
647
|
* **Code example**
|
|
586
648
|
*
|
|
587
|
-
* > Only Reputation Oracle or
|
|
649
|
+
* > Only Reputation Oracle or admin can call it.
|
|
588
650
|
*
|
|
589
651
|
* ```ts
|
|
590
652
|
* import { ethers, Wallet, providers } from 'ethers';
|
|
@@ -603,10 +665,9 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
603
665
|
* const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079';
|
|
604
666
|
* const txId = 1;
|
|
605
667
|
*
|
|
606
|
-
* await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, txId);
|
|
668
|
+
* await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, txId, true);
|
|
607
669
|
* ```
|
|
608
670
|
*/
|
|
609
|
-
@requiresSigner
|
|
610
671
|
async bulkPayOut(
|
|
611
672
|
escrowAddress: string,
|
|
612
673
|
recipients: string[],
|
|
@@ -614,7 +675,69 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
614
675
|
finalResultsUrl: string,
|
|
615
676
|
finalResultsHash: string,
|
|
616
677
|
txId: number,
|
|
617
|
-
forceComplete
|
|
678
|
+
forceComplete: boolean,
|
|
679
|
+
txOptions: Overrides
|
|
680
|
+
): Promise<void>;
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* This function pays out the amounts specified to the workers and sets the URL of the final results file.
|
|
684
|
+
*
|
|
685
|
+
* @param {string} escrowAddress Escrow address to payout.
|
|
686
|
+
* @param {string[]} recipients Array of recipient addresses.
|
|
687
|
+
* @param {bigint[]} amounts Array of amounts the recipients will receive.
|
|
688
|
+
* @param {string} finalResultsUrl Final results file URL.
|
|
689
|
+
* @param {string} finalResultsHash Final results file hash.
|
|
690
|
+
* @param {string} payoutId Payout ID.
|
|
691
|
+
* @param {boolean} forceComplete Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false).
|
|
692
|
+
* @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object).
|
|
693
|
+
* @returns Returns void if successful. Throws error if any.
|
|
694
|
+
*
|
|
695
|
+
*
|
|
696
|
+
* **Code example**
|
|
697
|
+
*
|
|
698
|
+
* > Only Reputation Oracle or admin can call it.
|
|
699
|
+
*
|
|
700
|
+
* ```ts
|
|
701
|
+
* import { ethers, Wallet, providers } from 'ethers';
|
|
702
|
+
* import { EscrowClient } from '@human-protocol/sdk';
|
|
703
|
+
* import { v4 as uuidV4 } from 'uuid';
|
|
704
|
+
*
|
|
705
|
+
* const rpcUrl = 'YOUR_RPC_URL';
|
|
706
|
+
* const privateKey = 'YOUR_PRIVATE_KEY';
|
|
707
|
+
*
|
|
708
|
+
* const provider = new providers.JsonRpcProvider(rpcUrl);
|
|
709
|
+
* const signer = new Wallet(privateKey, provider);
|
|
710
|
+
* const escrowClient = await EscrowClient.build(signer);
|
|
711
|
+
*
|
|
712
|
+
* const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'];
|
|
713
|
+
* const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')];
|
|
714
|
+
* const resultsUrl = 'http://localhost/results.json';
|
|
715
|
+
* const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079';
|
|
716
|
+
* const payoutId = uuidV4();
|
|
717
|
+
*
|
|
718
|
+
* await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, payoutId, true);
|
|
719
|
+
* ```
|
|
720
|
+
*/
|
|
721
|
+
async bulkPayOut(
|
|
722
|
+
escrowAddress: string,
|
|
723
|
+
recipients: string[],
|
|
724
|
+
amounts: bigint[],
|
|
725
|
+
finalResultsUrl: string,
|
|
726
|
+
finalResultsHash: string,
|
|
727
|
+
payoutId: string,
|
|
728
|
+
forceComplete: boolean,
|
|
729
|
+
txOptions: Overrides
|
|
730
|
+
): Promise<void>;
|
|
731
|
+
|
|
732
|
+
@requiresSigner
|
|
733
|
+
async bulkPayOut(
|
|
734
|
+
escrowAddress: string,
|
|
735
|
+
recipients: string[],
|
|
736
|
+
amounts: bigint[],
|
|
737
|
+
finalResultsUrl: string,
|
|
738
|
+
finalResultsHash: string,
|
|
739
|
+
id: number | string,
|
|
740
|
+
forceComplete: boolean,
|
|
618
741
|
txOptions: Overrides = {}
|
|
619
742
|
): Promise<void> {
|
|
620
743
|
await this.ensureCorrectBulkPayoutInput(
|
|
@@ -625,18 +748,20 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
625
748
|
finalResultsHash
|
|
626
749
|
);
|
|
627
750
|
|
|
751
|
+
const escrowContract = this.getEscrowContract(escrowAddress);
|
|
752
|
+
const idIsString = typeof id === 'string';
|
|
753
|
+
|
|
628
754
|
try {
|
|
629
|
-
|
|
630
|
-
if (forceComplete) {
|
|
755
|
+
if (idIsString) {
|
|
631
756
|
await (
|
|
632
757
|
await escrowContract[
|
|
633
|
-
'bulkPayOut(address[],uint256[],string,string,
|
|
758
|
+
'bulkPayOut(address[],uint256[],string,string,string,bool)'
|
|
634
759
|
](
|
|
635
760
|
recipients,
|
|
636
761
|
amounts,
|
|
637
762
|
finalResultsUrl,
|
|
638
763
|
finalResultsHash,
|
|
639
|
-
|
|
764
|
+
id,
|
|
640
765
|
forceComplete,
|
|
641
766
|
txOptions
|
|
642
767
|
)
|
|
@@ -644,19 +769,24 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
644
769
|
} else {
|
|
645
770
|
await (
|
|
646
771
|
await escrowContract[
|
|
647
|
-
'bulkPayOut(address[],uint256[],string,string,uint256)'
|
|
772
|
+
'bulkPayOut(address[],uint256[],string,string,uint256,bool)'
|
|
648
773
|
](
|
|
649
774
|
recipients,
|
|
650
775
|
amounts,
|
|
651
776
|
finalResultsUrl,
|
|
652
777
|
finalResultsHash,
|
|
653
|
-
|
|
778
|
+
id,
|
|
779
|
+
forceComplete,
|
|
654
780
|
txOptions
|
|
655
781
|
)
|
|
656
782
|
).wait();
|
|
657
783
|
}
|
|
658
|
-
return;
|
|
659
784
|
} catch (e) {
|
|
785
|
+
if (!idIsString && e.reason === 'DEPRECATED_SIGNATURE') {
|
|
786
|
+
throw ErrorBulkPayOutVersion;
|
|
787
|
+
}
|
|
788
|
+
// eslint-disable-next-line no-console
|
|
789
|
+
console.warn(WarnVersionMismatch);
|
|
660
790
|
return throwError(e);
|
|
661
791
|
}
|
|
662
792
|
}
|
|
@@ -666,12 +796,11 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
666
796
|
*
|
|
667
797
|
* @param {string} escrowAddress Address of the escrow to cancel.
|
|
668
798
|
* @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object).
|
|
669
|
-
* @returns {EscrowCancel} Returns the escrow cancellation data including transaction hash and refunded amount. Throws error if any.
|
|
670
799
|
*
|
|
671
800
|
*
|
|
672
801
|
* **Code example**
|
|
673
802
|
*
|
|
674
|
-
* > Only Job Launcher or
|
|
803
|
+
* > Only Job Launcher or admin can call it.
|
|
675
804
|
*
|
|
676
805
|
* ```ts
|
|
677
806
|
* import { ethers, Wallet, providers } from 'ethers';
|
|
@@ -691,7 +820,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
691
820
|
async cancel(
|
|
692
821
|
escrowAddress: string,
|
|
693
822
|
txOptions: Overrides = {}
|
|
694
|
-
): Promise<
|
|
823
|
+
): Promise<void> {
|
|
695
824
|
if (!ethers.isAddress(escrowAddress)) {
|
|
696
825
|
throw ErrorInvalidEscrowAddressProvided;
|
|
697
826
|
}
|
|
@@ -702,61 +831,22 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
702
831
|
|
|
703
832
|
try {
|
|
704
833
|
const escrowContract = this.getEscrowContract(escrowAddress);
|
|
705
|
-
|
|
706
|
-
const transactionReceipt = await (
|
|
707
|
-
await escrowContract.cancel(txOptions)
|
|
708
|
-
).wait();
|
|
709
|
-
|
|
710
|
-
let amountTransferred: bigint | undefined = undefined;
|
|
711
|
-
const tokenAddress = await escrowContract.token();
|
|
712
|
-
|
|
713
|
-
const tokenContract: HMToken = HMToken__factory.connect(
|
|
714
|
-
tokenAddress,
|
|
715
|
-
this.runner
|
|
716
|
-
);
|
|
717
|
-
if (transactionReceipt)
|
|
718
|
-
for (const log of transactionReceipt.logs) {
|
|
719
|
-
if (log.address === tokenAddress) {
|
|
720
|
-
const parsedLog = tokenContract.interface.parseLog({
|
|
721
|
-
topics: log.topics as string[],
|
|
722
|
-
data: log.data,
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
const from = parsedLog?.args[0];
|
|
726
|
-
if (parsedLog?.name === 'Transfer' && from === escrowAddress) {
|
|
727
|
-
amountTransferred = parsedLog?.args[2];
|
|
728
|
-
break;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
if (amountTransferred === undefined) {
|
|
734
|
-
throw ErrorTransferEventNotFoundInTransactionLogs;
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
const escrowCancelData: EscrowCancel = {
|
|
738
|
-
txHash: transactionReceipt?.hash || '',
|
|
739
|
-
amountRefunded: amountTransferred,
|
|
740
|
-
};
|
|
741
|
-
|
|
742
|
-
return escrowCancelData;
|
|
834
|
+
await (await escrowContract.cancel(txOptions)).wait();
|
|
743
835
|
} catch (e) {
|
|
744
836
|
return throwError(e);
|
|
745
837
|
}
|
|
746
838
|
}
|
|
747
839
|
|
|
748
840
|
/**
|
|
749
|
-
* This function
|
|
841
|
+
* This function requests the cancellation of the specified escrow (moves status to ToCancel or finalizes if expired).
|
|
750
842
|
*
|
|
751
|
-
* @param {string} escrowAddress Address of the escrow.
|
|
752
|
-
* @param {string[]} trustedHandlers Array of addresses of trusted handlers to add.
|
|
843
|
+
* @param {string} escrowAddress Address of the escrow to request cancellation.
|
|
753
844
|
* @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object).
|
|
754
845
|
* @returns Returns void if successful. Throws error if any.
|
|
755
846
|
*
|
|
756
|
-
*
|
|
757
847
|
* **Code example**
|
|
758
848
|
*
|
|
759
|
-
* > Only Job Launcher or
|
|
849
|
+
* > Only Job Launcher or admin can call it.
|
|
760
850
|
*
|
|
761
851
|
* ```ts
|
|
762
852
|
* import { Wallet, providers } from 'ethers';
|
|
@@ -769,41 +859,25 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
769
859
|
* const signer = new Wallet(privateKey, provider);
|
|
770
860
|
* const escrowClient = await EscrowClient.build(signer);
|
|
771
861
|
*
|
|
772
|
-
*
|
|
773
|
-
* await escrowClient.addTrustedHandlers('0x62dD51230A30401C455c8398d06F85e4EaB6309f', trustedHandlers);
|
|
862
|
+
* await escrowClient.requestCancellation('0x62dD51230A30401C455c8398d06F85e4EaB6309f');
|
|
774
863
|
* ```
|
|
775
864
|
*/
|
|
776
865
|
@requiresSigner
|
|
777
|
-
async
|
|
866
|
+
async requestCancellation(
|
|
778
867
|
escrowAddress: string,
|
|
779
|
-
trustedHandlers: string[],
|
|
780
868
|
txOptions: Overrides = {}
|
|
781
869
|
): Promise<void> {
|
|
782
870
|
if (!ethers.isAddress(escrowAddress)) {
|
|
783
871
|
throw ErrorInvalidEscrowAddressProvided;
|
|
784
872
|
}
|
|
785
873
|
|
|
786
|
-
if (trustedHandlers.length === 0) {
|
|
787
|
-
throw ErrorListOfHandlersCannotBeEmpty;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
trustedHandlers.forEach((trustedHandler) => {
|
|
791
|
-
if (!ethers.isAddress(trustedHandler)) {
|
|
792
|
-
throw new InvalidEthereumAddressError(trustedHandler);
|
|
793
|
-
}
|
|
794
|
-
});
|
|
795
|
-
|
|
796
874
|
if (!(await this.escrowFactoryContract.hasEscrow(escrowAddress))) {
|
|
797
875
|
throw ErrorEscrowAddressIsNotProvidedByFactory;
|
|
798
876
|
}
|
|
799
877
|
|
|
800
878
|
try {
|
|
801
879
|
const escrowContract = this.getEscrowContract(escrowAddress);
|
|
802
|
-
|
|
803
|
-
await (
|
|
804
|
-
await escrowContract.addTrustedHandlers(trustedHandlers, txOptions)
|
|
805
|
-
).wait();
|
|
806
|
-
return;
|
|
880
|
+
await (await escrowContract.requestCancellation(txOptions)).wait();
|
|
807
881
|
} catch (e) {
|
|
808
882
|
return throwError(e);
|
|
809
883
|
}
|
|
@@ -820,7 +894,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
820
894
|
*
|
|
821
895
|
* **Code example**
|
|
822
896
|
*
|
|
823
|
-
* > Only Job Launcher or
|
|
897
|
+
* > Only Job Launcher or admin can call it.
|
|
824
898
|
*
|
|
825
899
|
* ```ts
|
|
826
900
|
* import { ethers, Wallet, providers } from 'ethers';
|
|
@@ -893,7 +967,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
893
967
|
const escrowWithdrawData: EscrowWithdraw = {
|
|
894
968
|
txHash: transactionReceipt?.hash || '',
|
|
895
969
|
tokenAddress,
|
|
896
|
-
|
|
970
|
+
withdrawnAmount: amountTransferred,
|
|
897
971
|
};
|
|
898
972
|
|
|
899
973
|
return escrowWithdrawData;
|
|
@@ -909,14 +983,14 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
909
983
|
* @param {bigint[]} amounts Array of amounts the recipients will receive.
|
|
910
984
|
* @param {string} finalResultsUrl Final results file URL.
|
|
911
985
|
* @param {string} finalResultsHash Final results file hash.
|
|
912
|
-
* @param {
|
|
986
|
+
* @param {string} payoutId Payout ID to identify the payout.
|
|
913
987
|
* @param {boolean} forceComplete Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false).
|
|
914
988
|
* @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object).
|
|
915
989
|
* @returns Returns object with raw transaction and signed transaction hash
|
|
916
990
|
*
|
|
917
991
|
* **Code example**
|
|
918
992
|
*
|
|
919
|
-
* > Only Reputation Oracle or
|
|
993
|
+
* > Only Reputation Oracle or admin can call it.
|
|
920
994
|
*
|
|
921
995
|
* ```ts
|
|
922
996
|
* import { ethers, Wallet, providers } from 'ethers';
|
|
@@ -933,7 +1007,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
933
1007
|
* const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')];
|
|
934
1008
|
* const resultsUrl = 'http://localhost/results.json';
|
|
935
1009
|
* const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079';
|
|
936
|
-
* const
|
|
1010
|
+
* const payoutId = '372f6916-fe34-4711-b6e3-274f682047de';
|
|
937
1011
|
*
|
|
938
1012
|
* const rawTransaction = await escrowClient.createBulkPayoutTransaction('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, txId);
|
|
939
1013
|
* console.log('Raw transaction:', rawTransaction);
|
|
@@ -949,7 +1023,7 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
949
1023
|
amounts: bigint[],
|
|
950
1024
|
finalResultsUrl: string,
|
|
951
1025
|
finalResultsHash: string,
|
|
952
|
-
|
|
1026
|
+
payoutId: string,
|
|
953
1027
|
forceComplete = false,
|
|
954
1028
|
txOptions: Overrides = {}
|
|
955
1029
|
): Promise<TransactionLikeWithNonce> {
|
|
@@ -966,13 +1040,13 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
966
1040
|
const escrowContract = this.getEscrowContract(escrowAddress);
|
|
967
1041
|
|
|
968
1042
|
const populatedTransaction = await escrowContract[
|
|
969
|
-
'bulkPayOut(address[],uint256[],string,string,
|
|
1043
|
+
'bulkPayOut(address[],uint256[],string,string,string,bool)'
|
|
970
1044
|
].populateTransaction(
|
|
971
1045
|
recipients,
|
|
972
1046
|
amounts,
|
|
973
1047
|
finalResultsUrl,
|
|
974
1048
|
finalResultsHash,
|
|
975
|
-
|
|
1049
|
+
payoutId,
|
|
976
1050
|
forceComplete,
|
|
977
1051
|
txOptions
|
|
978
1052
|
);
|
|
@@ -1112,6 +1186,43 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
1112
1186
|
}
|
|
1113
1187
|
}
|
|
1114
1188
|
|
|
1189
|
+
/**
|
|
1190
|
+
* This function returns the reserved funds for a specified escrow address.
|
|
1191
|
+
*
|
|
1192
|
+
* @param {string} escrowAddress Address of the escrow.
|
|
1193
|
+
* @returns {Promise<bigint>} Reserved funds of the escrow in the token used to fund it.
|
|
1194
|
+
*
|
|
1195
|
+
* **Code example**
|
|
1196
|
+
*
|
|
1197
|
+
* ```ts
|
|
1198
|
+
* import { providers } from 'ethers';
|
|
1199
|
+
* import { EscrowClient } from '@human-protocol/sdk';
|
|
1200
|
+
*
|
|
1201
|
+
* const rpcUrl = 'YOUR_RPC_URL';
|
|
1202
|
+
*
|
|
1203
|
+
* const provider = new providers.JsonRpcProvider(rpcUrl);
|
|
1204
|
+
* const escrowClient = await EscrowClient.build(provider);
|
|
1205
|
+
*
|
|
1206
|
+
* const reservedFunds = await escrowClient.getReservedFunds('0x62dD51230A30401C455c8398d06F85e4EaB6309f');
|
|
1207
|
+
* ```
|
|
1208
|
+
*/
|
|
1209
|
+
async getReservedFunds(escrowAddress: string): Promise<bigint> {
|
|
1210
|
+
if (!ethers.isAddress(escrowAddress)) {
|
|
1211
|
+
throw ErrorInvalidEscrowAddressProvided;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
if (!(await this.escrowFactoryContract.hasEscrow(escrowAddress))) {
|
|
1215
|
+
throw ErrorEscrowAddressIsNotProvidedByFactory;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
try {
|
|
1219
|
+
const escrowContract = this.getEscrowContract(escrowAddress);
|
|
1220
|
+
return await escrowContract.reservedFunds();
|
|
1221
|
+
} catch (e) {
|
|
1222
|
+
return throwError(e);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1115
1226
|
/**
|
|
1116
1227
|
* This function returns the manifest file hash.
|
|
1117
1228
|
*
|
|
@@ -1264,6 +1375,44 @@ export class EscrowClient extends BaseEthersClient {
|
|
|
1264
1375
|
}
|
|
1265
1376
|
}
|
|
1266
1377
|
|
|
1378
|
+
/**
|
|
1379
|
+
* This function returns the intermediate results hash.
|
|
1380
|
+
*
|
|
1381
|
+
* @param {string} escrowAddress Address of the escrow.
|
|
1382
|
+
* @returns {Promise<string>} Hash of the intermediate results file content.
|
|
1383
|
+
*
|
|
1384
|
+
* **Code example**
|
|
1385
|
+
*
|
|
1386
|
+
* ```ts
|
|
1387
|
+
* import { providers } from 'ethers';
|
|
1388
|
+
* import { EscrowClient } from '@human-protocol/sdk';
|
|
1389
|
+
*
|
|
1390
|
+
* const rpcUrl = 'YOUR_RPC_URL';
|
|
1391
|
+
*
|
|
1392
|
+
* const provider = new providers.JsonRpcProvider(rpcUrl);
|
|
1393
|
+
* const escrowClient = await EscrowClient.build(provider);
|
|
1394
|
+
*
|
|
1395
|
+
* const intermediateResultsHash = await escrowClient.getIntermediateResultsHash('0x62dD51230A30401C455c8398d06F85e4EaB6309f');
|
|
1396
|
+
* ```
|
|
1397
|
+
*/
|
|
1398
|
+
async getIntermediateResultsHash(escrowAddress: string): Promise<string> {
|
|
1399
|
+
if (!ethers.isAddress(escrowAddress)) {
|
|
1400
|
+
throw ErrorInvalidEscrowAddressProvided;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
if (!(await this.escrowFactoryContract.hasEscrow(escrowAddress))) {
|
|
1404
|
+
throw ErrorEscrowAddressIsNotProvidedByFactory;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
try {
|
|
1408
|
+
const escrowContract = this.getEscrowContract(escrowAddress);
|
|
1409
|
+
|
|
1410
|
+
return escrowContract.intermediateResultsHash();
|
|
1411
|
+
} catch (e) {
|
|
1412
|
+
return throwError(e);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1267
1416
|
/**
|
|
1268
1417
|
* This function returns the token address used for funding the escrow.
|
|
1269
1418
|
*
|
|
@@ -1977,4 +2126,158 @@ export class EscrowUtils {
|
|
|
1977
2126
|
|
|
1978
2127
|
return payouts || [];
|
|
1979
2128
|
}
|
|
2129
|
+
|
|
2130
|
+
/**
|
|
2131
|
+
* This function returns the cancellation refunds for a given set of networks.
|
|
2132
|
+
*
|
|
2133
|
+
* > This uses Subgraph
|
|
2134
|
+
*
|
|
2135
|
+
* **Input parameters**
|
|
2136
|
+
*
|
|
2137
|
+
* ```ts
|
|
2138
|
+
* enum ChainId {
|
|
2139
|
+
* ALL = -1,
|
|
2140
|
+
* MAINNET = 1,
|
|
2141
|
+
* SEPOLIA = 11155111,
|
|
2142
|
+
* BSC_MAINNET = 56,
|
|
2143
|
+
* BSC_TESTNET = 97,
|
|
2144
|
+
* POLYGON = 137,
|
|
2145
|
+
* POLYGON_AMOY = 80002,
|
|
2146
|
+
* LOCALHOST = 1338,
|
|
2147
|
+
* }
|
|
2148
|
+
* ```
|
|
2149
|
+
*
|
|
2150
|
+
* ```ts
|
|
2151
|
+
* type CancellationRefund = {
|
|
2152
|
+
* id: string;
|
|
2153
|
+
* escrowAddress: string;
|
|
2154
|
+
* receiver: string;
|
|
2155
|
+
* amount: bigint;
|
|
2156
|
+
* block: number;
|
|
2157
|
+
* timestamp: number;
|
|
2158
|
+
* txHash: string;
|
|
2159
|
+
* };
|
|
2160
|
+
* ```
|
|
2161
|
+
*
|
|
2162
|
+
*
|
|
2163
|
+
* @param {Object} filter Filter parameters.
|
|
2164
|
+
* @returns {Promise<CancellationRefund[]>} List of cancellation refunds matching the filters.
|
|
2165
|
+
*
|
|
2166
|
+
* **Code example**
|
|
2167
|
+
*
|
|
2168
|
+
* ```ts
|
|
2169
|
+
* import { ChainId, EscrowUtils } from '@human-protocol/sdk';
|
|
2170
|
+
*
|
|
2171
|
+
* const cancellationRefunds = await EscrowUtils.getCancellationRefunds({
|
|
2172
|
+
* chainId: ChainId.POLYGON_AMOY,
|
|
2173
|
+
* escrowAddress: '0x1234567890123456789012345678901234567890',
|
|
2174
|
+
* });
|
|
2175
|
+
* console.log(cancellationRefunds);
|
|
2176
|
+
* ```
|
|
2177
|
+
*/
|
|
2178
|
+
public static async getCancellationRefunds(filter: {
|
|
2179
|
+
chainId: ChainId;
|
|
2180
|
+
escrowAddress?: string;
|
|
2181
|
+
receiver?: string;
|
|
2182
|
+
from?: Date;
|
|
2183
|
+
to?: Date;
|
|
2184
|
+
first?: number;
|
|
2185
|
+
skip?: number;
|
|
2186
|
+
orderDirection?: OrderDirection;
|
|
2187
|
+
}): Promise<CancellationRefund[]> {
|
|
2188
|
+
const networkData = NETWORKS[filter.chainId];
|
|
2189
|
+
if (!networkData) throw ErrorUnsupportedChainID;
|
|
2190
|
+
if (filter.escrowAddress && !ethers.isAddress(filter.escrowAddress)) {
|
|
2191
|
+
throw ErrorInvalidEscrowAddressProvided;
|
|
2192
|
+
}
|
|
2193
|
+
if (filter.receiver && !ethers.isAddress(filter.receiver)) {
|
|
2194
|
+
throw ErrorInvalidAddress;
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
const first =
|
|
2198
|
+
filter.first !== undefined ? Math.min(filter.first, 1000) : 10;
|
|
2199
|
+
const skip = filter.skip || 0;
|
|
2200
|
+
const orderDirection = filter.orderDirection || OrderDirection.DESC;
|
|
2201
|
+
|
|
2202
|
+
const { cancellationRefundEvents } = await gqlFetch<{
|
|
2203
|
+
cancellationRefundEvents: CancellationRefund[];
|
|
2204
|
+
}>(getSubgraphUrl(networkData), GET_CANCELLATION_REFUNDS_QUERY(filter), {
|
|
2205
|
+
escrowAddress: filter.escrowAddress?.toLowerCase(),
|
|
2206
|
+
receiver: filter.receiver?.toLowerCase(),
|
|
2207
|
+
from: filter.from ? getUnixTimestamp(filter.from) : undefined,
|
|
2208
|
+
to: filter.to ? getUnixTimestamp(filter.to) : undefined,
|
|
2209
|
+
first,
|
|
2210
|
+
skip,
|
|
2211
|
+
orderDirection,
|
|
2212
|
+
});
|
|
2213
|
+
|
|
2214
|
+
return cancellationRefundEvents || [];
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
/**
|
|
2218
|
+
* This function returns the cancellation refund for a given escrow address.
|
|
2219
|
+
*
|
|
2220
|
+
* > This uses Subgraph
|
|
2221
|
+
*
|
|
2222
|
+
* **Input parameters**
|
|
2223
|
+
*
|
|
2224
|
+
* ```ts
|
|
2225
|
+
* enum ChainId {
|
|
2226
|
+
* ALL = -1,
|
|
2227
|
+
* MAINNET = 1,
|
|
2228
|
+
* SEPOLIA = 11155111,
|
|
2229
|
+
* BSC_MAINNET = 56,
|
|
2230
|
+
* BSC_TESTNET = 97,
|
|
2231
|
+
* POLYGON = 137,
|
|
2232
|
+
* POLYGON_AMOY = 80002,
|
|
2233
|
+
* LOCALHOST = 1338,
|
|
2234
|
+
* }
|
|
2235
|
+
* ```
|
|
2236
|
+
*
|
|
2237
|
+
* ```ts
|
|
2238
|
+
* type CancellationRefund = {
|
|
2239
|
+
* id: string;
|
|
2240
|
+
* escrowAddress: string;
|
|
2241
|
+
* receiver: string;
|
|
2242
|
+
* amount: bigint;
|
|
2243
|
+
* block: number;
|
|
2244
|
+
* timestamp: number;
|
|
2245
|
+
* txHash: string;
|
|
2246
|
+
* };
|
|
2247
|
+
* ```
|
|
2248
|
+
*
|
|
2249
|
+
*
|
|
2250
|
+
* @param {ChainId} chainId Network in which the escrow has been deployed
|
|
2251
|
+
* @param {string} escrowAddress Address of the escrow
|
|
2252
|
+
* @returns {Promise<CancellationRefund>} Cancellation refund data
|
|
2253
|
+
*
|
|
2254
|
+
* **Code example**
|
|
2255
|
+
*
|
|
2256
|
+
* ```ts
|
|
2257
|
+
* import { ChainId, EscrowUtils } from '@human-protocol/sdk';
|
|
2258
|
+
*
|
|
2259
|
+
* const cancellationRefund = await EscrowUtils.getCancellationRefund(ChainId.POLYGON_AMOY, "0x1234567890123456789012345678901234567890");
|
|
2260
|
+
* ```
|
|
2261
|
+
*/
|
|
2262
|
+
public static async getCancellationRefund(
|
|
2263
|
+
chainId: ChainId,
|
|
2264
|
+
escrowAddress: string
|
|
2265
|
+
): Promise<CancellationRefund> {
|
|
2266
|
+
const networkData = NETWORKS[chainId];
|
|
2267
|
+
if (!networkData) throw ErrorUnsupportedChainID;
|
|
2268
|
+
|
|
2269
|
+
if (!ethers.isAddress(escrowAddress)) {
|
|
2270
|
+
throw ErrorInvalidEscrowAddressProvided;
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
const { cancellationRefundEvents } = await gqlFetch<{
|
|
2274
|
+
cancellationRefundEvents: any;
|
|
2275
|
+
}>(
|
|
2276
|
+
getSubgraphUrl(networkData),
|
|
2277
|
+
GET_CANCELLATION_REFUND_BY_ADDRESS_QUERY(),
|
|
2278
|
+
{ escrowAddress: escrowAddress.toLowerCase() }
|
|
2279
|
+
);
|
|
2280
|
+
|
|
2281
|
+
return cancellationRefundEvents?.[0] || null;
|
|
2282
|
+
}
|
|
1980
2283
|
}
|