@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/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, trustedHandlers, jobRequesterId);
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 a trusted handler can call it.
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 a trusted handler can call it.
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
- txOptions: Overrides = {}
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
- const escrowContract = this.getEscrowContract(escrowAddress);
513
-
514
- await (await escrowContract.storeResults(url, hash, txOptions)).wait();
515
-
516
- return;
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 a trusted handler can call it.
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 a trusted handler can call it.
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 = false,
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
- const escrowContract = this.getEscrowContract(escrowAddress);
630
- if (forceComplete) {
755
+ if (idIsString) {
631
756
  await (
632
757
  await escrowContract[
633
- 'bulkPayOut(address[],uint256[],string,string,uint256,bool)'
758
+ 'bulkPayOut(address[],uint256[],string,string,string,bool)'
634
759
  ](
635
760
  recipients,
636
761
  amounts,
637
762
  finalResultsUrl,
638
763
  finalResultsHash,
639
- txId,
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
- txId,
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 a trusted handler can call it.
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<EscrowCancel> {
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 adds an array of addresses to the trusted handlers list.
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 trusted handler can call it.
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
- * const trustedHandlers = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'];
773
- * await escrowClient.addTrustedHandlers('0x62dD51230A30401C455c8398d06F85e4EaB6309f', trustedHandlers);
862
+ * await escrowClient.requestCancellation('0x62dD51230A30401C455c8398d06F85e4EaB6309f');
774
863
  * ```
775
864
  */
776
865
  @requiresSigner
777
- async addTrustedHandlers(
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 a trusted handler can call it.
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
- amountWithdrawn: amountTransferred,
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 {number} txId Transaction ID.
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 a trusted handler can call it.
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 txId = 1;
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
- txId: number,
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,uint256,bool)'
1043
+ 'bulkPayOut(address[],uint256[],string,string,string,bool)'
970
1044
  ].populateTransaction(
971
1045
  recipients,
972
1046
  amounts,
973
1047
  finalResultsUrl,
974
1048
  finalResultsHash,
975
- txId,
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
  }